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