Как программно добавить реквизиты на форму и передать их значения в модуль объекта для упрощения обновлений?

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

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

Где размещать код для модификации формы

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

Рассмотрим алгоритм размещения кода:

  1. Создадим новое расширение (если оно еще не создано).
  2. Добавим в расширение форму нужного документа (например, ТребованиеНакладная).
  3. В модуле формы расширения создадим процедуру-обработчик с аннотацией &После("ПриСозданииНаСервере").

Если логика добавления реквизитов универсальна или вы хотите вынести её в отдельное место, создадим собственный Общий модуль в расширении. Назовем его, например, _РаботаСФормамиКастом. В свойствах модуля обязательно установим флаги Сервер и Вызов сервера. Теперь из процедуры ПриСозданииНаСервере в форме мы сможем вызвать метод нашего общего модуля.


// В модуле формы расширения
&НаСервере
&После("ПриСозданииНаСервере")
Процедура _ПослеПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    _РаботаСФормамиКастом.ДобавитьРеквизитыНаФорму(ЭтаФорма);
КонецПроцедуры

Алгоритм программного создания реквизитов

Процесс добавления элементов на форму состоит из двух принципиально разных этапов. Выясним, почему простого объявления переменной недостаточно. Проанализируем структуру управляемой формы: сначала мы создаем данные (реквизиты), а затем — представление (элементы формы).

Разберем создание реквизита по шагам в общем модуле:


Процедура ДобавитьРеквизитыНаФорму(Форма) Экспорт
    
    // Шаг 1: Описываем структуру нового реквизита
    ДобавляемыеРеквизиты = Новый Массив;
    ТипРеквизита = Новый ОписаниеТипов("Булево");
    НовыйРеквизит = Новый РеквизитФормы("СписыватьДомовыеЗатраты", ТипРеквизита, , "Списывать затраты", Истина);
    ДобавляемыеРеквизиты.Добавить(НовыйРеквизит);
    
    // Шаг 2: Применяем изменения к форме
    Форма.ИзменитьРеквизиты(ДобавляемыеРеквизиты);
    
    // Шаг 3: Создаем визуальный элемент (поле ввода или флажок)
    ИмяГруппы = "ГруппаШапкаЛевая"; // Или любая существующая группа на форме
    ЭлементГруппы = Форма.Элементы.Найти(ИмяГруппы);
    
    Если ЭлементГруппы <> Неопределено Тогда
        НовыйЭлемент = Форма.Элементы.Добавить("СписыватьДомовыеЗатраты", Тип("ПолеФормы"), ЭлементГруппы);
        НовыйЭлемент.Вид = ВидПоляФормы.ПолеФлажка;
        НовыйЭлемент.ПутьКДанным = "СписыватьДомовыеЗатраты";
    КонецЕсли;

КонецПроцедуры

Почему возникает ошибка «Переменная не определена» в модуле объекта

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

Если вам нужно использовать значение из программно созданного реквизита формы в логике проведения или перед записью, его необходимо передать внутрь объекта. Посмотрим, как это сделать правильно.

Передача данных через ДополнительныеСвойства

Наиболее корректный способ передачи «внештатных» данных из формы в модуль объекта — использование коллекции ДополнительныеСвойства. Эта коллекция доступна как в форме (через Объект.ДополнительныеСвойства), так и внутри модуля объекта.

Шаг 1. Передача значения из формы. Нам нужно перехватить момент записи. В расширении формы используем событие ПередЗаписьюНаСервере:


&НаСервере
&После("ПередЗаписьюНаСервере")
Процедура _ПослеПередЗаписьюНаСервере(Отказ, ПараметрыЗаписи)
    // Копируем значение из нашего программного реквизита в свойства объекта
    ТекущийОбъект = РеквизитФормыВЗначение("Объект");
    ТекущийОбъект.ДополнительныеСвойства.Вставить("СписыватьДомовыеЗатраты", ЭтаФорма.СписыватьДомовыеЗатраты);
    ЗначениеВРеквизитФормы(ТекущийОбъект, "Объект");
    
    // Либо более простой способ для УФ, если Объект уже доступен:
    Объект.ДополнительныеСвойства.Вставить("СписыватьДомовыеЗатраты", ЭтаФорма.СписыватьДомовыеЗатраты);
КонецПроцедуры

Шаг 2. Чтение значения в модуле объекта. Теперь в МодулеОбъекта (также через расширение) мы можем безопасно обратиться к этому свойству:


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

КонецПроцедуры

Проблема сохранения данных между сессиями

Важно понимать: программно созданный реквизит формы не сохраняется в базе данных автоматически. Если пользователь установит флажок, нажмет «Записать» и закроет форму, при следующем открытии значение будет потеряно (установится значение по умолчанию).

Чтобы данные сохранялись, рассмотрите следующие варианты:

Программная установка обработчиков событий

Чтобы созданные элементы формы реагировали на действия пользователя (например, при изменении флага нужно пересчитать итоги), необходимо программно назначить обработчик события. Используем метод УстановитьДействие.


// В процедуре создания элементов
НовыйЭлемент.УстановитьДействие("ПриИзменении", "Подключаемый_ПриИзмененииРеквизита");

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

Подведем итог: программное добавление реквизитов — это мощный инструмент для кастомизации типовых решений. Главное — помнить о разделении контекстов формы и объекта, использовать расширения для сохранения возможности легкого обновления и не забывать про механизмы сохранения данных, так как реквизиты формы эфемерны по своей природе.

← На главную