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