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