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

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

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

Разбор контекста выполнения: почему в форме документа метод доступен, а в форме списка — нет?

Для того чтобы понять причину ошибки, проанализируем, как платформа «1С:Предприятие» работает с контекстами различных типов форм. Рассмотрим эту разницу подробнее:

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

Решение для обычных форм (Толстый клиент)

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

Рассмотрим пример кода, который решает эту задачу для обычной формы списка документов:


// 1. Получаем ссылку на текущую строку (выбранный документ) из табличного поля формы списка
СсылкаНаДокумент = ЭлементыФормы.ДокументСписок.ТекущаяСтрока; 

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

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

Решение для управляемых форм (Тонкий и веб-клиент)

В управляемом приложении (платформа 1С v8.3) архитектура работы с данными принципиально отличается: из соображений безопасности и производительности мы не можем напрямую работать с объектами базы данных на клиенте. Объекты существуют только на стороне сервера. Для детального изучения принципов распределения логики подойдёт материал по управлению контекстом выполнения кода в управляемых формах.

Вызов экспортного метода в управляемой форме документа

В управляемой форме документа для вызова экспортного метода объекта нам потребуется временно преобразовать реквизит формы в реальный объект базы данных на сервере, выполнить метод, а затем (если данные объекта изменились) вернуть их обратно в форму. Посмотрим на пример реализации:


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

Вызов экспортного метода в управляемой форме списка

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


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

&НаСервереБезКонтекста
Процедура ВыполнитьОперациюНаСервере(СсылкаНаОбъект)
    // Получаем объект по ссылке на сервере
    ДокОбъект = СсылкаНаОбъект.ПолучитьОбъект();
    
    // Вызываем экспортный метод
    ДокОбъект.ИмяЭкспортногоМетода();
КонецПроцедуры

Архитектурные стандарты 1С: как оптимизировать код?

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

Проанализируем более изящные и производительные альтернативы:

Вариант 1. Перенос логики в модуль менеджера объекта

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

В модуле менеджера документа (например, РеализацияТоваровУслуг) определим экспортную функцию:


Функция ПолучитьСтатусДокумента(СсылкаНаДокумент) Экспорт
    // Здесь мы можем использовать легкий запрос к базе данных вместо получения всего объекта
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   РеализацияТоваровУслуг.Статус
        |ИЗ
        |   Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
        |ГДЕ
        |   РеализацияТоваровУслуг.Ссылка = &Ссылка";
    
    Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент);
    // Выполняем запрос и возвращаем результат...
КонецФункции

Теперь из формы списка мы можем вызвать этот метод напрямую, без использования тяжелого метода ПолучитьОбъект():


&НаСервереБезКонтекста
Функция ПолучитьСтатусНаСервере(СсылкаНаДокумент)
    Возврат Документы.РеализацияТоваровУслуг.ПолучитьСтатусДокумента(СсылкаНаДокумент);
КонецФункции

Вариант 2. Использование Общих модулей

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

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

← На главную