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

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

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

Почему данные «обнуляются»: разбор архитектурной причины

Для начала выясним причину проблемы. В системе 1С существует два принципиально разных способа хранения табличных данных внутри объекта:

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

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

Способ 1: Использование Набора Записей как реквизита формы

Это наиболее современный и «чистый» способ для управляемых форм. Вместо того чтобы создавать таблицу вручную, мы делегируем управление данными самой платформе через механизм реквизитов.

Разберем по шагам алгоритм настройки:

  1. Подготовка регистра: В регистре сведений обязательно должно быть измерение, ссылающееся на наш справочник (например, Владелец или Объект с типом СправочникСсылка.ВашСправочник).
  2. Настройка «Ведущее»: В свойстве этого измерения установите флаг «Ведущее». Это критически важно: так мы сообщаем системе, что запись регистра не может существовать без ссылки на справочник. При удалении элемента справочника связанные записи в регистре удалятся автоматически.
  3. Создание реквизита формы: Откройте редактор формы справочника. На закладке «Реквизиты» добавьте новый реквизит. Назовите его, например, ТаблицаРегистра. В поле «Тип» выберите РегистрСведенийНаборЗаписей.[ИмяВашегоРегистра].
  4. Связь по параметру: В свойствах этого реквизита найдите пункт «Связь по параметру» или настройте отбор. Платформа должна понимать, что этот набор записей всегда фильтруется по текущей ссылке справочника.
  5. Визуализация: Перетащите созданный реквизит ТаблицаРегистра в левую часть редактора (дерево элементов формы). Платформа предложит создать таблицу — соглашайтесь.

Теперь при открытии формы и записи объекта 1С будет пытаться синхронизировать этот набор записей, но для полной автоматизации нам все равно потребуется немного кода.

Способ 2: Программное управление набором записей (через обработчики)

Если автоматическая связь не подходит или требуется сложная логика фильтрации, рассмотрим программный метод. Мы будем использовать обработчики событий формы, чтобы «принудительно» читать и записывать данные в регистр вместе с основным объектом.

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

Для этого в модуле формы реализуем следующий код:


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    // Инициализируем данные в таблице формы при открытии карточки
    // НаборЗаписейРегистра — это реквизит формы с типом РегистрСведенийНаборЗаписей
    НаборЗаписейРегистра.Отбор.Владелец.Установить(ТекущийОбъект.Ссылка);
    НаборЗаписейРегистра.Прочитать();
КонецПроцедуры

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

Важные нюансы и типичные ошибки

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

Рассмотрим правила безопасной записи:

Использование Динамического списка как альтернативы

Если ваша задача — только отображать данные (например, историю изменений или справочную информацию), а редактирование происходит в отдельном окне, то лучше использовать Динамический список.

Посмотрим на преимущества этого метода:

  1. Производительность: Данные подгружаются порциями по мере прокрутки.
  2. Простота настройки: Достаточно перетащить таблицу регистра на форму и в свойствах указать произвольный запрос с отбором ГДЕ Владелец = &Ссылка.
  3. Стандартные команды: Кнопки «Создать», «Изменить», «Удалить» будут открывать стандартные формы записи регистра, и вам не придется писать ни одной строки кода для сохранения.

Однако, если требование заказчика — «редактировать строки прямо здесь, как в Excel», то использование РегистрСведенийНаборЗаписей в качестве реквизита формы остается единственным верным решением.

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

← На главную