При работе с системой компоновки данных (СКД) в 1С мы часто сталкиваемся с задачей вывода информации из различных источников. Иногда возникает потребность разместить данные из двух или более независимых (несвязанных) наборов данных в соседних колонках отчета, чтобы они отображались рядом, а не друг под другом. Рассмотрим, как решить эту проблему, используя возможности СКД и программного формирования отчетов.
Главная причина, по которой СКД не может автоматически вывести несвязанные данные в соседние колонки, заключается в том, что ей необходима логика сопоставления строк. Система не знает, какая строка из первого набора соответствует какой строке из второго набора. Если такой связи нет, данные будут выводиться последовательно, один блок за другим.
Если мы хотим отобразить данные из двух наборов бок о бок, и нас устраивает сопоставление по порядку следования строк (например, первая строка из первого набора напротив первой строки из второго, вторая напротив второй и т.д.), мы можем создать искусственную связь. Для этого нам потребуется добавить в каждый набор данных поле, которое будет содержать номер строки.
Добавление номера строки в запросы:
В запросах для каждого набора данных добавьте вычисляемое поле, которое будет присваивать уникальный порядковый номер каждой строке. Мы можем использовать для этого функцию ИНДЕКС() (если запрос к таблице базы данных и платформа поддерживает) или более универсальный подход, используя виртуальные таблицы или нумерацию во временной таблице.
Пример добавления номера строки в запрос:
ВЫБРАТЬ
...
, ВЫБОР
КОГДА Истина ТОГДА СТРОКА(НомерПоПорядку)
ИНАЧЕ 0
КОНЕЦ КАК НомерСтроки
ИЗ
(ВЫБРАТЬ
...
, РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1,1,1), ТЕКУЩАЯДАТА(), СЕКУНДА) КАК НомерПоПорядку // Пример для уникального ID, можно ИНДЕКС() для временной таблицы
ИЗ
ВашаТаблица1 КАК Таблица1
) КАК ВложенныйЗапрос1
Или, если у вас более сложный запрос, используйте временные таблицы и нумерацию:
ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Набор1
ИЗ
ВашаТаблица1;
ВЫБРАТЬ
ВТ_Набор1.*,
СТРОКА(ВТ_Набор1.Ссылка) КАК НомерСтроки // Или любая другая логика нумерации
ИЗ
ВТ_Набор1 КАК ВТ_Набор1
Проделайте аналогичные действия для второго набора данных, чтобы у него также появилось поле НомерСтроки.
Настройка связи наборов данных в СКД:
После того как в каждом наборе появится поле НомерСтроки, мы можем установить связь между этими наборами по этому полю. Перейдите во вкладку "Связи наборов данных" в схеме компоновки данных. Создайте новую связь, указав:
НомерСтрокиНомерСтрокиТаким образом, СКД будет понимать, что строки с одинаковыми номерами должны быть сопоставлены.
Настройка макета СКД: Теперь, когда связь установлена, вы можете настроить макет отчета, расположив поля из разных наборов в соседних колонках. СКД сможет корректно отобразить данные.
Важно: Этот метод корректно работает, если оба набора данных имеют одинаковое количество строк или если логика сопоставления по номеру строки соответствует вашей бизнес-задаче. Если количество строк разное, то данные могут не совпадать по смыслу, и мы получим пустые ячейки там, где нет соответствия.
Если структуры данных достаточно похожи или мы можем привести их к общему виду, мы можем рассмотреть возможность объединения двух независимых запросов в один с помощью оператора ОБЪЕДИНИТЬ ВСЕ (UNION ALL). В этом случае в выборку нужно добавить поле-признак, по которому затем можно будет различать данные первого и второго набора.
Объединение запросов:
Создайте один запрос, который объединит данные из обоих источников. Добавьте в него поле-признак, например, ТипДанных, чтобы потом отличить, откуда пришла строка.
ВЫБРАТЬ
"Набор1" КАК ТипДанных,
Поле11 КАК Поле1,
Поле12 КАК Поле2,
NULL КАК Поле21, // Заполняем NULL для полей другого набора
NULL КАК Поле22
ИЗ
ВашаТаблица1 КАК Таблица1
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"Набор2" КАК ТипДанных,
NULL КАК Поле1,
NULL КАК Поле2,
Поле21 КАК Поле21,
Поле22 КАК Поле22
ИЗ
ВашаТаблица2 КАК Таблица2
Использование поля-признака в СКД: После объединения у нас будет один набор данных. В СКД вы можете использовать условные выражения для отображения данных в разных колонках. Например, для первой колонки:
ВЫБОР КОГДА ТипДанных = "Набор1" ТОГДА Поле1 КОНЕЦ
Для второй колонки:
ВЫБОР КОГДА ТипДанных = "Набор2" ТОГДА Поле21 КОНЕЦ
Этот метод подходит, если вы хотите "свернуть" данные в одну таблицу, но при этом сохранить различие в колонках.
Для наиболее сложных случаев, когда стандартные средства СКД не позволяют достичь требуемой компоновки (например, когда количество строк в колонках может быть разным, или требуется очень специфичное позиционирование элементов), мы рекомендуем использовать программное формирование отчета. В этом случае СКД используется исключительно для получения данных, а весь процесс вывода в табличный документ мы выполняем самостоятельно в коде.
Использование СКД для получения данных:
Создаем несколько схем компоновки данных (или используем одну с разными наборами данных), чтобы получить необходимые данные. Для этого мы инициализируем объект КомпоновщикМакета, получаем макет компоновки и затем через ПроцессорКомпоновкиДанных и ПроцессорВыводаРезультатаКомпоновкиДанных выгружаем данные в объект ТаблицаЗначений или Выборка.
Программное построение табличного документа:
После получения данных мы начинаем "рисовать" отчет в объекте ТабличныйДокумент. Мы последовательно обходим полученные выборки (или таблицы значений) и заполняем ячейки табличного документа. Этот подход позволяет нам контролировать каждую ячейку и каждое расположение элементов.
ТабличныйДокумент: Новый ТабличныйДокумент.Вывести() объекта ТабличныйДокумент для вывода областей.Примерная логика может выглядеть так:
// ... Получаем данные из первого набора
ВыборкаДанных1 = ПолучитьДанныеИзСКД(СхемаСКД1);
// ... Получаем данные из второго набора
ВыборкаДанных2 = ПолучитьДанныеИзСКД(СхемаСКД2);
ТабДок = Новый ТабличныйДокумент;
// ... Настраиваем макеты областей, если нужно
// Например, получаем макет из внешней обработки или из самого отчета
// ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
// ТабДок.Вывести(ОбластьЗаголовок);
ИндексСтроки = 0;
Пока ВыборкаДанных1.Следующий() Или ВыборкаДанных2.Следующий() Цикл
ОбластьСтроки = Макет.ПолучитьОбласть("Строка"); // Область для одной строки отчета
Если ВыборкаДанных1.Следующий() Тогда
ОбластьСтроки.Параметры.Поле1_1 = ВыборкаДанных1.Поле1;
ОбластьСтроки.Параметры.Поле1_2 = ВыборкаДанных1.Поле2;
КонецЕсли;
Если ВыборкаДанных2.Следующий() Тогда
ОбластьСтроки.Параметры.Поле2_1 = ВыборкаДанных2.ПолеА;
ОбластьСтроки.Параметры.Поле2_2 = ВыборкаДанных2.ПолеБ;
КонецЕсли;
ТабДок.Вывести(ОбластьСтроки);
ИндексСтроки = ИндексСтроки + 1;
КонецЦикла;
ТабДок.Показать();
Этот подход позволяет нам полностью контролировать логику сопоставления и вывода данных, даже если наборы имеют разное количество строк. Мы можем выводить строки из одного набора, пока они есть, а для второго набора оставлять ячейки пустыми, и наоборот. Однако при этом мы теряем интерактивные возможности СКД по изменению структуры отчета пользователем.
Выбор конкретного решения зависит от сложности требуемого отчета, гибкости, которую мы хотим предоставить пользователю, и наличия логической связи между данными. Для простых случаев создания искусственной связи в СКД может быть достаточно, тогда как для сложных "бланковых" отчетов, несомненно, потребуется программное формирование.