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