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