Как вывести две даты в одной ячейке динамического списка в виде HH:mm-HH:mm при режиме совместимости 8.2

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В интерфейсе управляемого приложения 1С часто возникает задача компактного отображения данных. Одним из таких сценариев является вывод временного интервала доставки или записи (например, «10:00-12:00») в одной колонке динамического списка. На чистой платформе 1С 8.3 без ограничений совместимости разработчик имеет в арсенале множество удобных инструментов. Однако, если наша конфигурация работает в режиме совместимости с версией 8.2, мы сталкиваемся с жесткими технологическими рамками.

В этой статье мы подробно разберем, почему стандартные подходы новой платформы не работают в режиме совместимости, и проанализируем четыре практических метода обхода этого ограничения, которые позволят решить задачу красиво и эффективно.

Выясняем причину: почему не работает событие ПриПолученииДанныхНаСервере

Начиная с версии платформы 8.3.10, разработчикам стал доступен замечательный обработчик события динамического списка — ПриПолученииДанныхНаСервере. Он позволяет «на лету» перехватывать пакеты выводимых на экран данных, программно обрабатывать их (например, форматировать даты, соединять строки) и дополнять коллекцию оформления. Это идеальный инструмент для решения нашей задачи.

Однако, если в свойствах вашей конфигурации установлен режим совместимости с версией 8.2, этот обработчик вызываться не будет. Платформа 1С принудительно блокирует новые оптимизированные механизмы работы с динамическими списками, чтобы гарантировать идентичность поведения конфигурации на старых версиях движка. Попытка прописать этот метод в модуле формы ни к чему не приведет — событие просто игнорируется платформой.

Давайте рассмотрим, какие альтернативные пути решения у нас остаются.

Решение 1. Сборка интервала времени прямо в запросе динамического списка (трюк с ПОДСТРОКА)

Если мы не хотим изменять структуру метаданных конфигурации (создавать новые реквизиты документов или регистры сведений), мы можем попробовать решить задачу математически непосредственно в самом запросе динамического списка. Поскольку стандартные функции форматирования даты в языке запросов 1С отсутствуют, мы применим классический «хардкорный» трюк с функцией ПОДСТРОКА.

Идея заключается в том, что мы получаем числовое значение часа и минуты из даты, а затем с помощью функции ПОДСТРОКА выбираем нужные строковые символы из заранее подготовленного шаблона чисел. Посмотрим на практический пример реализации такого запроса:


ВЫБРАТЬ
    Док.Ссылка КАК Ссылка,
    Док.Номер КАК Номер,
    Док.Дата КАК Дата,
    
    // Получаем строковое представление часов начала периода
    ПОДСТРОКА("000102030405060708091011121314151617181920212223", ЧАС(Док.НачалоПериодаДоставки) * 2 + 1, 2) 
    + ":" + 
    // Получаем строковое представление минут начала периода
    ПОДСТРОКА("000102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859", МИНУТА(Док.НачалоПериодаДоставки) * 2 + 1, 2)
    + "-" +
    // Получаем строковое представление часов конца периода
    ПОДСТРОКА("000102030405060708091011121314151617181920212223", ЧАС(Док.КонецПериодаДоставки) * 2 + 1, 2) 
    + ":" + 
    // Получаем строковое представление минут конца периода
    ПОДСТРОКА("000102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859", МИНУТА(Док.КонецПериодаДоставки) * 2 + 1, 2) 
    КАК ПериодДоставкиСтрокой
ИЗ
    Документ.ЗаказПокупателя КАК Док

Как это работает: функция ЧАС(Дата) возвращает число от 0 до 23. Мы умножаем это число на 2 (так как в шаблоне на каждое число приходится ровно 2 символа) и прибавляем 1, чтобы получить стартовую позицию для функции ПОДСТРОКА. Аналогичная математика применяется для минут.

Плюсы метода:

  1. Полностью работает «на лету» без модификации метаданных конфигурации.
  2. Совместимо со всеми версиями платформ 1С, начиная с 8.0.

Минусы метода:

  1. Запрос выглядит громоздко и его сложно поддерживать при изменении требований.
  2. Сортировка и отборы по этой колонке будут работать в алфавитном (строковом) порядке, а не в хронологическом.

Решение 2. Использование реквизита или вспомогательного регистра сведений (Рекомендуемый способ)

Если производительность системы является для нас приоритетом, то постоянное вычисление строкового представления в запросе динамического списка (как в Решении 1) может негативно сказаться на скорости работы интерфейса при больших объемах данных. Самый надежный и быстродействующий способ для платформы 8.2 — это кэширование готовой текстовой строки периода непосредственно при записи документа.

Здесь у нас есть два архитектурных пути:

Вариант А: Добавление реквизита в документ. Если редактируемый интервал принадлежит конкретному документу (например, документу ЗаказПокупателя), мы можем добавить в него новый строковый реквизит длиной 11 символов с именем ПериодДоставкиСтрокой. Заполнение реквизита выполняем в обработчике события ПередЗаписью модуля документа:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    // Проверяем заполненность дат и формируем красивую строку
    Если ЗначениеЗаполнено(НачалоПериодаДоставки) И ЗначениеЗаполнено(КонецПериодаДоставки) Тогда
        ПериодДоставкиСтрокой = Формат(НачалоПериодаДоставки, "ДФ=HH:mm; ДП=") + "-" + Формат(КонецПериодаДоставки, "ДФ=HH:mm; ДП=");
    Иначе
        ПериодДоставкиСтрокой = "";
    КонецЕсли;
    
КонецПроцедуры

После этого мы просто выводим данный реквизит в динамический список как обычное поле. База данных выдает уже готовую строку мгновенно, без каких-либо накладных расходов.

Вариант Б: Использование регистра сведений. Если мы не хотим изменять структуру самого документа (например, конфигурация находится на поддержке без возможности редактирования объектов), мы можем создать вспомогательный независимый или подчиненный регистр сведений ПериодыДоставкиДокументов. Измерениями регистра будет Документ (тип ДокументСсылка), а ресурсом — ПериодСтрокой (тип Строка).

Для записи данных в этот регистр мы создадим подписку на событие ПриЗаписи для нужных документов:


Процедура ПриЗаписиДокументаРегистрацияПериода(Источник, Отказ) Экспорт
    
    // Записываем данные во вспомогательный регистр сведений
    НаборЗаписей = РегистрыСведений.ПериодыДоставкиДокументов.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.Документ.Установить(Источник.Ссылка);
    
    НоваяЗапись = НаборЗаписей.Добавить();
    НоваяЗапись.Документ = Источник.Ссылка;
    НоваяЗапись.ПериодСтрокой = Формат(Источник.НачалоПериодаДоставки, "ДФ=HH:mm; ДП=") + "-" + Формат(Источник.КонецПериодаДоставки, "ДФ=HH:mm; ДП=");
    
    НаборЗаписей.Записать();
    
КонецПроцедуры

В самом динамическом списке мы соединяем основную таблицу документа со вспомогательным регистром сведений по левому соединению и выводим поле ПериодСтрокой.

Решение 3. Визуальный обходной путь через группировку колонок управляемой формы

Если мы не хотим писать дополнительный программный код и усложнять логику работы базы данных, мы можем использовать стандартные визуальные механизмы управляемой формы 1С. Платформа позволяет объединять несколько колонок в группу с типом отображения «В ячейке».

Давайте разберем по шагам, как настроить такое отображение:

  1. В запросе динамического списка выберите три поля: НачалоПериодаДоставки, КонецПериодаДоставки и фиктивное текстовое поле-дефис (например: "-" КАК Разделитель).
  2. Перенесите все эти три поля на форму в элементы нашей таблицы динамического списка.
  3. Для полей начала и конца периода в свойствах оформления на форме (свойство Формат) задайте формат вывода времени: ДФ=HH:mm.
  4. Добавьте новую группу колонок в таблице формы и установите для нее свойство Группировка в значение «В ячейке».
  5. Переместите наши три поля (начало периода, поле-разделитель и конец периода) внутрь созданной группы.
  6. В свойствах самой группы снимите флаг ОтображатьЗаголовок для вложенных элементов.

Платформа 1С автоматически сгруппирует эти поля в пределах одной ячейки строки. Хотя в режиме совместимости с 8.2 платформа может добавлять системные разделители (запятые или пробелы в зависимости от версии), итоговый результат в интерфейсе будет выглядеть вполне аккуратно (например, «10:00 , - , 12:00» или «10:00 - 12:00»), что часто полностью устраивает конечных пользователей без написания сложного кода.

Подводим итоги и выбираем лучшее решение

Мы рассмотрели различные варианты реализации вывода интервала времени в динамическом списке 1С в режиме совместимости 8.2. Выбор конкретного метода зависит от архитектуры вашей базы данных:

← На главную