I have PDF documents that are mostly multi page but I only want to print page 1 from each document. The following prints the entire pdf document. I have seen reference to a parameter page=1 but do not seem to get that into the right place in the following:-
Shell ("""" & "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" & """/p /h """ & strPathAndFilename & """")
Can someone please show me how to get the above shell command to just print page 1 of the document. Many thanks.
CodePudding user response:
Using that method it should not in theory be possible, hysterically/historically the Adobe support take on that line is. Unclear if its a breach of EULA to programable aid a Reader user.
...with the free Reader too. Command lines were declared obsolete by Microsoft around 1992...
Thus not a supported Adobe means (just highly popular abuse of Acrobat Reader, including MS commercial printing). There are workarounds.
So to directly answer your question you would need to simply split off page 1 to only send that to Acrobat Reader for blind print the onepage.pdf
There are different methods within Acrobat API via vba to designate only one page is to be converted. but then that's using an expensive method for such a "simple" task.
Thus 3 more common routes to your solution
- command line extract page 1 to use as above.
- use a page addressable pdf to print solution not abusing Reader.
- using VBA or VBS address the default print dialog see
For the easier first 2 options there are many good solutions
- qpdf is FOSS can easily extract 1 page, but may not send to print.
- no good FOSS solution as better ones are naturally commercial
Disclaimer I support SumatraPDF which using just one portable exe (kept as binary is FOSS) can command line print page 1 easily, HOWEVER it will only be print as image and if that's acceptable should serve you well.
CodePudding user response:
Thank you for your response. I could do it using Acrobat Pro but will settle for just the /p parameter and let the user restrict the printed output to the first page.
CodePudding user response:
Please, try the next way. It launch the Adobe Acrobat Reader DC printing window and then finds its control necessary handlers and change/press them according to the printing need.
SendKeys
does mean a reliable method, if you move the mouse and change the focus from the window where it should act:- Copy the next API declarations on top of a standard module (in the declarations area:
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
Then copy the next code in the same module:
Sub PrintPdfSpecificPage() Dim strPathAndFilename As String, strPages As String strPathAndFilename = "C:\Teste VBA Excel\Areas.pdf" strPages = "2" 'the page to be printed number '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
It was a little more complicated than I thought, but worked in my environment...
Please, test it and send some feedback