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