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