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