I want to set the value of an AXDateTimeArea GUI element via Applescript. Attached is a screenshot of the Accessibility Inspector showing the element.
This is the code that I tried. No errors are thrown, but the value of the element doesn't change.
set value of attribute "AXValue" of tElement to "2012-06-21 13:45:18 +0000"
Additionally I tried the following lines but no success nor an error thrown.
set value of tElement to "2012-06-21 13:45:18 +0000"
set value of tElement to (current date)
set value of attribute "AXValue" of tElement to (current date)
This is always within a loop over the content of the sheet/window:
tell application "System Events"
tell process "myprocess"
set tElements to entire contents of (get sheet 1 of window 1)
repeat with tElement in tElements
end repeat
end tell
end tell
This is a screenshot:
Related
I am debugging a legacy desktop automation tool which use AppleScript for UI control on MacOS. One of the script keeps failing with error "System Events got an error: Can’t get static text \"2\" of window \"UISoup – mac_utils.py\" of application process \"pycharm\"." number -1728 from static text "2" of window "UISoup – mac_utils.py" of application process "pycharm", and here is the script
tell application "System Events" to tell process "PyCharm"
set visible to true
set uiElement to static text "2" of window "UISoup – mac_utils.py" of application process "pycharm" of application "System Events"
set layer to 1
if uiElement = null then
set layer to 0
set collectedElements to {UI elements of front window, layer}
else
set layer to layer + 1
set collectedElements to {null, layer}
if name of attributes of uiElement contains "AXChildren" then
set collectedElements to {value of attribute "AXChildren" of uiElement, layer}
end if
end if
end tell
It seems like this line set uiElement to static text "2" of window "UISoup – mac_utils.py" of application process "pycharm" of application "System Events" should set the uiElement to null if the element is not found. But in fact it will throw error instead. How to let it return null instead of throw error to make it works? Thank you.
In the AppleScript equivalent of null is missing value. When GUI scripting, the process should be frontmost. You can check existing of UI elements using command exists (you can use try block as well).
tell application "System Events" to tell process "PyCharm"
set frontmost to true
-- set visible to true
set uiElementExists to exists static text "2" of window "UISoup – mac_utils.py"
set layer to 1
if not uiElementExists then
set layer to 0
set collectedElements to {UI elements of front window, layer}
else
set layer to layer + 1
set collectedElements to {missing value, layer}
set uiElement to static text "2" of window "UISoup – mac_utils.py"
if name of attributes of uiElement contains "AXChildren" then
set collectedElements to {value of attribute "AXChildren" of uiElement, layer}
end if
end if
end tell
Script:
global frontApp, frontAppName, windowTitle
set windowTitle to ""
tell application "System Events"
set frontApp to first application process whose frontmost is true
set frontAppName to name of frontApp
tell process frontAppName
tell (1st window whose value of attribute "AXMain" is true)
set windowTitle to value of attribute "AXTitle"
end tell
end tell
end tell
return {frontAppName, windowTitle}
It works some times, but other times I get things like: [2021-03-15 19:43:53.947] [error] Error: 339:344: execution error: System Events got an error: Can’t get window 1 of process "Adobe Premiere Pro 2020" whose value of attribute "AXMain" = true. Invalid index. (-1719)
Any ideas?
Thanks!
This following repeat loop added to your AppleScript code should do the trick
global frontApp, frontAppName, windowTitle
set windowTitle to ""
tell application "System Events"
set frontApp to first application process whose frontmost is true
set frontAppName to name of frontApp
tell process frontAppName
repeat until exists of ¬
(1st window whose value of attribute "AXMain" is true)
delay 0.1
end repeat
tell (1st window whose value of attribute "AXMain" is true)
set windowTitle to value of attribute "AXTitle"
end tell
end tell
end tell
return {frontAppName, windowTitle}
Is it possible to get the name of an Illustrator artboard in Applescript?
This script works perfectly until I try to get the name of the artboard:
tell application "Adobe Illustrator"
tell document 1
set artboards_count to count of artboards
set c to 1
repeat while c <= artboards_count
log index of artboard c as text
log artboard rectangle of artboard c as text
log name of artboard c as text -- this line fails
set c to c + 1
end repeat
end tell
end tell
the line log name of artboard c as text fails - everything else works ok.
The message is:
Adobe Illustrator got an error: Can’t get name of artboard 1 of document 1. (-1728)
Any idea as to why?
Setting the name fails too, BTW. However if I do
tell application "Adobe Illustrator"
tell document 1
return properties of artboard 1
end tell
end tell
I get (carriage returns added for clarify):
artboard rectangle:0.0, 0.0, 841.889999999999, -595.280000000001,
ruler PAR:1.0, show center:false, show cross hairs:false,
show safe areas:false, ruler origin:0.0, 0.0, name:Artboard 1,
container:document 1, best type:reference, default type:reference,
class:artboard, index:1
from which one would think the property nameshould be there.
The name property is read-only so there is no way to change it once the artboard exists. And even though you can get the properties of an artboard, you can’t convert it to a string if you simply want to target a particular artboard. But there is a way to do it nonetheless that I discovered by accident. Suppose you have several artboards and want to target the artboard named "Squash this". Here's how to do that:
Tell application "Adobe Illustrator"
tell current document
set artCount to number of artboards
repeat with i from 1 to artCount
set artProp to get properties of artboard i
try
set propString to artProp as string --this will fail
on error
set errorDisp to text of result --this captures the text of the error
set errorDispText to errorDisp as string --changes the text to a ¬
searchable string
end try
if errorDispText contains "quash" then
display notification "errorDispText" --oddly enough, this displays just ¬
the artboard name
exit repeat
end if
end repeat
end tell
end tell
The best solution could be coercion; take the record returned from the Artboard properties and coerce the record into a list. So, your name property from the record becomes the 7th item in the list. The code below will get Artboard dimensions, name and index, and place them into a list for later use in your script.
Hope this helps!
tell application "Adobe Illustrator"
set artboardDetails to {}
tell front document
set allArtboards to every artboard
repeat with i from 1 to count of allArtboards
set thisArtboard to item i of allArtboards
set thisArtboardProps to properties of thisArtboard
set thisArtboardDimensions to artboard rectangle of thisArtboardProps
set thisArtboardIndex to index of thisArtboardProps
--WORKAROUND
set thisArtboardPropsCoerce to thisArtboardProps as list
set thisArtboardName to item 7 of thisArtboardPropsCoerce
set the end of artboardDetails to {thisArtboardName, thisArtboardIndex, thisArtboardDimensions}
end repeat
end tell
end tell
(*
--WORKAROUND
The following is a workaround for error returned from:
set anArtboardName to the name of anArtboard -- this line will not return a result, just errors out
BUT WE NEED TO WATCH OUT FOR THE COERCED LIST!
So, we have to coerce the properties record of artboard to a list first
WEIRD I KNOW!
The coercion then changes the record of 11 items to a list of 12 items
set anArtboardProps to properties of anArtboard as list
set anArtboardName to item 7 of anArtboardProps
NOW LETS MATCH UP THE COERCION ITEMS
The first lines are from the record properties, and the second lines are from the coerced to list versions.
01. artboard rectangle:{0.0, 768.0, 1366.0, 0.0},
01. {0.0, 768.0, 1366.0, 0.0},
02. ruler PAR:1.0,
02. 1.0,
03. show center:false,
03. false,
04. show cross hairs:false,
04. false,
05. show safe areas:false,
05. false,
06. ruler origin:{0.0, 0.0},
06. {0.0, 0.0},
07. name:"Artboard 1",
07. "Artboard 1",
08. container:document 1,
08. document 1,
09. best type:reference,
09. reference,
10. default type:reference,
10. reference,
11. index:1
11. artboard,
12. NULL - nothing in the record
12. 1 - so this line is the index of the artboard
*)
Here is my workaround. As the «class bAl9» vanishes every time you compile, you have to copy/paste every time, but it works. And yes, «class bAl9» will turn to "name" and will not compile correctly the next time. Thanks Adobe !
tell application "Adobe Illustrator"
tell document 1
repeat with x in (every artboard)
log index of x as text
log artboard rectangle of x as text
log «class bAl9» of x as text -- artboard's name property = «class bAl9»
end repeat
end tell
end tell
The name property of artboards is read/write, it's easy to rename artboards this way once you get the trick.
Edit : For the loop in a list, I always use the repeat with x in l statement. It's smart and fast.
Stu's answer was the best that I found. Coercing the record to a list is brilliant – I didn't even know you could do that. My code was:
repeat with i from 1 to the (count of AllArtBoards)
set ThisArtBoard to item i of AllArtBoards
set ThisArtBoardName to item 7 of ((properties of ThisArtBoard) as list)
set the end of AllArtBoardNames to ThisArtBoardName
end repeat
ƒIt's caused when run through osascript from terminal using the command line "osascript Export\ Library.scpt /Users/bryandunphy/Development/iTunesLibraryConsolidator testing.xml".
same script as my last (solved) question but posting it's entirety this time.
-- `menu_click`, by Jacob Rus, September 2006
--
-- Accepts a list of form: `{"Finder", "View", "Arrange By", "Date"}`
-- Execute the specified menu item. In this case, assuming the Finder
-- is the active application, arranging the frontmost folder by date.
on menuClick(mList)
local appName, topMenu, r
-- Validate our input
if mList's length < 3 then error "Menu list is not long enough"
-- Set these variables for clarity and brevity later on
set {appName, topMenu} to (items 1 through 2 of mList)
set r to (items 3 through (mList's length) of mList)
-- This overly-long line calls the menu_recurse function with
-- two arguments: r, and a reference to the top-level menu
tell application "System Events" to my menuClickRecurse(r, ((process appName)'s ¬
(menu bar 1)'s (menu bar item topMenu)'s (menu topMenu)))
end menuClick
on menuClickRecurse(mList, parentObject)
local f, r
-- `f` = first item, `r` = rest of items
set f to item 1 of mList
if mList's length > 1 then set r to (items 2 through (mList's length) of mList)
-- either actually click the menu item, or recurse again
tell application "System Events"
if mList's length is 1 then
click parentObject's menu item f
else
my menuClickRecurse(r, (parentObject's (menu item f)'s (menu f)))
end if
end tell
end menuClickRecurse
-- Created by Bryan Dunphy during January of 2017
--
-- select the folder "directory" in Window "WinName" of Application "appName" and then clicks the default button if requested
-- if WinName is "" then it uses the frontmost window (to allow for unnamed windows)
-- REQUIRES "on handleDir" and "on findRoot" to work!
-- ONLY call switchDir
-- "createIt" is a boolean that will create any missing directories if it is set to "true".
-- "selectDefault" is a boolean indicating whether or not to click the window's default button after selecting the specified directory
-- returns "true" or "false" to indicate success.
-- clicks "Cancel" button on failure
-- Always returns "true" if "createIt" is set to "true"
on switchDir(directory, winName, appName, createIt, selectDefault)
local dirs, delim
set delim to AppleScript's text item delimiters
set AppleScript's text item delimiters to "/"
set dirs to every text item of directory
tell application "System Events" to tell process appName to set frontmost to true
my findRoot(appName, winName)
repeat with dir in dirs
if not handleDir(dir, winName, createIt) then
tell application "System Events" to tell process appName to tell button "Cancel" to click
return false
end if
end repeat
if selectDefault then keystroke return
return true
end switchDir
on handleDir(dir, winName, appName, createIt)
local foundIt
foundIt = false
local ndx
if winName is not "" then
repeat with ndx from 1 to (count of window winName's list 1)
if window winName's list 1's item ndx's value is equal to dir then
select window winName's list 1's item ndx
foundIt = true
exit repeat
end if
end repeat
else
repeat with ndx from 1 to (count of front window's list 1)
if front window's list 1's item ndx's value is equal to dir then
select front window's list 1's item ndx
foundIt = true
exit repeat
end if
end repeat
end if
if not foundIt then
if createIt then
if winName is not "" then
tell application "System Events" to tell process appName to tell window winName
tell button "New Folder"
click
repeat until window "New Folder" exists
delay 0.5
end repeat
set value of text field 1 of window "New Folder" to dir
tell button "Create" to click
return my handleDir(dir)
end tell
end tell
else
tell application "System Events" to tell process appName to tell its front window
tell button "New Folder"
click
repeat until window "New Folder" exists
delay 0.5
end repeat
set value of text field 1 of window "New Folder" to dir
tell button "Create" to click
return my handleDir(dir)
end tell
end tell
end if
end if
else
return foundIt
end if
end handleDir
on findRoot(appName, winName)
local rootName
if winName is not "" then
tell application "System Events" to tell process appName to tell window winName
tell pop up button 1
click
repeat until menu 1 exists
delay 0.5
end repeat
local ndx
repeat with ndx from 1 to (count of menu 1)
if the title of menu 1's menu item ndx is "" then
set rootName to the title of menu 1's menu item (ndx - 1)
select (menu 1's menu item (ndx - 1))
exit repeat
end if
end repeat
end tell
end tell
else
tell application "System Events" to tell process appName's front window
tell pop up button 1
click
repeat until menu 1 exists
delay 0.5
end repeat
local ndx
repeat with ndx from 1 to (count of menu 1)
if the title of menu 1's menu item ndx is "" then
set rootName to the title of menu 1's menu item (ndx - 1)
select (menu 1's menu item (ndx - 1))
exit repeat
end if
end repeat
end tell
end tell
end if
return rootName
end findRoot
on run (clp)
if clp's length is not 2 then error "Incorrect Parameters"
local destination, libraryName
set destination to clp's item 1
set libraryName to clp's item 2
menuClick("iTunes", "File", "Library", "Export Library…")
set value of parentObject's text field "Save As:" to (libraryName and ".xml")
tell pop up button 1 of group 1 of window "New iTunes Library" of process iTunes of application "System Events" to click
repeat with ndx from 1 to (count of parentObject's menu 1)
if title of menu item ndx is "" then
select menu item (ndx - 1)
exit repeat
end if
end repeat
my switchDir(destination, "iTunes", "iTunes", true, false)
set the value of text field "Save As:" of window "iTunes" to (libraryName + ".xml")
tell button "Save" of window "iTunes" to click
return (destination and "/" and libraryName and ".xml")
end run
Change:
menuClick("iTunes", "File", "Library", "Export Library…")
to:
menuClick({"iTunes", "File", "Library", "Export Library…"})
AppleScript's error reporting is truly awful (no tracebacks, for starters), and osascript is even worse than Script Editor for debugging. If you run the script in SE, it will at least highlight the line in your script where the error occurred. If that doesn't give you a clue, add log commands to report the script's progress. osascript will write logged messages to stderr. In SE, click the awful 'document' (show/hide log) icon at the bottom of the window, then select 'Messages'. If your time is worth more than $100, get yourself a copy of Script Debugger which also lets you add breakpoints and step through and inspect variables as the script runs.
value of static text of row 1 of (table 1 of some scroll area)
--> {"Wi-Fi, Connected"}
select (row of (table 1 of some scroll area)
whose (value of static text) begins with "Wi-Fi")
error "Can’t get attribute \"AXValue\" of static text."
number -1728 from «class attr» "AXValue" of «class sttx»
While I can get the value, why I can't use it as a filter in 'whose' clause?
Thanks.
value of static text seems to return a list like {"Wi-Fi, Connected"}. Try using a repeat loop that coerces the list to text:
tell application "System Events" to tell process "System Preferences"
repeat with r in rows of table 1 of scroll area 1 of window 1
if (value of static text of r as text) starts with "Wi-Fi" then return r
end repeat
end tell