При работе с платформой 1С:Предприятие 8.3, особенно в управляемом приложении, мы часто сталкиваемся с необходимостью автоматизации различных задач. Одной из таких задач является программный запуск внешних печатных форм (ВПФ). Когда ВПФ регистрируется в системе с типом команды ВызовСерверногоМетода, мы знаем, что можем легко автоматизировать её выполнение, в том числе пакетно и в фоновом режиме, используя стандартные механизмы Библиотеки стандартных подсистем (БСП). Однако, когда тип команды ВПФ установлен как ВызовКлиентскогоМетода, задача значительно усложняется.
Нас интересует, существует ли аналогичный "командный интерфейс" в БСП или другие удобные средства для пакетного, неинтерактивного запуска ВПФ с клиентским вызовом. Давайте разберем эту ситуацию подробнее и рассмотрим возможные пути решения.
Прежде всего, давайте выясним, почему запуск ВызовКлиентскогоМетода так сильно отличается от серверного. Как следует из названия, клиентские методы предназначены для выполнения кода на стороне клиента. Это означает, что они всегда требуют активного клиентского сеанса (тонкий или толстый клиент, веб-клиент) и, как правило, связаны с некоторой формой. Форма выступает в роли контекста, в котором выполняются клиентские действия.
ВызовКлиентскогоМетода, это часто означает, что она может открывать промежуточную форму для ввода параметров, показывать диалоги, или выполнять другие действия, требующие пользовательского участия.ВызовСерверногоМетода, поскольку только он может быть выполнен полностью в фоновом режиме без участия пользователя.Таким образом, прямо "сделать клиентский запуск так же, как серверный" в полностью автоматизированном режиме без какого-либо взаимодействия с формой или клиентским приложением, к сожалению, не получится.
Если нам требуется пакетный, полностью автоматизированный запуск ВПФ, без какого-либо участия пользователя и без открытия форм, наиболее эффективным и правильным решением будет изменение логики ВПФ для использования ВызовСерверногоМетода. Мы настоятельно рекомендуем рассмотреть этот путь в первую очередь, так как он соответствует архитектуре платформы для автоматизации.
Нам необходимо переместить всю основную логику, которая генерирует печатную форму или выполняет необходимые действия, из клиентских процедур во внутренний или внешний общий модуль, доступный на сервере. Давайте рассмотрим пошаговый план:
&НаСервере или находиться в серверном контексте.
// Пример серверной функции в модуле ВПФ
// Допустим, это модуль объекта ВнешнейОбработки
&НаСервере
Функция СформироватьДокументНаСервере(ПараметрыПечати)
// Здесь будет вся логика формирования данных, обращения к базе
// и, при необходимости, взаимодействие со сторонним ПО на сервере.
// Например, формирование табличного документа, выгрузка данных в файл и т.д.
ТабличныйДокумент = Новый ТабличныйДокумент;
// ... Ваш код по формированию ТабличногоДокумента ...
Возврат ТабличныйДокумент;
КонецФункции
ВызовСерверногоМетода и в качестве имени метода укажите вашу новую серверную функцию.
// В процедуре ПолучитьСведенияОВнешнейОбработке()
// Вашей ВПФ
&НаКлиенте
Процедура ПолучитьСведенияОВнешнейОбработке(Сведения)
// ...
Сведения.ТипКоманды = "ВызовСерверногоМетода";
Сведения.ИмяМетода = "СформироватьДокументНаСервере"; // Имя вашей серверной функции
// ...
КонецПроцедуры
ВызовКлиентскогоМетода использовался для взаимодействия со сторонним ПО на стороне клиента, то при переходе на серверный вызов необходимо либо найти аналогичное ПО на стороне сервера, либо изменить логику таким образом, чтобы сервер формировал необходимые данные, а клиентское ПО запускалось извне 1С с этими данными.После перевода ВПФ на серверный вызов, вы сможете использовать стандартные средства БСП для пакетного и фонового выполнения. Например, подсистема "Длительные операции" или "Очередь заданий" позволяют планировать и контролировать выполнение таких задач.
Мы используем функции из общего модуля ДополнительныеОтчетыИОбработки или ПодключаемыеКоманды для запуска серверных команд ВПФ. Например, для программного запуска вам потребуется получить объект внешней обработки и вызвать его метод, который ранее был зарегистрирован как серверный.
// Пример кода для программного вызова серверной ВПФ
// на клиенте или сервере (в зависимости от контекста, где запускается ваш код)
&НаСервереБезКонтекста
Функция ВыполнитьПечатьСервернойВПФ(СсылкаНаОбъект, ИдентификаторКоманды)
// Находим зарегистрированную ВПФ по ее команде или имени
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДополнительныеОтчетыИОбработки.Ссылка КАК Ссылка
|ИЗ
| Справочник.ДополнительныеОтчетыИОбработки КАК ДополнительныеОтчетыИОбработки
|ГДЕ
| ДополнительныеОтчетыИОбработки.ИдентификаторКоманды = &ИдентификаторКоманды";
Запрос.УстановитьПараметр("ИдентификаторКоманды", ИдентификаторКоманды);
РезультатЗапроса = Запрос.Выполнить().Выбрать();
Если РезультатЗапроса.Следующий() Тогда
СсылкаНаВПФ = РезультатЗапроса.Ссылка;
// Получаем макет внешней обработки
МакетОбработки = ДополнительныеОтчетыИОбработки.ПолучитьМакет(СсылкаНаВПФ);
Если МакетОбработки = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
// Создаем временную внешнюю обработку
ИмяФайла = УникальныйИдентификатор().Строка() + ".epf";
ИмяВременногоФайла = КаталогВременныхФайлов() + ИмяФайла;
МакетОбработки.Записать(ИмяВременногоФайла);
// Подключаем внешнюю обработку
Попытка
ВнешняяОбработкаОбъект = ВнешниеОтчетыИОбработки.Подключить(ИмяВременногоФайла);
// Формируем параметры для вызова серверного метода ВПФ
// Это могут быть параметры, которые ожидает ваша функция СформироватьДокументНаСервере
ПараметрыПечати = Новый Структура;
ПараметрыПечати.Вставить("ОбъектыПечати", Новый Массив);
ПараметрыПечати.ОбъектыПечати.Добавить(СсылкаНаОбъект); // Например, ссылка на документ
// Добавьте другие необходимые параметры
// Вызываем серверный метод ВПФ
// Имя метода должно соответствовать тому, что указано в Сведения.ИмяМетода
Результат = ВнешняяОбработкаОбъект.СформироватьДокументНаСервере(ПараметрыПечати);
// При необходимости, отключаем внешнюю обработку
ВнешниеОтчетыИОбработки.Отключить(ИмяВременногоФайла);
Возврат Результат;
Исключение
// Обработка ошибки
Возврат Неопределено;
КонецПопытки;
КонецЕсли;
Возврат Неопределено;
КонецФункции
Мы видим, что такой подход позволяет полностью автоматизировать запуск ВПФ, если её логика переведена на серверную сторону.
Однако, бывают ситуации, когда переход на ВызовСерверногоМетода невозможен или крайне затруднителен. Например, если ВызовКлиентскогоМетода используется для взаимодействия со сторонним программным обеспечением (ПО), которое работает исключительно на стороне клиента. В таком случае нам придётся имитировать действия пользователя, программно открывая форму ВПФ и вызывая её команды.
Давайте проанализируем, как мы можем это сделать:
Мы можем использовать метод ПолучитьФорму() для программного получения экземпляра формы внешней обработки. Этот метод позволяет нам указать имя формы и, при необходимости, её владельца.
&НаКлиенте
Процедура ЗапуститьКлиентскуюВПФПрограммно()
// 1. Получаем зарегистрированную ВПФ.
// Мы можем получить ее как элемент справочника ДополнительныеОтчетыИОбработки.
// Предположим, у нас есть ссылка на элемент справочника, например:
// СсылкаНаВПФ = Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию("МояКлиентскаяВПФ");
// В реальной ситуации, мы могли бы получить ее из параметра или найти по ИдентификаторуКоманды.
// Для примера, создадим "виртуальный" объект ВПФ.
// В реальной жизни нужно загрузить ВПФ из базы или файла.
// Мы покажем пример загрузки из файла, но обычно БСП загружает ВПФ во временное хранилище.
ИмяФайлаВПФ = "C:\МоиОбработки\МояКлиентскаяВПФ.epf"; // Пример пути к файлу
Если Не ФайлСуществует(ИмяФайлаВПФ) Тогда
Сообщить("Файл ВПФ не найден: " + ИмяФайлаВПФ);
Возврат;
КонецЕсли;
// Создаем временный объект внешней обработки
ВнешняяОбработкаОбъект = Новый ВнешняяОбработка(ИмяФайлаВПФ);
// Если ВПФ подключается через БСП, то она уже загружена во временное хранилище,
// и нам нужно будет получить ее через механизм БСП, например, так:
// ИдентификаторВПФ = "МояУникальнаяВПФДляСправочникаСотрудники";
// ВнешняяОбработкаОбъект = ДополнительныеОтчетыИОбработки.ПолучитьОбъектОбработки(ИдентификаторВПФ);
// Если ВнешняяОбработкаОбъект = Неопределено Тогда ... Возврат; КонецЕсли;
// 2. Получаем форму ВПФ.
// Имя формы по умолчанию может быть "Форма", "ОсновнаяФорма" или другим,
// указанным в свойствах обработки.
ИмяФормы = "Форма";
Попытка
// Здесь мы можем передать владельца формы, если ВПФ ожидает его
// Например, ссылку на Справочник.Сотрудники, если ВПФ работает с ним
ВладелецФормы = Справочники.Сотрудники.НайтиПоКоду("000000001"); // Пример владельца
Если ВладелецФормы = Неопределено Тогда
Сообщить("Владелец формы не найден!");
Возврат;
КонецЕсли;
ФормаВПФ = ВнешняяОбработкаОбъект.ПолучитьФорму(ИмяФормы, ВладелецФормы);
Если ФормаВПФ = Неопределено Тогда
Сообщить("Не удалось получить форму ВПФ: " + ИмяФормы);
Возврат;
КонецЕсли;
// 3. Вызываем команды или методы формы.
// Нам нужно знать имя команды, которая соответствует клиентскому вызову.
// Обычно это команда печати или другая команда, которая выполняет логику ВПФ.
ИмяКоманды = "КомандаПечати"; // Пример имени команды на форме ВПФ
// Перед вызовом команды, возможно, потребуется установить параметры формы.
// Например, если на форме есть реквизиты, которые используются командой.
Если ФормаВПФ.ЕстьРеквизит("Параметр1") Тогда
ФормаВПФ.Параметр1 = "НекоеЗначение";
КонецЕсли;
// Вызываем команду. Команда должна быть доступна в коллекции КомандыФормы.
Если ФормаВПФ.Команды.Найти(ИмяКоманды) <> Неопределено Тогда
ФормаВПФ.Команды[ИмяКоманды].Выполнить();
Сообщить("Команда '" + ИмяКоманды + "' успешно выполнена.");
Иначе
Сообщить("Команда '" + ИмяКоманды + "' не найдена на форме ВПФ.");
КонецЕсли;
// 4. Закрываем форму, если она была открыта (в большинстве случаев она не открывается видимо,
// но создается в памяти)
ФормаВПФ.Закрыть();
Исключение
Сообщить("Ошибка при запуске клиентской ВПФ: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Мы видим, что метод ПолучитьФорму() возвращает объект формы, с которым мы можем взаимодействовать. Мы можем устанавливать значения реквизитов формы, вызывать её процедуры и функции, а также выполнять команды.
После получения формы, мы можем обратиться к её коллекции Команды и выполнить нужную команду. Важно знать точное имя команды, которая запускает логику ВПФ. Это имя обычно совпадает с именем, указанным при регистрации ВПФ в качестве ИмяКоманды.
Если команда требует каких-либо параметров, они либо передаются через реквизиты формы (которые мы можем установить программно до вызова команды), либо напрямую в метод команды, если она это поддерживает.
Если ВПФ ожидает параметры, например, ссылку на обрабатываемый объект (документ, элемент справочника), мы можем передать их через параметр ВладелецФормы при вызове ПолучитьФорму(), либо установить соответствующие реквизиты полученной формы.
Несмотря на то, что этот метод позволяет программно запустить клиентскую ВПФ, он имеет ряд существенных ограничений:
Форма.Открыть() не вызывается), она всё равно создается в памяти клиентского приложения, потребляя ресурсы.Мы разобрались, что прямого "командного интерфейса" в БСП для неинтерактивного программного запуска ВПФ с типом команды ВызовКлиентскогоМетода не существует, поскольку клиентские вызовы по своей природе ориентированы на пользовательский интерфейс и клиентский контекст. Мы рассмотрели два основных пути решения:
ВызовСерверногоМетода. Этот подход наиболее верен с архитектурной точки зрения, позволяет достичь полной автоматизации и пакетного выполнения через фоновые задания, освобождая нас от необходимости интерактивного взаимодействия.В большинстве случаев, если цель — полная автоматизация и пакетная обработка, мы будем стремиться к рефакторингу ВПФ для использования серверных вызовов. Если же без клиентского контекста никак не обойтись, мы будем использовать программное взаимодействие с формой, осознавая все связанные с этим ограничения.