Как программно записать значение в регистр Значения свойств объектов и почему запись может не сохраняться

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей
← На главную

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

Анализ проблемы: почему данные пропадают

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

  1. Выполняется процедура ПередЗаписью в модуле объекта.
  2. Начинается транзакция записи.
  3. Выполняется процедура ПриЗаписи, где разработчик часто пытается напрямую записать данные в регистр сведений.
  4. Важный момент: Срабатывают стандартные механизмы формы или подписки на события. В УТ 10.3 после записи самого объекта система программно собирает все свойства из табличной части формы и записывает их "пакетом", полностью замещая набор записей в регистре ЗначенияСвойствОбъектов по данному объекту.

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

Решение 1: Использование обработчика формы ПослеЗаписи

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

Пример кода для модуля формы:


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

Решение 2: Программная запись через МенеджерЗаписи

Для записи одиночных значений в независимый регистр сведений удобнее всего использовать РегистрСведенийМенеджерЗаписи. Этот объект позволяет работать с конкретной строкой регистра, определяемой набором измерений. Рассмотрим универсальную функцию, которую можно разместить в общем модуле:


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

    // 2. Работа с менеджером записи
    МенеджерЗаписи = РегистрыСведений.ЗначенияСвойствОбъектов.СоздатьМенеджерЗаписи();
    МенеджерЗаписи.Объект   = ОбъектСсылка;
    МенеджерЗаписи.Свойство = СвойствоСсылка;
    
    // Читаем существующую запись, чтобы не перезаписывать лишнего, если это нужно
    МенеджерЗаписи.Прочитать();
    
    МенеджерЗаписи.Значение = Значение;
    
    Попытка
        МенеджерЗаписи.Записать(Истина); // Параметр Истина означает замещение существующей записи
    Исключение
        Сообщить("Ошибка при записи свойства: " + ОписаниеОшибки());
    КонецПопытки;

КонецПроцедуры

Решение 3: Работа через НаборЗаписей

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


НаборЗаписей = РегистрыСведений.ЗначенияСвойствОбъектов.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Объект.Установить(ЭтотОбъект.Ссылка);
НаборЗаписей.Отбор.Свойство.Установить(ПланыВидовХарактеристик.СвойстваОбъектов.НайтиПоНаименованию("ДатаИзменения"));

НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Объект   = ЭтотОбъект.Ссылка;
НоваяЗапись.Свойство = ПланыВидовХарактеристик.СвойстваОбъектов.НайтиПоНаименованию("ДатаИзменения");
НоваяЗапись.Значение = ТекущаяДата();

НаборЗаписей.Записать(Истина); 

Внимание: Если вы устанавливаете отбор только по Объекту, но не по Свойству, то вызов Записать(Истина) удалит все остальные дополнительные свойства этого контрагента и оставит только те, что вы добавили в набор в текущем коде. Будьте осторожны!

Тонкости поиска свойств в ПВХ

Выясним одну из частых причин неудач при поиске свойства. Метод НайтиПоНаименованию чувствителен к точному написанию. В типовых конфигурациях (УТ 10.3) наименование элемента в Плане видов характеристик СвойстваОбъектов часто выглядит так: "ДатаИзменения (Контрагенты)". Если вы ищете просто "ДатаИзменения", система может ничего не найти.

Рекомендуется проверить реальное наименование в режиме "Предприятие" или использовать поиск по коду, если вы создали предопределенный элемент. Также убедитесь, что тип значения, который вы записываете (например, Дата), совпадает с типом, разрешенным для этого свойства в настройках ПВХ. Хотя ресурс Значение в регистре обычно имеет составной тип, несоответствие типов может привести к ошибкам в стандартных отчетах.

Как проверить, кто удаляет запись?

Если запись по-прежнему пропадает, воспользуемся инструментами отладки. Рассмотрим алгоритм поиска "виновника":

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

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

← На главную