Как программно нажать на кнопку в ПолеHTMLдокумента в 1С

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

При разработке интеграций или автоматизации работы с веб-сервисами внутри 1С программисты часто сталкиваются с необходимостью программного взаимодействия с веб-страницами. Одной из самых частых задач является поиск определенной кнопки на странице и имитация ее нажатия пользователем. В этой статье мы подробно разберем, как реализовать логику, аналогичную поиску элементов в C#, используя встроенные механизмы 1С и объектную модель HTML-документа (DOM).

Особенности работы ПоляHTMLдокумента в 1С

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

Базовый метод нажатия на кнопку по идентификатору

Если у кнопки на веб-странице есть уникальный атрибут id, задача решается максимально просто. Мы воспользуемся методом getElementById. Однако важно помнить, что обращаться к документу можно только после того, как он полностью загружен в поле.

Рассмотрим пример кода в обработчике события ДокументСформирован. Это событие гарантирует, что базовая структура страницы уже доступна для анализа:


Процедура ПолеHTMLДокумента1ДокументСформирован(Элемент)
    // Получаем объект документа
    ДокументHTML = ЭлементыФормы.ПолеHTMLДокумента1.Документ;
    
    // Пытаемся найти элемент по ID
    Кнопка = ДокументHTML.getElementById("findlink");
    
    // Важно проверить, что элемент найден, прежде чем вызывать методы
    Если Кнопка <> Неопределено Тогда
        Кнопка.click();
    КонецЕсли;
КонецПроцедуры

Проверка корректности загрузки данных

Иногда событие ДокументСформирован срабатывает, когда DOM-дерево еще не заполнено данными (например, при сложной структуре скриптов на сайте). Выясним причину, по которой метод click() может выдавать ошибку "Значение не является значением объектного типа". Чаще всего это происходит из-за того, что объект he (element) оказался равен null или undefined в контексте COM.

Разберем улучшенный вариант проверки с анализом содержимого body:


Процедура ПолеHTMLДокумента1ДокументСформирован(Элемент)
    ПолеHTML = ЭлементыФормы.ПолеHTMLДокумента1;
    
    // Проверяем, что тело документа не пустое
    Если ПолеHTML.Документ.body.innerText <> "" Тогда
        ПоискЭлемента = ПолеHTML.Документ.getElementById("button_id");
        
        Попытка
            ПоискЭлемента.click();
        Исключение
            Сообщить("Не удалось нажать кнопку: " + ОписаниеОшибки());
        КонецПопытки;
    КонецЕсли;
КонецПроцедуры

Поиск кнопок по атрибутам и классам (аналог C# FindElementByAttribute)

В исходном вопросе автор использовал сложную логику поиска по CSS-классам и регулярным выражениям. В 1С мы можем реализовать это через перебор коллекций элементов. Если нам нужно найти кнопку, у которой задан определенный класс (например, style-scope tt-icon-button), мы проанализируем все теги button на странице.

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

  1. Получаем все элементы с тегом button через getElementsByTagName.
  2. В цикле обходим каждый элемент.
  3. Проверяем соответствие атрибута className нашему условию.
  4. При совпадении вызываем событие нажатия.

// Пример поиска кнопки по классу
ВсеКнопки = ЭлементыФормы.ПолеHTMLДокумента1.Документ.getElementsByTagName("button");

Для Каждого ТекущаяКнопка Из ВсеКнопки Цикл
    // В COM-объекте IE атрибут class доступен через свойство className
    Если Найти(ТекущаяКнопка.className, "tt-icon-button") > 0 Тогда
        ТекущаяКнопка.click();
        Прервать; // Выходим из цикла после нажатия
    КонецЕсли;
КонецЦикла;

Использование CSS-селекторов (querySelector)

Если на компьютере установлена современная версия Internet Explorer (IE8 и выше), мы можем использовать более продвинутый метод querySelector. Это позволяет искать элементы так же, как в jQuery или современных браузерах, что значительно сокращает объем кода 1С.

Посмотрим на пример поиска кнопки со сложным набором классов:


// Используем CSS-селектор для поиска кнопки с классом tt-icon-button
Кнопка = ЭлементыФормы.ПолеHTMLДокумента1.Документ.querySelector("button.style-scope.tt-icon-button");

Если Кнопка <> Неопределено Тогда
    Кнопка.click();
КонецЕсли;

Альтернативные способы имитации клика

Бывают ситуации, когда прямой вызов метода click() не приводит к результату (например, если на кнопку навешаны сложные обработчики событий). В таких случаях проанализируем возможность принудительного вызова события (FireEvent) или выполнение кода через JavaScript.

Способ 1: FireEvent

Для старых версий движка IE используется метод инициации события:

Кнопка.fireEvent("onclick"); Способ 2: Исполнение JavaScript (eval)

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


// Выполнение произвольного JS-кода
ТекстСкрипта = "document.getElementById('button').click();";
ЭлементыФормы.ПолеHTMLДокумента1.Документ.parentWindow.eval(ТекстСкрипта);

Обработка динамически появляющихся элементов

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

Алгоритм действий:

  1. При формировании документа запускаем фоновое задание в форме через ПодключитьОбработчикОжидания.
  2. Раз в секунду проверяем наличие кнопки на странице.
  3. Как только кнопка найдена — нажимаем её и отключаем обработчик.

Процедура ПолеHTMLДокумента1ДокументСформирован(Элемент)
    // Запускаем проверку каждые 1 секунду
    ПодключитьОбработчикОжидания("НайтиИНажатьКнопку", 1);
КонецПроцедуры

Процедура НайтиИНажатьКнопку() Экспорт
    Документ = ЭлементыФормы.ПолеHTMLДокумента1.Документ;
    Кнопка = Документ.getElementById("dynamic_button");
    
    Если Кнопка <> Неопределено Тогда
        // Кнопка появилась! Нажимаем и отключаем таймер
        Кнопка.click();
        ОтключитьОбработчикОжидания("НайтиИНажатьКнопку");
    КонецЕсли;
КонецПроцедуры

Связь 1С и C# через COM

Как упоминалось в обсуждении, если логика поиска на C# уже написана и она слишком сложна для воспроизведения на встроенном языке 1С, можно использовать механизмы .NET Bridge. Это позволяет скомпилировать ваш C# код в DLL, сделать его ComVisible и вызывать напрямую из 1С, передавая внутрь объект Документ. В этом случае ваш метод на C# будет принимать object, приводить его к IHTMLDocument2 и выполнять все необходимые проверки IsVoid и регулярные выражения внутри привычной среды .NET.

Подводя итог, отметим, что для успешного нажатия кнопки в 1С необходимо убедиться в трех вещах: документ полностью загружен, элемент успешно найден в дереве DOM (проверка на Неопределено), и выбран правильный метод инициации события (click, fireEvent или eval).

← На главную