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

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

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

Способ 1. Использование реквизита типа ТабличныйДокумент

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

Разберем алгоритм действий по шагам:

  1. Создадим в объекте отчета реквизит ДанныеФайла с типом ТабличныйДокумент.
  2. В модуле формы после прочтения файла заполним этот реквизит.
  3. В модуле объекта в процедуре ПриКомпоновкеРезультата преобразуем его обратно в таблицу значений.

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


&НаСервере
Процедура ЗагрузитьФайлНаСервере(ПутьКФайлу)
    // Читаем файл в реквизит объекта (Табличный документ)
    Отчет.ДанныеФайла.Прочитать(ПутьКФайлу);
    Сообщить("Данные успешно загружены в объект отчета.");
КонецПроцедуры

Теперь выясним, как обработать эти данные в модуле объекта. Мы будем использовать ПостроительЗапроса, который позволяет быстро выгрузить содержимое области табличного документа в ТаблицуЗначений.


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

Способ 2. Использование Менеджера временных таблиц

Если ваша задача требует соединения внешних данных с таблицами информационной базы в запросе СКД, лучшим решением будет использование МенеджераВременныхТаблиц. Рассмотрим, как пробросить таблицу из модуля объекта в основной запрос компоновки.

Проанализируем пример кода в модуле объекта. Здесь мы создаем временную таблицу ВнешняяВТ, которая станет доступна внутри схемы компоновки данных:


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

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

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

После этого в тексте запроса самой СКД вы можете обращаться к ВнешняяВТ так же, как к любой другой таблице базы данных. Например: ЛЕВОЕ СОЕДИНЕНИЕ ВнешняяВТ КАК ВТ ПО Товары.Номенклатура = ВТ.Номенклатура.

Способ 3. Передача через Временное хранилище (рекомендуемый метод)

Рассмотрим наиболее современный и "чистый" метод, который позволяет избежать создания лишних реквизитов в метаданных отчета. Мы будем использовать АдресВременногоХранилища.

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


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

В модуле объекта (процедура ПриКомпоновкеРезультата) мы извлекаем таблицу по сохраненному адресу:


Если ЭтоАдресВременногоХранилища(АдресДанных) Тогда
    ТЗ = ПолучитьИзВременногоХранилища(АдресДанных);
    // Теперь ТЗ можно использовать в СКД
КонецЕсли;

Важно: При использовании этого метода помните, что если отчет формируется в фоновом задании (стандартное поведение для многих конфигураций на базе БСП), временное хранилище формы будет недоступно в сеансе фонового задания. В таких случаях адрес хранилища нужно передавать специальным образом через параметры фонового задания или использовать реквизиты объекта, которые сериализуются (например, ТабличнаяЧасть).

Способ 4. Использование Внешних наборов данных СКД

Если вам не нужно соединять таблицу со сложными запросами к БД, а нужно просто вывести её структуру средствами СКД, воспользуйтесь Набором данных - объект. Разберем, как это работает.

  1. В Схеме компоновки данных добавьте новый "Набор данных - объект".
  2. Укажите имя объекта, например, МояВнешняяТаблица.
  3. Добавьте поля с именами, соответствующими колонкам вашей ТаблицыЗначений.

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


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

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

Типичные ошибки при работе с внешними таблицами

Проанализируем ситуации, которые могут привести к ошибкам или пустому результату:

Выбор конкретного метода зависит от архитектуры вашего отчета. Для простых отчетов на основе Excel-файлов отлично подходит ТабличныйДокумент. Для сложных аналитических отчетов с объединением данных — МенеджерВременныхТаблиц. А для вывода уже готовых расчетов — Внешние наборы данных.

← На главную