Разработка и Конфигурация · 12 мин
Как создать форму программно в 1С
Программное создание форм в 1С: ПолучитьФорму, ОткрытьФорму, динамическое добавление реквизитов и элементов, примеры кода и типичные ошибки разработчика.
Программная работа с формами в 1С:Предприятии 8.3 встречается в двух сценариях: когда нужно открыть существующую форму объекта с параметрами и когда форму требуется построить полностью из кода — без заранее нарисованного макета в конфигураторе. Первый сценарий решается методами ПолучитьФорму() и ОткрытьФорму(), второй — динамическим изменением реквизитов и элементов управляемой формы в обработчике ПриСозданииНаСервере().
Важно понимать ограничение платформы: создать «с нуля» форму, которой нет в конфигурации, напрямую нельзя. Практический приём — использовать пустую форму общей формы или форму обработки как каркас и наполнять её реквизитами и элементами программно. Либо генерировать форму внешней обработки, где вся структура строится кодом.
Ниже разобраны оба подхода с рабочими примерами кода, различиями между управляемым и обычным приложением, типичными ошибками и способами проверить результат.
Способы программной работы с формами
В управляемом приложении есть три принципиально разных задачи, которые часто путают. Первая — открыть уже описанную в конфигураторе форму справочника, документа или обработки с нужными параметрами. Вторая — получить объект формы в переменную без отображения, чтобы обратиться к её данным. Третья — динамически достроить форму: добавить поля, таблицы, кнопки, которых нет в статическом описании.
Для открытия формы используется ОткрытьФорму() — асинхронный по логике интерфейса метод, который показывает форму пользователю. Для получения объекта без показа — ПолучитьФорму(). Динамическое построение выполняется только на сервере в обработчике ПриСозданииНаСервере(), потому что именно там доступно изменение состава реквизитов формы.
Сравнение подходов
Подходит для показа формы пользователю с параметрами. Не возвращает управление в вызывающий код до закрытия, если открыта модально.
Возвращает объект формы в переменную для программного доступа к данным. Форма не показывается, пока не вызван Открыть().
Полный контроль над составом элементов из кода. Требует пустой формы-каркаса и больше труда на сопровождение.
Открытие существующей формы с параметрами
Самая частая задача — открыть форму элемента справочника или документа и передать туда значения. Параметры формируются структурой, где ключи соответствуют именам параметров формы или стандартным ключам: Ключ (ссылка на объект), ЗначенияЗаполнения, Отбор для форм списка.
&НаКлиенте
Процедура ОткрытьКарточкуКлиента(Команда)
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Ключ", ТекущийКлиент);
ОткрытьФорму("Справочник.Контрагенты.Форма.ФормаЭлемента", ПараметрыФормы);
КонецПроцедуры
Для формы списка с отбором по владельцу или периоду используется параметр Отбор — структура, где ключи совпадают с именами полей динамического списка:
&НаКлиенте
Процедура ПоказатьДокументыКонтрагента(Команда)
Отбор = Новый Структура("Контрагент", ТекущийКонтрагент);
ПараметрыФормы = Новый Структура("Отбор", Отбор);
ОткрытьФорму("Документ.РеализацияТоваров.ФормаСписка", ПараметрыФормы);
КонецПроцедуры
Если нужно получить результат выбора из открываемой формы, используйте ОткрытьФорму() с описанием оповещения — модальный вызов с возвратом значения через обработчик. Это стандартный механизм вместо устаревшего ОткрытьФормуМодально(), который не поддерживается в веб-клиенте и блокируется современными браузерными ограничениями.
Создание формы обработки программно: каркас
Чтобы построить форму целиком из кода, создайте в конфигураторе обработку и добавьте ей пустую форму — без реквизитов и элементов. Вся структура будет добавляться в обработчике ПриСозданииНаСервере(). Порядок строго определён: сначала реквизиты формы, затем элементы, привязанные к реквизитам.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// 1. Добавляем реквизиты
ДобавляемыеРеквизиты = Новый Массив;
ДобавляемыеРеквизиты.Добавить(
Новый РеквизитФормы("Комментарий",
Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(200))));
ДобавляемыеРеквизиты.Добавить(
Новый РеквизитФормы("Количество",
Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 2))));
ИзменитьРеквизиты(ДобавляемыеРеквизиты);
// 2. Добавляем элементы и связываем с реквизитами
ЭлементКомментарий = Элементы.Добавить("Комментарий", Тип("ПолеФормы"));
ЭлементКомментарий.Вид = ВидПоляФормы.ПолеВвода;
ЭлементКомментарий.ПутьКДанным = "Комментарий";
ЭлементКомментарий.Заголовок = "Комментарий";
ЭлементКоличество = Элементы.Добавить("Количество", Тип("ПолеФормы"));
ЭлементКоличество.Вид = ВидПоляФормы.ПолеВвода;
ЭлементКоличество.ПутьКДанным = "Количество";
КонецПроцедуры
Ключевой момент — метод ИзменитьРеквизиты(). Он принимает два массива: добавляемые и удаляемые реквизиты, и вызывается только на сервере до обращения к элементам. Если попытаться создать элемент с ПутьКДанным, указывающим на несуществующий реквизит, платформа выдаст ошибку при открытии формы.
- 1Создайте обработку и добавьте ей пустую форму в конфигураторе
- 2В ПриСозданииНаСервере() сформируйте массив объектов РеквизитФормы с именами и типами
- 3Вызовите ИзменитьРеквизиты() для добавления реквизитов в форму
- 4Добавьте элементы через Элементы.Добавить() и задайте Вид и ПутьКДанным
- 5Назначьте команды и обработчики через УстановитьДействие()
- 6Откройте форму и проверьте ввод, сохранение и отсутствие ошибок в журнале регистрации
Динамическое добавление таблицы и команд
Табличная часть строится по той же логике: сначала реквизит типа ТаблицаЗначений, затем его колонки как подчинённые реквизиты, затем элемент ТаблицаФормы и поля колонок.
&НаСервере
Процедура ДобавитьТаблицуТоваров()
Реквизиты = Новый Массив;
Реквизиты.Добавить(Новый РеквизитФормы("Товары",
Новый ОписаниеТипов("ТаблицаЗначений")));
Реквизиты.Добавить(Новый РеквизитФормы("Номенклатура",
Новый ОписаниеТипов("СправочникСсылка.Номенклатура"), "Товары"));
Реквизиты.Добавить(Новый РеквизитФормы("Цена",
Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)), "Товары"));
ИзменитьРеквизиты(Реквизиты);
Таблица = Элементы.Добавить("Товары", Тип("ТаблицаФормы"));
Таблица.ПутьКДанным = "Товары";
КолонкаНоменклатура = Элементы.Добавить("ТоварыНоменклатура", Тип("ПолеФормы"), Таблица);
КолонкаНоменклатура.Вид = ВидПоляФормы.ПолеВвода;
КолонкаНоменклатура.ПутьКДанным = "Товары.Номенклатура";
КолонкаЦена = Элементы.Добавить("ТоварыЦена", Тип("ПолеФормы"), Таблица);
КолонкаЦена.Вид = ВидПоляФормы.ПолеВвода;
КолонкаЦена.ПутьКДанным = "Товары.Цена";
КонецПроцедуры
Кнопки и команды добавляются в два шага: сначала создаётся объект команды формы, затем кнопка, привязанная к ней. Обработчик назначается методом УстановитьДействие(), где указывается имя процедуры, которая должна существовать в модуле формы с директивой &НаКлиенте или &НаСервере в зависимости от контекста команды.
Команда = Команды.Добавить("ЗаполнитьЦены");
Команда.Действие = "ЗаполнитьЦены";
Команда.Заголовок = "Заполнить цены";
Кнопка = Элементы.Добавить("КнопкаЗаполнить", Тип("КнопкаФормы"), Таблица.КоманднаяПанель);
Кнопка.ИмяКоманды = "ЗаполнитьЦены";
Обычные формы: чем отличается подход
В обычном приложении (режим, актуальный для старых конфигураций на платформе 8.2 и ранних 8.3) формы строятся иначе. Там нет разделения на клиент и сервер внутри модуля формы, а элементы управления добавляются напрямую через коллекцию ЭлементыФормы с указанием типа и родителя, без предварительного создания реквизитов.
Процедура ПриОткрытии()
НовоеПоле = ЭлементыФормы.Добавить(Тип("ПолеВвода"), "ПолеКомментарий", Истина);
НовоеПоле.Верх = 10;
НовоеПоле.Лево = 10;
НовоеПоле.Ширина = 300;
НовоеПоле.Данные = "Комментарий";
КонецПроцедуры
Координатная привязка (Верх, Лево, Ширина) вместо компоновки — главное внешнее отличие. Если конфигурация работает в обычном режиме, учитывайте, что динамически добавленные элементы не сохраняются между сеансами и должны пересоздаваться при каждом открытии формы.
Типичные ошибки и как их избежать
Большинство проблем при программном построении форм связано с нарушением порядка вызовов или контекста выполнения. Платформа сообщает об ошибках не всегда очевидно: например, отсутствие реквизита проявляется только при открытии формы, а не при компиляции модуля.
Отдельная группа ошибок — работа с данными после закрытия формы. Объект управляемой формы нельзя хранить в переменных между серверными вызовами: форма сериализуется, и ссылки на её элементы теряют актуальность. Передавайте между вызовами примитивные данные и ссылки на объекты базы, а не объекты формы.
Проверка результата
После построения формы проверьте не только визуальное отображение, но и полный цикл работы с данными. Поля должны принимать ввод, таблица — добавлять и удалять строки, команды — выполнять назначенные процедуры без ошибок в журнале регистрации.
Как проверить результат
Форма открывается без сообщений об ошибках, все элементы видны
Ошибка «Поле не найдено» или пустая форма — нарушен порядок создания реквизитов и элементов
Введённые значения доступны в серверных процедурах через ЭтаФорма.ИмяРеквизита
Поле визуально заполняется, но на сервере значение пустое — не задан или неверен ПутьКДанным
Нажатие кнопки вызывает назначенную процедуру
Ошибка «Процедура не обнаружена» — имя в УстановитьДействие() не совпадает с процедурой модуля
Форма пересоздаётся корректно, без дублирования элементов
Ошибка о существующем реквизите — динамическое построение вызывается повторно для той же формы
Полезный приём отладки — временно выводить состав реквизитов и элементов в сообщения внутри ПриСозданииНаСервере(), чтобы убедиться, что структура построена именно в том виде, который ожидается. После отладки такой вывод удаляют, чтобы не засорять интерфейс пользователя.
Частые вопросы
Можно ли создать форму вообще без конфигуратора, только кодом?
Напрямую — нет: платформа требует наличия объекта формы в конфигурации. Практическое решение — пустая форма обработки или общая форма, которая наполняется реквизитами и элементами в ПриСозданииНаСервере(). Для внешних инструментов используют внешнюю обработку с аналогичным каркасом.
Как передать данные из открываемой формы обратно в вызывающую?
Используйте ОткрытьФорму() с параметром ОписаниеОповещенияОЗакрытии — процедура-обработчик получит значение, переданное через Закрыть(Результат) в открываемой форме. Альтернатива — Оповестить() и обработчик ОбработкаОповещения() в вызывающей форме.
Почему динамически добавленные поля не сохраняют введённые значения?
Чаще всего свойство ПутьКДанным не задано или указывает на несуществующий реквизит. Проверьте, что реквизит добавлен через ИзменитьРеквизиты() до создания элемента и что имена совпадают посимвольно, включая регистр букв в длинных составных именах.
Можно ли изменить состав элементов формы после её открытия?
Да, но только через серверный вызов: добавление реквизитов возможно в любом серверном обработчике, не только при создании. Учитывайте, что после ИзменитьРеквизиты() форма пересоздаётся, и несохранённые данные в динамических элементах могут быть потеряны.
Чем ПолучитьФорму() отличается от ОткрытьФорму()?
ПолучитьФорму() возвращает объект формы в переменную без отображения — для программного доступа к данным и экспортным процедурам формы. ОткрытьФорму() сразу показывает форму пользователю и не возвращает сам объект. Для показа полученной формы вызывают её метод Открыть().
Работает ли динамическое построение форм в веб-клиенте?
Да, управляемые формы с программно добавленными реквизитами и элементами корректно работают в веб-клиенте. Ограничения касаются модальных вызовов и некоторых методов тонкого клиента — используйте асинхронные аналоги с описаниями оповещений.
Что важно запомнить
Существующие формы открывают через ОткрытьФорму() с параметрами, программные формы строят на пустом каркасе: сначала ИзменитьРеквизиты() на сервере, затем Элементы.Добавить() с корректным ПутьКДанным. Проверяйте ввод данных, работу команд и повторное открытие — большинство ошибок проявляется именно там.