Одна из частых задач при разработке отчётов и обработок в 1С — получить в запросе таблицу дат за определённый период. Например‚ это нужно для построения отчётов по дням‚ когда в некоторые дни нет данных‚ но строки в отчёте должны присутствовать. В этой статье разберём основные способы решения задачи.
Зачем нужна таблица дат
Таблица дат (календарь) полезна в следующих ситуациях:
- формирование отчётов‚ где нужно показать все дни периода‚ включая дни без оборотов;
- расчёт скользящих средних и накопительных итогов;
- план-фактный анализ по дням‚ неделям‚ месяцам;
- заполнение графиков и диаграмм с непрерывной осью времени.
Способ 1. Генерация дат через декартово произведение таблицы чисел
Классический приём — создать в запросе вспомогательную таблицу чисел от 0 до 9‚ а затем соединить её саму с собой несколько раз. Так можно получить последовательность чисел‚ которую затем преобразовать в даты функцией ДОБАВИТЬКДАТЕ.
ВЫБРАТЬ 0 КАК Цифра ПОМЕСТИТЬ ВТ_Цифры ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9 ; //////////////////////////////////////////////////////////// ВЫБРАТЬ ДОБАВИТЬКДАТЕ(&НачалоПериода‚ ДЕНЬ‚ ВТ_Цифры2.Цифра * 100 + ВТ_Цифры1.Цифра * 10 + ВТ_Цифры.Цифра) КАК Дата ИЗ ВТ_Цифры КАК ВТ_Цифры‚ ВТ_Цифры КАК ВТ_Цифры1‚ ВТ_Цифры КАК ВТ_Цифры2 ГДЕ ДОБАВИТЬКДАТЕ(&НачалоПериода‚ ДЕНЬ‚ ВТ_Цифры2.Цифра * 100 + ВТ_Цифры1.Цифра * 10 + ВТ_Цифры.Цифра) МЕЖДУ &НачалоПериода И &КонецПериода УПОРЯДОЧИТЬ ПО Дата
Три соединения таблицы цифр дают 1000 комбинаций, этого достаточно для периода почти в три года. Если нужен больший диапазон‚ добавьте ещё одно соединение.
Способ 2. Использование регистра сведений «Регламентированный производственный календарь»
В типовых конфигурациях (БП‚ ЗУП‚ ERP) есть регистр сведений с календарём. Получить даты можно простым запросом:
ВЫБРАТЬ Календарь.ДатаКалендаря КАК Дата ИЗ РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК Календарь ГДЕ Календарь.ДатаКалендаря МЕЖДУ &НачалоПериода И &КонецПериода УПОРЯДОЧИТЬ ПО Дата
Это самый быстрый и надёжный способ‚ но он работает только если регистр заполнен на нужный период.
Способ 3. Программное формирование таблицы значений
Если логика сложная (например‚ настраиваемый шаг в днях)‚ удобнее сформировать таблицу значений встроенным языком и передать её в запрос как временную таблицу:
Функция ПолучитьТаблицуДатЗаПериод(НачДата‚ КонДата‚ ШагДней = 1)
тзИнтервалов = Новый ТаблицаЗначений;
тзИнтервалов.Колонки.Добавить("НачИнтервала"‚ Новый ОписаниеТипов("Дата"));
ТекДата = НачалоДня(НачДата);
Пока ТекДата <= КонДата Цикл
НоваяСтрока = тзИнтервалов.Добавить;
НоваяСтрока.НачИнтервала = ТекДата;
ТекДата = ТекДата + ШагДней * 86400; // шаг в секундах
КонецЦикла;
Возврат тзИнтервалов;
КонецФункции
Далее таблица помещается в запрос через менеджер временных таблиц:
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ
| ТаблицаДат.НачИнтервала КАК Дата
|ПОМЕСТИТЬ ВТ_Даты
|ИЗ
| &ТаблицаДат КАК ТаблицаДат";
Запрос.УстановитьПараметр("ТаблицаДат"‚ тзИнтервалов);
Запрос.Выполнить;
Полезные функции языка запросов для работы с датами
- ДОБАВИТЬКДАТЕ(Дата‚ Период‚ Количество) — прибавляет к дате заданное число периодов (СЕКУНДА‚ МИНУТА‚ ЧАС‚ ДЕНЬ‚ МЕСЯЦ‚ КВАРТАЛ‚ ГОД);
- РАЗНОСТЬДАТ(Дата1‚ Дата2‚ Период) — возвращает разницу между датами в указанных единицах. Например‚
РАЗНОСТЬДАТ(ДАТАВРЕМЯ(2016‚9‚28)‚ ДАТАВРЕМЯ(2017‚9‚28)‚ КВАРТАЛ)вернёт 4; - НАЧАЛОПЕРИОДА(Дата‚ Период) и КОНЕЦПЕРИОДА(Дата‚ Период) — приведение даты к началу или концу периода;
- ДАТАВРЕМЯ(Год‚ Месяц‚ День‚ …) — конструктор даты‚ позволяющий получить таблицу «из воздуха»‚ без источника данных.
Рекомендации
- Для типовых конфигураций предпочтителен запрос к производственному календарю — он быстрее всего.
- Для независимых решений используйте генерацию через таблицу цифр, метод не требует данных в базе.
- При сложном шаге (например‚ каждые 3 дня или только рабочие дни по особому графику) формируйте таблицу значений программно.
- Всегда ограничивайте выборку условием МЕЖДУ &НачалоПериода И &КонецПериода‚ чтобы не генерировать лишние строки.
Таким образом‚ получить таблицу дат в запросе 1С можно несколькими способами‚ и выбор зависит от конфигурации‚ требуемого периода и шага. Освоив эти приёмы‚ вы сможете строить полноценные отчёты по периодам без «дырок» в данных.