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