Как вывести число прописью на английском языке с дефисами и союзом and в 1С:Предприятие

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

При формировании печатных форм документов для иностранных контрагентов (например, инвойсов) разработчики часто сталкиваются с жесткими требованиями к оформлению финансовых показателей. В английском языке правила написания числительных строго регламентированы. Согласно правилам грамматики (как в американском en_US, так и в британском en_GB вариантах английского языка), составные числительные от 21 до 99 должны писаться через дефис (например, twenty-four, thirty-six). Кроме того, перед десятками и единицами в каждом разряде, а также перед центами принято ставить союз and.

Стандартная функция платформы 1С ЧислоПрописью() при базовых настройках выдает упрощенный вариант без дефисов и союза and (например, "Twenty four thousand one hundred thirty six"). В этой статье мы подробно разберем, как решить эту проблему с помощью современных штатных механизмов платформы 1С и эффективной обработки строк.

Причина проблемы: почему стандартные настройки не дают нужного результата?

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

Давайте рассмотрим, как решить задачу комплексно: сначала заставим платформу выводить союз and на его законных местах, а затем разберем способы расстановки дефисов — от классических методов замены строк до максимально производительного современного решения на регулярных выражениях.

---

Шаг 1. Автоматический вывод союза "and" (Классическая пропись)

Начнем с союза and. Мало кто знает, но в платформе 1С:Предприятие для англоязычных локализаций существует специальный параметр форматирования — ИИ (в англоязычной нотации — AU). Этот параметр управляет использованием классической (полной) или упрощенной прописи:

Проанализируем пример использования этого параметра:


// Формируем классическую пропись с союзом "and"
ФорматнаяСтрока = "L=en_US; ДП=Истина; ИИ=Использовать";
ПараметрыВалюты = "dollar, dollars, cent, cents, 2";
Результат = ЧислоПрописью(1234.56, ФорматнаяСтрока, ПараметрыВалюты);

// Полученный результат:
// "One thousand two hundred and thirty four dollars and fifty six cents"

Как мы видим, союз and автоматически встал на свои места: перед десятками долларов (and thirty four) и перед центами (and fifty six). Однако составные числительные по-прежнему выводятся через пробел. Перейдем к решении задачи с дефисами.

---

Шаг 2. Расстановка дефисов в числительных от 21 до 99

Для корректного преобразования пробелов в дефисы в составных числах существует три основных подхода. Рассмотрим их от простых и компромиссных к самым современным и быстродействующим.

Вариант А. Быстрая замена строк (для простых случаев)

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

Рассмотрим код этого решения:


ПредставлениеСуммы = ЧислоПрописью(Сумма, "L=en_US; ДП=Истина; ИИ=Использовать", "dollar, dollars, cent, cents, 2");

// Выполняем цепочку замен для расстановки дефисов
ПредставлениеСуммы = СтрЗаменить(ПредставлениеСуммы, "ty ", "ty-");
// Возвращаем пробелы там, где дефис не нужен (перед миллионами, тысячами и валютой)
ПредставлениеСуммы = СтрЗаменить(ПредставлениеСуммы, "ty-million", "ty million");
ПредставлениеСуммы = СтрЗаменить(ПредставлениеСуммы, "ty-thousand", "ty thousand");
ПредставлениеСуммы = СтрЗаменить(ПредставлениеСуммы, "ty-dollar", "ty dollar");

Преимущества: Высокая скорость работы и простота реализации. Не требует современных версий платформы и работает на любых релизах 1С v8.

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

---

Вариант Б. Перебор числительных циклом (классический точный метод)

Чтобы гарантировать стопроцентную точность без риска задеть лишние слова, можно использовать точечную замену числительных от 21 до 99. Для этого мы в цикле получаем прописной вариант каждого составного числа и заменяем его пробел на дефис в итоговой строке.

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


Процедура ПреобразоватьПредставлениеПоПравилу(ПредставлениеСуммы)
    
    // Перебираем все возможные составные числительные от 21 до 99
    Для Итератор = 21 По 99 Цикл 
        
        // Проверяем, делится ли число на 10 (числа типа 30, 40, 50 пишутся без дефиса)
        Если Итератор % 10 = 0 Тогда
            Продолжить;
        КонецЕсли;
        
        // Получаем написание текущего составного числительного на английском языке
        ТекПредставление = ЧислоПрописью(Итератор, "L=en_US; НП=Ложь;", ",,,,0");
        
        // Обрабатываем вариант с заглавной буквы (если число стоит в начале строки)
        Если СтрНайти(ПредставлениеСуммы, ТекПредставление) > 0 Тогда
            НовоеПредставление = СтрЗаменить(ТекПредставление, " ", "-");
            ПредставлениеСуммы = СтрЗаменить(ПредставлениеСуммы, ТекПредставление, НовоеПредставление);
        КонецЕсли;
        
        // Обрабатываем вариант в нижнем регистре (для середины строки)
        ТекПредставлениеНРег = НРег(ТекПредставление);
        Если СтрНайти(ПредставлениеСуммы, ТекПредставлениеНРег) > 0 Тогда
            НовоеПредставлениеНРег = СтрЗаменить(ТекПредставлениеНРег, " ", "-");
            ПредставлениеСуммы = СтрЗаменить(ПредставлениеСуммы, ТекПредставлениеНРег, НовоеПредставлениеНРег);
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

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

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

---

Вариант В. Использование регулярных выражений (Самый современный и оптимальный метод)

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

Для решения нашей задачи мы воспользуемся механизмом регулярного выражения с ретроспективной ((?<=...)) и опережающей ((?=...)) проверками. Мы будем искать только те пробелы, перед которыми стоит десяток (от twenty до ninety) и после которых идет единица (от one до nine).

Разберем готовый шаблон регулярного выражения:

(?<=\b(?:[Tt]wenty|[Tt]hirty|[Ff]orty|[Ff]ifty|[Ss]ixty|[Ss]eventy|[Ee]ighty|[Nn]inety))\s+(?=(?:[Oo]ne|[Tt]wo|[Tt]hree|[Ff]our|[Ff]ive|[Ss]ix|[Ss]even|[Ee]ight|[Nn]ine)\b)

Этот шаблон работает следующим образом:

  1. Конструкция (?<=\b(?:...)) проверяет, что перед пробелом находится граница слова и одно из названий десятков (с учетом регистра).
  2. Символ \s+ находит один или несколько пробельных символов между десятком и единицей.
  3. Конструкция (?=(?:...)\b) проверяет, что сразу после пробела идет одно из названий единиц и граница слова.

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


// 1. Формируем исходную пропись с использованием союза "and"
ФорматнаяСтрока = "L=en_US; ДП=Истина; ИИ=Использовать";
ПараметрыВалюты = "dollar, dollars, cent, cents, 2";
Пропись = ЧислоПрописью(24136.69, ФорматнаяСтрока, ПараметрыВалюты); 
// Базовый результат: 
// "Twenty four thousand one hundred and thirty six dollars and sixty nine cents"

// 2. Определяем шаблон регулярного выражения для поиска нужных пробелов
ШаблонДефисов = "(?<=\b(?:[Tt]wenty|[Tt]hirty|[Ff]orty|[Ff]ifty|[Ss]ixty|[Ss]eventy|[Ee]ighty|[Nn]inety))\s+(?=(?:[Oo]ne|[Tt]wo|[Tt]hree|[Ff]our|[Ff]ive|[Ss]ix|[Ss]even|[Ee]ight|[Nn]ine)\b)";

// 3. Выполняем замену нативного движка регулярных выражений 1С
ИтоговыйТекст = СтрЗаменитьПоРегулярномуВыражению(Пропись, ШаблонДефисов, "-");

// Итоговый корректный результат:
// "Twenty-four thousand one hundred and thirty-six dollars and sixty-nine cents"

Преимущества:

---

Резюме и рекомендации

Для получения корректной английской прописи в соответствии со всеми правилами финансовой грамматики мы рекомендуем придерживаться следующих правил:

  1. Всегда используйте параметр форматирования ИИ=Использовать (или AU), чтобы платформа автоматически расставляла союз and.
  2. Если вы работаете на современных версиях платформы 1С:Предприятие (начиная с 8.3.23), используйте функцию СтрЗаменитьПоРегулярномуВыражению с предложенным паттерном. Это наиболее производительный и чистый с точки зрения кода подход.
  3. Если ваша база работает на более старых версиях платформы (до 8.3.23), используйте быстрый вариант последовательной замены подстрок с восстановлением исключений (Вариант А). Это убережет ваши серверные процессы от лишней нагрузки, которую создают ресурсоемкие циклы.
← На главную