При формировании печатных форм, отчетов или отправке уведомлений пользователям разработчики часто сталкиваются с необходимостью согласования числительных с существительными. Статичный текст выглядит непрофессионально: конструкции вида «на 1 календарных дней», «на 2 календарных дней» или «получено 5 пакета» портят интерфейс и печатные документы. В русском языке окончания слов зависят от передаваемого числа, и ручной разбор всех возможных окончаний часто перегружает код.
В этой статье мы подробно разберем, как решить задачу автоматического склонения слов в зависимости от полученного количества в платформе «1С:Предприятие 8». Мы рассмотрим как современные платформенные механизмы, так и универсальные алгоритмы, которые будут работать на абсолютно любой, даже самой старой версии платформы.
СтрокаСЧисломНачиная с версии платформы 8.3.10.2168, в глобальном контексте появился крайне удобный метод СтрокаСЧислом. Эта функция предназначена для формирования представлений чисел с учетом правил локализации (языка интерфейса) и грамматических категорий числительных.
Синтаксис функции выглядит следующим образом:
СтрокаСЧислом(<Шаблон>, <Число>, <ВидЧисла>, <ФорматнаяСтрока>)
Разберем параметры функции подробнее:
Строка) — это строка, содержащая разделенные точкой с запятой (;) формы слова для разных категорий чисел. Всего таких категорий шесть: Ноль, Один, Два, Немного, Много, Другое. Порядок следования строго фиксирован. Если в выбранном языке какая-то категория не используется, соответствующий раздел просто оставляют пустым, но разделитель «точка с запятой» обязательно сохраняют. Символ %1 внутри шаблона указывает место, куда будет подставлено само число.Число) — количественное значение, которое необходимо согласовать со словом.ВидЧисловогоЗначения) — системное перечисление. Обычно используется значение ВидЧисловогоЗначения.Количественное для обычного счета или ВидЧисловогоЗначения.Порядковое для порядковых числительных.Строка) — задает локализацию (параметр Л или 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 календарного дня"
ПолучитьСклоненияСтрокиПоЧислу (с версии 8.3.14)Если вам требуется не просто подставить слово в нужной форме, а полностью просклонять целое словосочетание по падежам совместно с числительным (например, вывести в акте фразу «в количестве пятисот двадцати трех рублей»), то на помощь приходит метод ПолучитьСклоненияСтрокиПоЧислу. Он появился в платформе начиная с версии 8.3.14.1565.
Этот метод избавляет от необходимости писать сложные шаблоны вручную, так как платформа обращается к системному словарю склонений.
Синтаксис метода:
ПолучитьСклоненияСтрокиПоЧислу(<СклоняемаяСтрока>, <Число>, <СклоняемыеЕдиницыИзмерения>, <ОписаниеСтроки>, <ФорматнаяСтрока>, <ФорматнаяСтрокаЧисла>)
Основные параметры:
"ЧС=Количественное; Л=ru_RU".ПД) и представлением числа (параметр ПЧ). Параметр ПД может принимать значения: Именительный, Родительный, Дательный, Винительный, Творительный, Предложный. Параметр ПЧ определяет формат вывода самого числа:
Число — число выводится цифрами (например, "15 календарным дням").ЧислоПрописью — число выводится словами ("пятнадцати календарным дням").ЧислоСОкончанием — число выводится цифрами с буквенным наращением ("15-ти календарным дням").Метод возвращает Массив строк. В большинстве реальных задач разработчику нужен самый первый элемент этого массива с индексом [0]. Рассмотрим пример реализации:
// Склонение словосочетания "календарный день" в родительном падеже
Количество = 5;
СклоняемаяСтрока = "календарный день";
ПараметрыОписания = "ЧС=Количественное; Л=ru_RU";
ПараметрыФормата = "ПД=Родительный; ПЧ=Число"; // Выведет число цифрами в родительном падеже
РезультатМассив = ПолучитьСклоненияСтрокиПоЧислу(СклоняемаяСтрока, Количество, , ПараметрыОписания, ПараметрыФормата);
Если РезультатМассив.Количество() > 0 Тогда
СтрокаПечати = "Срок проведения не может превышать " + РезультатМассив[0];
// Результат: "Срок проведения не может превышать 5 календарных дней"
КонецЕсли;
Важное примечание по производительности: Начиная с версии платформы 8.3.16, алгоритм выполнения функций склонения строк был оптимизирован. Теперь эти методы возвращают не более 10 наиболее подходящих вариантов склонения (ранее возвращались все возможные варианты, что могло приводить к задержкам при генерации объемных отчетов). Это изменение значительно ускорило работу серверных вызовов при формировании печатных форм.
ЧислоПрописью и параметров предмета исчисленияДо появления специализированных функций склонения в платформе традиционно использовался метод ЧислоПрописью. Его можно успешно применять для получения правильного окончания существительного, даже если само число прописью нам выводить не нужно.
Для этого в третий параметр метода (ПараметрыПредметаИсчисления) передается специальным образом сконструированная строка формата. Она описывает правила склонения единиц измерения для мужского, женского или среднего рода.
Формат строки параметров предмета исчисления выглядит так:
"ЕдиницаЦелаяМужскойЖенскийСредний, Форма1, Форма2, Форма5, ЕдиницаДробная..."
Рассмотрим, как использовать этот метод, чтобы получить только согласованное существительное, отбросив числовое представление прописью. Для этого мы можем передать число, получить общую строку и заменить текстовую часть числа на цифровой формат:
// Функция для получения согласованного слова "день" через ЧислоПрописью
Функция ПолучитьПредметИсчисленияДней(Знач ЧислоДней) Экспорт
// Описываем параметры предмета исчисления для слова "день" (мужской род, день, дня, дней)
ПараметрыПредмета = "день, дня, дней, м, , , , , 0";
ФорматнаяСтрока = "Л = ru_RU; НД = Ложь"; // НД=Ложь убирает вывод дробной части, если она нулевая
// Получаем полное представление числа прописью вместе с единицей измерения
ПолныйТекст = ЧислоПрописью(ЧислоДней, ФорматнаяСтрока, ПараметрыПредмета);
// ПолныйТекст вернет, например, "Двадцать один день" или "Пять дней"
// Если нам нужно именно число цифрами + правильная форма слова:
// Найдем последнее слово в строке (это и будет наше существительное)
МассивСлов = СтрРазделить(ПолныйТекст, " ", Ложь);
ФормаСлова = МассивСлов[МассивСлов.ВГРАНИЦУ()];
Возврат Формат(ЧислоДней, "ЧГ=0") + " " + НРег(ФормаСлова);
КонецФункции
// Применение функции:
Сообщить(ПолучитьПредметИсчисленияДней(1)); // "1 день"
Сообщить(ПолучитьПредметИсчисленияДней(14)); // "14 дней"
Сообщить(ПолучитьПредметИсчисленияДней(102));// "102 дня"
Если вы ведете разработку на старой версии платформы (например, на 8.3.10.2580 или более ранних, где новые функции склонения могут быть недоступны или работать некорректно в зависимости от сборки), задачу склонения целых чисел можно легко решить с помощью чистого математического расчета.
Этот способ основан на анализе остатка от деления числа на 10 и 100. Он работает мгновенно, не требует обращения к системным словарям локализации и гарантирует стабильность на любой конфигурации 1С.
Рассмотрим алгоритм выбора правильной формы слова:
Реализуем этот универсальный алгоритм в виде функции на языке 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 календарных дня"
Если конфигурация, в которой вы работаете, построена на базе БСП (а это практически все современные типовые конфигурации фирмы 1С: «Бухгалтерия предприятия», «ERP Управление предприятием», «Управление торговлей» и др.), то в вашем распоряжении есть готовые общие модули.
Наиболее современной и рекомендуемой к использованию является функция СтрокаСЧисломДляЛюбогоЯзыка общего модуля СтроковыеФункцииКлиентСервер.
Пример использования функции БСП в коде:
ЧислоМинут = 15;
// Формируем мультиязычный шаблон
ШаблонДляБСП = НСтр("ru = ';%1 минута;;%1 минуты;%1 минут;%1 минуты'");
СтрокаМинут = СтроковыеФункцииКлиентСервер.СтрокаСЧисломДляЛюбогоЯзыка(ШаблонДляБСП, ЧислоМинут);
// Результат: "15 минут"
Важное предостережение для разработчиков: Ранее в старых версиях БСП для решения этой задачи использовались функции ФормаМножественногоЧисла() и ЧислоЦифрамиПредметИсчисленияПрописью(). На данный момент в актуальных версиях библиотеки они официально объявлены устаревшими (deprecated), поддержка их в будущем может быть прекращена. Настоятельно рекомендуется заменять их в коде на СтрокаСЧисломДляЛюбогоЯзыка() или на стандартные вызовы методов платформы.
Выбор оптимального метода склонения существительных зависит от системных требований вашей конфигурации:
ПолучитьСклоненияСтрокиПоЧислу. Это наиболее мощный и современный инструмент платформы.СтрокаСЧислом или обертка БСП СтроковыеФункцииКлиентСервер.СтрокаСЧисломДляЛюбогоЯзыка().ПолучитьФормуМножественногоЧисла.