При разработке отчетов в 1С часто возникает задача представить длительность, которая хранится в базе в минутах, в удобном для пользователя виде — например, вместо «150 мин» вывести «2 ч 30 мин». В этой статье мы подробно разберем, как реализовать такой пересчет, используя Систему компоновки данных (СКД), и как избежать типичных ошибок при подсчете итогов в отчете.
В обычных документах разработчики часто используют простые функции в модуле формы для обновления надписей. Рассмотрим пример кода, который часто применяется в формах документов:
Функция ОбновитьНадписьВремя() Экспорт
ВремяДляНадписи = УчетРабочегоВремени.Итог("ИтогоОтработано") / 60;
ВремяЧасы = Цел(ВремяДляНадписи);
ВремяМинуты = Формат((ВремяДляНадписи - ВремяЧасы) * 60, "ЧЦ=2; ЧДЦ=0");
ЗаголовокВремяНадписи = "" + ВремяЧасы + " ч " + ВремяМинуты + " мин";
НадписьВремя = ?(СокрЛП(ЗаголовокВремяНадписи) = "0 ч 00 мин", "", ЗаголовокВремяНадписи);
КонецФункции
Однако в отчетах СКД мы не можем просто вызвать процедуру из формы. Нам необходимо либо создать функцию в общем модуле, либо использовать механизмы вычисляемых полей самой СКД. Проанализируем оба варианта.
Это самый гибкий и «чистый» способ. Мы выносим логику преобразования в общий модуль, что позволяет использовать ее в любых отчетах и формах системы.
РаботаСоВременем).
Функция ПолучитьДлительностьТекстом(Знач ДлительностьВМинутах) Экспорт
Если ДлительностьВМинутах = 0 Или ДлительностьВМинутах = Неопределено Тогда
Возврат "";
КонецЕсли;
КолЧасов = Цел(ДлительностьВМинутах / 60);
КолМинут = ДлительностьВМинутах % 60; // Получаем остаток от деления на 60
ТекстЧасов = ?(КолЧасов > 0, Формат(КолЧасов, "ЧГ=0") + " ч ", "");
ТекстМинут = ?(КолМинут > 0, Формат(КолМинут, "ЧЦ=2; ЧВН=") + " мин", "");
Возврат СокрЛП(ТекстЧасов + ТекстМинут);
КонецФункции
Важное замечание: В некоторых примерах предлагают использовать конструкцию Дата(1,1,1) + Минуты * 60. Мы настоятельно рекомендуем избегать этого метода. Если количество минут превысит 1440 (24 часа), 1С обнулит часы и начнет отсчет новых суток, что приведет к потере данных в отчетах за большие периоды. Математический расчет через Цел() и % (остаток от деления) лишен этого недостатка.
Теперь разберем, как вызвать эту функцию внутри схемы компоновки данных. Перейдем на закладку «Вычисляемые поля» и добавим новое поле:
ВремяПредставлениеРаботаСоВременем.ПолучитьДлительностьТекстом(СуммаМинут)Отработано (ч:мин)Здесь СуммаМинут — это имя вашего поля из набора данных, в котором хранятся исходные числа.
Частая проблема: в детальных записях отчет выводит «1 ч 30 мин», а в строке «Итого» либо пусто, либо выводится ошибка. Выясним причину: СКД пытается применить функцию к итоговому значению, но настройки ресурсов заданы неверно.
Чтобы итоги считались правильно, перейдем на закладку «Ресурсы»:
ВремяПредставление (или то поле, где должен быть текст).РаботаСоВременем.ПолучитьДлительностьТекстом(Сумма(ИтогоОтработано))Проанализируем это выражение: Сначала СКД выполняет агрегатную функцию Сумма(), складывая все минуты (числа) по группировке, и только потом передает полученное число в вашу функцию для форматирования в текст. Это гарантирует, что в итогах вы увидите правильную сумму часов и минут, а не результат сложения строк.
Если у вас нет возможности или желания создавать новый общий модуль, можно прописать всю логику прямо в СКД. Рассмотрим подробнее выражение для вычисляемого поля:
Выбор
Когда СуммаМинут > 0
Тогда Строка(Цел(СуммаМинут / 60)) + " ч " + Формат(СуммаМинут % 60, "ЧЦ=2; ЧВН=") + " мин"
Иначе ""
Конец
В этом выражении мы используем:
Цел(СуммаМинут / 60) — для получения целого количества часов.СуммаМинут % 60 — операцию получения остатка от деления для получения минут.Формат(..., "ЧВН=") — форматную строку, которая заставляет систему выводить ведущий ноль (например, «1 ч 05 мин» вместо «1 ч 5 мин»).Если при формировании отчета вы столкнулись с ошибкой Индекс находится за границами массива, проанализируем ситуацию. Скорее всего, в вашу функцию попадает значение NULL или 0, а внутри функции происходит попытка разделения строки или обращения к элементам коллекции.
Чтобы этого избежать, всегда оборачивайте числовые поля в наборе данных функцией ЕСТЬNULL(Поле, 0). Это гарантирует, что в расчеты всегда будет попадать число, и логика не сломается на пустых значениях.
Посмотрим на еще один профессиональный прием. Иногда удобно оставить поле числовым (чтобы пользователь мог сам суммировать его в Excel), но в отчете видеть текст. Для этого используйте свойство «Выражение представления» в настройках поля СКД. Туда можно вставить вызов функции РаботаСоВременем.ПолучитьДлительностьТекстом(ИтогоОтработано). В итоге визуально в ячейке будет текст «2 ч 10 мин», но «внутри» 1С будет помнить, что это число 130.
Мы рассмотрели основные способы пересчета минут в человекочитаемый формат. Выбор конкретного метода зависит от архитектуры вашей конфигурации, но использование общего модуля с корректным суммированием в ресурсах является наиболее надежным и универсальным решением.