Как программно добавить реквизит и элемент на управляемую форму в 1С 8.3 и обеспечить сохранение его значения

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В разработке на платформе 1С:Предприятие 8.3 часто возникают задачи, когда структуру формы необходимо изменить «на лету». Это может быть связано с динамическим отображением настроек, выводом дополнительных колонок в таблицы или интеграцией с расширениями. Однако при программном добавлении реквизитов начинающие разработчики часто сталкиваются с проблемой: реквизит на форме появляется, но данные в нем не сохраняются или сбрасываются сразу после завершения процедуры создания. Рассмотрим подробно, как правильно реализовать этот механизм и избежать типичных ошибок.

Анализ основной проблемы: почему значение реквизита «пропадает»

Разберем типичную ситуацию. Разработчик добавляет реквизит через массив и метод ИзменитьРеквизиты, затем вставляет элемент формы (поле ввода) и пытается присвоить ему значение. В отладке внутри процедуры ПриСозданииНаСервере значение отображается как заполненное, но при выполнении любого другого действия (например, нажатии кнопки) значение реквизита становится Неопределено или пустым.

Основная причина кроется в области видимости переменных. Когда мы пишем в коде:

КадровыйДокумент = ВыборкаДетальныеЗаписи.Ссылка;

Если в данной процедуре не определено иное, платформа 1С воспринимает КадровыйДокумент как локальную переменную процедуры. Несмотря на то, что мы только что создали реквизит формы с точно таким же именем, локальная переменная имеет приоритет. В итоге значение записывается в «память» процедуры, которая очищается сразу после ее завершения, а программно созданный реквизит формы остается пустым.

Шаг 1: Правильное создание реквизита формы

Процесс начинается с формирования массива новых реквизитов. Важно помнить, что метод ИзменитьРеквизиты является ресурсоемким, так как он инициирует полную пересборку структуры формы на сервере. Проанализируем правильный подход к созданию:


// Создаем массив для добавления
ДобавляемыеРеквизиты = Новый Массив;

// Определяем тип данных. Избегайте использования ТипВсеСсылки(), 
// так как это замедляет работу системы. Лучше указывать конкретный тип.
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("ДокументСсылка.ПриемНаРаботу"));
МассивТипов.Добавить(Тип("ДокументСсылка.Увольнение"));
ОписаниеТиповКД = Новый ОписаниеТипов(МассивТипов);

// Инициализируем реквизит формы
// Параметры: Имя, Тип, Путь, Заголовок, СохраняемыеДанные
Реквизит_КД = Новый РеквизитФормы("КадровыйДокумент", ОписаниеТиповКД, , "Кадровый документ", Истина);
ДобавляемыеРеквизиты.Добавить(Реквизит_КД);

// Применяем изменения на форме
ЭтаФорма.ИзменитьРеквизиты(ДобавляемыеРеквизиты);

Шаг 2: Добавление визуального элемента

После того как место в памяти (реквизит) выделено, нам нужно создать элемент управления, чтобы пользователь мог видеть данные. Мы используем метод Элементы.Вставить или Элементы.Добавить. Выясним разницу: Вставить позволяет указать позицию относительно других элементов (например, внутри группы), а Добавить помещает элемент в конец коллекции.


// Вставляем поле на форму
// Параметры: ИмяЭлемента, ТипЭлемента, Родитель, ЭлементПередКоторымВставляем
НовоеПоле = ЭтаФорма.Элементы.Вставить("ДекорацияКадровыйДокумент", Тип("ПолеФормы"), Элементы.ГруппаСодержание, Элементы.Содержание);
НовоеПоле.Вид = ВидПоляФормы.ПолеВвода;
НовоеПоле.ПутьКДанным = "КадровыйДокумент"; // Указываем имя созданного реквизита
НовоеПоле.Гиперссылка = Истина;

Важный нюанс: Если вы добавляете реквизит, который должен принадлежать основному объекту формы (например, колонку в табличную часть Объект.Товары), то в конструкторе РеквизитФормы третьим параметром нужно обязательно передать путь к родителю: "Объект.Товары".

Шаг 3: Корректное обращение к программному реквизиту

Чтобы избежать конфликтов с локальными переменными, о которых мы говорили выше, всегда используем явное обращение к контексту формы через ЭтаФорма или ЭтотОбъект (в модуле формы они идентичны). Рассмотрим исправленный блок заполнения данных:


// Выполняем запрос для поиска данных
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Документ.ПриемНаРаботу ГДЕ Организация = &Организация");
Запрос.УстановитьПараметр("Организация", Объект.Организация);
Результат = Запрос.Выполнить();

Если Не Результат.Пустой() Тогда
    Выборка = Результат.Выбрать();
    Выборка.Следующий();
    
    // ПРАВИЛЬНО: Обращаемся через ЭтаФорма
    ЭтаФорма.КадровыйДокумент = Выборка.Ссылка;
    
    // Или через квадратные скобки, если имя динамическое
    // ЭтаФорма["КадровыйДокумент"] = Выборка.Ссылка;
КонецЕсли;

Дополнительные возможности: Обработчики событий

Просто создать поле часто недостаточно — нужно, чтобы оно реагировало на действия пользователя. Для программно созданных элементов мы можем назначать обработчики событий с помощью метода УстановитьДействие. Разберем на примере события ПриИзменении:


// Назначаем обработчик
НовоеПоле.УстановитьДействие("ПриИзменении", "Подключаемый_КадровыйДокументПриИзменении");

// В модуле формы должна быть соответствующая процедура:
&НаКлиенте
Процедура Подключаемый_КадровыйДокументПриИзменении(Элемент)
    // Код обработки изменения
    Сообщить("Значение изменено на: " + КадровыйДокумент);
КонецПроцедуры

Рекомендации по оптимизации

  1. Группировка вызовов: Никогда не вызывайте ИзменитьРеквизиты в цикле. Если нужно добавить 10 реквизитов, сначала добавьте все 10 объектов РеквизитФормы в один массив и вызовите метод один раз.
  2. Удаление старого: Метод ИзменитьРеквизиты имеет второй параметр — массив имен удаляемых реквизитов. Если ваша форма предполагает динамическое перестроение (например, при смене вида операции), не забывайте удалять старые программные реквизиты, чтобы не перегружать память сеанса.
  3. Проверка на существование: Перед добавлением всегда проверяйте, не был ли реквизит уже создан ранее. Это особенно актуально, если код выполняется в процедурах, отличных от ПриСозданииНаСервере.
    
    Если ЭтаФорма.НайтиРеквизит("КадровыйДокумент") = Неопределено Тогда
        // Код добавления
    КонецЕсли;
    
  4. Типизация: Использование ОписаниеТипов с максимально узким списком типов значительно ускоряет отрисовку формы и работу выпадающих списков для пользователя.

Таким образом, программное управление элементами формы — это мощный инструмент, требующий аккуратности в работе с контекстом. Используя явное обращение к свойствам формы и соблюдая правила типизации, вы сможете создавать гибкие и производительные интерфейсы.

← На главную