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

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

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

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

Решение 1. Использование встроенной функции СтрокаСЧислом

Начиная с версии платформы 8.3.10.2168, в глобальном контексте появился крайне удобный метод СтрокаСЧислом. Эта функция предназначена для формирования представлений чисел с учетом правил локализации (языка интерфейса) и грамматических категорий числительных.

Синтаксис функции выглядит следующим образом:

СтрокаСЧислом(<Шаблон>, <Число>, <ВидЧисла>, <ФорматнаяСтрока>)

Разберем параметры функции подробнее:

  1. Шаблон (обязательный, тип Строка) — это строка, содержащая разделенные точкой с запятой (;) формы слова для разных категорий чисел. Всего таких категорий шесть: Ноль, Один, Два, Немного, Много, Другое. Порядок следования строго фиксирован. Если в выбранном языке какая-то категория не используется, соответствующий раздел просто оставляют пустым, но разделитель «точка с запятой» обязательно сохраняют. Символ %1 внутри шаблона указывает место, куда будет подставлено само число.
  2. Число (обязательный, тип Число) — количественное значение, которое необходимо согласовать со словом.
  3. ВидЧисла (обязательный, тип ВидЧисловогоЗначения) — системное перечисление. Обычно используется значение ВидЧисловогоЗначения.Количественное для обычного счета или ВидЧисловогоЗначения.Порядковое для порядковых числительных.
  4. ФорматнаяСтрока (необязательный, тип Строка) — задает локализацию (параметр Л или L), например, L=ru_RU, а также параметры округления дробной части (ЧДЦ).

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

Для русского языка шаблон склонения слова «день» будет выглядеть следующим образом:

";%1 день;;%1 дня;%1 дней;%1 дня"

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

Давайте посмотрим на практический пример использования этой функции в коде 1С:


// Пример вывода количества календарных дней
ЧислоДней = 21; // Значение может быть получено программно
ШаблонСклонения = ";%1 календарный день;;%1 календарных дня;%1 календарных дней;%1 календарного дня";

РезультатСтрока = СтрокаСЧислом(ШаблонСклонения, ЧислоДней, ВидЧисловогоЗначения.Количественное, "L=ru_RU");
// Результат: "21 календарный день"

ЧислоДнейДробь = 4.5;
РезультатДробь = СтрокаСЧислом(ШаблонСклонения, ЧислоДнейДробь, ВидЧисловогоЗначения.Количественное, "L=ru_RU");
// Результат: "4.5 календарного дня"

Решение 2. Современный метод ПолучитьСклоненияСтрокиПоЧислу (с версии 8.3.14)

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

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

Синтаксис метода:

ПолучитьСклоненияСтрокиПоЧислу(<СклоняемаяСтрока>, <Число>, <СклоняемыеЕдиницыИзмерения>, <ОписаниеСтроки>, <ФорматнаяСтрока>, <ФорматнаяСтрокаЧисла>)

Основные параметры:

Метод возвращает Массив строк. В большинстве реальных задач разработчику нужен самый первый элемент этого массива с индексом [0]. Рассмотрим пример реализации:


// Склонение словосочетания "календарный день" в родительном падеже
Количество = 5;
СклоняемаяСтрока = "календарный день";
ПараметрыОписания = "ЧС=Количественное; Л=ru_RU";
ПараметрыФормата = "ПД=Родительный; ПЧ=Число"; // Выведет число цифрами в родительном падеже

РезультатМассив = ПолучитьСклоненияСтрокиПоЧислу(СклоняемаяСтрока, Количество, , ПараметрыОписания, ПараметрыФормата);

Если РезультатМассив.Количество() > 0 Тогда
    СтрокаПечати = "Срок проведения не может превышать " + РезультатМассив[0];
    // Результат: "Срок проведения не может превышать 5 календарных дней"
КонецЕсли;

Важное примечание по производительности: Начиная с версии платформы 8.3.16, алгоритм выполнения функций склонения строк был оптимизирован. Теперь эти методы возвращают не более 10 наиболее подходящих вариантов склонения (ранее возвращались все возможные варианты, что могло приводить к задержкам при генерации объемных отчетов). Это изменение значительно ускорило работу серверных вызовов при формировании печатных форм.

Решение 3. Использование функции ЧислоПрописью и параметров предмета исчисления

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

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

Формат строки параметров предмета исчисления выглядит так:

"ЕдиницаЦелаяМужскойЖенскийСредний, Форма1, Форма2, Форма5, ЕдиницаДробная..."

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


// Функция для получения согласованного слова "день" через ЧислоПрописью
Функция ПолучитьПредметИсчисленияДней(Знач ЧислоДней) Экспорт
    
    // Описываем параметры предмета исчисления для слова "день" (мужской род, день, дня, дней)
    ПараметрыПредмета = "день, дня, дней, м, , , , , 0"; 
    ФорматнаяСтрока = "Л = ru_RU; НД = Ложь"; // НД=Ложь убирает вывод дробной части, если она нулевая
    
    // Получаем полное представление числа прописью вместе с единицей измерения
    ПолныйТекст = ЧислоПрописью(ЧислоДней, ФорматнаяСтрока, ПараметрыПредмета);
    
    // ПолныйТекст вернет, например, "Двадцать один день" или "Пять дней"
    // Если нам нужно именно число цифрами + правильная форма слова:
    // Найдем последнее слово в строке (это и будет наше существительное)
    МассивСлов = СтрРазделить(ПолныйТекст, " ", Ложь);
    ФормаСлова = МассивСлов[МассивСлов.ВГРАНИЦУ()];
    
    Возврат Формат(ЧислоДней, "ЧГ=0") + " " + НРег(ФормаСлова);
    
КонецФункции

// Применение функции:
Сообщить(ПолучитьПредметИсчисленияДней(1));  // "1 день"
Сообщить(ПолучитьПредметИсчисленияДней(14)); // "14 дней"
Сообщить(ПолучитьПредметИсчисленияДней(102));// "102 дня"

Решение 4. Универсальный математический алгоритм (для старых версий платформ)

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

Этот способ основан на анализе остатка от деления числа на 10 и 100. Он работает мгновенно, не требует обращения к системным словарям локализации и гарантирует стабильность на любой конфигурации 1С.

Рассмотрим алгоритм выбора правильной формы слова:

  1. Если число оканчивается на промежуток от 11 до 14 (остаток от деления на 100 лежит в диапазоне 11..14), то всегда выбирается форма множественного числа ("дней").
  2. В остальных случаях смотрим на последнюю цифру числа (остаток от деления на 10):
    • Если последняя цифра равна 1, выбирается форма единственного числа ("день").
    • Если последняя цифра лежит в диапазоне от 2 до 4, выбирается родительный падеж единственного числа ("дня").
    • Если последняя цифра равна 5..9 или 0, выбирается форма множественного числа ("дней").

Реализуем этот универсальный алгоритм в виде функции на языке 1С:


// Функция возвращает корректную форму существительного в зависимости от целого числа
Функция ПолучитьФормуМножественногоЧисла(Знач ЧислоЗначение, ФормаОдин, ФормаНесколько, ФормаМного) Экспорт
    
    // Приводим число к целому модулю, чтобы исключить влияние отрицательных значений
    ЧислоЗначение = Цел(Макс(ЧислоЗначение, -ЧислоЗначение));
    
    Остаток100 = ЧислоЗначение % 100;
    Остаток10  = ЧислоЗначение % 10;
    
    // Правило 1: Исключение для чисел, оканчивающихся на 11-14 (11 дней, 112 дней)
    Если Остаток100 >= 11 И Остаток100 <= 14 Тогда
        Возврат ФормаМного;
    // Правило 2: Числа, оканчивающиеся на 1 (кроме 11) - 1 день, 21 день
    ИначеЕсли Остаток10 = 1 Тогда
        Возврат ФормаОдин;
    // Правило 3: Числа, оканчивающиеся на 2, 3, 4 (кроме 12-14) - 2 дня, 34 дня
    ИначеЕсли Остаток10 >= 2 И Остаток10 <= 4 Тогда
        Возврат ФормаНесколько;
    // Правило 4: Все остальные числа (0, 5-9) - 5 дней, 20 дней, 100 дней
    Иначе
        Возврат ФормаМного;
    // КонецЕсли
    
КонецФункции

Пример вызова этой функции в модуле печатной формы:


КоличествоДней = ПолучитьКоличествоДнейПрограммно(); // Например, 32

ФормаДней = ПолучитьФормуМножественногоЧисла(КоличествоДней, "календарный день", "календарных дня", "календарных дней");
СтрокаВывода = "Срок выполнения работ составляет " + КоличествоДней + " " + ФормаДней;
// Результат: "Срок выполнения работ составляет 32 календарных дня"

Решение 5. Использование возможностей БСП (Библиотеки Стандартных Подсистем)

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

Наиболее современной и рекомендуемой к использованию является функция СтрокаСЧисломДляЛюбогоЯзыка общего модуля СтроковыеФункцииКлиентСервер.

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


ЧислоМинут = 15;
// Формируем мультиязычный шаблон
ШаблонДляБСП = НСтр("ru = ';%1 минута;;%1 минуты;%1 минут;%1 минуты'");

СтрокаМинут = СтроковыеФункцииКлиентСервер.СтрокаСЧисломДляЛюбогоЯзыка(ШаблонДляБСП, ЧислоМинут);
// Результат: "15 минут"

Важное предостережение для разработчиков: Ранее в старых версиях БСП для решения этой задачи использовались функции ФормаМножественногоЧисла() и ЧислоЦифрамиПредметИсчисленияПрописью(). На данный момент в актуальных версиях библиотеки они официально объявлены устаревшими (deprecated), поддержка их в будущем может быть прекращена. Настоятельно рекомендуется заменять их в коде на СтрокаСЧисломДляЛюбогоЯзыка() или на стандартные вызовы методов платформы.

Резюме и рекомендации по выбору решения

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

← На главную