При разработке отчетов на базе Системы компоновки данных (СКД) в 1С программисты регулярно сталкиваются с двумя классическими задачами. Первая — это организация удобной фильтрации данных по реквизиту даты (который не является стандартным полем Период виртуальной таблицы), используя привычный для пользователей механизм выбора периода. Вторая — получение количественных итогов по булевым реквизитам в группировках (например, подсчет количества просроченных документов за месяц). В этой статье мы подробно разберем, как элегантно решить обе задачи стандартными средствами СКД, избегая типичных ошибок и не прибегая к неоправданному изменению метаданных конфигурации.
Представим ситуацию: у нас есть документ определенного типа, у которого присутствует реквизит ДатаВыписки с типом Дата. Нам необходимо предоставить пользователю возможность выбирать интервал дат на форме отчета с помощью стандартного диалогового окна выбора периода (где есть предопределенные значения вроде «Текущий месяц», «Прошлый квартал» и т.д.), чтобы отчет автоматически фильтровал документы по этому реквизиту.
Рассмотрим по шагам, как это реализовать наиболее эффективным образом.
Для начала создадим базовый запрос в наборе данных СКД. Чтобы наложить ограничение на выборку документов по дате выписки, мы укажем параметры в секции ГДЕ нашего запроса:
ВЫБРАТЬ
Док.Ссылка КАК Ссылка,
Док.ДатаВыписки КАК ДатаВыписки,
Док.Просрочен КАК Просрочен
ИЗ
Документ.НашДокумент КАК Док
ГДЕ
Док.ДатаВыписки МЕЖДУ &ДатаНачала И &ДатаОкончания
Этот запрос ожидает на входе два параметра: &ДатаНачала и &ДатаОкончания. Однако напрямую выводить их пользователю неудобно — заполнять две даты вручную занимает много времени.
Перейдем на вкладку Параметры в конструкторе схемы компоновки данных. Система автоматически добавила туда параметры ДатаНачала и ДатаОкончания. Наша цель — связать их в один удобный элемент управления. Выполним следующие настройки:
Период.СтандартныйПериод.ДатаНачала в колонке Выражение пропишем связь с началом стандартного периода: &Период.ДатаНачала.ДатаОкончания в колонке Выражение пропишем выражение с приведением к концу дня (это критически важно!): КонецПериода(&Период.ДатаОкончания, "ДЕНЬ").ДатаНачала и ДатаОкончания установим флажок в колонке Ограничение доступности. Это скроет их от пользователя на форме настроек, чтобы они не путали его.Период, напротив, снимем флажок ограничения доступности и при необходимости установим флажок «Быстрый доступ», чтобы параметр сразу отображался в шапке отчета.Важное примечание по поводу конца дня: Если вы укажете в выражении окончания периода просто &Период.ДатаОкончания, то время этой границы установится в значение 00:00:00. Это приведет к тому, что все документы, выписанные в последний день периода в течение дня (например, в 12:00 или 18:00), не попадут в отчет. Использование функции КонецПериода гарантирует корректный захват всего последнего дня выбранного интервала.
Если мы хотим, чтобы период не был жестко обязательным для заполнения (чтобы при очистке периода СКД просто выбирала все документы за все время без ошибок выполнения запроса), нам следует использовать фигурные скобки. Перепишем наше условие ГДЕ в запросе:
ВЫБРАТЬ
Док.Ссылка КАК Ссылка,
Док.ДатаВыписки КАК ДатаВыписки,
Док.Просрочен КАК Просрочен
ИЗ
Документ.НашДокумент КАК Док
{ГДЕ
(Док.ДатаВыписки >= &ДатаНачала И Док.ДатаВыписки <= &ДатаОкончания)}
Благодаря фигурным скобкам СКД сама проанализирует, заполнен ли параметр Период. Если он пуст, условие фильтрации будет бесследно удалено из конечного SQL-запроса к базе данных, и отчет сформируется без ошибок.
---
Вторая задача, озвученная автором темы: в отчете необходимо вывести группировку по месяцам. Первая колонка отчета должна показывать общее количество документов за месяц, а вторая колонка — количество только тех документов, у которых реквизит Просрочен (тип Булево) равен Истина.
У начинающих разработчиков часто возникает мысль: «Давайте добавим в сам документ новый реквизит с типом Число, будем при проведении документа записывать туда 1, если он просрочен, и 0 в противном случае, а потом просто просуммируем его в отчете». Это классический пример архитектурной ошибки («костыля»). Изменение структуры метаданных ради одного отчета усложняет поддержку конфигурации, увеличивает размер базы данных и требует написания лишнего кода для обновления этого реквизита при изменении данных документа.
Выясним, как решить эту задачу правильно исключительно средствами СКД.
Самый простой и распространенный путь — переложить задачу преобразования типов на СУБД с помощью конструкции языка запросов ВЫБОР. Изменим наш запрос СКД следующим образом:
ВЫБРАТЬ
Док.Ссылка КАК Ссылка,
Док.ДатаВыписки КАК ДатаВыписки,
Док.Просрочен КАК Просрочен,
ВЫБОР
КОГДА Док.Просрочен = ИСТИНА
ТОГДА 1
ИНАЧЕ 0
КОНЕЦ КАК КоличествоПросроченных
ИЗ
Документ.НашДокумент КАК Док
Теперь у нас появилось новое числовое поле КоличествоПросроченных. Настроим агрегацию этих полей на вкладке Ресурсы нашей СКД:
Ссылка в список ресурсов. В колонке «Выражение» укажем функцию Количество(Ссылка) (или Количество(Различные Ссылка)). Это даст нам общее число документов за каждый период. В колонке «Рассчитывать по...» оставим значение пустым, чтобы расчет шел по всем группировкам.КоличествоПросроченных в ресурсы. Для него выставим выражение Сумма(КоличествоПросроченных).В настройках структуры отчета добавим группировку по полю ДатаВыписки с периодичностью «Месяц» (это можно сделать через свойства поля или формат группировки). В выбранные поля добавим ресурсы Ссылка (можно переименовать заголовок колонки на «Всего документов») и КоличествоПросроченных (с заголовком «Просрочено»). Мы получим идеальный результат без единой строчки лишнего кода в конфигурации!
Существует еще более изящный метод, который позволяет вообще не менять исходный текст запроса и оставить его максимально чистым. Мы можем производить условное суммирование прямо в выражении ресурса СКД.
Пусть в нашем запросе выбирается стандартное булево поле Просрочен. Мы переходим на вкладку Ресурсы, добавляем поле Просрочен в список ресурсов и в колонке Выражение пишем специальную формулу:
Сумма(Выбор Когда Просрочен Тогда 1 Иначе 0 Конец)
Система компоновки данных самостоятельно обработает это выражение при расчете итогов. На уровне детальных записей (если пользователь захочет расшифровать отчет до документов) поле Просрочен по-прежнему будет отображаться как красивый флажок (Да/Нет), а на уровне группировок (по месяцам, контрагентам или ответственным) система выведет точную сумму просроченных документов.
Если мы хотим отделить логику вычислений от ресурсов и запроса, мы можем воспользоваться вкладкой Вычисляемые поля в конструкторе СКД:
КоличествоПросрочено.Выбор Когда Просрочен Тогда 1 Иначе 0 Конец.Сумма(КоличествоПросрочено).Этот подход невероятно удобен при работе с нетиповыми или сложными отчетами, так как исходный SQL-запрос к базе данных остается максимально простым и читаемым, а вся логика трансформации данных наглядно сосредоточена в настройках компоновки.
---
Разрабатывая отчеты в системе 1С, всегда стремитесь разделять слой хранения данных и слой их представления:
СтандартныйПериод или выводите реквизиты напрямую в пользовательские настройки отбора без жесткого кодирования параметров в запросе.ВЫБОР в ресурсах или вычисляемых полях — это сохранит чистоту вашего кода и убережет конфигурацию от лишних доработок.