GUI scripting of print dialog

I don’t know if any of you have seen the posts by CalvinFold, but he and I have been trying to find a way to get Illustrator CS to print to a true postscript file. Scripting CS itself just doesn’t seem to update any settings for the final print so he’s trying gui scripting of the print command. The script following seems to work basically, but I have found out that the printer referenced is the printer last used. Eventhough you can watch the buttons being clicked in the print dialog, they seem to have no effect. I decided to get the properties of the print window and two of the properties (enabled and selected) report missing values. Through the script I’m seemingly able to set these to true, but when checking the properties again they still report missing values. If these can be set to true would it actually make any difference on whether or not scripted clicks were registered? Am I barking up a wrong tree? Can you hear the voices too?

set fileLoc to "Macintosh HD:Users:uName:Desktop:theTest2:" as Unicode text

tell application "Illustrator CS"
	activate
	set thisDoc to current document
	set n to name of thisDoc
	set h to height of thisDoc
	set w to width of thisDoc
	set fileName to n & ".ps"
	tell application "System Events"
		tell process "Illustrator CS"
			keystroke "p" using command down
			set frontmost to true
			tell window "Print"
				set properties to {enabled:true, selected:true}
				--get properties of pop up button 4
				click pop up button 4
				click menu item "Adobe PDF" of menu 1 of pop up button 4
				--delay 2
				click pop up button 5
				click menu item "Adobe PostScript® File" of menu 1 of pop up button 5
				--delay 2
				click pop up button 3
				click menu item "Custom" of menu 1 of pop up button 3
				--delay 2
				click button "Printer..."
				delay 2
				set properties to {enabled:true, selected:true}
				--click button "Done"
				--keystroke return
			end tell
			get properties of window "Print"
			(*keystroke "p" using command down
			delay 2
			keystroke return
			get properties of text field 1 of front window --"Print to File"
			set value of text field 1 of front window to fileName
			keystroke return*)
		end tell
	end tell
end tell

I know that this is Illustrator oriented, but this may be a more wide spread issue, I don’t know. If you can shed any light it would be appreciated.

PreTech

You already know I can hear the voices. They keep reminding me AppleScript is supposed to be easy, natural-language programming.

Uh, yeah.

Anybody but me sometimes think we’re only a few steps short of just going back to Perl or C++ and being done with it?

I mean, I scoured Adobe’s JavaScript guides and aside from syntax, scripting Adobe apps in AppleScript is almost identical.

:stuck_out_tongue:

(My untold thanks to PreTech for wading through this with me…)

Hello,

I’ve had an AppleScript handler I’ve used for some time to save a document as a pdf using GUI scripting and the Save as PDF… command in the standard macOS print dialog.

I’ve recently noticed that there has been some changes to that dialog in Big Sur which has meant I have needed to update my script.

I assume these changes were introduced in macOS 11.0, but I’m not sure. I’m running macOS 11.2 and don’t have any test machines running earlier versions of Big Sur. I know that the print dialog was different in Mojave, which was the last OS I used (I skipped Catalina).

I’d like to know what version introduced the change so I can ensure that it will work properly on other systems. I use this handler as part of other scripts which I distribute to a number of people running various versions of macOS.

Does anybody have any more details or would be willing and able to test on earlier versions of Big Sur?

Basically the issue is that, in 11.2, the macOS print dialog, which is a sheet of a window, contains only one UI element, namely a splitter group. That splitter group then contains all the UI elements which were, on earlier versions of macOS, direct children of the print dialog sheet. So in effect the majority of the UI elements (buttons, menu items, etc) of the print dialog are now grandchildren of the print dialog sheet rather than immediate children.

So if you’re running a version of macOS earlier than 11.2 and later than Mojave, could you please bring up the print dialog and test whether its UI elements are contained within one splitter group or not, and let me know? You should be Abel to do that by running something along the following lines:


set theApp to "" -- the name of the app in which the print dialog has been triggered

tell application "System Events"
tell application process theApp
every UI element of sheet 1 of window 1 -- where sheet 1 of window 1 should be a reference to the print dialog
end tell
end tell

In case it helps understand, my handler is as follows:


on printPDFOfFrontDocument of theApp to theLocation : missing value given fileName:theFileName : "untitled"
    -- saves the frontmost document to PDF
    -- the location must be in POSIX format (tip: use POSIX path of to convert)
    -- #todo: should test whether theLocation given is in POSIX format and, if it's not, should convert it
    -- theFileName should not include an extension as one will be added
    
    try
        set theFile to missing value -- this will be returned by the handler and, if successful, will be a file object of «class furl»
        
        if theLocation is missing value then set theLocation to POSIX path of (path to desktop folder)
        
        -- first ensure the file name is unique
        set theFileName to uniqueFileName for theLocation given fileName:theFileName, extension:".pdf"
        
        repeat -- until user allows accessibility access
            try
                activate application theApp
                
                -- click the print button (sometimes print shortcut (command-p) doesn't work, particularly it seems in Numbers)
                -- send the commands through System Events for GUI scripting
                tell application "System Events" to tell application process theApp
                    if exists menu item "Print Without Preview…" of menu "File" of menu bar item "File" of menu bar 1 then
                        click menu item "Print Without Preview…" of menu "File" of menu bar item "File" of menu bar 1
                        set thereIsAPrintPreviewWindow to false

                    else
                        click menu item "Print…" of menu "File" of menu bar item "File" of menu bar 1
                        set thereIsAPrintPreviewWindow to true
                    end if
                end tell
                exit repeat
            on error msg
                activate
                display dialog "The most likely reason for this is because you have not granted accessibility permission to " & name of me & ". Please go to System preferences > Security and Privacy > Accesssibility and ensure that " & name of me & " is checked." & return & return & "The other reason might be that your system language is something other than English." & return & return & msg with title "Unable to find the “Print…” button in the file menu" buttons {"Give Up", "Try Again"} default button 2 with icon caution
                if button returned of result is "Give Up" then error "Unable to print because the application was not given accessibility permissions, or because the system language is not English." & return & return & msg
            end try
        end repeat
        
        -- back to System Events
        tell application "System Events" to tell application process theApp
            -- in Numbers, there is an internal print dialog before the system print dialog appears
            if theApp is "Numbers" and thereIsAPrintPreviewWindow then -- wait for the Print Setup formatter to appear
                with timeout of 15 seconds
                    repeat until (button "Print…" of group 1 of window 1) exists
                    end repeat
                    click button "Print…" of group 1 of window 1
                end timeout
            end if -- ap is Numbers
            
            -- wait for the print dialog to appear
            with timeout of 60 seconds
                repeat until (sheet 1 of window 1) exists
                end repeat
            end timeout
            
            -- in Big Sur, the print dialog only contains one UI element, namely a splitter group
            -- and that splitter group contains the other UI elements
-- not sure what version of Big Sur it was introduced in, but assuming 11.0/10.16 for now
            if macOSIsNewerThan("10.16")) then
                set PDFButton to first menu button of splitter group 1 of sheet 1 of window 1
            else
                set PDFButton to first menu button of sheet 1 of window 1
            end if
            click PDFButton
            click menu item 2 of menu 1 of PDFButton -- the save to PDF button
            
            -- wait for the save sheet to appear
            with timeout of 60 seconds
                repeat until sheet 1 of sheet 1 of window 1 exists
                end repeat
            end timeout
            delay 0.5
            tell sheet 1 of sheet 1 of window 1
                
                -- set the file name
                if theFileName is not "" then set value of text field 1 to theFileName
                
                delay 0.2
                
                -- set the save in location
                keystroke "g" using {command down, shift down}
                
                with timeout of 60 seconds
                    repeat until sheet 1 exists
                    end repeat
                end timeout
                
                tell sheet 1
                    -- In macOS Sierra, the location field is a combo box. In earlier versions, it was a text field.
                    if macOSIsNewerThan("10.12") of OBUtility then
                        set the value of combo box 1 to theLocation
                    else
                        set the value of text field 1 to theLocation
                    end if
                    click button "Go" -- to set the location
                end tell -- go to sheet
                
                -- Prior to High Sierra, the "Save" button was button 1. In High Sierra, it's no longer button 1, but it is the last UI element
                if macOSIsNewerThan("10.13") of OBUtility then
                    click the last UI element -- to save
                    -- note: in Mohave 10.14 and newer, it's also button "Save", but it's also the last button so I have not updated the script
                else
                    click button 1 -- to save
                end if
            end tell -- save dialog
            
            if theApp is "Numbers" and thereIsAPrintPreviewWindow then -- dismiss the Print Setup formatter
                try -- in case the save dialog doesn't dismiss in time
                    with timeout of 15 seconds
                        -- wait for the save dialog window to be dismissed
                        repeat until (scroll area "Print Setup formatter" of group 1 of window 1) exists
                        end repeat
                    end timeout
                    if (button "Done" of group 1 of window 1) exists then click button "Done" of group 1 of window 1 -- to dismiss the print setup formatter
                    -- if there's a timeout error, the handler simply terminates without dismissing the Print Setup formatter – it's not worth worrying about
                end try
            end if
        end tell -- system events

        try
            set thisFilePath to ((theLocation as text) & theFileName & ".pdf")
            set theFile to POSIX file thisFilePath
            delay 1
            tell application "Finder" to open theFile
        end try

        try
display notification "PDF saved in " & (theLocation as text) with title "PDF Saved" with subtitle theFileName with sound "Glass"
        end try

        set theFile to theFile as alias
        return a reference to file (theFile as text)
    on error
        return missing value
    end try
    -- returns a reference to the newly saved pdf file or missing value on error
end printPDFOfFrontDocument

on macOSVersion()
    set theInfo to system info
    set theVersion to system version of theInfo
    -- when running this script in ScriptDebugger system info still reports macOS 11 Big Sur as version 10.16
    -- but when running it from KM (I think) it reports it as 11.x
    -- so we'll no longer extract the second part of the version
    return theVersion
end macOSVersion

on macOSIsNewerThan(specifiedVersion)
    set usersVersion to macOSVersion()
    considering numeric strings
        return usersVersion is greater than or equal to specifiedVersion
    end considering
end macOSIsNewerThan

on uniqueFileName for thisPath as text given fileName:(theFileName as text), extension:theExtension as text
    (*
thisPath should be in POSIX format
should check and convert to POSIX format if not already
*)
    set i to 1
    set theModifier to ""
    repeat
        set theTestFile to POSIX file (thisPath & theFileName & theModifier & theExtension)
        tell application "Finder"
            if theTestFile exists then
                set theModifier to " v" & i
            else
                exit repeat
            end if
        end tell -- Finder
        set i to i + 1
    end repeat
    set theFileName to (theFileName & theModifier) as text -- otherwise it seems that it might be a list 
    return theFileName
end uniqueFileName

Thanks for any help you can offer.