Как вывести данные отчета в две параллельные колонки в 1С

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

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

Почему не подходит метод ВставитьОбласть()

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

  1. Метод требует обязательного указания параметра смещения — ТипСмещенияТабличногоДокумента.ПоВертикали или ТипСмещенияТабличногоДокумента.ПоГоризонтали.
  2. Если мы пробуем вставлять ячейки справа со смещением по горизонтали, ранее сформированные правые области таблицы неконтролируемо сдвигаются дальше вправо.
  3. Смещение по вертикали приводит к разрыву и смещению строк в уже выведенных левых колонках, разрушая общую сетку макета.

Метод ВставитьОбласть() служит для точечной вставки блоков в уже сформированный документ, а не для поточного заполнения параллельных списков.

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

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

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

Рассмотрим пример кода:


// Предположим, что ТаблицаГруппа1 и ТаблицаГруппа2 уже получены из запроса
МаксКоличествоСтрок = Макс(ТаблицаГруппа1.Количество(), ТаблицаГруппа2.Количество());

ОбластьСтрока = Макет.ПолучитьОбласть("СтрокаДанных");

Для Индекс = 0 По МаксКоличествоСтрок - 1 Цикл
    // Заполняем левую колонку
    Если Индекс < ТаблицаГруппа1.Количество() Тогда
        Строка1 = ТаблицаГруппа1[Индекс];
        ОбластьСтрока.Параметры.Товар1 = Строка1.Номенклатура;
        ОбластьСтрока.Параметры.Количество1 = Строка1.Количество;
    Иначе
        ОбластьСтрока.Параметры.Товар1 = "";
        ОбластьСтрока.Параметры.Количество1 = 0;
    КонецЕсли;

    // Заполняем правую колонку
    Если Индекс < ТаблицаГруппа2.Количество() Тогда
        Строка2 = ТаблицаГруппа2[Индекс];
        ОбластьСтрока.Параметры.Товар2 = Строка2.Номенклатура;
        ОбластьСтрока.Параметры.Количество2 = Строка2.Количество;
    Иначе
        ОбластьСтрока.Параметры.Товар2 = "";
        ОбластьСтрока.Параметры.Количество2 = 0;
    КонецЕсли;

    ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;

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

Способ 2. Использование метода Присоединить()

Если структура макета требует раздельных областей колонок (например, КолонкаЛевая и КолонкаПравая), вместо метода Вывести() для второй части используется Присоединить().

Разберем логику работы табличного документа:

  1. Метод ТабличныйДокумент.Вывести() всегда начинает вывод данных с новой строки.
  2. Метод ТабличныйДокумент.Присоединить() выводит область в текущей строке справа от последней заполненной ячейки.

Посмотрим на пример заполнения:


ОбластьЛевая = Макет.ПолучитьОбласть("КолонкаЛевая");
ОбластьПравая = Макет.ПолучитьОбласть("КолонкаПравая");

Для Индекс = 0 По МаксКоличествоСтрок - 1 Цикл
    // Заполняем параметры левой части
    Если Индекс < ТаблицаГруппа1.Количество() Тогда
        ОбластьЛевая.Параметры.Заполнить(ТаблицаГруппа1[Индекс]);
    Иначе
        ОбластьЛевая.Параметры.Очистить();
    КонецЕсли;
    ТабДок.Вывести(ОбластьЛевая);

    // Присоединяем правую часть к текущей строке
    Если Индекс < ТаблицаГруппа2.Количество() Тогда
        ОбластьПравая.Параметры.Заполнить(ТаблицаГруппа2[Индекс]);
    Иначе
        ОбластьПравая.Параметры.Очистить();
    КонецЕсли;
    ТабДок.Присоединить(ОбластьПравая);
КонецЦикла;

Способ 3. Реализация параллельного вывода в СКД

В схеме компоновки данных часто предлагают использовать конструкцию с разделением колонок через условие:


ВЫБОР 
    КОГДА Номенклатура.Родитель = &Группа1 ТОГДА Количество 
    ИНАЧЕ 0 
КОНЕЦ КАК КоличествоГруппа1,
ВЫБОР 
    КОГДА Номенклатура.Родитель = &Группа2 ТОГДА Количество 
    ИНАЧЕ 0 
КОНЕЦ КАК КоличествоГруппа2

Внимание: подводный камень СКД! Если просто сгруппировать отчет по полю Номенклатура, параллельного вывода не получится. Каждая позиция принадлежит строго одной группе, поэтому строки выстроятся так называемой «лесенкой»: сначала пойдут товары первой группы с пустыми значениями справа, а затем ниже — товары второй группы с пустыми значениями слева.

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

  1. Формируем временную таблицу для первой группы и вычисляем порядковый номер строки (от 1 до N).
  2. Формируем аналогичную временную таблицу с порядковыми номерами для второй группы.
  3. Объединяем обе таблицы через ПОЛНОЕ СОЕДИНЕНИЕ по равенству вычисленного номера строки.

Тогда СКД воспримет строки с одинаковым порядковым номером как единую запись и выведет товары обеих групп на одном уровне.

Ограничение свойства КоличествоКолонок

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

← На главную