Как вывести данные запроса в виде кросс-таблицы с динамическими колонками на форму в 1С?

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

При построении аналитических отчетов и обработок часто возникает задача вывести линейный список данных в виде матрицы или шахматки (кросс-таблицы). На практике это означает, что в строках матрицы должны располагаться ключевые объекты (например, клиенты или сотрудники), в колонках — динамический перечень показателей, а в ячейках на пересечении — их значения.

Рассмотрим основные способы решения этой задачи в платформе 1С, выясним технические ограничения системы компоновки данных (СКД) и разберем примеры программного формирования элементов формы.

Способ 1. Выгрузка из СКД в коллекцию значений и ее ограничения

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


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

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

Способ 2. Программное создание динамических колонок на Управляемой форме

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

Попытка вызвать метод Элементы.Добавить() без предварительного изменения структуры реквизитов формы приведет к ошибке: Недопустимое значение параметра (параметр номер '1').

Проанализируем правильный двухуровневый алгоритм создания колонок на сервере:

  1. Добавление реквизитов в данные формы: через метод ИзменитьРеквизиты() создаются новые поля для объекта формы.
  2. Создание визуальных элементов: вызывается метод Элементы.Добавить() с указанием вида элемента ВидПоляФормы.ПолеВвода и пути к данным.

Разберем пример кода добавления динамических колонок на управляемой форме:


// Шаг 1. Формируем массив новых реквизитов формы
МассивДобавляемыхРеквизитов = Новый Массив;

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

// Регистрируем новые реквизиты в контексте формы
ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);

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

При повторном переформировании таблицы не забудьте удалить ранее созданные элементы через Элементы.Удалить() и очистить реквизиты через второй параметр метода ИзменитьРеквизиты().

Способ 3. Использование объекта СводнаяТаблица в Табличном документе

Если основной задачей является отображение кросс-таблицы с автоматическими итогами без необходимости сложного программного редактирования каждой ячейки, удобным решением выступает объект СводнаяТаблица, размещенный в ПолеТабличногоДокумента.

Для этого в запросе формируются итоги по группировкам строк и колонок, после чего результат передается в источник данных сводной таблицы:


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

Запрос.УстановитьПараметр("Д1", НачалоДня(Дата1));
Запрос.УстановитьПараметр("Д2", КонецДня(Дата2));

Результат = Запрос.Выполнить();

// ПолеТабДок - элемент формы с типом ПолеТабличногоДокумента
СводТаб = ЭлементыФормы.ПолеТабДок.ВстроенныеТаблицы.Добавить(Тип("СводнаяТаблица"));
СводТаб.ИсточникДанных = Результат;

Данный подход позволяет встроенными средствами платформы получить полноценную интерактивную шахматку с возможностью сворачивания и группировки данных пользователем.

Способ 4. Разворачивание матрицы на уровне текста Запроса

Если перечень показателей известeн заранее или его можно динамически сформировать перед выполнением запроса, разворот из строк в колонки выгодно выполнять прямо в тексте запроса через условное агрегирование:


ВЫБРАТЬ
    Продажи.Клиент КАК Клиент,
    СУММА(ВЫБОР КОГДА Продажи.Показатель = &Показатель1 ТОГДА Продажи.Значение ИНАЧЕ 0 КОНЕЦ) КАК Выручка,
    СУММА(ВЫБОР КОГДА Продажи.Показатель = &Показатель2 ТОГДА Продажи.Значение ИНАЧЕ 0 КОНЕЦ) КАК Количество
ИЗ
    РегистрНакопления.Продажи КАК Продажи
СГРУППИРОВАТЬ ПО
    Продажи.Клиент

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

← На главную