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

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

Как обратиться к реквизиту объекта из расширения в 1С

Как обратиться к реквизиту объекта из расширения 1С: обращение по имени, через точку, УстановитьРеквизит, типовые ошибки и проверка результата.

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

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

Ниже разобраны рабочие способы обращения к реквизитам из расширения: прямое обращение по имени, работа через менеджер объекта, использование методов для безопасного доступа, а также типовые ошибки и способы проверки результата.

Обращение к типовому реквизиту из кода расширения

Если реквизит существует в основной конфигурации (например, «Организация» в документе «РеализацияТоваровУслуг»), то из любого модуля расширения к нему обращаются стандартно — через точку от ссылки или объекта. Расширение не создаёт отдельного пространства имён: оно дополняет контекст конфигурации.

// В общем модуле расширения

Функция ПолучитьОрганизациюДокумента(ДокументСсылка) Экспорт

Возврат ДокументСсылка.Организация;

КонецФункции

Обращение через точку к ссылке приводит к обращению к базе данных: платформа считывает объект целиком или нужные поля. Если требуется получить сразу несколько реквизитов, эффективнее использовать один запрос или метод получения значений реквизитов, чтобы не порождать несколько обращений к СУБД.

В модулях формы, заимствованной в расширение, доступ к реквизитам объекта выполняется через стандартные свойства формы — например, Объект.Комментарий для основного реквизита формы типа «ДанныеФормыСтруктура» на основе объекта.

Обращение к реквизиту, добавленному самим расширением

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

// Реквизит "Проект_Код" добавлен расширением в справочник "Номенклатура"

КодПроекта = НоменклатураСсылка.Проект_Код;

Критичное ограничение: реквизит существует только тогда, когда расширение подключено и применено к информационной базе. Если расширение отключено в настройках, снято флажком «Использовать» или сеанс запущен в безопасном режиме с отключёнными расширениями, обращение Ссылка.Проект_Код вызовет ошибку «Поле объекта не обнаружено (Проект_Код)».

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

Безопасное обращение: проверка наличия реквизита

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

Функция БезопасноПолучитьРеквизит(Ссылка, ИмяРеквизита) Экспорт

МетаданныеОбъекта = Ссылка.Метаданные();

Если МетаданныеОбъекта.Реквизиты.Найти(ИмяРеквизита) = Неопределено Тогда

Возврат Неопределено; // реквизита нет — расширение не подключено

КонецЕсли;

Возврат Ссылка[ИмяРеквизита];

КонецФункции

Обратите внимание на обращение через квадратные скобки: Ссылка[ИмяРеквизита]. Этот синтаксис позволяет обращаться к реквизиту по имени, заданному строкой, что удобно для универсальных механизмов. Стандартные реквизиты (Ссылка, Код, Наименование, Дата, Номер) в коллекцию «Реквизиты» метаданных не входят — их наличие проверяют отдельно или обрабатывают особо.

Для реквизитов формы аналогичную проверку выполняют через массив, возвращаемый методом ПолучитьРеквизиты() управляемой формы: если реквизит формы добавлен расширением, он появится в этом списке только при активном расширении.

Обращение к реквизиту в заимствованной форме

Частый сценарий — форма объекта заимствована в расширение, и в ней нужно прочитать или изменить реквизит объекта в обработчиках «ПриСозданииНаСервере», «ПередЗаписью» и других. Порядок действий стандартный: заимствуете форму, добавляете свою процедуру-обработчик с директивой &После, &Перед или &Вместо, внутри обращаетесь к объекту через реквизит формы.

&НаСервере

&После("ПриСозданииНаСервере")

Процедура Расш1_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

// Типовой реквизит объекта

Если Объект.ЭтоГруппа Тогда

Возврат;

КонецЕсли;

// Реквизит, добавленный расширением

Объект.Проект_Код = "НОВЫЙ";

КонецПроцедуры

Если реквизит добавлен расширением в объект, но не выведен на форму, значение всё равно доступно через Объект.ИмяРеквизита — реквизит объекта и элемент формы это разные сущности. Чтобы пользователь видел и редактировал значение, реквизит нужно перетащить из списка реквизитов формы в дерево элементов формы.

Обращение через запрос и программное получение данных

В запросах реквизиты расширения доступны так же, как типовые, — по имени поля. Платформа при построении запроса учитывает поля, добавленные расширением:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Ссылка,

| Номенклатура.Проект_Код КАК ПроектКод

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| НЕ Номенклатура.Проект_Код = """;

Тот же принцип действует в динамических списках, отчётах на СКД и произвольных выборках. Если расширение отключено, запрос с таким полем не пройдёт проверку и выдаст ошибку «Поле не найдено», поэтому в типовых отчётах, которые должны работать без расширения, поля расширения лучше не использовать.

Контрольные точки

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

Значение реквизита в отладчике
Норма

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

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

Ошибка «Поле объекта не обнаружено»

Список реквизитов в конфигураторе
Норма

Реквизит виден в дереве объекта с пометкой расширения

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

Реквизита нет — расширение не применено к базе

Запрос в консоли запросов
Норма

Поле доступно в конструкторе и выборка возвращает данные

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

Ошибка «Поле не найдено» при выполнении

Форма объекта в режиме предприятия
Норма

Новое поле отображается и сохраняет значение

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

Поле отсутствует или значение не сохраняется

Типичные ошибки и их причины

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

Вторая группа ошибок связана с контекстом выполнения. В модуле объекта, заимствованном в расширение, обращение к реквизитам идёт напрямую по имени без «Объект.» — как в типовом модуле объекта: ЭтотОбъект.Комментарий или просто Комментарий. Попытка использовать переменную «Объект» в модуле объекта приведёт к ошибке, такой переменной там нет.

Типичные ошибки
01
Обращение к реквизиту расширения без проверки — при отключённом расширении код падает с ошибкой
02
Использование &Вместо вместо &После — типовая логика обработчика перестаёт выполняться
03
Ожидание, что реквизит появится на форме автоматически — его нужно вручную добавить в элементы формы
04
Обращение к реквизиту расширения из основной конфигурации — типовой код не должен зависеть от расширения
05
Изменение имени реквизита в расширении без миграции данных — старые значения теряются из виду

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

Ограничения и альтернативные подходы

Расширение не может добавлять реквизиты ко всем типам объектов и не может изменять тип существующих типовых реквизитов. Если нужно хранить данные, не привязанные к составу объекта, рассмотрите альтернативы: дополнительные реквизиты и сведения (механизм БСП), регистры сведений с измерением по ссылке на объект, или собственный справочник-регистратор. Эти варианты устойчивы к отключению расширения в части структуры основной базы, хотя код доступа к ним всё равно зависит от расширения.

Маршрут решения

Как выбрать действие

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

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

Итог

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

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

Часто задаваемые вопросы

Можно ли из основной конфигурации обратиться к реквизиту, добавленному расширением?

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

Почему возникает ошибка «Поле объекта не обнаружено» при обращении к реквизиту расширения?

Три основные причины: расширение отключено или не применено к текущей информационной базе; не выполнено обновление структуры базы после добавления реквизита; опечатка в имени реквизита. Начните проверку со статуса расширения и наличия реквизита в дереве конфигурации.

Как обратиться к реквизиту по имени, заданному строкой?

Используйте обращение через квадратные скобки: Ссылка["ИмяРеквизита"] или Объект[ПеременнаяСИменем]. Перед обращением желательно проверить наличие реквизита через Метаданные().Реквизиты.Найти(Имя), чтобы избежать ошибки при отсутствии поля.

Видны ли реквизиты расширения в запросах и отчётах СКД?

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

Можно ли изменить тип или длину типового реквизита через расширение?

Нет, расширение не позволяет менять тип, длину и состав существующих реквизитов основной конфигурации. Доступно только добавление новых реквизитов и изменение некоторых свойств формы. Если требуется изменить типовой реквизит, придётся дорабатывать саму конфигурацию или хранить данные в отдельном объекте.

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

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