Как извлечь сумму комиссии банка из текста назначения платежа в 1С?

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

При автоматической загрузке банковских выписок по эквайрингу в конфигурациях 1С (в частности, в «Бухгалтерии предприятия 2.0») реквизит НазначениеПлатежа часто содержит детальную расшифровку операции. Типичный пример строки: «Эквайринг, перечислено по реестру от 01.11.2016. (Количество операций 2 на сумму 1,400.00 по мерчанту , удержано: комиссии 25.20, возвратов 0.00/0.00)». Перед разработчиком встает практическая задача: программно выделить числовое значение комиссии банка из этой текстовой строки и заполнить соответствующий реквизит документа.

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

Способ 1. Быстрое извлечение через разбиение строки (метод СтрЗаменить и СтрПолучитьСтроку)

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

Разберем логику работы по шагам:

  1. Определим ключевой маркер начала суммы — подстроку ": комиссии ".
  2. Заменим этот маркер на символ переноса строки с помощью функции СтрЗаменить(). Теперь нужная нам сумма окажется в начале второй строки.
  3. С помощью функции СтрПолучитьСтроку() получим второй фрагмент текста.
  4. Отрежем всё лишнее после суммы: маркером конца числа служит запятая, отделяющая комиссии от возвратов. Снова выполним замену запятой на Символы.ПС и возьмем первую строку.
  5. Подготовим строку к преобразованию в число: заменим точку на запятую и исключим лишние пробелы.

Посмотрим на пример реализации на встроенном языке 1С:


ТекстНазначения = "Эквайринг, перечислено по реестру от 01.11.2016. (Количество операций 2 на сумму 1,400.00 по мерчанту , удержано: комиссии 25.20, возвратов 0.00/0.00)";

Маркер = ": комиссии ";
ПозицияМаркера = Найти(ТекстНазначения, Маркер);

Если ПозицияМаркера > 0 Тогда
    // Отсекаем начало текста до суммы
    ФрагментПослеМаркера = СтрПолучитьСтроку(СтрЗаменить(ТекстНазначения, Маркер, Символы.ПС), 2);
    
    // Отсекаем хвост после суммы по первой запятой
    СтрокаСуммы = СтрПолучитьСтроку(СтрЗаменить(ФрагментПослеМаркера, ",", Символы.ПС), 1);
    СтрокаСуммы = СокрЛП(СтрокаСуммы);
    
    // В 1С при русской локализации разделителем дробной части является запятая
    СтрокаСуммы = СтрЗаменить(СтрокаСуммы, ".", ",");
    
    // Удаляем неразрывные и обычные пробелы на случай разделителей тысяч
    СтрокаСуммы = СтрЗаменить(СтрокаСуммы, " ", "");
    СтрокаСуммы = СтрЗаменить(СтрокаСуммы, Символ(160), "");
    
    Попытка
        СуммаКомиссии = Число(СтрокаСуммы);
    Исключение
        СуммаКомиссии = 0;
    КонецПопытки;
КонецЕсли;

Способ 2. Посимвольный разбор с проверкой кодов символов

Проанализируем альтернативный подход. Метод разбиения через СтрЗаменить() может дать сбой, если банк изменит знаки препинания после суммы (например, поставит точку с запятой или пробел вместо запятой). Для более надежного разбора подходит посимвольный сбор числа.

Разберем алгоритм по шагам:

  1. Находим стартовую позицию подстроки "комиссии".
  2. Сдвигаем указатель вперед и начинаем посимвольное чтение с помощью функции Сред().
  3. Пропускаем пробелы и знаки-разделители, пока не встретим первую цифру.
  4. Считываем все идущие подряд цифры, а также возможный десятичный разделитель (точку или запятую).
  5. Как только встречаем символ, не являющийся цифрой или разделителем, завершаем чтение.

Посмотрим на практический код такой функции:


Функция ПолучитьСуммуКомиссииИзТекста(Знач Текст) Экспорт

    Маркер = "комиссии";
    Позиция = Найти(НРег(Текст), Маркер);
    
    Если Позиция = 0 Тогда
        Возврат 0;
    КонецЕсли;
    
    // Смещаем позицию за слово-маркер
    Индекс = Позиция + СтрДлина(Маркер);
    ДлинаТекста = СтрДлина(Текст);
    
    СтрокаЧисла = "";
    СборНачат = Ложь;
    
    Пока Индекс <= ДлинаТекста Цикл
        СимволТекста = Сред(Текст, Индекс, 1);
        Код = КодСимвола(СимволТекста);
        
        // Цифры 0-9 имеют коды 48-57
        ЭтоЦифра = (Код >= 48 И Код <= 57);
        ЭтоРазделитель = (СимволТекста = "." Или СимволТекста = ",");
        
        Если ЭтоЦифра Тогда
            СтрокаЧисла = СтрокаЧисла + СимволТекста;
            СборНачат = Истина;
        ИначеЕсли ЭтоРазделитель И СборНачат Тогда
            СтрокаЧисла = СтрокаЧисла + ",";
        ИначеЕсли СборНачат Тогда
            // Если сбор уже начался и встретился нецифровой символ — число закончилось
            Прервать;
        КонецЕсли;
        
        Индекс = Индекс + 1;
    КонецЦикла;
    
    Попытка
        Возврат Число(СтрокаЧисла);
    Исключение
        Возврат 0;
    КонецПопытки;

КонецФункции

Особенности функций поиска строк: Найти() и СтрНайти()

При написании строковых алгоритмов важно учитывать версию платформы и режим совместимости вашей конфигурации:

  1. Функция Найти(<Строка>, <ПодстрокаПоиска>) — базовый глобальный метод, который работает во всех версиях 1С:Предприятия 8.x. Однако начиная с релиза платформы 8.3.6 данный метод объявлен устаревшим.
  2. Функция СтрНайти(<Строка>, <ПодстрокаПоиска>, <НаправлениеПоиска>, <НачальнаяПозиция>, <НомерВхождения>) — современная функция платформы 8.3. Она значительно гибче, так как позволяет искать вхождения с определенной позиции и в обратном направлении. При отключении режима совместимости с устаревшими версиями рекомендуется использовать именно её.

Важные нюансы надежности алгоритма

Выясним причину возможных сбоев при автоматическом разборе текста выписок и перечислим правила безопасной работы:

  1. Локализация разделителя дробной части: Функция Число("25.20") с точкой вызовет исключение при русской локализации информационной базы. Перед вызовом Число() точка всегда должна заменяться на запятую.
  2. Невидимые разделители: Банковские системы при формировании сумм часто используют неразрывный пробел с кодом 160. Стандартная замена пробела " " его не удалит, поэтому обязательно вызывайте СтрЗаменить(Строка, Символ(160), "").
  3. Контроль через Попытка...Исключение: Строковые поля из клиент-банка заполняются внешними системами или вручную операторами банка. Любое неожиданное форматирование может сорвать выполнение загрузки. Оборачивайте блок парсинга в конструкцию перехвата ошибок, чтобы один некорректный документ не прерывал импорт всей выписки.
  4. Альтернатива разбору текста: Если банк периодически меняет шаблоны формулировок, надежнее использовать расчет комиссии по ставке договора эквайринга, заложенный в функционал 1С, либо настраивать импорт структурированных реестров операций (Excel, CSV или XML).
← На главную