#! ''' Open and close PDF documents and restore viewing state in Acrobat Acrobat on Windows (using OLE automation) Author: Matthias Stevens (mstevens@vub.ac.be) Based on acroctl.py by Chris Unkel (cunkel@stanford.edu): http://suif.stanford.edu/~cunkel/acroctl.html ''' import win32com.client from os.path import basename, normcase, abspath __all__ = ["findAvFor", "closeAndReturnCurrentPage", "saveToStateFile", "openPDF", "openAtPage", "restoreFromStateFile"] '''State string format: ViewMode|PageNum|ZoomType|Zoom|Aperture.left|Aperture.top''' def findAvFor(doc): ''' Close Acrobat windows with doc open. If PDF file is open, return page number of an (arbitrary) view; else None. Note: open files are compared only by the filename, NOT including the directory. For example, pdfClose("c:\\some.pdf") would close both c:\\spam\\some.pdf and c:\\eggs.pdf. It seems that only the filename portion is available from the Acrobat OLE interface? ''' pdf = normcase(basename(doc)) app = win32com.client.Dispatch("AcroExch.App") avDocs = [app.GetAVDoc(i) for i in range(app.getNumAVDocs())] for av in avDocs: if normcase(av.GetPDDoc().GetFileName()) == pdf: return av return None def closeAndReturnCurrentPage(doc, av): if av is not None: page = str(av.GetAVPageView().GetPageNum()) av.Close(0) #0 = ask user to save changes if any print("Closed " + doc + " in Acrobat") return page def saveToStateFile(doc, av): if av is not None: state = "" state += str(av.GetViewMode()) + "|" view = av.GetAVPageView() state += str(view.GetPageNum()) + "|" state += str(view.GetZoomType()) + "|" state += str(view.GetZoom()) + "|" rect = view.GetAperture() state += str(rect.left) + "|" state += str(rect.top) pdf = basename(doc) statefilename = pdf[0:pdf.rfind(".")] + ".acrobatstate" try: with open(abspath(statefilename), mode='w', encoding='utf-8') as statefile: statefile.write(state) statefile.close() except Exception as ex: print("Could not save to acrobatstate file: ", ex) return print("Acrobat state for " + doc + " saved to acrobatstate file.") def openPDF(doc): #app = win32com.client.Dispatch("AcroExch.App") #app.Show() av = win32com.client.Dispatch("AcroExch.AVDoc") av.Open(abspath(doc), doc) #av.Open(abspath(doc), doc) av.BringToFront() print("Opened " + doc + " in Acrobat") return av def openAtPage(doc, page): '''Open an Acrobat window with doc open to page (zero indexed).''' av = openPDF(doc) view = av.GetAVPageView() view.Goto(page) print("Jumped to page " + str(page)) def restoreFromStateFile(doc, av): pdf = basename(doc) statefilename = pdf[0:pdf.rfind(".")] + ".acrobatstate" try: statefile = open(abspath(statefilename), mode='r', encoding='utf-8') state = statefile.read() statefile.close() except: print("No acrobatstate file found.") return print("acrobatstate file found, restoring state...") parts = state.split("|") av.SetViewMode(int(parts[0])) view = av.GetAVPageView() view.Goto(int(parts[1])) view.ZoomTo(int(parts[2]), int(parts[3])) view.ScrollTo(int(parts[4]), int(parts[5])) ################################################################ ## MAIN if __name__ == "__main__": import sys, optparse parser = optparse.OptionParser(usage="usage: %prog [options] PDFFILE") def noAction(ignore, ignore2): sys.stderr.write("You must specify an action (open, close, or restore.)\n") parser.print_help() sys.exit(1) def closeAction(doc, ignore): av = findAvFor(doc) if av is not None: page = closeAndReturnCurrentPage(doc, av) if not options.quiet: if page is None: print("-1") else: print(page) else: print(doc + " is not open in Acrobat") def saveStateAndCloseAction(doc, ignore): av = findAvFor(doc) if av is not None: saveToStateFile(doc, av) closeAndReturnCurrentPage(doc, av) else: print(doc + " is not open in Acrobat.") def openAction(doc, page): if page >= 0: openAtPage(doc, page) else: openPDF(doc) def openAndRestoreStateAction(doc, ignore): av = openPDF(doc) if av is not None: restoreFromStateFile(doc, av) else: print("Could not restore state.") parser.set_defaults(todo=noAction, page=-1, quiet=False, debug=False) parser.add_option("-c", "--close", action="store_const", dest="todo", const=closeAction, help="close all views of PDFFILE") parser.add_option("-s", "--saveclose", action="store_const", dest="todo", const=saveStateAndCloseAction, help="close all views of PDFFILE and save state to acrobatstate file") parser.add_option("-o", "--open", action="store_const", dest="todo", const=openAction, help="open view of PDFFILE; and goto PAGE if specified and nonnegative") parser.add_option("-r", "--openrestore", action="store_const", dest="todo", const=openAndRestoreStateAction, help="open PDFFILE and restore view using saved acrobatstate file (if one exists, otherwise PDFFILE is opened on first page)") parser.add_option("-p", "--page", action="store", dest="page", type="int", metavar="PAGE", help="open to PAGE") parser.add_option("-q", "--quiet", action="store_true", dest="quiet", help="don't print page PDFFILE was open to") parser.add_option("--debug", action="store_true", dest="debug") (options, args) = parser.parse_args() if len(args) != 1: sys.stderr.write("You must specify a filename.") parser.print_help() sys.exit(1) try: options.todo(args[0], options.page) except: if options.debug: raise sys.exit(1) sys.exit(0)