Как программно записать дополнительные сведения в документ и избежать ошибок версионирования

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

В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью автоматизировать заполнение дополнительных сведений. Типичная ситуация: при заполнении табличной части документа из внешней обработки необходимо одновременно установить значение некоего коэффициента или признака, который хранится не в самом документе, а в регистре сведений ДополнительныеСведения. Однако, если в конфигурации включено версионирование объектов, простая запись в регистр может привести к критической ошибке. В этой статье мы подробно разберем, почему возникает ошибка «Элемент не выбран!» и как правильно использовать механизмы Библиотеки стандартных подсистем (БСП) для решения этой задачи.

Анализ проблемы: почему возникает ошибка версионирования

Рассмотрим ситуацию, описанную в теме. При попытке записи набора записей или менеджера записи в регистр ДополнительныеСведения, система выдает ошибку в общем модуле ВерсионированиеОбъектов. Текст ошибки выглядит следующим образом:

{ОбщийМодуль.ВерсионированиеОбъектов.Модуль(267)}: Ошибка при вызове метода контекста (ПолучитьОбъект) Источник = Источник.ПолучитьОбъект(); по причине: Элемент не выбран!

Давайте выясним причину этого поведения. В БСП настроены подписки на события, которые отслеживают изменения в регистре дополнительных сведений. Когда мы записываем сведения для конкретного документа, срабатывает механизм версионирования, который пытается создать новую версию основного объекта (в нашем случае — документа). Для этого подсистема должна получить объект документа по ссылке.

Если код выполняется в обработке заполнения для нового документа, который еще не был физически записан в базу данных, ссылка на него уже существует (сформирована платформой), но в самой базе данных объекта еще нет. Метод ПолучитьОбъект(), вызванный от такой «пустой» ссылки в модуле версионирования, закономерно выдает исключение «Элемент не выбран».

Решение №1: Использование стандартных процедур БСП

Вместо того чтобы вручную создавать менеджер записи и заполнять измерения регистра, рекомендуется использовать программный интерфейс БСП. Это наиболее правильный и безопасный путь, так как стандартные процедуры общего модуля уже содержат необходимые проверки и корректно взаимодействуют с другими подсистемами (версионирование, даты запрета изменения, права доступа).

Проанализируем работу с общим модулем УправлениеСвойствами. Для записи дополнительных сведений предназначена процедура ЗаписатьДополнительныеСведения. Рассмотрим пример кода:


// СсылкаНаОбъект - ссылка на документ, для которого пишем сведения
// ИмяСвойства - наименование или ссылка на ПВХ ДополнительныеРеквизитыИСведения
// ЗначениеСвойства - записываемое значение

СвойствоСсылка = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Коэффициент Пересчета");

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

КонецЕсли;

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

Решение №2: Исправление работы с Менеджером Записи

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


Процедура ЗапишемКоэффициент(СсылкаНаДок)
    // 1. Проверяем, что ссылка не пустая и объект существует в базе
    Если СсылкаНаДок.Пустая() Или СсылкаНаДок.ПолучитьОбъект() = Неопределено Тогда
        Возврат; // Нельзя писать сведения для несуществующего документа
    КонецЕсли;

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

Важный момент: Использование параметра Истина в методе Записать() означает замещение существующей записи. Это критично для корректной работы регистра сведений с уникальным ключом «Объект + Свойство».

Различие между Дополнительными реквизитами и сведениями

Проанализируем ситуацию: возможно, для вашей задачи лучше подходят Дополнительные реквизиты, а не сведения. Давайте выясним принципиальную разницу:

  1. Дополнительные реквизиты хранятся в табличной части самого документа (ДополнительныеРеквизиты). Они записываются одновременно с документом в одной транзакции. Если вы программно заполните эту табличную часть в обработке заполнения, то при нажатии кнопки «Записать» в документе всё сохранится автоматически без лишних вызовов регистров и ошибок версионирования.
  2. Дополнительные сведения хранятся в отдельном регистре ДополнительныеСведения. Они существуют «отдельно» от документа. Их удобно использовать, когда нужно добавить информацию к закрытым периодам или когда нельзя менять сам документ.

Если вы автоматизируете заполнение данных при создании документа, настоятельно рекомендуем использовать дополнительные реквизиты. Это избавит вас от проблем с транзакциями и версионированием.

Как избежать лишних версий в истории изменений

Иногда программная запись сведений вызывает создание «мусорных» версий в истории изменений документа, что затрудняет анализ действий пользователя. Чтобы этого избежать при использовании БСП, можно воспользоваться дополнительными параметрами записи.

В некоторых случаях программисты временно отключают версионирование для текущего сеанса или используют свойство ДополнительныеСвойства у объекта документа, передавая туда флаг ОтказОтВерсионирования (точное имя свойства зависит от версии БСП и настроек подписки). Однако при использовании УправлениеСвойствами.ЗаписатьДополнительныеСведения система ведет себя максимально сбалансированно.

Резюме для разработчика

Подведем итоги нашего разбора:

Соблюдение этих правил позволит вам создавать надежные механизмы заполнения данных, которые не будут конфликтовать со стандартными подсистемами конфигураций на базе 1С:ERP, УТ 11 или Бухгалтерии предприятия.

← На главную