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

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

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

Проанализируем основные ограничения, с которыми мы сталкиваемся. Объект УправляемаяФорма существует исключительно в клиентском пространстве и не поддерживает сериализацию. Следовательно, мы не можем передать саму форму в качестве параметра в серверную процедуру нашей внешней обработки, чтобы заполнить ее там. Разберем несколько способов, как обойти это ограничение и добиться нужного результата.

Способ 1: Заполнение ячеек непосредственно на клиенте

Зачастую разработчики ошибочно полагают, что с табличным документом вообще нельзя работать на стороне клиента. На самом деле, ограничения клиента касаются преимущественно получения макетов (метод ПолучитьМакет() работает только на сервере) и вывода областей из макета в документ.

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

Способ 2: Передача табличного документа в серверную процедуру

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


&НаКлиенте
Процедура ЗаполнитьШтатнуюОбработку()
    
    // Получаем форму нужной нам обработки
    ф = ПолучитьФорму("Обработка.ЗагрузкаДанныхИзВнешнихФайлов.Форма.Форма",
        ПараметрыФормы,
        ВладелецФормы,
        УникальныйИдентификатор);
        
    // Передаем табличный документ на сервер
    ЗаполнитьТД(ф.ТабличныйДокумент);
    
    ф.Открыть();
    
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьТД(т)
    // В параметре "т" мы получаем табличный документ
    оАртикул_л = т.Область("Артикул").Лево;
    оКоличество_л = т.Область("Количество").Лево;
    оЦена_л = т.Область("Цена").Лево;
    
    i = 1;
    Для каждого стр Из Табл Цикл
        i = i + 1;
        т.Область(i, оАртикул_л, i, оАртикул_л).Текст = стр.Артикул;
        т.Область(i, оКоличество_л, i, оКоличество_л).Текст = стр.Количество;
        т.Область(i, оЦена_л, i, оЦена_л).Текст = стр.Цена;
    КонецЦикла;
    
КонецПроцедуры

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

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

Способ 3: Формирование нового документа на сервере и метод Вывести()

Чтобы избежать двойной передачи тяжелого объекта через границу клиент-сервер, рассмотрим более оптимальный вариант. Мы можем сформировать и заполнить абсолютно новый ТабличныйДокумент внутри серверной процедуры внешней обработки, вернуть его на клиент и присвоить реквизиту полученной формы.

Так как прямое присваивание реквизиту формы на клиенте (ф.ТабличныйДокумент = НовыйТД) недоступно, используем метод Вывести():


// На клиенте после получения формы и вызова серверной функции:
НовыйТД = СформироватьДокументНаСервере();
ф.ТабличныйДокумент.Очистить();
ф.ТабличныйДокумент.Вывести(НовыйТД);

Способ 4: Использование временного хранилища

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

Способ 5: Инициализация через параметры формы

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

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

← На главную