View Full Version : [SOLVED:] Replace specific characters in a selection
Jennifer
02-11-2017, 02:55 PM
I am having a little trouble writing a macro that will replace specific individual characters in a selection with corresponding characters from another string. For example, if I wanted to replace all occurrences of the first 5 letters with the next letter in the alphabet ('a' -> 'b', 'b' -> 'c', 'c' -> 'd', etc.), I might define
Alphabet1 = "ABCDEabcde"
Alphabet2 = "BCDEFbcdef"
Then I need some code to step through the selection character by character, look it up in Alphabet1, and, if it is found, replace it with the corresponding character in Alphabet2.
Here's what I have so far. It works for 1 iteration, but on the second iteration, the Selection.Characters statement gets a run-time 5941 error. If I comment it out, as shown below, the rest of the loop works correctly.
I suspect that that statement is somehow changing the selection to just the first character, but I don't know what to do about it.
Dim String1 As String   'The original text
Dim StrNdx As Long      'The loop index
Dim CharNdx As Long     'The character index in Alphabet1
Dim NextChar1 As String 'The next character from the source string
Dim NextChar2 As String 'The replacement character from Alphabet2
String1 = Selection.Range       'Get the source string
For StrNdx = 1 To Len(String1)                'Loop through the source characters
  NextChar1 = Mid(String1, StrNdx, 1)           'Get the next source character
  CharNdx = InStr(Alphabet1, NextChar1)         'Get its index in Alphabet1
  If CharNdx > 0 Then                           'If it's in the alphabet,
    NextChar2 = Mid(Alphabet2, CharNdx, 1)        'Get coded character
    MsgBox "Replace (" & NextChar1 & ") with (" & NextChar2 & ")"
'   Selection.Characters(StrNdx).Text = NextChar2 'Store it in the document
  End If                                        'Otherwise, leave it alone (skip it)
Next StrNdx
gmaxey
02-11-2017, 05:40 PM
It is not clear to me what you are trying to do.  Maybe:
Sub ScratchMacro()
'A basic Word macro coded by Greg Maxey
Const Alphabet1 As String = "ABCDEabcde"
Const Alphabet2 As String = "BCDEFbcdef"
Dim strSel As String
Dim lngIndex As Long
Dim CharNdx As Long 'The character index in Alphabet1
Dim strChr As String 'The next character from the source string
Dim strChrRplc As String 'The replacement character from Alphabet2
Dim oRng As Range
  Set oRng = Selection.Range.Duplicate
  strSel = Selection.Range.Text 'Get the source string
  For lngIndex = 1 To Len(strSel) 'Loop through the source characters
    strChr = Mid(strSel, lngIndex, 1)
    CharNdx = InStr(Alphabet1, strChr) 'Get its index in Alphabet1
    If CharNdx > 0 Then
        strChrRplc = Mid(Alphabet2, CharNdx, 1) 'Get coded character
        oRng.Characters(lngIndex) = strChrRplc
        MsgBox "Replace (" & strChr & ") with (" & strChrRplc & ")"
     End If
  Next lngIndex
lbl_Exit:
  Exit Sub
End Sub
Jennifer
02-12-2017, 01:26 AM
It is not clear to me what you are trying to do.
I'm trying to write a little macro that will encrypt letters to my grandkids with a simple replacement code that they might have fun trying to decode.
What does this instruction do, especially the .Duplicate?
Set oRng = Selection.Range.Duplicate
I came up with something similar, but instead of 
oRng.Characters(lngIndex) = strChrRplc
I had
Selection.Characters(lngIndex).Text = strChrRplc
What's the difference? Mine seemed to reset the selection so that the subscript was out of range. Yours doesn't seem to do that. Is that because of the .Duplicate parameter?
PS: What the heck is this "mark007" comment?
gmaxey
02-12-2017, 01:56 AM
Well in this case you don't' really need .duplicate.  This works just as well:
Sub ScratchMacro()
'A basic Word macro coded by Greg Maxey
Const Alphabet1 As String = "ABCDEabcde"
Const Alphabet2 As String = "BCDEFbcdef"
Dim strSel As String
Dim lngIndex As Long
Dim CharNdx As Long 'The character index in Alphabet1
Dim strChr As String 'The next character from the source string
Dim strChrRplc As String 'The replacement character from Alphabet2
Dim oRng As Range
  Set oRng = Selection.Range
  strSel = Selection.Range.Text 'Get the source string
  For lngIndex = 1 To Len(strSel) 'Loop through the source characters
    strChr = Mid(strSel, lngIndex, 1)
    CharNdx = InStr(Alphabet1, strChr) 'Get its index in Alphabet1
    If CharNdx > 0 Then
      strChrRplc = Mid(Alphabet2, CharNdx, 1) 'Get coded character
      oRng.Characters(lngIndex) = strChrRplc
      MsgBox "Replace (" & strChr & ") with (" & strChrRplc & ")"
    End If
  Next lngIndex
lbl_Exit:
  Exit Sub
End Sub
Yours falls over because you destroy the selection as soon as  you use Selection.Characters(lngIndex).Text
Select some text and step through this:
Sub ScratchMacro()
'A basic Word macro coded by Greg Maxey
Dim lngIndex As Long
Dim oRng As Range
  Set oRng = Selection.Range
  For lngIndex = 1 To Selection.Characters.Count
    On Error GoTo Err_Handler
    Selection.Characters(lngIndex).Text = "A"
Err_ReEntry:
  Next
lbl_Exit:
  Exit Sub
Err_Handler:
  Debug.Print Err.Number & " " & Err.Description
  oRng.Characters(lngIndex) = "A"
  Resume Err_ReEntry
End Sub
 
I suppose Mark is the fellow that created the code tags.
Jennifer
02-12-2017, 08:26 AM
Well in this case you don't' really need .duplicate.
OK, but what does .duplicate do?
Yours falls over because you destroy the selection as soon as  you use Selection.Characters(lngIndex).Text
Why does mine reset the selection and yours does not? What is different about how the two instructions work?
Thanks
gmaxey
02-12-2017, 08:42 AM
Well the documentation says this:
Word Developer Reference
Range.Duplicate Property
Returns a read-only Range object that represents all the properties of the specified range.Syntax
expression.Duplicate
expression   Required. A variable that represents a Range (http://www.vbaexpress.com/forum/HV10329911.htm) object.
Remarks
By duplicating a Range object, you can change the starting or ending character position of the duplicate range without changing the original range.
© 2010 Microsoft Corporation. All rights reserved. (http://www.vbaexpress.com/forum/HV10323630.htm)
Here is a practical example of how I use it.  In a new blank document, type about ten X's e.g., *********X.  Then select the first 5.  Run this code.
Sub ScratchMacroI()
'A basic Word macro coded by Greg Maxey
Dim oRng As Word.Range
  Set oRng = Selection.Range
  With oRng.Find
    .Text = "X"
    While .Execute
      oRng.Text = "Y"
      oRng.Collapse wdCollapseEnd
    Wend
  End With
lbl_Exit:
  Exit Sub
End Sub
The goal is to replace the 5  Xs selected with Ys.  That is not the outcome.  Repeat using this code:
Sub ScratchMacroII()
'A basic Word macro coded by Greg Maxey
Dim oRng As Word.Range, oRngChk As Range
  Set oRng = Selection.Range
  Set oRngChk = oRng.Duplicate
  With oRng.Find
    .Text = "X"
    Do While .Execute
       If oRng.InRange(oRngChk) Then
         oRng.Text = "Y"
         oRng.Collapse wdCollapseEnd
       Else
         Exit Do
       End If
    Loop
  End With
lbl_Exit:
  Exit Sub
End Sub
Your version falls over as I explained in my last post.
Jennifer
02-12-2017, 09:22 AM
Well the documentation says this:
What is the Developer Reference? Is it a hard copy book or is it online where I can access it?
I found these online:
 https://msdn.microsoft.com/en-us/library/office/gg264383(v=office.15).aspx Office 2013 and later 
 https://msdn.microsoft.com/en-us/library/office/gg264383(v=office.14).aspx Office 2010 (not maintained) 
 
I found these on Amazon:
 https://www.amazon.com/dp/0782129781/ VBA Developers Handbook, 2nd Edition (Getz) 
 https://www.amazon.com/dp/1565923588/ VB & VBA in a Nutshell: Language (O'Reilly) 
 https://www.amazon.com/dp/0470634006/ Mastering VBA for Office 2010 (Richard Mansfield) 
Here is a practical example of how I use it.  In a new blank document, type about ten X's e.g., *********X.  Then select the first 5.  Run this code.
I'll play around with this. Thanks.
gmaxey
02-12-2017, 09:37 AM
Select the "Duplicate"  (or whatever you want information on) and press F1
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.