QUESTION: Scripting advice

So at work, I use a program that requires a lot of text fields to be filled in, I have several macros that use AppleScript to help me select the fields, get the value of the fields so they can be copied, set the fields to certain text, etc. But something that bothers me, is that all the macros are basically the same, i.e. They start with an action (set, get, click, press) and then they have a really long string that references the element the action is being performed on, like this:

set emailOnFile to value of static text 1 of group 2 of group 9 of group 3 of group 10 of group 1 of UI element 1 of scroll area 1 of splitter group 1 of window 1

The problem with this is first off, that long string is impossible to know what it refers to without comments or something to identify it, and second it really reduces the readability of the script itself.
What I would like to do, is to be able to set the element reference (the long string) to a variable and then use the variable to reference it. Something like this:

set ref__emailOnFile to "static text 1 of group 2 of group 9 of group 3 of group 10 of group 1 of UI element 1 of scroll area 1 of splitter group 1 of window 1"

So that way the first script could be written like this (which is much more understandable and I actually know what it’s referring to):

set emailOnFile to value of ref__emailOnFile

But when trying that, it gets an error:

Can’t get value of "static text 1 of group 2 of group 9 of group 3 of group 10 of group 1 of UI element 1 of scroll area 1 of splitter group 1 of window 1".

Now I’m pretty sure the reason for this error is because it is treating the variable as a string rather than a reference to the location of the element, but I just can’t seem to find a way to make this work as I would like. It seems fairly straightforward but I’m hitting a wall here, if it’s not possible then no big deal, I just figured I’d see what you guys had to say.
Thanks for any advice!

  • Kevin

Assuming that your above snippet works, then this should work also:

tell window 1
  tell splitter group 1
    tell scroll area 1
      tell UI element 1
        tell group 1
          tell group 10
            tell group 3
              tell group 9
                tell group 2
                  tell static text 1
                    set emailOnFile to value
                  end tell
                end tell
              end tell
            end tell
          end tell
        end tell
      end tell
    end tell
  end tell
end tell

This is way more readable and you can easily place comments.

I think what you mean is a handler (function). In its most basic form, you can build a handler like this:

on ref__emailOnFile()
  tell application "System Events"
    tell application process "<your process name here>"
      tell window 1
        tell splitter group 1
          tell scroll area 1
            tell UI element 1
              tell group 1
                tell group 10
                  tell group 3
                    tell group 9
                      tell group 2
                        tell static text 1
                          set myVar to value
                        end tell
                      end tell
                    end tell
                  end tell
                end tell
              end tell
            end tell
          end tell
        end tell
      end tell
    end tell
  end tell
  return myVar
end ref__emailOnFile

And then:

set emailOnFile to ref__emailOnFile()

It would probably be a good idea to read some introductions to handlers:

What you are showing is known as "UI scripting", and it is very difficult without the proper tools.

So, if you have a lot of workflows that need UI scripting, or you have even a few that are complex, then it may be worthwhile to invest in a tool to help you identify and create the necessary AppleScript statements to access/set/click a specific UI element.

One of the best tools for this is UI Browser.
Not cheap @ $50, but well worth it if you have many or complex UI elements to script. It can often enable solutions not otherwise achievable and/or save you many, many hours of work (an frustration).

You can also google "AppleScript UI scripting" to find other tools, solutions, suggestions. You don't say what app(s) you are trying to script, but you could also include the app name in the search.

Good luck, and let us know how it goes.

Thanks for the advice, I didn't even consider using a sub-routine to handle the reference, I'll probably give that a shot and see if that works out the way I'd like to.

.[quote="JMichaelTX, post:3, topic:6458"]
One of the best tools for this is UI Browser.Not cheap @ $50, but well worth it if you have many or complex UI elements to script. It can often enable solutions not otherwise achievable and/or save you many, many hours of work (an frustration).
[/quote]

I definitely agree, I actually did use UI Browser to get all the elements I gathered, it is totally worth the $50. For me, it wasn't so much figuring out the UI scripting that was an issue, it was trying to just clean up the script in a way to try to hide all of the all of the strings like "group 1 of group 9 of group 3" etc. I'm probably going to try to rearrange some stuff along the lines Tom suggested (making a sub-routine) to handle all that junk.

Thanks again!

Oh btw, I just remembered the continuation character! It’s not exactly what I was asking about, but it definitely helped make the script much more readable.

Instead of this:

    set emailOnFile to value of static text 1 of group 2 of group 9 of group 3 of group 10 of group 1 of UI element 1 of scroll area 1 of splitter group 1 of window 1

The lines breaks up into much more readable chunks, like so:

set emailOnFile to value of ¬
	static text 1 of group 2 of group 9 of group 3 of group 10 of ¬
	group 1 of UI element 1 of scroll area 1 of splitter group 1 of window 1

Hey Kevin,

In my opinion it’s generally a good idea to use the nested form of reference Tom demonstrated - it’s easier to read, understand, test, and maintain.

Depending upon the structure you may be able to use a name for an element instead of a number, but you have to check and test.

Using a handler for a reference is a worthwhile idea, however you can use an actual reference form.

This represents the search field in Apple Mail:

-----------------------------------------------------------------
tell application "System Events"
   tell application process "Mail"
      tell (first window whose subrole is "AXStandardWindow")
         tell toolbar 1
            tell group 4
               set mailSearchField to a reference to text field "Search"
            end tell
         end tell
      end tell
   end tell
end tell
-----------------------------------------------------------------
using terms from application "System Events"
   
   set value of mailSearchField to "my search string"
   
end using terms from
-----------------------------------------------------------------

Keeping the reference(s) within the System Events tell-block cancels the need for the using-terms-from block.

Alternatively I could write it like this:

-----------------------------------------------------------------
use application "System Events"
-----------------------------------------------------------------

tell application process "Mail"
   tell (first window whose subrole is "AXStandardWindow")
      tell toolbar 1
         tell group 4
            set mailSearchField to a reference to text field "Search"
         end tell
      end tell
   end tell
end tell

set value of mailSearchField to "my search string"

-----------------------------------------------------------------

You need to have some understanding of how the scoping works for this form though, or you’ll likely create problems for yourself.

-Chris

1 Like