Как найти открытую форму обработки в 1С 8.3 и выполнить на ней команды?

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

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

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

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

Вариант 1. Поиск открытой формы через менеджер окон

Рассмотрим ситуацию, когда управляющее воздействие исходит от сторонней обработки (например, от специального «робота» или управляющего пульта, запущенного в той же сессии пользователя). Нам необходимо найти в памяти тонкого клиента конкретную форму по её имени и вызвать её экспортный метод.

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

Разберем по шагам код, который решает эту задачу:


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

Важное требование к коду формы-приемника: Чтобы вызываемая процедура была доступна извне, она обязательно должна быть объявлена в модуле целевой формы с директивой &НаКлиенте и ключевым словом Экспорт. Например:


&НаКлиенте
Процедура ВыполнитьЗагрузкуВыписокЭкспорт() Экспорт
    // Логика запуска загрузки выписок
    ПолучитьДанныеИзБанкаНаКлиенте();
КонецПроцедуры

Вариант 2. Использование механизма глобальных оповещений

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

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

Разберем, как реализовать этот подход:

Шаг 1. Отправка сигнала из управляющей обработки:


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

Шаг 2. Прием и обработка события в форме «иБанк2»:

В модуле целевой формы обработки нам необходимо переопределить стандартное предопределенное событие ОбработкаОповещения:


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

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

Вариант 3. Подключение обработчика ожидания на клиенте

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

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

Проанализируем программную реализацию обработчика ожидания:


&НаКлиенте
Перем ИмяПроцедурыОбработчика; // Глобальная переменная модуля формы для хранения имени процедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    ИмяПроцедурыОбработчика = "ВыполнитьРегулярныйОбменСБанком";
КонецПроцедуры

&НаКлиенте
Процедура КнопкаСтартАвторежимаНажатие(Кнопка)
    
    // Задаем интервал обновления в секундах (например, каждые 30 минут = 1800 секунд)
    ИнтервалОбновления = 1800; 
    
    // Подключаем однократное или многократное выполнение процедуры
    // Третий параметр Ложь означает, что обработчик будет выполняться периодически
    ПодключитьОбработчикОжидания(ИмяПроцедурыОбработчика, ИнтервалОбновления, Ложь);
    
    Элементы.ГруппаАвторежим.Доступность = Ложь;
    Элементы.ДекорацияСтатус.Заголовок = "Автоматический обмен запущен. Следующее обновление через " + ИнтервалОбновления + " сек.";
    
КонецПроцедуры

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

&НаКлиенте
Процедура КнопкаСтопАвторежимаНажатие(Кнопка)
    
    // Отключаем обработчик ожидания
    ОтключитьОбработчикОжидания(ИмяПроцедурыОбработчика);
    
    Элементы.ГруппаАвторежим.Доступность = Истина;
    Элементы.ДекорацияСтатус.Заголовок = "Автоматический обмен остановлен.";
    
КонецПроцедуры

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

Ограничения и недостатки клиентской автоматизации

Несмотря на то, что использование обработчика ожидания решает локальную проблему «здесь и сейчас», данный метод имеет архитектурные ограничения, которые необходимо донести до руководства:

  1. Блокировка интерфейса 1С. Если процедура загрузки выполняется на клиенте в один поток с интерфейсом, то в моменты отправки запросов в банк и ожидания ответов сеанс 1С у пользователя будет визуально «зависать». Для решения этой проблемы тяжелые вызовы (не связанные напрямую с криптографией на клиенте) следует выносить на сервер в фоновые задания.
  2. Зависимость от активности ПК. Если компьютер пользователя уходит в спящий режим, блокируется или отключается RDP-сессия, выполнение обработчиков ожидания в тонком клиенте может встать на паузу. Сеанс должен быть постоянно активен.
  3. Безопасность сессии. Оставлять открытую банковскую сессию с введенными SMS-паролями без присмотра на рабочем месте — серьезный риск информационной безопасности.

Альтернативное решение: Переход на 1С:ДиректБанк

Если бизнес требует полностью прозрачной, регулярной и безопасной загрузки выписок в фоновом режиме на сервере (без участия клиента и SMS-паролей), правильным техническим решением будет переход на технологию 1С:ДиректБанк.

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

← На главную