При разработке интерфейсов на платформе 1С:Предприятие 8.3 часто возникает задача визуального выделения строк в динамических списках. Например, нам необходимо выделить просроченные задачи красным цветом или отметить документы, которые были изменены за последние несколько минут. Стандартный конструктор условного оформления предлагает удобные предопределенные значения времени, такие как НачалоЭтогоДня или КонецЭтогоДня. Однако эти значения работают без учета точного времени (с точностью до секунд).
Если перед нами стоит задача сравнивать дату документа или задачи с точным текущим временем (включая часы, минуты и секунды), стандартных настроек компоновки данных становится недостаточно. Значение текущей даты и времени постоянно меняется, и нам необходимо своевременно обновлять этот параметр в настройках условного оформления динамического списка. В этой статье мы подробно разберем, как решить эту задачу, рассмотрим классический метод с использованием обработчика ожидания и современный, более оптимальный подход через перехват события получения данных.
Разберем ситуацию на практическом примере. Допустим, у нас есть динамический список задач, у каждой из которых задан жесткий срок исполнения (дата со временем). Нам необходимо окрашивать задачи в красный цвет, как только текущее время превысит срок исполнения. Если мы попытаемся настроить условное оформление через стандартные настройки компоновки данных, система предложит нам использовать встроенные функции периода:
НачалоЭтогоДняНачалоЭтойНеделиГраницаКвартала и так далее.Все эти функции работают с "общечеловеческими" датами, отсекая время до начала дня. Сравнить дату с точностью до секунды динамически "из коробки" без программного вмешательства в условное оформление динамического списка невозможно, так как правое значение отбора должно постоянно актуализироваться.
Проанализируем классический подход, который часто применяется разработчиками. Суть метода заключается в том, что мы вешаем на форму клиентский таймер, который с заданной периодичностью обращается к серверу и обновляет правое значение в элементе отбора условного оформления динамического списка.
Посмотрим на пример реализации этого метода по шагам.
Шаг 1. Нам необходимо запустить обработчик ожидания при открытии формы. Для этого в процедуре ПриОткрытии на клиенте мы подключаем процедуру, которая будет срабатывать, например, каждые 30 секунд:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Подключаем периодический обработчик ожидания с интервалом 30 секунд
ПодключитьОбработчикОжидания("ОбновитьПараметрВремениУО", 30, Ложь);
КонецПроцедуры
Шаг 2. Опишем сам обработчик ожидания на клиенте. В нем мы будем получать точную текущую дату сеанса и передавать ее на сервер для обновления параметров оформления:
&НаКлиенте
Процедура ОбновитьПараметрВремениУО()
// Получаем точное время с учетом часового пояса сеанса пользователя
ТекущееВремя = ТекущаяДатаСеанса();
ОбновитьПараметрУОНаСервере(ТекущееВремя);
КонецПроцедуры
Шаг 3. Теперь реализуем серверную процедуру, которая будет выполнять непосредственный поиск нужного правила условного оформления и заменять в нем сравниваемое значение на новую дату:
&НаСервере
Процедура ОбновитьПараметрУОНаСервере(НоваяДата)
// Обходим элементы условного оформления динамического списка
Для Каждого ЭлементОформления Из Список.КомпоновщикНастроек.Настройки.УсловноеОформление.Элементы Цикл
// Для идентификации нужного правила проверяем левое значение в отборе
Для Каждого ЭлементОтбора Из ЭлементОформления.Отбор.Элементы Цикл
Если ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СрокИсполнения") Тогда
// Устанавливаем актуальное время для сравнения
ЭлементОтбора.ПравоеЗначение = НоваяДата;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Рассмотрим подробнее особенности этого метода. Изменение настроек компоновщика динамического списка на сервере автоматически инициирует обновление отображения данных на клиенте. Нам не нужно принудительно вызывать метод Элементы.Список.Обновить(), так как платформа сама поймет, что настройки изменились, и перерисует список.
Начиная с версии платформы 1С:Предприятие 8.3.10, у разработчиков появился гораздо более изящный и производительный инструмент — обработчик события таблицы ПриПолученииДанныхНаСервере. Это событие вызывается непосредственно в момент, когда сервер подготавливает строки динамического списка для отображения на экране пользователя.
Разберем, почему этот вариант считается наиболее оптимальным:
Давайте посмотрим на практический пример реализации этого события. Для этого перейдем в свойства элемента формы (таблицы, связанной с динамическим списком) и создадим обработчик ПриПолученииДанныхНаСервере:
&НаСервереБезКонтекста
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
// Получаем точное время на сервере для текущего сеанса
ТекущееВремя = ТекущаяДатаСеанса();
// Обходим только видимые на экране строки
Для Каждого СтрокаСписка Из Строки Цикл
// Проверяем наличие ключевого поля в данных строки
Если СтрокаСписка.Данные.Свойство("СрокИсполнения") Тогда
СрокЗадачи = СтрокаСписка.Данные.СрокИсполнения;
// Если срок просрочен, применяем индивидуальное оформление строки
Если ЗначениеЗаполнено(СрокЗадачи) И СрокЗадачи < ТекущееВремя Тогда
// Окрашиваем текст всей строки (или конкретной ячейки) в красный цвет
СтрокаСписка.Оформление["СрокИсполнения"].УстановитьЗначениеПараметра("ЦветТекста", WebЦвета.Красный);
// Делаем шрифт полужирным для привлечения внимания
СтрокаСписка.Оформление["СрокИсполнения"].УстановитьЗначениеПараметра("Шрифт", Новый Шрифт(,,Истина));
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Обратите внимание на директиву компиляции &НаСервереБезКонтекста. Использование внеконтекстных серверных вызовов критически важно для производительности системы, так как при прокрутке списка не происходит передача тяжелого контекста всей формы на сервер и обратно.
При работе со временем в динамических списках крайне важно соблюдать несколько правил, чтобы избежать ошибок отображения данных у пользователей в разных часовых поясах и снижения производительности СУБД.
Правило 1. Всегда используйте ТекущаяДатаСеанса() вместо ТекущаяДата()
Метод ТекущаяДата() возвращает время того компьютера, на котором выполняется код. В клиент-серверном варианте работы сервер приложения 1С может физически находиться в Москве (UTC+3), а пользователь — в Новосибирске (UTC+7). Если использовать ТекущаяДата() на сервере, время у новосибирского пользователя будет отставать на 4 часа, что приведет к неверному условному оформлению. Метод ТекущаяДатаСеанса() автоматически учитывает часовой пояс текущего сеанса пользователя и гарантирует корректность расчетов.
Правило 2. Используйте штатное автообновление динамического списка
Если мы хотим, чтобы список обновлялся автоматически без участия пользователя, нам не обязательно писать собственные таймеры на клиенте. У динамического списка есть стандартные свойства:
Автообновление (установите в значение Истина)ПериодАвтообновления (задается в секундах, минимальное значение — 60 секунд)В связке с обработчиком ПриПолученииДанныхНаСервере штатное автообновление позволяет создать полностью динамический и актуальный интерфейс, который будет самостоятельно перерисовывать просроченные строки каждую минуту без написания сложного кода поддержки таймеров.
Таким образом, мы рассмотрели два надежных подхода к обновлению даты в параметрах условного оформления динамического списка. Выбирайте наиболее подходящий вариант в зависимости от архитектурных требований вашей конфигурации!