При разработке интерфейсов часто возникает задача вывода текстовых сообщений, в которых окончания слов должны зависеть от числового значения. Например, "1 секунда", "3 секунды" или "10 секунд". Стандартный подход с использованием операторов Если...ИначеЕсли или тернарного оператора ?() кажется очевидным, однако существуют ситуации (например, учебные задания или требования к чистоте кода), когда использование условий запрещено или нежелательно. Платформа 1С:Предприятие 8.3 предоставляет мощные встроенные механизмы для решения этой задачи элегантно и в одну строку.
В данной статье мы разберем несколько способов реализации автоматического склонения существительных, проанализируем работу системных функций и выясним, как правильно обрабатывать возвращаемые ими данные.
Это наиболее современный и рекомендуемый способ, появившийся в платформе начиная с версии 8.3.13. Функция ПолучитьСклоненияСтрокиПоЧислу предназначена именно для формирования словосочетаний, где существительное должно быть согласовано с числом.
Рассмотрим структуру этой функции. Она принимает три основных параметра:
Разберем практический пример реализации склонения для часов и минут, который обсуждался на форуме. Обратите внимание, что функция всегда возвращает объект типа Массив. Это связано с тем, что в некоторых языках для одного и того же числа может существовать несколько вариантов склонения. Для русского языка нас всегда будет интересовать первый элемент массива — индекс [0].
// Предположим, у нас есть рассчитанные значения времени
КоличествоЧасов = 21;
КоличествоМинут = 1;
// Получаем склонение для часов
МассивСклоненийЧас = ПолучитьСклоненияСтрокиПоЧислу("час", КоличествоЧасов, , "ПД=Именительный");
РезультатЧас = МассивСклоненийЧас[0]; // "часа"
// Получаем склонение для минут
МассивСклоненийМин = ПолучитьСклоненияСтрокиПоЧислу("минута", КоличествоМинут, , "ПД=Именительный");
РезультатМин = МассивСклоненийМин[0]; // "минута"
// Формируем итоговую строку
ТекстВывода = "" + КоличествоЧасов + " " + РезультатЧас + " " + КоличествоМинут + " " + РезультатМин;
Сообщить(ТекстВывода); // Выведет: 21 час 1 минута
Проанализируем возможность сокращения этого кода. В функции ПолучитьСклоненияСтрокиПоЧислу есть параметр представления ДП (Добавить Пояснение). Если установить его в значение Истина, платформа сама добавит число перед словом. Это избавит нас от необходимости вручную склеивать (конкатенировать) числа и строки.
// Краткий вариант без ручной склейки
ЧасыТекст = ПолучитьСклоненияСтрокиПоЧислу("час", ЧасЗначение, "ДП=Истина", "ПД=Именительный")[0];
МинутыТекст = ПолучитьСклоненияСтрокиПоЧислу("минута", МинутаЗначение, "ДП=Истина", "ПД=Именительный")[0];
СекундыТекст = ПолучитьСклоненияСтрокиПоЧислу("секунда", СекундаЗначение, "ДП=Истина", "ПД=Именительный")[0];
Сообщить(ЧасыТекст + " " + МинутыТекст + " " + СекундыТекст);
Существует еще один профессиональный способ, который часто используется при разработке тиражных решений. Функция НСтр (строка на разных языках) поддерживает специальный синтаксис для работы со множественными числами. Это позволяет избежать создания массивов и обращения к ним по индексу.
Синтаксис форматной строки выглядит так: ru = 'форма1;; форма2;; форма3'. Платформа автоматически выберет нужный фрагмент в зависимости от переданного числа. Посмотрим на пример:
Количество = 5;
// Синтаксис: 1 - единственное число, 2 - от двух до четырех, 5 - пять и более
Текст = НСтр("ru = '%1 секунда;; %1 секунды;; %1 секунд'", Количество);
Сообщить(Текст); // Выведет: 5 секунд
Этот метод считается максимально "чистым", так как он не содержит логических ветвлений внутри программного кода 1С, перенося всю логику выбора формы слова в ресурсную строку. Рассмотрим, как это применить к нашей задаче:
ТекстЧасы = СтрШаблон(НСтр("ru = '%1 час;; %1 часа;; %1 часов'"), ЧасХ);
ТекстМинуты = СтрШаблон(НСтр("ru = '%1 минута;; %1 минуты;; %1 минут'"), МинутаХ);
ТекстСекунды = СтрШаблон(НСтр("ru = '%1 секунда;; %1 секунды;; %1 секунд'"), СекундаХ);
Сообщить(ТекстЧасы + " " + ТекстМинуты + " " + ТекстСекунды);
Важно разобраться, почему при использовании ПолучитьСклоненияСтрокиПоЧислу новички часто допускают ошибки. Как было замечено в обсуждении, если попытаться поместить результат функции в другой массив без указания индекса, получится "массив массивов".
Выясним причину: ПолучитьСклоненияСтрокиПоЧислу возвращает список всех возможных вариантов склонения для заданного падежа. Если вы создаете свой собственный массив _Вывод = Новый Массив(); и присваиваете его элементам результат функции (например, _Вывод[0] = ПолучитьСклонения...), то в первой ячейке вашего массива будет лежать не строка, а другой массив. Именно поэтому для получения текста нужно обращаться к двойному индексу: _Вывод[0][0].
Правильное правило работы: Результат функции — это всегда коллекция. Даже если там один вариант слова, извлекайте его через [0] сразу при получении.
Чтобы получить значения часов, минут и секунд для задачи "время до конца суток", разберем эффективный способ вычисления без использования сложных математических операций. Проанализируем пример кода:
// Вычисляем разницу между концом дня и текущим моментом
// КонецДня(ТекущаяДата()) возвращает время 23:59:59
// Добавим 1 секунду, чтобы получить честную разницу до 00:00:00 следующего дня
ОстатокВСекундах = (КонецДня(ТекущаяДата()) + 1) - ТекущаяДата();
// Используем пустую дату (00010101000000) для преобразования секунд в компоненты времени
ВремяОбъект = '00010101' + ОстатокВСекундах;
ТекЧас = Час(ВремяОбъект);
ТекМин = Минута(ВремяОбъект);
ТекСек = Секунда(ВремяОбъект);
Этот подход позволяет быстро получить числовые значения, которые затем можно передать в функции склонения, описанные выше. Таким образом, мы получаем комплексное решение задачи, полностью соответствующее условию "без циклов и условных операторов".