Как правильно сохранить и восстановить значения табличного поля во внешней обработке 1С?

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

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

В чем причина появления пустых строк?

Для понимания проблемы проанализируем внутреннее устройство элементов формы обычного интерфейса:

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

Способ 1. Заполнение строк без разрушения структуры колонок

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

Рассмотрим реализацию в обработчиках событий формы ПриОткрытии и ПриЗакрытии:


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

Процедура ПриЗакрытии()
    // Сохраняем именно данные (копию таблицы значений)
    СохранитьЗначение("Объекты82", ТабличноеПоле1.Скопировать());
КонецПроцедуры

Способ 2. Принудительное пересоздание колонок элемента управления

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

Посмотрим на пример такого кода:


Процедура ПриОткрытии()
    ВосстановленнаяТЗ = ВосстановитьЗначение("Объекты82");
    
    Если ТипЗнч(ВосстановленнаяТЗ) = Тип("ТаблицаЗначений") Тогда
        // Переприсваиваем источник данных
        ТабличноеПоле1 = ВосстановленнаяТЗ;
        
        // Принудительно генерируем колонки элемента управления
        ЭлементыФормы.ТабличноеПоле1.СоздатьКолонки();
    КонецЕсли;
КонецПроцедуры

Процедура ПриЗакрытии()
    СохранитьЗначение("Объекты82", ТабличноеПоле1);
КонецПроцедуры

Способ 3. Использование системного Хранилища Общих Настроек

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

Разберем пример сохранения и восстановления через системное хранилище:


Процедура ПриОткрытии()
    ВосстановленныеДанные = ХранилищеОбщихНастроек.Загрузить("ВнешняяОбработка_Объекты", "ТаблицаДанных");
    
    Если ТипЗнч(ВосстановленныеДанные) = Тип("ТаблицаЗначений") Тогда
        ТабличноеПоле1.Очистить();
        Для Каждого Стр Из ВосстановленныеДанные Цикл
            ЗаполнитьЗначенияСвойств(ТабличноеПоле1.Добавить(), Стр);
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

Процедура ПриЗакрытии()
    ХранилищеОбщихНастроек.Сохранить(
        "ВнешняяОбработка_Объекты",
        "ТаблицаДанных",
        ТабличноеПоле1.Скопировать()
    );
КонецПроцедуры

Способ 4. Сериализация и сохранение в базе данных (для фоновых процессов и веб-сервисов)

Если данные необходимо передавать в сеансы, где нет интерфейсного контекста формы (веб-сервисы, HTTP-сервисы), следует сохранять таблицу в регистр сведений или сериализовать ее.

Рассмотрим два основных варианта сохранения:

  1. Через ХранилищеЗначения в регистр сведений:
    
    // Запись в базу данных
    Хранилище = Новый ХранилищеЗначения(ТабличноеПоле1.Скопировать(), Новый СжатиеДанных(9));
    // Записать Хранилище в ресурс регистра сведений...
    
    // Извлечение из базы данных
    ТаблицаИзБазы = Хранилище.Получить();
    
  2. Через сериализацию XDTO:
    
    // Преобразование таблицы в XML-строку
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.УстановитьСтроку();
    СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ТабличноеПоле1.Скопировать());
    СтрокаXML = ЗаписьXML.Закрыть();
    
    // Чтение таблицы из XML-строки
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.УстановитьСтроку(СтрокаXML);
    ВосстановленнаяТЗ = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
    

Резюме: Чтобы избежать пустых строк в табличном поле, всегда разделяйте объект данных (ТаблицаЗначений) и элемент формы (ТабличноеПоле). Сохраняйте исключительно копию таблицы значений через Скопировать(), а при открытии формы заполняйте строки через ЗаполнитьЗначенияСвойств() либо вызывайте метод СоздатьКолонки().

← На главную