При формировании печатных форм договоров, актов или накладных разработчики часто сталкиваются с необходимостью вывести количество товара или услуг прописью в косвенном падеже. Например, распространенный шаблон в договорах: «купили телевизор в количестве 1 (Одной) единицы» или «в количестве 5 (Пяти) единиц».
Стандартная функция ЧислоПрописью по умолчанию формирует текст в именительном падеже. Если использовать ее напрямую для вывода единиц измерения, мы получим грамматически некорректные конструкции вроде «один единиц» или «два единиц». В этой статье мы подробно разберем, как решить эту проблему программными средствами в среде 1С:Предприятие различных версий.
Если вы работаете на современной версии платформы (начиная с релиза 8.3.14.1565), задача решается буквально одной строкой кода. Разработчики платформы добавили мощную встроенную функцию ПолучитьСклоненияСтрокиПоЧислу, которая идеально подходит под наши требования.
Эта функция самостоятельно связывает числительное с существительным, склоняет их в нужный падеж и форматирует результат. Давайте разберем по шагам параметры этого метода:
"единица, единицы, единиц, ж" (где «ж» указывает на женский род).ПД) и способ представления самого числа (параметр ПЧ).Проанализируем конкретный пример использования этого метода для вывода количества единиц в родительном падеже:
// Пример получения строки в родительном падеже для разных чисел
Для Каждого ТекущееЧисло Из Новый Массив() Цикл
// Добавим для проверки несколько чисел
МассивЧисел = Новый Массив;
МассивЧисел.Добавить(1);
МассивЧисел.Добавить(2);
МассивЧисел.Добавить(5);
МассивЧисел.Добавить(21);
Для Каждого Кол Из МассивЧисел Цикл
ПараметрыПредмета = "единица, единицы, единиц, ж";
ФорматнаяСтрока = "ПД = Родительный; ПЧ = ЧислоПрописью";
РезультатМассив = ПолучитьСклоненияСтрокиПоЧислу(
"телевизор",
Кол,
ПараметрыПредмета,
"ЧС=Количественное",
ФорматнаяСтрока
);
// Метод возвращает массив вариантов склонения, нам нужен первый элемент
Если РезультатМассив.Количество() > 0 Тогда
Сообщить("Для числа " + Кол + ": " + РезультатМассив[0]);
КонецЕсли;
КонецЦикла;
КонецЦикла;
В результате выполнения этого кода мы получим грамматически верные конструкции:
Если ваша база работает на версии платформы 8.3.13, функции ПолучитьСклоненияСтрокиПоЧислу в ней еще нет, но уже присутствует функция ПолучитьСклоненияСтроки. Мы можем скомбинировать её со стандартной функцией ЧислоПрописью.
Рассмотрим пример реализации этой логики:
ФормСтрока = "Л = ru_RU; НД = Ложь";
ПарПредмета = "единица,единицы,единиц,ж,,,,,0";
Для инд = 1 По 5 Цикл
// Сначала получаем стандартную пропись числа с единицей измерения в именительном падеже
ИсходнаяПропись = ЧислоПрописью(инд, ФормСтрока, ПарПредмета);
// Склоняем полученную фразу целиком в родительный падеж
МассивСклонений = ПолучитьСклоненияСтроки(ИсходнаяПропись, , "ПД = Родительный");
Если МассивСклонений.Количество() > 0 Тогда
Сообщить("Число " + инд + " в родительном падеже: " + МассивСклонений[0]);
КонецЕсли;
КонецЦикла;
Этот способ также отлично справляется со своей задачей на любых разрядах чисел, автоматически преобразуя «одна единица» в «одной единицы», а «двадцать две единицы» в «двадцати двух единиц».
Выясним, как поступить, если ваша конфигурация работает на старой версии платформы, где встроенные функции склонения полностью отсутствуют, а обновить платформу нет возможности. В этом случае нам придется написать собственный строковый парсер. Если техническая возможность перехода на новые релизы сохраняется, можно автоматизировать архивирование и обновление нескольких баз 1С в тихом режиме.
Идея заключается в следующем: мы получаем стандартную пропись числа с помощью ЧислоПрописью, разбиваем её на слова, находим последнее слово и программно меняем его окончание и падеж в зависимости от логики русского языка.
Разберем реализацию этого алгоритма с помощью набора вспомогательных функций:
// Функция делает первую букву строки заглавной
Функция стрПерваяБукваЗаглавная(мСтрока) Экспорт
мНоваяСтрока = "";
мПерваяБуква = ВРег(СокрЛП(Сред(мСтрока, 1, 1)));
мОстаток = НРег(СокрЛП(Сред(мСтрока, 2, СтрДлина(мСтрока))));
мНоваяСтрока = мПерваяБуква + мОстаток;
Возврат мНоваяСтрока;
КонецФункции
// Функция возвращает последнее слово из переданной строки
Функция стрПолучитьПоследнееСловоИзСтроки(Слово) Экспорт
мСтрока = Слово;
Пока СтрЧислоВхождений(СокрЛП(мСтрока), " ") > 0 Цикл
мСтрока = Сред(мСтрока, Найти(мСтрока, " ") + 1, СтрДлина(мСтрока));
КонецЦикла;
Возврат СокрЛП(мСтрока);
КонецФункции
// Функция возвращает всю строку, кроме последнего слова
Функция стрПолучитьСловаДоПоследнегоИзСтроки(Слово) Экспорт
мСтрока = Слово;
ДлинаСтроки = СтрДлина(мСтрока);
ПоследСлово = стрПолучитьПоследнееСловоИзСтроки(Слово);
ДлинаПоследСлова = СтрДлина(ПоследСлово);
ДлинаСтрокиДоСлова = ДлинаСтроки - ДлинаПоследСлова;
мСтрока = Сред(мСтрока, 1, ДлинаСтрокиДоСлова);
Возврат СокрЛП(мСтрока);
КонецФункции
Теперь объединим эти функции в единый блок логики, который будет анализировать корень слова «единица» и подставлять нужные окончания для родительного падежа:
// Основная процедура формирования фразы
Функция ПолучитьЕдиницыПрописьюВРодительномПадеже(мЧисло) Экспорт
Корень = "наименован"; // Базовый корень для изменения
Фраза = "";
Если (мЧисло >= 10) и (мЧисло <= 20) Тогда
ЧислоПрописью = НРег(Формат(мЧисло, "ЧП"));
Корень = "единиц";
Фраза = стрПерваяБукваЗаглавная(ЧислоПрописью) + " " + Корень;
Иначе
ВсеЧислоПрописью = НРег(Формат(мЧисло, "ЧП"));
Если мЧисло > 20 Тогда
ПоследняяЦифраЧислом = мЧисло % 10;
ПервыеЦифрыПрописью = стрПолучитьСловаДоПоследнегоИзСтроки(ВсеЧислоПрописью);
ПоследняяЦифраПрописью = стрПолучитьПоследнееСловоИзСтроки(ВсеЧислоПрописью);
Иначе // Меньше 10
ПоследняяЦифраЧислом = мЧисло;
ПервыеЦифрыПрописью = "";
ПоследняяЦифраПрописью = НРег(Формат(мЧисло, "ЧП"));
КонецЕсли;
// Корректируем окончания для родительного падежа ("единицы", "единиц")
Если ПоследняяЦифраЧислом = 1 Тогда
ПоследняяЦифраПрописью = "одной";
Корень = "единицы";
ИначеЕсли (ПоследняяЦифраЧислом >= 2) и (ПоследняяЦифраЧислом <= 4) Тогда
// Например: двух, трех, четырех
Если ПоследняяЦифраЧислом = 2 Тогда
ПоследняяЦифраПрописью = "двух";
ИначеЕсли ПоследняяЦифраЧислом = 3 Тогда
ПоследняяЦифраПрописью = "трех";
ИначеЕсли ПоследняяЦифраЧислом = 4 Тогда
ПоследняяЦифраПрописью = "четырех";
КонецЕсли;
Корень = "единиц";
Иначе
// Для 5-9, а также круглых десятков
Если ПоследняяЦифраЧислом = 5 Тогда ПоследняяЦифраПрописью = "пяти";
ИначеЕсли ПоследняяЦифраЦислом = 6 Тогда ПоследняяЦифраПрописью = "шести";
ИначеЕсли ПоследняяЦифраЦислом = 7 Тогда ПоследняяЦифраПрописью = "семи";
ИначеЕсли ПоследняяЦифраЦислом = 8 Тогда ПоследняяЦифраПрописью = "восьми";
ИначеЕсли ПоследняяЦифраЦислом = 9 Тогда ПоследняяЦифраПрописью = "девяти";
ИначеЕсли ПоследняяЦифраЧислом = 0 Тогда ПоследняяЦифраПрописью = "ноля";
КонецЕсли;
Корень = "единиц";
EndЕсли;
ВсеЧислоПрописью = СокрЛП(ПервыеЦифрыПрописью + " " + ПоследняяЦифраПрописью);
Фраза = СокрЛП(стрПерваяБукваЗаглавная(ВсеЧислоПрописью) + " " + Корень);
КонецЕсли;
Возврат Фраза;
КонецФункции
Важное примечание к Способу 3: Этот ручной метод требует скрупулёзной отладки числительных (особенно составных чисел вроде 121, 1002 и т.д.). Его стоит использовать только как крайнюю меру в устаревших системах, лишенных БСП и современных версий платформы.
Если вы работаете в конфигурации, где внедрена БСП (например, «Управление торговлей», «Бухгалтерия предприятия 3.0», «ERP»), склонение словосочетаний можно выполнить с помощью функций общего модуля БСП СклонениеПредставленийОбъектов.
Для этого используется следующая конструкция:
// Пример склонения через БСП
ИсходныйТекст = "одна единица";
ПадежРодительный = 2; // Код родительного падежа
РезультатСклонения = СклонениеПредставленийОбъектов.ПросклонятьПредставление(ИсходныйТекст, ПадежРодительный);
Сообщить(РезультатСклонения); // Выведет "одной единицы"
Преимущество этого метода в том, что БСП использует под капотом либо встроенные механизмы платформы, либо поставляемую внешнюю компоненту склонения (NameDecl), что гарантирует высокую точность результатов без необходимости писать громоздкий код разбора строк.
Подводя итоги, дадим рекомендации по выбору инструмента:
ПолучитьСклоненияСтрокиПоЧислу — это самый быстрый, надежный и производительный метод.ПолучитьСклоненияСтроки и ЧислоПрописью.СклонениеПредставленийОбъектов.