При разработке отчетов в среде 1С часто возникает необходимость отойти от классического статического макета Системы компоновки данных (СКД) и реализовать более гибкие механизмы. Например, когда нужно создать универсальный реестр документов, который будет строить запрос динамически в зависимости от выбора пользователя, или когда данные сначала подготавливаются в сложном алгоритме и только потом должны быть выведены через механизм компоновки. В этой статье мы подробно разберем, как программно работать с запросами в СКД, как использовать внешние наборы данных и какие возможности предоставляют современные конфигурации.
Рассмотрим базовый вариант, который подходит в большинстве случаев, когда структура запроса известна заранее. Для реализации такого отчета выполним следующие шаги:
Этот метод является фундаментом, на котором строятся более сложные механизмы. Если же нам требуется универсальность, перейдем к программным методам.
Проанализируем ситуацию, когда текст запроса должен меняться «на лету» (например, меняется имя таблицы документа). Вместо того чтобы создавать десятки наборов данных, мы можем программно изменить свойство Запрос существующего набора.
Рассмотрим пример кода, который можно разместить в модуле объекта отчета перед его формированием:
// Получаем схему из макета
Схема = ЭтотОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
// Находим нужный набор данных по имени
НаборДанных = Схема.НаборыДанных.Найти("НаборДанных1");
// Формируем текст запроса динамически
ТекстЗапроса = "ВЫБРАТЬ * ИЗ Документ." + ИмяВыбранногоДокумента;
НаборДанных.Запрос = ТекстЗапроса;
// Важно: если состав полей меняется, нужно обновить коллекцию полей набора данных
// Для простых случаев СКД подхватит поля автоматически, если они соответствуют настройкам
При использовании этого метода крайне полезно использовать расширения языка запросов СКД. Например, конструкции {ГДЕ...} и {ВЫБРАТЬ...} позволяют СКД автоматически вставлять пользовательские отборы в ваш динамический текст, сохраняя высокую производительность на уровне СУБД.
Иногда логика получения данных настолько сложна, что её невозможно описать одним запросом (требуются расчеты в цикле, обращение к внешним API или сложная обработка строк). В этом случае мы сначала формируем ТаблицуЗначений, а затем передаем её в СКД. Выясним, как это реализовать правильно.
Шаг 1: В схеме компоновки создаем «Набор данных — объект» и указываем «Имя объекта», например, ВнешниеДанные. Добавляем в этот набор поля с именами, соответствующими колонкам нашей будущей таблицы.
Шаг 2: В модуле отчета реализуем процедуру ПриКомпоновкеРезультата:
Процедура ПриКомпоновкеРезультата(ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь; // Отключаем стандартный вывод
// 1. Формируем таблицу значений программно
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("ДокументСсылка.РеализацияТоваровУслуг"));
ТЗ.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
// Заполняем ТЗ данными...
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Ссылка = ВыбранныйДокумент;
НоваяСтрока.Сумма = 1000;
// 2. Инициализируем настройки
Схема = ЭтотОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = ЭтотОбъект.КомпоновщикНастроек.ПолучитьНастройки();
// 3. Подготавливаем внешние данные
ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ВнешниеДанные", ТЗ); // Имя должно совпадать с именем в схеме
// 4. Компонуем макет
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, ДанныеРасшифровки);
// 5. Выполняем компоновку
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);
// 6. Выводим результат в табличный документ
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(Результат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Важное предостережение: при использовании внешних наборов данных все отборы, установленные пользователем, будут применяться к уже готовой таблице в оперативной памяти. Если ваша таблица содержит миллионы строк, это может привести к значительному потреблению ресурсов сервера.
Если вы работаете в современных конфигурациях (таких как ЗУП 3.1, БП 3.0 или ERP), многие задачи по программному заполнению СКД уже решены на уровне общих модулей. Разберем на примере ЗУП, как система заполняет общие источники данных.
В типовых решениях часто используется механизм подмены схем или динамического дозаполнения полей. Посмотрите на использование процедур типа ЗаполнитьОбщиеИсточникиДанныхОтчета. Это позволяет системе автоматически добавлять в запрос информацию о подразделениях, организациях или правах доступа, не заставляя программиста прописывать это в каждом отчете вручную.
Если ваша задача — создать «универсальный реестр», обратите внимание на стандартный отчет УниверсальныйОтчет. Вместо написания своего кода, вы можете вызвать его программно, передав в качестве параметра тип метаданных (Документ, Справочник или Регистр). Система сама построит схему на лету, предоставив пользователю мощный функционал отборов и группировок БСП.
Подведем итог и проанализируем основные правила работы с запросами в СКД:
ПостроительОтчета в старых («самописных») базах на обычных формах позволяет в одну строку кода ЗаполнитьНастройки() получить готовый интерфейс отборов из текста запроса.Рассмотренные методы позволяют решать задачи любого уровня сложности: от простых реестров до мощных аналитических инструментов с динамической структурой данных. Выбор конкретного подхода зависит от архитектуры вашей базы данных и требований к гибкости отчета.