Почему новый реквизит расширения не виден в модуле формы и как это исправить?

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

При разработке расширений в среде 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда новый реквизит, добавленный в расширение документа, отказывается «узнаваться» компилятором в модуле формы. Ошибка Переменная не определена может поставить в тупик, особенно если в этом же модуле стандартные реквизиты объекта доступны без проблем. В данной статье мы детально разберем, почему это происходит, и проанализируем механизмы работы с данными в контексте управляемых форм типовых конфигураций, таких как 1С:ERP или 1С:Комплексная автоматизация 2.

Суть проблемы: контекст формы и метаданные

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

Первое, что нам необходимо сделать, — это проанализировать, с какой именно формой мы работаем. В конфигурациях на базе ERP/УТ 11/КА 2 формы создания документов (например, форма создания счета на оплату) часто не являются формами объекта. Это вспомогательные формы обработки или специализированные формы, у которых нет основного реквизита типа ДокументОбъект. Следовательно, переменная Объект там отсутствует или не содержит данных самого документа в привычном виде.

Почему стандартные реквизиты видны, а новые — нет?

В типовых решениях формы подбора или создания документов оперируют набором реквизитов формы или специальными структурами данных. Стандартный реквизит ДокументОснование виден только потому, что он либо явно добавлен в состав реквизитов этой формы в основной конфигурации, либо передан в контекст процедуры через параметры. Ваш новый реквизит ДокОснование, добавленный в метаданные документа, автоматически не становится реквизитом вспомогательной формы. Чтобы форма его «увидела», его нужно либо добавить в расширение самой формы как реквизит формы, либо передать через механизм параметров.

Решение 1: Добавление реквизита в форму расширения

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

  1. Откроем расширение формы в конфигураторе.
  2. Перейдем на вкладку Реквизиты.
  3. Добавим новый реквизит формы с именем ДокОснование и соответствующим типом.
  4. Теперь в модуле формы мы сможем обращаться к нему напрямую по имени.

Однако в процедурах, замещающих стандартную логику (например, при использовании аннотации &Вместо), этого может быть недостаточно, так как данные должны попасть в алгоритм формирования документа.

Решение 2: Использование параметров и структур (на примере структуры ШапкаОснование)

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

Посмотрим на пример реализации в процедуре &НаСервере. Если при открытии формы в нее был передан параметр ДокОснование, мы можем извлечь его и передать дальше:


&НаСервере
&Вместо("ОбновитьСервер")
Процедура ВСП_ОбновитьСервер()
    
    // ... (код формирования запросов для получения данных основания) ...

    Если ВыборкаШапка.Следующий() Тогда
        
        // Стандартное заполнение свойств из выборки запроса
        ЗаполнитьЗначенияСвойств(ШапкаОснование, ВыборкаШапка);
        
        // Вставка нашего нового реквизита в структуру данных
        // Обращаемся к параметрам формы, которые были переданы при открытии
        Если Параметры.Свойство("ДокОснование") Тогда
            ШапкаОснование.Вставить("ДокОснование", Параметры.ДокОснование);
        КонецЕсли;
        
        Валюта = ВыборкаШапка.Валюта;
        
    КонецЕсли;

    // Вызов оригинальной логики, если это необходимо
    ПродолжитьВызов();
КонецПроцедуры

Использование Параметры.ДокОснование позволяет получить значение без создания лишних реквизитов формы, если значение требуется только в момент инициализации или обновления данных на сервере.

Разбор по шагам: передача данных через ПриСозданииНаСервере

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


&НаСервере
Процедура ВСП_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    
    // Проверяем наличие параметра, переданного из формы-инициатора
    Если Параметры.Свойство("ДокОснование") Тогда
        // Присваиваем значение реквизиту формы (он должен быть создан в расширении!)
        ЭтаФорма.ДокОснование = Параметры.ДокОснование;
    КонецЕсли;
    
КонецПроцедуры

Теперь, когда значение сохранено в ЭтаФорма.ДокОснование, любая другая серверная процедура (например, ОбновитьСервер) сможет получить к нему доступ. Обратите внимание, что обращение к Объект.ДокОснование в данном контексте выдаст ошибку Переменная не определена (Объект), так как форма не привязана к конкретному объекту метаданных напрямую.

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

Часто ошибка возникает не только в коде 1С, но и при попытке получить данные через запрос внутри расширения. Если вы добавляете реквизит в расширение, помните, что он становится частью физической таблицы БД. Рассмотрим фрагмент запроса, который собирает данные для «Шапки» документа из расширенного справочника или документа:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ДанныеДокумента.Ссылка КАК Документ,
    |    ДанныеДокумента.Партнер КАК Партнер,
    |    ДанныеДокумента.ДокОснование КАК ДокОснование // Наш новый реквизит
    |ИЗ
    |    Документ.СчетНаОплатуКлиенту КАК ДанныеДокумента
    |ГДЕ
    |    ДанныеДокумента.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ТекущийДокумент);

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

Важные рекомендации при использовании &Вместо

Использование аннотации &Вместо — мощный, но опасный инструмент. При замещении процедуры ОбновитьСервер мы берем на себя ответственность за всю логику, которая была в типовом решении. Если фирма «1С» обновит конфигурацию и добавит в эту процедуру важные проверки или расчеты, ваше расширение продолжит выполнять старый код, что приведет к логическим ошибкам.

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

Итоги

Подведем итог нашему исследованию. Если реквизит в расширении «не виден» в форме:

Соблюдение этих правил позволит вам избежать ошибок компиляции и обеспечит корректную работу расширения даже в сложных типовых конфигурациях 1С.

← На главную