簡體   English   中英

使用 shell 從 VBA 打印一頁 pdf 文檔

[英]Print one page of pdf document from VBA using shell

我有 PDF 文檔,這些文檔大多是多頁的,但我只想從每個文檔中打印第 1 頁。 下面打印整個 pdf 文檔。 我已經看到對參數 page=1 的引用,但似乎沒有將其放入以下正確的位置:-

Shell ("""" & "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" & """/p /h """ & strPathAndFilename & """")

有人可以告訴我如何獲得上述 shell 命令來打印文檔的第 1 頁。 非常感謝。

使用這種方法,理論上應該是不可能的,歇斯底里/歷史上 Adobe 支持在這條線上采取的做法是。 不清楚它是否違反 EULA 對 Reader 用戶的可編程幫助。

...也有免費的閱讀器。 命令行在 1992 年左右被微軟宣布過時......

因此不支持 Adobe 方法(只是 Acrobat Reader 的流行濫用,包括 MS 商業印刷)。 有解決方法。

因此,要直接回答您的問題,您只需將第 1 頁拆分為僅將其發送到 Acrobat Reader 以盲打印onepage.pdf

Acrobat API 通過 vba 有不同的方法來指定只轉換一頁。 但那是使用昂貴的方法來完成這樣一個“簡單”的任務。

因此,您的解決方案有 3 條更常見的途徑

  1. 命令行提取第 1 頁以按上述方式使用。
  2. 使用可尋址的頁面 pdf 打印不濫用閱讀器的解決方案。
  3. using VBA or VBS address the default print dialog see https://stackoverflow.com/a/63279528/10802527 "Works for me" (note the different output location with only one page) attribution/kudos to @freesoftwareservers
wscript  "pdf_print_sendkeys.vbs" "C:\Users\WDAGUtilityAccount\Desktop\SandBox\apps\PDF\Adobe\Reader\AcroRd32.exe" "C:\test.pdf" "1"

在此處輸入圖像描述

對於更簡單的前 2 個選項,有許多好的解決方案

  1. qpdf 是 FOSS 可以輕松提取 1 頁,但可能無法發送打印。
  2. 沒有好的 FOSS 解決方案,因為更好的解決方案自然是商業化的

免責聲明我支持 SumatraPDF,它只使用一個便攜式 exe(保留為二進制文件是 FOSS)可以輕松地在命令行打印第 1 頁,但是它只會打印為圖像,如果可以接受的話應該會很好地為您服務。

謝謝您的答復。 我可以使用 Acrobat Pro 來做到這一點,但只接受 /p 參數並讓用戶將打印的 output 限制在第一頁。

請嘗試下一個方法。 它啟動 Adobe Acrobat Reader DC 打印 window 然后找到它的控制必要的處理程序並根據打印需要更改/按下它們。 SendKeys確實意味着一種可靠的方法,如果您移動鼠標並將焦點從 window 更改它應該起作用的位置:

  1. 將下一個 API 聲明復制到標准模塊頂部(在聲明區域中:
 Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
 Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hwnd1 As LongPtr, _
        ByVal hwnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr
 Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, _
        ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As Long
 Private Declare PtrSafe Function GetNextWindow Lib "user32.dll" Alias "GetWindow" (ByVal hwnd As LongPtr, _
        ByVal wFlag As Long) As LongPtr

然后復制同一模塊中的下一個代碼:

Sub PrintPdfSpecificPage()
    Dim strPathAndFilename As String, strPages As String
    
    strPathAndFilename = "your pdf file full name" 'use here the real full name
    strPages = "2" 'the page to be printed number
                   'it may be "1,2" or "2-4"...
    
    'launch the Adobe Acrobat DC printing window:
    Shell ("""" & "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" & """/p """ & strPathAndFilename & """")
    
    'wait for the window to expose its handle and continue the process of the necessary controls identification (their handles):
     Dim prHwnd As LongPtr, grBoxHw1 As LongPtr, grNext4 As LongPtr, grNext20 As LongPtr
     Dim pgHwnd As LongPtr, pgNHwnd As LongPtr, printHwnd As LongPtr, nrPag As String
     Const BM_CLICK = &HF5, WM_SETTEXT = &HC
     Const WM_LBUTTON_DOWN = &H201, WM_LBUTTON_UP = &H202
     
     Do While prHwnd = 0
        prHwnd = FindWindow("#32770", "Print")
        DoEvents
     Loop
     Application.Wait Now + TimeValue("00:00:02") 'wait two seconds for the whole window to expose its controls handles
      grBoxHw1 = FindWindowEx(prHwnd, 0, "GroupBox", vbNullString)     'the first child GroupBox window
        grNext4 = getNextChildX(grBoxHw1, 3, "GroupBox"): Hex (grNext4) 'find the fourth control handle
         pgHwnd = FindWindowEx(grNext4, 0, "Button", "Pa&ges")                'find the radio button accepting pages interval handler
         
          SendMessage pgHwnd, WM_LBUTTON_DOWN, 0&, 0&
          SendMessage pgHwnd, BM_CLICK, 0&, ByVal 0&                               'check the radio button
          
          pgNHwnd = FindWindowEx(grNext4, 0, "RICHEDIT50W", vbNullString) 'find the window where the page number to be dropped
             
         SendMessage pgNHwnd, WM_LBUTTON_DOWN, ByVal 0&, 0& 'without this lines, the page number is changed, but the changing event is not triggered...
         SendMessage pgNHwnd, WM_LBUTTON_UP, ByVal 0&, 0&
             
           SendMessage pgNHwnd, WM_SETTEXT, 0&, ByVal strPages  'place the page to be printed number
             
         SendMessage pgNHwnd, WM_LBUTTON_DOWN, ByVal 0&, 0&
         SendMessage pgNHwnd, WM_LBUTTON_UP, ByVal 0&, 0&
             
          grNext20 = getNextChildX(grBoxHw1, 19, "GroupBox"): Debug.Print 'find the GroupBox where the Print button exists
            printHwnd = FindWindowEx(grNext20, 0&, "Button", "Print")            'find the Print button handle
              
              SendMessage printHwnd, BM_CLICK, 0&, ByVal 0&                          'press/click the Print button:
              
        'close the Acrobat main Window:
        Dim acrobatHwnd As LongPtr
        Const WM_SYSCOMMAND = &H112, SC_CLOSE = &HF060
        
         'wait for the printing Window to be closed, to let Acrobat expose its main window handle:
         Do While acrobatHwnd = 0
                    acrobatHwnd = FindWindow("AcrobatSDIWindow", "Adobe Acrobat Reader DC (32-bit)")
                    DoEvents
        Loop

        SendMessage acrobatHwnd, &H10, 0&, 0& 'close the main Acrobat Reader window
End Sub

Function getNextChildX(parentHwnd As LongPtr, x As Long, strClass As String) As LongPtr
       Dim nextChild As LongPtr, i As Long
       nextChild = FindWindowEx(parentHwnd, 0&, strClass, vbNullString)
        For i = 1 To x
             nextChild = GetNextWindow(nextChild, 2)
        Next i
        getNextChildX = nextChild
End Function

它比我想象的要復雜一些,但在我的環境中工作......

請測試它並發送一些反饋

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM