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