При разработке отчетов в 1С:Предприятие 8.3 часто возникает ситуация, когда структура данных заранее неизвестна. Классический пример — вывод дополнительных реквизитов номенклатуры. Поскольку пользователь может в любой момент добавить новое свойство (например, «Цвет» или «Размер»), мы не можем жестко прописать эти поля в схеме компоновки данных (СКД) на этапе проектирования в конфигураторе. В данной статье мы подробно разберем, как реализовать полностью динамический отчет, используя программное создание полей и наборов данных.
Если мы создадим обычный запрос в СКД, нам придется вручную выбирать каждое свойство из таблицы дополнительных реквизитов. Это неудобно, так как при добавлении нового свойства придется переписывать отчет. Нам же нужно, чтобы система сама анализировала состав свойств и превращала их в колонки отчета. Для этого мы проанализируем подход, основанный на программной модификации текста запроса и структуры полей СхемыКомпоновкиДанных.
Первым делом нам необходимо подготовить текст запроса, который будет «собирать» данные. Разберем логику построения такого запроса. Мы будем использовать базовую таблицу (например, справочник Номенклатура) и присоединять к ней таблицу дополнительных реквизитов столько раз, сколько у нас есть уникальных свойств.
Рассмотрим пример кода, который динамически формирует текст запроса, подставляя ЛЕВОЕ СОЕДИНЕНИЕ для каждого свойства:
ТекстЗапроса = "ВЫБРАТЬ РАЗЛИЧНЫЕ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Артикул КАК Артикул,
| 0=0
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
// Получаем список всех доступных свойств
ЗапросСвойств = Новый Запрос;
ЗапросСвойств.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ Свойство.Имя КАК Имя Из Справочник.Номенклатура.ДополнительныеРеквизиты";
Выборка = ЗапросСвойств.Выполнить().Выгрузить();
Индекс = 0;
Для каждого Стр Из Выборка Цикл
ИмяПоля = Стр.Имя;
// Заменяем заглушку 0=0 на новое поле и новую заглушку
СтрокаЗамены = "НоменклатураДоп" + Индекс + ".Значение КАК " + ИмяПоля + ", 0=0";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "0=0", СтрокаЗамены);
// Добавляем соединение
ТекстЗапроса = ТекстЗапроса + Символы.ПС +
"ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураДоп" + Индекс +
" ПО Номенклатура.Ссылка = НоменклатураДоп" + Индекс + ".Ссылка
И НоменклатураДоп" + Индекс + ".Свойство.Имя = """ + ИмяПоля + """";
Индекс = Индекс + 1;
КонецЦикла;
// Убираем лишнюю запятую и заглушку в конце
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ", 0=0", "");
В данном примере мы используем конструкцию 0=0 как маркер места, куда будут вставляться новые поля. Это позволяет избежать сложных манипуляций со строками при добавлении запятых.
После того как текст запроса сформирован, СКД «не узнает» о новых полях автоматически, если мы просто подставим текст. Нам нужно прописать эти поля в объекте НаборДанныхСхемыКомпоновкиДанных. Разберем, как это сделать в процедуре ПриКомпоновкеРезультата модуля объекта отчета.
Выясним причину, по которой это важно: если поле не описано в наборе данных схемы, компоновщик настроек не позволит пользователю выбрать это поле в настройках (в группировках или выбранных полях).
// Предположим, ТЗ — это таблица с колонками, которые мы хотим добавить в СКД
Для каждого Колонка Из ТЗ.Колонки Цикл
// Проверяем, нет ли уже такого поля в наборе данных
ПолеСКД = СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1.Поля.Найти(Колонка.Имя);
Если ПолеСКД = Неопределено Тогда
ПолеСКД = СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
ПолеСКД.ПутьКДанным = Колонка.Имя;
ПолеСКД.Поле = Колонка.Имя;
ПолеСКД.Заголовок = Колонка.Имя; // Можно задать более понятное имя
ПолеСКД.ТипЗначения = Колонка.ТипЗначения;
КонецЕсли;
КонецЦикла;
Важный нюанс: свойство ПутьКДанным должно быть уникальным идентификатором без пробелов. Если имя дополнительного реквизита содержит спецсимволы, обязательно очищайте их или заменяйте на подчеркивания при формировании ПутьКДанным, оставляя читаемое название только в свойстве Заголовок.
Просто добавить поле в схему недостаточно — оно появится в списке доступных, но не выведется в отчет автоматически. Чтобы избавить пользователя от необходимости каждый раз заходить в настройки, добавим эти поля в выбранные поля программно.
Проанализируем работу с компоновщиком настроек:
Настройки = КомпоновщикНастроек.Настройки;
Для каждого Колонка Из ТЗ.Колонки Цикл
ВыбранноеПоле = Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных(Колонка.Имя);
ВыбранноеПоле.Использование = Истина;
КонецЦикла;
Если вы решили не динамически менять текст запроса, а сначала выгрузить данные в Таблицу Значений (ТЗ), а затем передать её в СКД, схема работы немного меняется. В конфигураторе вы создаете «Набор данных - объект» и указываете ему имя (например, ВнешниеДанные).
В коде процедуры ПриКомпоновкеРезультата необходимо связать вашу ТЗ с этим именем:
ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ВнешниеДанные", Тз); // Тз — ваша сформированная таблица
ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных,
КомпоновщикНастроек.ПолучитьНастройки(), ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Рассмотрим более элегантный способ, который предоставляет платформа 1С «из коробки» без написания сложного кода по соединению таблиц. В СКД на вкладке «Наборы данных» есть кнопка «Характеристики».
Посмотрим на алгоритм настройки характеристик:
СправочникСсылка.Номенклатура).Ссылка и Свойство).После этой настройки СКД сама при выполнении запроса проанализирует все доступные дополнительные реквизиты и добавит их в список доступных полей отчета. Это наиболее производительный и правильный метод с точки зрения архитектуры 1С.
При программном формировании отчетов следует учитывать несколько критических моментов:
ОписаниеТипов. Если колонка будет иметь неопределенный тип, СКД не сможет применить к ней агрегатные функции (Сумма, Минимум и т.д.).ПриКомпоновкеРезультата устанавливать СтандартнаяОбработка = Ложь;, иначе система попытается сформировать отчет дважды — по вашей логике и по стандартной.Таким образом, мы разобрали основные способы работы с динамическими данными в СКД. Выбор между программным изменением схемы и механизмом характеристик зависит от сложности вашей задачи, но понимание того, как программно добавлять поля (объекты ПолеНабораДанныхСхемыКомпоновкиДанных), является обязательным навыком для продвинутого разработчика 1С.