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

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

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

Метод 1: Копирование стандартных форм в состав внешнего отчета

Самый простой и быстрый способ, к которому пришел автор темы, — это использование стандартных форм из библиотеки конфигурации в качестве шаблона. Это позволяет сохранить привычный интерфейс «Варианты», «Настройки», «Сформировать», но при этом дает свободу действий для модификации.

Разберем этот процесс по шагам:

  1. Откроем дерево конфигурации и найдем раздел Общие формы.
  2. Найдем формы с именами ФормаОтчета и ФормаНастроекОтчета (в различных конфигурациях, например, на базе БСП, они могут называться немного иначе).
  3. Скопируем эти формы в свой внешний отчет.
  4. В свойствах внешнего отчета на закладке Основные укажем скопированные формы как основную форму отчета и основную форму настроек.
  5. Теперь проанализируем структуру формы отчета. В реквизиты формы добавим новый реквизит с типом ТаблицаЗначений. Обязательно опишем колонки (например, Номенклатура, Количество).
  6. Перетащим этот реквизит на форму, создав элемент управления типа Поле таблицы.

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

Метод 2: Программное добавление элементов формы

Если мы хотим избежать копирования целых форм (чтобы отчет не «растолстел» и не возникло конфликтов при обновлении БСП), мы можем внедрить таблицу программно. Проанализируем, как это сделать в обработчике ПриСозданииНаСервере формы отчета.

Рассмотрим пример кода для динамического создания таблицы:


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

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

Интеграция данных в схему СКД через набор данных «Объект»

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

В схеме компоновки данных выполним следующие действия:

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

Теперь самое важное — программная сборка отчета. Нам нужно перехватить момент формирования и передать таблицу. Для этого в модуле объекта внешнего отчета используем процедуру ПриКомпоновкеРезультата.


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

Сохранение данных между сеансами

Одной из проблем, упомянутых в обсуждении, является сохранение введенных данных. Пользователь не захочет заполнять таблицу заново при каждом открытии отчета. Поскольку ТаблицаЗначений не может быть стандартным параметром, рассмотрим вариант использования типа ХранилищеЗначения.

Проанализируем алгоритм сохранения:

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

Если структура таблицы простая, можно воспользоваться альтернативным методом: сериализовать ТЗ в строку формата JSON или XML и хранить её в обычном строковом параметре СКД. Это позволит данным сохраняться в стандартных механизмах «Сохранить настройки» без написания сложного кода по управлению хранилищем.


// Пример сериализации ТЗ в JSON для хранения в параметре
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ТЗ_Пользователя);
СтрокаДляХранения = ЗаписьJSON.Закрыть();
// Записываем СтрокаДляХранения в параметр СКД

Особенности работы в веб-клиенте

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

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

← На главную