VBA - IE Automation - сохранить как PDF не работает - PullRequest
0 голосов
/ 19 октября 2018

Я пытаюсь автоматически загружать PDF-файлы с веб-сайта (размещение вакансий) благодаря автоматизации IE в VBA, и по какой-то причине мне не удается сгенерировать один PDF-файл.

Выполнение вручнуюзайдя на веб-страницу и выполнив команду «сохранить цель как» на значке pdf, она работает нормально и дает мне действительный файл PDF, но автоматизация не работает.

Я не понимаю, почему и надеюсь, что кто-то сможет датьмне подсказка.

Спасибо,

VeeBee

Пожалуйста, найдите ниже код, который у меня есть (URL-адреса общедоступны, и я выбрал предложения наугад)

Private Declare Function DownloadFilefromURL Lib "urlmon" _
Alias "URLDownloadToFileA" _
(ByVal pCaller As Long, _
ByVal szURL As String, _
ByVal szFileName As String, _
ByVal dwReserved As Long, _
ByVal lpfnCB As Long) As Long

Private Const ERROR_SUCCESS As Long = 0
Private Const BINDF_GETNEWESTVERSION As Long = &H10


Public Function DownloadFile(SourceUrl As String, LocalFile As String) As Boolean
    DownloadFile = DownloadFilefromURL(0&, SourceUrl, LocalFile, BINDF_GETNEWESTVERSION, 0&) = ERROR_SUCCESS
End Function


Sub TestSavePDF()
    Dim oNav As SHDocVw.InternetExplorer
    Dim oDoc As MSHTML.HTMLDocument
    Dim MyURL As String

    Set oNav = New SHDocVw.InternetExplorer
    oNav.Visible = True
    'Test Altays Client A (Banque de France)
    MyURL = "https://www.recrutement.banque-france.fr/detail-offre/?NoSource=16001&NoSociete=167&NoOffre=2036788&NoLangue=1"
    'Test Altays Client B (Egis)
    '        MyURL = "https://www.altays-progiciels.com/clicnjob/FicheOffreCand.php?PageCour=1&Liste=Oui&Autonome=0&NoOffre=2037501&RefOffrel=&NoFaml=0&NoParam1l=0&NoParam2l=0&NoParam3l=0&NoParam133l=0&NoParam134l=0&NoParam136l=0&NoEntite1=0&NoEntite=&NoPaysl=0&NoRegionl=0&NoDepartementl=0&NoTableOffreLieePl=0&NoTableOffreLieeFl=0&NoNivEtl=0&NoTableCCl=0&NoTableCC2l=0&NoTableCC3l=0&NoTableOffreUnl=0&NoTypContratl=0&NoTypContratProl=0&NoStatutOffrel=&NoUtilisateurl=&RechPleinTextel=#ancre3"


    oNav.navigate MyURL
    'link provided to download the job offer in PDF. when clicked the PDF opens in a new tab
    MyURL = "https://www.altays-progiciels.com/clicnjob/ExportPDFFront.php"

    DownloadFile MyURL, "C:\[...Path...]\test.pdf"

End Sub

1 Ответ

0 голосов
/ 20 октября 2018

Теневой DOM и создание недействительной ссылки:

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

Целевая ссылка:

enter image description here

Вы можетенажмите кнопку загрузки на этой странице

Кнопка загрузки:

enter image description here

Откроется новое окно, котороеВот почему Selenium великолепен.У Selenium есть способы переключиться на это новое окно.В противном случае вы можете использовать методы FindWindow, которые я подробно опишу позже в ответе для поиска окна Save As.

В этом новом окне вы не можете взаимодействовать с кнопками так, как вы это обычно делаете при извлечении в качестве необходимого содержимого.недоступно через DOM.Если вы внимательно посмотрите, то увидите, что кнопка pdf находится в shadow-root, то есть там, где вы не можете получить к ней доступ.Это выбор дизайна.Мне нужно исследовать эту возможность (выбор с помощью теневого DOM с помощью '/ deep /' комбинатора) в какой-то момент, но я не думаю, что это верно в VBA.

Кнопка загрузки в Shadow root:

enter image description here


Имитация действий клавиатуры:

Я использую оболочку selenium basic VBA и API для имитации действий на экране, чтобы сохранить их в формате PDF с помощью окна Save As (см. Изображение в самом низу).Особенно используется комбинация клавиш Save через SendKeys.Это работает.Я использовал Spy++, чтобы проверить древовидную структуру окна и проверить имена окон Class и Titles.

. Я использую SendKeys, чтобы автоматизировать открытие диалогового окна Save As для PDF.Затем я опускаю древовидную структуру Окна, чтобы получить указатели на ComboBox, где вводится имя файла, чтобы я мог отправить ему сообщение , то есть имя файла, и кнопку Save, чтобы я мог щелкнуть по ней,Возможно, вам потребуется больше времени, чтобы убедиться, что загрузка прошла правильно.На мой взгляд, это немного глючит, и я надеюсь улучшить.

Структура окна через Spy ++

image

Это довольно надежно.Я использовал Selenium Basic для простоты работы с фреймами и решения проблем с той же политикой происхождения .С IE вы не можете просто взять ссылку src в iframe и с удовольствием перейти на страницу для печати в формате PDF из оригинального дополнения.Я думаю, что вы можете сделать начальный запрос XMLHTTP и получить значение атрибута src, то есть ссылку.Затем передайте эту ссылку src на IE, а затем продолжайте, как показано ниже для частей обработки Windows.

Со временем я мог бы добавить версию IE и взглянуть на более надежный метод, чем явное ожидание.добавление времени для мониторинга загрузки файла перед выходом из экземпляра IE.Вероятно, в соответствии с this (Как указано в одном из ответов: используйте SetWindowsHookEx, чтобы установить WH_SHELL hook и найдите событие HSHELL_WINDOWCREATED.)


Примечания:

  1. Это написано для 64 бит.32 бит удалить PtrSafe.Вы могли бы переключить LongPtr на Long, но я думаю, что он остается совместимым.
  2. Огромное спасибо @ErikvonAsmuth за его огромное терпение в прохождении API со мной.Посмотрите на его превосходный ответ здесь для работы с Windows .

VBA:

Option Explicit

Declare PtrSafe Function SendMessageW Lib "User32" (ByVal hWnd As LongPtr, ByVal wMsg As LongPtr, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr

Declare PtrSafe Function FindWindowExW Lib "User32" (ByVal hWndParent As LongPtr, _
                                                     Optional ByVal hwndChildAfter As LongPtr, Optional ByVal lpszClass As LongPtr, _
                                                     Optional ByVal lpszWindow As LongPtr) As LongPtr

Public Declare PtrSafe Function FindWindowW Lib "User32" (ByVal lpClassName As LongPtr, Optional ByVal lpWindowName As LongPtr) As LongPtr

Public Const WM_SETTEXT = &HC
Public Const BM_CLICK = &HF5

Public Sub GetInfo()
    Dim d As WebDriver, keys As New Selenium.keys
    Const MAX_WAIT_SEC As Long = 5
    Dim t As Date

    Set d = New ChromeDriver
    Const URL = "https://www.recrutement.banque-france.fr/detail-offre/charge-de-recrutement-confirme-h-f-2037343/"
    With d
        .start "Chrome"
        .get URL
        .SwitchToFrame .FindElementById("altiframe")
        .FindElementById("btn-pdf").Click
        .SwitchToNextWindow
        .SendKeys keys.Control, "s"

        Dim str1 As String, cls As String, name As String
        Dim ptrSaveWindow As LongPtr

        str1 = "#32770" & vbNullChar

        t = Timer
        Do
            DoEvents
            ptrSaveWindow = FindWindowW(StrPtr(str1))
            If Timer - t > MAX_WAIT_SEC Then Exit Do
        Loop While ptrSaveWindow = 0

        Dim duiViewWND As LongPtr, directUIHWND As LongPtr
        Dim floatNotifySinkHWND As LongPtr, comboBoxHWND As LongPtr, editHWND As LongPtr


        If Not ptrSaveWindow > 0 Then Exit Sub

        duiViewWND = FindWindowExW(ptrSaveWindow, 0&)

        If Not duiViewWND > 0 Then Exit Sub

        directUIHWND = FindWindowExW(duiViewWND, 0&)

        If Not directUIHWND > 0 Then Exit Sub

        floatNotifySinkHWND = FindWindowExW(directUIHWND, 0&)

        If Not floatNotifySinkHWND > 0 Then Exit Sub

        comboBoxHWND = FindWindowExW(floatNotifySinkHWND, 0&)

        If Not comboBoxHWND > 0 Then Exit Sub

        editHWND = FindWindowExW(comboBoxHWND, 0&)

        If Not editHWND > 0 Then Exit Sub

        Dim msg As String
        msg = "myTest.pdf" & vbNullChar

        SendMessageW editHWND, WM_SETTEXT, 0, StrPtr(msg)

        .SendKeys keys.Control, "s"

        Dim ptrSaveButton As LongPtr
        cls = "Button" & vbNullChar
        name = "&Save" & vbNullChar

        ptrSaveButton = FindWindowExW(ptrSaveWindow, 0, StrPtr(cls), StrPtr(name))

        SendMessageW ptrSaveButton, BM_CLICK, 0, 0

        Application.Wait Now + TimeSerial(0, 0, 4)

        .Quit
    End With
End Sub

Диалоговое окно "Сохранить как":

image


Ссылки:

  1. Shadow DOM
  2. Использование shadow DOM - страницы разработчика Mozilla.

Ссылки на проекты:

  1. Библиотека типов селена

    `

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...