При разработке отчетов на Системе компоновки данных (СКД) нередко возникает задача получить дополнительные данные, которые нецелесообразно или невозможно выбрать прямым запросом. Разработчики часто пытаются вызывать экспортные функции общих модулей прямо в выражении вычисляемого поля или пользовательского поля СКД. Однако при попытке передать результат одной функции в качестве параметра другой или разобрать сложную структуру нередко возникает исключение: Синтаксическая ошибка "ИмяОбщегоМодуля.ИмяФункции" при выполнении метода ПроцессорВыводаРезультатаОтчета.Вывести().
Разберем детально, почему парсер языка выражений СКД выдает такую ошибку, какие системные настройки платформы за это отвечают и как правильно извлекать данные из структур.
Проанализируем базовый механизм работы СКД. По умолчанию платформа 1С в целях безопасности и производительности отключает вызов внешних процедур и функций общих модулей из выражений схемы компоновки данных. Это поведение управляется четвертым параметром метода Инициализировать() объекта ПроцессорКомпоновкиДанных.
Синтаксис метода выглядит следующим образом:
ПроцессорКомпоновкиДанных.Инициализировать(<Макет>, <ВнешниеНаборыДанных>, <ДанныеРасшифровки>, <ВозможностьИспользованияВнешнихФункций>)
Если четвертый параметр не передан явно, платформа принимает его равным Ложь. При таком значении любой вызов функций общих модулей из выражений вычисляемых полей парсер СКД блокирует и считает синтаксической ошибкой. Особенно часто это проявляется при тестировании отчетов во внешних «Консолях системы компоновки данных», где в коде формирования отчета параметр ВозможностьИспользованияВнешнихФункций попросту опущен.
Для программного формирования отчета с поддержкой функций общих модулей необходимо явно передавать Истина:
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(
МакетКомпоновки,
ВнешниеНаборыДанных,
ДанныеРасшифровки,
Истина // ВозможностьИспользованияВнешнихФункций
);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(Результат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Язык выражений СКД — это специализированный встроенный интерпретатор, синтаксис которого существенно отличается от обычного языка 1С:Предприятия. Рассмотрим, с какими жесткими ограничениями сталкивается разработчик:
Модуль.ПолучитьСтруктуру().ЮридическийАдрес или Модуль.ПолучитьСтруктуру()["ЮридическийАдрес"] вызывают ошибку синтаксиса.Модуль1.Функция1(Модуль2.Функция2(Поле1, Поле2), "Ключ") часто не проходит грамматический анализатор выражений СКД в зависимости от версии платформы и режима совместимости.Чтобы избежать синтаксических конфликтов во вложенных вызовах и не перегружать язык выражений парсингом структур, создадим отдельную функцию в серверном общем модуле, которая инкапсулирует вызов типового метода и сразу возвращает готовое примитивное значение.
Посмотрим на пример кода серверного модуля (например, Мой_ОбщийМодульСервер):
// Функция возвращает юридический адрес контрагента на указанную дату
Функция ПолучитьЮридическийАдресКонтрагента(Контрагент, ДатаСведений) Экспорт
Если Не ЗначениеЗаполнено(Контрагент) Тогда
Возврат "";
КонецЕсли;
Сведения = БухгалтерскийУчетПереопределяемый.СведенияОЮрФизЛице(Контрагент, ДатаСведений);
Если ТипЗнч(Сведения) = Тип("Структура") И Сведения.Свойство("ЮридическийАдрес") Тогда
Возврат Сведения.ЮридическийАдрес;
КонецЕсли;
Возврат "";
КонецФункции
Теперь перейдем в схему компоновки данных на вкладку Вычисляемые поля и зададим простое, прямое выражение:
Мой_ОбщийМодульСервер.ПолучитьЮридическийАдресКонтрагента(Получатель, ДатаОтправки)
Такой вызов легко разбирается парсером СКД, не требует вложенных конструкций и гарантирует корректный тип возвращаемого значения.
Вызов функций общих модулей в вычисляемых полях для каждой строки отчета приводит к проблеме N+1 запросов. Если в отчете выводится 10 000 строк, функция будет вызвана 10 000 раз, что существенно замедлит формирование отчета. Разберем, как оптимизировать этот процесс:
Повторное использование возвращаемых значений в положение На время вызова или На время сеанса.КонтактнаяИнформация прямо в тексте запроса СКД.