В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда пользователь самостоятельно настраивает интерфейс под себя: создает новые группы, перетаскивает поля, меняет заголовки через меню «Изменить форму». Однако при попытке программно обратиться к этим новым группам через стандартную коллекцию ЭтаФорма.Элементы, выясняется, что их там попросту нет. В этой статье мы подробно разберем, почему так происходит, и какие инструменты существуют для решения этой задачи.
Разберем внутреннее устройство управляемой формы. Коллекция ЭтаФорма.Элементы содержит только те объекты, которые определены на этапе разработки в конфигураторе или были добавлены программно с помощью метода Элементы.Добавить(). Пользовательские же изменения (создание групп, изменение порядка) — это не изменение самой структуры формы, а наложение декоративного слоя настроек.
Платформа хранит эти изменения отдельно от метаданных формы. При открытии формы система берет «эталонную» структуру из конфигуратора и «накатывает» на нее сохраненные настройки конкретного пользователя. Именно поэтому в коде на сервере мы видим исходную структуру, а пользователь на экране — свою индивидуальную. Если нам нужно программно взаимодействовать с тем, что создал пользователь, стандартный обход коллекции Для Каждого Элемент Из ЭтаФорма.Элементы нам не поможет.
Если ваша задача состоит в том, чтобы сохранить несколько разных вариантов расположения элементов для одной и той же формы (например, «Режим бухгалтера» и «Режим менеджера»), не обязательно пытаться «прочитать» группы. Рассмотрю механизм КлючСохраненияНастроек (WindowSettingsKey).
Проанализируем ситуацию: если мы программно меняем значение этого ключа, 1С автоматически подгружает соответствующий набор пользовательских настроек из хранилища. Это самый штатный и безопасный способ управления интерфейсом без прямого вмешательства в структуру XML-описания формы.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// В зависимости от условий устанавливаем нужный ключ
Если ЭтоАдминистратор Тогда
ЭтаФорма.КлючСохраненияНастроек = "НастройкаДляАдмина";
Иначе
ЭтаФорма.КлючСохраненияНастроек = "НастройкаДляПользователя";
КонецЕсли;
КонецПроцедуры
В современных версиях платформы (8.3.x) появился более продвинутый способ программного доступа к тому, что наворотил пользователь. Мы можем получить объект НастройкиФормы. Этот объект содержит всю информацию о пользовательских группах, видимости и расположении элементов.
Рассмотрим, как выгрузить эти данные в читаемый формат. Напрямую коллекция внутри настроек закрыта для простого перебора, но мы можем использовать сериализацию XDTO, чтобы превратить настройки в XML-структуру, которую уже легко распарсить.
&НаСервере
Функция ПолучитьСтруктуруПользовательскойФормы()
// Получаем объект настроек текущей формы
Настройки = ЭтаФорма.ПолучитьНастройкиФормы();
// Используем сериализатор XDTO для перевода в XML
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Настройки);
Возврат ЗаписьXML.Закрыть(); // Здесь будет XML с описанием всех групп
КонецФункции
Проанализировав полученный XML, вы увидите узлы, соответствующие пользовательским группам. Это позволяет «увидеть» структуру, даже если она не представлена в ЭтаФорма.Элементы.
Как отмечалось в обсуждении на форуме, наиболее надежный путь — это перехват инициативы. Вместо того чтобы позволять пользователю создавать группы вручную через интерфейс, мы можем реализовать в форме кнопку «Создать группу», которая будет выполнять код на сервере.
Выясним преимущество: элементы, созданные методом Элементы.Добавить(), будут видны в коллекции ЭтаФорма.Элементы. Мы сможем управлять их видимостью, цветом и вложенностью стандартными методами. Посмотрим на пример программного создания группы:
&НаСервере
Процедура ДобавитьГруппуПрограммно(ИмяГруппы, ЗаголовокГруппы)
// Проверяем, не создана ли она уже
Если ЭтаФорма.Элементы.Найти(ИмяГруппы) = Неопределено Тогда
НоваяГруппа = ЭтаФорма.Элементы.Добавить(ИмяГруппы, Тип("ГруппаФормы"), ЭтаФорма.Элементы.ОсновнаяПанель);
НоваяГруппа.Вид = ВидГруппыФормы.ОбычнаяГруппа;
НоваяГруппа.Заголовок = ЗаголовокГруппы;
КонецЕсли;
КонецПроцедуры
Если нам нужно прочитать настройки формы другого пользователя или скопировать их, мы можем обратиться к ХранилищеСистемныхНастроек. Данные там хранятся по ключу вида "ВнешнийВид/НастройкиФорм/ИмяВашейФормы".
Важно помнить: данные в хранилище часто находятся в бинарном формате или специфическом внутреннем представлении 1С. Для их извлечения часто используют «костыльный», но рабочий метод ЗначениеВСтрокуВнутр(). Хотя этот метод возвращает трудночитаемый текст (псевдо-JSON), в нем содержатся имена всех добавленных пользователем полей и групп.
Алгоритм действий при использовании этого метода:
ЗначениеВСтрокуВнутр() к объекту настроек.Мы выяснили, что архитектура управляемых форм в 1С жестко разделяет структуру (доступную в коде) и представление (настраиваемое пользователем). Если вам жизненно необходимо управлять группами, которые создает пользователь, лучше всего:
Элементы.Добавить).ЭтаФорма.ПолучитьНастройкиФормы() и сериализацию в XML/JSON для анализа структуры «на лету».КлючСохраненияНастроек.Помните, что попытки парсить внутренние строки платформы — это крайняя мера, которую стоит применять только тогда, когда стандартные методы НастройкиФормы не дают нужного результата.