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

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

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

Способ 1. Вызов через поиск открытой формы и преобразование данных

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

Рассмотрим пример кода, который позволяет это реализовать. Предположим, у нас есть ссылка на интересующий нас Документ №2.


&НаКлиенте
Процедура ВыполнитьВызовФункции(Команда)
    // 1. Ищем открытую форму документа по ссылке
    ФормаДокумента = НайтиОткрытуюФорму(СсылкаНаДокумент2);
    
    Если ФормаДокумента = Неопределено Тогда
        Сообщить("Документ №2 не найден среди открытых окон.");
        Возврат;
    КонецЕсли;

    // 2. Вызываем серверную процедуру, передавая данные формы
    ВызватьЭкспортныйМетодНаСервере(ФормаДокумента.Объект);
КонецПроцедуры

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

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

Важный нюанс: метод ДанныеФормыВЗначение создает в памяти сервера копию объекта. Если ваша экспортная функция внутри модуля объекта меняет какие-либо реквизиты, эти изменения останутся в этой временной копии и не отобразятся на экране пользователя в открытой форме Документа №2. Чтобы изменения вернулись на форму, потребуется вызвать ЗначениеВДанныеФормы, но это может привести к конфликтам блокировок, если пользователь в этот момент тоже редактирует документ.

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

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

Разберем по шагам, как это сделать:

  1. Создайте новый Общий модуль (например, РаботаСДокументамиСервер).
  2. Установите флаги «Сервер» и «Вызов сервера».
  3. Перенесите туда логику функции, сделав её экспортной. В качестве параметров передавайте необходимые данные (например, таблицу значений или структуру реквизитов).

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


// В Документе №1 просто вызываем общий модуль
Результат = РаботаСДокументамиСервер.РассчитатьЗначение(ПараметрыРасчета);

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

Способ 3. Вызов через Модуль менеджера

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

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


// Вызов из любого места конфигурации
Результат = Документы.ИмяДокумента2.МояФункция(Параметры);

Способ 4. Механизм оповещений (Оповестить и ОбработкаОповещения)

Проанализируем сценарий, когда Документ №2 открыт, и нам нужно «попросить» его форму отдать какую-то информацию или выполнить действие. Для интерактивной связи между двумя открытыми формами идеально подходит механизм Оповещений.

В форме Документа №1 (откуда инициируем запрос):


&НаКлиенте
Процедура ЗапроситьДанные(Команда)
    Оповестить("НужныДанныеДляДокумента1", , ЭтаФорма);
КонецПроцедуры

В форме Документа №2 (которая должна ответить):


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

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

Способ 5. Использование Временного хранилища

Если данных в табличной части Документа №2 много, и передавать их через параметры оповещения неудобно, можно использовать Временное хранилище.

Алгоритм действий будет таким:

  1. Документ №2 помещает свою таблицу во временное хранилище: Адрес = ПоместитьВоВременноеХранилище(Объект.ТабличнаяЧасть.Выгрузить()).
  2. Через механизм Оповестить передает Адрес в Документ №1.
  3. Документ №1 на сервере получает данные по адресу: Таблица = ПолучитьИзВременногоХранилища(Адрес).

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

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

Помните, что использование ДанныеФормыВЗначение для вызова функций модуля объекта — это ресурсоемкая операция. Старайтесь проектировать систему так, чтобы логика была отделена от интерфейса и конкретных экземпляров объектов.

← На главную