Как сохранить и восстановить настройки внешнего отчета без СКД для всех пользователей в 1С?

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

При разработке внешних отчетов на управляемых формах часто возникает задача: пользователь настраивает параметры отчета (период, списки отборов, реквизиты), сохраняет их, а другой пользователь при открытии отчета должен получить уже измененные значения. Если отчет построен на системе компоновки данных (СКД), с этой задачей справляется типовая подсистема вариантов отчетов БСП. Однако если отчет написан программно, без использования СКД, разработчики сталкиваются с рядом платформенных ограничений.

Рассмотрим, почему стандартные средства платформы работают персонально для каждого пользователя, проанализируем ограничения файлового подхода и разберем проверенные варианты реализации единых настроек.

Ограничения стандартных механизмов платформы

Выясним причину, по которой стандартные свойства формы не решают задачу общего доступа:

  1. Изоляция настроек сеанса. Свойство формы АвтоматическоеСохранениеДанныхВНастройках и системные объекты ХранилищеОбщихНастроек, ХранилищеСистемныхНастроек и ХранилищеНастроекДанныхФорм по умолчанию сохраняют структуру значений строго в разрезе текущего пользователя информационной базы.
  2. Ограничение прав на запись чужих настроек. Метод ХранилищеОбщихНастроек.Сохранить() позволяет передать имя конкретного пользователя, но для сохранения настроек под другим именем требуются административные права (Администрирование или СохранениеДанныхПользователя). У обычного пользователя в рабочей базе при такой попытке возникнет ошибка нарушения прав доступа.
  3. Ограничение безопасного режима. Вызов УстановитьПривилегированныйРежим(Истина) во внешнем отчете, открытом через меню «Файл — Открыть», заблокирован платформой. Включить привилегированный режим можно только в том случае, если отчет зарегистрирован в справочнике ДополнительныеОтчетыИОбработки с отключенным безопасным режимом.

Анализ сохранения через файлы и внутренние строки

Посмотрим на пример ручной сериализации реквизитов отчета, предложенный на форуме:


// Сохранение настроек в файл
Реквизиты = ЭтотОбъект.Метаданные().Реквизиты;
СтруктураЭлементов = Новый Структура;

Для Каждого ЭлементФормы Из Реквизиты Цикл
    Если ЭлементФормы.Имя = "Организация" Тогда
        ЗнВСтр = ЗначениеВСтрокуВнутр(Организации);
        СтруктураЭлементов.Вставить(ЭлементФормы.Имя, ЗнВСтр);
    Иначе
        ЗнВСтр = ЗначениеВСтрокуВнутр(ЭтотОбъект[ЭлементФормы.Имя]);
        СтруктураЭлементов.Вставить(ЭлементФормы.Имя, ЗнВСтр);
    КонецЕсли;
КонецЦикла;

ЗначениеВФайл(ФайлНастроек, СтруктураЭлементов);

И восстановление данных из полученного файла:


// Восстановление настроек из файла
СтруктураЭлементов = ЗначениеИзФайла(ФайлНастроек);
Реквизиты = ЭтотОбъект.Метаданные().Реквизиты;

Для Каждого ЭлементФормы Из Реквизиты Цикл
    Попытка
        Если ЭлементФормы.Имя = "Организация" Тогда
            Организации = ЗначениеИзСтрокиВнутр(СтруктураЭлементов[ЭлементФормы.Имя]);
        Иначе
            ЭтотОбъект[ЭлементФормы.Имя] = ЗначениеИзСтрокиВнутр(СтруктураЭлементов[ЭлементФормы.Имя]);
        КонецЕсли;
    Исключение
        // Обработка отсутствующих реквизитов
    КонецПопытки;
КонецЦикла;

Проанализируем архитектурные недостатки данного подхода в реальной эксплуатации:

  1. Несовместимость с клиент-серверной архитектурой. Методы ЗначениеВФайл и ЗначениеИзФайла требуют наличия общего пути в файловой системе. На клиенте и сервере пути различаются, в веб-клиенте доступ к файловой системе ограничен, а при наличии кластера серверов 1С с несколькими рабочими машинами локальный файл будет недоступен для других процессов.
  2. Опасность функции ЗначениеВСтрокуВнутр. Этот формат жестко завязан на внутренние идентификаторы (UUID). При переносе базы, изменении или удалении ссылочных данных функция ЗначениеИзСтрокиВнутр может возвращать «битые ссылки» (объект не найден). Для сериализации данных предпочтительнее использовать СериализаторXDTO или формат JSON.

Вариант 1. Использование фиктивной СКД и штатной БСП (рекомендуемый)

Разберем наиболее надежный и поддерживаемый путь для конфигурации ЗУП 3.1. Типовая подсистема «Варианты отчетов» рассчитана на работу с СКД и предоставляет пользователям готовый интерфейс: сохранение настроек, загрузка, выбор видимости («Только автору» или «Всем пользователям»).

Чтобы подключить этот механизм к нетиповому отчету, сделаем следующее:

  1. Добавим в отчет минимальную («фиктивную») схему компоновки данных. В ней не обязательно создавать сложные наборы данных — достаточно объявить параметры или поля, которые должны настраиваться пользователями.
  2. В свойствах объекта отчета установим свойство Хранилище вариантов в значение ХранилищеВариантовОтчетов.
  3. В модуле объекта отчета переопределим стандартное формирование через предопределенное событие ПриКомпоновкеРезультата. В нем сформируем отчет программно, отключив стандартную компоновку:

Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Считываем пользовательские настройки СКД
    ПользовательскиеНастройки = КомпоновщикНастроек.ПользовательскиеНастройки;
    
    // Формируем собственный табличный документ программным алгоритмом
    СформироватьОтчетВручную(ДокументРезультат, ПользовательскиеНастройки);
    
КонецПроцедуры

В этом случае пользователи получают весь штатный функционал ЗУП 3.1: сохранение настроек для всех пользователей информационной базы без написания сложного кода чтения/записи.

Вариант 2. Программное сохранение структуры в информационную базу

Если добавление схемы компоновки данных нежелательно, настройки необходимо сохранять централизованно непосредственно в базу данных. Для внешнего отчета, подключенного через подсистему «Дополнительные отчеты и обработки» (с отключенным безопасным режимом), запись настроек можно реализовать через служебный регистр сведений или реквизит элемента справочника.

Разберем по шагам обработку событий управляемой формы отчета с упаковкой реквизитов через ХранилищеЗначения:


&НаСервере
Процедура СохранитьНастройкиНаСервере()
    
    УстановитьПривилегированныйРежим(Истина);
    
    СтруктураНастроек = Новый Структура;
    СтруктураНастроек.Вставить("Организация", Отчет.Организация);
    СтруктураНастроек.Вставить("ПериодРегистрации", Отчет.ПериодРегистрации);
    СтруктураНастроек.Вставить("Подразделение", Отчет.Подразделение);
    
    Хранилище = Новый ХранилищеЗначения(СтруктураНастроек, Новый СжатиеДанных(9));
    
    // Записываем данные в общее хранилище настроек конфигурации под системным ключом
    ХранилищеОбщихНастроек.Сохранить(
        "НастройкиВнешнегоОтчета_Свод",
        "ОбщиеНастройкиДляВсех",
        Хранилище
    );
    
КонецПроцедуры

&НаСервере
Процедура ЗагрузитьНастройкиНаСервере()
    
    УстановитьПривилегированныйРежим(Истина);
    
    Хранилище = ХранилищеОбщихНастроек.Загрузить(
        "НастройкиВнешнегоОтчета_Свод",
        "ОбщиеНастройкиДляВсех"
    );
    
    Если ТипЗнч(Хранилище) = Тип("ХранилищеЗначения") Тогда
        СтруктураНастроек = Хранилище.Получить();
        Если ТипЗнч(СтруктураНастроек) = Тип("Структура") Тогда
            ЗаполнитьЗначенияСвойств(Отчет, СтруктураНастроек);
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Вызов процедуры ЗагрузитьНастройкиНаСервере() помещается в обработчик формы ПриСозданииНаСервере, а сохранение настроек вызывается по нажатию специальной кнопки команды на форме («Сохранить общие настройки») либо в процедуре перед закрытием формы.

Применение привилегированного режима здесь обязательно, так как метод ХранилищеОбщихНастроек.Сохранить() с общим разделением ключа требует повышенных прав доступа.

← На главную