Доработка формы 1С через нейросеть: что дать модели на вход и что проверить в её ответе
Иван Недомолков · Chop etilgan:
Доработка формы через нейросеть чаще всего ломается не на синтаксисе. Код компилируется, расширение ставится, а результата нет: подсветка не появляется, обработчик не срабатывает. Причина почти всегда в том, что модель не видела форму целиком. У формы три слоя, и в одном файле из них лежит только один.
Ниже порядок работы, к которому мы пришли после замера на типовой УТ для Казахстана 3.4.4.87: что положить модели на вход, где она ошибается без каждого из источников и как проверить её ответ, не открывая базу.
Три источника и что каждый закрывает
| Источник | Что даёт модели | Чего в нём нет |
|---|---|---|
| Form.xml из выгрузки | точные имена элементов, групп, страниц, команд и обработчиков | видимость, которую ставит код; поля и кнопки, которые добавляются при создании |
Модуль формы, ПриСозданииНаСервере и то, что он вызывает | что форма достраивает и прячет при создании, порядок действий типового кода | что окажется на экране у конкретного пользователя |
| Снимок открытой формы или слова пользователя | фактическую видимость полей | путь к данным, обработчики, условное оформление |
Ни один источник не заменяет другой. Ниже про каждый подробнее, с цифрами.
Form.xml: имена полные, видимость нет
Файл лежит в выгрузке конфигурации (Конфигуратор, “Конфигурация - Выгрузить конфигурацию в файлы”, или проект EDT). У формы элемента номенклатуры путь Catalogs\Номенклатура\Forms\ФормаЭлемента\Ext\Form.xml, модуль рядом, Ext\Form\Module.bsl.
Мы сравнили XML двух типовых форм с тем, что получается в клиенте:
| Форма | В XML | Нашлись в клиенте | Появились при открытии | Видимы по XML, скрыты в работе |
|---|---|---|---|---|
| Номенклатура, форма элемента | 856 | 856 | 82 | 127 |
| Контрагенты, форма списка | 102 | 102 | 126 | 2 |
Потерь нет: каждый элемент из файла в клиенте существует. Появившееся при открытии оказалось служебным. Это кнопки командных панелей и контекстных меню, подменю, расширенные подсказки к ним, часть рисует платформа, часть добавляют подключаемые команды БСП (печать, отчёты, “Создать на основании”). Полей ввода среди добавленных нет ни одного. Исключение будет в базе с дополнительными реквизитами: такие поля БСП вставляет из ПриСозданииНаСервере через УправлениеСвойствами, и в XML их нет. На нашем полигоне их не было.
Последняя колонка таблицы и есть главная проблема. 127 полей номенклатуры, среди них Артикул, по файлу видимы, а пользователь их не видит.
Второе, ради чего файл нужен: имена обработчиков. Угадывать их по схеме “имя элемента плюс событие” нельзя. У формы номенклатуры 102 обработчика событий элементов, 39 из них схеме не подчиняются. На 29 событиях висит одна процедура СвернутьРазвернутьГруппу (декорации “открыть” и “закрыть”), остальные 10 названы кто как. Пример, переключатель шаблона ценника:
<RadioButtonField name="ИспользоватьОбщийШаблонЦенника" id="1438">
<DataPath>ИспользоватьИндивидуальныйШаблонЦенника</DataPath>
...
<Events>
<Event name="OnChange">ИспользоватьИндивидуальныйШаблонЦенникПриИзменении</Event>
</Events>
</RadioButtonField>
Элемент ИспользоватьОбщийШаблонЦенника привязан к реквизиту с другим именем и делит обработчик со вторым переключателем. Оба смотрят в одно число: 0 означает общий шаблон, 1 индивидуальный. В имени обработчика нет буквы “а” после “Ценник”, так в типовой и задумано. Процедуры ИспользоватьОбщийШаблонЦенникаПриИзменении, которую модель напишет по схеме, в модуле нет.
Файл тяжёлый: Form.xml номенклатуры занимает 356 307 байт. Его можно сжать до сводки элементов, обработчиков и команд, например скилом form-info из открытого набора cc-1c-skills. Сводка, как и полный файл, отвечает на вопрос “как называется”, но не на вопрос “что видно”.
Модуль формы: что достраивается кодом
Видимость Артикул в файле не задана, значит, по XML поле видимое. В открытой форме нового элемента у него Видимость = Ложь. Поиск по модулю формы на 4 502 строки тоже не поможет: строки Элементы.Артикул.Видимость там нет. Видимость ставит цикл в процедуре НастроитьФорму, а имена элементов приходят в него строками из модуля менеджера справочника, по настройкам вида номенклатуры:
ВидимостьЭлементов = НастройкиВидимостиИЗаголовков.ВидимостьЭлементов;
...
Для Каждого ЭлементВидимость Из ВидимостьЭлементов Цикл
Если Элементы.Найти(ЭлементВидимость.Ключ) <> Неопределено Тогда
Элементы[ЭлементВидимость.Ключ].Видимость = ЭлементВидимость.Значение;
КонецЕсли;
...
Из 127 скрытых полей у 119 в XML нет вообще никакого следа. У 8 стоит функциональная опция на реквизите или команде формы, но включена ли она, файл не знает. Снимали карточку нового элемента с пустым видом, у заполненной карточки набор скрытых будет другим.
Насколько это типично, видно по выгрузке всей конфигурации: 1 508 форм документов и справочников и 1 434 модуля к ним.
| Что | Где задано в XML | Где задано кодом модуля |
|---|---|---|
| видимость элементов | функциональные опции у 348 форм | .Видимость = в 607 модулях |
| условное оформление | у 37 форм | УстановитьУсловноеОформление в 400 модулях |
| кнопки печати, отчётов, “Создать на основании” | нигде | ПодключаемыеКоманды.ПриСозданииНаСервере в 562 модулях |
| поля дополнительных реквизитов | нигде | УправлениеСвойствами.ПриСозданииНаСервере в 113 модулях |
Условное оформление в файле есть у 37 форм из 1 508, кодом оно строится в 400 модулях. У номенклатуры в XML ноль правил, в модуле четыре, и первая строка ПриСозданииНаСервере их пересобирает:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
УстановитьУсловноеОформление();
...
&НаСервере
Процедура УстановитьУсловноеОформление()
УсловноеОформление.Элементы.Очистить();
Элемент = УсловноеОформление.Элементы.Добавить();
...
Это Очистить() понадобится ниже, на нём ломается перехват.
Открытая форма: единственный способ узнать видимость
Получить форму кодом на сервере не выйдет. Глобальный ПолучитьФорму в серверном коде не компилируется (“Процедура или функция с указанным именем не определена”), а Документы.РеализацияТоваровУслуг.ПолучитьФорму("ФормаДокумента") через Выполнить отвечает “Интерактивные операции недоступны”. Это проверено на сервере типовой УТ 11.5, платформа 8.3.27.
На клиенте форму можно получить, не открывая окно. Так и сняли снимок на полигоне, упрощённо:
&НаКлиенте
Процедура ПоказатьСкрытые(Команда)
// Истина в четвёртом параметре: всегда новый экземпляр формы
Ф = ПолучитьФорму("Справочник.Номенклатура.Форма.ФормаЭлемента", , , Истина);
Скрытые = Новый Массив;
Для Каждого Эл Из Ф.Элементы Цикл
Попытка
Если Не Эл.Видимость Тогда
Скрытые.Добавить(Эл.Имя);
КонецЕсли;
Исключение
// как в замере: каждое свойство читается под Попыткой
КонецПопытки;
КонецЦикла;
Сообщить(СтрСоединить(Скрытые, ", "));
КонецПроцедуры
ПолучитьФорму прогоняет ПриСозданииНаСервере полностью, поэтому видимость в снимке та, что осталась после обработчика, для того пользователя, под которым снимали. Клиентский ПриОткрытии при этом не вызывается, а у номенклатуры он обновляет подключаемые команды, так что набор кнопок в живом окне может отличаться. Получение формы заняло 1 172 мс, обход 440 мс, один прогон.
Больше снимок почти ничего не даёт. На клиенте не читаются путь к данным (“Поле объекта не обнаружено (ПутьКДанным)”), обработчики событий (ПолучитьДействие отдал 0 из 102, “Метод недоступен на клиенте”), условное оформление и реквизиты формы. А форма документа может не получиться вовсе: форма реализации на полигоне упала на “Не удалось заполнить поле “Организация"", потому что ПриСозданииНаСервере заполняет новый документ по умолчанию.
Если снимать форму неудобно, видимость можно просто написать модели словами: “поле Артикул у нас скрыто, вкладка такая-то выключена опцией”. Важно, чтобы модель об этом знала.
Пример: перехват с четырьмя ошибками
Чтобы показать, как это складывается, мы написали перехват по догадке, без формы перед глазами, как его написала бы модель без выгрузки. Задача: подсвечивать пустой артикул и после переключения шаблона ценника требовать заполнения поля шаблона.
&НаСервере
&Перед("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Элемент = УсловноеОформление.Элементы.Добавить();
Поле = Элемент.Поля.Элементы.Добавить();
Поле.Поле = Новый ПолеКомпоновкиДанных("Артикул");
Отбор = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Артикул");
Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
Элемент.Оформление.УстановитьЗначениеПараметра("ОтметкаНезаполненного", Истина);
КонецПроцедуры
&НаКлиенте
&После("ИспользоватьОбщийШаблонЦенникаПриИзменении")
Процедура Расш1_ИспользоватьОбщийШаблонЦенникаПриИзменении(Элемент)
Элементы.ИндивидуальныйШаблонЦенника.АвтоОтметкаНезаполненного = Истина;
КонецПроцедуры
Синтаксис чистый. Ошибок четыре, и каждую ловит свой источник из таблицы в начале:
| Ошибка | Кто её видит | Что не так |
|---|---|---|
&Перед("ПриСозданииНаСервере") | модуль формы | типовой обработчик первой строкой вызывает Очистить() и стирает добавленное правило; нужен &После |
оформление на Артикул | снимок открытой формы | поле в новой карточке скрыто, пользователь подсветку не увидит |
имя в &После("...") | Form.xml | процедуры с таким именем нет, настоящая ИспользоватьИндивидуальныйШаблонЦенникПриИзменении, общая для двух переключателей |
Элементы.ИндивидуальныйШаблонЦенника | Form.xml | такого элемента нет, поле шаблона называется ШаблонЦенника |
После сверки:
&НаСервере
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Элемент = УсловноеОформление.Элементы.Добавить();
Поле = Элемент.Поля.Элементы.Добавить();
Поле.Поле = Новый ПолеКомпоновкиДанных(Элементы.Артикул.Имя);
Отбор = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Артикул");
Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
Элемент.Оформление.УстановитьЗначениеПараметра("ОтметкаНезаполненного", Истина);
КонецПроцедуры
&НаКлиенте
&После("ИспользоватьИндивидуальныйШаблонЦенникПриИзменении")
Процедура Расш1_ИспользоватьИндивидуальныйШаблонЦенникПриИзменении(Элемент)
// процедура общая для двух переключателей: сработает на любом из них
Элементы.ШаблонЦенника.АвтоОтметкаНезаполненного = (ИспользоватьИндивидуальныйШаблонЦенника = 1);
КонецПроцедуры
Элементы.Артикул.Имя возвращает ту же строку, что и литерал, но если поля нет, форма упадёт при первом создании и ошибка не останется незамеченной. Видимость кодом не лечится: в новой карточке на полигоне скрыты и Артикул, и ШаблонЦенника, и оба переключателя. Это настройка вида номенклатуры, и спросить про неё модель сможет, только если знает, что поля скрыты.
Как поведёт себя платформа с расширением, где в &После указана несуществующая процедура, мы не проверяли. Проще не доводить: имя из аннотации ищется в Module.bsl строкой Процедура ИмяИзАннотации(. Строки нет, значит, и перехватывать нечего.
Проверка ответа модели за пять минут
- Каждое
Элементы.Имяиз ответа найти в Form.xml какname="Имя". - Каждое имя из
&Перед,&После,&Вместонайти в Module.bsl. - Прочитать
ПриСозданииНаСерверетиповой формы: что она делает до и после места вашего перехвата. - Узнать видимость нужных полей снимком или у того, кто работает в базе.
Первые два пункта ловят две ошибки из четырёх в примере, третий и четвёртый по одной.
Остальной код внутри обработчиков формы уже к форме не относится: запросы, обращения к справочникам и регистрам, вызовы БСП. Здесь модель выдумывает имена так же, как в любом другом модуле, и проверяется это проверкой кода и запросов нейросети: она компилирует процедуры без выполнения, сверяет справочники, документы, регистры и значения перечислений с метаданными базы и находит несуществующие методы общих модулей. Как именно ловится выдуманный метод БСП без его вызова, разобрано в статье про выдуманные методы и поля. Имена элементов формы и аннотаций перехвата обработка пока не сверяет, для них остаётся поиск по выгрузке из списка выше.
Если модели нужна структура всей конфигурации, а не одной формы, её удобно дать выгрузкой метаданных.
Как мерили
Полигон на типовой УТ для Казахстана 3.4.4.87, тонкий клиент 8.3.27.1606, замер 01.11.2026. Снимали три формы для нового объекта без записи: элемента номенклатуры, списка контрагентов и документа реализации. Форма документа не создалась, поэтому в таблицах две. Сверка шла с Form.xml и Module.bsl из выгрузки той же версии, она же дала счёт по 1 508 формам и 1 434 модулям, элементы сопоставлялись по имени. Серверные вызовы ПолучитьФорму проверяли отдельно на типовой УТ 11.5. Нейросеть в замере не участвовала: перехват написан нами по догадке, чтобы показать, где сверка ловит угаданное.