В интерфейсе управляемого приложения 1С часто возникает задача компактного отображения данных. Одним из таких сценариев является вывод временного интервала доставки или записи (например, «10:00-12:00») в одной колонке динамического списка. На чистой платформе 1С 8.3 без ограничений совместимости разработчик имеет в арсенале множество удобных инструментов. Однако, если наша конфигурация работает в режиме совместимости с версией 8.2, мы сталкиваемся с жесткими технологическими рамками.
В этой статье мы подробно разберем, почему стандартные подходы новой платформы не работают в режиме совместимости, и проанализируем четыре практических метода обхода этого ограничения, которые позволят решить задачу красиво и эффективно.
Начиная с версии платформы 8.3.10, разработчикам стал доступен замечательный обработчик события динамического списка — ПриПолученииДанныхНаСервере. Он позволяет «на лету» перехватывать пакеты выводимых на экран данных, программно обрабатывать их (например, форматировать даты, соединять строки) и дополнять коллекцию оформления. Это идеальный инструмент для решения нашей задачи.
Однако, если в свойствах вашей конфигурации установлен режим совместимости с версией 8.2, этот обработчик вызываться не будет. Платформа 1С принудительно блокирует новые оптимизированные механизмы работы с динамическими списками, чтобы гарантировать идентичность поведения конфигурации на старых версиях движка. Попытка прописать этот метод в модуле формы ни к чему не приведет — событие просто игнорируется платформой.
Давайте рассмотрим, какие альтернативные пути решения у нас остаются.
Если мы не хотим изменять структуру метаданных конфигурации (создавать новые реквизиты документов или регистры сведений), мы можем попробовать решить задачу математически непосредственно в самом запросе динамического списка. Поскольку стандартные функции форматирования даты в языке запросов 1С отсутствуют, мы применим классический «хардкорный» трюк с функцией ПОДСТРОКА.
Идея заключается в том, что мы получаем числовое значение часа и минуты из даты, а затем с помощью функции ПОДСТРОКА выбираем нужные строковые символы из заранее подготовленного шаблона чисел. Посмотрим на практический пример реализации такого запроса:
ВЫБРАТЬ
Док.Ссылка КАК Ссылка,
Док.Номер КАК Номер,
Док.Дата КАК Дата,
// Получаем строковое представление часов начала периода
ПОДСТРОКА("000102030405060708091011121314151617181920212223", ЧАС(Док.НачалоПериодаДоставки) * 2 + 1, 2)
+ ":" +
// Получаем строковое представление минут начала периода
ПОДСТРОКА("000102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859", МИНУТА(Док.НачалоПериодаДоставки) * 2 + 1, 2)
+ "-" +
// Получаем строковое представление часов конца периода
ПОДСТРОКА("000102030405060708091011121314151617181920212223", ЧАС(Док.КонецПериодаДоставки) * 2 + 1, 2)
+ ":" +
// Получаем строковое представление минут конца периода
ПОДСТРОКА("000102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859", МИНУТА(Док.КонецПериодаДоставки) * 2 + 1, 2)
КАК ПериодДоставкиСтрокой
ИЗ
Документ.ЗаказПокупателя КАК Док
Как это работает: функция ЧАС(Дата) возвращает число от 0 до 23. Мы умножаем это число на 2 (так как в шаблоне на каждое число приходится ровно 2 символа) и прибавляем 1, чтобы получить стартовую позицию для функции ПОДСТРОКА. Аналогичная математика применяется для минут.
Плюсы метода:
Минусы метода:
Если производительность системы является для нас приоритетом, то постоянное вычисление строкового представления в запросе динамического списка (как в Решении 1) может негативно сказаться на скорости работы интерфейса при больших объемах данных. Самый надежный и быстродействующий способ для платформы 8.2 — это кэширование готовой текстовой строки периода непосредственно при записи документа.
Здесь у нас есть два архитектурных пути:
Вариант А: Добавление реквизита в документ. Если редактируемый интервал принадлежит конкретному документу (например, документу ЗаказПокупателя), мы можем добавить в него новый строковый реквизит длиной 11 символов с именем ПериодДоставкиСтрокой. Заполнение реквизита выполняем в обработчике события ПередЗаписью модуля документа:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Проверяем заполненность дат и формируем красивую строку
Если ЗначениеЗаполнено(НачалоПериодаДоставки) И ЗначениеЗаполнено(КонецПериодаДоставки) Тогда
ПериодДоставкиСтрокой = Формат(НачалоПериодаДоставки, "ДФ=HH:mm; ДП=") + "-" + Формат(КонецПериодаДоставки, "ДФ=HH:mm; ДП=");
Иначе
ПериодДоставкиСтрокой = "";
КонецЕсли;
КонецПроцедуры
После этого мы просто выводим данный реквизит в динамический список как обычное поле. База данных выдает уже готовую строку мгновенно, без каких-либо накладных расходов.
Вариант Б: Использование регистра сведений. Если мы не хотим изменять структуру самого документа (например, конфигурация находится на поддержке без возможности редактирования объектов), мы можем создать вспомогательный независимый или подчиненный регистр сведений ПериодыДоставкиДокументов. Измерениями регистра будет Документ (тип ДокументСсылка), а ресурсом — ПериодСтрокой (тип Строка).
Для записи данных в этот регистр мы создадим подписку на событие ПриЗаписи для нужных документов:
Процедура ПриЗаписиДокументаРегистрацияПериода(Источник, Отказ) Экспорт
// Записываем данные во вспомогательный регистр сведений
НаборЗаписей = РегистрыСведений.ПериодыДоставкиДокументов.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Документ.Установить(Источник.Ссылка);
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Документ = Источник.Ссылка;
НоваяЗапись.ПериодСтрокой = Формат(Источник.НачалоПериодаДоставки, "ДФ=HH:mm; ДП=") + "-" + Формат(Источник.КонецПериодаДоставки, "ДФ=HH:mm; ДП=");
НаборЗаписей.Записать();
КонецПроцедуры
В самом динамическом списке мы соединяем основную таблицу документа со вспомогательным регистром сведений по левому соединению и выводим поле ПериодСтрокой.
Если мы не хотим писать дополнительный программный код и усложнять логику работы базы данных, мы можем использовать стандартные визуальные механизмы управляемой формы 1С. Платформа позволяет объединять несколько колонок в группу с типом отображения «В ячейке».
Давайте разберем по шагам, как настроить такое отображение:
НачалоПериодаДоставки, КонецПериодаДоставки и фиктивное текстовое поле-дефис (например: "-" КАК Разделитель).Формат) задайте формат вывода времени: ДФ=HH:mm.Группировка в значение «В ячейке».ОтображатьЗаголовок для вложенных элементов.Платформа 1С автоматически сгруппирует эти поля в пределах одной ячейки строки. Хотя в режиме совместимости с 8.2 платформа может добавлять системные разделители (запятые или пробелы в зависимости от версии), итоговый результат в интерфейсе будет выглядеть вполне аккуратно (например, «10:00 , - , 12:00» или «10:00 - 12:00»), что часто полностью устраивает конечных пользователей без написания сложного кода.
Мы рассмотрели различные варианты реализации вывода интервала времени в динамическом списке 1С в режиме совместимости 8.2. Выбор конкретного метода зависит от архитектуры вашей базы данных:
ПОДСТРОКА).