I had a question asked of me relating to how one could change the viewed page of an actively open PDF through VBA and that got me curious.
The concept is pretty straightforward, in the sense, that you need to identify the textbox in Adobe that you need to update once you know that, you can use APIs to locate it, update it’s value, …
I’m too stubborn to let it go, so last night I figured it out. The heart of the process is a very simple procedure
'---------------------------------------------------------------------------------------
' Procedure : ChangePDFPage
' Author : Daniel Pineault, CARDA Consultants Inc.
' Website : http://www.cardaconsultants.com
' Purpose : Change the page of a Adobe Reader PDF
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
' (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Uses Late Binding, so none required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sFile : Fully qualified path, filename & extension of the PDF file
' lPage : Page number to view
'
' Usage:
' ~~~~~~
' Call ChangePDFPage("C:\Users\Daniel\Documents\AccessTechniques.pdf", 65)
'
' Revision History:
' Rev Date(yyyy/mm/dd) Description
' **************************************************************************************
' 1 2018-11-25 Initial Release
'---------------------------------------------------------------------------------------
Public Function ChangePDFPage(sFile As String, lPage As Long)
Dim hwndParent&
Dim hwndChild&
Dim sFileName As String
On Error GoTo Error_Handler
sFileName = Right(sFile, Len(sFile) - InStrRev(sFile, "\")) 'Get just the filename from the full path/filename/ext
hwndParent = FindChildWindow(FnFindWindowLike("*" & sFileName & "* - Adobe*"), "AVL_AVView", "AVTopBarView", True)
If hwndParent = 0 Then
'This means that we can't find an instance of Adobe with the specified File, so we could use the traditional approach for the first time
Call OpenPDF(sFile, lPage)
Else
hwndChild = GetWindow(hwndParent, GW_CHILD) 'Find the 1st Child window handle - Zoom %
hwndChild = GetWindow(hwndChild, GW_HWNDNEXT) 'Find the next window handle - Page No.
'Can use PostMessage instead if wanted
Call SendMessage(hwndChild, WM_SETTEXT, 0&, lPage) 'Enter our page number into the Adobe Reader Page number textbox
Call SendMessage(hwndChild, WM_KEYDOWN, VK_RETURN, 0) 'Submit an Enter key to actually switch to the input page
Call SendMessage(hwndChild, WM_KEYUP, VK_RETURN, 0)
End If
Error_Handler_Exit:
On Error Resume Next
Exit Function
Error_Handler:
MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Source: ChangePDFPage" & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End Function
but around that are all the APIs and other procedures. So look over the demo db provided below for the complete solution.
The other beauty about this code is that although my sample is in Access (my workhorse of choice), it isn’t Access specific, so you can port it into whatever VBA application you need it in (Excel, PowerPoint, Word, …).
I should also mention the above was specifically developed for Adobe Acrobat Reader DC and hasn’t been tested on any other versions.
Disclaimer/Notes:
If you do not have Microsoft Access, simply download and install the freely available runtime version (this permits running MS Access databases, but not modifying their design):Microsoft Access 2010 Runtime
Microsoft Access 2013 Runtime
Microsoft Access 2016 Runtime
Microsoft 365 Access Runtime
In no event will Devhut.net or CARDA Consultants Inc. be liable to the client/end-user or any third party for any damages, including any lost profits, lost savings or other incidental, consequential or special damages arising out of the operation of or inability to operate the software which CARDA Consultants Inc. has provided, even if CARDA Consultants Inc. has been advised of the possibility of such damages.
Download a Demo Database
Feel free to download a 100% unlocked demo copy by using the link provided below:
Download “VBA - Switch Adobe Reader Page” PDF.zip – Downloaded 6668 times – 47.78 KBVersion History
(2018-11-25) Initial Release
V1.0000 (2018-11-26) Glitch identifying main Adobe parent window on first call fixed
thanks, you are a guru
Hi Daniel,
Your code was extremely helpful and it saves me lots of time. I got one issue though..when i ran the code the pdf page number in the pdf text box does change but the actual page remain the same. Wondering what could be the cause. I am using a userform input to change the page. I have used it with your openpdf page code and it works fine. but when i switch i noticed the above problem
I’m not sure what is going on, as it works for me. I will try and make some time to look at the code again.
Any chance you can tell me what OS, bitness and build you are running, what version of Adobe Reader you are running, what version, bitness and build of Access you are running to run the code. Thank you.
I am using windows 10. adobe acrobat reader Dc 32, acroRd32. i am running the code on Excel 2016.
Read in your instruction that it can be ported to work in excel. Your openpdf has really been a life saver.
It saves time and worked really well. I cant than you enough. Thank you for your thoughtful ideas and codes.
Thank you.
Using your OpenPDF with adaptions. I have an index in Excel to article names in quarterly publications for a local history society (genealogy) and I get my document name and page from the spreadsheet. Works beautifully and will demo it to users tomorrow – I’m all prepared to tell the users to close Adobe before selecting the next page to view (because otherwise they’ll only see the unchanged image – I.e. same document, same page)
Just now I spotted your ChangePDFPAGE code and I will test it in Excel ASAP – this could be the solution! Looking forward to testing this!
Your code is superb and very well documented – thanks mate!
I get an error on “FnFindWindowLike”. Sub or function not defined
Did you download and try the sample? All the code is there including the module/function.
Too much stuff going on trying to port it to 64 bit (I figured out I needed the download attached here).