Yes Another Find/Replace Question

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.

Thanks in advance,
George

(Duplicate posts deleted…)

Hi,

what’s about doing it without TextEdit?

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

thanks stefan! that worked. I don’t know how it works, but it does :smiley:

You might see: Tutorial for Using AppleScript’s Text Item Delimiters in MacScripter.net/unscripted

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. :wink:

Of course, the non-Text Edit is probably better, but I pulled the above from a script designed before knowing StefanK’s cool technique. :wink:

Hi Kevin,

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. :wink:

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. :slight_smile:

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

Hi George,

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?