Find and replace in Excel 2011 using Applescript - macos

I was wondering if anyone could help me. I'm trying to find and replace blank spaces in an excel workbook. I want it to search the current sheet I'm on in a workbook, find all instances of "" and replace it with " ".
Does anyone happen to know how to do this?

With Applescript:
searchAndReplaceTextInCells("hello", "world")
on searchAndReplaceTextInCells(search_str, replace_str)
tell application "Microsoft Excel"
set search_range to range "A:Z"
set all_found_ranges to {} -- store for the ranges, to manipulate after searching
set found_range to ""
set counter to 0
try
set found_range to find search_range what search_str with match case
on error
log ("No matches found")
end try
if (found_range is not "") then
set first_cell_address to (get address of the cells of found_range) -- we use this to break our loop
repeat while true
set counter to counter + 1
copy found_range to end of all_found_ranges
-- Now look for next result
set found_range to find next search_range after found_range
set cell_address to (get address of the cells of found_range)
if (cell_address = first_cell_address) then
-- have looped around so we are finished!
exit repeat
end if
end repeat
end if
-- walk all the ranges found and do the string replacing
repeat with r in all_found_ranges
set value of r to my replace_chars(the value of r, search_str, replace_str)
end repeat
log ("found and replaced " & counter & " items")
end tell
end searchAndReplaceTextInCells
on replace_chars(this_text, search_string, replacement_string)
set my text item delimiters to the search_string
set the item_list to every text item of this_text
set my text item delimiters to the replacement_string
set this_text to the item_list as string
set my text item delimiters to ""
return this_text
end replace_chars

How about Command + F, and hit the Replace button to give you this:

Have you tried the following:
replace range targetRange what searchStr replacement replaceStr
This should be rather straight forward replacement statement.

Related

Get text of selected field code in Microsoft Word using AppleScript

I'm making a Automator to jump from citation in Word to the reference software(Zotero). But I can't find a AppleScript to extract text of selected field code (the first step).
The field code in Word is
ADDIN ZOTERO_ITEM CSL_CITATION {"citationID":"AFUiwuqi","properties":{"formattedCitation":"[1]","plainCitation":"[1]","noteIndex":0},"citationItems":[{"id":9752,"uris":["http://zotero.org/users/6410528/items/YYTRWPHH"],"itemData":{"id":9752,"type":"article-journal","container-title":"Nature","DOI":"10.1038/s41586-019-1737-7","ISSN":"0028-0836, 1476-4687","issue":"7782","page":"324-329","title":"Controlled flight of a microrobot powered by soft artificial muscles","volume":"575","author":[{"family":"Chen","given":"Yufeng"},{"family":"Zhao","given":"Huichan"},{"family":"Mao","given":"Jie"},{"family":"Chirarattananon","given":"Pakpong"},{"family":"Helbling","given":"E. Farrell"},{"family":"Hyun","given":"Nak-seung Patrick"},{"family":"Clarke","given":"David R."},{"family":"Wood","given":"Robert J."}],"issued":{"date-parts":[["2019",11,14]]}}}],"schema":"https://github.com/citation-style-language/schema/raw/master/csl-citation.json"}
Here is the script process:
Extract text from selected field code in Word (This is the question)
Get the uris text(http://zotero.org/users/6410528/items/YYTRWPHH)
Get the item-codes (YYTRWPHH).
Open url (zotero://select/library/items?itemKey=YYTRWPHH)
Now I use VBA to extract field code text, see below. But in this way, the file will be changed. So I want to do this via AppleScript.
Sub GetFiledsCodes()
Dim myRange As Range, myCodes As String
Set myRange = Selection.Range
With myRange
If .Fields.Count = 0 Then
MsgBox "No Code!", vbInformation
Exit Sub
Else
.Fields.Update
.TextRetrievalMode.IncludeFieldCodes = True
.TextRetrievalMode.IncludeHiddenText = True
myCodes = .Text
myCodes = VBA.Replace(myCodes, Chr(19), "{")
myCodes = VBA.Replace(myCodes, Chr(21), "}")
.SetRange .End, .End
.InsertAfter myCodes
.Font.Name = "Times New Roman"
.Font.Size = 12
.Cut
End If
End With
End Sub
PS:
Here is my process in Automator(it can work but using VBA):
Run AppleScript
on run {input, parameters}
tell application "Microsoft Word" to activate
tell application "Microsoft Word"
run VB macro macro name "GetFiledsCodes"
delay 0.5
end tell
return input
end run
Get contents from clipboard
Extract URLs from Text
Filter Paragraphs begin with http://zotero.org/users/
Copy to Clipboard
Run AppleScript
set myStr to do shell script "pbpaste"
tell application "Zotero" to activate
set AppleScript's text item delimiters to "
"
set myList to every text item of myStr
set zoterocode to ""
set codes to ""
repeat with j from 1 to the length of myList
set itemValue to item j of myList
set zoterocode to (do shell script "sed -E 's#http://zotero.org/users/[0-9]+/items/##g' <<< " & itemValue)
if j = 1 then
set codes to zoterocode
else
set codes to codes & "," & zoterocode
end if
end repeat
tell application "System Events"
key code 18 using {command down, control down, option down}
delay 0.5
set collectionKey to do shell script "pbpaste"
if collectionKey = myStr then
set theurl to "zotero://select/library/items?itemKey=" & codes
else
set theurl to collectionKey & "/items?itemKey=" & codes
end if
open location theurl
end tell
That helps a lot. Okay, so this isn't a turnkey solution for your question but I don't think you really need that as you'd probably end up having to tell me more about how this app works than is really necessary. So this script focuses on your initial question about getting the field codes/result ranges from a merge document.
I put together a simple mail merge consisting of labels and a data file with 8 records, each of which have 5 fields: {"«LastName»", "«JobTitle»", "«Company»", "«City»", "«Web»"}. The latter is the key field.
Basically, the script runs through the data merge document and cycles first through its fields, then the web field, and finally the web addresses.
Based on your script, I can't really determine what you are doing with each address so it finishes by collecting just the final part of each address in a list. The obscure parts for me are the pbpastes, the codes and the whole System Events block. This area would need tweaking.
Incidentally, it's quite likely that you can avoid some of the shell scripts but I can't say how yet. Obviously the script has some redundancies and could be further refined but I think it demonstrates how to extract the information you need. Take a look at it and let me know what issues there are that need addressing.
tell application "Microsoft Word"
set d1 to document "cardo_labels.docx"
set fContents to {} -- list of mergefield
set fResRange to {} -- list of result range, i.e. field merge data
repeat with x from 1 to (count of fields of d1)
set fcs to content of field code of field x of d1 --> " MERGEFIELD LastName "
set frr to content of result range of field x of d1 --> "Smith"
if fcs is not " NEXT " then -- ignore «Next Record»
set end of fContents to fcs
set end of fResRange to frr
end if
end repeat
--> single record example
fContents --> {" MERGEFIELD LastName ", " MERGEFIELD JobTitle ", " MERGEFIELD Company ", " MERGEFIELD City ", " MERGEFIELD Web "}
fResRange --> {"Smith", "President", "Acme Screw & Gear", "Metz", "http://zotero.org/users/1234/items/smith-metz"}
-- NB when not displaying 'merged data', fResRange will appear thusly: {"«LastName»", "«JobTitle»", "«Company»", "«City»", "«Web»"}
set webList to {}
repeat with y from 1 to (count of fResRange)
if item y of fResRange begins with "http://zotero.org/users/" then
set end of webList to (item y of fResRange)
end if
end repeat
--> {"http://zotero.org/users/1234/items/smith-metz"}
--> {"http://zotero.org/users/1234/items/smith-metz", "http://zotero.org/users/4222/items/branson-metz", "http://zotero.org/users/3236/items/house-metz", "http://zotero.org/users/3342/items/kurtz-london", "http://zotero.org/users/12345/items/jones-london"}
set urlPiece to {}
set AppleScript's text item delimiters to "/"
repeat with z in webList
set end of urlPiece to last text item of z
end repeat
-- contents of z
--> "http://zotero.org/users/1234/items/smith-metz"
set AppleScript's text item delimiters to ""
urlPiece
--> {"smith-metz"}
--> {"smith-metz", "jones-saopaolo", "branson-metz", "house-metz", "kurtz-london", "jones-london"}
end tell
Thanks to ideas from #Mockman.
Combining with the selection, here is the way to extract text from selected field code via AppleScript:
tell application "Microsoft Word"
tell selection
set fcs to content of field code of field of text object
end tell
end tell
fcs

Applescript Replace all <br> tags with empty lines?

This code gets two bits of two and copies them to the clipboard.
One bit of text is html. Before stripping out all the html I want to replace the tags with empty lines.
I can't get the replaced correctly, but the rest of the code works.
Any idea what I am doing wrong. I also tried using return instead of linefeed.
tell application "GarageSale 7"
repeat with theListing in (get selected ebay listings)
set des to get the description of theListing
set comment to get private comment of theListing
end repeat
end tell
set theText to des
to searchReplace(thisText, "<br>", linefeed)
set AppleScript's text item delimiters to searchTerm
set thisText to thisText's text items
set AppleScript's text item delimiters to replacement
set thisText to "" & thisText
set AppleScript's text item delimiters to {""}
return thisText
end searchReplace
on removeMarkupFromText(theText)
set tagDetected to false
set theCleanText to ""
repeat with a from 1 to length of theText
set theCurrentCharacter to character a of theText
if theCurrentCharacter is "<" then
set tagDetected to true
else if theCurrentCharacter is ">" then
set tagDetected to false
else if tagDetected is false then
set theCleanText to theCleanText & theCurrentCharacter as string
end if
end repeat
return theCleanText
end removeMarkupFromText
get the clipboard
set the clipboard to removeMarkupFromText(theText) & comment
You've defined a handler called searchReplace(), but you never actually use it. That's why your script isn't replacing the <br> tags.
Firstly, you want to define the handler properly. It should take arguments that are represented by variables; currently, your last two arguments are specific values:
to searchReplace(thisText, "<br>", linefeed)
Here's a suggested edit:
to searchReplace(thisText, searchTerm, replacement)
set my text item delimiters to searchTerm
set thisText to thisText's text items
set my text item delimiters to replacement
set thisText to thisText as text
set my text item delimiters to {""}
return thisText
end searchReplace
Then you can call it from your script like so:
tell application "GarageSale 7"
repeat with theListing in (get selected ebay listings)
set des to get the description of theListing
set comment to get private comment of theListing
end repeat
end tell
set theText to searchReplace(des, "<br>", linefeed)
set the clipboard to removeMarkupFromText(theText) & comment

Avoid AppleScript to make line breaks

I'm using this AppleScript to get the content of a selection of eMails:
using terms from application "Mail"
on run {input, parameters}
set mailContents to {}
repeat with aMessage in input
set end of mailContents to content of aMessage
end repeat
return mailContents
end run
end using terms from
The result looks like this:
{"

Here's some text followed by a longer URL, which is cut by a line break!
http://www.XYZ.net/diario/actualidad/economia/20140714/-ciudad-bar
ata-para-el-turismo_353_34541.html
"}
I want to use all links in those specific mails for fort her processing but it's not possible to use the divided URLs as seen in the example before.
So how to tell the AppleScript to keep the URL together?
Try this. I started with your mailContents example. You end up with a list of the links in the httpLinks variable. This works assuming every link starts with "http" and ends with "html". Good luck.
set mailContents to {"

Here's some text followed by a longer URL, which is cut by a line break!
http://www.XYZ.net/diario/actualidad/economia/20140714/-ciudad-bar
ata-para-el-turismo_353_34541.html
"}
set httpLinks to {}
repeat with i from 1 to count of mailContents
set thisContent to item i of mailContents
-- remove all return characters (mac, unix, and windows characters)
set AppleScript's text item delimiters to {character id 10, character id 13, character id 13 & character id 10}
set textItems to text items of thisContent
set AppleScript's text item delimiters to ""
set newText to textItems as text
-- find links
set AppleScript's text item delimiters to "http"
set textItems to text items of newText
if (count of textItems) is greater than 1 then
set AppleScript's text item delimiters to "html"
repeat with j from 2 to count of textItems
set linkItems to text items of (item j of textItems)
set thisLink to "http" & item 1 of linkItems & "html"
set end of httpLinks to thisLink
end repeat
end if
set AppleScript's text item delimiters to ""
end repeat
return httpLinks
This does not break lines, hope you can use it somehow:
tell application "Mail"
set mailSelection to selection
set mailContents to {}
repeat with mail in mailSelection
set end of mailContents to content of mail
end repeat
get mailContents
end tell
Thank you very much! I had to customize your script a bit because not every URL ends with html. Furthermore I used the source of the messages instead of content, because the deleted line breaks had the result, that it was very difficult to separate the URLs from other text. There was no space between them. This is my actual code:
`using terms from application "Mail"
on run {input, parameters}
set mailContents to {}
repeat with aMessage in input
set end of mailContents to source of aMessage
end repeat
set httpLinks to {}
repeat with i from 1 to count of mailContents
set thisContent to item i of mailContents
-- remove all return characters (mac, unix, and windows characters)
set AppleScript's text item delimiters to {"=09", "=" & character id 10, "=" & character id 13, "3D", character id 92}
set textItems to text items of thisContent
set AppleScript's text item delimiters to ""
set newText to textItems as rich text
-- find links
set AppleScript's text item delimiters to "http"
set textItems to text items of newText
if (count of textItems) is greater than 1 then
set AppleScript's text item delimiters to "target"
repeat with j from 2 to count of textItems
set linkItems to text items of (item j of textItems)
set thisLink to "http" & item 1 of linkItems & "target"
set end of httpLinks to thisLink
end repeat
end if
set AppleScript's text item delimiters to ""
end repeat
set list1 to httpLinks
set list2 to {}
repeat with x from 1 to count of items of list1
set n to item x of list1
if n is not in list2 then set end of list2 to n
end repeat
return list2
end run
end using terms from`

Find text from a file and set it as a variable in applescript?

I am trying to build a script that sends me updates and notifications from cex.io. Please keep on reading below, so I may guide you until the point I have trouble with.
The first simple script in this operation goes to cex.io's trading page for BTC/GHS. It records ands saves the text to a file every 4 seconds. It works great. It doesn't need to have safari refresh because the site pushes info to the browser live.
repeat
set the webpage_content to ""
tell application "Safari" to set the webpage_content to the text of document 1
set theText to webpage_content
set a to "Macintosh HD:Users:PRIVATE:Desktop:CEX:"
set theFile to (open for access file ((a) & "CEXRaw") with write permission)
write theText to theFile
close access theFile
delay 4
end repeat
-
And it returns this in a main file every 4 seconds: (note I cut off a chunk from the bottom and the top of the file, because they are unimportant)
GHS:
0.05233439
BTC:
0.00000223
NMC:
0.00002939
LTC:
0.00000000
GHS/BTC
0.02362958 LTC/BTC
0.02438131 NMC/BTC
0.00597565 GHS/NMC
3.96951800 BF1/BTC
1.67000000 Fund Account
GHS/BTC
Last price:
0.02362958
Daily change:
-0.00018042
Today's open:
0.02381000
24h volume:
73812.35539255
-
I now need an applescript to read that file, and return wanted values. But I'm lost on how to write it.
It needs to find the number under BTC, and set it as a variable.
It needs to find the number under GHS, and set it as a variable.
It needs to find the number under Last Price, and set it as a variable.
If anyone could script that really quick for me, or tell me how to do it, that would be amazing. Thank you so much!
Well, if those values will always be in the same paragraph counts, you could just pull them by line number.
set theCEXRaw to read file "Macintosh HD:Users:PRIVATE:Desktop:CEX:CEXRaw"
set theGHS to paragraph 2 of theCEXRaw
set theBTC to paragraph 4 of theCEXRaw
set thePRICE to paragraph 17 of theCEXRaw
You'd need to adjust the paragraph numbers. But, assuming that paragraph numbers aren't reliably consistent, in pure Applescript, you'd use Applescript's Text Item Delimiters.
set theCEXRaw to read file "Macintosh HD:Users:PRIVATE:Desktop:CEX:CEXRaw"
set AppleScript's text item delimiters to {("GHS:
"), ("BTC:
"), ("Last price:
")}
set theCEXRaw to text items of theCEXRaw
set theGHS to paragraph 1 of item 2 of theCEXRaw
set theBTC to paragraph 1 of item 3 of theCEXRaw
set thePRICE to paragraph 1 of item 4 of theCEXRaw
Note that the three delims include a return character inside the quotes. You will want to capture the old delimiter first, so you can restore it, and hopefully you can do the setting of the delimiter outside your repeat loop to save juice.
You could also use do shell script with sed or grep to strip each value.
You could get those values using the offset which searches a string for a substring and returns it's character position.
eg, set pos to the offset of "world" in "hello world" -- returns 7
Here is a solution that uses this principal to find your values and convert them into the Applescript floating point type Number
property line_delimiter : linefeed -- OR return OR return & linefeed pending your data
set results to "GHS:
0.05233439
BTC:
0.00000223
NMC:
0.00002939
LTC:
0.00000000
Last price:
0.02362958"
processCEX(results)
on processCEX(in_text)
set btc_val to searchNumberValueLine("BTC:" & line_delimiter, in_text)
set ghs_val to searchNumberValueLine("GHS:" & line_delimiter, in_text)
set last_price_val to searchNumberValueLine("Last price:" & line_delimiter, in_text)
display dialog ("btc = " & btc_val & return & "ghs = " & ghs_val & return & " last price = " & last_price_val)
end processCEX
on searchNumberValueLine(key_name, input_str)
set start_index to the offset of key_name in input_str
if (start_index is not 0) then
set input_str to text (start_index + ((length of key_name))) thru -1 of input_str
set end_index to the offset of line_delimiter in input_str
if (end_index is 0) then
return input_str as number
else
return (text 1 thru (end_index - 1) of input_str) as number
end if
else
return -1
end if
end searchNumberValueLine
Also i'd recommend against writing to a text file if you don't need to, to avoid any file io issues when reading the same file from a different script, given you are modifying it every 4 seconds.
You could change your code to something like this:
repeat
set the webpage_content to ""
tell application "Safari" to set the webpage_content to the text of document 1
processCEX(webpage_content)
delay 4
end repeat

Applescript repetitive renaming

I'm trying to make an AppleScript droplet to rename a bunch of images annoyingly formatted, but I found out my AppleScript skills have become nonexistent and I'm getting nowhere. So if possible, full code, not just snippets.
The file setup is always the same, but there are many variations (ex: Yellowst.Nat.Park.D12P55.DMS.3248.jpg)
It starts with a place name, should be a find and replace for a bunch of different strings, ("Yellowst.Nat.Park" -> "Yellowstone National Park")
Then it is followed by two numbers that should be changed in format (D12P55 -> [12x55]). They're always set up in a "D" followed by two numbers, a "P" and again two numbers.
And it ends with a random string, can be numbers, letters etc, which all have to go. They differ in format and length, no pattern in them.
Basically I want to go from "Yellowst.Nat.Park.D12P55.DMS.3248.jpg" to "Yellowstone National Park [02x03] .jpg" I want to add text afterwards so want to end with a space.
The best way to do this seems to me a repetitive find and replace for the first part, Make a list for a bunch of terms wich have to be replaced by a bunch of respective terms. Followed by a detection of the number format and ending with deleting of the random string after it.
Here is another approach.
property pictureFolder : (alias "Mac OS X:Users:Sam:Pictures:test:")
property findList : {"Yellowst.Nat.Park", "Jellyst.Nat.Park"}
property replaceList : {"Yellowstone National Park", "Jellystone \\& National Park"}
tell application "System Events"
set nameList to (name of every file of pictureFolder whose visible = true)
repeat with i from 1 to count of (list folder pictureFolder without invisibles)
set fileName to item i of nameList
set fileExtension to (name extension of (file fileName of pictureFolder))
repeat with j from 1 to count of findList
if fileName contains item j of findList then
set tempName to do shell script "echo " & fileName & " | sed 's/.D\\([0-9][0-9]\\)P\\([0-9][0-9]\\).*/[\\1x\\2] " & i & "." & fileExtension & "/'"
set tempName to do shell script "echo " & tempName & " | sed 's/^" & item j of findList & "/" & item j of replaceList & " /'"
set name of (file fileName of pictureFolder) to tempName
exit repeat
else if j = (count of findList) then
set tempName to do shell script "echo " & fileName & " | sed 's/[.]/ /g'"
set tempName to do shell script "echo " & tempName & " | sed 's/.D\\([0-9][0-9]\\)P\\([0-9][0-9]\\).*/ [\\1x\\2] " & i & "." & fileExtension & "/'"
set name of (file fileName of pictureFolder) to tempName
end if
end repeat
end repeat
end tell
To avoid duplicate names, I added a counter to the end of the file name. If there are no duplicates, you can use this instead:
set tempName to do shell script "echo " & fileName & " | sed 's/.D\\([0-9][0-9]\\)P\\([0-9][0-9]\\).*/[\\1x\\2] " & "." & fileExtension & "/'"
I like small challenges like this Sam. They're fun to me... maybe I'm sick ;). Anyway, I wrote you a handler to clean the file name as you requested. It's not really hard to manipulate text in applescript if you're comfortable with text item delimiters and such. These small challenges keep my text skills sharp.
NOTE: in the nameList property the name must end with a period or whatever character is just before the letter D in the number sequence DxxPxx as you mentioned.
So give this a try. Plug in a variety of fileNames and ensure it works how you want. Of course you need to put more values into the nameList and nameReplaceList properties too.
property nameList : {"Yellowst.Nat.Park."}
property nameReplaceList : {"Yellowstone National Park"}
set fileName to "Yellowst.Nat.Park.D12P55.DMS.3248.jpg"
cleanFilename(fileName)
(*================ SUBROUTINES ================*)
on cleanFilename(fileName)
-- first find the base name and file extension of the file name
set tids to AppleScript's text item delimiters
set ext to ""
if fileName contains "." then
set AppleScript's text item delimiters to "."
set textItems to text items of fileName
set ext to "." & item -1 of textItems
set baseName to (items 1 thru -2 of textItems) as text
set text item delimiters to ""
else
set baseName to fileName
end if
-- next find the pattern D, 2 numbers, P, and 2 numbers in the baseName
set chars to characters of baseName
set theSequence to missing value
repeat with i from 1 to (count of chars) - 6
set thisChar to item i of chars
if thisChar is "d" and item (i + 3) of baseName is "p" then
try
set firstNum to text (i + 1) thru (i + 2) of baseName
firstNum as number
set secondNum to text (i + 4) thru (i + 5) of baseName
secondNum as number
set theSequence to text i through (i + 5) of baseName
exit repeat
end try
end if
end repeat
-- now make the changes
if theSequence is not missing value then
set AppleScript's text item delimiters to theSequence
set theParts to text items of baseName
set fixedFirstPart to item 1 of theParts
repeat with i from 1 to count of nameList
if item i of nameList is fixedFirstPart then
set fixedFirstPart to item i of nameReplaceList
exit repeat
end if
end repeat
set fixedName to fixedFirstPart & " [" & firstNum & "x" & secondNum & "]" & ext
else
set fixedName to fileName
end if
set AppleScript's text item delimiters to tids
return fixedName
end cleanFilename
Now if you want to automate this for a folder full of files you can use this code. Just replace lines 3 and 4 of the above script with this. I didn't check this code but it's simple enough it should work as-is.
NOTE: you don't need to worry if non-image files are in the folder you choose with this code because they won't (I'm assuming this) have the DxxPxx number sequence and thus this script will not change them in any way.
set theFolder to choose folder
tell application "Finder"
set theFiles to files of theFolder
repeat with aFile in theFiles
set thisName to name of aFile
set newName to my cleanFilename(thisName)
if newName is not thisName then
set name of aFile to newName
end if
end repeat
end tell

Resources