При работе с динамическими списками в управляемых формах 1С часто возникает задача отображения длительности процессов (например, времени выполнения документов или регламентных заданий). Если интервал измеряется в секундах и может превышать 24 часа, стандартные механизмы форматирования даты перестают работать некорректно. Рассмотрим подробнее, почему так происходит, и разберем эффективные способы решения этой задачи.
Распространенная ошибка заключается в попытке прибавить количество секунд к пустой дате в запросе dynamic list:
ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, ВложенныйЗапрос.ВремяВыполненияСекунды) КАК ВремяВыполнения
Если затем применить к полученному полю формат длительности времени ДЛФ=T или ДФ=ЧЧ:мм:сс, то при значении длительности в 101 559 секунд (что составляет 28 часов 12 минут и 39 секунд) платформа выведет 04:12:39. Происходит это потому, что тип Дата в 1С хранит календарное время. При превышении 24 часов дата переходит на следующие сутки (станет 02.01.0001 04:12:39), а стандартный формат выводит лишь время текущих суток, игнорируя прибавившиеся дни.
В самом языке запросов 1С при этом нельзя преобразовать числовое значение в строку (отсутствует функция СТРОКА() или возможность приведения типов к строке).
Динамический список основан на схеме компоновки данных, а язык выражений СКД имеет существенно больше возможностей, чем язык запросов. В отличие от запроса, в выражениях СКД поддерживаются вызовы экспортных функций общих модулей, а также математические функции Цел() и остаток от деления %.
Разберем по шагам настройку вычисляемого поля:
ВремяВыполненияСтрокой.МойОбщийМодуль.ПреобразоватьСекундыВВремя(ВремяВыполненияСекунды)
Строка(Цел(ВремяВыполненияСекунды / 3600)) + ":" + Строка(Цел((ВремяВыполненияСекунды % 3600) / 60)) + ":" + Строка(ВремяВыполненияСекунды % 60)
Начиная с версии платформы 8.3.10, у элемента формы «Таблица», отображающего динамический список, появилось серверное событие ПриПолученииДанныхНаСервере. Это самый удобный и производительный способ оформления строк без изменения запроса.
Проанализируем пример кода для данного обработчика:
&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
Для Каждого СтрокаИзСписка Из Строки Цикл
// Получаем значение секунд из текущей строки
ВсегоСекунд = СтрокаИзСписка.Данные.ВремяВыполненияСекунды;
Если ВсегоСекунд = Неопределено Или ВсегоСекунд = 0 Тогда
Продолжить;
КонецЕсли;
// Переводим секунды в формат ЧЧ:ММ:СС
Часы = Цел(ВсегоСекунд / 3600);
Остаток = ВсегоСекунд % 3600;
Минуты = Цел(Остаток / 60);
Секунды = Остаток % 60;
ТекстВремени = Формат(Часы, "ЧЦ=10; ЧВН=") + ":"
+ Формат(Минуты, "ЧЦ=2; ЧЧ=02; ЧВН=") + ":"
+ Формат(Секунды, "ЧЦ=2; ЧЧ=02; ЧВН=");
// Устанавливаем текстовое представление в оформление ячейки
ОформлениеЯчейки = СтрокаИзСписка.Оформление["ВремяВыполненияФорматированное"];
ОформлениеЯчейки.УстановитьПараметр("Текст", ТекстВремени);
КонецЦикла;
КонецПроцедуры
Преимущество этого метода заключается в том, что обработка происходит только для той порции данных, которая в данный момент отображается на экране пользователя, что гарантирует высокую скорость работы.
Если платформа не поддерживает событие ПриПолученииДанныхНаСервере, а вычисляемые поля СКД по каким-то причинам использовать нельзя, можно рассчитать часы, минуты и секунды прямо в запросе динамического списка в виде отдельных числовых колонок:
ВЫБРАТЬ
Т.Ссылка КАК Ссылка,
Т.ВремяВыполненияСекунды КАК ВремяВыполненияСекунды,
ВЫРАЗИТЬ(Т.ВремяВыполненияСекунды / 3600 - 0.5 КАК ЧИСЛО(10, 0)) КАК Часы,
// Расчет минут и секунд через математический остаток
...
ИЗ
Документ.Заявка КАК Т
В форме эти колонки можно расположить в одну группу с горизонтальной ориентацией без отображения заголовков и разделять визуально двоеточиями, либо выводить отдельными числовыми полями.
В случаях, когда по форматированному полю требуется выполнять полноценную сортировку, поиск или группировку пользователем непосредственно в списке, оптимальным решением является расчет и запись готовой строки вида "28:12:39" в реквизит объекта или регистр сведений при проведении/записи документа.