При разработке отчетов на системе компоновки данных (СКД) программисты часто сталкиваются с типовым поведением платформы 1С: когда пользователь один раз меняет дату или период в отчете, система запоминает этот выбор. При следующем открытии отчета платформа услужливо подставляет «вчерашние» настройки из хранилища. Это удобно для пользователя, но критично, если бизнес-логика требует, чтобы отчет всегда открывался с актуальной датой (например, на начало текущего дня), сохраняя при этом возможность ручной корректировки.
В этой статье мы подробно разберем, как решить эту задачу, не прибегая к созданию отдельной управляемой формы отчета, используя возможности модуля объекта и механизмы Библиотеки стандартных подсистем (БСП).
Рассмотрим ситуацию: в схеме компоновки данных на закладке «Параметры» мы можем указать выражение для параметра Период, например, &ТекущаяДата или НачалоПериода(ТекущаяДата(), "День"). Однако это значение считается «значением по умолчанию». Система применит его только в тот момент, когда пользователь открывает отчет в самый первый раз. Как только пользователь изменит дату и сформирует отчет, платформа сохранит эти настройки в системное хранилище. При повторном открытии приоритет будет отдан сохраненным настройкам, а не выражению в схеме.
Чтобы обойти это ограничение без создания формы, нам необходимо программно вмешаться в процесс загрузки настроек. Проанализируем, как это сделать наиболее эффективно.
Если ваша конфигурация построена на базе БСП (что справедливо для большинства современных конфигураций, таких как 1С:ERP, 1С:Управление торговлей 11 или 1С:Бухгалтерия 3.0), мы можем использовать специальные экспортные процедуры в модуле объекта отчета. Это позволяет перехватить событие открытия отчета в стандартной форме.
Разберем по шагам, какой код необходимо добавить в модуль объекта отчета:
ОпределитьНастройкиФормы, чтобы сообщить системе, что мы хотим обрабатывать событие загрузки настроек на сервере.ПриЗагрузкеПользовательскихНастроекНаСервере, где и пропишем установку нужной даты.Рассмотрим пример кода:
// В модуле объекта отчета
Процедура ОпределитьНастройкиФормы(Форма, КлючВарианта, Настройки) Экспорт
// Разрешаем перехват события загрузки пользовательских настроек
Настройки.События.ПриЗагрузкеПользовательскихНастроекНаСервере = Истина;
КонецПроцедуры
Процедура ПриЗагрузкеПользовательскихНастроекНаСервере(Форма, НовыеПользовательскиеНастройкиКД) Экспорт
// Получаем доступ к компоновщику настроек
КомпоновщикНастроек = Форма.Отчет.КомпоновщикНастроек;
// Ищем нужный нам параметр в основной схеме (чтобы получить его идентификатор)
ПараметрОбъект = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("Период");
Если ПараметрОбъект <> Неопределено Тогда
// Ищем этот же параметр в пользовательских настройках по идентификатору
ПараметрПользовательский = КомпоновщикНастроек.ПользовательскиеНастройки.Элементы.Найти(ПараметрОбъект.ИдентификаторПользовательскойНастройки);
Если ПараметрПользовательский <> Неопределено Тогда
// Устанавливаем требуемое значение - начало текущего дня
ПараметрПользовательский.Значение = НачалоДня(ТекущаяДата());
ПараметрПользовательский.Использование = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важный нюанс: в данном примере мы обращаемся к КомпоновщикНастроек.ПользовательскиеНастройки. Это важно, так как именно значения из пользовательских настроек отображаются в шапке отчета на форме и имеют приоритет при формировании.
Часто в отчетах используется не просто тип Дата, а тип СтандартныйПериод. В этом случае подход остается прежним, но меняется способ установки значения. Выясним, как правильно инициализировать период.
Проанализируем ситуацию: если нам нужно установить период «Сегодня», код внутри процедуры будет выглядеть следующим образом:
// Если параметр имеет тип СтандартныйПериод
НовыйПериод = Новый СтандартныйПериод;
НовыйПериод.Вариант = ВариантСтандартногоПериода.Сегодня;
// Либо задать произвольные даты
// НовыйПериод.Вариант = ВариантСтандартногоПериода.ПроизвольныйПериод;
// НовыйПериод.ДатаНачала = НачалоДня(ТекущаяДата());
// НовыйПериод.ДатаОкончания = КонецДня(ТекущаяДата());
ПараметрПользовательский.Значение = НовыйПериод;
ПараметрПользовательский.Использование = Истина;
Если вы работаете с типовой конфигурацией и не хотите изменять модуль объекта (чтобы не снимать отчет с поддержки), мы можем применить Расширение. В расширении можно создать процедуру-обработчик для общей формы отчета, которая используется в БСП.
Рассмотрим алгоритм действий:
ФормаОтчета (обычно это ОбщаяФорма.ФормаОтчета из состава БСП).&После("ПриСозданииНаСервере").Посмотрим на пример реализации в расширении:
&После("ПриСозданииНаСервере")
Процедура Расш_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем, что форма открыта для конкретного отчета
Если ЭтотОбъект.Отчет.Метаданные().Имя = "НашКритическиВажныйОтчет" Тогда
ПараметрыДанных = ЭтотОбъект.Отчет.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы;
// Дальнейшая логика поиска и установки параметра аналогична коду в модуле объекта
КонецЕсли;
КонецПроцедуры
Существует еще один способ гарантировать «чистоту» параметров при открытии — это управление свойством ХранилищеНастроек в свойствах отчета. Если в конфигураторе для отчета указать пустое хранилище настроек или реализовать свой объект хранилища, система перестанет запоминать выбор пользователя. Однако этот метод радикален: пользователь потеряет возможность сохранять вообще любые свои настройки (отборы, группировки, сортировки).
Поэтому программная установка в ПриЗагрузкеПользовательскихНастроекНаСервере остается самым гибким и рекомендуемым методом. Мы позволяем пользователю сохранять сложные отборы и структуру отчета, но принудительно «обнуляем» только критически важный параметр даты при каждом новом сеансе работы с формой.
Подведем итоги: для реализации задачи без создания формы наиболее правильно использовать экспортные процедуры БСП в модуле объекта отчета. Это сохраняет чистоту структуры метаданных и обеспечивает надежное управление поведением отчета в управляемом интерфейсе 1С:Предприятие 8.3.