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