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