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