【问题标题】:Find words with more than one capital letter in word/VBA在word/VBA中查找多个大写字母的单词
【发布时间】:2018-11-14 12:30:49
【问题描述】:

我有一段 VBA 代码使用Find 来查找文档中的所有首字母缩写词。它通过搜索由 2 个或更多字符长的大写字母组成的所有单词来实现这一点...

<[A-Z]{2,}>

问题在于它无法识别所有首字母缩略词,例如 CoP、W3C、DVD 和 CD-ROM。它分两部分选取带连字符的首字母缩略词,这些部分并不理想,但在用户检查列表时是允许的。我还可以通过不使用搜索到单词末尾来选择以“s”或其他字符结尾的单词...

<[A-Z]{2,}

但这不会将任何非大写字符作为它找到的单词的一部分。

是否有一个表达式可以让我在任何位置搜索具有两个或多个大写字母的单词并找到整个单词?

【问题讨论】:

  • 您无法使用单个通配符模式来做到这一点。 MS“正则表达式”(实际上不是“常规”)不支持可选模式。不过,您可以使用几种模式来找到您正在寻找的确切模式。
  • \b(?:[A-Z0-9]+[a-z\-]?){2,}\b
  • @WiktorStribiżew 谢谢,似乎是这样。我能看到的最简单的方法是找到所有以大写字母 (&lt;[A-Z]*&gt;) 开头的条目,然后针对 .+[A-Z] 测试找到的每个单词。这很好用(假设所有首字母缩写词都以大写字母开头),但需要额外的引用,这使得共享变得更加困难。

标签: regex vba ms-word find acronym


【解决方案1】:

我认为“在任何位置搜索具有两个或多个大写字母的单词并找到整个单词”是不可能的,除非与宏代码结合使用。无论如何,由于您使用的是宏,因此这是一种使用以下示例文本对我有用的方法

CoP, this That and AnoTher thing W3C, DVDs and CD-ROM

还有这个通配符组合(请注意,我的 Windows 配置中的列表分隔符是 ;,对于其他地区可能需要 ,)。

<[A-Z][0-9A-Z\-a-z]{1;10}>

以下函数检查“找到”范围内的第二个或任何后面的字母是否大写,并向调用过程返回一个布尔值。它遍历给定Range 中的字符,检查ASCII 值。一旦找到,循环退出。

Function ContainsMoreThanOneUpperCase(rng As Word.Range) As Boolean
    Dim nrChars As Long, i As Long
    Dim char As String
    Dim HasUpperCase

    HasUpperCase = False
    nrChars = rng.Characters.Count
    For i = 2 To nrChars
        char = rng.Characters(i).text
        If Asc(char) >= 65 And Asc(char) <= 90 Then
            'It's an uppercase letter
            HasUpperCase = True
            Exit For
        End If
    Next
    ContainsMoreThanOneUpperCase = HasUpperCase
End Function

一个使用它的例子:

Sub FindAcronyms()
    Dim rngFind As Word.Range
    Dim bFound As Boolean

    Set rngFind = ActiveDocument.content
    With rngFind.Find
        .text = "<[A-Z][0-9A-Z\-a-z]{1;10}>"
        .MatchWildcards = True
        .Forward = True
        .wrap = wdFindStop
        bFound = .Execute
        Do While bFound
            If bFound And ContainsMoreThanOneUpperCase(rngFind) Then
                Debug.Print rngFind.text
                rngFind.HighlightColorIndex = wdBrightGreen
            End If
            rngFind.Collapse wdCollapseEnd
            bFound = .Execute
        Loop
    End With
End Sub

【讨论】:

  • 谢谢,这很好用,不需要额外的引用(显然在 VBA 中使用与正则表达式进行比较)。我唯一要更改的是初始查找表达式可以是"&lt;[A-Z]*&gt;",它更简洁一些,并且没有字符限制。
  • 很高兴该方法对您有用 :-) 尝试在 Word 中使用正则表达式的问题是您丢失了格式。当然,如果你用它来比较“找到”的术语,那么它会起作用,是的......
【解决方案2】:

您无法在一次查找/替换中完成此操作。您还必须考虑 Word 应用程序所认为的单词以及首字母缩略词在句子或段落中的位置。

下面的代码应该提供一个想法,让您了解如何结合通配符搜索和其他 VBA 字符串操作来执行此操作。

它被设置为处理以大写字母开头的单词,如果您希望有任何以小写字母开头的单词,您需要进一步携带它并为以小写字母开头的单词添加代码和通配符搜索条件。

Sub FindAcronynms()
    Dim rng As word.Range
    Set rng = ActiveDocument.Content
    With rng.Find
        .ClearFormatting
        .Format = False
        .Forward = True
        .MatchWildcards = True
        .Text = "<[A-Z]{1,}[a-z][A-Z]>"
        .Wrap = wdFindStop
        .Execute
        Do While .found
            MoveEndOfString rng
            rng.HighlightColorIndex = wdTeal
            rng.Collapse wdCollapseEnd
            .Execute
        Loop
    End With
    Set rng = ActiveDocument.Content
    With rng.Find
        .ClearFormatting
        .Format = False
        .Forward = True
        .MatchWildcards = True
        .Text = "[A-Z]{1,5}[0-9][A-Z]{1,5}"
        .Wrap = wdFindStop
        .Execute
        Do While .found
            MoveEndOfString rng
            rng.HighlightColorIndex = wdTeal
            rng.Collapse wdCollapseEnd
            .Execute
        Loop
    End With
    Set rng = ActiveDocument.Content
    With rng.Find
        .ClearFormatting
        .Format = False
        .Forward = True
        .MatchWildcards = True
        .Text = "<[A-Z]{2,}>"
        .Wrap = wdFindStop
        .Execute
        Do While .found
            MoveEndOfString rng
            rng.HighlightColorIndex = wdTeal
            rng.Collapse wdCollapseEnd
            .Execute
        Loop
    End With
    MsgBox "Action Complete", vbExclamation, "Custom Find"
End Sub
Private Function MoveEndOfString(ByRef rng As word.Range)
    rng.MoveEnd wdCharacter, 1
    Select Case Asc(rng.Characters.Last)
        Case Is <= 32
            rng.MoveEnd wdCharacter, -1
        Case 45
            rng.MoveEnd wdCharacter, 1
            rng.MoveEnd wdWord, 1
            If Asc(rng.Characters.Last) = 32 Then
                'required because move above includes
                'trailing space
                rng.MoveEnd wdCharacter, -1
            End If
    End Select
End Function

【讨论】:

  • 谢谢,不幸的是,它似乎不能在一次操作中完成。这段代码似乎没有挑选出包含小写字母的单词(尽管它确实突出了它们后面的标点符号),并且似乎在它找到的单词之后拾取了标点符号。
【解决方案3】:

你可能会使用类似的东西:

Sub Demo()
Application.ScreenUpdating = False
Options.DefaultHighlightColorIndex = wdPink
With ActiveDocument.Range
  With .Find
    .ClearFormatting
    .Replacement.ClearFormatting
    .Replacement.Highlight = True
    .Forward = True
    .Format = True
    .Wrap = wdFindContinue
    .MatchWildcards = True
    .Text = "<[A-Z][A-Z0-9/-]{1,}"
    .Replacement.Text = "^&"
    .Execute Replace:=wdReplaceAll
    .Text = "<[A-Z][A-Za-z0-9/-]@[A-Z]"
    .Replacement.Text = "^&"
    .Execute Replace:=wdReplaceAll
  End With
End With
Application.ScreenUpdating = True
End Sub

【讨论】:

  • 我认为您需要对此进行一些解释......这如何解决问题并不明显。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-28
  • 1970-01-01
  • 2022-10-06
  • 1970-01-01
  • 2015-02-15
  • 2023-04-09
相关资源
最近更新 更多