При разработке отчетов на базе типового механизма «Универсальный отчет» (часто встречающегося в конфигурациях «Управление производственным предприятием 1.2/1.3», «Управление торговлей 10.3» или «Комплексная автоматизация 1.1») программисты часто сталкиваются с необходимостью добавить на форму собственные реквизиты. Это могут быть такие параметры, как КоличествоЛет, Периодичность или флаги управления логикой запроса. Проблема заключается в том, что стандартный механизм сохранения настроек «подхватывает» только настройки построителя (фильтры, группировки, поля), игнорируя новые добавленные элементы. Разберем, как элегантно решить эту задачу, не внося изменений в сам объект УниверсальныйОтчет.
Проанализируем ситуацию: «Универсальный отчет» — это сложная надстройка над ПостроителемОтчета. Когда пользователь нажимает кнопку «Сохранить настройку», система вызывает экспортный метод, который собирает данные из Построителя и упаковывает их в структуру. Поскольку ваши новые реквизиты (например, КоличествоЛет) не являются частью Построителя, они просто не попадают в итоговый пакет данных, который записывается в регистр сведений СохраненныеНастройки.
Наша задача — принудительно «подмешать» значения этих реквизитов в структуру сохранения и правильно извлечь их при восстановлении настройки. Рассмотрим несколько способов реализации этой задачи.
Если нам нужно быстро добавить сохранение пары параметров, мы можем перехватить момент сохранения непосредственно в командах формы. Рассмотрим пример кода, который необходимо разместить в модуле формы вашего отчета:
Процедура КоманднаяПанельФормыСохранитьНастройку(Кнопка)
// Перед вызовом типового сохранения принудительно вставляем данные в структуру
ЭтотОбъект.УниверсальныйОтчет.мТекущаяНастройка.СохраненнаяНастройка.Вставить("КоличествоЛет", КоличествоЛет);
ЭтотОбъект.УниверсальныйОтчет.мТекущаяНастройка.СохраненнаяНастройка.Вставить("ГруппировкаКолонок", Периодичность);
// Вызываем стандартный механизм
УниверсальныйОтчет.СохранитьНастройки(УниверсальныйОтчет, ЭтотОбъект, ЭтаФорма);
КонецПроцедуры
Процедура КоманднаяПанельФормыВосстановитьНастройку(Кнопка)
// Вызываем типовое восстановление
УниверсальныйОтчет.ВосстановитьНастройки(УниверсальныйОтчет, ЭтотОбъект, ЭтаФорма);
// После того как структура заполнена, извлекаем наши значения
Настройка = УниверсальныйОтчет.мТекущаяНастройка.СохраненнаяНастройка;
Если Настройка.Свойство("КоличествоЛет") Тогда
КоличествоЛет = Настройка.КоличествоЛет;
КонецЕсли;
Если Настройка.Свойство("ГруппировкаКолонок") Тогда
Периодичность = Настройка.ГруппировкаКолонок;
КонецЕсли;
КонецПроцедуры
Этот метод работает, но он требует вмешательства в обработчики кнопок формы. Существует более «чистый» архитектурный подход.
В архитектуре «Универсального отчета» предусмотрены специальные «точки входа», которые вызываются автоматически. Если в модуле вашего отчета (не формы, а самого объекта) определить процедуры СформироватьСтруктуруДляСохраненияНастроек и ВосстановитьНастройкиИзСтруктуры, система будет использовать их. Это позволяет разделить логику интерфейса и логику хранения данных.
Разберем реализацию этого подхода по шагам:
// В модуле объекта отчета
Процедура СформироватьСтруктуруДляСохраненияНастроек(СтруктураСНастройками) Экспорт
// Сначала даем Универсальному отчету заполнить стандартные поля
УниверсальныйОтчет.СформироватьСтруктуруДляСохраненияНастроек(СтруктураСНастройками);
// Добавляем свои параметры
СтруктураСНастройками.Вставить("КоличествоЛет", КоличествоЛет);
СтруктураСНастройками.Вставить("ГруппировкаКолонок", ГруппировкаКолонок);
КонецПроцедуры
Функция ВосстановитьНастройкиИзСтруктуры(СтруктураСНастройками) Экспорт
// Восстанавливаем свои параметры вручную из переданной структуры
Если СтруктураСНастройками.Свойство("КоличествоЛет") Тогда
КоличествоЛет = СтруктураСНастройками.КоличествоЛет;
КонецЕсли;
Если СтруктураСНастройками.Свойство("ГруппировкаКолонок") Тогда
ГруппировкаКолонок = СтруктураСНастройками.ГруппировкаКолонок;
КонецЕсли;
// Передаем управление Универсальному отчету для восстановления остального
Возврат УниверсальныйОтчет.ВосстановитьНастройкиИзСтруктуры(СтруктураСНастройками, ЭтотОбъект);
КонецФункции
В типовых конфигурациях (УПП, УТ 10.3) существует отличный вспомогательный механизм в общем модуле УправлениеОтчетами. Он позволяет автоматически сохранять все реквизиты объекта, имена которых совпадают с ключами в структуре настроек. Это наиболее лаконичный вариант, так как вам не нужно перечислять каждое поле вручную.
Проанализируем пример реализации в модуле объекта:
Процедура СформироватьСтруктуруДляСохраненияНастроек(СтруктураСНастройками) Экспорт
УниверсальныйОтчет.СформироватьСтруктуруДляСохраненияНастроек(СтруктураСНастройками);
// Метод автоматически найдет реквизиты отчета и поместит их в структуру
УправлениеОтчетами.СохранитьРеквизитыОтчета(ЭтотОбъект, СтруктураСНастройками);
КонецПроцедуры
Функция ВосстановитьНастройкиИзСтруктуры(СтруктураСНастройками) Экспорт
// Метод автоматически заполнит реквизиты отчета из структуры по именам
УправлениеОтчетами.ВосстановитьРеквизитыОтчета(ЭтотОбъект, СтруктураСНастройками);
Возврат УниверсальныйОтчет.ВосстановитьНастройкиИзСтруктуры(СтруктураСНастройками, ЭтотОбъект);
КонецФункции
Важный нюанс: Чтобы этот способ сработал, имена реквизитов на закладке «Данные» в конфигураторе должны в точности совпадать с именами, которые используются в логике вашего отчета. Метод СохранитьРеквизитыОтчета работает через перебор метаданных объекта ОтчетОбъект.
Выясним, где физически хранятся эти данные. В обычных формах 1С 8.2 настройки сохраняются в регистр сведений СохраненныеНастройки. Поле Настройка в этом регистре имеет тип ХранилищеЗначения.
Когда мы выполняем Структура.Вставить("Имя", Значение), важно помнить о сериализации:
Число, Строка, Дата, Булево) сохраняются без проблем.СправочникСсылка, ДокументСсылка) сохраняются корректно.ТаблицаЗначений или ПостроительОтчета) сериализуются в XML внутри хранилища.Если вы попытаетесь сохранить объект, который не поддерживает сериализацию (например, COMОбъект или открытое соединение с базой), вся настройка может не сохраниться или выдать ошибку при открытии отчета.
Если вы разрабатываете отчет как внешний файл, помните, что механизм УниверсальныйОтчет привязывает настройки к имени объекта. Для внешних отчетов имя часто формируется динамически или зависит от пути к файлу.
Чтобы настройки гарантированно сохранялись и были доступны всем пользователям, рекомендуется в процедуре ПриОткрытии или в конструкторе объекта явно задавать идентификатор отчета:
УниверсальныйОтчет.ИмяОбъекта = "МойУникальныйОтчетПоПродажам";
Это позволит избежать ситуации, когда после переименования файла Отчет_v1.erf в Отчет_v2.erf все сохраненные настройки пользователей «пропадают».
Мы рассмотрели три способа расширения функционала «Универсального отчета». Наиболее правильным и надежным с точки зрения поддержки кода является Способ 3, использующий возможности общего модуля УправлениеОтчетами. Он минимизирует количество ручного кода и автоматически обрабатывает все добавленные реквизиты отчета. Использование экспортных процедур СформироватьСтруктуруДляСохраненияНастроек в модуле объекта гарантирует, что ваши параметры будут сохраняться в базу данных 1С (в регистр сведений), а не в локальный профиль пользователя Windows, что делает их доступными при работе с любого компьютера.