Как программно работать с группами и элементами, созданными пользователем в режиме «Изменить форму»?

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

В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда пользователь самостоятельно настраивает интерфейс под себя: создает новые группы, перетаскивает поля, меняет заголовки через меню «Изменить форму». Однако при попытке программно обратиться к этим новым группам через стандартную коллекцию ЭтаФорма.Элементы, выясняется, что их там попросту нет. В этой статье мы подробно разберем, почему так происходит, и какие инструменты существуют для решения этой задачи.

Анализируем причину: почему коллекция Элементы «не видит» пользовательские правки

Разберем внутреннее устройство управляемой формы. Коллекция ЭтаФорма.Элементы содержит только те объекты, которые определены на этапе разработки в конфигураторе или были добавлены программно с помощью метода Элементы.Добавить(). Пользовательские же изменения (создание групп, изменение порядка) — это не изменение самой структуры формы, а наложение декоративного слоя настроек.

Платформа хранит эти изменения отдельно от метаданных формы. При открытии формы система берет «эталонную» структуру из конфигуратора и «накатывает» на нее сохраненные настройки конкретного пользователя. Именно поэтому в коде на сервере мы видим исходную структуру, а пользователь на экране — свою индивидуальную. Если нам нужно программно взаимодействовать с тем, что создал пользователь, стандартный обход коллекции Для Каждого Элемент Из ЭтаФорма.Элементы нам не поможет.

Решение 1: Использование Ключа сохранения настроек

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

Проанализируем ситуацию: если мы программно меняем значение этого ключа, 1С автоматически подгружает соответствующий набор пользовательских настроек из хранилища. Это самый штатный и безопасный способ управления интерфейсом без прямого вмешательства в структуру XML-описания формы.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // В зависимости от условий устанавливаем нужный ключ
    Если ЭтоАдминистратор Тогда
        ЭтаФорма.КлючСохраненияНастроек = "НастройкаДляАдмина";
    Иначе
        ЭтаФорма.КлючСохраненияНастроек = "НастройкаДляПользователя";
    КонецЕсли;
КонецПроцедуры

Решение 2: Работа с объектом НастройкиФормы и XDTO

В современных версиях платформы (8.3.x) появился более продвинутый способ программного доступа к тому, что наворотил пользователь. Мы можем получить объект НастройкиФормы. Этот объект содержит всю информацию о пользовательских группах, видимости и расположении элементов.

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


&НаСервере
Функция ПолучитьСтруктуруПользовательскойФормы()
    // Получаем объект настроек текущей формы
    Настройки = ЭтаФорма.ПолучитьНастройкиФормы();
    
    // Используем сериализатор XDTO для перевода в XML
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.УстановитьСтроку();
    СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Настройки);
    
    Возврат ЗаписьXML.Закрыть(); // Здесь будет XML с описанием всех групп
КонецФункции

Проанализировав полученный XML, вы увидите узлы, соответствующие пользовательским группам. Это позволяет «увидеть» структуру, даже если она не представлена в ЭтаФорма.Элементы.

Решение 3: Программное создание элементов вместо пользовательского

Как отмечалось в обсуждении на форуме, наиболее надежный путь — это перехват инициативы. Вместо того чтобы позволять пользователю создавать группы вручную через интерфейс, мы можем реализовать в форме кнопку «Создать группу», которая будет выполнять код на сервере.

Выясним преимущество: элементы, созданные методом Элементы.Добавить(), будут видны в коллекции ЭтаФорма.Элементы. Мы сможем управлять их видимостью, цветом и вложенностью стандартными методами. Посмотрим на пример программного создания группы:


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

Решение 4: Чтение через ХранилищеСистемныхНастроек

Если нам нужно прочитать настройки формы другого пользователя или скопировать их, мы можем обратиться к ХранилищеСистемныхНастроек. Данные там хранятся по ключу вида "ВнешнийВид/НастройкиФорм/ИмяВашейФормы".

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

Алгоритм действий при использовании этого метода:

  1. Получаем данные из хранилища системных настроек.
  2. Применяем ЗначениеВСтрокуВнутр() к объекту настроек.
  3. Используем регулярные выражения или строковые функции для поиска имен пользовательских элементов.
  4. Помним, что этот метод не является официальным и может измениться в будущих версиях платформы.

Подводим итоги

Мы выяснили, что архитектура управляемых форм в 1С жестко разделяет структуру (доступную в коде) и представление (настраиваемое пользователем). Если вам жизненно необходимо управлять группами, которые создает пользователь, лучше всего:

Помните, что попытки парсить внутренние строки платформы — это крайняя мера, которую стоит применять только тогда, когда стандартные методы НастройкиФормы не дают нужного результата.

← На главную