2
votes

My object is simple - I want a shortcut to replace text in a selection with uppercase characters, without applying the "AllCaps" style, for reasons I won't go into here.

I have succeeded by using Selection.Delete and Selection.Insert, but that doesn't seem to preserve font styles not inherent to the paragraph style.

When I try using VBA Selection.Find.Execute:=ReplaceAll, it is replacing all instances in the entire document. I am aware that this should be the behavior for .wrap=wdFindContinue, but I have set .wrap=wdFindStop. My best guess is that because my .text is set as a variable that calls the Selection object, it loses the selection somehow when setting .text (although visually this is not apparent when I step through the code - selection stays highlighted), resulting in .ReplaceAll executing for the whole document. If I manually enter the "find" (.text) string for a particular case, it executes on the selection only (even with the variable txt called in the .Replacement.Text field!), but obviously that won't be practical.

Here is my code:

Option Explicit
Sub ReplaceWithUppercase()

Dim pasteAutoFormatSetting As Boolean
Dim txt As String
'Save current user selection of whether to adjust spacing automatically when pasting:
pasteAutoFormatSetting = Options.PasteAdjustWordSpacing

'Turn off auto spacing adjustment:
Options.PasteAdjustWordSpacing = False

txt = Selection.Range.text


With Selection.Font
        .AllCaps = False
End With

'The next two lines work but do not seem to preserve built-in font styles
'already applied to the selected text, so I wanted to instead use find/replace:

'Selection.Range.Delete
'Selection.Range.InsertAfter (UCase(txt))


    With Selection.Range.Find
        .ClearFormatting
        .Replacement.ClearFormatting
        .text = txt
        .Replacement.text = UCase(txt)
        .Forward = True
        .Wrap = wdFindStop
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchAllWordForms = False
        .MatchSoundsLike = False
        .MatchWildcards = True
        .Execute Replace:=wdReplaceAll
    End With

'Return to user preference for auto apacing adjustment:
Options.PasteAdjustWordSpacing = pasteAutoFormatSetting

End Sub
3

3 Answers

1
votes

Fast work using an array for selection range - and the StrConv function

Sub ChangeRangeToUCase()
    Const vbUpperCase = 1 ' strConv constant

    Dim arrCells    As Variant
    Dim intRow      As Integer
    Dim intCol      As Integer

    ' Assign Range to an array
    arrCells = Selection
    For intRow = LBound(arrCells, 1) To UBound(arrCells, 1)
        For intCol = LBound(arrCells, 2) To UBound(arrCells, 2)
            arrCells(intRow, intCol) = StrConv(arrCells(intRow, intCol), vbUpperCase)
        Next intCol
    Next intRow

    Selection = arrCells

End Sub
1
votes

@PatentWookiee, I think you were on the right track initially with,

Selection.Range.Delete
Selection.Range.InsertAfter (UCase(txt))

The problem is, once you delete your selected text, anything you put in its place will assume the formatting of the first character prior to your deletion. To solve this problem you'll want to go with:

Option Explicit
Sub ReplaceWithUppercase()
    Selection.Text = UCase(Selection.Text)
End Sub

Instead of replacing the actual text (and the formatting along with it) we simply replace the case of the selected string, thus leaving your formatting fully intact. If I've read your question right, this should fully solve your problem. If not, be sure to let me know, we'll work through it.

0
votes

With help from the macro recorder we find:

    Sub ChangeSelectionToUCase()
        ' MsgBox Selection.Range.text
        Selection.Range.Case = wdUpperCase
        ' MsgBox Selection.Range.text
    End Sub

Would that be acceptable? It certainly looks a lot easier. The OP is concerned about not using the "AllCapsStyle". But using the lines commented out, we can convince ourselves that the text in the document is really changed to uppercase, not just its visual appearance ("style").