Как программно добавить поле во все сохраненные варианты отчетов СКД?

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

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

Почему изменения в справочнике не отображаются в интерфейсе?

Для начала проанализируем ситуацию и выясним причину. В системе 1С настройки отчета формируются путем последовательного наложения слоев. Всего таких слоев три:

  1. Основная схема компоновки данных (схема): То, что задал разработчик в конфигураторе.
  2. Настройки варианта: То, что хранится в справочнике ВариантыОтчетов. Это "эталонные" настройки для конкретного варианта.
  3. Пользовательские настройки: Персональные изменения, которые внес пользователь (состав полей, фильтры, сортировки). Они хранятся в Системном хранилище настроек.

Важный момент: если пользователь хотя бы один раз открывал отчет и нажимал "Завершить редактирование" или система автоматически сохранила состояние формы, в системном хранилище создается запись. Эта запись имеет наивысший приоритет. Даже если мы добавим поле в справочник (слой 2), слой 3 (пользовательские настройки) "перекроет" наши изменения, так как в нем зафиксирован старый список выбранных полей без нашего нового элемента.

Шаг 1. Программное изменение справочника вариантов отчетов

Первым делом нам необходимо внести изменения в базу. Мы должны пройтись по справочнику ВариантыОтчетов, найти нужные записи и добавить поле в настройки компоновки. Рассмотрим пример кода, который выполняет эту операцию:


// Получаем ссылку на вариант отчета из справочника
ВариантОбъект = СсылкаНаВариант.ПолучитьОбъект();

// Извлекаем настройки из хранилища значений
НастройкиКомпоновки = ВариантОбъект.Настройки.Получить();

Если НастройкиКомпоновки = Неопределено Тогда
    // Если настроек нет в справочнике, их нужно взять из схемы
    ОтчетОбъект = Отчеты[ИмяОтчета].Создать();
    НастройкиКомпоновки = ОтчетОбъект.СхемаКомпоновкиДанных.НастройкиПоУмолчанию;
КонецЕсли;

// Находим коллекцию выбранных полей
ВыбранныеПоля = НастройкиКомпоновки.Выбор.Элементы;

// Проверяем, нет ли уже такого поля
ПолеУжеЕсть = Ложь;
Для Каждого Поле Из ВыбранныеПоля Цикл
    Если ТипЗнч(Поле) = Тип("ВыбранноеПолеКомпоновкиДанных") 
        И Строка(Поле.Поле) = "НовоеПоле" Тогда
        ПолеУжеЕсть = Истина;
        Прервать;
    КонецЕсли;
КонецЦикла;

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

// Сохраняем настройки обратно в объект справочника
ВариантОбъект.Настройки = Новый ХранилищеЗначения(НастройкиКомпоновки);
ВариантОбъект.Записать();

После выполнения этого кода "базовый" вариант изменен. Однако, как мы выяснили, пользователи с уже сохраненными настройками изменений не увидят.

Шаг 2. Работа с системным хранилищем настроек

Теперь перейдем к самому сложному — обновлению персональных настроек пользователей. В БСП и платформе 1С они хранятся в СтандартноеХранилищеНастроек. Чтобы изменения вступили в силу, у нас есть два пути: удалить старые пользовательские настройки (тогда система возьмет новые из справочника) или обновить их программно для каждого пользователя.

Рассмотрим структуру ключей, которые используются для поиска настроек в хранилище:

Вариант А: Кардинальный (Очистка настроек)

Проанализируем ситуацию: если пользователей много, а их персональные фильтры не критичны, проще всего удалить записи из хранилища. При следующем открытии отчета СКД автоматически подтянет обновленные настройки из справочника ВариантыОтчетов.


// Пример очистки настроек для всех пользователей
ВсеПользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
КлючОбъекта = "Отчет.Продажи/Основной/ТекущиеПользовательскиеНастройки";

Для Каждого ТекущийПользователь Из ВсеПользователи Цикл
    ХранилищеСистемныхНастроек.Удалить(КлючОбъекта, "", ТекущийПользователь.Имя);
КонецЦикла;

Вариант Б: Мягкий (Программное обновление)

Если нам важно сохранить пользовательские фильтры, но добавить в их список полей наше новое поле, придется выполнить итерацию по всем пользователям и модифицировать объект ДанныеКомпоновкиДанныхПользовательскиеНастройки. Посмотрим на пример реализации этой задачи:


// Используем функции общего назначения БСП для безопасной работы с хранилищем
Для Каждого ПользовательИБ Из ПользователиИнформационнойБазы.ПолучитьПользователей() Цикл
    
    // Ключ формируется согласно стандартам БСП
    ПолныйКлючОбъекта = "Отчет." + ИмяОтчета + "/" + КлючВарианта + "/ТекущиеПользовательскиеНастройки";
    
    // Загружаем настройки конкретного пользователя
    ПользовательскиеНастройки = ХранилищеСистемныхНастроек.Загрузить(ПолныйКлючОбъекта, "", , ПользовательИБ.Имя);
    
    Если ТипЗнч(ПользовательскиеНастройки) = Тип("ДанныеКомпоновкиДанныхПользовательскиеНастройки") Тогда
        
        // В пользовательских настройках нужно найти элемент, отвечающий за выбранные поля
        Для Каждого ЭлементНастройки Из ПользовательскиеНастройки.Элементы Цикл
            
            // Проверяем, является ли элемент коллекцией выбранных полей
            Если ТипЗнч(ЭлементНастройки) = Тип("ВыбранныеПоляКомпоновкиДанных") Тогда
                
                // Проверяем наличие поля, чтобы не дублировать
                ПолеНайдено = Ложь;
                Для Каждого ВыбранноеПоле Из ЭлементНастройки.Элементы Цикл
                    Если Строка(ВыбранноеПоле.Поле) = "НовоеПоле" Тогда
                        ПолеНайдено = Истина;
                        Прервать;
                    КонецЕсли;
                КонецЦикла;
                
                Если Не ПолеНайдено Тогда
                    НовоеПолеПользователя = ЭлементНастройки.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
                    НовоеПолеПользователя.Поле = Новый ПолеКомпоновкиДанных("НовоеПоле");
                    НовоеПолеПользователя.Использование = Истина;
                КонецЕсли;
                
            КонецЕсли;
        КонецЦикла;
        
        // Сохраняем обновленные настройки обратно в хранилище для этого пользователя
        ХранилищеСистемныхНастроек.Сохранить(ПолныйКлючОбъекта, "", ПользовательскиеНастройки, , ПользовательИБ.Имя);
        
    КонецЕсли;
КонецЦикла;

Нюансы работы в ERP и БСП

В современных версиях БСП (библиотеки стандартных подсистем) работа с вариантами отчетов может быть дополнительно обернута в программный интерфейс модуля ВариантыОтчетов. Рассмотрим важные моменты:

Резюме

Чтобы успешно добавить поле во все варианты отчетов, мы должны действовать комплексно. Просто изменить справочник недостаточно — пользовательские настройки всегда будут иметь приоритет. Выясним, критично ли сохранение текущих настроек пользователей. Если нет — очистим хранилище. Если да — используем цикл по пользователям ИБ и точечно модифицируем ДанныеКомпоновкиДанныхПользовательскиеНастройки. Такой подход гарантирует, что при следующем запуске отчета каждый сотрудник увидит обновленный состав полей без необходимости ручной настройки.

← На главную