Как программно добавить динамические колонки в отчет 1С без использования СКД?

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

При работе со старыми конфигурациями или специфическими задачами часто возникает необходимость доработки отчетов, построенных на классическом выводе в макет (без использования Системы компоновки данных). Одной из наиболее сложных задач в этом случае является создание динамических колонок, количество которых заранее неизвестно — например, вывод сумм платежей в разрезе месяцев года. Разберем подробно, как реализовать такой механизм программно.

Принцип построения кросс-отчета в 1С

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

Проанализируем алгоритм работы: сначала мы выводим фиксированную левую часть шапки (например, "Номенклатура" или "Контрагент") методом Вывести(), а затем в цикле по количеству месяцев используем Присоединить(), чтобы достроить шапку вправо.

Шаг 1: Подготовка макета

Прежде всего, нам нужно правильно подготовить макет в конфигураторе. Разберем структуру областей:

  1. Создадим горизонтальную область для шапки (назовем ее ШапкаВерх).
  2. Внутри этой области (или отдельно) выделим вертикальную область для динамической колонки (назовем ее КолонкаПериод).
  3. Аналогично поступим со строками: создадим горизонтальную область Строка и вертикальную область ЯчейкаСуммы, которая находится на пересечении строки и динамической колонки.

В ячейках области КолонкаПериод установим параметр МесяцГод, а в ЯчейкаСуммы — параметр СуммаПлатежа.

Шаг 2: Получение и форматирование данных

Чтобы отчет выглядел профессионально, нам нужно преобразовать стандартную дату 1С в читаемый формат месяца. Посмотрим на пример кода, который обсуждался в теме:


// Пример формирования строки месяца
ДатаПлатежа = Выборка.Дата;
МесяцСтрокой = Формат(ДатаПлатежа, "ДФ='MMMM (yyyy)'"); 
// Результат: "Март (2020)"

Выясним причину, по которой у автора темы данные "уходили в разнос". Это происходит из-за отсутствия синхронизации. Если у одного контрагента есть платеж в марте, а у другого нет, то при простом переборе выборки колонки сместятся. Чтобы этого избежать, сначала подготовим массив всех уникальных периодов, которые будут в отчете.


// Сначала соберем все уникальные месяцы из данных запроса
ТаблицаПериодов = Запрос.Выполнить().Выгрузить();
ТаблицаПериодов.Свернуть("ПериодМесяц"); // ПериодМесяц должен быть началом месяца
ТаблицаПериодов.Сортировать("ПериодМесяц Возр");

Шаг 3: Программный вывод шапки и данных

Рассмотрим по шагам процесс сборки таблицы в коде. Сначала выводим шапку:


// Выводим статичную часть шапки
ОбластьШапкаЛево = Макет.ПолучитьОбласть("Шапка|ЛеваяЧасть");
ТабДок.Вывести(ОбластьШапкаЛево);

// Присоединяем динамические колонки в шапку
ОбластьКолонка = Макет.ПолучитьОбласть("Шапка|КолонкаПериод");
Для Каждого СтрокаПериода Из ТаблицаПериодов Цикл
    ОбластьКолонка.Параметры.МесяцГод = Формат(СтрокаПериода.ПериодМесяц, "ДФ='MMMM (yyyy)'");
    ТабДок.Присоединить(ОбластьКолонка);
КонецЦикла;

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


Пока ВыборкаКонтрагенты.Следующий() Цикл
    // Выводим начало строки (ФИО или Название)
    ОбластьСтрокаЛево = Макет.ПолучитьОбласть("Строка|ЛеваяЧасть");
    ОбластьСтрокаЛево.Параметры.Заполнить(ВыборкаКонтрагенты);
    ТабДок.Вывести(ОбластьСтрокаЛево);
    
    // Выводим суммы по каждому месяцу
    ОбластьЯчейка = Макет.ПолучитьОбласть("Строка|ЯчейкаСуммы");
    Для Каждого СтрокаПериода Из ТаблицаПериодов Цикл
        // Ищем сумму по конкретному контрагенту за конкретный месяц
        ПараметрыОтбора = Новый Структура("Контрагент, ПериодМесяц", ВыборкаКонтрагенты.Контрагент, СтрокаПериода.ПериодМесяц);
        СтрокиДанных = ТЗРезультат.НайтиСтроки(ПараметрыОтбора);
        
        Если СтрокиДанных.Количество() > 0 Тогда
            ОбластьЯчейка.Параметры.СуммаПлатежа = СтрокиДанных[0].Сумма;
        Иначе
            ОбластьЯчейка.Параметры.СуммаПлатежа = 0; // Обязательно заполняем нулем для красоты
        КонецЕсли;
        
        ТабДок.Присоединить(ОбластьЯчейка);
    КонецЦикла;
КонецЦикла;

Полезные советы по оформлению

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

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

← На главную