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