2018年7月21日 星期六

[VBA] 打開 IE 瀏覽器去操作和列印

辦公室之用,之前寫過如何用 VBA 控制 IE 去將網頁列印成 PDF。但後來遇到在 PDF 軟件上的問題,本應可以將存檔也自動化的步驟失效了,而自己對這工具的需求也減少了,就未有再檢視如何改進它。最近重新拾起辦公室內的一些VBA小工具,看見能發揮效果的感覺真不錯,所以,一於重新嘗試如何改進這個自動化的小工具,先整理之前的方法。

在基本的VBA功能以外,還有兩個 Library 需要先引入:打開 Reference - VBAProject,勾選引入 Microsoft Internet Controls 及 Microsoft HTML Object Library。 下面代碼中的 "ShellWindows" 會得到 Windows 下的 Shell 窗口對象,可以用来操控 Windows的文件夹和 IE 瀏覽器。 "InternetExplorer" 顧名思義可以控制Internet Explorer。 取得某個 IE 的控制後,會需要一點 HTML 語法 和 DOM 結構的認識,之後用 GetElementByID("") GetElementsByTagName("").Item(n)、 GetElementsByClassName("").Item(n) 之類的方法去取得HTML 當中的元素; 甚或如透過 .Style.display 、 .innerText 等屬性去改變網頁的顯示。

(直接印紙的話仍可以做到,只是要轉成 PDF 的話就要看 PDF 軟件的造化..... 可能下周試用 Sendkeys處理 Print Dialog?其實VBA又是否能做到其他語言中的Web Scraping方式呢,大概是未有Library的第 3 方支持?。 另外,因為保守地想給予足夠時間讀取網頁,所以也加入很多等待的時間。)

Sub IEautoprint
    
    Dim shellWins As ShellWindows
    Dim myIE As InternetExplorer
    
    Set shellWins = New ShellWindows
    Set mySheet = ThisWorkbook.Sheets("SecuritySheet")
    Set myIE = CreateObject("InternetExplorer.Application")
    StartRow = 2
    MaxRow = 65536
    
    '打開網址
    myIE.Navigate "http://website.com/fullpath"
    Application.Wait (Now + Time("0:00:01")) 

    ' Optional - 以 Title 標題去選擇視窗
    If shellWins.Count > 0 Then
        For i = shellWins.Count - 1 to 0 Step -1
            If (shellWins.Item(i).LocationName = "Window Title") Then
                Set myIE = shellWins.Item(i)
                myIE.Visible = True
                Exit For
            End If
        Next
    End If
    
    ' Loop Excel mySheet 中的 Input, 重覆:遞交HTML表單、改變頁面顯示、列印 等動作 
    For x = StartRow To MaxRow
        ' 填入HTML的表單及遞交
        Do While .ReadyState <> 4
        Loop ' 等待網頁載入完畢
        myIE.Document.Form(0).Elements("CTYPE").Value = mySheet.Cells(x,1).Value 'Html 表單中的元素
        myIE.Document.Form(0).Elements("CCODE").Value = mySheet.Cells(x,2).Value 'Html 表單中的元素 
        myIE.Document.Form(0).Submit 'Html 表單Submit
 
        ' 改變 HTML中的Style屬性去影響 Expand/Collapse 
        Do While .ReadyState <> 4
        Loop
        On Error Resume Next
        If Not (.Document.getElementbyID("hide105") Is Nothing) Then
            myIE.Document.getElementbyID("hide101").Style.display = "None"
            myIE.Document.getElementbyID("hide105").Style.display = "Block"
        End If
        
        ' 列印
        myIE.ExecWB 6, 2   'ExecWB指令, OLECMDID_PRINT=6, OLECMDEXECOPT_DONTPROMPTUSER=2
        Application.Wait (Now + TimeValue("0:00:02")) ' 等待特定的時間讓檔案建立
        
        Do While .Busy Or .ReadyState <> 4
        Loop
        
        ' 新一格沒有內容時完結 => Done~!!
        If mySheet.Cells(x+1, 1).Value = "" Then
            GoTo LastLine            
        End If
    Next
' 完結時的處理LineDone:
    MsgBox "Done"
    Set shellWins = Nothing
    Set myIE = Nothing
End Sub


ShellWindowshttps://msdn.microsoft.com/en-us/library/windows/desktop/bb773974(v=vs.85).aspx
InternetExplorerhttps://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa752084(v=vs.85)
ExecWB 的 IOleCommandTarget interfacehttps://docs.microsoft.com/en-us/windows/desktop/api/docobj/ne-docobj-olecmdid
OLECMDIDhttps://docs.microsoft.com/en-us/windows/desktop/api/docobj/ne-docobj-olecmdid

沒有留言:

張貼留言