Разработка и Конфигурация · 12 мин
Как обратиться к реквизиту объекта из расширения в 1С
Как обратиться к реквизиту объекта из расширения 1С: обращение по имени, через точку, УстановитьРеквизит, типовые ошибки и проверка результата.
Расширения конфигурации позволяют дорабатывать типовые решения 1С без снятия их с поддержки: добавлять собственные реквизиты, формы, процедуры и функции. Но у разработчиков регулярно возникает вопрос — как из кода расширения обратиться к реквизиту: как к типовому, так и к добавленному самим расширением. Способ обращения зависит от того, где находится реквизит (в основной конфигурации или в расширении) и от контекста, в котором выполняется код (модуль объекта, модуль формы, общий модуль).
Принципиально важно понимать: расширение работает «поверх» основной конфигурации. Объекты основной конфигурации видны из расширения напрямую, а объекты, добавленные расширением, видны только в том сеансе, где расширение подключено. Если расширение отключено или не применено к текущей информационной базе, обращение к его реквизиту вызовет ошибку «Поле объекта не обнаружено».
Ниже разобраны рабочие способы обращения к реквизитам из расширения: прямое обращение по имени, работа через менеджер объекта, использование методов для безопасного доступа, а также типовые ошибки и способы проверки результата.
Обращение к типовому реквизиту из кода расширения
Если реквизит существует в основной конфигурации (например, «Организация» в документе «РеализацияТоваровУслуг»), то из любого модуля расширения к нему обращаются стандартно — через точку от ссылки или объекта. Расширение не создаёт отдельного пространства имён: оно дополняет контекст конфигурации.
// В общем модуле расширения
Функция ПолучитьОрганизациюДокумента(ДокументСсылка) Экспорт
Возврат ДокументСсылка.Организация;
КонецФункции
Обращение через точку к ссылке приводит к обращению к базе данных: платформа считывает объект целиком или нужные поля. Если требуется получить сразу несколько реквизитов, эффективнее использовать один запрос или метод получения значений реквизитов, чтобы не порождать несколько обращений к СУБД.
В модулях формы, заимствованной в расширение, доступ к реквизитам объекта выполняется через стандартные свойства формы — например, Объект.Комментарий для основного реквизита формы типа «ДанныеФормыСтруктура» на основе объекта.
Обращение к реквизиту, добавленному самим расширением
Расширение может добавлять собственные реквизиты в справочники, документы и другие объекты. Такие реквизиты хранятся в той же таблице объекта (платформа физически расширяет структуру данных при обновлении), и синтаксис обращения к ним ничем не отличается от обращения к типовым:
// Реквизит "Проект_Код" добавлен расширением в справочник "Номенклатура"
КодПроекта = НоменклатураСсылка.Проект_Код;
Критичное ограничение: реквизит существует только тогда, когда расширение подключено и применено к информационной базе. Если расширение отключено в настройках, снято флажком «Использовать» или сеанс запущен в безопасном режиме с отключёнными расширениями, обращение Ссылка.Проект_Код вызовет ошибку «Поле объекта не обнаружено (Проект_Код)».
Ещё одно следствие: код, который планируется переносить между базами или публиковать как универсальный, не должен жёстко зависеть от реквизитов расширения. Для таких случаев используют защитные проверки, описанные ниже.
Безопасное обращение: проверка наличия реквизита
Когда нельзя гарантировать, что реквизит существует (расширение может быть отключено, код выполняется в другой конфигурации), перед обращением проверяют наличие реквизита через метаданные объекта:
Функция БезопасноПолучитьРеквизит(Ссылка, ИмяРеквизита) Экспорт
МетаданныеОбъекта = Ссылка.Метаданные();
Если МетаданныеОбъекта.Реквизиты.Найти(ИмяРеквизита) = Неопределено Тогда
Возврат Неопределено; // реквизита нет — расширение не подключено
КонецЕсли;
Возврат Ссылка[ИмяРеквизита];
КонецФункции
Обратите внимание на обращение через квадратные скобки: Ссылка[ИмяРеквизита]. Этот синтаксис позволяет обращаться к реквизиту по имени, заданному строкой, что удобно для универсальных механизмов. Стандартные реквизиты (Ссылка, Код, Наименование, Дата, Номер) в коллекцию «Реквизиты» метаданных не входят — их наличие проверяют отдельно или обрабатывают особо.
Для реквизитов формы аналогичную проверку выполняют через массив, возвращаемый методом ПолучитьРеквизиты() управляемой формы: если реквизит формы добавлен расширением, он появится в этом списке только при активном расширении.
Обращение к реквизиту в заимствованной форме
Частый сценарий — форма объекта заимствована в расширение, и в ней нужно прочитать или изменить реквизит объекта в обработчиках «ПриСозданииНаСервере», «ПередЗаписью» и других. Порядок действий стандартный: заимствуете форму, добавляете свою процедуру-обработчик с директивой &После, &Перед или &Вместо, внутри обращаетесь к объекту через реквизит формы.
&НаСервере
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Типовой реквизит объекта
Если Объект.ЭтоГруппа Тогда
Возврат;
КонецЕсли;
// Реквизит, добавленный расширением
Объект.Проект_Код = "НОВЫЙ";
КонецПроцедуры
Если реквизит добавлен расширением в объект, но не выведен на форму, значение всё равно доступно через Объект.ИмяРеквизита — реквизит объекта и элемент формы это разные сущности. Чтобы пользователь видел и редактировал значение, реквизит нужно перетащить из списка реквизитов формы в дерево элементов формы.
Обращение через запрос и программное получение данных
В запросах реквизиты расширения доступны так же, как типовые, — по имени поля. Платформа при построении запроса учитывает поля, добавленные расширением:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Проект_Код КАК ПроектКод
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.Проект_Код = """;
Тот же принцип действует в динамических списках, отчётах на СКД и произвольных выборках. Если расширение отключено, запрос с таким полем не пройдёт проверку и выдаст ошибку «Поле не найдено», поэтому в типовых отчётах, которые должны работать без расширения, поля расширения лучше не использовать.
Как проверить результат
Реквизит читается и содержит ожидаемое значение
Ошибка «Поле объекта не обнаружено»
Реквизит виден в дереве объекта с пометкой расширения
Реквизита нет — расширение не применено к базе
Поле доступно в конструкторе и выборка возвращает данные
Ошибка «Поле не найдено» при выполнении
Новое поле отображается и сохраняет значение
Поле отсутствует или значение не сохраняется
Типичные ошибки и их причины
Самая распространённая ошибка — «Поле объекта не обнаружено». Она возникает в трёх ситуациях: расширение отключено в текущем сеансе; реквизит добавлен в расширение, но расширение не применено к базе (не выполнено обновление); опечатка в имени реквизита. Проверяйте в первую очередь статус расширения в разделе «Администрирование — Печатные формы, отчеты и обработки — Расширения» (в типовых) или через функциональность «Расширения конфигурации».
Вторая группа ошибок связана с контекстом выполнения. В модуле объекта, заимствованном в расширение, обращение к реквизитам идёт напрямую по имени без «Объект.» — как в типовом модуле объекта: ЭтотОбъект.Комментарий или просто Комментарий. Попытка использовать переменную «Объект» в модуле объекта приведёт к ошибке, такой переменной там нет.
Третья группа — проблемы обновления. После добавления реквизита в расширение обязательно выполните обновление конфигурации базы данных (F7 в конфигураторе или обновление в режиме предприятия), иначе физического поля в таблице не будет и обращение завершится ошибкой на уровне СУБД.
Ограничения и альтернативные подходы
Расширение не может добавлять реквизиты ко всем типам объектов и не может изменять тип существующих типовых реквизитов. Если нужно хранить данные, не привязанные к составу объекта, рассмотрите альтернативы: дополнительные реквизиты и сведения (механизм БСП), регистры сведений с измерением по ссылке на объект, или собственный справочник-регистратор. Эти варианты устойчивы к отключению расширения в части структуры основной базы, хотя код доступа к ним всё равно зависит от расширения.
Как выбрать действие
При выборе между реквизитом объекта и дополнительным реквизитом учитывайте производительность и удобство: реквизит объекта хранится в основной таблице и быстро читается, дополнительный реквизит — в отдельной табличной части, что даёт лишнее соединение при выборках, но не требует доработки структуры и легче переносится между конфигурациями.
Что важно запомнить
Из расширения к реквизитам обращаются так же, как из основной конфигурации — по имени через точку. Реквизиты, добавленные расширением, существуют только при подключённом расширении, поэтому в переносимом коде проверяйте их наличие через метаданные. После добавления реквизита обязательно обновляйте базу и выводите реквизит на форму вручную.
Часто задаваемые вопросы
Можно ли из основной конфигурации обратиться к реквизиту, добавленному расширением?
Технически платформа объединяет метаданные, поэтому код основной конфигурации при подключённом расширении увидит реквизит. Но делать так не следует: при отключении расширения типовой код начнёт падать, а при обновлении конфигурации поставщиком такая зависимость создаст лишние риски. Зависимость должна быть односторонней — расширение зависит от конфигурации, а не наоборот.
Почему возникает ошибка «Поле объекта не обнаружено» при обращении к реквизиту расширения?
Три основные причины: расширение отключено или не применено к текущей информационной базе; не выполнено обновление структуры базы после добавления реквизита; опечатка в имени реквизита. Начните проверку со статуса расширения и наличия реквизита в дереве конфигурации.
Как обратиться к реквизиту по имени, заданному строкой?
Используйте обращение через квадратные скобки: Ссылка["ИмяРеквизита"] или Объект[ПеременнаяСИменем]. Перед обращением желательно проверить наличие реквизита через Метаданные().Реквизиты.Найти(Имя), чтобы избежать ошибки при отсутствии поля.
Видны ли реквизиты расширения в запросах и отчётах СКД?
Да, при подключённом расширении его реквизиты доступны в запросах, динамических списках и схемах компоновки данных наравне с типовыми полями. Но если расширение отключить, такие запросы и отчёты перестанут выполняться с ошибкой «Поле не найдено», поэтому в типовых отчётах поля расширения использовать не рекомендуется.
Можно ли изменить тип или длину типового реквизита через расширение?
Нет, расширение не позволяет менять тип, длину и состав существующих реквизитов основной конфигурации. Доступно только добавление новых реквизитов и изменение некоторых свойств формы. Если требуется изменить типовой реквизит, придётся дорабатывать саму конфигурацию или хранить данные в отдельном объекте.
Что произойдёт с данными в реквизите расширения при его отключении?
Физически данные в таблице сохраняются, но становятся недоступными: реквизит исчезает из метаданных сеанса, и обратиться к нему нельзя. После повторного включения расширения значения снова станут видны. Однако при удалении расширения с очисткой данных информация может быть утрачена, поэтому перед удалением делайте резервную копию.