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