Как сохранить и восстановить поле табличного документа в управляемой форме 1С?

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

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

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

Основные ошибки при работе с хранилищем значений

Часто при попытке сохранить табличный документ разработчики сталкиваются с тем, что при открытии документа формуляр остается пустым. Выясним основные причины этой проблемы:

  1. Незначение процедуры обработчиком события: процедура написана в модуле формы вручную, но не привязана к событию в палитре свойств формы. В таком случае платформа просто не вызывает код при записи или чтении.
  2. Использование некорректных событий формы: чтение данных из объекта пытается выполняться в ПриСозданииНаСервере вместо ПриЧтенииНаСервере, либо используются лишние преобразования РеквизитФормыВЗначение при наличии стандартного параметра ТекущийОбъект.
  3. Применение метода Вывести() вместо прямого присвоения: метод Вывести() добавляет область в конец существующего документа, тогда как для полного восстановления табличного документа следует напрямую присваивать его реквизиту формы.

Шаг 1. Настройка реквизитов и назначение обработчиков событий

Для начала создадим в объекте (документе или справочнике) реквизит Хранилище с типом ХранилищеЗначения. На управляемой форме создадим реквизит формы с типом ТабличныйДокумент (например, ПолеТабличногоДокументаСтраница1).

Далее обязательно назначим обработчики событий формы через палитру свойств (кнопка с лупой напротив события):

  1. Событие ПередЗаписьюНаСервере — для упаковки табличного документа в хранилище перед записью объекта.
  2. Событие ПриЧтенииНаСервере — для извлечения табличного документа из хранилища при чтении сохраненного объекта.

Шаг 2. Сохранение и считывание одного табличного документа

Разберем код процедур-обработчиков для одного табличного документа на форме.

В событии ПередЗаписьюНаСервере мы берем заправленный реквизит формы и помещаем его в параметр ТекущийОбъект:


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    // Упаковываем табличный документ формы в ХранилищеЗначения
    ТекущийОбъект.Хранилище = Новый ХранилищеЗначения(ПолеТабличногоДокументаСтраница1);
КонецПроцедуры

В событии ПриЧтенииНаСервере считываем значение из базы и напрямую присваиваем его реквизиту формы:


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    // Извлекаем табличный документ из хранилища
    ЗначениеИзХранилища = ТекущийОбъект.Хранилище.Получить();
    
    Если ТипЗнч(ЗначениеИзХранилища) = Тип("ТабличныйДокумент") Тогда
        ПолеТабличногоДокументаСтраница1 = ЗначениеИзХранилища;
    КонецЕсли;
КонецПроцедуры

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

Шаг 3. Сохранение нескольких страниц/документов в одно хранилище

Если форма содержит несколько страниц или табличных документов, создавать под каждый из них отдельный реквизит с типом ХранилищеЗначения не требуется. Все табличные документы можно упаковать в одну коллекцию (например, в Структуру или Соответствие) и сохранить в единственный реквизит объекта.

Проанализируем пример сохранения и восстановления структуры с несколькими табличными документами:


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    
    // Формируем структуру со всеми страницами
    КонтейнерТабДоков = Новый Структура;
    КонтейнерТабДоков.Вставить("Страница1", ПолеТабличногоДокументаСтраница1);
    КонтейнерТабДоков.Вставить("Страница2", ПолеТабличногоДокументаСтраница2);
    
    // Сохраняем структуру в ХранилищеЗначения
    ТекущийОбъект.Хранилище = Новый ХранилищеЗначения(КонтейнерТабДоков);
    
КонецПроцедуры

&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    
    КонтейнерТабДоков = ТекущийОбъект.Хранилище.Получить();
    
    Если ТипЗнч(КонтейнерТабДоков) = Тип("Структура") Тогда
        
        Если КонтейнерТабДоков.Свойство("Страница1") Тогда
            ПолеТабличногоДокументаСтраница1 = КонтейнерТабДоков.Страница1;
        КонецЕсли;
        
        Если КонтейнерТабДоков.Свойство("Страница2") Тогда
            ПолеТабличногоДокументаСтраница2 = КонтейнерТабДоков.Страница2;
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Практические рекомендации по оптимизации

  1. Сериализуемость данных: убедитесь, что в ячейках табличного документа (в свойствах Расшифровка) не содержатся объекты, которые не могут быть сериализованы. Используйте в расшифровках только простые типы, ссылки или структуры.
  2. Сжатие данных: если табличные документы имеют крупный размер или много оформления, передавайте при создании ХранилищеЗначения второй параметр сжатия — СжатиеДанных.Максимальное, чтобы не перегружать таблицу информационной базы.
← На главную