【问题标题】:Getting wildcards to work in find and replace function in VBA macro for Microsoft Word让通配符在 Microsoft Word 的 VBA 宏中的查找和替换功能中起作用
【发布时间】:2010-11-29 03:34:56
【问题描述】:

我有一个用于 Microsoft Word 的 VBA 宏,我正在努力改进。

宏的目的是将文档中与文档第一个表中的搜索词匹配的所有单词加粗和斜体。

问题是搜索词包含以下通配符:

连字符“-”:字母之间的通配符表示空格或句点

星号“&”:(该网站不允许我输入星号,因为这是斜体的降价,所以我将输入 & 符号来绕过过滤器)任意数量的字符的通配符词首或词尾。然而,与普通编程语言不同的是,当它用于单词的中间时,它需要与连字符组合成为一系列字符的通配符。例如,“th&-e”会选择“there”,而“th&e”则不会。

问号“?”:单个字符的通配符

到目前为止,我所做的只是测试这些字符,如果它们存在,我要么在星号的情况下将它们去掉,要么提醒用户他们必须手动搜索单词。不理想:-P

我已经在 VBA 中尝试了 .MatchWildcard 属性,但还没有让它工作。我感觉它与替换文本有关,而不是搜索文本。

工作宏将以下内容作为其输入(第一行被有意忽略,第二列是带有目标搜索词的行):

在第二列中的表格中想象一下(因为此处允许的 html 不允许 tr 和 td 等)

第一行:单词
第二行:搜索
第三行:&earch1
第四行:Search2&
第五排:S-earch3
第六行:S?arch4
第七行:S&-ch5

它将搜索文档并替换为粗体和斜体内容,如下所示:

搜索 Search1 Search2 Search3 Search4 Search5

注意:S-earch3 也可以选择 S.earch3 并替换为 Search3

正如人们可能假设的那样,搜索词通常不会彼此相邻 - 宏应该找到所有实例。

我将在第一个工作宏之后包含我尝试过但没有功能的代码。

工作宏的代码将从今天(2009 年 9 月 17 日)开始在 pastebin 上保存一个月,地址如下:url

再次感谢您提供的任何想法和帮助!

萨拉

工作 VBA 宏:

Sub AllBold()

Dim tblOne As Table

Dim celTable As Cell

Dim rngTable As Range

Dim intCount As Integer

Dim celColl As Cells

Dim i As Integer

Dim rngLen As Integer

Dim bolWild As Boolean

Dim strWild As String


Set tblOne = ActiveDocument.Tables(1)

intCount = tblOne.Columns(2).Cells.Count

Set celColl = tblOne.Columns(2).Cells

strWild = ""

For i = 1 To intCount

    If i = 1 Then

    i = i + 1

    End If

    Set celTable = ActiveDocument.Tables(1).Cell(Row:=i, Column:=2)

    Set rngTable = ActiveDocument.Range(Start:=celTable.Range.Start, _
        End:=celTable.Range.End - 1)

    rngLen = Len(rngTable.Text)

    bolWild = False

    If (Mid(rngTable.Text, rngLen, 1) = "&") Then 'remember to replace & with asterisk!'

    rngTable.SetRange Start:=rngTable.Start, End:=rngTable.End - 1

    End If

    If (Mid(rngTable.Text, 1, 1) = "&") Then 'remember to replace & with asterisk!'

    rngTable.SetRange Start:=rngTable.Start + 1, End:=rngTable.End

    End If

    If InStr(1, rngTable.Text, "-", vbTextCompare) > 0 Then

    strWild = strWild + rngTable.Text + Chr$(13)

    bolWild = True

    End If

    If InStr(1, rngTable.Text, "?", vbTextCompare) > 0 Then

    strWild = strWild + rngTable.Text + Chr$(13)

    bolWild = True

    End If

    If (bolWild = False) Then

        Dim oRng As Word.Range

            Set oRng = ActiveDocument.Range

            With oRng.Find

            .ClearFormatting

            .Text = rngTable.Text

            With .Replacement

            .Text = rngTable.Text

            .Font.Bold = True

            .Font.Italic = True

            End With

            .Execute Replace:=wdReplaceAll

    End With

    End If

Next

If bolWild = True Then

MsgBox ("Please search the following strings with - or ? manually:" + Chr$(13) + strWild)

End If

End Sub

尝试过的非功能性 VBA 宏:

Sub AllBoldWildcard()

Dim tblOne As Table

Dim celTable As Cell

Dim rngTable As Range

Dim intCount As Integer

Dim celColl As Cells

Dim i As Integer

Dim rngLen As Integer

Dim bolWild As Boolean

Dim strWild As String

Dim strWildcard As String


Set tblOne = ActiveDocument.Tables(1)

intCount = tblOne.Columns(2).Cells.Count

Set celColl = tblOne.Columns(2).Cells

strWild = ""

For i = 1 To intCount

    If i = 1 Then

    i = i + 1

    End If

    Set celTable = ActiveDocument.Tables(1).Cell(Row:=i, Column:=2)

    Set rngTable = ActiveDocument.Range(Start:=celTable.Range.Start, _
        End:=celTable.Range.End - 1)

    rngLen = Len(rngTable.Text)

    bolWild = False

    If (Mid(rngTable.Text, 1, 1) = "&") Then 'remember to replace & with asterisk!'

    rngTable.SetRange Start:=rngTable.Start + 1, End:=rngTable.End

    End If

    If InStr(1, rngTable.Text, "&", vbTextCompare) > 0 Then 'remember to replace & with asterisk!'

    strWildcard = rngTable.Text

    rngTable.Text = Replace(rngTable.Text, "&", "", 1) 'remember to replace & with asterisk!'

    bolWild = True

    End If

    If InStr(1, rngTable.Text, "-", vbTextCompare) > 0 Then

    strWildcard = Replace(rngTable.Text, "-", "[.-]", 1)

    bolWild = True

    End If

    If InStr(1, rngTable.Text, "?", vbTextCompare) > 0 Then

    strWild = strWild + rngTable.Text + Chr$(13)

    strWildcard = Replace(rngTable.Text, "?", "_", 1)


    bolWild = True

    End If

    If (bolWild = False) Then

        Dim oRng As Word.Range

            Set oRng = ActiveDocument.Range

            With oRng.Find

            .ClearFormatting

            .Text = strWildcard

            .MatchAllWordForms = False

            .MatchSoundsLike = False

            .MatchFuzzy = False

            .MatchWildcards = True


            With .Replacement

            .Text = rngTable.Text

            .Font.Bold = True

            .Font.Italic = True

            End With

            .Execute Replace:=wdReplaceAll

    End With

    End If

Next

'    If bolWild = True Then'

'    MsgBox ("Please search the following strings with - or ? manually:" + Chr$(13) + strWild)'

'    End If'

End Sub

【问题讨论】:

    标签: vba replace ms-word wildcard


    【解决方案1】:

    也许 LIKE 语句可以帮助你:

    if "My House" like "* House" then
    
    end if
    

    正则表达式: 搜索 Search4 并将其替换为 SEARCH4 并使用通配符来实现:

    Set objRegEx = CreateObject("vbscript.regexp")
    objRegEx.Global = True
    objRegEx.IgnoreCase = True
    objRegEx.MultiLine = True 
    
    'here you can enter your search with wild cards
    'mine says "S" followed by any character followed by "arch" followed by 1-n numbers.
    objRegEx.Pattern = "S.arch([0-9]+)"
    
    
    newText = objRegEx.Replace("Test Search4", "SEARCH$1")
    MsgBox (newText) 
    'gives you: Test SEARCH4
    

    更多信息如何使用这些通配符可以找到here 一开始可能很难,但我保证你会喜欢的;)

    你也可以替换 use 来搜索字符串:

    将文本变暗为字符串 text = "你好 Search4 search3 sAarch2 search0 search"

    Set objRegEx = CreateObject("vbscript.regexp")
    objRegEx.Global = True
    objRegEx.IgnoreCase = True
    objRegEx.MultiLine = True
    
    'here you can enter your search with wild cards
    'mine says "S" followed by any character followed by "arch" followed by 1-n numbers.
    objRegEx.Pattern = "S.arch[0-9]+"
    
    
    If (objRegEx.test(text) = True) Then
        Dim objMatch As Variant
        Set objMatch = objRegEx.Execute(text)   ' Execute search.
    
        Dim wordStart As Long
        Dim wordEnd As Long
        Dim intIndex As Integer
        For intIndex = 0 To objMatch.Count - 1
            wordStart = objMatch(intIndex).FirstIndex
            wordEnd = wordStart + Len(objMatch(intIndex))
    
            MsgBox ("found " & objMatch(intIndex) & " position: " & wordStart & " - " & wordEnd)
        Next
    End If
    

    变量文本的结果是:

    Search4 position: 6 - 13
    Search3 position: 14- 21
    ...
    

    所以在你的代码中你会使用

    rngTable.Text as text
    

    rngTable.SetRange Start:=rngTable.Start + wordStart, End:=rngTable.Start + wordEnd
    

    将是您要设置粗体的范围。

    【讨论】:

    • 感谢发帖!这听起来很对,但我试图找到一个代码示例来说明如何在搜索和替换中使用“like”。幸运的是,“like”这个词在英语中经常被用来表示代码以外的东西,所以我在使用如此挑剔的搜索引擎时遇到了麻烦! ;-) 您能否发布使用 VBA Find 的代码示例或指向我的教程说明它的链接?非常感谢!
    • 你有多可爱?感谢您的代码 - 我注意到这是在 vbscript 中 - 这将与 VBA 兼容吗?我不认为 VBA 支持正则表达式,只支持通配符(否则这是我会使用的第一件事。一定喜欢 MS Office 开发:-P)
    • 不客气。我使用 MS Word 2008 尝试了该示例代码,没有任何问题。 VBA 是 afaik VBScript 加上 MS Office Api。
    • 这很有帮助!仍然有点卡在粗体格式部分。由于我使用 Find 方法向替换文本添加粗体格式,因此我不确定如何改用 Regex 对象,但仍返回格式化字符串。我可以遍历文档中的每个单词并根据正则表达式对其进行测试,然后在成功时对其进行格式化,但这似乎有点矫枉过正。另外,我没有看到 Regex Replace 方法返回一个布尔值来测试,只有成功字符串。 Match 听起来可能会更好,但它显然不会返回匹配的位置(根据您的教程:-)。
    • 实际上我现在可能正在做一些事情 - dotnetslackers.com/Community/blogs/dsmyth/archive/2006/09/09/…> 看起来很有希望......我现在正在测试我的正则表达式......(充满希望/兴奋)
    【解决方案2】:
    Sub AllBold()
    
    Dim tblOne As Table
    Dim celTable As Cell
    Dim rngTable As Range
    Dim intCount As Integer
    Dim intMatch As Integer
    Dim celColl As Cells
    Dim i As Integer
    Dim strRegex As String
    Dim Match, Matches
    
    Set tblOne = ActiveDocument.Tables(1)
    intCount = tblOne.Columns(2).Cells.Count
    Set celColl = tblOne.Columns(2).Cells
    Set objRegEx = CreateObject("vbscript.regexp")
    objRegEx.Global = True
    objRegEx.IgnoreCase = True
    objRegEx.MultiLine = True
    
    For i = 1 To intCount
        If i = 1 Then
            i = i + 1
        End If
    
        Set celTable = ActiveDocument.Tables(1).Cell(Row:=i, Column:=2)
        Set rngTable = ActiveDocument.Range(Start:=celTable.Range.Start, _
                                            End:=celTable.Range.End - 1)
    
        If rngTable.Text <> "" Then
            strRegex = rngTable.Text
            strRegex = Replace(strRegex, "*-", "[\w]{0,}[^\w]{0,1}[\w]{0,}", 1)
            strRegex = Replace(strRegex, "*", "\w+", 1)
            strRegex = Replace(strRegex, "-", "[^\w]{0,1}", 1)
            strRegex = Replace(strRegex, "?", ".", 1)
            objRegEx.Pattern = "\b" + strRegex + "\b"
    
            Dim oRng As Word.Range
            Set oRng = ActiveDocument.Range
            Set Matches = objRegEx.Execute(ActiveDocument.Range.Text)
    
            intMatch = Matches.Count
            If intMatch >= 1 Then
                rngTable.Bold = True
                For Each Match In Matches
                    With oRng.Find
                        .ClearFormatting
                        .Text = Match.Value
                        With .Replacement
                            .Text = Match.Value
                            .Font.Bold = True
                            .Font.Italic = True
                        End With
    
                        .Execute Replace:=wdReplaceAll
                    End With
                Next Match
            End If
        End If
    Next i
    
    End Sub
    

    【讨论】:

    • 所以最后,结果证明我无法使用 Match.FirstIndex,因为文件的设置方式让表格无法使用。我最终在 Matches For Each 中使用 Word Find 来查找 Match.Value 而不是使用 Range。这是我正在寻找的确切解决方案。 @ghommey 没有你,我无法做到 - 在我们两人之间,这个解决方案非常完美。
    • 很高兴听到我可以帮助你
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-13
    • 2017-10-20
    • 1970-01-01
    • 2019-08-27
    相关资源
    最近更新 更多