Ошибка инициализации выражения параметра в СКД: как исправить синтаксическую ошибку и программно управлять параметрами компоновки

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

Причина ошибки: Блокировка внешних функций в СКД

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

Посмотрим на стандартный код инициализации процессора компоновки данных, который вызывает ошибку, если в выражениях параметров используются функции общих модулей:


ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
// Данный вызов приведет к ошибке, если в схеме есть внешние функции:
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки);

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

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


ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;

// Разрешаем использование внешних функций, передав Истина четвертым параметром
ПроцессорКомпоновкиДанных.Инициализировать(
    МакетКомпоновки, 
    , // Внешние наборы данных (если есть)
    ДанныеРасшифровки, 
    Истина // ВозможностьИспользованияВнешнихФункций
);

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

Как программно удалить Выражение из Параметра СКД?

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

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

Рассмотрим по шагам пример программного удаления выражения из параметра схемы:


// 1. Получаем исходную схему компоновки (например, из макета нашего отчета)
СхемаСКД = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");

// 2. Ищем нужный параметр в коллекции параметров схемы по его имени
ИмяПараметра = "Период";
ПараметрСхемы = СхемаСКД.Параметры.Найти(ИмяПараметра);

Если ПараметрСхемы <> Неопределено Тогда
    // 3. Сбрасываем выражение, присваивая пустую строку
    ПараметрСхемы.Выражение = "";
    
    // При необходимости можно сразу задать значение по умолчанию или тип данных
    ПараметрСхемы.ДоступныеЗначения = Неопределено;
КонецЕсли;

// 4. Далее используем измененную схему для создания макета компоновки
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаСКД, КомпоновщикНастроек.ПолучитьНастройки());

Этот способ позволяет гибко управлять метаданными схемы "на лету" без физического изменения самого макета в конфигураторе.

Использование встроенной функции "ПредопределенноеЗначение"

Очень часто разработчики используют функции БСП вроде ОбщегоНазначенияКлиентСервер.ПредопределенныйЭлемент() для получения ссылок на предопределенные данные прямо в выражениях параметров. Однако во многих случаях более правильным и производительным решением будет использование встроенной системной функции платформы — ПредопределенноеЗначение().

Рассмотрим преимущества перехода на встроенную функцию платформы:

  1. Высокая производительность: Функция ПредопределенноеЗначение обрабатывается непосредственно на уровне ядра платформы 1С. Вызовы функций из общих модулей конфигурации всегда создают дополнительную нагрузку на серверную часть и интерпретатор кода.
  2. Работа в безопасном режиме: Если отчет запускается в безопасном режиме (например, во фреше или в качестве внешней обработки под ограниченными правами), вызовы внешних модулей могут аварийно завершаться из-за политик безопасности. Встроенные функции платформы работают всегда.
  3. Простота кода: При использовании системной функции вам не нужно заботиться о передаче флага ВозможностьИспользованияВнешнихФункций = Истина в процессор компоновки.

Пример правильной записи встроенной функции в поле "Выражение" параметра СКД:

ПредопределенноеЗначение("Справочник.Валюты.СистемнаяВалюта")

Альтернатива: Установка параметров в событии "ПриКомпоновкеРезультата"

Хорошей практикой программирования в 1С считается отказ от сложных выражений внутри XML-схемы СКД. Наличие тяжелой логики в схеме затрудняет тестирование и отладку отчетов в консоли компоновки данных. Вместо этого гораздо удобнее вычислять и устанавливать параметры программно на встроенном языке 1С.

Для этого мы можем использовать предопределенную процедуру ПриКомпоновкеРезультата(), которая располагается в модуле объекта нашего отчета. Это позволяет централизованно управлять параметрами и гарантирует выполнение кода на стороне сервера конфигурации.

Проанализируем пример реализации такого подхода:


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

Используя этот паттерн проектирования, мы делаем наши отчеты более предсказуемыми, простыми в отладке и полностью совместимыми с любыми режимами безопасности выполнения кода 1С.

← На главную