Почему не сохраняются данные в таблице значений на форме документа и как это исправить

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

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

Причина проблемы: Жизненный цикл реквизитов формы

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

Решение №1: Использование стандартной табличной части (ТЧ)

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

  1. Добавим в расширении к нужному документу новую Табличную часть и назовем ее, например, ТоварыДляОбработки.
  2. Создадим в этой ТЧ необходимые реквизиты (колонки).
  3. Перетащим созданную табличную часть на форму.

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

Решение №2: Сохранение данных в Регистр сведений

Иногда использование табличной части документа нецелесообразно (например, если данных слишком много или они носят технический характер). В такой ситуации проанализируем вариант с использованием Регистра сведений. Разберем по шагам, как организовать связь между формой документа и регистром:

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

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


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

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


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    
    // Читаем данные из регистра
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ * ИЗ РегистрСведений.ДанныеДокументовРасширения 
        |ГДЕ ДокументСсылка = &Ссылка";
    Запрос.УстановитьПараметр("Ссылка", ТекущийОбъект.Ссылка);
    
    РезультатЗапроса = Запрос.Выполнить().Выгрузить();
    
    // Заполняем реквизит формы из таблицы значений
    ЗначениеВРеквизитФормы(РезультатЗапроса, "РеквизитТЗ");
    
КонецПроцедуры

Решение №3: Сериализация в JSON или строку

Если структура таблицы часто меняется или данные не требуют сложного анализа, мы можем применить метод «упаковки» таблицы в одну строку. Для этого создадим у документа строковый реквизит неограниченной длины (например, ТехническиеДанныеТЗ). Посмотрим на пример реализации с использованием современных методов JSON-сериализации:

В обработчике ПередЗаписьюНаСервере превращаем таблицу в строку:


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

Важно помнить, что метод ЗначениеВСтрокуВнутр, упомянутый в некоторых обсуждениях, является устаревшим и платформенно-зависимым. Использование JSON является более гибким и современным стандартом в экосистеме 1С v8.3.

Важные технические нюансы работы с расширениями

При использовании любого из вышеперечисленных методов в расширении, обратим внимание на следующие моменты:

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

Таким образом, мы выяснили, что «исчезновение» данных — это не ошибка системы, а следствие работы механизмов управляемых форм. Выбор конкретного метода сохранения (ТЧ, РС или сериализация) зависит от архитектуры вашего решения и требований к производительности системы.

← На главную