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

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

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

Вызов функций из модуля менеджера отчета

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

Разберем по шагам, как реализовать этот механизм:

  1. Откройте модуль менеджера вашего отчета.
  2. Создайте в нем функцию и обязательно добавьте ключевое слово Экспорт. Проанализируем пример функции, которая перебирает строку и оставляет в ней только цифры:

Функция ПолучитьНомерМагазина(Магазин) Экспорт
    ВыхСтрока = "";
    Для п = 1 По СтрДлина(Магазин) Цикл
        Симв = Сред(Магазин, п, 1);
        Если Симв >= "0" И Симв <= "9" Тогда
            ВыхСтрока = ВыхСтрока + Симв;
        КонецЕсли;
    КонецЦикла;
    Возврат ВыхСтрока;
КонецФункции
  1. В схеме компоновки данных (СКД) перейдите на закладку Вычисляемые поля.
  2. В поле "Выражение" пропишите путь к вашей функции, используя обращение через менеджер отчетов: Отчеты.ИмяВашегоОтчета.ПолучитьНомерМагазина(Магазин).

Важный нюанс: данный метод будет работать только в том случае, если отчет встроен в конфигурацию. Для внешних отчетов (файлы .erf) такой синтаксис не применим, так как у них нет фиксированного имени в дереве метаданных Отчеты.

Использование функций общих модулей

Если отчет является внешним или вы хотите создать универсальный механизм, который можно использовать в нескольких отчетах сразу, следует вынести логику в общий модуль. Рассмотрим требования к такому модулю:

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

Обработка строк стандартными средствами платформы и БСП

Иногда создание собственных функций в модулях избыточно. Рассмотрим, как можно извлечь цифры из строки напрямую в выражении СКД, используя возможности платформы 8.3.15+ или функции Библиотеки стандартных подсистем (БСП).

Вариант 1: Использование функций БСП

Если в вашей конфигурации внедрена БСП, мы можем воспользоваться мощной функцией ЗаменитьОдниСимволыДругими. Идея заключается в том, чтобы сначала получить все "лишние" символы, а затем удалить их из исходной строки:


СтроковыеФункцииКлиентСервер.ЗаменитьОдниСимволыДругими(
    СтроковыеФункцииКлиентСервер.ЗаменитьОдниСимволыДругими("0123456789", Магазин, ""), 
    Магазин, 
    ""
)

Вариант 2: Использование современных строковых функций платформы (например, если нужно сравнение строки с представлением ссылки)

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


СтрСоединить(СтрРазделить(Магазин, СтрСоединить(СтрРазделить(Магазин, "0123456789"))))

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

Альтернативный подход: Внешний набор данных

Если логика преобразования настолько сложна, что выражения СКД становятся нечитаемыми, а менять конфигурацию (добавлять общие модули) запрещено, проанализируем вариант с использованием Набора данных - объект.

Суть метода заключается в следующем:

  1. В модуле объекта отчета в процедуре ПриКомпоновкеРезультата вы самостоятельно выполняете запрос к базе данных (быстро написать его поможет консоль запросов) — для этого подойдёт универсальная консоль запросов и СКД.
  2. Выгружаете результат запроса в ТаблицаЗначений (к которой можно применить отбор компоновки данных).
  3. В цикле обходите таблицу и заполняете новую колонку НомерМагазина, вызывая любую локальную функцию модуля объекта.
  4. Передаете готовую таблицу в СКД через ВнешниеНаборыДанных.

Рассмотрим пример кода в модуле объекта:


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

Важные ограничения и рекомендации

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

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

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

← На главную