Как вызвать процедуру одной формы из другой в 1С 8.3: передача контекста и лучшие практики

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

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

Способ 1. Использование общего модуля (Рекомендуемый подход)

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

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

Разберем пример кода в общем модуле:


// В общем модуле (Серверный, Вызов сервера)
Процедура ОбработатьДанныеФормы(КонтекстФормы) Экспорт
    // Получаем данные объекта через свойство формы
    ОбъектДокумента = КонтекстФормы.Объект;
    
    // Выполняем общую логику
    Если ОбъектДокумента.СуммаДокумента > 1000 Тогда
        ОбъектДокумента.Комментарий = "Крупный заказ";
    КонецЕсли;
    
    // Если нужно изменить реквизиты самой формы (не объекта)
    КонтекстФормы.ТолькоПросмотр = Ложь;
КонецПроцедуры

Теперь в модуле любой из ваших форм (Форма 1 или Форма 2) вы можете вызвать эту общую процедуру, передав в нее ключевое слово ЭтаФорма:


&НаСервере
Процедура ВызватьОбщуюЛогику()
    РаботаСФормамиКлиентСервер.ОбработатьДанныеФормы(ЭтаФорма);
КонецПроцедуры

Преимущества: код хранится в одном месте, его легко обновлять, и он доступен для любого объекта конфигурации.

Способ 2. Вызов экспортной процедуры через ПолучитьФорму()

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

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

Рассмотрим пример реализации:

В модуле Формы 2 (откуда берем код):


&НаКлиенте
Процедура МояЭкспортнаяПроцедура(Параметр1) Экспорт
    Сообщить("Вызвана процедура из второй формы: " + Параметр1);
КонецПроцедуры

В модуле Формы 1 (где вызываем):


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

Важный нюанс: Если форма управляемая, то вызвать таким образом можно только клиентские процедуры (&НаКлиенте). Прямой вызов серверных процедур модуля формы извне не поддерживается платформой из соображений безопасности и контекстной изоляции.

Способ 3. Механизм оповещений (Событийная модель)

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

Представим, что при изменении данных в одной форме нам нужно запустить алгоритм в другой. Используем метод Оповестить():


// В Форме 1
&НаКлиенте
Процедура ПослеИзмененияДанных()
    ПараметрыСобытия = Новый Структура("ID, Статус", 123, "Обновлено");
    Оповестить("СобытиеОбновленияДанных", ПараметрыСобытия, ЭтаФорма);
КонецПроцедуры

Во Форме 2 (которая должна отреагировать) создаем обработчик события:


&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
    Если ИмяСобытия = "СобытиеОбновленияДанных" Тогда
        // Здесь пишем код, который должен выполниться
        РассчитатьИтогиПоПараметрам(Параметр);
    КонецЕсли;
КонецПроцедуры

Этот подход идеален для реализации «отложенного» вызова или синхронизации данных между несколькими открытыми окнами.

Способ 4. Программное создание команд и механизм БСП

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

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

Посмотрим на пример программного создания команды в ПриСозданииНаСервере:


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

&НаКлиенте
Процедура Подключаемый_ВыполнитьДействие()
    // Вызываем логику из общего модуля, передавая текущий контекст
    ВнешниеОбработчикиСервер.ВыполнитьЛогику(ЭтаФорма);
КонецПроцедуры

Подведем итоги и выберем лучшее решение

Выбор метода зависит от вашей конкретной задачи:

  1. Если вы проектируете систему с нуля: Используйте способ №1 (Общий модуль). Это золотой стандарт разработки. Выносите всю бизнес-логику из модулей форм. Модуль формы должен отвечать только за отображение и интерфейсные действия.
  2. Если вам нужно разово вызвать код из уже готовой формы: Подойдет способ №2 (экспортная процедура), но следите за тем, чтобы форма не была слишком «тяжелой» для инициализации.
  3. Если формы открыты одновременно: Однозначно используйте оповещения (Способ №3).
  4. Если вы работаете в типовой конфигурации: Посмотрите, как реализованы ПодключаемыеКоманды. Это сложный, но самый гибкий путь для тиражируемых решений.

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

Рассмотрев все варианты, мы видим, что наиболее эффективным и безопасным является передача контекста ЭтаФорма в серверный общий модуль. Это дает полный доступ к данным объекта и реквизитам формы, сохраняя при этом чистоту и расширяемость кода.

← На главную