Как исправить ошибку «Метод объекта не обнаружен» при вызове экспортной функции документа из формы в 1С?

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

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

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

Выясняем причину: разница между Ссылкой и Объектом

Проанализируем исходную ситуацию. У нас есть форма, в которой добавлен реквизит СсылкаНаОбъект с типом данных ДокументСсылка.РеализацияТоваровУслуг. Разработчик пытается выполнить следующий код при нажатии кнопки:


Процедура Кнопка2Нажатие(Элемент)
    ДоверенноеЛицо = "---";
    Доверенность   = "(По доверенности № 02/20-ГС от 09 января 2020 года)";                
    СсылкаНаОбъект.ПечатьДоверенности(); // Ошибка возникает здесь!
    ЭтаФорма.Закрыть();    
КонецПроцедуры

Почему система выдает ошибку «Метод объекта не обнаружен (ПечатьДоверенности)», хотя функция в модуле документа объявлена как Экспорт?

Дело в типах данных. Реквизит СсылкаНаОбъект имеет тип ДокументСсылка. Ссылка в 1С — это всего лишь уникальный идентификатор записи (GUID) в таблице базы данных. Ссылка не содержит в себе данные документа (его табличные части, большинство реквизитов) и, самое главное, ссылка не имеет доступа к исполняемому коду модуля объекта.

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

Решение 1. Получение объекта из ссылки (Классический метод)

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


Процедура Кнопка2Нажатие(Элемент)
    // Получаем объект документа из ссылки
    ДокОбъект = СсылкаНаОбъект.ПолучитьОбъект();
    
    // Теперь мы можем вызвать экспортный метод объекта!
    ДокОбъект.ПечатьДоверенности();
    
    ЭтаФорма.Закрыть();    
КонецПроцедуры

Казалось бы, задача решена. Однако при запуске этого кода мы можем столкнуться со следующей ошибкой:
«Ошибка при вызове метода контекста (ПолучитьОбъект) по причине: Элемент не выбран!»

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

Чтобы избежать подобных ситуаций, мы обязательно должны проверять заполнение реквизита перед выполнением любых операций. Напишем надежный код с проверкой:


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

Передача параметров в экспортную функцию

Обратите внимание на локальные переменные в процедуре кнопки: ДоверенноеЛицо и Доверенность. В исходном коде автора они просто объявляются внутри процедуры формы, но никак не передаются в функцию печати. Модуль документа ничего не знает о переменных, объявленных локально в модуле формы!

Если нам нужно передать эти данные в печатную форму, мы должны передавать их как параметры экспортного метода.

Изменим объявление функции в модуле документа:


Функция ПечатьДоверенности(ИмяДоверенногоЛица, ТекстДоверенности) Экспорт
    // Теперь внутри функции доступны переменные ИмяДоверенногоЛица и ТекстДоверенности
    ТабДокумент = ПечатьУниверсальногоПередаточногоДокумента(); 
    
    // Здесь должна быть логика вывода этих параметров в макет...
    
    УниверсальныеМеханизмы.НапечататьДокумент(ТабДокумент, , , ОбщегоНазначения.СформироватьЗаголовокДокумента(Ссылка));
КонецФункции

Соответственно, вызов этой функции из модуля формы будет выглядеть так:


Процедура Кнопка2Нажатие(Элемент)
    Если Не ЗначениеЗаполнено(СсылкаНаОбъект) Тогда
        Предупреждение("Документ не выбран!");
        Возврат;
    КонецЕсли;

    ДоверенноеЛицо = "Иванов И.И.";
    Доверенность   = "Доверенность № 02/20-ГС от 09.01.2020";                
    
    ДокОбъект = СсылкаНаОбъект.ПолучитьОбъект();
    
    // Передаем параметры в метод объекта
    ДокОбъект.ПечатьДоверенности(ДоверенноеЛицо, Доверенность);
    
    ЭтаФорма.Закрыть();    
КонецПроцедуры

Решение 2. Использование Модуля Менеджера (Best Practice)

Хотя первый метод полностью рабочий, с точки зрения производительности и стандартов разработки 1С вызов метода ПолучитьОбъект() исключительно ради формирования печатной формы считается плохой практикой (антипаттерном).

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

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

Выполним оптимизацию по шагам:

Шаг 1. Перенесем функцию печати в Модуль менеджера документа РеализацияТоваровУслуг:


Функция ПечатьДоверенности(СсылкаНаДокумент, ДоверенноеЛицо, Доверенность) Экспорт
    // Для получения данных документа внутри модуля менеджера используется запрос по переданной СсылкаНаДокумент.
    // Это работает в разы быстрее, чем ПолучитьОбъект().
    
    ТабДокумент = Новый ТабличныйДокумент;
    // (Здесь располагается код заполнения макета данными из запроса)
    
    Возврат ТабДокумент;
КонецФункции

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


Процедура Кнопка2Нажатие(Элемент)
    Если Не ЗначениеЗаполнено(СсылкаНаОбъект) Тогда
        Предупреждение("Документ не выбран!");
        Возврат;
    КонецЕсли;

    ДоверенноеЛицо = "Иванов И.И.";
    Доверенность   = "Доверенность № 02/20-ГС от 09.01.2020";                
    
    // Вызываем экспортную функцию из модуля менеджера документа напрямую
    ТабДокумент = Документы.РеализацияТоваровУслуг.ПечатьДоверенности(СсылкаНаОбъект, ДоверенноеЛицо, Доверенность);
    
    // Отправляем сформированный табличный документ на печать средствами УТ 10.3
    УниверсальныеМеханизмы.НапечататьДокумент(ТабДокумент, , , ОбщегоНазначения.СформироватьЗаголовокДокумента(СсылкаНаОбъект));
    
    ЭтаФорма.Закрыть();    
КонецПроцедуры

Контекст встроенных форм документов

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

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


Процедура Кнопка2Нажатие(Элемент)
    ДоверенноеЛицо = "Иванов И.И.";
    Доверенность   = "Доверенность № 02/20-ГС от 09.01.2020";                
    
    // Прямой вызов метода текущего объекта формы
    ЭтотОбъект.ПечатьДоверенности(ДоверенноеЛицо, Доверенность);
    
    ЭтаФорма.Закрыть();    
КонецПроцедуры

Этот способ работает мгновенно, так как объект документа уже загружен в память формы, и никаких повторных обращений к базе данных не происходит.

Рекомендация: Использование Внешних печатных форм (ВПФ)

Если вы работаете с типовой конфигурацией «Управление торговлей 10.3», любое изменение структуры метаданных (добавление новых кнопок на формы, изменение модуля документа) снимает конфигурацию с поддержки и сильно затрудняет последующие обновления.

Для решения подобных задач настоятельно рекомендуется использовать механизм Внешних печатных форм:

  1. Создается внешняя обработка, в которой размещается форма для ввода параметров (Доверенное лицо, Доверенность).
  2. В модуле обработки пишется функция формирования печатной формы, принимающая ссылку на документ.
  3. Обработка регистрируется в справочнике «Внешние обработки» системы.

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

← На главную