Как проверить программно добавленный реквизит табличной части при проведении документа

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

В практике разработки на платформе 1С:Предприятие 8.3 (Управляемые формы) часто возникает ситуация, когда необходимо расширить функционал формы документа, не внося изменений в структуру метаданных. Мы добавляем программные реквизиты в процедуре ПриСозданииНаСервере, размещаем их в табличной части на форме, и пользователь успешно с ними работает. Однако при попытке обратиться к этим данным в модуле объекта (например, в процедуре ОбработкаПроведения) мы обнаруживаем, что этих данных там просто не существует.

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

Почему модуль объекта «не видит» программные реквизиты формы

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

Когда мы нажимаем кнопку «Провести», на сервер передается Объект (тип ДанныеФормыСтруктура), который затем преобразуется в ДокументОбъект. В этот момент все программные добавки, существующие только на форме, отсекаются. Модуль объекта работает только с тем, что определено в метаданных конфигурации.

Решение 1: Использование механизма ДополнительныеСвойства

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

Шаг 1. Подготовка данных в модуле формы

В модуле формы в обработчике ПередЗаписьюНаСервере нам нужно собрать значения из программных реквизитов и «упаковать» их в объект. Поскольку нам нужно передать данные по каждой строке табличной части, лучше всего использовать Таблицу Значений.


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    
    // Создаем таблицу значений для передачи данных
    ТЗ_ПрограммныеДанные = Новый ТаблицаЗначений;
    ТЗ_ПрограммныеДанные.Колонки.Добавить("НомерСтроки", Новый ОписаниеТипов("Число"));
    ТЗ_ПрограммныеДанные.Колонки.Добавить("СпецРежим", Новый ОписаниеТипов("Булево"));
    
    // Заполняем таблицу данными из программных реквизитов формы
    Для Каждого СтрокаТЧ Из Объект.Товары Цикл
        НоваяСтрока = ТЗ_ПрограммныеДанные.Добавить();
        НоваяСтрока.НомерСтроки = СтрокаТЧ.НомерСтроки;
        // Предположим, что "СпецРежим" - это программный реквизит формы, привязанный к строке
        НоваяСтрока.СпецРежим = СтрокаТЧ.СпецРежим; 
    КонецЦикла;
    
    // Помещаем таблицу в ДополнительныеСвойства объекта
    ТекущийОбъект.ДополнительныеСвойства.Вставить("ТаблицаПрограммныхРеквизитов", ТЗ_ПрограммныеДанные);
    
КонецПроцедуры

Шаг 2. Обработка данных в модуле объекта

Теперь в модуле документа в процедуре ОбработкаПроведения мы можем извлечь эту таблицу и использовать её для принятия решения о том, в какой регистр делать запись.


Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    
    // Проверяем наличие наших данных в ДополнительныхСвойствах
    Если ЭтотОбъект.ДополнительныеСвойства.Свойство("ТаблицаПрограммныхРеквизитов") Тогда
        ТЗ_Данные = ЭтотОбъект.ДополнительныеСвойства.ТаблицаПрограммныхРеквизитов;
        
        Для Каждого СтрокаТовары Из Товары Цикл
            // Ищем соответствующие данные по номеру строки
            ПараметрыПоиска = Новый Структура("НомерСтроки", СтрокаТовары.НомерСтроки);
            НайденныеСтроки = ТЗ_Данные.НайтиСтроки(ПараметрыПоиска);
            
            Если НайденныеСтроки.Количество() > 0 Тогда
                Если НайденныеСтроки[0].СпецРежим Тогда
                    // Логика записи в Регистр №1
                Иначе
                    // Логика записи в Регистр №2
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
    Иначе
        // Если данных нет (например, при программном проведении),
        // нужно предусмотреть логику по умолчанию или выдать ошибку
    КонецЕсли;
    
КонецПроцедуры

Решение 2: Использование Идентификатора строки для надежности

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

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

Решение 3: БСП и «Дополнительные реквизиты»

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

  1. Сохранение в БД: Данные не пропадают после закрытия формы.
  2. Доступность везде: Они видны и в форме, и в модуле объекта, и в отчетах.
  3. Отсутствие кодинга метаданных: Вам не нужно менять структуру таблиц в конфигураторе.

В модуле объекта данные БСП можно получить с помощью программного интерфейса библиотеки, например, вызвав функцию УправлениеСвойствами.ЗначениеСвойства().

Критически важный момент: Риски групповой обработки

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

Как этого избежать:

Подведение итогов

Мы рассмотрели основной способ решения проблемы — передачу данных через ДополнительныеСвойства. Посмотрим на алгоритм действий еще раз:

  1. На форме формируем Таблицу Значений или Структуру с данными программных полей.
  2. В обработчике ПередЗаписьюНаСервере передаем эту коллекцию в ТекущийОбъект.ДополнительныеСвойства.
  3. В модуле объекта в процедуре ОбработкаПроведения проверяем наличие ключа в свойствах и выполняем нужную логику.

Этот метод позволяет сохранить «чистоту» метаданных и при этом обеспечить гибкость бизнес-логики в зависимости от действий пользователя на форме.

← На главную