При переходе с обычных форм на управляемые разработчики часто сталкиваются с ситуацией, когда проверенный временем внешний отчет на базе Системы компоновки данных (СКД) внезапно перестает работать. При попытке формирования отчета система выдает крайне неприятную ошибку: «Не задано значение параметра» (например, для склада или номенклатуры), хотя на обычных формах этот же отчет прекрасно формировался с пустыми или незаполненными параметрами.
В этой статье мы подробно разберем причины такого поведения платформы 1С:Предприятие 8.3, проанализируем разницу в работе механизмов компоновки данных и рассмотрим три эффективных практических способа решения этой проблемы.
На обычных формах инициализация отчета происходила менее строго. Платформа зачастую неявно инициализировала незаданные параметры значениями по умолчанию (например, пустой ссылкой соответствующего типа справочника) при открытии формы или выполнении стандартных обработчиков. Это маскировало ошибки проектирования запроса, позволяя СУБД успешно отрабатывать условие вида Субконто2 В ИЕРАРХИИ (&Склад).
На управляемых формах СКД работает в строгом и динамическом режиме. Если параметр жестко зашит в тексте запроса виртуальной таблицы и пользователь не заполнил его на форме (или снял флаг использования), управляемая форма передает в компоновщик настроек состояние «Не используется». Платформа при попытке сгенерировать итоговый SQL-запрос не находит значения для подстановки и аварийно завершает работу с ошибкой.
Проанализируем ситуацию на примере классического запроса к виртуальной таблице остатков и оборотов:
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(
&НачалоПериода,
&КонецПериода,
Регистратор,
Движения,
Счет = &счет,
,
Субконто2 В ИЕРАРХИИ (&Склад)
И Субконто1 В ИЕРАРХИИ (&Номенклатура)) КАК ХозрасчетныйОстаткиИОбороты
Если пользователь захочет сформировать отчет в целом по компании (не указывая конкретный склад), параметр &Склад окажется неинициализированным, что и приведет к ошибке выполнения запроса.
Разберем по шагам три способа решения этой технической проблемы.
Этот метод является наиболее правильным, изящным и производительным с точки зрения стандартов разработки фирмы «1С». Мы не просто переносим фильтрацию на уровень итогового отбора (что заставило бы СУБД выбирать гигантские объемы лишних данных), а делаем условия внутри виртуальной таблицы необязательными.
Для этого мы воспользуемся конструкцией фигурных скобок {} — расширением языка запросов СКД. Перепишем наш запрос следующим образом:
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(
&НачалоПериода,
&КонецПериода,
Регистратор,
Движения,
Счет = &счет,
,
{(Субконто2 В ИЕРАРХИИ (&Склад)), (Субконто1 В ИЕРАРХИИ (&Номенклатура))}
) КАК ХозрасчетныйОстаткиИОбороты
Важные нюансы настройки схемы компоновки данных при этом подходе:
&Склад и &Номенклатура нам необходимо установить свойство «Использование» в значение «Авто» (вместо значения «Всегда»).Этот способ позволяет полностью уйти от использования классических параметров &Склад и &Номенклатура на вкладке параметров СКД. Вместо этого мы предоставляем пользователю возможность настраивать стандартные отборы компоновщика, но при этом сохраняем высокую производительность отчета.
Для реализации этого метода перепишем запрос с использованием синтаксиса разыменования полей внутри фигурных скобок:
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(
&НачалоПериода,
&КонецПериода,
Регистратор,
Движения,
Счет = &счет,
,
{(Субконто2).* КАК Склад, (Субконто1).* КАК Номенклатура}
) КАК ХозрасчетныйОстаткиИОбороты
Рассмотрим подробнее логику работы этого механизма:
(Субконто2).* КАК Склад сообщает системе компоновки данных, что если пользователь добавит стандартный отбор по полю «Склад», то этот отбор должен быть транслирован (перенаправлен) платформой непосредственно в параметры виртуальной таблицы бухгалтерского регистра.Если вам по каким-то причинам (например, для вывода сложных заголовков или специфической логики постобработки в модуле объекта) крайне важно сохранить именно классические параметры СКД в явном виде, можно решить проблему через настройки свойств параметров и доработку условий запроса.
Выполним следующие шаги:
&Склад и &Номенклатура принудительно установим свойство «Использование» в значение «Всегда». Это заставит платформу гарантированно передавать эти параметры в запрос. Если пользователь их не заполнит, система передаст пустые ссылки соответствующих типов.
(Субконто2 В ИЕРАРХИИ (&Склад) ИЛИ &Склад = ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка))
И (Субконто1 В ИЕРАРХИИ (&Номенклатура) ИЛИ &Номенклатура = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка))
Важное предупреждение: Несмотря на простоту реализации, этот способ уступает первому и второму вариантам в плане производительности. Наличие логического оператора ИЛИ при проверке пустых значений параметров в запросах к виртуальным таблицам может приводить к тому, что СУБД откажется от использования индексов и выполнит полное сканирование таблиц (Table Scan), что существенно замедлит построение отчета на крупных базах данных.
Мы проанализировали проблему инициализации параметров виртуальных таблиц в управляемом приложении 1С. Для исправления ошибки «Не задано значение параметра» рекомендуется использовать Способ 1 (фигурные скобки вокруг параметров) или Способ 2 (трансляция отборов). Они обеспечивают идеальный баланс между удобством работы пользователя на управляемой форме и быстродействием СУБД.