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