Как из формы списка документа запустить процедуру из модуля формы этого документа?

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

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

Способ 1. Прямой вызов через получение формы (Технический подход)

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

  1. Процедура в модуле формы документа должна быть помечена ключевым словом Экспорт.
  2. В форме списка нам нужно программно получить экземпляр формы документа.

Рассмотрим пример кода в форме списка, где мы пытаемся вызвать экспортную процедуру ВыполнитьВажноеДействие() из формы документа:


&НаКлиенте
Процедура КомандаВызватьПроцедуруФормы(Команда)
    // Получаем ссылку на текущий документ из строки списка
    ТекущаяСтрока = Элементы.Список.ТекущиеДанные;
    Если ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;

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

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

Способ 2. Использование Модуля Менеджера (Архитектурно правильный подход)

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

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


// В Модуле менеджера документа
Процедура СформироватьПечатнуюФорму(СсылкаНаДокумент) Экспорт
    // Здесь располагается логика формирования документа
    // ...
КонецПроцедуры

Теперь из любой формы (будь то список, или форма другого документа) вызов будет выглядеть элегантно и просто:


&НаСервере
Процедура ВызватьМетодМенеджера(ВыбраннаяСсылка)
    Документы.РеализацияТоваровУслуг.СформироватьПечатнуюФорму(ВыбраннаяСсылка);
КонецПроцедуры

Проанализируем ситуацию: этот метод позволяет нам работать с данными документа, не создавая лишних объектов в памяти. Если процедура требует контекста сервера, это идеальное решение.

Способ 3. Модуль объекта (Для работы с данными)

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

Вызов из формы списка в таком случае будет выглядеть так:


&НаСервере
Процедура ИзменитьДанныеОбъекта(ВыбраннаяСсылка)
    // Получаем объект документа для редактирования
    ОбъектДокумента = ВыбраннаяСсылка.ПолучитьОбъект();
    
    // Вызываем экспортный метод модуля объекта
    ОбъектДокумента.РассчитатьСкидкиПоАкциям();
    
    // Записываем изменения
    ОбъектДокумента.Записать();
КонецПроцедуры

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

Использование БСП и подсистемы «Печать»

Если ваша задача — запустить печать, то в современных конфигурациях (УТ 11, ERP, БП 3.0), построенных на базе Библиотеки Стандартных Подсистем (БСП), процедуру печати вообще не нужно вызывать вручную «через точку». Система делает это автоматически.

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

  1. Кнопка печати автоматически появляется в форме документа.
  2. Эта же кнопка автоматически появляется в форме списка.
  3. Пользователь может выделить в списке несколько строк и нажать «Печать» — система сама передаст массив ссылок в процедуру печати.

Это избавляет от необходимости писать какой-либо код в модуле формы списка вообще.

Проблема контекста: Клиент или Сервер?

Рассмотрим еще одну сложность. Процедуры в модуле формы часто используют директиву &НаКлиенте. Если вы пытаетесь вызвать такую процедуру из серверного контекста формы списка, платформа выдаст ошибку. Форма списка — это динамический список, который живет на сервере, а взаимодействие с пользователем происходит на клиенте.

Если вы вызываете процедуру через ПолучитьФорму(), помните:

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

Подводя итог, можно сказать: техническая возможность вызвать процедуру из формы документа существует (через ПолучитьФорму() и Экспорт), но это считается «антипаттерном» в разработке на 1С.

Правильный алгоритм действий:

  1. Если логика относится к печати или обработке нескольких документов — перенесите её в Модуль менеджера.
  2. Если логика меняет внутренние данные документа — перенесите её в Модуль объекта.
  3. Если логика должна использоваться в разных объектах метаданных — создайте Общий модуль.
  4. Оставляйте в модуле формы только тот код, который управляет элементами интерфейса (видимость кнопок, доступность полей, раскраска строк).

Следуя этим правилам, вы сделаете свой код надежным, быстрым и понятным для других разработчиков.

← На главную