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