Как из строки выделить число и удалить лишние символы в 1С

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

В процессе интеграции 1С с внешними системами, парсинга сайтов или загрузки прайс-листов из Excel разработчики часто сталкиваются с грязными данными. Типичный пример — когда цена или количество приходят в виде текстовой строки с суффиксами валют или единиц измерения, например: "1280руб.", " 1 250,50 $" или даже "125руб.13коп.". Прямая попытка преобразовать такую строку с помощью стандартной функции Число() вызовет аварийное завершение программы.

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

Способ 1. Нативная поддержка регулярных выражений (для платформы 8.3.23 и выше)

Начиная с версии платформы 8.3.23, разработчикам больше не нужно использовать COM-объекты операционной системы Windows для работы с регулярными выражениями. В платформу была добавлена встроенная кроссплатформенная поддержка регулярных выражений, которая отлично работает как на Windows, так и на Linux-серверах, а также в мобильном клиенте.

Это самый простой, элегантный и современный способ решения задачи в одну строку. Рассмотрим пример кода, который удаляет все символы, кроме цифр:


// Очищаем строку от любых символов, кроме цифр
ИсходнаяСтрока = "1280руб.";
ОчищеннаяСтрока = СтрЗаменитьПоРегулярномуВыражению(ИсходнаяСтрока, "[^\d]", "");
РезультатЧисло = Число(ОчищеннаяСтрока); // Возвратит число 1280

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


// Сохраняем разделители дробной части
ИсходнаяСтрока = "125руб.13коп.";
// Шаблон [^\d\.,] означает: удалить всё, кроме цифр, точек и запятых
ОчищеннаяСтрока = СтрЗаменитьПоРегулярномуВыражению(ИсходнаяСтрока, "[^\d\.,]", "");

// Заменяем разделители на единый формат, понятный платформе 1С (запятую)
ОчищеннаяСтрока = СтрЗаменить(ОчищеннаяСтрока, ".", ",");
РезультатЧисло = Число(ОчищеннаяСтрока); // Возвратит число 125,13

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

Способ 2. Использование COM-объекта RegExp (для старых версий платформ на Windows)

Если ваша информационная база работает на старой версии платформы (ниже 8.3.23), встроенных регулярных выражений у вас нет. Однако, если сервер 1С или клиентское приложение запущены под операционной системой Windows, вы можете воспользоваться системным COM-объектом VBScript.RegExp.

Проанализируем пример функции, реализующей этот подход:


Функция ВыделитьЧислоРегулярнымВыражениемCOM(Знач ИсходнаяСтрока) Экспорт
    #Если Клиент Или НаСервере Тогда
    // Данный код выполнится только на Windows-системах
    Попытка
        RegExp = Новый COMОбъект("VBScript.RegExp");
    Исключение
        // На случай, если код выполняется в среде Linux
        ВызватьИсключение "Регулярные выражения COM не поддерживаются на данной ОС!";
    КонецПопытки;
    
    RegExp.IgnoreCase = Истина;
    RegExp.Global = Истина;
    RegExp.MultiLine = Ложь;
    
    // Шаблон для удаления всего, кроме цифр и разделителей
    RegExp.Pattern = "[^\d\.,]"; 
    ОчищеннаяСтрока = RegExp.Replace(ИсходнаяСтрока, "");
    
    // Приводим к единому разделителю дробной части
    ОчищеннаяСтрока = СтрЗаменить(ОчищеннаяСтрока, ".", ",");
    
    Попытка
        Возврат Число(ОчищеннаяСтрока);
    Исключение
        Возврат 0;
    КонецПопытки;
    #Иначе
    Возврат 0;
    #КонецЕсли;
КонецФункции

Внимание: помните, что этот код вызовет критическую ошибку на сервере под управлением Linux, так как технология COM там не поддерживается. Для реализации обработки строк по шаблонам без системных COM-объектов можно применить подсистему для работы с регулярными выражениями в 1С.

Способ 3. Оптимальный ручной алгоритм в один проход (без RegExp)

Если вам требуется кроссплатформенное решение для старых версий платформы или вы хотите полностью контролировать логику разбора строки (например, выделять только первое число из строки вида "Цена 100 руб, скидка 10%"), то идеальным вариантом будет посимвольный перебор.

На форумах часто предлагают использовать конструкции с многократным вызовом функции СтрЗаменить() для каждого нецифрового символа. Однако этот подход крайне неэффективен с точки зрения производительности (алгоритмическая сложность составляет $O(M \cdot N)$, где $M$ — количество заменяемых символов, а $N$ — длина строки). При обработке больших массивов данных такой код будет сильно тормозить систему.

Разберем действительно быстрый алгоритм с линейной сложностью $O(N)$, который делает всего один проход по строке и анализирует коды символов:


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

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

Способ 4. Готовые инструменты Библиотеки Стандартных Подсистем (БСП)

Если вы ведете разработку в типовой конфигурации (например, 1С:ERP, 1С:Управление торговлей или 1С:Бухгалтерия), то в вашем распоряжении уже есть готовые функции общего модуля БСП СтроковыеФункцииКлиентСервер.

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

  1. СтроковыеФункцииКлиентСервер.ТолькоЦифрыВСтроке(Строка) — возвращает логическое значение Истина, если строка состоит только из цифр. Это удобно для предварительной валидации данных перед вызовом функции преобразования.
  2. СтроковыеФункцииКлиентСервер.СтрокаВЧисло(Значение) — безопасная альтернатива стандартному методу Число(). Главный плюс этой функции в том, что при неудачной попытке преобразования (например, если в строке остались буквы) она не вызывает исключение, приводящее к остановке программы, а тихо возвращает значение Неопределено.

Пример использования функций БСП в кодовой базе:


ИсходноеЗначение = " 1500 ";
// Удаляем пробелы и неразрывные пробелы
ОчищенноеЗначение = СокрЛП(СтрЗаменить(ИсходноеЗначение, Символы.НПП, ""));

Если СтроковыеФункцииКлиентСервер.ТолькоЦифрыВСтроке(ОчищенноеЗначение) Тогда
    ЧисловоеЗначение = СтроковыеФункцииКлиентСервер.СтрокаВЧисло(ОчищенноеЗначение);
Иначе
    ЧисловоеЗначение = 0; // Или обработка ошибки
КонецЕсли;

Способ 5. Простая замена фиксированных подстрок

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

Однако здесь важно учесть разделители групп разрядов (триад). Очень часто при выгрузке чисел в строку добавляются пробелы для удобства чтения человеком (например, "1 280 руб."). Причем этот пробел может быть не обычным (код 32), а неразрывным (символ Символы.НПП с кодом 160). Обычная замена строки "руб." оставит пробелы внутри числа, и функция Число() упадет с ошибкой.

Рассмотрим правильный пример реализации простой замены:


ИсходнаяСтрока = "1 280,50 руб.";

// 1. Избавляемся от известного суффикса
Результат = СтрЗаменить(ИсходнаяСтрока, "руб.", "");

// 2. Очищаем пробелы (как обычные, так и неразрывные)
Результат = СтрЗаменить(Результат, " ", "");
Результат = СтрЗаменить(Результат, Символы.НПП, "");

// 3. Заменяем разделитель дробной части на запятую
Результат = СтрЗаменить(Результат, ".", ",");

// 4. Безопасно преобразуем в число
Попытка
    ИтоговаяЦена = Число(Результат);
Исключение
    ИтоговаяЦена = 0;
КонецПопытки;

Можно ли решить эту задачу на уровне запроса 1С?

Периодически у разработчиков возникает желание производить такую очистку данных непосредственно в запросе. Однако в стандартном языке запросов 1С нет встроенных механизмов для сложной работы со строками.

Конструкция языка запросов ВЫРАЗИТЬ(Поле КАК Число) для строковых полей **не поддерживается** СУБД и вызовет синтаксическую ошибку на этапе компиляции запроса. Попытки реализовать посимвольный разбор строки через комбинации функций ПОДСТРОКА и условий ВЫБОР КОГДА приводят к созданию монструозных запросов, которые крайне медленно выполняются и создают колоссальную нагрузку на сервер СУБД.

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

← На главную