Почему не работает период в СКД и как правильно передавать даты в отчет?

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

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

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

Анализ проблемы: почему сбрасываются параметры периода?

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

Как показывает практика и разбор реальных кейсов с форумов, причин у этой проблемы может быть несколько:

  1. Неправильная связь параметров на форме и в схеме. Пользователь работает с одним параметром на форме, а в запросе используются другие.
  2. Программное вмешательство в модуле отчета. В обработчике события ПриКомпоновкеРезультата написан код, который затирает, обнуляет или некорректно инициализирует настройки компоновщика.
  3. Использование условий ГДЕ вместо параметров виртуальных таблиц. Это приводит не только к падению производительности, но и к логическим ошибкам при расчете остатков и оборотов.

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

Причина №1. Типичная ошибка в обработчике ПриКомпоновкеРезультата

Очень часто для кастомизации вывода отчета (например, для вывода в разные вкладки, программной установки заголовков или постобработки таблицы) разработчики используют предопределенную процедуру ПриКомпоновкеРезультата в модуле объекта отчета.

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

Давайте посмотрим на пример неправильного кода, из-за которого введенные пользователем даты начала и окончания периода бесследно исчезают:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    
    // ОШИБКА: Инициализация макета выполняется по дефолтным настройкам схемы!
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, ДанныеРасшифровки);
    
    // Дальнейший вывод...
КонецПроцедуры

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

Более того, если в коде присутствует очистка параметров или инициализация параметров по умолчанию (например, установка пустых дат), то СКД получит пустые границы периода, что приведет к выборке данных за все время существования базы.

Правильное решение: для программной компоновки необходимо всегда использовать метод ПолучитьНастройки() компоновщика настроек. Этот метод автоматически объединяет настройки по умолчанию (из конфигуратора), фиксированные настройки и пользовательские настройки с формы в единую результирующую структуру.

Рассмотрим правильный шаблон программного вывода отчета в СКД:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    // Отключаем стандартный вывод платформы
    СтандартнаяОбработка = Ложь;
    
    // ПРАВИЛЬНО: Получаем объединенные настройки (с учетом ввода пользователя на форме)
    АктуальныеНастройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    // Если вам нужно программно изменить или проверить параметры, делайте это здесь:
    // Например: АктуальныеНастройки.ПараметрыДанных.УстановитьЗначениеПараметра("НачалоПериода", НачалоДня(ТекущаяДата()));
    
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    
    // Передаем объединенные настройки в компоновщик макета
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, АктуальныеНастройки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
    
    ДокументРезультат.Очистить();
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

Использование метода КомпоновщикНастроек.ПолучитьНастройки() гарантирует, что выбранный пользователем период (и любые другие отборы) долетят до процессора компоновки и правильно отработают в запросе. При необходимости реализовать сложные варианты формирования отчетов можно использовать примеры программной работы с СКД и управляемыми формами.

Причина №2. Как правильно связать «Стандартный период» и параметры виртуальных таблиц

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

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

  1. Откроем вкладку «Параметры» в схеме компоновки данных.
  2. Добавим новый параметр, назовем его, например, ПериодОтчета. Установим для него тип значения СтандартныйПериод. Именно этот параметр мы сделаем доступным пользователю на форме (поставим флаг «Включать в пользовательские настройки»).
  3. Для системных параметров НачалоПериода и КонецПериода (которые автоматически создаются СКД при использовании виртуальных таблиц в запросе) установим флаг «Ограничение доступности». Пользователю не нужно видеть их на форме, они будут заполняться автоматически.
  4. В колонке «Выражение» для параметра НачалоПериода напишем выражение:
    &ПериодОтчета.ДатаНачала
  5. В колонке «Выражение» для параметра КонецПериода напишем выражение:
    &ПериодОтчета.ДатаОкончания

Платформа 1С самостоятельно позаботится о границах дат. Для начала периода время автоматически установится в 00:00:00, а для конца периода — в 23:59:59. Нам больше не нужно вручную прописывать функции приведения к концу дня в тексте запроса.

Причина №3. Производительность и корректность итогов: параметры виртуальной таблицы против секции ГДЕ

Иногда на форумах можно встретить вредные советы: «Если период не работает, просто перейдите на закладку \"Условия\" и наложите условие на дату документа или дату регистратора». Давайте проанализируем, почему делать так категорически не рекомендуется.

Представим, что мы пишем запрос к виртуальной таблице оборотов продаж.

Неправильный вариант (фильтрация через ГДЕ):


ВЫБРАТЬ
    ПродажиОбороты.ДокументПродажи КАК ДокументПродажи,
    ПродажиОбороты.СтоимостьОборот КАК СтоимостьОборот
ИЗ
    РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты
ГДЕ
    ПродажиОбороты.Период МЕЖДУ &НачалоПериода И &КонецПериода

При таком подходе СУБД сначала прочитает и рассчитает обороты по всей таблице регистра за всю историю его существования, и только потом, на самом последнем этапе, начнет отсекать записи, не подходящие под условие ГДЕ. Если в вашей базе миллионы записей, этот отчет будет выполняться крайне медленно и может привести к зависанию всей системы.

Правильный вариант (передача параметров в виртуальную таблицу):


ВЫБРАТЬ
    ПродажиОбороты.ДокументПродажи КАК ДокументПродажи,
    ПродажиОбороты.СтоимостьОборот КАК СтоимостьОборот
ИЗ
    РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода) КАК ПродажиОбороты

Когда параметры передаются непосредственно в круглые скобки виртуальной таблицы, СУБД выполняет фильтрацию на уровне индексов еще до расчета итогов. Выбирается строго необходимый срез данных, что работает в десятки и сотни раз быстрее.

Кроме того, при использовании виртуальных таблиц остатков (или остатков и оборотов) фильтрация через секцию ГДЕ гарантированно приведет к искажению и неверному расчету конечных остатков в отчете. Запомните правило: любые ограничения по времени для виртуальных таблиц должны передаваться исключительно в их параметры!

Как отлаживать подобные проблемы самостоятельно?

Если вы настроили параметры, проверили программный код, но данные все равно не сходятся, используйте проверенные инструменты отладки:

Мы надеемся, что этот подробный разбор поможет вам избежать досадных ошибок при работе с периодами в СКД, а ваши отчеты всегда будут работать быстро и выдавать только корректные данные!

← На главную