I have a problem with an applescript on an iMac I am upgrading at work, this is below, it stops at:
error number -1719 from text field 1 of window 1 of process "QuarkXPress"
The full script I am trying to run:
try
tell application "FileMaker Pro Advanced"
--tell database "artdb_Client"
set theRecord to current record of database "artdb_Client"
tell theRecord
set theCustomer to item 4
set theCustomerName to item 5
set theFileName to item 2
end tell
--end tell
end tell
tell application "QuarkXPress"
activate
display dialog ¬
theCustomer & " - " & theCustomerName default answer theCustomer buttons {"Cancel", "OK"} default button 2 ¬
with title "Enter the Customer Code for Job"
(*
display dialog ¬
theCustomer & " - " & theCustomerName & ¬
"?" with title "Export PDF for Customer"
*)
end tell
set theFolder to "Data HD:Proofs:" & theCustomer
set theFolderOfPosix to "/volumes/Data HD/Proofs/" & theCustomer
set this_item to theFolder & ":" & theFileName & ".pdf"
set theProofsDir to "Data HD:Proofs:" as alias
tell application "System Events"
tell process "QuarkXPress"
tell menu bar 1
tell menu bar item "File"
tell menu "File"
tell menu item "Export"
tell menu "Export"
click menu item "Layout as PDF..."
delay 1
end tell
end tell
end tell
end tell
end tell
end tell
repeat 5 times
tell process "QuarkXPress"
if window "Export as PDF" exists then
keystroke "G" using command down
set value of text field 1 of window 1 to theFolderOfPosix & "/"
keystroke return
click button "Go" of window 1
exit repeat
else
delay 1
end if
end tell
delay 1
end repeat
end tell
end try
I finally got it to work, where the script was stopping (without putting the called data in):
set value of text field 1 of window 1 to theFolderOfPosix & "/"
I changed it to:
set value of text field 1 of sheet 1 of window 2 to theFolderOfPosix & "/"
Thanks to UI Browser for showing me the "sheet" field I was missing, it doesn't look right but it does the job so that's all that matters I guess.
You need to provision YOUR.app for UI Scripting (Accessibility support) in the Security pane of the System Preferences. There is a good writeup on how that works here: AppleScript System Notifications Support (advanced). That is, it describes the steps necessary to make ui scripting work.
HTH
Related
I am writing a script to go to the NYT website on Corona, get the US data, extract numbers (total, death), and to send me a notification. I am close, but when I extract numbers and display them, they are put together (ie 700021 instead of 7000,21). My question is:
How do I extract the numbers so that they are delineated?
Here is the code:
set theURL to "https://www.nytimes.com/interactive/2020/world/coronavirus-maps.html?action=click&pgtype=Article&state=default&module=styln-coronavirus&variant=show®ion=TOP_BANNER&context=storyline_menu"
tell application "Safari" to make new document with properties {URL:theURL}
tell application "System Events"
repeat until exists (UI elements of groups of toolbar 1 of window 1 of application process "Safari" whose name = "Reload this page")
delay 0.5
end repeat
end tell
to getInputByClass(theClass, num)
tell application "Safari"
set input to do JavaScript "
document.getElementsByClassName('" & theClass & "')[" & num & "].innerText;" in document 1
end tell
return input
end getInputByClass
set myVar to getInputByClass("g-body ", 5)
on returnNumbersInString(inputString)
set s to quoted form of inputString
do shell script "sed s/[a-zA-Z\\']//g <<< " & s
set dx to the result
set numlist to {}
repeat with i from 1 to count of words in dx
set this_item to word i of dx
try
set this_item to this_item as number
set the end of numlist to this_item
end try
end repeat
return numlist
end returnNumbersInString
set theNums to returnNumbersInString(myVar) as text
display notification "COVID-19 UPDATE" subtitle theNums sound name "glass"
tell application "Safari"
close its front window
end tell
You are getting a list of numbers from the returnNumbersInString handler, but just coercing the list to text doesn't normally provide any kind of formatting. One solution would be to use text item delimiters to specify the text to use when joining the list items. For example, when converting to text for the notification you could do something like:
set tempTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to ", "
set theNums to returnNumbersInString(myVar) as text
set AppleScript's text item delimiters to tempTID
Similar to your other question I helped you with, the target data is already in a table and as such I'd use the table data to get the information as its structure layout is not likely to change where target 'g-body ' of 5 may not always be the United States.
I get my data a little different way:
set theURL to "https://www.nytimes.com/interactive/2020/world/coronavirus-maps.html?action=click&pgtype=Article&state=default&module=styln-coronavirus&variant=show®ion=TOP_BANNER&context=storyline_menu"
tell application "Safari" to make new document with properties {URL:theURL}
tell application "System Events"
repeat until exists ¬
(UI elements of groups of toolbar 1 of window 1 of ¬
application process "Safari" whose name = "Reload this page")
delay 0.5
end repeat
end tell
tell application "Safari" to tell document 1 to set CountriesTable to ¬
do JavaScript "document.getElementsByClassName('svelte-f9sygj')[0].innerText;"
tell application "Safari" to close its front window
set awkCommand to ¬
"awk '/United States/{print $3,\"Cases &\",$4,\"Deaths\"}'"
set notificationMessage to ¬
do shell script awkCommand & "<<<" & CountriesTable's quoted form
display notification notificationMessage subtitle "US COVID-19 UPDATE" sound name "glass"
NOTE: The code used to determine when the page in Safari has finished loading works in macOS Mojave and later, however, for macOS High Sierra and some earlier versions, add the words buttons of in front of UI elements ... in the repeat until exists ¬ ... code.
Note: The example AppleScript code is just that and does not contain any error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors. Additionally, the use of the delay command may be necessary between events where appropriate, e.g. delay 0.5, with the value of the delay set appropriately.
Ability to export all Notes in macOS Notes.app as PDFs.
execution error: Notes got an error: AppleEvent handler failed. (-10000)
Multiple scripts, latest below.
tell application "Notes"
activate
repeat with theFolder in every folder
repeat with theNote in every note of theFolder
tell application "System Events"
tell process "Notes"
set dockPrefs to dock preferences
set appearancePrefs to appearance preferences
delay 1
display dialog "Foo"
tell menu bar 1 of process "Notes"
click menu bar item "File"
click menu item "Export as PDF..." of menu "File" of menu bar of process "Notes"
end tell
click button "Save" of sheet 1 of window "Notes" of process "Notes"
delay 1
key code 125
end tell
end tell
end repeat
end repeat
end tell
execution error: Notes got an error: AppleEvent handler failed. (-10000)
There are a few problems in there:
You are already targeting the Notes process, so including that in
the click statements is adding another process target - use one or the other, but if you are
doing a lot of menu clicks you might look at using a general
purpose handler;
The export menu item uses an ellipse (a single character), not three
periods;
By placing a display dialog statement in the System Events tell statement, you are moving the focus away from the application.
Also note that the text field is selected and the save button is the default in the sheet, so you can use keystrokes instead of trying to click UI elements. A cleaned up example (tested in Mojave) would look something like:
tell application "Notes"
launch -- seems to work better than 'activate'
repeat with aFolder in folders
repeat with aNote in notes of aFolder
set noteName to (name of aNote)
try -- keep the name a reasonable length
set noteName to text 1 thru 20 of noteName
end try
tell (current date) to set timeStamp to text 2 thru -1 of (get (1000000 + (its hours) * 10000 + (its minutes) * 100 + (its seconds)) as text) -- hhmmss
tell application "System Events"
#display dialog noteName -- testing?
tell process "Notes"
set frontmost to true -- retarget the Notes app
delay 0.5
click menu item "Export as PDF…" of menu "File" of menu bar item "File" of menu bar 1
repeat until exists sheet 1 of window 1 -- wait for the sheet
delay 0.02
end repeat
end tell
keystroke noteName & "_" & timeStamp -- update the name, trying to avoid duplicates
delay 0.5
keystroke return -- dismiss the sheet
delay 0.5
key code 125
end tell
end repeat
end repeat
end tell
Writing an AppleScript to open Image Capture and click the Import All button.
tell application "Image Capture"
activate
tell application "System Events"
tell process "Image Capture"
click button "Import All" of group 1 of splitter group 1 of window 1
end tell
end tell
end tell
Image Capture opens but the script throws an error message saying it couldn't find the button "Import All".
Have followed advice on other threads on how to check the location in Accessibility Inspector and how to translate that to AppleScript instructions.
What's missing?
To get the button and group numbers, you have 2 ways: use the utility aplication provided by Apple in the developper toolkit "Accessibility Inspector" or use small scripts to find the number yourselves.
I prefer using script method. it is a bit longer sometime, but it always works. Just write a script with instruction get UI elements. Here is a small example of such script:
-- return lis of UI elements of active application and paste result in Excel
property tab : ASCII character 9
global T
-- to find last active application
tell application "System Events"
set frontmostProcess to first process where it is frontmost
set visible of frontmostProcess to false
repeat while (frontmostProcess is frontmost)
delay 0.2
end repeat
set secondFrontmost to name of first process where it is frontmost
set frontmost of frontmostProcess to true
end tell
set ActifProcess to secondFrontmost as text
tell application ActifProcess to activate -- set active the last actived application
delay 1
-- recursive loop to list all elements of active window
tell application "System Events" to tell process ActifProcess to set myWindow to front window
set T to ""
getUI(myWindow, 1)
set the clipboard to T
display dialog "Result is in clipboard. paste in Excel or text document"
on getUI(UIObjet, myLevel) -- get recursively the list of UI elements
set AppleScript's text item delimiters to {"//"}
tell application "System Events" to set UIliste to UI elements of UIObjet
repeat with oneUI in UIliste
tell application "System Events"
set UItext to ("Level=" & myLevel & tab & "Name=" & (name of oneUI) & tab & (description of oneUI) & tab & "Class=" & (class of oneUI) as string) & tab & "Title=" & (title of oneUI) as string
set UItext to (UItext & tab & "Value=" & (value of oneUI) as string) & tab
try
set UItext to (UItext & "Position=" & (position of oneUI) as text)
end try
set UItext to UItext & return
try
set NbSub to count of UI elements of oneUI
on error
set NbSub to 0
end try
set T to T & return & UItext
end tell
if NbSub > 0 then
getUI(oneUI, myLevel + 1) -- there are other sub UI elements, get them
end if
end repeat
end getUI
Copy this script in Script Editor. Make active the window/application you want to get UI elements. Make this script active and run.
The result is sometime not easy to interpret because developper of the application/window you're looking for may not have use UI element clear names or titles which describe what they are. Then you will have to look their relative position in the window.
The "import all" button is "button 3 of group 2 of splitter group 1 of window 1" for image capture version 6.6. Also, I prefer to use button number, instead of button name to make sure the script works with any language.
tell application "Image Capture"
activate
tell application "System Events"
tell process "Image Capture"
click button 3 of group 2 of group 1 of splitter group 1 of window 1
end tell
end tell
end tell
Please note that any next changes done by Apple on Image Capture will impact your script.
i'm newbies with AppleScript and i wanted to create an UI Selector for many of AppleScripts.
Example, i've testA.scpt, testB.scpt, testC.scpt and i want to run just one of these scripts by choosing from a list of choices in a window (UI).
it's possible ?
so, it's possible, could you help me and give an example !?
i think is a very similar code but i'm not sure :
set theName to (choose from list {"testA", "testB", "testC"})
if theName is false then
display dialog "You clicked cancel to exit." with icon stop buttons {"Exit"} default button {"Exit"}
else
set theName to (item 1 of theName)
display dialog theName with icon note buttons {"Info"} default button {"Info"}
end if
Give this a try. It's based on your scripts being in the same directory as this script.
set theName to (choose from list {"testA", "testB", "testC"})
if theName is false then
display dialog "You clicked cancel to exit." with icon stop buttons {"Exit"} default button {"Exit"}
else
set theName to (item 1 of theName)
tell application "Finder"
set the_script_path to ((container of the (path to me)) as text) & theName & ".scpt"
set the_script to load script alias the_script_path
end tell
run script the_script
end if
Applescript newbie question again :) I am trying to create a small applescript that will allow me to select multiple items from a list of currently running applications and then quit those selected apps. Something like this works but rather than having to click on each dialog it would be much easier to chose from a list.
tell application "System Events"
repeat with p in every process
if background only of p is false then
display dialog "Would you like to quit " & name of p & "?" as string
end if
end repeat
end tell
Any and all help would be greatly appreciated!
Thanks!
Try this:
tell application "System Events"
set listOfProcesses to (name of every process where background only is false)
tell me to set selectedProcesses to choose from list listOfProcesses with multiple selections allowed
end tell
--The variable `selectedProcesses` will contain the list of selected items.
repeat with processName in selectedProcesses
do shell script "Killall " & quoted form of processName
end repeat
tell application "System Events"
set processList to get the name of every process whose background only is false
set processNameList to choose from list processList with prompt "Select process to quit" with multiple selections allowed
if the result is not false then
repeat with processName in processNameList
do shell script "Killall " & quoted form of processName
end repeat
end if
end tell
you can use this script which is much simpler
tell application "Finder"
get the name of every process whose visible is true
end tell
You can try this
tell application "System Events"
set AppName to name of every process whose background only is false
choose from list AppName OK button name "Ok" cancel button name "Cancel"
end
& (name of every process whose (name is "AppName") can be added to Michele Percich's and Parag Bafna's solutions to include specific menu bar applications by name.
tell application processName to quit can be used instead of do shell script "Killall " & quoted form of processName.
tell application "System Events"
set processList to ¬
(name of every process where background only is false) & ¬
(name of every process whose ¬
(name is "AppName") or ¬
(name is "AnotherAppName"))
tell me to set selectedProcesses to choose from list processList with prompt "Select process(es) to quit:" with multiple selections allowed
end tell
if the result is not false then
repeat with processName in selectedProcesses
tell application processName to quit
end repeat
end if
I wrote this following AppleScript code a few years back. I consider it to be a “Must Have” because I use it almost every single day.
This code will generate a list of Visible and Hidden application processes, allowing multiple items to be selected to kill their processes. The first items in the list will be visible application processes (not sorted alphabetically), then an empty list item (used to separate the visible from the hidden processes), and the remaining list items will be the hidden application processes (sorted alphabetically)
use framework "Foundation"
use scripting additions
property appsToKill : missing value
property NSArray : a reference to current application's NSArray
listAllAppProcesses()
activate
set killApp to (choose from list ¬
appsToKill with title "Choose The App To Kill" with prompt ¬
"Choose The App/Apps To Kill" & linefeed & linefeed ¬
& "The Empty List Item Separates The Visible From The Hidden Applications" OK button name ¬
"OK" cancel button name "CANCEL" with multiple selections allowed)
set pidList to {}
if killApp is not false then
tell application "System Events"
repeat with i from 1 to count of killApp
set thisItem to item i of killApp
tell application process thisItem
set thePID to unix id
set end of pidList to thePID
end tell
end repeat
end tell
else
return
end if
set text item delimiters to space
do shell script ({"kill -9", pidList} as text)
on listAllAppProcesses()
tell application "System Events"
set visibleAppsToKill to name of every application process ¬
where visible is true
set invisibleAppsToKill to name of every application process ¬
where visible is false
set aList to ((NSArray's arrayWithArray:invisibleAppsToKill)'s ¬
sortedArrayUsingSelector:"caseInsensitiveCompare:") as list
set appsToKill to visibleAppsToKill & "" & aList
end tell
end listAllAppProcesses
If you want it from Terminal, you can use a simple script like this quit.rb
The following example AppleScript code is pretty straight forward and will gracefully quit the selected application(s), providing the selected application(s) is (are) in a stable state:
tell application "System Events" to ¬
set appList to the name of ¬
every process whose visible is true
set quitAppList to ¬
choose from list appList ¬
with multiple selections allowed
repeat with thisApp in quitAppList
quit application thisApp
end repeat
When I present a list to choose from, I prefer to have it in alphabetical order and to that end I use a handler to first sort the list before presenting it:
on SortList(thisList)
set indexList to {}
set sortedList to {}
set theCount to (count thisList)
repeat theCount times
set lowItem to ""
repeat with i from 1 to theCount
if i is not in the indexList then
set thisItem to item i of thisList as text
if lowItem is "" then
set lowItem to thisItem
set lowItemIndex to i
else if thisItem comes before lowItem then
set lowItem to thisItem
set lowItemIndex to i
end if
end if
end repeat
set end of sortedList to lowItem
set end of indexList to lowItemIndex
end repeat
return the sortedList
end SortList
To use this with the first block of code presented I typically add handlers at the bottom of my code and then to use it, add the following example AppleScript code between the tell application "Finder" to ¬ and set quitAppList to ¬ statements:
set appList to SortList(appList)
Note: I acquired this particular handler somewhere on the Internet too many years ago to remember and unfortunately lost who to credit it to. My apologies to whomever you are.