Как соединить два столбца с датами в один столбец в 1С?

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

При разработке отчетов и печатных форм часто возникает необходимость объединить две даты (например, ДатаНачала и ДатаОкончания) в один столбец со строковым представлением вида "01.01.2024 - 31.01.2024" или "1 квартал 2024 г.". Рассмотрим, с какими ограничениями можно столкнуться при выполнении этой задачи в языке запросов 1С и какими способами ее можно эффективно решить.

Ограничения языка запросов 1С

Проанализируем, почему не получается выполнить простое сложение полей в запросе вида ДатаС + " - " + ДатаПо:

  1. Несовместимость типов при конкатенации: оператор сложения + в языке запросов требует, чтобы оба операнда имели строковый тип. Попытка сложить поле типа Дата со строкой приводит к ошибке СУБД.
  2. Отсутствие функции Формат(): в языке запросов 1С нет встроенной функции Формат(), а приведение типа Дата к строке через ВЫРАЗИТЬ не поддерживается.
  3. Ограничения функции Строка(): начиная с платформы 8.3.20 в запросах появилась функция Строка(), однако она приводит дату к стандартному системному формату и не позволяет задать произвольную маску (например, вырезать время или изменить разделители).

Способ 1. Постобработка результата запроса в коде

Наиболее производительным и гибким решением является выборка дат в исходном типе Дата с последующей программной обработкой результата. Это позволяет сохранить высокую скорость выполнения запроса и корректность сортировок.

Для человекочитаемого представления периода можно использовать встроенную функцию ПредставлениеПериода() или механизмы Библиотеки стандартных подсистем (БСП):


Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    // Формирование стандартного представления периода ("1 квартал 2024 г.")
    ТекстПериода = ПредставлениеПериода(Выборка.ДатаНачала, Выборка.ДатаОкончания, "ФП=Истина");
    
    // Или с помощью подсистем БСП:
    // ТекстПериода = ОбщегоНазначенияКлиентСервер.СформироватьПредставлениеПериода(Выборка.ДатаНачала, Выборка.ДатаОкончания);
КонецЦикла;

Способ 2. Использование Системы компоновки данных (СКД)

Разберем, как объединить поля без написания кода постобработки, если отчет строится на базе СКД.

В СКД предусмотрено специальное свойство поля — Выражение представления. Оно позволяет изменить отображение данных, не меняя само значение поля в выборке:

  1. Перейдем на вкладку Настройки или Поля датасета в схеме компоновки данных.
  2. В колонке Выражение представления для нужного поля напишем выражение с использованием функций форматирования.

Пример выражения представления для объединения полей периода:


Формат(ДатаНачала, "ДФ=dd.MM.yyyy") + " - " + Формат(ДатаОкончания, "ДФ=dd.MM.yyyy")

Также в выражениях СКД можно вызывать экспортные функции общих модулей. При этом важно учитывать особенности контекста исполнения:

  1. Общий модуль должен иметь установленный флаг Вызов сервера или Клиент (на сервере).
  2. Если сеанс работает в безопасном режиме, исполнение произвольного кода в выражениях СКД может требовать дополнительного разрешения.

Способ 3. Использование макета табличного документа

Если результат выводится в табличный документ без СКД, логику соединения столбцов можно перенести в макет:

  1. Для ячейки макета установим тип заполнения Шаблон.
  2. Зададим текст ячейки: [ДатаНачала] - [ДатаОкончания].
  3. В свойствах параметров ячейки настроим формат отображения для каждой даты отдельно.

Способ 4. Математические манипуляции в запросе (не рекомендуется)

Рассмотрим вариант конструирования строки даты непосредственно в тексте запроса через математические функции работы с датой и подстроками. На практике такой подход считается крайним средством из-за высокой нагрузки на СУБД и сложности поддержки кода:


ВЫБРАТЬ
    ПОДСТРОКА("0123456789", ДЕНЬ(ТаблицаДанных.ДатаНачала) / 10 + 1, 1) 
    + ПОДСТРОКА("0123456789", СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, 6 * ДЕНЬ(ТаблицаДанных.ДатаНачала))) / 6 + 1, 1) 
    + "/" + ПОДСТРОКА("0123456789", МЕСЯЦ(ТаблицаДанных.ДатаНачала) / 10 + 1, 1) 
    + " - " 
    + ПОДСТРОКА("0123456789", ДЕНЬ(ТаблицаДанных.ДатаОкончания) / 10 + 1, 1) КАК Период
ИЗ
    &ТаблицаДанных КАК ТаблицаДанных

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

← На главную