При разработке отчета на СКД часто требуется указать связь между параметрами этого отчета. Например если в отчете имеется параметры "Номенклатура" и "Серия", при выборе серии показывать только серии данной номенклатуры. Или нужно отображать в списке выбора элементов справочника "ЗначенияСвойствОбъектов" только значения, принадлежащие определенному элементу плана видов характеристик "ДополнительныеРеквизитыИСведения". Несмотря на то, что в полях и параметрах СКД есть возможность указать параметры выбора и связи параметров выбора, этот механизм не работает (по крайней мере, так обстоит дело в ERP 2.4.9.98).
Можно написать свою форму отчета, разместить на ней элементы отбора и сделать в ней все, что угодно. Но не хотелось бы терять мощные механизмы общей формы "ФормаОтчета" или копипастить их в свой отчет.
Можно модифицировать общую форму "ФормаОтчета" под свои задачи. Но не хотелось бы это делать каждый раз при разработке нового отчетов.
Предлагаю пример решения этой задачи для двух вариантов:
1. Фиксированный параметр выбора для поля "Отбор". В отчете сделан отбор по полю с типом "Справочник.ЗначенияСвойствОбъектов". При выборе значения отбора требуется показать пользователю только элементы с заданным владельцем.
2. Связи параметров выбора для поля "Параметр". В отчете имеется 2 параметра: Номенклатура и Серия. При выборе серии, показывать пользователю только серии выбранной номенклатуры
1. Фиксированный параметр выбора
Создаем отчет (файл ВнешнийОтчет_ФиксированныеПараметрыОтбора.erf).
Если отчет встроен в расширение, то необходимо:
1. Добавить в расширение подсистему ПодключаемыеОтчетыИОбработки
2. Добавить отчет в эту подсистему
3. В модуле менеджера отчета написать код:
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
Процедура ПриОпределенииНастроек(Настройки) Экспорт
Настройки.ОпределитьНастройкиФормы = Истина;
КонецПроцедуры
#КонецЕсли
В 1С добавить дополнительный реквизит справочника Номенклатура "Раздел комплектации" с типом значений "Дополнительное значение". Указать или сгенерировать имя реквизита, в моем случае это "РазделКомплектации_c7a03c267bb64e0eb58489873f24c25e"
В отчете составляем текст запроса:
ВЫБРАТЬ
НоменклатураДополнительныеРеквизиты.Ссылка КАК Ссылка,
НоменклатураДополнительныеРеквизиты.Свойство КАК Свойство,
НоменклатураДополнительныеРеквизиты.Значение КАК РазделКомплектации
ИЗ
Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураДополнительныеРеквизиты
ГДЕ
НоменклатураДополнительныеРеквизиты.Свойство = &Свойство
Для поля "РазделКомплектации" нужно указать тип значения СправочникСсылка.ЗначенияСвойствОбъектов
На вкладке "Параметры" укажем выражение для параметра "Свойство": ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", "РазделКомплектации_c7a03c267bb64e0eb58489873f24c25e", Истина)
Включим отбор по полю "РазделКомплектации" в пользовательские настройки: на вкладке "Настройки", "Отбор" добавими отбор "РазделКомплектации", щелкнем на нем правой кнопкой мыши, "Свойства элементов пользовательских настроек", установим флажок "Включать в пользовательские настройки".
В модуле отчета указываем, что мы перехватываем событие "ПослеЗаполненияПанелиБыстрыхНастроек":
Процедура ОпределитьНастройкиФормы(Форма, КлючВарианта, Настройки) Экспорт
Настройки.События.ПослеЗаполненияПанелиБыстрыхНастроек = Истина;
КонецПроцедуры
В обработчике этого события нужно найти элемент формы в панели быстрого отбора, в котором пользователь указывает значение отбора "Раздел комплектации". В параметрах выбора этого элемента задаем отбор по владельцу - плану видов характеристик "Раздел комплектации":
Процедура ПослеЗаполненияПанелиБыстрыхНастроек(Форма, ПараметрыОбновления) Экспорт
ПутьКДаннымПоля_РазделКомплектации = ПутьКДаннымЭлементаФормыЗначенияОтбора("РазделКомплектации");
Для Каждого Элемент Из Форма.Элементы Цикл
Если СтрНачинаетсяС(Элемент.Имя, "КомпоновщикНастроекПользовательскиеНастройкиЭлемент")
И ТипЗнч(Элемент) = Тип("ПолеФормы") Тогда
Если Элемент.ПутьКДанным = ПутьКДаннымПоля_РазделКомплектации Тогда
Массив = Новый Массив;
Массив.Добавить(Новый ПараметрВыбора("Отбор.Владелец", ПВХ_РазделКомплектации()));
ПараметрыВыбора = Новый ФиксированныйМассив(Массив);
Элемент.ПараметрыВыбора = ПараметрыВыбора;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ПутьКДаннымЭлементаФормыЗначенияОтбора(ИмяПоляКомпоновкиДанных)
ПолеКомпоновкиДанных = Новый ПолеКомпоновкиДанных(ИмяПоляКомпоновкиДанных);
Для Каждого Элемент Из КомпоновщикНастроек.Настройки.Отбор.Элементы Цикл
Если Элемент.ЛевоеЗначение = ПолеКомпоновкиДанных Тогда
ИдентификаторПользовательскойНастройки = Элемент.ИдентификаторПользовательскойНастройки;
Прервать;
КонецЕсли;
КонецЦикла;
Если ИдентификаторПользовательскойНастройки = Неопределено Тогда
возврат Неопределено;
КонецЕсли;
ПользовательскиеНастройки = КомпоновщикНастроек.ПользовательскиеНастройки.Элементы;
Для Индекс = 0 По ПользовательскиеНастройки.Количество()-1 Цикл
Если ПользовательскиеНастройки[Индекс].ИдентификаторПользовательскойНастройки = ИдентификаторПользовательскойНастройки Тогда
возврат "Отчет.КомпоновщикНастроек.ПользовательскиеНастройки["+Формат(Индекс, "ЧДЦ=0; ЧН=0; ЧГ=")+"].Значение";
КонецЕсли;
КонецЦикла;
возврат Неопределено;
КонецФункции
Функция ПВХ_РазделКомплектации()
возврат ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", "РазделКомплектации_c7a03c267bb64e0eb58489873f24c25e", Истина)
КонецФункции
2. Связи параметров выбора
Здесь мне уже не получилось обойтись без модификации общей формы "ФормаОтчета". Произошло это потому, что не получилось задать связи параметров выбора в существующих элементах панели быстрых настроек. Я выбрал обходной путь - скрывать существующий элемент формы со значением отбора, и подставлять на его место свой элемент. Связи параметров выбора зависимого элемента (серии) я задаю с данными этого элемента. Я постарался свести изменения ФормыОтчета к минимуму, и сделать их универсальными (их не нужно переписывать при создании другого отчета).
Создаем отчет (файл ВнешнийОтчет_СвязиПараметровВыбора.erf).
Как и в предыдущем примере, если отчет встроен в расширение, то необходимо:
1. Добавить в расширение подсистему ПодключаемыеОтчетыИОбработки
2. Добавить отчет в эту подсистему
3. В модуле менеджера отчета написать:
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
Процедура ПриОпределенииНастроек(Настройки) Экспорт
Настройки.ОпределитьНастройкиФормы = Истина;
КонецПроцедуры
#КонецЕсли
В отчете составляем текст запроса:
ВЫБРАТЬ
РеализацияТоваровУслугСерии.Ссылка КАК Ссылка,
РеализацияТоваровУслугСерии.Количество КАК Количество
ИЗ
Документ.РеализацияТоваровУслуг.Серии КАК РеализацияТоваровУслугСерии
ГДЕ
РеализацияТоваровУслугСерии.Номенклатура = &Номенклатура
И РеализацияТоваровУслугСерии.Серия = &Серия
Параметры "Номенклатура" и "Серия" включим в пользовательские настройки (см. выше).
В модуле отчета указываем, что мы перехватываем событие "ПослеЗаполненияПанелиБыстрыхНастроек":
Процедура ОпределитьНастройкиФормы(Форма, КлючВарианта, Настройки) Экспорт
Настройки.События.ПослеЗаполненияПанелиБыстрыхНастроек = Истина;
КонецПроцедуры
В обработчике этого события:
1. Находим элементы формы - значения параметров "Номенклатура" и "Серия"
2. Добавляем в форму новый реквизит "МойРеквизит_Номенклатура". Добавить элемент формы для этого реквизита.
Элементу формы указать обработчик события "ПриИзменении" (обработчик этого события и будет то единственным изменением общей формы "ФормаОтчета").
3. Скрываем старый элемент формы "Номенклатура".
4. Для элемента формы "Серия" задаем связи параметров выбора.
5. Сохраняем необходимую в дальнейшем информацию в дополнительных свойствах пользовательских настроек компоновщика настроек:
Процедура ПослеЗаполненияПанелиБыстрыхНастроек(Форма, ПараметрыОбновления) Экспорт
//находим элементы формы - параметры "Номенклатура" и "Серия"
ИмяПараметра_Номенклатура = "Номенклатура";
ИдентификаторПользовательскойНастройки_Номенклатура = ИдентификаторПользовательскойНастройки(ИмяПараметра_Номенклатура);
ПутьКДаннымПоля_Номенклатура = ПутьКДаннымЭлементаФормыЗначениеПараметра(ИдентификаторПользовательскойНастройки_Номенклатура);
ИмяПараметра_Серия = "Серия";
ИдентификаторПользовательскойНастройки_Серия = ИдентификаторПользовательскойНастройки(ИмяПараметра_Серия);
ПутьКДаннымПоля_Серия = ПутьКДаннымЭлементаФормыЗначениеПараметра(ИдентификаторПользовательскойНастройки_Серия);
СтарыйЭлемент_Номенклатура = ЭлементФормыПоПутиКДанным(Форма, ПутьКДаннымПоля_Номенклатура);
Если СтарыйЭлемент_Номенклатура = Неопределено Тогда
возврат;
КонецЕсли;
ПараметрыКомпоновкиДанныхСоответствующиеДобавленнымРеквизитам = Новый Структура();
ЗначенияВДобавленныхРеквизитахФормы = Новый Структура();
//добавляем новый реквизит в форму
ИмяДобавляемогоРеквизита_Номенклатура = "МойРеквизит_Номенклатура";
Если Не СуществуетРеквизитФормы(Форма, ИмяДобавляемогоРеквизита_Номенклатура) Тогда
ДобавляемыеРеквизиты = Новый Массив;
РеквизитФормы = Новый РеквизитФормы(ИмяДобавляемогоРеквизита_Номенклатура, Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ДобавляемыеРеквизиты.Добавить(РеквизитФормы);
Форма.ИзменитьРеквизиты(ДобавляемыеРеквизиты);
КонецЕсли;
//заполняем его значение
СохраненноеЗначение_Номенклатура = ПолучитьЗначениеПараметраПользовательскойНастройкиОтчета(Форма, ИдентификаторПользовательскойНастройки_Номенклатура);
Форма[ИмяДобавляемогоРеквизита_Номенклатура] = СохраненноеЗначение_Номенклатура;
//добавляем элемент формы в панель пользовательских настроек
НовыйЭлемент_Номенклатура = Форма.Элементы.Вставить(ИмяДобавляемогоРеквизита_Номенклатура, Тип("ПолеФормы"), СтарыйЭлемент_Номенклатура.Родитель, СтарыйЭлемент_Номенклатура);
НовыйЭлемент_Номенклатура.Вид = ВидПоляФормы.ПолеВвода;
НовыйЭлемент_Номенклатура.ПутьКДанным = ИмяДобавляемогоРеквизита_Номенклатура;
НовыйЭлемент_Номенклатура.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
//эта процедура должна быть определена в общей форме "ФормаОтчета"
НовыйЭлемент_Номенклатура.УстановитьДействие("ПриИзменении", "МоиДобавленныеЭлементыПриИзменении");
//скрываем старый элемент формы
СтарыйЭлемент_Номенклатура.Видимость = Ложь;
//определяем связи параметров выбора
Элемент_Серия = ЭлементФормыПоПутиКДанным(Форма, ПутьКДаннымПоля_Серия);
Если Элемент_Серия <> Неопределено Тогда
Массив = Новый Массив;
Массив.Добавить(Новый СвязьПараметраВыбора("Номенклатура", ИмяДобавляемогоРеквизита_Номенклатура, РежимИзмененияСвязанногоЗначения.Очищать));
СвязиПараметровВыбора = Новый ФиксированныйМассив(Массив);
Элемент_Серия.СвязиПараметровВыбора = СвязиПараметровВыбора;
КонецЕсли;
//сохраняем все необходимые связи в дополнительных свойствах пользовательских настроек.
//они затем используются в процедурах ПриКомпоновкеРезультата этого модуля
//и в МоиДобавленныеЭлементыПриИзменении общей формы "ФормаОтчета"
ПараметрыКомпоновкиДанныхСоответствующиеДобавленнымРеквизитам.Вставить(ИмяДобавляемогоРеквизита_Номенклатура, ИмяПараметра_Номенклатура);
ЗначенияВДобавленныхРеквизитахФормы.Вставить(ИмяДобавляемогоРеквизита_Номенклатура, СохраненноеЗначение_Номенклатура);
Форма.Отчет.КомпоновщикНастроек.ПользовательскиеНастройки.ДополнительныеСвойства.Вставить(
"ЗначенияВДобавленныхРеквизитахФормы", ЗначенияВДобавленныхРеквизитахФормы);
Форма.Отчет.КомпоновщикНастроек.ПользовательскиеНастройки.ДополнительныеСвойства.Вставить(
"ПараметрыКомпоновкиДанныхСоответствующиеДобавленнымРеквизитам", ПараметрыКомпоновкиДанныхСоответствующиеДобавленнымРеквизитам);
КонецПроцедуры
В обработчике события "ПриИзменении" модуля формы "ФормаОтчета" сохраняем в дополнительных свойствах компоновщика выбранное значение поля "МойРеквизит_Номенклатура":
&НаКлиенте
Процедура МоиДобавленныеЭлементыПриИзменении(Элемент)
ЗначенияВДобавленныхРеквизитахФормы = Неопределено;
Если Отчет.КомпоновщикНастроек.ПользовательскиеНастройки.ДополнительныеСвойства.Свойство("ЗначенияВДобавленныхРеквизитахФормы", ЗначенияВДобавленныхРеквизитахФормы)
И ТипЗнч(ЗначенияВДобавленныхРеквизитахФормы) = Тип("Структура") Тогда
ЗначениеДобавленногоРеквизита = Неопределено;
Если ЗначенияВДобавленныхРеквизитахФормы.Свойство(Элемент.Имя, ЗначениеДобавленногоРеквизита) Тогда
//имя добавленного реквизита должно совпадать с именем элемента
Отчет.КомпоновщикНастроек.ПользовательскиеНастройки.ДополнительныеСвойства["ЗначенияВДобавленныхРеквизитахФормы"].Вставить(Элемент.Имя, ЭтотОбъект[Элемент.Имя]);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
В процедуре "При компоновке данных" извлекаем эти данные и подставляем в компоновщик:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
Для Каждого КлючИЗначение Из КомпоновщикНастроек.ПользовательскиеНастройки.ДополнительныеСвойства.ПараметрыКомпоновкиДанныхСоответствующиеДобавленнымРеквизитам Цикл
ПараметрКомпоновкиДанных = Новый ПараметрКомпоновкиДанных(КлючИЗначение.Значение);
Если ПараметрКомпоновкиДанных<>Неопределено Тогда
Для Каждого Элемент Из КомпоновщикНастроек.ПользовательскиеНастройки.Элементы Цикл
Если Элемент.Параметр = ПараметрКомпоновкиДанных Тогда
ЗначениеПользовательскойНастройки = КомпоновщикНастроек.ПользовательскиеНастройки.ДополнительныеСвойства.ЗначенияВДобавленныхРеквизитахФормы[КлючИЗначение.Ключ];
Элемент.Значение = ЗначениеПользовательскойНастройки;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Вспомогательные процедуры модуля объекта отчета:
#Область Вспомогательные
Функция ЭлементФормыПоПутиКДанным(Форма, ПутьКДанным)
Для Каждого Элемент Из Форма.Элементы Цикл
Если СтрНачинаетсяС(Элемент.Имя, "КомпоновщикНастроекПользовательскиеНастройкиЭлемент")
И ТипЗнч(Элемент) = Тип("ПолеФормы") Тогда
Если Элемент.ПутьКДанным = ПутьКДанным Тогда
возврат Элемент;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецФункции
Функция ПутьКДаннымЭлементаФормыЗначениеПараметра(ИдентификаторПользовательскойНастройки)
Если ИдентификаторПользовательскойНастройки = Неопределено Тогда
возврат Неопределено;
КонецЕсли;
ПользовательскиеНастройки = КомпоновщикНастроек.ПользовательскиеНастройки.Элементы;
Для Индекс = 0 По ПользовательскиеНастройки.Количество()-1 Цикл
Если ПользовательскиеНастройки[Индекс].ИдентификаторПользовательскойНастройки = ИдентификаторПользовательскойНастройки Тогда
возврат "Отчет.КомпоновщикНастроек.ПользовательскиеНастройки["+Формат(Индекс, "ЧДЦ=0; ЧН=0; ЧГ=")+"].Значение";
КонецЕсли;
КонецЦикла;
возврат Неопределено;
КонецФункции
Функция ИдентификаторПользовательскойНастройки(ИмяПоляКомпоновкиДанных)
ПараметрКомпоновкиДанных = Новый ПараметрКомпоновкиДанных(ИмяПоляКомпоновкиДанных);
Для Каждого Элемент Из КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы Цикл
Если Элемент.Параметр = ПараметрКомпоновкиДанных Тогда
возврат Элемент.ИдентификаторПользовательскойНастройки;
КонецЕсли;
КонецЦикла;
КонецФункции
Функция ПолучитьЗначениеПараметраПользовательскойНастройкиОтчета(Форма, ИдентификаторПользовательскойНастройки)
Если ИдентификаторПользовательскойНастройки = Неопределено Тогда
возврат Неопределено;
КонецЕсли;
Для Каждого Элемент Из Форма.Отчет.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы Цикл
Если Элемент.ИдентификаторПользовательскойНастройки = ИдентификаторПользовательскойНастройки Тогда
возврат Элемент.Значение;
КонецЕсли;
КонецЦикла;
КонецФункции
Функция СуществуетРеквизитФормы(Форма, ИмяРеквизита)
РеквизитыФормы = Форма.ПолучитьРеквизиты();
Для Каждого Реквизит Из РеквизитыФормы Цикл
Если Реквизит.Имя = ИмяРеквизита Тогда
возврат Истина;
КонецЕсли;
КонецЦикла;
возврат Ложь;
КонецФункции
#КонецОбласти