При разработке отчетов в системе компоновки данных (СКД) программисты часто сталкиваются с задачей отображения временных интервалов. Например, время работы оборудования или производственного цикла может составлять 45.5 часов. Стандартное приведение к типу Дата с форматом ДФ=ЧЧ:мм здесь не поможет, так как платформа при превышении 24 часов автоматически перекинет «лишнее» время в сутки, и вместо ожидаемых «45:30» пользователь увидит «21:30» (одни сутки отбросятся). В этой статье мы подробно разберем, как обойти это ограничение и корректно вывести длительность в человекочитаемом виде, сохранив при этом возможность расчета итогов.
Рассмотрим ситуацию: у нас есть числовое поле ВремяЦикла, значение которого равно 25.5. Мы хотим видеть в отчете «25:30». Если мы попытаемся в запросе прибавить это число (в секундах) к пустой дате '0001-01-01' и задать формат в СКД, то получим «01:30», так как 24 часа превратятся в полноценный день, который формат ЧЧ просто не отображает. Наша задача — заставить систему вывести общее количество часов, не ограничиваясь сутками.
Это классический и наиболее гибкий подход. Мы создаем функцию, которая принимает число (минуты или секунды) и возвращает красиво оформленную строку. Проанализируем пример функции, которую можно разместить в общем модуле с признаком Сервер, Внешнее соединение и Клиент (сервер):
Функция ПреобразоватьЧислоВЧасыМинуты(Знач ЧислоМинут) Экспорт
Если ЧислоМинут = 0 Или ЧислоМинут = Неопределено Тогда
Возврат "00:00";
КонецЕсли;
ЦелоеКоличествоЧасов = Цел(ЧислоМинут / 60);
ОстатокМинут = ЧислоМинут - (ЦелоеКоличествоЧасов * 60);
// Формируем строку с лидирующими нулями для минут
СтрокаЧасов = Формат(ЦелоеКоличествоЧасов, "ЧГ=0");
СтрокаМинут = Формат(ОстатокМинут, "ЧЦ=2; ЧВН=; ЧН=00");
Возврат СтрокаЧасов + ":" + СтрокаМинут;
КонецФункции
Для использования этой функции в СКД выполним следующие шаги:
ИмяОбщегоМодуля.ПреобразоватьЧислоВЧасыМинуты(ВремяВМинутах).Если мы не хотим изменять конфигурацию и добавлять новые функции в модули, можно воспользоваться мощью выражений СКД. Разберем вариант, когда расчет происходит прямо в ресурсах отчета. Это позволит корректно выводить итоговое время по группировкам.
В поле Выражение на закладке Ресурсы пропишем формулу, которая суммирует часы и минуты отдельно, а затем склеивает их в строку:
Формат(Цел(Сумма(ВремяВЧасах)), "ЧГ=0")
+ ":"
+ Формат((Сумма(ВремяВЧасах) - Цел(Сумма(ВремяВЧасах))) * 60, "ЧЦ=2; ЧВН=; ЧН=00")
Рассмотрим подробнее, что здесь происходит: Цел(Сумма(ВремяВЧасах)) выделяет целое количество часов из суммы. Далее мы вычитаем из общей суммы целую часть, получая дробный остаток часа, и умножаем его на 60, чтобы перевести в минуты. Функция Формат с параметром ЧВН= гарантирует нам появление нуля перед цифрой, если минут меньше десяти (например, «05» вместо «5»).
Существует очень изящный способ, который позволяет избежать преобразования в строку. Мы можем подготовить число в специальном виде и применить к нему хитрую форматную маску. Посмотрим на алгоритм:
ЧЧММ.СС. Формула будет выглядеть так:
Цел(ВремяСекунды/3600)*100 + Цел((ВремяСекунды%3600)/60) + (ВремяСекунды%60)/100
ЧЦ=10; ЧДЦ=2; ЧРД=:; ЧРГ=:; ЧГ=2,2.Проанализируем ситуацию: мы превратили время в число, где каждые две цифры — это разряд времени. С помощью ЧРД=: (разделитель дробной части) мы заменяем точку на двоеточие, а с помощью ЧРГ=: (разделитель групп) и ЧГ=2,2 (группировка по две цифры) мы заставляем систему разделять часы и минуты двоеточием. Это позволяет полю оставаться «числовым» для системы сортировки, но выглядеть как «127:22:46».
Иногда удобнее подготовить данные еще на этапе выполнения запроса к базе данных. Выясним, как это сделать с помощью конструкции ВЫБОР и ВЫРАЗИТЬ. Это актуально, когда нам нужно получить готовое представление сразу в наборе данных.
ВЫБОР
КОГДА ВремяВСекундах <> 0
ТОГДА СТРОКА(ВЫРАЗИТЬ(ВремяВСекундах / 3600 - 0.5 КАК ЧИСЛО(15, 0)))
+ ":" +
СТРОКА(ФОРМАТ((ВремяВСекундах / 60) % 60, "ЧЦ=2; ЧВН=; ЧН=00"))
ИНАЧЕ "00:00"
КОНЕЦ
Здесь мы используем математическое округление для получения целых часов и оператор остатка от деления для получения минут. Обратите внимание, что работа со строками в запросе может ограничивать возможности дальнейшего суммирования этого поля в СКД, поэтому данный метод лучше использовать для детальных записей, а не для итогов.
1. Проблема сортировки: Если вы преобразуете время в строку (например, «100:05» и «20:10»), стандартная сортировка СКД может поставить «100:05» выше «20:10», так как будет сравнивать их посимвольно. Чтобы этого избежать, на вкладке Наборы данных для вашего вычисляемого поля обязательно заполните колонку Выражение упорядочивания, указав в ней исходное числовое поле с временем в секундах или часах.
2. Отрицательные значения: Если ваш отчет подразумевает отклонения (например, экономия времени может быть отрицательной), формулы из примера выше могут выдать некорректный результат (например, «-1:-30»). В таких случаях рекомендуется сначала вычислить абсолютное значение времени (Abs), сформировать строку, а затем добавить знак «-» в начало выражения, если исходное число было меньше нуля.
3. Использование БСП: Если ваша конфигурация использует Библиотеку Стандартных Подсистем, проанализируем возможности модуля Длительность. Вы можете вызвать в СКД функцию Длительность.СтрокаДлительности(Секунды). Она автоматически сформирует представление вида «1 дн. 2 ч.» или «26:15» в зависимости от переданных параметров. Это избавит вас от написания собственного кода.
4. Корректные итоги (Ресурсы): Помните, что если вы создали макет оформления поля для вывода времени, итоги могут перестать считаться автоматически. Рекомендуется всегда использовать Выражение представления или сложные формулы в Ресурсах с использованием функции ВычислитьВыражение, чтобы агрегация данных (сумма) происходила по числам, а пользователь видел результат в удобном временном формате.
Рассмотренные методы позволяют гибко настроить отображение времени в СКД под любые требования заказчика: от простых детальных записей до сложных иерархических отчетов с итогами по всем уровням группировки.