Работа со строковыми данными в Системе компоновки данных (СКД) часто выходит за рамки простого вывода полей. Часто возникают задачи, когда необходимо очистить комментарий от лишних слов, извлечь номер документа из середины текста или обрезать строку по определенному маркеру. В этой статье мы подробно разберем, как решать такие задачи, используя встроенные функции языка выражений СКД и возможности общих модулей.
Рассмотрим ситуацию, когда в комментарии к документу (например, "Алименты на детей Ивана...") нужно оставить только ту часть текста, которая начинается со слова "детей". Проблема заключается в том, что мы не знаем точную позицию этого слова в каждой строке. Для решения этой задачи идеально подходят вычисляемые поля СКД.
Разберем логику: нам нужно найти позицию слова "детей" и начиная с этой позиции «забрать» весь оставшийся текст до конца строки. Проанализируем формулу, которую можно вставить в колонку «Выражение» на закладке «Вычисляемые поля»:
Подстрока(ИмяПоляКомментарий,
СтрНайти(ИмяПоляКомментарий, "детей"),
ДлинаСтроки(ИмяПоляКомментарий) - СтрНайти(ИмяПоляКомментарий, "детей") + 1)
Давайте разберем по шагам, как работает это выражение:
СтрНайти определяет порядковый номер символа, с которого начинается искомое слово.ДлинаСтроки вычисляет общее количество символов в поле.ДлинаСтроки - СтрНайти + 1 позволяет нам динамически определить, сколько символов нужно взять справа от найденного слова, чтобы захватить строку до самого конца.Подстрока собирает итоговый результат, используя полученную позицию и длину.Важное примечание: Если вы попытаетесь использовать функцию Найти (старый вариант), она может не заработать в некоторых контекстах СКД. Рекомендуется использовать современную функцию СтрНайти, которая появилась в платформе 8.3.
Проанализируем ситуацию: почему некоторые строковые функции не работают прямо в тексте запроса? Это связано с тем, что запрос транслируется в SQL, и СУБД (например, MS SQL или PostgreSQL) имеет свой ограниченный набор функций для работы с текстом. В запросе нам доступна только функция ПОДСТРОКА (SUBSTRING), но она требует четких координат, которые в SQL-запросе вычислить сложно (функция CHARINDEX или POSITION не всегда доступны через стандартный конструктор запроса 1С).
Поэтому, если вам нужно гибкое манипулирование текстом, лучше всего использовать вкладку Вычисляемые поля в СКД. Код, написанный там, исполняется уже средствами самой платформы 1С после получения данных из базы, что дает доступ к полному набору функций встроенного языка.
Бывают задачи сложнее: например, нужно извлечь номер договора из строки вида "Оплата по счету № 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)))
Рассмотрим основные инструменты, которые всегда должны быть под рукой у разработчика отчетов:
СтрНайти(Строка, Подстрока) — возвращает позицию первого вхождения.СтрЗаменить(Строка, ЧтоМеняем, НаЧтоМеняем) — незаменима для удаления специфических символов (например, кавычек или лишних тире).Сред(Строка, Начало, [Длина]) — аналог Подстрока, позволяет вырезать кусок текста из середины.СтрРазделить(Строка, Разделитель) — превращает строку в массив (удобно использовать в общем модуле, если данные разделены запятыми).СокрЛ, СокрП, СокрЛП — удаление незначащих пробелов слева и справа.Используя эти методы, вы сможете превратить неструктурированные комментарии в чистые, пригодные для анализа данные прямо в момент формирования отчета.