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