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