Почему 1С не видит экспортную процедуру из модуля объекта в модуле формы и как это исправить?

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

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

Разбор типичной ситуации и анализ кода

Представим сценарий: мы создаем обработку для конфигурации «Управление торговлей 10.3» (или любой другой на обычных формах). В модуле объекта нашей обработки мы пишем полезный функционал, например, поиск номенклатуры по штрихкоду. Код в модуле объекта выглядит следующим образом:


Процедура ПолучитьНоменклатуруПоШК(ШК) Экспорт 
    Запрос = Новый Запрос; 
    Запрос.Текст = "ВЫБРАТЬ 
                   | Штрихкоды.Штрихкод КАК ШК, 
                   | Штрихкоды.Владелец КАК Номенклатура, 
                   | Штрихкоды.ТипШтрихкода, 
                   | Штрихкоды.ЕдиницаИзмерения, 
                   | Штрихкоды.ХарактеристикаНоменклатуры, 
                   | Штрихкоды.СерияНоменклатуры, 
                   | Штрихкоды.Качество 
                   |ИЗ 
                   | РегистрСведений.Штрихкоды КАК Штрихкоды 
                   |ГДЕ 
                   | Штрихкоды.Штрихкод = &Штрихкод"; 
    Запрос.УстановитьПараметр("Штрихкод", ШК); 
    Таблица = Запрос.Выполнить.Выгрузить; 
    
    Если Таблица.Количество() = 1 Тогда 
        ЗаполнитьСписокНоменклатур(Таблица[0].ШК, Таблица[0].Номенклатура, Таблица[0].ЕдиницаИзмерения);
    ИначеЕсли Таблица.Количество() > 1 Тогда 
        ВыборИзНесколькихНоменклатур(Таблица); 
    Иначе 
        Сообщить("Не удалось найти номенклатуру с введенным штрихкодом: " + ШК); 
    КонецЕсли; 
КонецПроцедуры

Затем в модуле формы мы пытаемся вызвать эту процедуру при изменении текста в поле ввода:


Процедура ВводШКАвтоПодборТекста(Элемент, Текст, ТекстАвтоПодбора, СтандартнаяОбработка) 
    СтандартнаяОбработка = Ложь; 
    ПолучитьНоменклатуруПоШК(Текст); // Здесь возникает ошибка
    ВводШК = ""; 
КонецПроцедуры

Несмотря на то, что процедура в модуле объекта объявлена как Экспорт, система ее не видит. Выясним причину этого поведения.

Причина 1: Отсутствие или неверная настройка основного реквизита формы

В обычных формах (толстый клиент) ключевым связующим звеном между формой и логикой объекта является Основной реквизит. Проанализируем, как это работает: когда вы создаете «Форму объекта» (для справочника или документа) или «Форму обработки» через мастер создания форм, система автоматически добавляет реквизит с типом СправочникОбъект, ДокументОбъект или ОбработкаОбъект соответственно.

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

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

  1. Откройте закладку «Реквизиты» в редакторе формы.
  2. Проверьте наличие реквизита с типом ОбработкаОбъект.ИмяВашейОбработки.
  3. Если его нет — добавьте вручную.
  4. В свойствах этого реквизита обязательно установите флажок «Основной реквизит».

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

Причина 2: Обращение к объекту в произвольной форме

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

Проанализируем способы решения для произвольных форм:

Способ А: Программное создание объекта. Мы можем создать экземпляр обработки непосредственно в коде формы и вызвать его метод:


ОбъектОбработки = Обработки.ИТЛ_СравнениеНоменклатурПоШК.Создать();
ОбъектОбработки.ПолучитьНоменклатуруПоШК(Текст);

Способ Б: Использование не основного реквизита. Если у вас есть реквизит формы (допустим, с именем Объект), тип которого ОбработкаОбъект, но он не назначен основным, обращение должно идти через него:

Объект.ПолучитьНоменклатуруПоШК(Текст);

Причина 3: Директивы компиляции и препроцессора

Хотя в обычных формах мы не используем привычные для управляемого приложения директивы &НаСервере или &НаКлиенте, в модулях объектов могут присутствовать инструкции препроцессора. Посмотрим на пример:


#Если Сервер Тогда
Процедура ПолучитьНоменклатуруПоШК(ШК) Экспорт
    // Код процедуры
КонецПроцедуры
#КонецЕсли

Если код формы выполняется в контексте толстого клиента, а процедура обернута в блок #Если Сервер Тогда, то при определенных настройках соединения (например, в клиент-серверном варианте без использования сервера приложений для выполнения кода объектов) метод может оказаться недоступным. Убедитесь, что процедура в модуле объекта не ограничена директивами, которые исключают её из области видимости клиента.

Использование ключевого слова ЭтотОбъект

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

Рассмотрим правильный вариант вызова:


Процедура ВводШКАвтоПодборТекста(Элемент, Текст, ТекстАвтоПодбора, СтандартнаяОбработка) 
    СтандартнаяОбработка = Ложь; 
    ЭтотОбъект.ПолучитьНоменклатуруПоШК(Текст); 
    ВводШК = ""; 
КонецПроцедуры

Важный нюанс: Не путайте это с управляемыми формами, где ЭтотОбъект в модуле формы ссылается на саму форму. В обычных формах это прямая ссылка на объект метаданных.

Подведем итоги

Если вы столкнулись с тем, что форма «не видит» экспортный метод модуля объекта, пройдите по шагам этого алгоритма:

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

← На главную