Разработка и Конфигурация · 11 мин
1С: как программно изменить дополнительный реквизит
Как программно изменить дополнительный реквизит в 1С: работа с табличной частью ДополнительныеРеквизиты, поиск по имени, запись значений, типовые ошибки и примеры кода.
Дополнительные реквизиты в 1С — это пользовательские поля, которые администратор добавляет к справочникам и документам без изменения конфигурации. В отличие от обычных реквизитов, они не хранятся в отдельных колонках таблицы объекта, а размещаются в специальной табличной части «ДополнительныеРеквизиты», поэтому обратиться к ним напрямую через точку нельзя.
Программное изменение дополнительного реквизита сводится к трём шагам: найти строку в табличной части по ссылке на свойство, записать в неё нужное значение и сохранить объект. Сложность в том, что ссылку на свойство нужно сначала получить из плана видов характеристик «ДополнительныеРеквизитыИСведения», причём искать её надёжнее по имени или по предопределённому имени, а не по наименованию.
Ниже разобраны рабочие способы поиска свойства, изменения значения в режимах обычной записи и через объект, особенности управляемых форм, работа с дополнительными сведениями и типовые ошибки, из-за которых значение «не сохраняется».
Где физически хранятся дополнительные реквизиты
Когда пользователь в режиме Предприятия добавляет элементу справочника дополнительный реквизит, платформа создаёт запись в плане видов характеристик «ДополнительныеРеквизитыИСведения». Само значение хранится в табличной части объекта с именем «ДополнительныеРеквизиты»: каждая строка содержит ссылку на свойство (колонка «Свойство») и значение (колонка «Значение»).
Из этого следуют два практических вывода. Во-первых, у одного объекта может быть несколько строк с разными свойствами, и состав строк у разных элементов различается. Во-вторых, обращение вида СправочникОбъект.МойРеквизит для дополнительного реквизита не работает — нужен перебор или поиск по табличной части.
Как получить ссылку на свойство
Первый шаг любой операции — получить ссылку на элемент плана видов характеристик, соответствующий нужному реквизиту. Самый надёжный способ — поиск по имени свойства:
Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоИмени("МойДопРеквизит");
Если Свойство.Пустая() Тогда
ВызватьИсключение "Свойство не найдено";
КонецЕсли;
Имя свойства формируется платформой автоматически при создании реквизита и не совпадает с заголовком, который видит пользователь. Посмотреть его можно в конфигураторе через «Все функции» либо запросом. Альтернатива — поиск по наименованию через НайтиПоНаименованию, но этот способ хрупок: наименование может быть изменено администратором или продублировано.
Если реквизит предопределённый (создан в конфигураторе), удобно использовать предопределённое имя:
Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения["ИмяПредопределенного"];
Базовый код изменения значения
Типовой фрагмент для изменения дополнительного реквизита у элемента справочника выглядит так:
Объект = СсылкаНаЭлемент.ПолучитьОбъект();
ПараметрыОтбора = Новый Структура("Свойство", Свойство);
Строки = Объект.ДополнительныеРеквизиты.НайтиСтроки(ПараметрыОтбора);
Если Строки.Количество() > 0 Тогда
Строка = Строки[0];
Иначе
Строка = Объект.ДополнительныеРеквизиты.Добавить();
Строка.Свойство = Свойство;
КонецЕсли;
Строка.Значение = НовоеЗначение;
Объект.Записать();
Ключевой момент — строка с нужным свойством может отсутствовать, если значение никогда не заполнялось. Поэтому код обязан уметь добавлять новую строку, иначе при первом заполнении значение просто не запишется.
Тип значения должен соответствовать типу, заданному в свойстве. Если свойство имеет составной тип (например, строка или ссылка на справочник), платформа примет значение любого из разрешённых типов, но запись несовместимого типа вызовет ошибку при проведении проверки заполнения.
- 1Получите ссылку на свойство через НайтиПоИмени или по предопределённому имени
- 2Получите объект методом ПолучитьОбъект() по ссылке
- 3Найдите строку в табличной части ДополнительныеРеквизиты по отбору Свойство
- 4Если строки нет — добавьте её и заполните колонку Свойство
- 5Запишите значение в колонку Значение с учётом типа свойства
- 6Вызовите Записать() и проверьте результат в режиме Предприятия
Изменение на управляемой форме
Если код выполняется в модуле формы объекта, получать объект через ПолучитьОбъект() нельзя — это создаст второй экземпляр и приведёт к конфликту версий при записи. Вместо этого работайте с реквизитом формы:
ОбъектФормы = РеквизитФормыВЗначение("Объект");
// ... изменение табличной части ДополнительныеРеквизиты ...
ЗначениеВРеквизитФормы(ОбъектФормы, "Объект");
Либо, если структура данных позволяет, изменяйте табличную часть напрямую через Объект.ДополнительныеРеквизиты в контексте формы — в управляемых формах данные объекта доступны как реквизит формы, и строки табличной части можно искать тем же методом НайтиСтроки.
В типовых конфигурациях на БСП (УТ, ERP, БП) на форме дополнительные реквизиты часто представлены отдельными реквизитами формы вида «ДополнительныйРеквизитЗначение_...». В этом случае корректнее использовать программный интерфейс подсистемы свойств, а не прямую запись в табличную часть.
Использование БСП: модуль УправлениеСвойствами
В конфигурациях на базе Библиотеки стандартных подсуществует готовый API. Для чтения и записи значений свойств используется общий модуль УправлениеСвойствами (в старых версиях — УправлениеСвойствамиСлужебный).
Полезные функции модуля:
УправлениеСвойствами.ЗначениеСвойства(Объект, Свойство)— вернуть текущее значение дополнительного реквизита или сведения;- запись значения выполняется через заполнение табличной части объекта с последующим
Записать()— отдельной функции «записать одно значение» в БСП нет, но есть процедуры обработки заполнения свойств при записи; - для дополнительных сведений запись идёт в регистр сведений «ДополнительныеСведения» через менеджер записи.
Пример записи дополнительного сведения:
МенеджерЗаписи = РегистрыСведений.ДополнительныеСведения.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Объект = СсылкаНаЭлемент;
МенеджерЗаписи.Свойство = Свойство;
МенеджерЗаписи.Значение = НовоеЗначение;
МенеджерЗаписи.Записать();
Сравнение вариантов
Универсально, работает в любой конфигурации. Минус — нужно вручную искать свойство и контролировать типы.
Удобно для чтения и интеграции с формами типовых конфигураций. Ограничение — доступно только в конфигурациях на БСП.
Подходит для пакетного чтения значений по многим объектам. Для записи запрос не применим — нужен объект.
Пакетное изменение и производительность
Если дополнительный реквизит нужно изменить у тысяч элементов, наивный цикл с ПолучитьОбъект() и Записать() для каждого элемента работает медленно и создаёт нагрузку на блокировки. Разумный подход — выбрать ссылки запросом, обрабатывать их порциями и оборачивать каждую запись в отдельную транзакцию, чтобы сбой одного элемента не откатывал всю пачку.
Для массовых операций полезно отключать проверку заполнения через Объект.ОбменДанными.Загрузка = Истина только в том случае, если вы полностью контролируете корректность данных. Этот режим пропускает обработчики проверки и бизнес-логику, поэтому его нельзя применять, если при записи должны срабатывать подписки на события, пересчёт итогов или регистрация в планах обмена.
Типичные ошибки и их диагностика
Самая частая жалоба — «код отработал, а значение не сохранилось». Причины почти всегда одни и те же:
- свойство искали по наименованию, нашли пустую ссылку, строка добавилась с пустым свойством и не отображается на форме;
- забыли вызвать
Записать()после изменения табличной части; - изменили объект, полученный через ПолучитьОбъект, пока тот же объект открыт на форме, — при записи возник конфликт версий;
- передали значение несовместимого типа, и запись упала с ошибкой проверки заполнения;
- реквизит является дополнительным сведением, а не реквизитом — его нет в табличной части, поэтому строка не находится.
Проверить результат проще всего запросом к табличной части справочника или открыв элемент в режиме Предприятия. Если значение видно в запросе, но не видно на форме — проблема в настройках видимости свойства для данного набора свойств объекта.
Как проверить результат
Строка с нужным свойством содержит новое значение
Строки нет или значение старое — запись не выполнилась
Реквизит отображается с новым значением
Значение есть в базе, но не на форме — проверьте набор свойств и видимость
Нет ошибок записи в момент выполнения кода
Ошибки проверки заполнения или конфликта блокировок
FAQ
Как узнать внутреннее имя дополнительного реквизита для НайтиПоИмени?
Откройте в режиме Предприятия «Все функции», найдите план видов характеристик «ДополнительныеРеквизитыИСведения», откройте нужный элемент — имя указано в соответствующем поле. Альтернатива — вывести имена запросом или через консоль кода, перебрав элементы ПВХ.
Чем дополнительный реквизит отличается от дополнительного сведения при программной работе?
Реквизит хранится в табличной части объекта и записывается вместе с ним. Сведение хранится в регистре сведений «ДополнительныеСведения» и записывается отдельным менеджером записи — объект при этом изменять не нужно, что удобно, когда нельзя трогать сам документ или элемент.
Можно ли изменить дополнительный реквизит у документа, не перепроводя его?
Да, если записывать объект методом Записать() с режимом записи «Запись», а не «Проведение». Дополнительные реквизиты не участвуют в движениях, поэтому перепроведение для их изменения не требуется.
Почему НайтиСтроки не находит строку, хотя реквизит заполнен?
Вероятно, вы ищете не ту ссылку на свойство: у разных наборов свойств могут существовать разные элементы ПВХ с одинаковым наименованием. Сравните ссылку в найденной строке табличной части с той, что вернул поиск, — они должны совпадать точно.
Как очистить значение дополнительного реквизита программно?
Найдите строку по свойству и либо присвойте колонке «Значение» пустое значение соответствующего типа (НЕОПРЕДЕЛЕНО обычно тоже допустимо), либо удалите строку из табличной части методом Удалить и запишите объект. Удаление строки предпочтительнее, чтобы не накапливать пустые записи.
Работает ли изменение дополнительных реквизитов через COM или внешние соединения?
Да, логика та же: через COM-объект получаете ссылку на свойство, открываете объект, меняете табличную часть и записываете. Учитывайте только, что типы значений (даты, ссылки) должны быть корректно преобразованы в типы 1С на той стороне соединения.
Что важно запомнить
Дополнительный реквизит изменяется через табличную часть «ДополнительныеРеквизиты»: найдите свойство по имени, найдите или добавьте строку, запишите значение и сохраните объект. Различайте реквизиты и сведения, не используйте поиск по наименованию и аккуратно применяйте режим загрузки при пакетной записи.