searched but didn’t see this specific question answered.
What I’m trying to do:
Search a TextEdit document for the words “Last Update” and replace all of them with the word “Created”.
So here’s the part of my script that’s having trouble (TextEdit has already been activated).
tell application "TextEdit"
tell application "System Events"
tell process "Textedit"
key down command
keystroke "f"
key up command
keystroke "Last Update"
keystroke tab
keystroke "Created"
end tell
tell process "Textedit"
tell window "Find"
click button "Replace All" of window "Find"
end tell
end tell
end tell
end tell
The Error
The script works fine up until the ‘click button “Replace all”’ part. It even opens up the Find window and inputs the correct stuff in the Find and Replace field.
Here’s the error Message
I’m a noob, so sorry if I’m missing something annoyingly simple. This little action is very important to me. If I can get it to work, I’ll be one step closer to taking over the world, and I promise to reward all those who help.
set theFile to choose file
try
set ff to open for access theFile with write permission
set theText to (read ff)
set {ASTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "Last Update"}
set theText to text items of theText
set AppleScript's text item delimiters to "Created"
set theText to theText as string
set AppleScript's text item delimiters to ASTID
write theText to ff starting at 0
close access ff
on error
try
close access theFile
end try
end try
I don’t have a “replace” portion, but this was my “Find”:
on dataFinder(search_string)
tell application "System Events"
tell process "TextEdit"
-- move cursor to start of file
keystroke (ASCII character 30) using {command down}
--initiate Find
keystroke "f" using {command down}
delay small_delay --give dialog time to appear
keystroke search_string --enter what to find
keystroke return --start Find
delay small_delay --wait for find to finish
keystroke "." using {command down} --close Find dialog
end tell
end tell
end dataFinder
With GUI scripting, delays are your friend. Often errors are just the fact that the on-screen display hasn’t caught-up to where the script is trying to keystroke or click. In other words, the script is often quicker than the User Interface itself.
Of course, the non-Text Edit is probably better, but I pulled the above from a script designed before knowing StefanK’s cool technique.
delays are necessary but crucial, so I try to avoid them whenever possible.
For example I prefer to wait a certain amount of time until a UI element (like a window) exist.
And if I can access text fields directly, I prefer this way instead of scripting keystrokes.
Here a version of your routine with a minimum of time-critical stuff
on dataFinder(search_string)
activate application "TextEdit" -- this is important, if something else has a cmd-F command
tell application "System Events"
tell process "TextEdit"
-- move cursor to start of file
keystroke (ASCII character 30) using command down
--initiate Find
keystroke "f" using command down
repeat until exists window "Find"
delay 0.5
end repeat
tell window "Find"
set value of text field 1 to search_string
click button "Next"
delay 0.5
click button 1
end tell
end tell
end tell
end dataFinder
Sweet, I like it. Though for streamlining the code, I prefer the generic-variabled “delay” command…only one line of code. I use three generic variables (delay_small, delay_medium, delay_long). Usually 0.3, 0.5, and 1.0 repectively…but fine-tunable.
I didn’t have the “activate TextEdit” because this handler is only used inside such an activation in the main script, so that was a great catch for the OP, thanks!
I do agree with activating a particular element directly, that’s a nice touch I hadn’t considered. I discovered, at least pre-Tiger, that not all the elements in TextEdit responded properly to direct access, so I gave up figuring out which liked it and which didn’t and just did it all the manual way…call it lazy or expedient, your choice.
You might consider using 0.1 as your delay increment, since think ApplyScript (at least in Tiger) will respond to delays that small, and thus make the delays only as long as necessary.
I learn more about GUI every day, even though like must of us, avoided it like the plague when I can.
I love your both your non-TextEdit version (wouldn’t have fit my need, but handles the OP’s really well), and love the extra tools you’ve added to my GUI scripting arsenal. Always enlightening StefanK.
thanks! I think it’d be in my best interest to learn read through that a couple of times. Very helpful stuff.
so my script is finished and works. I thought I’d just post it here, since it’s my first script and I’m naturally really proud of it. It tells you the possible create date (which Yahoo lists as “Last Updated”) for a yahoo email address. I just used “johnsmith” as an example. What I want to do with this script is make it more accessible to lists.
Ideally, here’s how it’s going to work when I’m completely finished.
I’ll have a list of yahoo email addresses in an excel sheet. My script will extract the part before “@yahoo.com”, or the Yahoo Name. The script will visit the Yahoo Profiles site, extract the Create Date (or Last Update as it’s called) from the site and return it in the next column of the excel sheet. And the script will go down the list of email addresses.
I honestly have no idea how I’m going to make it interact with a list in Excel, but I know it can be done. If anyone thinks this is an interesting script and ends up writing it how I ultimately want it, feel free to share it.
set yahoo_name to "johnsmith"
set yahoo_page to "http://profiles.yahoo.com/"
tell application "Safari"
activate
open location yahoo_page & yahoo_name
delay 3
end tell
tell application "Safari"
set textVersion to (the text of the front document)
end tell
tell application "TextEdit"
activate
make new document at the front
set the text of the front document to textVersion
end tell
tell application "TextEdit"
delete paragraphs 1 through 21 of the front document
end tell
tell application "TextEdit"
delete paragraphs 2 through 47 of the front document
end tell
tell application "TextEdit"
activate
save the front document in ":Users:[MYUSERNAME]:Documents:yahoo.rtf"
end tell
set theFile to ":Users:[MYUSERNAME]:Documents:yahoo.rtf"
try
set ff to open for access theFile with write permission
set theText to (read ff)
set {ASTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "Last Update"}
set theText to text items of theText
set AppleScript's text item delimiters to "johnsmith"
set theText to theText as string
set AppleScript's text item delimiters to ASTID
write theText to ff starting at 0
close access ff
on error
try
close access theFile
end try
end try
congratulations for your first script.
I know, it’s a lot of work to write all the code.
Anyway I’m sorry to tell you, that the text parsing can be done much easier without Safari and TextEdit.
Three shell commands in one line do the same: curl reads the source code of the page awk filters the line with “Last Update” in it and returns the characters from the date till the end of the line cut cuts all characters off from “<” till end
set yahoo_name to "johnsmith"
set yahoo_page to "http://profiles.yahoo.com/"
set theDate to do shell script "curl " & yahoo_page & yahoo_name & " | awk '/Last Update: / {print $4}' | cut -f 1 -d '<' "
set theFile to ((path to documents folder as Unicode text) & "yahoo_" & yahoo_name & ".txt")
try
set ff to open for access theFile with write permission
write yahoo_name & ": " & theDate to ff starting at 0
close access ff
on error
try
close access theFile
end try
end try
Wow, thanks for letting me know about that! Your script is much quicker to run than mine. This was to be just one small part of a much larger script that retrieves similar information from the internet, so I definitely appreciate you showing me that.
both of these methods are definitely useful solutions for the find replace issue.
I wonder why that functions isnt built into the text edit library in Snow Leopard.
Seems like something a lot of people would use.
In terms of speed, which have you found to respond faster. My guess would be the GUI Scripting.
Are there any UNIX commands that would accomplish the same function?