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