Как выделить префикс и суффикс из номера документа переменной длины в 1С?

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

В процессе разработки в среде «1С:Предприятие» программисты регулярно сталкиваются с необходимостью текстового анализа номеров документов или артикулов. Типичная бизнес-задача — получить аналитический отчет в разрезе составных частей номера. Например, когда номер документа содержит сложную структуру: буквенный префикс (индекс) переменной длины, уникальный цифровой номер и буквенный суффикс (постфикс), указывающий на тип или статус документа.

Рассмотрим практическую ситуацию. В базе данных существуют документы типа АрхивныйДокумент. Их номера (реквизит РегНомер) могут иметь следующий вид:

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

Метод 1. Классический разбор в запросе с помощью функции ПОДСТРОКА (для старых версий платформы)

Если мы ограничены старыми версиями платформы «1С:Предприятие» (ниже 8.3.20), стандартный язык запросов предоставляет нам очень скромный инструментарий для работы со строками. Главным инструментом здесь выступает функция ПОДСТРОКА. Сложность заключается в том, что длина префикса заранее неизвестна (она может составлять как 1 символ, так и 4), а значит, позиция разделителя (дефиса) и цифрового блока динамически меняется.

Проанализируем структуру номера. Мы можем попытаться определить положение дефиса "-" в строке, последовательно проверяя символы на определенных позициях с помощью конструкции ВЫБОР КОГДА. Рассмотрим пример реализации такого запроса:


ВЫБРАТЬ
    АрхивныйДокумент.РегНомер КАК РегНомер,
    // Определяем префикс документа на основании положения дефиса
    ВЫБОР
        КОГДА ПОДСТРОКА(АрхивныйДокумент.РегНомер, 2, 1) = "-" 
            ТОГДА ПОДСТРОКА(АрхивныйДокумент.РегНомер, 1, 1)
        КОГДА ПОДСТРОКА(АрхивныйДокумент.РегНомер, 5, 1) = "-" 
            ТОГДА ПОДСТРОКА(АрхивныйДокумент.РегНомер, 1, 4)
        ИНАЧЕ "Неопределен"
    КОНЕЦ КАК Префикс,

    // Определяем суффикс документа на конце строки
    ВЫБОР
        КОГДА ПОДСТРОКА(АрхивныйДокумент.РегНомер, 12, 1) = "Т" 
              И ПОДСТРОКА(АрхивныйДокумент.РегНомер, 13, 1) = "Т" 
            ТОГДА "ТТ"
        КОГДА ПОДСТРОКА(АрхивныйДокумент.РегНомер, 12, 1) = "Т" 
              И НЕ ПОДСТРОКА(АрхивныйДокумент.РегНомер, 13, 1) = "Т" 
            ТОГДА "Т"
        ИНАЧЕ "Прочее"
    КОНЕЦ КАК Суффикс,
    АрхивныйДокумент.КолвоКопий КАК КолвоКопий
ИЗ
    Документ.АрхивныйДокумент КАК АрхивныйДокумент

Преимущества метода: работает на любых, даже самых старых версиях платформы 1С v8; выполняется полностью на уровне СУБД в рамках одного запроса.

Недостатки метода: крайне низкая гибкость. Если в базе появится префикс другой длины (например, "ОТД-"), или изменится длина цифрового кода номера, данный запрос перестанет выдавать корректные данные. Код запроса быстро становится громоздким и сложным для отладки.

Метод 2. Использование оператора ПОДОБНО в запросе

Для упрощения условий в запросе мы можем использовать оператор сравнения по шаблону ПОДОБНО (аналог SQL-оператора LIKE). Это позволяет отсекать неподходящие строки и группировать результаты на основе фиксированных масок номеров.

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


ВЫБРАТЬ
    ВЫБОР
        КОГДА АрхивныйДокумент.РегНомер ПОДОБНО "Ф-%" ТОГДА "Ф"
        КОГДА АрхивныйДокумент.РегНомер ПОДОБНО "Инв.-%" ТОГДА "Инв."
        ИНАЧЕ "Прочие"
    КОНЕЦ КАК Префикс,
    ВЫБОР
        КОГДА АрхивныйДокумент.РегНомер ПОДОБНО "%ТТ" ТОГДА "ТТ"
        КОГДА АрхивныйДокумент.РегНомер ПОДОБНО "%Т" ТОГДА "Т"
        ИНАЧЕ "БезСуффикса"
    КОНЕЦ КАК Суффикс,
    СУММА(АрхивныйДокумент.КолвоКопий) КАК КолвоКопий
ИЗ
    Документ.АрхивныйДокумент КАК АрхивныйДокумент

СГРУППИРОВАТЬ ПО
    ВЫБОР
        КОГДА АрхивныйДокумент.РегНомер ПОДОБНО "Ф-%" ТОГДА "Ф"
        КОГДА АрхивныйДокумент.РегНомер ПОДОБНО "Инв.-%" ТОГДА "Инв."
        ИНАЧЕ "Прочие"
    КОНЕЦ,
    ВЫБОР
        КОГДА АрхивныйДокумент.РегНомер ПОДОБНО "%ТТ" ТОГДА "ТТ"
        КОГДА АрхивныйДокумент.РегНомер ПОДОБНО "%Т" ТОГДА "Т"
        ИНАЧЕ "БезСуффикса"
    КОНЕЦ

Важное примечание: Оператор ПОДОБНО транслируется СУБД напрямую. Однако использование символа маски "%" в начале шаблона (например, "%Т") делает невозможным использование индексов СУБД по полю номера, что приведет к полному сканированию таблицы (Table Scan) и снижению быстродействия на больших объемах данных.

Метод 3. Современные строковые функции в запросах (Платформа 8.3.20+)

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

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


ВЫБРАТЬ
    АрхивныйДокумент.РегНомер КАК РегНомер,
    
    // Динамически вычисляем префикс до знака дефиса
    ВЫБОР 
        КОГДА СтрНайти(АрхивныйДокумент.RegНомер, "-") > 0 
            ТОГДА Лев(АрхивныйДокумент.РегНомер, СтрНайти(АрхивныйДокумент.РегНомер, "-") - 1)
        ИНАЧЕ "БезДефиса" 
    КОНЕЦ КАК Префикс,
    
    // Динамически определяем суффикс (ТТ или Т) на конце строки
    ВЫБОР 
        КОГДА Прав(СокрЛП(АрхивныйДокумент.РегНомер), 2) = "ТТ" ТОГДА "ТТ"
        КОГДА Прав(СокрЛП(АрхивныйДокумент.РегНомер), 1) = "Т" ТОГДА "Т"
        ИНАЧЕ "Другой" 
    КОНЕЦ КАК Суффикс
ИЗ
    Документ.АрхивныйДокумент КАК АрхивныйДокумент

Этот запрос полностью решает проблему динамической длины префикса. Функция СтрНайти определяет точную позицию дефиса, а функция Лев забирает все символы левее него. Это наиболее гибкий и лаконичный способ решения задачи "на лету" средствами самого запроса.

Метод 4. Быстрая обработка на встроенном языке с помощью регулярных выражений (Платформа 8.3.23+)

Если задача допускает обработку данных во временной таблице значений на стороне сервера перед выводом в отчет, то встроенный язык предоставляет невероятно мощный инструмент. Начиная с версии платформы 8.3.23, в 1С реализована встроенная поддержка регулярных выражений (стандарт ICU).

Вместо сложных посимвольных циклов перебора (как в старых решениях) мы можем очистить строку от цифр буквально в одну строчку кода, используя функцию СтрЗаменитьПоРегулярномуВыражению. Рассмотрим, как быстро разобрать строку и получить префикс и суффикс:


// Пример обработки номера документа на сервере
НомерДокумента = "Инв.-000000005ТТ";

// Шаблон "\d+" найдет любую последовательность цифр в номере
// Заменяем все цифры на пустую строку
СтрокаБезЦифр = СтрЗаменитьПоРегулярномуВыражению(НомерДокумента, "\d+", "");

// На выходе получаем чистую маску структуры: "Инв.-ТТ"
// Теперь достаточно разделить строку по символу "-"
ЧастиНомера = СтрРазделить(СтрокаБезЦифр, "-");

Если ЧастиНомера.Количество() >= 2 Тогда
    Префикс = ЧастиНомера[0]; // Результат: "Инв."
    Суффикс = ЧастиНомера[1]; // Результат: "ТТ"
КонецЕсли;

Этот код работает невероятно быстро, так как регулярные выражения обрабатываются оптимизированным скомпилированным алгоритмом платформы на уровне C++, минуя медленный интерпретатор встроенного языка 1С.

Метод 5. Оптимальный архитектурный подход (для высоконагруженных систем)

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

Если таблица документов содержит сотни тысяч или миллионы записей, выполнение строковых функций (ПОДСТРОКА, СтрНайти, Прав) в запросе отчета приведет к лавинообразному росту нагрузки на процессор сервера СУБД и полному сканированию таблиц (Table Scan). База данных начнет тормозить, возникнут транзакционные блокировки.

Правильное архитектурное решение заключается в денормализации данных — то есть в расчете префикса и суффикса в момент записи документа и сохранении их в отдельные индексируемые реквизиты. Разберем этот паттерн по шагам:

  1. Добавим в документ АрхивныйДокумент два новых реквизита: ПрефиксИндекса (Тип: Строка, Длина: 10) и СуффиксИндекса (Тип: Строка, Длина: 5).
  2. В свойствах обоих реквизитов обязательно установим свойство Индексировать в значение Индексировать.
  3. В модуле объекта документа пропишем автоматический расчет этих полей в обработчике события ПередЗаписью:

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    Если Не Отказ Тогда
        // Производим разбор номера при изменении или создании
        // Используем штатный механизм регулярных выражений платформы 8.3.23+
        СтрокаБезЦифр = СтрЗаменитьПоРегулярномуВыражению(ЭтотОбъект.Номер, "\d+", "");
        ЧастиНомера = СтрРазделить(СтрокаБезЦифр, "-");
        
        Если ЧастиНомера.Количество() >= 2 Тогда
            ЭтотОбъект.ПрефиксИндекса = ЧастиНомера[0];
            ЭтотОбъект.СуффиксИндекса = ЧастиНомера[1];
        Иначе
            ЭтотОбъект.ПрефиксИндекса = "";
            ЭтотОбъект.СуффиксИндекса = "";
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

После проведения денормализации наш отчет по группировкам префиксов и суффиксов превращается в элементарный, безопасный и мгновенно выполняющийся запрос, который идеально задействует индексы СУБД:


ВЫБРАТЬ
    АрхивныйДокумент.ПрефиксИндекса КАК Префикс,
    АрхивныйДокумент.СуффиксИндекса КАК Суффикс,
    СУММА(АрхивныйДокумент.КолвоКопий) КАК КолвоКопий
ИЗ
    Документ.АрхивныйДокумент КАК АрхивныйДокумент
СГРУППИРОВАТЬ ПО
    АрхивныйДокумент.ПрефиксИндекса,
    АрхивныйДокумент.СуффиксИндекса

Подведем итоги

Мы детально изучили эволюцию методов разбора строк в системе «1С:Предприятие». Выбор конкретного инструмента зависит от технических требований проекта:

← На главную