Как сохранить программно созданные страницы и данные в документе 1С?

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

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

Почему программные элементы «пропадают»?

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

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

Шаг 1: Подготовка места для хранения данных

Программно созданные реквизиты формы (через ИзменитьРеквизиты) не умеют автоматически сохраняться в базу данных. Чтобы данные «выжили» после закрытия формы, они должны быть привязаны к физическим реквизитам объекта (документа). Для динамических наборов данных лучше всего подходят Табличные части.

Создадим в документе табличную часть, например, ДополнительныеРеквизиты с колонками:

  1. ИмяРеквизита (Строка) — чтобы знать, куда вернуть данные.
  2. Значение (Любой тип или строка) — для хранения самого значения.
  3. КлючСвязи (Число или Ссылка) — если данные нужно привязать к конкретной странице или менеджеру.

Шаг 2: Правильное создание динамических реквизитов

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


&НаСервере
Процедура СоздатьДинамическиеРеквизиты(Количество)
    МассивДобавляемыхРеквизитов = Новый Массив;
    
    Для Сч = 1 По Количество Цикл
        ИмяРеквизита = "ДинамическийРеквизит_" + Сч;
        
        // Описываем тип данных (например, СправочникСсылка.Партнеры)
        МассивТипов = Новый Массив;
        МассивТипов.Добавить(Тип("СправочникСсылка.Партнеры"));
        ОписаниеТипа = Новый ОписаниеТипов(МассивТипов);
        
        НовыйРеквизит = Новый РеквизитФормы(ИмяРеквизита, ОписаниеТипа, , "Поставщик " + Сч, Истина);
        МассивДобавляемыхРеквизитов.Добавить(НовыйРеквизит);
    КонецЦикла;
    
    // Добавляем реквизиты в структуру формы
    ЭтаФорма.ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);
КонецПроцедуры

Шаг 3: Программное создание элементов интерфейса

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


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

Шаг 4: Восстановление данных при открытии формы

Это самый важный этап. Вызовем логику построения формы в событии ПриСозданииНаСервере. Мы должны прочитать данные из табличной части объекта и на их основе воссоздать структуру элементов. Проанализируем алгоритм:

  1. Обходим строки табличной части документа Объект.ДополнительныеРеквизиты.
  2. Для каждой строки вызываем создание реквизита формы и элемента управления.
  3. Заполняем созданный реквизит формы значением из таблицы.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Восстанавливаем структуру по сохраненным данным
    Если Объект.МенеджерыПоСнабжению.Количество() > 0 Тогда
        
        // 1. Сначала создаем все необходимые реквизиты в памяти
        СоздатьДинамическиеРеквизиты(Объект.МенеджерыПоСнабжению.Количество());
        
        // 2. Затем создаем визуальные элементы и заполняем их данными
        Сч = 1;
        Для Каждого СтрокаТЧ Из Объект.МенеджерыПоСнабжению Цикл
            СоздатьЭлементыИнтерфейса(Сч);
            
            // Заполняем созданный реквизит формы значением из ТЧ объекта
            ЭтаФорма["ДинамическийРеквизит_" + Сч] = СтрокаТЧ.ЗначениеПоставщика;
            
            Сч = Сч + 1;
        КонецЦикла;
        
    КонецЕсли;
КонецПроцедуры

Шаг 5: Сохранение данных перед записью

Чтобы данные из «виртуальных» полей попали в базу, их нужно перенести обратно в объект перед записью. Разберем работу обработчика ПередЗаписьюНаСервере:


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    // Очищаем старые данные в объекте и записываем актуальные из формы
    ТекущийОбъект.МенеджерыПоСнабжению.Очистить();
    
    // В реальном коде стоит использовать счетчик или массив имен реквизитов
    Для Сч = 1 По МаксимальноеКоличествоЦикла Цикл
        ИмяРеквизита = "ДинамическийРеквизит_" + Сч;
        
        // Проверяем, существует ли такой реквизит на форме
        ЗначениеДляЗаписи = ЭтаФорма[ИмяРеквизита];
        
        Если ЗначениеЗаполнено(ЗначениеДляЗаписи) Тогда
            НоваяСтрока = ТекущийОбъект.МенеджерыПоСнабжению.Добавить();
            НоваяСтрока.ЗначениеПоставщика = ЗначениеДляЗаписи;
            НоваяСтрока.ИмяРеквизита = ИмяРеквизита;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Рекомендации и альтернативы

Посмотрим на ситуацию шире: ручное управление динамическими реквизитами — трудоемкий процесс, чреватый ошибками при обновлении конфигурации или изменении типов данных. Рассмотрим альтернативные подходы:

Таким образом, для успешного сохранения данных в динамических формах необходимо четко разделять визуальное представление (создается в ПриСозданииНаСервере) и физическое хранение (табличные части Объект).

← На главную