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