В процессе разработки периодически возникает задача программно получить данные из уже существующего в конфигурации отчета (или внешнего отчета) для их последующей обработки в коде. Стандартный механизм Системы компоновки данных (СКД) позволяет выводить результат не только в привычный табличный документ, но и во внутренние коллекции, такие как ТаблицаЗначений или ДеревоЗначений. Однако при попытке сделать это напрямую разработчики часто сталкиваются с ошибками платформы.
В этой статье мы подробно разберем по шагам, почему возникает популярная ошибка «Не поддерживается вывод таблиц и диаграмм в универсальную коллекцию значений», как её правильно исправить программным путем, а также как корректно получить объект внешнего отчета из справочника БСП «Дополнительные отчеты и обработки».
Рассмотрим типовой сценарий. Разработчик пытается инициализировать отчет, загрузить настройки одного из вариантов и выполнить компоновку с использованием объекта ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений. Код выглядит следующим образом:
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(ОтчетСостояниеШтатногоРасписания.СхемаКомпоновкиДанных, НастройкиОтчета,,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
При выполнении этого фрагмента система аварийно завершает работу с сообщением об ошибке компоновки макета. Проанализируем причину такого поведения платформы.
Процессор вывода СКД при использовании генератора макета для коллекции значений имеет жесткое ограничение. Он не умеет обрабатывать сложные структуры настроек, к которым относятся:
В большинстве штатных отчетов (например, в отчете «Состояние штатного расписания») структура настроек по умолчанию спроектирована именно в виде кросс-таблицы или содержит диаграммы для визуализации. Чтобы успешно выгрузить данные такого отчета в плоскую ТаблицуЗначений, структуру его настроек необходимо программно изменить — «выпрямить», превратив в список или детальные записи.
Разберем, как подготовить настройки отчета перед формированием макета компоновки. Нам нужно полностью очистить текущую структуру настроек и добавить туда одну простую группировку — детальные записи (без указания конкретных полей группировки).
Добавим в процедуру обработки отчета следующий блок кода:
// 1. Очищаем существующую структуру (удаляем таблицы, диаграммы и сложные иерархические группировки)
НастройкиОтчета.Структура.Очистить();
// 2. Создаем новую плоскую группировку (детальные записи)
ГруппировкаДетальныеЗаписи = НастройкиОтчета.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
ГруппировкаДетальныеЗаписи.Использование = Истина;
// 3. Настраиваем автовыбор полей и автопорядок для новой группировки
ВыбранноеПоле = ГруппировкаДетальныеЗаписи.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Использование = Истина;
ПорядокГруппировки = ГруппировкаДетальныеЗаписи.Порядок.Элементы.Добавить(Тип("АвтоЭлементПорядкаКомпоновкиДанных"));
ПорядокГруппировки.Использование = Истина;
Важные нюансы, которые следует учитывать при выгрузке в таблицу значений:
Если нужный нам отчет зарегистрирован в базе данных как дополнительный (внешний) в справочнике «Дополнительные отчеты и обработки» Библиотеки Стандартных Подсистем (БСП), нам не требуется вручную сохранять его файл на диск и подключать через метод ВнешниеОтчеты.Подключить().
В БСП предусмотрен готовый программный интерфейс, позволяющий быстро получить полноценный объект внешнего отчета на сервере по его ссылке:
// Получаем ссылку на элемент справочника дополнительных отчетов
СсылкаНаДопОтчет = Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию("Состояние штатного расписания");
Если ЗначениеЗаполнено(СсылкаНаДопОтчет) Тогда
// Получаем готовый объект внешнего отчета средствами БСП (выполняется строго НА СЕРВЕРЕ)
ОтчетОбъект = ДополнительныеОтчетыИОбработки.ОбъектВнешнейОбработки(СсылкаНаДопОтчет);
КонецЕсли;
Полученный таким образом ОтчетОбъект является экземпляром класса ВнешнийОтчетОбъект. У него доступны все стандартные свойства (включая свойство СхемаКомпоновкиДанных), а также любые экспортные методы и переменные, которые были объявлены в модуле этого внешнего отчета.
Теперь объединим все полученные знания в одну рабочую процедуру. Напишем код, который находит внешний отчет, устанавливает параметр даты, перестраивает его структуру в «детальные записи» и выгружает итоговые данные в ТаблицуЗначений.
Процедура ПолучитьДанныеОтчетаВТаблицу() Экспорт
// Шаг 1. Получаем объект внешнего отчета из дополнительных отчетов БСП
СсылкаНаДопОтчет = Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию("Состояние штатного расписания");
Если Не ЗначениеЗаполнено(СсылкаНаДопОтчет) Тогда
ВызватьИсключение "Не найден дополнительный отчет 'Состояние штатного расписания'!";
КонецЕсли;
// Получаем объект внешнего отчета на сервере
ОтчетОбъект = ДополнительныеОтчетыИОбработки.ОбъектВнешнейОбработки(СсылкаНаДопОтчет);
// Шаг 2. Загружаем настройки выбранного варианта
ВариантНастроек = ОтчетОбъект.СхемаКомпоновкиДанных.ВариантыНастроек.ЗаполненностьШтатногоРасписания;
ОтчетОбъект.КомпоновщикНастроек.ЗагрузитьНастройки(ВариантНастроек.Настройки);
НастройкиОтчета = ОтчетОбъект.КомпоновщикНастроек.ПолучитьНастройки();
// Шаг 3. Заполняем параметры данных
ПараметрДата = НастройкиОтчета.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("ДатаАктуальности"));
Если ПараметрДата <> Неопределено Тогда
ПараметрДата.Значение = ТекущаяДата();
ПараметрДата.Использование = Истина;
КонецЕсли;
// Шаг 4. Преобразуем структуру отчета в детальные записи
НастройкиОтчета.Структура.Очистить();
ГруппировкаДетальныеЗаписи = НастройкиОтчета.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
ГруппировкаДетальныеЗаписи.Использование = Истина;
ВыбранноеПоле = ГруппировкаДетальныеЗаписи.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Использование = Истина;
ПорядокГруппировки = ГруппировкаДетальныеЗаписи.Порядок.Элементы.Добавить(Тип("АвтоЭлементПорядкаКомпоновкиДанных"));
ПорядокГруппировки.Использование = Истина;
// Шаг 5. Компонуем макет для коллекции значений
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(
ОтчетОбъект.SхемаКомпоновкиДанных,
НастройкиОтчета,
,
,
Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений")
);
// Инициализируем процессор компоновки
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , , Истина);
// Выводим результат компоновки в Таблицу Значений
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
РезультатТаблица = Новый ТаблицаЗначений;
ПроцессорВывода.УстановитьОбъект(РезультатТаблица);
ПроцессорВывода.Вывести(ПроцессорКомпоновки, Истина);
// Теперь переменная 'РезультатТаблица' содержит плоскую таблицу с данными отчета
ЗначениеВРеквизитФормы(РезультатТаблица, "ТаблицаРезультатНаФорме");
КонецПроцедуры
Используя предложенный алгоритм, вы сможете извлекать данные из любых сложных аналитических отчетов конфигурации без необходимости дублировать их логику (запросы, временные таблицы, связи) в коде своих обработок.