Как программно найти номер счета по маске в строке назначения платежа?

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

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

Способ 1: Поиск по разделителям и смещениям (встроенный язык)

Если номер счета имеет жесткую структуру, например, XX/XX/XX/XXXXXX, мы можем использовать алгоритм, который ищет разделители (косую черту) и проверяет их взаимное расположение. Это решение не требует сторонних компонент и работает на любой версии платформы.

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

Проанализируем пример функции:


Функция НайтиНомерСчетаПоМаске(Знач ИсходнаяСтрока) Экспорт
    Результат = "";
    // Находим позицию первой косой черты
    Поз = СтрНайти(ИсходнаяСтрока, "/");
    
    // Пока находим разделители в строке
    Пока Поз > 0 Цикл
        // Проверяем, достаточно ли длины строки для маски (нам нужно еще минимум 12 символов после первой /)
        Если СтрДлина(ИсходнаяСтрока) >= Поз + 12 Тогда
            // Проверяем наличие разделителей на позициях А+3 и А+6
            // Маска: XX/XX/XX/XXXXXX
            // Поз:    ^  ^  ^
            Если (Сред(ИсходнаяСтрока, Поз + 3, 1) = "/") И 
                 (Сред(ИсходнаяСтрока, Поз + 6, 1) = "/") Тогда
                
                // Если разделители на месте, извлекаем весь номер (2 знака до первой черты + 13 знаков хвоста)
                Результат = Сред(ИсходнаяСтрока, Поз - 2, 15);
                Прервать; // Номер найден
            КонецЕсли;
        КонецЕсли;
        
        // Ищем следующий разделитель, начиная со следующей позиции
        Поз = СтрНайти(ИсходнаяСтрока, "/", Поз + 1);
    КонецЦикла;
    
    Возврат СокрЛП(Результат);
КонецФункции

Этот метод хорош тем, что он крайне быстр, но он чувствителен к лишним пробелам внутри номера. Поэтому перед поиском рекомендуем нормализовать строку.

Способ 2: Использование нативных регулярных выражений (1С 8.3.24+)

В современных версиях платформы 1С (начиная с 8.3.24) появилась встроенная поддержка регулярных выражений. Это "золотой стандарт" для поиска текста по шаблону. Вместо сложных циклов мы можем описать маску одним выражением \d{2}/\d{2}/\d{2}/\d{6}.

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


// Пример для новых версий платформы
РегЭксп = Новый РегулярноеВыражение("\d{2}/\d{2}/\d{2}/\d{6}");
РезультатПоиска = РегЭксп.Найти(ТекстНазначенияПлатежа);

Если РезультатПоиска.Количество() > 0 Тогда
    НомерСчета = РезультатПоиска[0].Значение;
    // Номер найден и готов к использованию
КонецЕсли;

Преимущества этого подхода:

Способ 3: Регулярные выражения через COM-объект (для старых версий)

Если ваша база работает на версии ниже 8.3.24, вы можете использовать системный объект VBScript.RegExp. Выясним, как правильно настроить этот объект для поиска в 1С.


Функция ИзвлечьНомерЧерезRegExp(Текст)
    RegExp = Новый COMОбъект("VBScript.RegExp");
    RegExp.IgnoreCase = Истина; // Игнорировать регистр
    RegExp.Global = Ложь;       // Нам нужно только первое совпадение
    RegExp.MultiLine = Ложь;
    
    // Описываем шаблон: 2 цифры, слэш, 2 цифры, слэш, 2 цифры, слэш, 6 цифр
    RegExp.Pattern = "\d{2}/\d{2}/\d{2}/\d{6}";
    
    Matches = RegExp.Execute(Текст);
    
    Если Matches.Count > 0 Тогда
        Возврат Matches.Item(0).Value;
    КонецЕсли;
    
    Возврат "";
КонецФункции

Важно помнить, что этот метод работает только в среде Windows. Если сервер 1С работает на Linux, данный код вызовет ошибку.

Способ 4: Метод разделения строки (СтрРазделить)

Иногда удобно не искать вхождения, а "разбить" строку на части по разделителю / и проанализировать полученные сегменты. Посмотрим на этот алгоритм:

  1. Используем функцию СтрРазделить(ИсходнаяСтрока, "/"), чтобы получить массив частей.
  2. Перебираем массив и ищем последовательность элементов, длины которых соответствуют нашей маске (2, 2, 2 и 6 символов).
  3. Собираем номер обратно из найденных кусков.

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

Важность нормализации данных

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

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

Мы рассмотрели несколько подходов к программному поиску конструкций. Для простых задач и старых конфигураций отлично подходит Способ 1 (ручной перебор). Если же вы работаете на современной платформе или вам нужна максимальная гибкость — используйте регулярные выражения. Это позволит вам не дописывать код при каждом новом варианте написания фразы "по счету", а просто корректировать шаблон поиска.

← На главную