К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как из формы внешнего отчета вызвать процедуру модуля объекта в 1С

Как из формы внешнего отчета 1С вызвать процедуру модуля объекта: ЭтотОбъект, ПолучитьОбъект, экспортные методы, управляемые и обычные формы, типичные ошибки.

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

Ключевой момент: в управляемой форме контекст модуля объекта напрямую недоступен, потому что форма и объект существуют в разных контекстах исполнения. Способ вызова зависит от того, работаете ли вы в обычном приложении, в управляемом приложении, на клиенте или на сервере. Ниже разобраны рабочие приёмы для каждого случая, ограничения платформы и типичные ошибки.

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

Как устроена связь формы и модуля объекта внешнего отчета

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

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

Поэтому первый шаг перед написанием кода — определить, в каком режиме работает ваше решение: обычное приложение, управляемое приложение или тонкий/веб-клиент. От этого зависит весь дальнейший синтаксис.

Вызов в обычной форме: прямое обращение к объекту

В обычной форме внешнего отчета обращение к модулю объекта максимально простое. Если в модуле объекта объявлена процедура с ключевым словом Экспорт, она вызывается из модуля формы как обычный метод:

// Модуль объекта внешнего отчета

Процедура СформироватьДанные(ПараметрыОтчета) Экспорт

// логика формирования

КонецПроцедуры

// Модуль обычной формы

Процедура КнопкаСформироватьНажатие(Элемент)

ЭтотОбъект.СформироватьДанные(ПараметрыОтчета);

КонецПроцедуры

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

ОтчетОбъект.СформироватьДанные(ПараметрыОтчета);

Важное условие: без ключевого слова Экспорт в объявлении процедуры вызов завершится ошибкой «Процедура или функция с указанным именем не определена». Это самая частая причина «неработающего» кода у начинающих разработчиков.

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

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

Если форма — это основная форма отчета на СКД, у нее есть реквизит Отчет. В серверном контексте модуля формы доступен метод РеквизитФормыВЗначение("Отчет"), который возвращает объект отчета, у которого можно вызывать экспортные процедуры:

&НаКлиенте

Процедура Сформировать(Команда)

СформироватьНаСервере();

КонецПроцедуры

&НаСервере

Процедура СформироватьНаСервере()

ОбъектОтчета = РеквизитФормыВЗначение("Отчет");

ОбъектОтчета.СформироватьДанные(Период);

КонецПроцедуры

Обратите внимание: РеквизитФормыВЗначение создает копию объекта. Если ваша процедура меняет данные объекта и эти изменения должны отразиться в форме, после вызова нужно вернуть объект обратно методом ЗначениеВРеквизитФормы(ОбъектОтчета, "Отчет").

Порядок действий для управляемой формы
  1. 1
    В модуле объекта объявите нужную процедуру с ключевым словом Экспорт
  2. 2
    В модуле формы создайте клиентский обработчик команды или события
  3. 3
    Из клиентского обработчика вызовите серверную процедуру с директивой &НаСервере
  4. 4
    В серверной процедуре получите объект через РеквизитФормыВЗначение("Отчет")
  5. 5
    Вызовите экспортную процедуру у полученного объекта
  6. 6
    При необходимости верните изменения через ЗначениеВРеквизитФормы

Альтернатива: создание объекта внешнего отчета напрямую

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

&НаСервере

Процедура ВыполнитьНаСервере()

ОбъектОтчета = ВнешниеОтчеты.Создать("МойВнешнийОтчет");

ОбъектОтчета.МояЭкспортнаяПроцедура(Параметр);

КонецПроцедуры

Для файлового внешнего отчета, не зарегистрированного в информационной базе, применяется ВнешниеОтчеты.Создать(ПутьКФайлу, Ложь) — первым параметром передается полный путь к файлу .erf. Второй параметр определяет безопасный режим. Этот способ требует, чтобы файл был доступен на сервере, а не на клиенте, что в клиент-серверном варианте часто становится источником ошибок «файл не найден».

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

Сравнение способов вызова

ЭтотОбъект / ОтчетОбъект (обычная форма)

Самый простой синтаксис. Работает только в обычном приложении, недоступен на тонком клиенте.

РеквизитФормыВЗначение("Отчет")

Штатный способ для управляемой формы отчета на СКД. Требует серверного вызова и возврата значения при изменениях.

ВнешниеОтчеты.Создать()

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

Передача через параметры формы

Подходит при программном открытии формы. Не работает при интерактивном открытии пользователем.

Ограничения клиентского и серверного контекста

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

Директива &НаСервереБезКонтекста в форме отчета лишает доступа к реквизитам формы, включая Отчет, поэтому РеквизитФормыВЗначение там недоступен. Если нужен вызов без контекста, создавайте объект отдельно через ВнешниеОтчеты.Создать().

Также учитывайте: внешние отчеты по соображениям безопасности могут открываться в безопасном режиме, где запрещены операции с файловой системой и COM-объектами. Если экспортная процедура модуля объекта использует такие операции, она завершится ошибкой при выполнении в безопасном режиме.

Проверка результата и отладка

Быстрый способ убедиться, что вызов доходит до модуля объекта, — временно добавить в начало экспортной процедуры строку Сообщить("Процедура вызвана") или точку останова и запустить отладку. Если сообщение не появляется, проблема в цепочке вызова: неверная директива, отсутствует Экспорт или объект создается не тот.

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

Контрольные точки

Как проверить результат

Наличие Экспорт в объявлении процедуры
Норма

Процедура Имя(...) Экспорт в модуле объекта

Тревожный признак

Экспорт отсутствует — ошибка «процедура не определена»

Директива серверной процедуры формы
Норма

&НаСервере, есть доступ к РеквизитФормыВЗначение

Тревожный признак

&НаКлиенте — обращение к объекту невозможно

Изменения объекта видны в форме
Норма

После вызова выполнен ЗначениеВРеквизитФормы

Тревожный признак

Объект изменился, но форма показывает старые данные

Типичные ошибки и как их избежать

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

Вторая частая проблема — забытый Экспорт. При этом в обычной форме вызов падает с ошибкой «Процедура или функция с указанным именем не определена», а разработчик ищет проблему в имени процедуры, хотя имя верное.

Третья группа ошибок связана с потерей изменений: разработчик получил объект через РеквизитФормыВЗначение, изменил его, но не вернул обратно в форму. С точки зрения пользователя «процедура не работает», хотя код выполнился корректно — просто результат остался в локальной переменной.

Типичные ошибки
01
Вызов метода объекта из &НаКлиенте — ошибка компиляции или выполнения; переносите вызов в &НаСервере
02
Пропущено ключевое слово Экспорт — метод не виден извне модуля объекта
03
Нет ЗначениеВРеквизитФормы после изменений — форма не отражает результат работы процедуры
04
Путь к файлу отчета передан с клиента на сервер — файл не найден на сервере; используйте временное хранилище
05
Редактируется файл на диске, а в базе хранится старая копия — изменения не проявляются в режиме предприятия

Когда лучше перенести логику из модуля объекта

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

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

Итог

Что важно запомнить

Процедура модуля объекта доступна извне только с ключевым словом Экспорт. В обычной форме вызов идет напрямую через ЭтотОбъект или ОтчетОбъект, в управляемой — только на сервере через РеквизитФормыВЗначение("Отчет") или создание объекта методом ВнешниеОтчеты.Создать(). Измененный объект нужно вернуть в форму через ЗначениеВРеквизитФормы.

Частые вопросы

Почему возникает ошибка «Процедура или функция с указанным именем не определена»?

Чаще всего в объявлении процедуры модуля объекта отсутствует ключевое слово «Экспорт», и метод остается приватным. Реже причина в том, что вызов идет из клиентского контекста управляемой формы, где объект недоступен в принципе, либо редактируется другая копия отчета.

Можно ли вызвать процедуру модуля объекта без открытия формы?

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

Чем ЭтотОбъект в форме отличается от РеквизитФормыВЗначение("Отчет")?

ЭтотОбъект работает в обычной форме и ссылается на «живой» объект отчета. РеквизитФормыВЗначение в управляемой форме создает копию объекта из данных формы — изменения в копии не отражаются в форме, пока не выполнен обратный вызов ЗначениеВРеквизитФормы.

Как передать параметры в процедуру модуля объекта из формы?

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

Работает ли вызов в безопасном режиме?

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

Можно ли из формы одного внешнего отчета вызвать процедуру объекта другого отчета?

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