Как в 1С вывести строки в колонки и сформировать отчет с горизонтальными группировками

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

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

Решение задачи штатными средствами СКД

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

Разберем настройки по шагам:

  1. В схеме компоновки данных на вкладке Настройки добавим элемент Таблица.
  2. В Строки таблицы добавим необходимые группировки (например, Период или Показатель).
  3. В Колонки таблицы добавим группировку Логист. Вложенной группировкой к логисту добавим поле Водитель.
  4. Перейдем на вкладку Другие настройки для группировки колонок. Установим параметр Расположение группировок в значение Горизонтально.

Если нам нужно, чтобы свойства (например, «Цвет кузова», «Модель») выводились не отдельными строками, а колонками под водителем, воспользуемся советом из обсуждения: свойства должны стать ресурсами. Это позволит СКД агрегировать их и выводить в ячейках на пересечении строк и колонок.

Программный вывод отчета через макет

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

Проанализируем алгоритм вывода:


// Создаем соответствие для группировки по логистам
СоответствиеЛогистов = Новый Соответствие; // Логист -> Количество водителей
МассивЛогистов = Новый Массив; // Для сохранения порядка логистов

// Сначала собираем структуру данных
Для каждого Строка Из Таблица Цикл
    Логист = Строка.Логист;
    Если СоответствиеЛогистов[Логист] = Неопределено Тогда
        СоответствиеЛогистов.Вставить(Логист, 1);
        МассивЛогистов.Добавить(Логист);
    Иначе
        СоответствиеЛогистов[Логист] = СоответствиеЛогистов[Логист] + 1;
    КонецЕсли;
КонецЦикла;

После подготовки структуры данных мы используем метод Присоединить() объекта ТабличныйДокумент. Важно понимать разницу: Вывести() добавляет область вниз, а Присоединить() — справа от последней выведенной области.


ТекущаяКолонка = 1;
Для каждого Строка Из Таблица Цикл
    ОбластьВодители.Параметры.Заполнить(Строка);
    // Выводим данные по горизонтали
    ТабДок.Присоединить(ОбластьВодители);
    ТекущаяКолонка = ТекущаяКолонка + 1;
КонецЦикла;

Программное объединение ячеек в шапке отчета

Одной из главных сложностей является создание «шапки» над динамическими колонками. Если у одного логиста пять водителей, его имя должно быть написано в одной объединенной ячейке над всеми пятью колонками водителей. Выясним, как это реализовать.

Используем метод Область(НомерСтроки, НомерКолонки, НомерСтроки, НомерКолонки).Объединить(). Проанализируем пример кода:


ТекущаяКолонка = НачальнаяКолонкаДанных; // Номер колонки, с которой начинается вывод данных
Для каждого Логист Из МассивЛогистов Цикл
    КоличествоВодителей = СоответствиеЛогистов[Логист];
    Если КоличествоВодителей > 1 Тогда
        // Определяем границы области для объединения
        // Предположим, заголовок логиста находится в 3-й строке
        Начало = ТекущаяКолонка;
        Конец = ТекущаяКолонка + КоличествоВодителей - 1;
        ТабДок.Область(3, Начало, 3, Конец).Объединить();
        
        // Устанавливаем текст и форматирование
        Ячейка = ТабДок.Область(3, Начало);
        Ячейка.Текст = СокрЛП(Логист);
        Ячейка.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
    Иначе
        ТабДок.Область(3, ТекущаяКолонка).Текст = СокрЛП(Логист);
    КонецЕсли;
    ТекущаяКолонка = ТекущаяКолонка + КоличествоВодителей;
КонецЦикла;

Использование параметра «ВСЕ» в выборке запроса

Рассмотрим продвинутый способ обхода результата запроса, который часто применяется при создании кросс-отчетов вручную. В методе Выбрать() объекта РезультатЗапроса существует третий параметр. Если установить его в значение "ВСЕ", система позволит получить все значения группировки, даже если для конкретной вышестоящей группировки данных нет.

Посмотрим на пример логики:


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

Использование этого метода позволяет избежать «рваных» краев в отчете, когда в одной строке данных больше, чем в другой. Однако помните, что при большом количестве данных параметр "ВСЕ" может существенно замедлить формирование отчета, так как системе приходится перебирать пустые комбинации.

Особенности оформления макета

Для корректного вывода данных важно правильно настроить макет в конфигураторе. Создадим несколько именованных областей:

Проанализируем ситуацию с цветами: чтобы отчет был читаемым, программно меняйте ЦветФона ячеек. Например, ТабДок.Область(...).ЦветФона = WebЦвета.Золотой; поможет визуально отделить одного логиста от другого. Также не забывайте устанавливать свойство АвтоМасштаб = Истина для табличного документа, так как горизонтальные отчеты часто получаются очень широкими и требуют масштабирования при печати.

← На главную