Как передать необязательный параметр в функцию ВычислитьВыражение в СКД

Программист 1С v8.3 (Обычные формы)
← На главную

При работе с Системой компоновки данных (СКД) разработчики часто сталкиваются с необходимостью вызова функций общих модулей из вычисляемых полей. Одной из самых мощных функций для этих целей является ВычислитьВыражение. Однако при попытке передать в неё параметр отчета, который пользователь может не заполнить (у которого свойство Использование установлено в значение Авто), система часто выдает ошибку. Давайте разберем, почему это происходит и как решить проблему элегантным способом.

В чем заключается суть проблемы?

Рассмотрим стандартную ситуацию. У нас есть вычисляемое поле, в котором прописано выражение:

ВычислитьВыражение("МойОбщийМодуль.РассчитатьДанные(&НужныйПараметр)", "Группировка")

Если пользователь в настройках отчета установил галочку использования параметра &НужныйПараметр и выбрал значение, отчет работает корректно. Но стоит пользователю снять галочку (так как параметр необязателен), как система выдает ошибку: "Параметр не найден".

Проблема кроется в механизме парсинга строки внутри ВычислитьВыражение. СКД анализирует текст внутри кавычек и пытается подставить значения всех встреченных параметров еще до того, как само выражение будет вычислено. Если флаг использования параметра снят, СКД исключает его из доступного контекста, и попытка обращения к нему в строке вызывает критический сбой. Обычная проверка через ВЫБОР КОГДА ... ТОГДА внутри строки не помогает, так как парсер проверяет наличие параметра во всей строке целиком.

Решение №1: Метод «Теневого» параметра (Shadow Parameter)

Проанализируем самый простой и эффективный способ, который не требует написания программного кода. Суть метода заключается в создании вспомогательного параметра, который будет существовать в контексте СКД всегда, независимо от выбора пользователя.

Разберем этот метод по шагам:

  1. Перейдем на закладку Параметры в схеме компоновки данных.
  2. Создадим новый параметр, назовем его, например, &ВспомогательныйПараметр.
  3. Установим для него тип данных, соответствующий вашему основному параметру (например, СправочникСсылка.Подразделения).
  4. В колонке Ограничение доступности установим галочку, чтобы пользователь не видел этот технический параметр в настройках.
  5. Самый важный шаг: в колонке Использование выберем значение Всегда.
  6. В колонке Выражение пропишем имя нашего основного (необязательного) параметра: &НужныйПараметр.

Теперь в выражении вычисляемого поля мы будем использовать наш новый параметр:


ВычислитьВыражение("РаботаСКонтрагентами.Просрочка(&Период.ДатаНачала, &Период.ДатаОкончания, измКлиент, измПредприятие, &ВспомогательныйПараметр, Сумма(ресСуммаБазКонечныйОстаток), &ПоПоставщикам)", "измКлиент", "Группировка")

Как это работает: Поскольку у вспомогательного параметра стоит флаг Использование: Всегда, СКД инициализирует его в любом случае. Если основной параметр &НужныйПараметр не выбран пользователем, вспомогательный параметр просто получит значение по умолчанию для своего типа (для справочников — ПустаяСсылка). В итоге функция общего модуля получит корректный объект, и ошибка не возникнет.

Решение №2: Программная установка значения в модуле отчета

Если мы хотим избежать создания лишних параметров в схеме, мы можем программно управлять состоянием параметров. Для этого воспользуемся процедурой ПриКомпоновкеРезультата в модуле отчета.

Проанализируем пример кода, который принудительно включает использование параметра и подставляет в него пустое значение, если пользователь его проигнорировал:


Процедура ПриКомпоновкеРезультата(ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Получаем настройки пользователя
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    // Ищем нужный параметр
    ПараметрНужный = Настройки.ПараметрыДанных.Элементы.Найти("НужныйПараметр");
    
    Если ПараметрНужный <> Неопределено Тогда
        // Если пользователь не поставил галку использования
        Если Не ПараметрНужный.Использование Тогда
            ПараметрНужный.Использование = Истина;
            // Устанавливаем пустое значение нужного типа
            ПараметрНужный.Значение = Справочники.Подразделения.ПустаяСсылка();
        КонецЕсли;
    КонецЕсли;
    
    // Продолжаем стандартный вывод отчета с обновленными настройками
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(Результат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

Этот способ более «чистый» с точки зрения архитектуры схемы, так как не плодит скрытые сущности, но требует навыков программирования и понимания работы программного вывода отчетов.

Важные нюансы обработки в общем модуле

Выясним причину, по которой отчет может все равно работать некорректно, даже если ошибка исчезла. После того как вы применили метод «теневого» параметра, ваша функция в общем модуле всегда будет получать какое-то значение. В случае, если параметр не выбран, это будет ПустаяСсылка.

Следовательно, внутри функции общего модуля обязательно нужно предусмотреть обработку такого значения. Рассмотрим пример правильной логики внутри функции:


Функция Просрочка(ДатаНачала, ДатаКонца, Клиент, Организация, Подразделение, Сумма, ПоПоставщикам) Экспорт
    
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ ... ГДЕ Клиент = &Клиент И Организация = &Организация";
    
    // Проверяем, заполнено ли подразделение
    Если ЗначениеЗаполнено(Подразделение) Тогда
        Запрос.Текст = Запрос.Текст + " И Подразделение = &Подразделение";
        Запрос.УстановитьПараметр("Подразделение", Подразделение);
    КонецЕсли;
    
    // ... дальнейшая логика расчета
    
КонецФункции

Подведем итог: Для решения проблемы с необязательными параметрами в ВычислитьВыражение наиболее практичным является использование вспомогательного параметра с признаком использования «Всегда». Это гарантирует стабильную работу парсера СКД и избавляет от необходимости писать сложный код инициализации настроек.

← На главную