Как вызвать команду заполнения, которая находится в модуле формы 1С

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

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

Почему вызов процедуры из модуля формы — это проблема?

Прежде всего, проанализируем архитектуру управляемого приложения. Модуль формы предназначен исключительно для управления интерфейсом. Код, который там находится, тесно связан с контекстом формы, её реквизитами и визуальными элементами. Попытка вызвать этот код «снаружи» (например, из другого документа или обработки) наталкивается на ряд ограничений:

  1. Контекстная зависимость: Методы формы работают с данными, которые еще не записаны в базу, или с элементами оформления. При программном создании документа формы как таковой может вообще не существовать.
  2. Клиент-серверное разделение: Процедуры формы часто имеют директиву &НаКлиенте. Программное же создание документов обычно происходит на сервере. Вызвать клиентский метод с сервера технически невозможно.
  3. Производительность: Получение формы через ПолучитьФорму() на сервере — крайне ресурсоемкая операция, которая создает «тяжелый» объект в памяти ради выполнения одной процедуры.

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

Решение 1. Перенос логики в модуль объекта или менеджера (Золотой стандарт)

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

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


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

Теперь в модуле формы документа Производство кнопка будет просто вызывать этот метод:


&НаСервере
Процедура КомандаЗаполнитьНаСервере()
    // Преобразуем данные формы в объект, вызываем метод и возвращаем обратно
    ДокОбъект = РеквизитВЗначение("Объект");
    ДокОбъект.ЗаполнитьМатериалыПоСпецификации();
    ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедуры

А при программном создании документа из Реализации вызов будет выглядеть максимально просто и эффективно:


НовыйДокумент = Документы.Производство.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
// Заполняем основные реквизиты...
НовыйДокумент.ЗаполнитьМатериалыПоСпецификации(); // Вызываем логику напрямую
НовыйДокумент.Записать();

Решение 2. Использование механизма «ОбработкаЗаполнения»

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

В модуле объекта документа Производство опишем логику:


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
        // Логика заполнения на основании реализации
        ЭтотОбъект.ДокументОснование = ДанныеЗаполнения;
        // Вызываем расчет материалов
        ЗаполнитьМатериалыПоСпецификации();
    КонецЕсли;
КонецПроцедуры

Теперь при программном создании достаточно передать ссылку на основание:


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

Решение 3. Вызов экспортных методов формы (Если форма открыта)

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

Предположим, в форме документа Производство есть процедура:


&НаКлиенте
Процедура ВыполнитьПолноеЗаполнение() Экспорт
    // Код заполнения
КонецПроцедуры

Чтобы вызвать её из другого места (например, из формы Реализации), нам нужно получить ссылку на окно формы. Разберем по шагам:

  1. Получаем уникальный идентификатор или ищем открытую форму по параметрам.
  2. Вызываем экспортный метод через точку от объекта формы.

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

Важный нюанс: Этот способ работает только на клиенте. Если вы находитесь в серверном контексте, вызвать клиентский метод формы невозможно. Более того, если метод формы помечен &НаСервере, вы также не сможете вызвать его просто так, не имея инициализированного контекста формы.

Решение 4. Программное выполнение команд формы

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


// Где-то в коде, где доступен объект Форма
ИмяКоманды = "ЗаполнитьМатериалы";
ЭтаФорма.ВыполнитьКоманду(ИмяКоманды);

Однако помните, что это сработает только в том случае, если команда определена в коллекции Команды этой формы и её действие доступно в текущем контексте.

Решение 5. Работа через расширения (для типовых конфигураций)

Если вы работаете с типовой конфигурацией (ERP, УТ 11, КА) и не хотите менять основную конфигурацию, проанализируем возможности расширений. Вы можете перенести логику из формы в модуль объекта через расширение, используя аннотацию &Вместо или &После.

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

Резюме и рекомендации

Подведем итог нашему разбору. Попытка вызвать метод модуля формы «снаружи» — это сигнал о том, что архитектура системы требует улучшения. Выясним основные правила:

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

← На главную