Как преобразовать число из прописи в цифровой вид в 1С

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

В стандартной платформе «1С:Предприятие» существует мощная встроенная функция ЧислоПрописью, которая позволяет легко превратить число 1380.00 в строку «Одна тысяча триста восемьдесят рублей 00 копеек». Однако разработчики часто сталкиваются с обратной задачей: когда из текстового файла, распознанного скана или PDF-выписки нужно извлечь сумму, представленную словами, и превратить ее в обычное число для записи в информационную базу.

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

Почему в 1С нет встроенной функции «ПрописьВЧисло»?

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

Важно понимать, что ни в платформе, ни в «Библиотеке стандартных подсистем» (БСП) готового метода не существует. Поэтому нам необходимо реализовать собственный алгоритм «накопителя».

Разбор алгоритма: логика работы «накопителя»

Основная сложность преобразования заключается в том, что числительные в русском языке имеют сложную иерархию. Мы не можем просто складывать значения слов. Например, в фразе «две тысячи» слово «две» (2) должно умножиться на «тысячи» (1000), а в фразе «двадцать две» — сложиться.

Проанализируем ситуацию и выделим основные этапы обработки строки:

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

Практическая реализация функции парсинга

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


// Функция преобразует прописное число в цифровое
// Пример: "Сто Двадцать Три тысячи Двести Сорок один рубль 15 копеек" -> 123241.15
Функция ПрописьВЧисло(Знач Пропись) Экспорт
    
    // Приводим к нижнему регистру для удобства сравнения
    Пропись = НРег(Пропись);
    
    // Инициализируем переменные
    ТекущийРазряд = 0;
    Результат = 0;
    Копейки = 0;
    ОбрабатываемКопейки = Ложь;
    
    // Разбиваем строку на слова
    Слова = СтрРазделить(Пропись, " ", Ложь);
    
    // Основной цикл по словам
    Для Каждого Слово Из Слова Цикл
        
        Если Слово = "" Тогда
            Продолжить;
        КонецЕсли;
        
        // Определяем момент перехода к копейкам
        Если Слово = "копейка" Или Слово = "копеек" Или Слово = "копейки" Тогда
            ОбрабатываемКопейки = Истина;
            Продолжить;
        КонецЕсли;
        
        // Валюту (рубли) просто пропускаем, они служат разделителем
        Если Слово = "рубль" Или Слово = "рублей" Или Слово = "рубля" Тогда
            Продолжить;
        КонецЕсли;
        
        Если НЕ ОбрабатываемКопейки Тогда
            // Обрабатываем основную часть (рубли)
            СтруктураРезультата = ОбработатьСловоРубли(Слово, ТекущийРазряд, Результат);
            ТекущийРазряд = СтруктураРезультата.ТекущийРазряд;
            Результат = СтруктураРезультата.Результат;
        Иначе
            // Обрабатываем дробную часть (копейки)
            Копейки = ОбработатьСловоКопейки(Слово, Копейки);
        КонецЕсли;
        
    КонецЦикла;
    
    // Добавляем последний накопленный разряд к результату
    Результат = Результат + ТекущийРазряд;
    
    // Добавляем копейки к результату
    Если Копейки > 0 Тогда
        Результат = Результат + Копейки / 100;
    КонецЕсли;
    
    Возврат Результат;
    
КонецФункции

Вспомогательные функции для поиска соответствий

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


Функция ОбработатьСловоРубли(Слово, ТекущийРазряд, Результат)
    СтруктураРезультата = Новый Структура("ТекущийРазряд, Результат", ТекущийРазряд, Результат);
    
    // 1. Проверяем простые числа (1-9, 10-19, 20-90, 100-900)
    Значение = ПолучитьЧисловоеЗначение(Слово);
    Если Значение > 0 Тогда
        СтруктураРезультата.ТекущийРазряд = ТекущийРазряд + Значение;
        Возврат СтруктураРезультата;
    КонецЕсли;

    // 2. Обрабатываем слова-множители (разряды)
    Если Слово = "тысяч" Или Слово = "тысяча" Или Слово = "тысячи" Тогда
        СтруктураРезультата.Результат = Результат + ТекущийРазряд * 1000;
        СтруктураРезультата.ТекущийРазряд = 0;
    ИначеЕсли Слово = "миллион" Или Слово = "миллиона" Или Слово = "миллионов" Тогда
        СтруктураРезультата.Результат = Результат + ТекущийРазряд * 1000000;
        СтруктураРезультата.ТекущийРазряд = 0;
    ИначеЕсли Слово = "миллиард" Или Слово = "миллиарда" Или Слово = "миллиардов" Тогда
        СтруктураРезультата.Результат = Результат + ТекущийРазряд * 1000000000;
        СтруктураРезультата.ТекущийРазряд = 0;
    КонецЕсли;
    
    Возврат СтруктураРезультата;
КонецФункции

Обратите внимание на логику работы с множителями: когда мы встречаем слово «тысяча», мы берем всё, что накопили в ТекущийРазряд, умножаем на 1000 и прибавляем к общему Результату. После этого ТекущийРазряд обнуляется, чтобы начать собирать сотни и десятки следующего порядка.

Работа со словарями (соответствиями)

Для корректного сопоставления слов нам необходимо создать справочник всех возможных вариантов написания чисел. В коде 1С это удобнее всего реализовать через серию условий ИначеЕсли или используя объект Соответствие.


Функция ПолучитьЧисловоеЗначение(Слово)
    // Единицы
    Если Слово = "один" Или Слово = "одна" Тогда Возврат 1;
    ИначеЕсли Слово = "два" Или Слово = "две" Тогда Возврат 2;
    // ... и так далее до девяти
    
    // Десятки
    ИначеЕсли Слово = "десять" Тогда Возврат 10;
    ИначеЕсли Слово = "одиннадцать" Тогда Возврат 11;
    // ... и так далее до девятнадцати
    
    // Десятки (20-90)
    ИначеЕсли Слово = "двадцать" Тогда Возврат 20;
    ИначеЕсли Слово = "тридцать" Тогда Возврат 30;
    
    // Сотни (100-900)
    ИначеЕсли Слово = "сто" Тогда Возврат 100;
    ИначеЕсли Слово = "двести" Тогда Возврат 200;
    
    Возврат 0;
КонецФункции

Проблемы OCR и нечеткого поиска

Проанализируем ситуацию, когда текст получен путем распознавания сканированного документа. Часто возникают опечатки: например, «одинадцать» вместо «одиннадцать». Обычное строковое сравнение в этом случае вернет 0, и итоговая сумма будет неверной.

Для решения этой проблемы в профессиональных разработках рекомендуется:

Обработка копеек в разных форматах

Посмотрим на примеры записи дробной части. Копейки могут быть записаны:

  1. Прописью: «... пятьдесят копеек».
  2. Цифрами: «... 50 копеек».
  3. Дробью: «... 50/100».

Чтобы алгоритм был универсальным, перед обработкой слова функцией ПолучитьЧисловоеЗначение, стоит попытаться преобразовать его в число напрямую с помощью Число(Слово) внутри блока Попытка...Исключение. Если преобразование удалось — значит, копейки указаны цифрами, и мы можем сразу добавить их к результату.

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

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

← На главную