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

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

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

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

Способ 1. Передача через массив структур в параметрах формы

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

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

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

Посмотрим на пример кода в модуле формы документа-источника:


&НаКлиенте
Процедура ОткрытьОбработкуПереноса(Команда)

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

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

Теперь рассмотрим, как обработать полученные данные в форме обработки в событии ПриСозданииНаСервере:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

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

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

Важная особенность метода ЗаполнитьЗначенияСвойств

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

Если в документе реквизит называется КоличествоУпаковок, а в табличной части обработки — КоличествоЦенников, автоматическое заполнение не сработает, если вы вызовете ЗаполнитьЗначенияСвойств напрямую из строки документа в структуру. Чтобы данные перенеслись корректно, необходимо явно указать соответствие полей при заполнении структуры либо выполнить явное присваивание:


НоваяСтрока = Объект.Товары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, Элемент);
// Если имена колонок не совпадали, дозаполняем поле вручную:
НоваяСтрока.КоличествоЦенников = Элемент.КоличествоУпаковок;

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

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

Разберем по шагам данный подход:

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

Посмотрим на пример реализации в форме документа:


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

&НаКлиенте
Процедура ОткрытьОбработкуЧерезХранилище(Команда)
    
    АдресВХранилище = ПоместитьТаблицуВХранилище();
    
    ПараметрыФормы = Новый Структура("АдресДанных", АдресВХранилище);
    ОткрытьФорму("Обработка.ПечатьЭтикетокИЦенников.Форма.ФормаТовары", ПараметрыФормы, ЭтаФорма);
    
КонецПроцедуры

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    Если Параметры.Свойство("АдресДанных") И ЭтоАдресВременногоХранилища(Параметры.АдресДанных) Тогда
        ТаблицаДанных = ПолучитьИзВременногоХранилища(Параметры.АдресДанных);
        Объект.Товары.Загрузить(ТаблицаДанных);
    КонецЕсли;

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

Способ 3. Использование механизма ОбработкаЗаполнения (для записанных документов)

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

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


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

В модуле объекта обработки (не формы) описываем стандартную процедуру ОбработкаЗаполнения:


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    
    Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.Лист") Тогда
        
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |	Товары.Номенклатура КАК Номенклатура,
            |	Товары.КоличествоУпаковок КАК КоличествоЦенников
            |ИЗ
            |	Документ.Лист.Товары КАК Товары
            |ГДЕ
            |	Товары.Ссылка = &Ссылка";
            
        Запрос.УстановитьПараметр("Ссылка", ДанныеЗаполнения);
        
        ЭтотОбъект.Товары.Загрузить(Запрос.Выполнить().Выгрузить());
        
    КонецЕсли;
    
КонецПроцедуры

При таком подходе платформа 1С автоматически вызовет событие заполнения при создании основного реквизита Объект формы обработки, что избавит от необходимости писать дополнительный код в обработчиках формы.

← На главную