Help with a multiple text replacement script

Even though this forum so far has been for sharing scripts and not for writing them, I was wondering if I could pick the brains of AHK experts ( and  come to mind right now), to figure something out.

I'm trying to put together a script to do multiple text replacements at a segment level, i.e., for the active segment only, so I can easily see what has been changed, without calling up the Find & Replace window.

I've managed to put together this script (silly examples included):

#r::
ClipSaved := ClipboardAll
Clipboard =
SendInput, ^a^c
ClipWait, 30
FixString := Clipboard
vList := " ;continuation section
(
dog perro

house casa
¿ ¿
/ /
, ,
? ?
. .
pie 2 pie2
m 2 m2
)"
Loop, Parse, vList, `n
{
oTemp := StrSplit(A_LoopField, "`t")
FixString := StrReplace(FixString, oTemp.1, oTemp.2)
}
oTemp := ""
Clipboard := FixString ; load the new string to clipboard
Sleep 200
Send ^v
Return

This works fine in segments with no tags, but when there are tags, they get stripped at some point during the replacement operation and the text that is pasted back into the segment has all the necessary replacements but no tags. Is there any way of preserving the tags in the clipboard?

I came up with a very clumsy workaround for this, which involves using Studio's Delete to Next Tag shortcut, so instead of Select All-Copy, the script would do Delete to Next Tag-Undo-Copy:

#r::
ClipSaved := ClipboardAll
Clipboard =
;SendInput, ^a^c
;ClipWait, 30
Send ^+D ;delete to next tag
Sleep 100
Send ^z ;undo
Sleep 50
Send ^c
ClipWait, 30
FixString := Clipboard
vList := " ;continuation section
(
organisation organization
¿ ¿
/ /
, ,
? ?
. .
pie 2 pie2
m 2 m2
)"
Loop, Parse, vList, `n
{
oTemp := StrSplit(A_LoopField, "`t")
FixString := StrReplace(FixString, oTemp.1, oTemp.2)
}
oTemp := ""
Clipboard := FixString ; load the new string to clipboard
Sleep 200
Send ^v
Return

While this also works in segments with no tags, I would like to optimize it.

My second question is: how would I go about creating a list of all these replacements (CSV? Excel?) and getting the script to take them from there instead of having to add them manually to the script? I've been reading up on arrays but I'm still far away from being able to implement what I need.

I have another simpler script attempt with just multiple StringReplace lines (see below), but again, that would require creating possibly hundreds of replacement lines and I imagine it's not the best solution.

#p:: 
Send, ^a
Send, ^c
StringReplace, clipboard, clipboard, dog, perro, All
StringReplace, clipboard, clipboard, cat, gato, All
StringReplace, clipboard, clipboard, raining, lloviendo, All
Send ^v
Return

So, any help with this would be greatly appreciated.

Thank you!

Parents
  • Hello Nora Díaz,

    I know nothing about writing lines to make a script to work. And I am so glad that I found your script which actually saves me a lot of time of working. Thank you so much for this!!

    I mean this one:

    #p::
    Send, ^a
    Send, ^c
    StringReplace, clipboard, clipboard, dog, perro, All
    StringReplace, clipboard, clipboard, cat, gato, All
    StringReplace, clipboard, clipboard, raining, lloviendo, All
    Send ^v
    Return

    But I got a problem when I try this line: StringReplace, clipboard, clipboard, cto, Chief Technology Officer, All

    My wish is to expand the short "CTO" to full "Chief Technology Officer" every I meet the short word.
    But this sentence: "Director, cto" will become "DireChief Technology Officerr, Chief Technology Officer" because there is "cto" in the word "director" and I don't know how to fix this.

    Could you help me please??
    Thank you so much!!

  • Try with this:

    SendMode, Input

    ; -- Win + p -> Select all text + replace whole word only

    #p::
    Search := "cto"
    Replace := "Chief Technology Officer"
    Gosub, CheckKeysPressed
    Send, ^a
    Gosub, SelectToClip
    Clipboard := RegExReplace(Clipboard, "i)\b" Search "\b", Replace)
    Send, ^v
    Return

    SelectToClip:
    Clipboard := ""
    Send, ^c
    ClipWait, 0
    If ErrorLevel
        Exit
    Sleep, 50
    Return

    CheckKeysPressed:
    While GetKeyState("Ctrl","P") || GetKeyState("LWin","P") || GetKeyState("RWin","P") || GetKeyState("Shift","P") || GetKeyState("Alt","P")
        Sleep, 25
    Return
  • Many many thanks Rafa Gómez !!!
    It works perfectly!!
    I have a list of hundred words such as "cmo" for "Chief Marketing Officer", "&" for "and", "mba" for "Master of Business Administration"... Can you show me how to put more words to your script please?

    And I am using this script, it helps me to capitalize every words except "and, a, an,in....". I tried to combine your script (the one you just wrote for me) with the one I am using but it didn't work.

    ^+SPACE::
    Send, ^a
    Send, ^x
    StringUpper str, Clipboard, T
    head := SubStr( str, 1 , 1 )
    tail := SubStr( str, 2 )
    Clipboard := head RegExReplace( tail , "i)\b(a|an|and|in|the|with|of)\b", "$L1")
    StringReplace, clipboard, clipboard, &, and, All
    StringReplace, clipboard, clipboard, svp, Senior Vice President, All
    StringReplace, clipboard, clipboard, vp, Vice President, All
    StringReplace, clipboard, clipboard, mba, Master of Business Administration, All
    StringReplace, clipboard, clipboard, r&d, Research and Development, All
    StringReplace, clipboard, clipboard, m&a, Mergers and Acquisitions, All
    StringReplace, clipboard, clipboard, mena, Middle East and North Africa, All
    StringReplace, clipboard, clipboard, cfo, Chief Financial Officer, All
    StringReplace, clipboard, clipboard, ceo, Chief Executive Officer, All
    StringReplace, clipboard, clipboard, co-head, Co-Head, All
    Send ^v
    RETURN

    ****For the final result, my wish is the ability to do something like this:

    - From: vice president of r&d, japan & singapore
    - or: vp of r&d, japan & singapore

    Can transform immediately into:

    - Vice President of Research and Development, Japan and Singapore
    with just one key press.

    Please have a look and help me if you have spare time.

    I am truly appreciate your help.
    Thank you so much!!

  • [update]

    It has a small issue when I try

    north america     NA

    United States     US

    U.S.                   US

    The outcome are Na and Us. How can we make it all capital letters for those terms?

    and can I replace - (hyphen or dash) into , (comma)?

    Thank you!

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

    Dear Rafa Gómez,

    This script really works like a charm.

    Thank you so much (from me and six of my team members).

    I know that it pretty too much of asking but can you do one final favor please? This I just think of a moment ago so I couldn't put it into the previous post (my apologies for that)

    This time, I would like to keep the work smoothly and continuously by adding this line, so I don't need to change windows to paste then press #p and again and again with that loop.

    Send, {CTRLDOWN}c{CTRLUP}{ALTDOWN}{TAB}{ALTUP}{CTRLDOWN}v{CTRLUP}{ENTER}

    I tried to put it in your script but couldn't get it to work.

    Please show me how to do it.

    Many thanks to you!!!

Reply Children
  • Thanks a lot Rafa Gómez!! I'm in love with your kindness in helping me this much!

    I just want to let you know that before asking you here, I had tried to search and to test by any means that I could, and I'm glad that I'm getting better with understanding these lines, yet still not enough.

    For WindowSpy I already searched for it and tested it successfully however only with different programs (one program and another).
    My main tool for working are: 2 monitors, one Chrome on the left and one on the right, I copy data from right one then paste to the left one.
    So the problem is they are the same program: Chome (ahk_class Chrome_WidgetWin_1). I can't figure out how to use WinActive in this case. I searched on internet and found this script:


    CoordMode, Pixel, Screen

    !1::
    ChromeList := GetWinListByClass("Chrome_WidgetWin_1")

    LeftmostPos := 9999
    LeftmostId := ""
    Loop, % ChromeList.MaxIndex()
    {
    currentId := ChromeList[A_Index][1]
    currentX := ChromeList[A_Index][2]

    if (currentX < LeftmostPos)
    {
    LeftmostPos := currentX
    LeftmostId := currentId
    }
    }

    WinActivate, % "ahk_id" LeftmostId
    Return

    !2::
    ChromeList := GetWinListByClass("Chrome_WidgetWin_1")

    RightmostPos := -9999
    RightmostId := ""
    Loop, % ChromeList.MaxIndex()
    {
    currentId := ChromeList[A_Index][1]
    currentX := ChromeList[A_Index][2]

    if (currentX > RightmostPos)
    {
    RightmostPos := currentX
    RightmostId := currentId
    }
    }

    WinActivate, % "ahk_id" RightmostId
    Return


    GetWinListByClass(filterClass)
    {
    WinGet, all, list
    ChromeList := {}
    winCount := 1
    Loop, %all%
    {
    WinGetClass, WClass, % "ahk_id " all%A_Index%
    if (WClass = filterClass)
    {
    winId := all%A_Index%
    WinGetPos, X, Y, W, H, % "ahk_id " winId
    ChromeList[winCount] := [winId, X]
    winCount++
    }
    }
    return ChromeList
    }

    but when I add more lines for sending texts (combine with this), this script doesn't work very well.
    What is your method to switch windows of the same program please?

    Many thanks!