К статье
Практический материал

Разработка и Конфигурация · 11 мин

1С: как программно изменить дополнительный реквизит

Как программно изменить дополнительный реквизит в 1С: работа с табличной частью ДополнительныеРеквизиты, поиск по имени, запись значений, типовые ошибки и примеры кода.

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

Программное изменение дополнительного реквизита сводится к трём шагам: найти строку в табличной части по ссылке на свойство, записать в неё нужное значение и сохранить объект. Сложность в том, что ссылку на свойство нужно сначала получить из плана видов характеристик «ДополнительныеРеквизитыИСведения», причём искать её надёжнее по имени или по предопределённому имени, а не по наименованию.

Ниже разобраны рабочие способы поиска свойства, изменения значения в режимах обычной записи и через объект, особенности управляемых форм, работа с дополнительными сведениями и типовые ошибки, из-за которых значение «не сохраняется».

Где физически хранятся дополнительные реквизиты

Когда пользователь в режиме Предприятия добавляет элементу справочника дополнительный реквизит, платформа создаёт запись в плане видов характеристик «ДополнительныеРеквизитыИСведения». Само значение хранится в табличной части объекта с именем «ДополнительныеРеквизиты»: каждая строка содержит ссылку на свойство (колонка «Свойство») и значение (колонка «Значение»).

Из этого следуют два практических вывода. Во-первых, у одного объекта может быть несколько строк с разными свойствами, и состав строк у разных элементов различается. Во-вторых, обращение вида СправочникОбъект.МойРеквизит для дополнительного реквизита не работает — нужен перебор или поиск по табличной части.

Как получить ссылку на свойство

Первый шаг любой операции — получить ссылку на элемент плана видов характеристик, соответствующий нужному реквизиту. Самый надёжный способ — поиск по имени свойства:

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

Если Свойство.Пустая() Тогда

ВызватьИсключение "Свойство не найдено";

КонецЕсли;

Имя свойства формируется платформой автоматически при создании реквизита и не совпадает с заголовком, который видит пользователь. Посмотреть его можно в конфигураторе через «Все функции» либо запросом. Альтернатива — поиск по наименованию через НайтиПоНаименованию, но этот способ хрупок: наименование может быть изменено администратором или продублировано.

Если реквизит предопределённый (создан в конфигураторе), удобно использовать предопределённое имя:

Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения["ИмяПредопределенного"];

Базовый код изменения значения

Типовой фрагмент для изменения дополнительного реквизита у элемента справочника выглядит так:

Объект = СсылкаНаЭлемент.ПолучитьОбъект();

ПараметрыОтбора = Новый Структура("Свойство", Свойство);

Строки = Объект.ДополнительныеРеквизиты.НайтиСтроки(ПараметрыОтбора);

Если Строки.Количество() > 0 Тогда

Строка = Строки[0];

Иначе

Строка = Объект.ДополнительныеРеквизиты.Добавить();

Строка.Свойство = Свойство;

КонецЕсли;

Строка.Значение = НовоеЗначение;

Объект.Записать();

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

Тип значения должен соответствовать типу, заданному в свойстве. Если свойство имеет составной тип (например, строка или ссылка на справочник), платформа примет значение любого из разрешённых типов, но запись несовместимого типа вызовет ошибку при проведении проверки заполнения.

Порядок действий
  1. 1
    Получите ссылку на свойство через НайтиПоИмени или по предопределённому имени
  2. 2
    Получите объект методом ПолучитьОбъект() по ссылке
  3. 3
    Найдите строку в табличной части ДополнительныеРеквизиты по отбору Свойство
  4. 4
    Если строки нет — добавьте её и заполните колонку Свойство
  5. 5
    Запишите значение в колонку Значение с учётом типа свойства
  6. 6
    Вызовите Записать() и проверьте результат в режиме Предприятия

Изменение на управляемой форме

Если код выполняется в модуле формы объекта, получать объект через ПолучитьОбъект() нельзя — это создаст второй экземпляр и приведёт к конфликту версий при записи. Вместо этого работайте с реквизитом формы:

ОбъектФормы = РеквизитФормыВЗначение("Объект");

// ... изменение табличной части ДополнительныеРеквизиты ...

ЗначениеВРеквизитФормы(ОбъектФормы, "Объект");

Либо, если структура данных позволяет, изменяйте табличную часть напрямую через Объект.ДополнительныеРеквизиты в контексте формы — в управляемых формах данные объекта доступны как реквизит формы, и строки табличной части можно искать тем же методом НайтиСтроки.

В типовых конфигурациях на БСП (УТ, ERP, БП) на форме дополнительные реквизиты часто представлены отдельными реквизитами формы вида «ДополнительныйРеквизитЗначение_...». В этом случае корректнее использовать программный интерфейс подсистемы свойств, а не прямую запись в табличную часть.

Использование БСП: модуль УправлениеСвойствами

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

Полезные функции модуля:

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

Пример записи дополнительного сведения:

МенеджерЗаписи = РегистрыСведений.ДополнительныеСведения.СоздатьМенеджерЗаписи();

МенеджерЗаписи.Объект = СсылкаНаЭлемент;

МенеджерЗаписи.Свойство = Свойство;

МенеджерЗаписи.Значение = НовоеЗначение;

МенеджерЗаписи.Записать();

Сравнение вариантов

Прямая работа с табличной частью

Универсально, работает в любой конфигурации. Минус — нужно вручную искать свойство и контролировать типы.

API БСП (УправлениеСвойствами)

Удобно для чтения и интеграции с формами типовых конфигураций. Ограничение — доступно только в конфигурациях на БСП.

Запрос к табличной части

Подходит для пакетного чтения значений по многим объектам. Для записи запрос не применим — нужен объект.

Пакетное изменение и производительность

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

Для массовых операций полезно отключать проверку заполнения через Объект.ОбменДанными.Загрузка = Истина только в том случае, если вы полностью контролируете корректность данных. Этот режим пропускает обработчики проверки и бизнес-логику, поэтому его нельзя применять, если при записи должны срабатывать подписки на события, пересчёт итогов или регистрация в планах обмена.

Типичные ошибки и их диагностика

Самая частая жалоба — «код отработал, а значение не сохранилось». Причины почти всегда одни и те же:

  • свойство искали по наименованию, нашли пустую ссылку, строка добавилась с пустым свойством и не отображается на форме;
  • забыли вызвать Записать() после изменения табличной части;
  • изменили объект, полученный через ПолучитьОбъект, пока тот же объект открыт на форме, — при записи возник конфликт версий;
  • передали значение несовместимого типа, и запись упала с ошибкой проверки заполнения;
  • реквизит является дополнительным сведением, а не реквизитом — его нет в табличной части, поэтому строка не находится.

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

Типичные ошибки
01
Поиск свойства по наименованию — наименование меняется администратором, код перестаёт находить свойство; используйте имя или предопределённое имя.
02
Отсутствие ветки добавления строки — если значение раньше не заполнялось, строки нет, и присваивание молча не срабатывает.
03
Запись объекта, открытого на форме, через ПолучитьОбъект — конфликт версий и потеря изменений пользователя.
04
Путаница между дополнительным реквизитом и дополнительным сведением — они хранятся в разных местах и требуют разного кода.
Контрольные точки

Как проверить результат

Запрос к табличной части ДополнительныеРеквизиты
Норма

Строка с нужным свойством содержит новое значение

Тревожный признак

Строки нет или значение старое — запись не выполнилась

Открытие элемента в режиме Предприятия
Норма

Реквизит отображается с новым значением

Тревожный признак

Значение есть в базе, но не на форме — проверьте набор свойств и видимость

Журнал регистрации
Норма

Нет ошибок записи в момент выполнения кода

Тревожный признак

Ошибки проверки заполнения или конфликта блокировок

FAQ

Как узнать внутреннее имя дополнительного реквизита для НайтиПоИмени?

Откройте в режиме Предприятия «Все функции», найдите план видов характеристик «ДополнительныеРеквизитыИСведения», откройте нужный элемент — имя указано в соответствующем поле. Альтернатива — вывести имена запросом или через консоль кода, перебрав элементы ПВХ.

Чем дополнительный реквизит отличается от дополнительного сведения при программной работе?

Реквизит хранится в табличной части объекта и записывается вместе с ним. Сведение хранится в регистре сведений «ДополнительныеСведения» и записывается отдельным менеджером записи — объект при этом изменять не нужно, что удобно, когда нельзя трогать сам документ или элемент.

Можно ли изменить дополнительный реквизит у документа, не перепроводя его?

Да, если записывать объект методом Записать() с режимом записи «Запись», а не «Проведение». Дополнительные реквизиты не участвуют в движениях, поэтому перепроведение для их изменения не требуется.

Почему НайтиСтроки не находит строку, хотя реквизит заполнен?

Вероятно, вы ищете не ту ссылку на свойство: у разных наборов свойств могут существовать разные элементы ПВХ с одинаковым наименованием. Сравните ссылку в найденной строке табличной части с той, что вернул поиск, — они должны совпадать точно.

Как очистить значение дополнительного реквизита программно?

Найдите строку по свойству и либо присвойте колонке «Значение» пустое значение соответствующего типа (НЕОПРЕДЕЛЕНО обычно тоже допустимо), либо удалите строку из табличной части методом Удалить и запишите объект. Удаление строки предпочтительнее, чтобы не накапливать пустые записи.

Работает ли изменение дополнительных реквизитов через COM или внешние соединения?

Да, логика та же: через COM-объект получаете ссылку на свойство, открываете объект, меняете табличную часть и записываете. Учитывайте только, что типы значений (даты, ссылки) должны быть корректно преобразованы в типы 1С на той стороне соединения.

Итог

Что важно запомнить

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