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