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