I have extensive autocorrect lists inside TextExpander (over 3000 words between them). I don’t want to have to recreate them all in KM or a Word Macro. It’s also easiest to keep updates in one app.
Is there a way that Keyboard Maestro could come to the rescue here? Is there any way that it could look at an already created Word doc and check against those lists (or run TE in a way that it would act like a new doc)?
I’m not sure I understand your request.
Are you saying that you want to replace all of the abbreviations in an existing Word doc with the expansion stored in TE?
If so, could you please provide an example of your Word doc, and the TE items to be used.
For each word from the MS Word doc, search the TE list
IF found, replace the word in MS Word with the TE expansion
Here's the TE AppleScript basics:
tell application "TextExpander"
set snippetAbbList to abbreviation of every snippet of every group
set snippetExp to plain text expansion of every snippet of every group
end tell
What I’m looking to to is copyedit a very long Word document. Normally, when I write, TE autocorrects on the fly. But there are times that either TE can’t because an app locks it out for ‘security’ reasons, or the document is already in place (emailed to me).
Since I already have a folder in TE which has a ton of autocorrects for misspelled words, words that should be capped, some that should have hyphens, some that should’t, I’d like to make use of them.
Yeah. I was afraid I’d have to convert them to a Word Macro. Might have to look at how TE exports, then create a KM macro to go through and modify the exported TE file so that a Word Macro can look at a separate document to run against. Typing them in all by hand would be way past excruciating.
In this case, it would be easy using AppleScript to get the TE snipped data (abbreviations and expanded text) and write that to a file, even a CSV file. You can then open this file using Word VBA, and load the data into VBA array.
I love KM, and use it daily. But I don't see an obvious roll for KM in this process. Maybe Peter or Chris (ccstone) will jump in and offer alternative process that I don't see.
If you're dealing with plain-text then AppleScript + the Satimage.osax AppleScript extension is a viable answer. I've wrote a pretty sophisticated find/replace script for someone on the BBEdit-Talk list (IIRC) that does much of what you're talking about.
If you're dealing with styled-text then the AppleScript solution is out.
I'm wondering though if you can import your corrections into Word's custom dictionary (not the auto-correct list). It might even be possible to do this on a per-document basis.
I’ll look into the possibility of somehow getting those TE corrections into Word’s custom dictionary. Not quite sure how that’ll be possible as TE doesn’t seem to make it easy to extract information. Like I said, I don’t know beans about AppleScripts.
Hey JustRed, all of us were in that position at some point in our life. What motivated many of us to learn AppleScript was the need to automate something like your project. It's a matter of having the right demand (need for something), and the time available to invest in learning a new tool. The payback is huge.
If you are interested in learning AppleScript, then:
If you don't have TextWrangler on your system then download and install it.
Open TextWrangler.
Open the Script Editor.app.
Paste in the AppleScript below.
Run the script.
It'll take a couple or three minutes to complete.
-Chris
-------------------------------------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2016/02/25 16:39
# dMod: 2016/02/25 16:39
# Appl: TextExpander
# Task: Export TextExpander Snippets to TextWrangler
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Export, @TextExpander, @Snippets, @TextWrangler
-------------------------------------------------------------------------------------------
set _sep to "------------------------------------------------------------------"
set docSaveLocation to (path to desktop as text) & "TextExpander_Export.txt"
tell application "TextWrangler"
if not running then run
delay 1
activate
set newDoc to make new text window with properties {bounds:{0, 44, 905, 1196}} initial save location docSaveLocation
save newDoc's document
end tell
tell application "TextExpander"
set groupNameList to name of every group
repeat with theGroup in groupNameList
set _name to _sep & return & (contents of theGroup) & space & "Snippet Group" & return & _sep & return & return
textwranglerSetNamedDocText(1, _name, "append", "don't activate") of me
tell group theGroup
repeat with theSnippet in snippets
set theSnippetText to theSnippet's abbreviation & tab & theSnippet's plain text expansion & return
textwranglerSetNamedDocText(1, theSnippetText & return, "append", "don't activate") of me
end repeat
end tell
end repeat
end tell
-------------------------------------------------------------------------------------------
--» HANDLERS
-------------------------------------------------------------------------------------------
on textwranglerSetNamedDocText(_document, _text, _append, _activate)
tell application "TextWrangler"
if _document = 0 or _document = "new" then
set newDoc to make new document with properties {text:_text, bounds:{303, 44, 1617, 1196}}
else if _append = true or _append = "append" or _append = 1 then
set after text of text document _document to _text
end if
if _activate = 1 or _activate = "activate" then activate
end tell
end textwranglerSetNamedDocText
-------------------------------------------------------------------------------------------
I got interested in this as a learning exercise, and I have written the below script which should give you a big jumpstart.
I took a completely different approach from what I suggested earlier:
It is 100% AppleScript
It loads your MS Word document into a AppleScript variable, which is a list of words (defined as being separated by a space
It then uses each word to lookup a snippet in TextExpander
If it finds a snippet, it returns the plain text expansion of the snippet.
AND, the final step will be for you to complete:
Use the MS Word Find and Replace method to find the word, and replace with the snippet returned in step #4.
To get started:
Open a COPY of your Word doc to be used for testing
Open the Script Editor and paste in the below code
(be sure to change the language to "AppleScript"
Compile the code (CMD-K)
SAVE the script (CMD-S)
RUN the script (CMD-R)
You will see the results at the bottom of the script window. You may need to click on the the rectangle that looks like a note: , and then on the button.
I think this will run quite fast. The script has a timer in it, so you can see how long it takes. In my test, it processed 186 words in 0.6 sec. The lookup of the snippet in TE using AppleScript seems quite fast.
To write the AppleScript for the MS Word Find & Replace, you can start by doing a google on "microsoft word AppleScript replace". To learn the MS Word object model, open its scripting dictionary in Script Editor: CMD-SHIFT-O, then scroll down to "Microsoft Word", and double click on it.
If you have any questions along the way, just post here, and I'm sure either I or @ccstone (Chris) will answer.
Good luck, and let us know how it goes.
@ccstone, please jump in if you see any issues, or have suggestions for improvement.
(*
===============================================================================
[WORD] Replace Abbreviations in Word Doc with TextExpander Snippet
===============================================================================
VER: 1.0 LAST UPDATE: 2016-02-25
PURPOSE:
• Process every word in a MS Word document, and replace with the Snippet
plain text expansion in TextExpander, IF the word exists as an Abbreviation.
AUTHOR: JMichaelTX
Find any bugs/issues or have suggestions for improvement?
Contact me via PM or at blog.jmichaeltx.com/contact/
REQUIRED:
1. Mac OS X Yosemite 10.10.5+
2. Mac Applications
• Microsoft Word 2011 Mac
• TextExpander 5.1.4
3. EXTERNAL OSAX Additions/LIBRARIES/FUNCTIONS
• NONE
4. INTERNAL FUNCTIONS:
• on getTESnippet(pAbbreviationStr)
• on collapseList(pMultiList)
• on splitStrToList(pString, pDelim)
• on joinListToStr(pList, pDelim)
• on continueScript(pMsgStr)
• on timer(pAction)
• on trimThis(pstrSourceText, pstrCharToTrim, pstrTrimDirection)
REF: The following were used in some way in the writing of this script.
1.
===============================================================================
*)
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
timer("start")
tell application "Microsoft Word"
tell active document
set theContent to content of text object
--log theContent
set contentParagraphs to paragraphs of theContent
set {astid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, " "}
set theContent to contentParagraphs as text
--log theContent
--set wordList to my splitStrToList(theContent, linefeed)
--set theContent to my joinListToStr(wordList, " ")
set wordList to my splitStrToList(theContent, " ")
set numWords to count of wordList
log "numWords: " & numWords
repeat with iWord from 1 to numWords
set wordStr to item iWord of wordList
set wordStr to my trimThis(wordStr, true, "full")
if wordStr ≠ "" then
--log "[" & iWord & "]: " & "WORD: " & wordStr
set snippetStr to my getTESnippet(wordStr)
else
set snippetStr to ""
end if
--- REPLACE ABBREVIATION IN WORD DOC IF FOUND ---
if snippetStr ≠ "" then
log ("[" & iWord & "]: " & "ABBREVIATION FOUND: " & wordStr)
display notification ¬
"Replacing Abbreviation in Word Doc with TE Expansion" with title (name of me)
--- FIND & REPLACE IN WORD DOC ---
#### TODO: ADD CODE FOR FIND & REPLACE ###
end if
end repeat -- Word List
end tell
end tell
timer("STOP")
###———————————— END OF MAIN SCRIPT —————————————————————
###~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# getTESnippet() Get Plain Text Expansion of TextExpander Snippet
#
# Ver 1.0 2016-02-25
###——————————————————————————————————————————————————————————————————————————————————
on getTESnippet(pAbbreviationStr)
--log "getTESnippet() called with: " & pAbbreviationStr
tell application "TextExpander"
if pAbbreviationStr ≠ "" then
set abbStr to pAbbreviationStr -- Example:";km"
set snippetMultiList to every snippet of every group whose abbreviation is abbStr
set snippetList to my collapseList(snippetMultiList)
if snippetList ≠ {} then
set oSnippet to item 1 of snippetList ### ASSUMES only 1 matching Snippet
set snippetStr to plain text expansion of oSnippet ---> THIS is what I'm after.
else
set snippetStr to "" -- IF Snippet NOT Found, set to empty string
end if
else
set snippetStr to ""
end if -- pAbbreviationStr ≠ ""
end tell -- TextExpander
return snippetStr
end getTESnippet -- function getTESnippet
###~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
###~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# collapseList() Collapse List of Lists to One List with NO Empty Items
#
# Ver 1.0 2016-02-25
###——————————————————————————————————————————————————————————————————————————————————
on collapseList(pMultiList)
set singleList to {}
repeat with ndx1 in pMultiList
if contents of ndx1 is not {} then
repeat with ndx2 in ndx1
set end of singleList to contents of ndx2
end repeat -- ndx2
end if
end repeat -- ndx1
set pMultiList to {}
return singleList
end collapseList
###~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
on splitStrToList(pString, pDelim)
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set textDelimSave to AppleScript's text item delimiters
set AppleScript's text item delimiters to pDelim
set newList to text items of pString
set AppleScript's text item delimiters to textDelimSave
return newList
end splitStrToList
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
on joinListToStr(pList, pDelim)
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set textDelimSave to AppleScript's text item delimiters
set AppleScript's text item delimiters to pDelim
set newString to pList as string
set AppleScript's text item delimiters to textDelimSave
return newString
end joinListToStr
###——————————————————————————————————————————————
# continueScript() Prompt User to Continue or Not
#
# Ver 2.1 2016-02-21
###——————————————————————————————————————————————
on continueScript(pMsgStr)
beep
set titleStr to (name of me) & "
" & pMsgStr & "
" & "Continue or Cancel?"
set recAns to (display alert titleStr as critical ¬
buttons {"Cancel", "Continue"}) -- last button is default
set strAns to button returned of recAns
if (strAns = "Continue") then
set continueBol to true
else
set continueBol to false
end if
return continueBol
end continueScript
###——————————————————————————————————————————————
###——————————————————————————————————————————————
# timer() Calculate and Log Execution Time
#
# Ver 1.0 2016-02-21
#
# REF: The base ASObjC code was provided by Shane Stanley
###——————————————————————————————————————————————
on timer(pAction)
(*
### Requires these two statements at top of main script: ###
use scripting additions
use framework "Foundation"
*)
global gTimerStartDate
if (pAction = "start") then
set gTimerStartDate to current application's NSDate's |date|()
log "START: " & ((current date) as text)
else
log pAction & ":
• " & ((current date) as text) & "
• EXECUTION TIME: " & (round (-(gTimerStartDate's timeIntervalSinceNow())) * 1000) / 1000.0 & " sec"
end if
end timer
###~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# trimThis() Trim (remove) Characters from Left and/or Right of String
#
# Ver 1.0 2016-02-25
# AUTHOR: Shane Stanley
# REF: MacScripter / Trim [Remove Spaces]
# http://macscripter.net/viewtopic.php?pid=182209#p182209
# PARAMETERS:
# • pstrCharToTrim : A list of characters to trim, or true to use default
# • pstrSourceText : The text to be trimmed
# • pstrTrimDirection : Direction of Trim left, right or any value for full
###——————————————————————————————————————————————————————————————————————————————————
on trimThis(pstrSourceText, pstrCharToTrim, pstrTrimDirection)
if pstrCharToTrim = missing value or pstrCharToTrim = true then
-- SPACE, TAB, RETURN, newline characters (U+000A–U+000D, U+0085)
-- Equiv to: ASCII character 10, return, ASCII character 0
set setToTrim to current application's NSCharacterSet's whitespaceAndNewlineCharacterSet()
else
set setToTrim to current application's NSCharacterSet's characterSetWithCharactersInString:pstrCharToTrim
end if
set anNSString to current application's NSString's stringWithString:pstrSourceText
if pstrTrimDirection = left then
set theRange to anNSString's rangeOfCharacterFromSet:(setToTrim's invertedSet())
if |length| of theRange = 0 then return ""
set anNSString to anNSString's substringFromIndex:(theRange's location)
else if pstrTrimDirection = right then
set theRange to anNSString's rangeOfCharacterFromSet:(setToTrim's invertedSet()) options:(current application's NSBackwardsSearch)
if |length| of theRange = 0 then return ""
set anNSString to anNSString's substringToIndex:(theRange's location)
else
set anNSString to anNSString's stringByTrimmingCharactersInSet:setToTrim
end if
return anNSString as text
end trimThis
###~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Once again Satimage surfaces.
So Chris, are you using any custom GUIs? I was reading the Satimage documentation and it appears they offer some tools for making them.
This verges on making Apps and the GUI windows look like some windows I have seen before.