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

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

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

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

Почему нельзя заполнить реквизиты формы через ДокументОбъект

Проанализируем разделение контекстов данных и интерфейса в управляемом приложении:

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

Вариант 1. Автоматический расчет данных внутри формы документа (рекомендуемый подход)

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

Рассмотрим правильный алгоритм:

  1. В обработке заполняем только базовые реквизиты метаданных (Номенклатура, Количество и др.) и записываем объект.
  2. В модуле формы самого документа настраиваем автоматический расчет дополнительных колонок в процедуре ПриЧтенииНаСервере или отдельной серверной процедуре заполнения отображаемых данных.

Посмотрим на пример заполнения данных объекта в обработке:


&НаСервере
Процедура ЗаполнитьДокументНаСервере(СсылкаНаДокумент)
    ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
    
    Для Каждого СтрТЧ Из ДокументОбъект.Товары Цикл
        СтрТЧ.Количество = СтрТЧ.Количество + 1;
    КонецЦикла;
    
    ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
КонецПроцедуры

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

Вариант 2. Передача значений при программном открытии формы документа

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

Разберем по шагам, как это реализовать:

  1. В обработке подготавливаем структуру параметров, куда помещаем таблицу значений или массив структур с данными для дополнительных колонок.
  2. Открываем форму документа с помощью метода ОткрытьФорму.
  3. В модуле формы документа считываем переданные параметры и переносим их в строки табличной части формы.

Посмотрим на пример вызова формы из обработки:


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

В модуле формы документа обрабатываем полученные параметры при создании формы:


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

Вариант 3. Взаимодействие с уже открытой формой документа через оповещения

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

Рассмотрим пошаговую реализацию:

  1. В обработке на клиенте вызываем процедуру Оповестить, передавая имя события и структуру с заполненными значениями:
    
    &НаКлиенте
    Процедура ПередатьДанныеВФорму()
        ПараметрыСобытия = Новый Структура;
        ПараметрыСобытия.Вставить("ДокументСсылка", Объект.Документ);
        ПараметрыСобытия.Вставить("ДанныеКолонок", МассивЗначений);
        
        Оповестить("ОбновитьДополнительныеКолонки", ПараметрыСобытия, ЭтотОбъект);
    КонецПроцедуры
    
  2. В модуле формы документа создаем стандартный обработчик ОбработкаОповещения:
    
    &НаКлиенте
    Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
        Если ИмяСобытия = "ОбновитьДополнительныеКолонки" 
            И Параметр.ДокументСсылка = Объект.Ссылка Тогда
            
            // Обходим строки табличной части формы и заполняем реквизиты
            Для Каждого СтрТЧ Из Объект.Товары Цикл
                // Заполнение вычисляемых колонок формы
            КонецЦикла;
            
        КонецЕсли;
    КонецПроцедуры
    

Вариант 4. Добавление реквизита в метаданные или расширение

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

  1. Добавить нужный реквизит в табличную часть документа в дереве метаданных конфигурации или в расширении (без снятия конфигурации с типовой поддержки).
  2. После этого колонка станет полноценным полем объекта базы данных, и к ней можно будет свободно обращаться через ДокументОбъект.ИмяТабличнойЧасти.ИмяКолонки из любого серверного кода обработки.
← На главную