Как программно заполнить дополнительные реквизиты и сведения в 1С: разбираем ошибки и эффективные методы

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

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

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

Прежде чем приступать к написанию кода, давайте вспомним фундаментальное различие между двумя типами свойств в 1С. Это критически важно, так как методы работы с ними принципиально отличаются:

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

Рассмотрим ситуацию, когда программная запись не срабатывает. Часто это происходит из-за попытки записать «сведение» методом для «реквизита» или наоборот. Если вы используете универсальный механизм УправлениеСвойствами.ЗаписатьСвойстваУОбъекта, система сама пытается определить тип свойства, но здесь могут возникнуть нюансы с настройками метаданных.

Анализ стандартного метода записи через БСП

Типичный код, который часто встречается в обработках, выглядит следующим образом. Давайте разберем его по шагам и выясним, где могут скрываться «подводные камни»:


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

Проанализируем причины, по которым этот код может не работать для типа Булево:

  1. Привязка к набору свойств: В БСП каждое свойство (реквизит или сведение) должно быть включено в соответствующий Набор дополнительных реквизитов и сведений. Если вы создали свойство в ПВХ, но не добавили его в набор конкретного документа (например, «Документ_РеализацияТоваровУслуг»), метод ЗаписатьСвойстваУОбъекта просто проигнорирует эту запись, так как посчитает свойство «чужим» для данного объекта.
  2. Поиск по наименованию: Использование НайтиПоНаименованию — крайне ненадежный метод. В базе может существовать несколько свойств с одинаковым именем для разных документов. Всегда лучше использовать поиск по уникальному идентификатору (Имени), если свойство создано программно, или передавать ссылку напрямую из настроек.
  3. Тип значения в ПВХ: Проверьте, что в настройках ДополнительныеРеквизитыИСведения для данного элемента четко указан тип Булево. Если тип составной или не указан, БСП может ожидать объектное значение вместо примитивного Истина.

Метод записи через Регистр Сведений (для Дополнительных Сведений)

Если ваше свойство является «Дополнительным сведением», самым надежным и быстрым способом будет прямая работа с регистром. Это позволяет избежать сложных проверок БСП и гарантированно поместить данные в базу. Рассмотрим пример универсальной процедуры:


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

Этот метод работает безотказно для «Сведений». Обратите внимание на использование ОбменДанными.Загрузка = Истина — это полезный прием, когда нужно записать данные в обход подписок на события и проверок бизнес-логики, которые могут блокировать запись.

Метод записи через Табличную Часть (для Дополнительных Реквизитов)

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

Рассмотрим алгоритм действий:

  1. Получаем объект документа из ссылки.
  2. Ищем строку в табличной части ДополнительныеРеквизиты.
  3. Если строка найдена — обновляем значение.
  4. Если не найдена — добавляем новую строку и заполняем реквизиты Свойство и Значение.
  5. Записываем объект.

ДокОбъект = ДокументСсылка.ПолучитьОбъект();
ТЧ_ДопРеквизиты = ДокОбъект.ДополнительныеРеквизиты;

ПараметрыОтбора = Новый Структура("Свойство", СсылкаРеквизит);
НайденныеСтроки = ТЧ_ДопРеквизиты.НайтиСтроки(ПараметрыОтбора);

Если НайденныеСтроки.Количество() > 0 Тогда
    СтрокаРеквизита = НайденныеСтроки[0];
Иначе
    СтрокаРеквизита = ТЧ_ДопРеквизиты.Добавить();
    СтрокаРеквизита.Свойство = СсылкаРеквизит;
КонецЕсли;

СтрокаРеквизита.Значение = Истина;

Попытка
    ДокОбъект.Записать();
Исключение
    Сообщить("Ошибка при записи документа: " + ОписаниеОшибки());
КонецПопытки;

Почему не обновляются данные в форме?

Иногда программная запись проходит успешно (в базе значение изменилось), но пользователь, у которого открыта форма этого документа, видит старое значение. Это происходит из-за кэширования данных в БСП.

Если вы меняете реквизиты «на лету» из контекста формы, обязательно вызывайте метод обновления свойств в самой форме. В модуле формы это может выглядеть так:

УправлениеСвойствамиКлиент.ОбновитьДополнительныеРеквизиты(ЭтотОбъект);

Это заставит систему перечитать значения из объекта и корректно отобразить их в динамически создаваемых полях формы.

Итоги и рекомендации

Подводя итог, проанализируем основные правила работы с доп. свойствами:

Соблюдение этих правил позволит вам избежать большинства проблем при интеграции и автоматизации бизнес-процессов в среде 1С.

← На главную