ПриСозданииНаСервере : единственное место для модификаций формы
Важный факт: динамическое добавление реквизитов и элементов формы 1С возможно только до полной отрисовки формы, в обработчике события ПриСозданииНаСервере. Именно там выполняется программная «рисовка» интерфейса. Так, по данным разработчиков, «любые элементы управляемой формы 1С программно могут добавляться… из предопределенного события формы ПриСозданииНаСервере()» . Если попытаться запустить ИзменитьРеквизиты() или Элементы.Добавить() позже – например, в обычном серверном методе после открытия – произойдет ошибка ( подробнее об этом ниже). В общем, первая задача – позаботиться, чтобы код модификации находился внутри &НаСервере Процедура ПриСозданииНаСервере(...) соответствующего модуля формы.
Немного отвлечёмся: на самом деле лучше всего сначала делать ИзменитьРеквизиты, а после – добавлять элементы. Так рекомендует практика. Ведь если вы добавляете новый реквизит формы (поле, которое может сохраняться), для него нужно сперва вызвать ИзменитьРеквизиты(МассивНовыхРеквизитов). И только после этого создавать элементы (поле ввода, кнопку, и т.п.), задавая им путь к данным. Иначе элемент не найдёт своего поля. Проще говоря, сначала добавляем поля в форму, потом привязываем к ним элементы (или сразу к свойствам объекта). Об этом тоже прямо говорится: «Добавлять новые реквизиты в управляемую форму необходимо с помощью метода ИзменитьРеквизиты() … » . Далее — «эти изменения выполняются до создания элементов формы» . Это важно держать в голове: поля и связанные с ними элементы создаются в обработчике ПриСозданииНаСервере, иначе система их не применит.
Методы: ИзменитьРеквизиты, Элементы.Добавить и Элементы.Вставить
Для программного добавления используются три основных средства. Первое – метод формы ИзменитьРеквизиты(Добавляемые,Удаляемые). В него передают массивы новых и удаляемых реквизитов формы. Обычно создают новые поля так (пример на «форме документа» или «справочника»):
ДобавляемыеРеквизиты = Новый Массив; // Описываем будущие поля формы: НовыйРеквизит = Новый РеквизитФормы("ИмяПоля", Новый ОписаниеТипов("Булево"), "", "НазваниеПоля"); // Добавляем в массив ДобавляемыеРеквизиты.Добавить(НовыйРеквизит); // Применяем изменения к форме ЭтаФорма.ИзменитьРеквизиты(ДобавляемыеРеквизиты);
После вызова ИзменитьРеквизиты() новые поля становятся доступными в ЭтаФорма. Только вот ошибка: если вызвать этот метод не на этапе создания формы (а, скажем, в ПриОткрытии() или в даже в любом другом обработчике на сервере, но позже события создания формы), произойдет исключение «Изменение состава элементов недоступно». Это сообщение означает: «форма уже построена, менять её нельзя». Фактически, платформа позволяет изменить состав полей только один раз при создании формы.
Второе и третье средство – это методы коллекции элементов Элементы.Добавить(Имя,Тип,Родитель) и Элементы.Вставить(Имя,Тип,Родитель,ПередКем). С помощью Добавить создают элемент в конце указанной группы или на форме:
НовыйЭлемент = ЭтаФорма.Элементы.Добавить("ПолеФлажка", Тип("ПолеФормы"), ЭтаФорма); НовыйЭлемент.Вид = ВидПоляФормы.ПолеФлажка; НовыйЭлемент.ПутьКДанным = "ИмяРеквизита";
С помощью Вставить можно разместить элемент между существующими:
НовыйЭлемент = ЭтаФорма.Элементы.Вставить("Кнопка", Тип("КнопкаФормы"), ЭтаФорма, Элементы.ДругаяКнопка);
То есть методы ЭтаФорма.Элементы.Добавить и ЭтаФорма.Элементы.Вставить – единственные инструменты для программной генерации элементов (текстовых полей, кнопок, декораций и т.п.). Их следует вызывать именно после ИзменитьРеквизиты(). Лишнюю элементную иерархию задавать не нужно – методы сами добавляют в ЭтаФорма.Элементы.
Небольшое отступление: во многих типовых расширениях 1С такой код считают основным способом доработки интерфейсов. Всё-таки, как говорится, «код легко обновлять и сопровождать, но медленнее отрабатывает» – так что на практике стараются разделять дизайн и код. Но иногда приходится добавлять хоть одно поле через код, и тогда алгоритм ясен: ПриСозданииНаСервере → НовыйРеквизитФормы() → ИзменитьРеквизиты → Элементы.Добавить… – такая пошаговая схема справляется с задачей.
Создание группового элемента и его особенности
Бывает задача добавить группу на форму программно. При создании группы на форме важно правильно указать ее тип. Пример:
НоваяГруппа = ЭтаФорма.Элементы.Добавить("МояГруппа", Тип("ГруппаФормы"), ЭтаФорма); НоваяГруппа.Вид = ВидГруппыФормы.ОбычнаяГруппа;
Без явной установки свойства Вид будет возникать ошибка. На практике встречается такая ситуация: код вроде
ЭлГруппа = Элементы.Добавить("гр_"+some, Тип("ГруппаФормы"), Элементы.ВерхнийРядВыкладки);
создаёт группу, но потом при попытке вложить в неё другое поле выскакивает «Недопустимое значение параметров». Решение – сразу после Добавить указывайте ЭлГруппа.Вид = ВидГруппыФормы.ОбычнаяГруппа. Как пишут разработчики 1С на форумах, «в итоге сменил тип на Тип("ГруппаФормы") и добавил Группа.Вид = ВидГруппыФормы.ОбычнаяГруппа – и всё заработало» . Иными словами, не забывайте отмечать тип группы, иначе дочерние элементы туда не «добавятся».
Тут же важно помнить: имя каждого элемента (включая группы) должно быть уникальным на форме. Если вы попытаетесь создать элемент с именем, уже занятым типовой формой или другим расширением, платформа выдаст «Элемент с таким именем уже есть на форме» или просто «Недопустимое значение параметров». Это частая причина ошибок: конфликт имён. Решение простое – придумать уникальное имя (например, с префиксом вашего расширения). Например: Добавить("МояКнопка", Тип("КнопкаФормы"), ЭтаФорма) – так сформируется на форме элемент с данным именем; потом задайте его НовыйЭлемент.ПутьКДанным или обработчики.
Типичные ошибки при программном добавлении
Программирование форм – дело тонкое, и ряд ошибок тут встречается часто. Перечислим самые популярные сценарии проблем (и как их решать):
- Изменение формы в неподходящем событии. Если вызвать
ИзменитьРеквизиты()илиЭлементы.Добавить()не вПриСозданииНаСервере, платформа ругается. Частая ошибка: пытаются в обработчике ПриОткрытии или на клиенте изменить форму. Результат – «Недопустимое значение параметров» или «Изменение состава элементов недоступно». Официально об этом не сказано, но ясно: форма уже построена – дальше менять её нельзя. Выход – перенести код в серверный обработчикПриСозданииНаСервере. Кстати, на форумах советуют даже переходить в server-контекст модули, чтобы гарантированно быть на сервере. - Неправильно указан тип элемента. Например, попытка добавить список значений через
Тип()приведёт к ошибке. Более конкретно: в коде клиента или сервере один разработчик писали получил «Недопустимое значение параметров». Оказалось: для поля со списком значений нужно указывать Тип("ПолеФормы"), а для поля флажка – Тип("ПолеФормы") + .Вид=ВидПоляФормы.ПолеФлажка, и т.д. Если тип элемента не соответствует тому, что вы думаете, метод Добавить упадёт с этой ошибкой. Всегда смотрите, какие типы элементов доступны: Типы называются «ПолеФормы», «КнопкаФормы», «ГруппаФормы» и т.д.НовЭлемент = Элементы.Добавить("СвоиЦены", Тип("СписокЗначений"));
- Неправильное указание родительского элемента. При использовании методов
Элементы.Вставить()илиЭлементы.Добавить()может помочь явно указать группу. В диалоге один программист добавлял Вставить без параметра «перед элементом» (третьим), и форма думала, что это невалидно. Если не уверены, попробуйте обе сигнатуры:Добавить(Имя,Тип,Родитель)иВставить(Имя,Тип,Родитель,ПередКем). Иногда после обновлений платформы «элементы.ТекущийПредок» меняется – тогда форумчане советуют задать родителя явно. - Попытка установить некорректный путь данных. После создания элемента нужно задать ПутьКДанным. Чаще всего это либо имя реквизита формы, либо путь вида Объект.Поле. Если перепутать, получите либо «Недопустимое значение» (если поля нет), либо элемент просто останется пустым. Например, если задать НовыйПоле.ПутьКДанным = "НеСуществующий" – это сразу бросит исключение. Если вы хотите связать элемент с основным объектом, пишите «Объект.Реквизит» (см. далее). Если связать с новым реквизитом формы – пишите его точное имя.
Вот таблица-резюме распространённых ошибок:
| Ошибка на форме/сообщение | Причина | Решение |
|---|---|---|
Изменение состава элементов недоступно |
Код не в ПриСозданииНаСервере или на клиенте |
Перенести вызов на сервер в обработчик ПриСозданииНаСервере |
Недопустимое значение параметров |
Неправильный тип элемента, конфликт имён или неправильный вызов метода | Исправить тип (например, Тип("ПолеФормы") вместо
Тип("СписокЗначений")
), убедиться в уникальности имени, правильно указать аргументы |
Элемент с таким именем уже есть на форме |
Дублирование имени элемента | Выбрать уникальное имя (с учётом других расширений) |
Другие ошибки (Недопустимый инд., ТекВалюта...) |
Обычно связано с неверными параметрами/порядком вызова | Проверить параметры, типы и места вызова |
Каждая из этих ошибок – повод свериться с правилами: добавить реквизит надо через ИзменитьРеквизиты, элемент – через Элементы.Добавить/Вставить, в правильном событии. Ошибки сами по себе – лишь указатель, что что-то сделано не в том месте или не тем методом.
Привязка элементов к реквизитам и свойствам объекта
После того как элементы созданы, их надо связать с данными: назначить, что именно отображать и сохранять. Связь задаётся через свойство ПутьКДанным. Можно связать элемент либо с реквизитом формы, либо с свойством основного объекта формы (справочника, документа).
- Связь с реквизитом формы: если вы создали новый реквизит формы (через
НовыйРеквизитФормы()и ИзменитьРеквизиты), его имя становится доступным. Допустим, вы добавили реквизит «НовыйПолеТекста». Тогда при создании элемента делайте так:Таким образом элемент привязывается к только что добавленному реквизиту. В примерах говорится, что новый элемент нужно «подштукатурить» таким же именем: в готовом видеЭл = ЭтаФорма.Элементы.Добавить("ПолеТекст", Тип("ПолеФормы"), ЭтаФорма); Эл.ПутьКДанным = "НовыйПолеТекста";
НовыйЭлемент.ПутьКДанным = "ИмяРеквизита". Например:НовыйЭлемент.ПутьКДанным = "пр_Использование";где пр_Использование – имя добавленного реквизита. - Связь с полем основного объекта: если вы хотите вывести на форму свойство основного объекта (например, поле справочника/документа), начинайте путь с Объект. Например, чтобы вывести свойство Дата и Номер документа, пишут:
Такой код встречается в пособиях: «ПолеДата.ПутьКДанным = "Объект.Дата"; … ПолеНомер.ПутьКДанным = "Объект.Номер"» . После этого в элемент будет передаваться значение поля объекта. Аналогично можно привязать другие свойства: например, числовое поле к «Объект.Сумма» и т.д. Главное – «Объект» + точка + имя поля.
ПолеДата = ЭтаФорма.Элементы.Добавить("ПолеДата", Тип("ПолеФормы"), Группа); ПолеДата.ПутьКДанным = "Объект.Дата"; ПолеНомер = ЭтаФорма.Элементы.Добавить("ПолеНомер", Тип("ПолеФормы"), Группа); ПолеНомер.ПутьКДанным = "Объект.Номер";
Таким образом, чтобы связать добавленный элемент со значениями, сначала убедитесь, что у вас есть подходящее поле (реквизит) в форме либо объекте, а затем указывайте путь. В результате, при открытии формы в этих элементах будут показаны нужные данные, и при изменении пользователем они сохранятся обратно в реквизиты формы или объекта.
Итог
Программное добавление элементов формы в 1С требует строгого соблюдения порядка и контекста. Главное – исполнять код в обработчике ПриСозданииНаСервере и внимательно работать с именами и типами: так, группа должна получить свой вид, а ПутьКДанным – корректный адрес поля. При правильном подходе появляется гибкость – можно в расширении добавить любые интерфейсные элементы динамически. Но остаётся вопрос: не станет ли столько усилий избыточным, если платформа всё равно не позволяет вмешиваться в форму после создания? Можно ли придумать удобные шаблоны для добавления целых блоков интерфейса? Как вы думаете, насколько разумно полагаться на динамические формы, или стоит искать другие способы? Оставляем это открытым вопросом: действительно ли такие тонкости программирования оправданы, если многие действия придётся повторять в разных конфигурациях?













































