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