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