Как обрезать строку или извлечь данные из текста в отчете СКД

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

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

Способ 1: Использование вычисляемых полей и встроенных функций

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

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


Подстрока(ИмяПоляКомментарий, 
         СтрНайти(ИмяПоляКомментарий, "детей"), 
         ДлинаСтроки(ИмяПоляКомментарий) - СтрНайти(ИмяПоляКомментарий, "детей") + 1)

Давайте разберем по шагам, как работает это выражение:

  1. Функция СтрНайти определяет порядковый номер символа, с которого начинается искомое слово.
  2. Функция ДлинаСтроки вычисляет общее количество символов в поле.
  3. Математическое действие ДлинаСтроки - СтрНайти + 1 позволяет нам динамически определить, сколько символов нужно взять справа от найденного слова, чтобы захватить строку до самого конца.
  4. Функция Подстрока собирает итоговый результат, используя полученную позицию и длину.

Важное примечание: Если вы попытаетесь использовать функцию Найти (старый вариант), она может не заработать в некоторых контекстах СКД. Рекомендуется использовать современную функцию СтрНайти, которая появилась в платформе 8.3.

Способ 2: Работа на уровне запроса vs Вычисляемые поля

Проанализируем ситуацию: почему некоторые строковые функции не работают прямо в тексте запроса? Это связано с тем, что запрос транслируется в SQL, и СУБД (например, MS SQL или PostgreSQL) имеет свой ограниченный набор функций для работы с текстом. В запросе нам доступна только функция ПОДСТРОКА (SUBSTRING), но она требует четких координат, которые в SQL-запросе вычислить сложно (функция CHARINDEX или POSITION не всегда доступны через стандартный конструктор запроса 1С).

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

Способ 3: Извлечение данных сложной структуры (случай с номером №)

Бывают задачи сложнее: например, нужно извлечь номер договора из строки вида "Оплата по счету № 1122 от 2014 года". Сложность в том, что между знаком № и цифрами может быть разное количество пробелов, а само число может иметь длину от 3 до 5 знаков. Стандартными функциями Лев или Сред здесь обойтись трудно.

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


Функция ИзвлечьНомерИзСтроки(Знач ИсходнаяСтрока) Экспорт
    
    // Создаем объект для работы с регулярными выражениями
    RegExp = Новый COMОбъект("VBScript.RegExp");
    RegExp.IgnoreCase = Истина;
    RegExp.Global = Ложь;
    
    // Шаблон: ищем знак №, затем любое кол-во пробелов (\s*), 
    // затем группу цифр (\d+), которую и хотим получить
    RegExp.Pattern = "№\s*(\d+)";
    
    Matches = RegExp.Execute(ИсходнаяСтрока);
    
    Если Matches.Count > 0 Тогда
        // Возвращаем первую найденную группу (само число)
        Возврат Matches.Item(0).SubMatches.Item(0);
    Иначе
        Возврат "";
    КонецЕсли;
    
КонецФункции

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

Полезные советы по оптимизации поиска

Чтобы поиск слов (например, того же слова "детей") был надежным и не зависел от того, с какой буквы пользователь написал комментарий, проанализируем использование функций регистра. Мы рекомендуем всегда приводить строку к одному регистру перед поиском:

Пример надежного поиска:

СтрНайти(ВРег(Комментарий), "ДЕТЕЙ")

Также разберем по шагам очистку от лишних пробелов. Если вы извлекаете числовое значение, которое может быть окружено пробелами, используйте комбинацию функций СокрЛП и Число. Это гарантирует, что отчет не "упадет" с ошибкой при попытке сложения строк:


// В выражении СКД
Число(СокрЛП(ИмяОбщегоМодуля.ИзвлечьНомерИзСтроки(Поле1)))

Сводная таблица функций для работы со строками в СКД

Рассмотрим основные инструменты, которые всегда должны быть под рукой у разработчика отчетов:

Используя эти методы, вы сможете превратить неструктурированные комментарии в чистые, пригодные для анализа данные прямо в момент формирования отчета.

← На главную