Разработка отчетов в Системе компоновки данных (СКД) — одна из самых частых задач для разработчика 1С. Казалось бы, настройка периода в отчете — базовая операция, которая должна выполняться автоматически. Однако на практике разработчики часто сталкиваются с ситуацией, когда пользователь выбирает период на форме, но в отчет все равно попадают документы или движения за другие даты. Бывает и хуже: отчет выводит данные корректно только при определенных действиях, например, если зайти в расширенные настройки и нажать «Закрыть и сформировать».
В этой статье мы подробно разберем, почему может возникать подобное поведение, проанализируем распространенные ошибки при работе с параметрами виртуальных таблиц и выясним, как некорректный программный код в модуле отчета может полностью «сломать» передачу дат из пользовательской формы.
Давайте рассмотрим типичный сценарий. Разработчик спроектировал простейшую схему компоновки данных, выводящую данные по оборотам регистра накопления. В схеме настроен стандартный период, параметры связаны, но при формировании отчета фильтрация по датам не происходит.
Как показывает практика и разбор реальных кейсов с форумов, причин у этой проблемы может быть несколько:
ПриКомпоновкеРезультата написан код, который затирает, обнуляет или некорректно инициализирует настройки компоновщика.Давайте детально разберем каждую из этих ситуаций и найдем универсальные, правильные решения.
Очень часто для кастомизации вывода отчета (например, для вывода в разные вкладки, программной установки заголовков или постобработки таблицы) разработчики используют предопределенную процедуру ПриКомпоновкеРезультата в модуле объекта отчета.
Если в этой процедуре установить стандартную обработку в значение Ложь, то всю цепочку формирования макета и вывода результата программисту приходится писать вручную. Именно на этом этапе чаще всего совершается критическая ошибка.
Давайте посмотрим на пример неправильного кода, из-за которого введенные пользователем даты начала и окончания периода бесследно исчезают:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// ОШИБКА: Инициализация макета выполняется по дефолтным настройкам схемы!
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, ДанныеРасшифровки);
// Дальнейший вывод...
КонецПроцедуры
В чем заключается ошибка? Обратите внимание на второй параметр метода Выполнить. Передавая туда напрямую коллекцию КомпоновщикНастроек.Настройки, мы берем настройки по умолчанию, которые заданы в конфигураторе в схеме СКД. При этом все интерактивные изменения, которые пользователь внес на форме (выбрал даты, установил отборы, поменял группировки), хранятся в другой коллекции — КомпоновщикНастроек.ПользовательскиеНастройки. Они просто игнорируются!
Более того, если в коде присутствует очистка параметров или инициализация параметров по умолчанию (например, установка пустых дат), то СКД получит пустые границы периода, что приведет к выборке данных за все время существования базы.
Правильное решение: для программной компоновки необходимо всегда использовать метод ПолучитьНастройки() компоновщика настроек. Этот метод автоматически объединяет настройки по умолчанию (из конфигуратора), фиксированные настройки и пользовательские настройки с формы в единую результирующую структуру.
Рассмотрим правильный шаблон программного вывода отчета в СКД:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Отключаем стандартный вывод платформы
СтандартнаяОбработка = Ложь;
// ПРАВИЛЬНО: Получаем объединенные настройки (с учетом ввода пользователя на форме)
АктуальныеНастройки = КомпоновщикНастроек.ПолучитьНастройки();
// Если вам нужно программно изменить или проверить параметры, делайте это здесь:
// Например: АктуальныеНастройки.ПараметрыДанных.УстановитьЗначениеПараметра("НачалоПериода", НачалоДня(ТекущаяДата()));
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
// Передаем объединенные настройки в компоновщик макета
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, АктуальныеНастройки, ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
ДокументРезультат.Очистить();
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Использование метода КомпоновщикНастроек.ПолучитьНастройки() гарантирует, что выбранный пользователем период (и любые другие отборы) долетят до процессора компоновки и правильно отработают в запросе. При необходимости реализовать сложные варианты формирования отчетов можно использовать примеры программной работы с СКД и управляемыми формами.
Часто программисты пытаются заставить пользователя выбирать даты начала и окончания периода отдельно. Это крайне неудобно. В платформе 1С общепринятым стандартом является использование типа данных СтандартныйПериод. Он позволяет выбирать удобные интервалы (например, «Этот месяц», «Прошлый квартал», «Вчера») в один клик. Для реализации более сложных интерфейсных решений и синхронизации параметров формы со схемой можно использовать методику стыковки элементов управляемой формы и пользовательских настроек СКД.
Давайте пошагово настроим правильную связь стандартного периода и параметров виртуальной таблицы регистра в конструкторе СКД:
ПериодОтчета. Установим для него тип значения СтандартныйПериод. Именно этот параметр мы сделаем доступным пользователю на форме (поставим флаг «Включать в пользовательские настройки»).НачалоПериода и КонецПериода (которые автоматически создаются СКД при использовании виртуальных таблиц в запросе) установим флаг «Ограничение доступности». Пользователю не нужно видеть их на форме, они будут заполняться автоматически.НачалоПериода напишем выражение:
&ПериодОтчета.ДатаНачала
КонецПериода напишем выражение:
&ПериодОтчета.ДатаОкончания
Платформа 1С самостоятельно позаботится о границах дат. Для начала периода время автоматически установится в 00:00:00, а для конца периода — в 23:59:59. Нам больше не нужно вручную прописывать функции приведения к концу дня в тексте запроса.
Иногда на форумах можно встретить вредные советы: «Если период не работает, просто перейдите на закладку \"Условия\" и наложите условие на дату документа или дату регистратора». Давайте проанализируем, почему делать так категорически не рекомендуется.
Представим, что мы пишем запрос к виртуальной таблице оборотов продаж.
Неправильный вариант (фильтрация через ГДЕ):
ВЫБРАТЬ
ПродажиОбороты.ДокументПродажи КАК ДокументПродажи,
ПродажиОбороты.СтоимостьОборот КАК СтоимостьОборот
ИЗ
РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты
ГДЕ
ПродажиОбороты.Период МЕЖДУ &НачалоПериода И &КонецПериода
При таком подходе СУБД сначала прочитает и рассчитает обороты по всей таблице регистра за всю историю его существования, и только потом, на самом последнем этапе, начнет отсекать записи, не подходящие под условие ГДЕ. Если в вашей базе миллионы записей, этот отчет будет выполняться крайне медленно и может привести к зависанию всей системы.
Правильный вариант (передача параметров в виртуальную таблицу):
ВЫБРАТЬ
ПродажиОбороты.ДокументПродажи КАК ДокументПродажи,
ПродажиОбороты.СтоимостьОборот КАК СтоимостьОборот
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода) КАК ПродажиОбороты
Когда параметры передаются непосредственно в круглые скобки виртуальной таблицы, СУБД выполняет фильтрацию на уровне индексов еще до расчета итогов. Выбирается строго необходимый срез данных, что работает в десятки и сотни раз быстрее.
Кроме того, при использовании виртуальных таблиц остатков (или остатков и оборотов) фильтрация через секцию ГДЕ гарантированно приведет к искажению и неверному расчету конечных остатков в отчете. Запомните правило: любые ограничения по времени для виртуальных таблиц должны передаваться исключительно в их параметры!
Если вы настроили параметры, проверили программный код, но данные все равно не сходятся, используйте проверенные инструменты отладки:
01.01.0001 (пустая дата), значит, проблема точно кроется в затирании параметров в коде 1С.Мы надеемся, что этот подробный разбор поможет вам избежать досадных ошибок при работе с периодами в СКД, а ваши отчеты всегда будут работать быстро и выдавать только корректные данные!