Как правильно записывать данные в регистр сведений при создании нового элемента справочника в 1С?

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

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

В чем причина ошибки при записи в событии ПриЗакрытии?

Проанализируем механику работы управляемой формы. Событие ПриЗакрытии вызывается в момент завершения работы с формой в любом случае — вне зависимости от того, нажал пользователь кнопку Записать и закрыть, нажал Отмена или просто закрыл окно крестиком.

Если пользователь открыл форму нового элемента, заполнил временную таблицу и закрыл форму без сохранения, то:

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

Рассмотрим правильные и надежные способы реализации этой логики.

Способ 1. Сохранение в транзакции объекта через ДополнительныеСвойства (Рекомендуемый)

Наиболее надежный способ с точки зрения стандартов разработки платформы 1С:Предприятие — передача данных из формы в модуль объекта и выполнение записи в одной транзакции. Для этого используется свойство ДополнительныеСвойства.

Разберем по шагам, как это реализовать.

Шаг 1. Передача данных из формы в объект

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


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

Шаг 2. Запись данных регистра в модуле объекта

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


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

При таком подходе обеспечивается полная транзакционная целостность: если произойдет сбой при записи набора регистра, будет отменена и запись самого элемента справочника.

Способ 2. Запись в обработчике формы ПослеЗаписиНаСервере

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

Для этого используется обработчик ПослеЗаписиНаСервере:


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

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

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

В таком случае перед началом редактирования таблицы проверяем состояние ссылки:


&НаКлиенте
Процедура ТаблицаКонтактнойИнформацииПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, ЭтоГруппа)
    
    Если Объект.Ссылка.Пустая() Тогда
        Отказ = Истина;
        ПоказатьВопрос(Новый ОписаниеОповещения("ПослеОтветаНаВопросОЗаписи", ЭтотОбъект), 
            "Для добавления контактной информации необходимо сначала записать элемент. Записать?", 
            РежимДиалогаВопрос.ДаНет);
    КонецЕсли;
    
КонецПроцедуры

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

Важные рекомендации

  1. Флаг «Ведущее» в измерении регистра: Убедимся, что для измерения Объект в регистре сведений включено свойство Ведущее. Это гарантирует, что платформа автоматически очистит зависимые записи при удалении элемента справочника.
  2. Использование функций БСП: Если в конфигурации используется библиотека стандартных подсистем (БСП) и регистр сведений КонтактнаяИнформация является типовым, не рекомендуется писать напрямую в набор записей. Для этого следует применять методы специализированного программного интерфейса подсистемы контактной информации.
← На главную