Как вызвать процедуру модуля менеджера документа из обычной (неуправляемой) формы?

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

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

Анализ проблемы: почему директивы &НаСервере не работают в обычных формах

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

Выясним причину: в обычном приложении (Толстый клиент) код выполняется в едином контексте, и разделение на клиент/сервер происходит иначе, чем в управляемом приложении. Здесь за доступность кода отвечают не директивы, а инструкции препроцессора и свойства самих модулей в дереве метаданных.

Решение 1: Правильная настройка модуля менеджера и синтаксис вызова

Рассмотрим первый и самый важный шаг. Чтобы процедура модуля менеджера была доступна, она должна быть объявлена с ключевым словом Экспорт. Но этого недостаточно для обычного приложения. Посмотрим, как должен выглядеть код в модуле менеджера документа ЕС_ДоставкаДоКлиента:


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

Обратим внимание, что мы убрали &НаСервере. Теперь проанализируем, как вызвать эту процедуру из обычной формы внешней обработки. В модуле формы обработки также следует удалить все директивы &НаСервере. Вызов должен выглядеть следующим образом:


// В модуле обычной формы обработки
Процедура ОбработатьДокумент(Ссылка)
    ДокОбъект = Ссылка.ПолучитьОбъект();
    
    // Вызов через глобальную коллекцию менеджеров документов
    Документы.ЕС_ДоставкаДоКлиента.НайтиДокументыПоНомеруЗаказа(ДокОбъект);
    
    ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
КонецПроцедуры

Процедура КнопкаВыполнитьНажатие(Кнопка)
    Выборка = Документы.ЕС_ДоставкаДоКлиента.Выбрать();
    Пока Выборка.Следующий() Цикл
        ОбработкаПрерыванияПользователя();
        ОбработатьДокумент(Выборка.Ссылка);
    КонецЦикла;
КонецПроцедуры

Решение 2: Настройка свойств компиляции модуля

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

  1. Откроем дерево метаданных и найдем нужный документ.
  2. Нажмем правой кнопкой мыши на документ и выберем "Открыть модуль менеджера".
  3. В открывшемся окне модуля (в правой части экрана или через контекстное меню) откроем Свойства.
  4. Убедимся, что установлены флажки Сервер и Толстый клиент (обычное приложение).

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

Решение 3: Переход на сервер через Общие модули

Если нам принципиально нужно, чтобы код выполнился именно на стороне сервера (например, для оптимизации работы с БД или если процедура использует функционал, доступный только на сервере), вызов из обычной формы напрямую в модуль менеджера может не обеспечить реального серверного исполнения (в толстом клиенте код может выполниться на стороне клиента).

Разберем, как сделать "честный" переход на сервер:

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

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

Теперь из обычной формы мы вызываем этот общий модуль. Это гарантирует, что управление будет передано с клиента на сервер.

Важные замечания по передаче данных

Проанализируем передачу параметров. В обычном приложении между процедурами можно передавать ДокументОбъект. Однако, если вы решите перейти на управляемые формы в будущем, помните: на сервер нельзя передать объект, можно передавать только Ссылка или ДанныеФормы.

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

Резюмируем:

← На главную