【问题标题】:Using regex to find paragraphs in VBA Excel使用正则表达式在 VBA Excel 中查找段落
【发布时间】:2017-12-24 04:09:30
【问题描述】:

我正在尝试使用正则表达式来“提取”文档中的段落。每个段落的前后都有一个单独的行上的“-”,并且每个段落都以一个数字开头。

例如

-
1. 这是一个段落
它可能会跨越多行
-

理想情况下,我不想包含“-”,但这并不重要,因为我会将它放在一个字符串中并针对它运行另一个正则表达式(我知道一个有效的)

我尝试使用的代码基本如下

Dim matchPara as Object
Dim regex as Object
Dim theMatch as Object
Dim matches as Object
Dim fileName as String
Dim fileNo as Integer
Dim document as String

matchPara = "-?(\d.*?)?-"
Set regex = CreateObject("VBScript.RegExp")
regex.Pattern = matchPara
regex.Global = True
regex.Multiline = True

fileName = "C:\file.txt"
fileNo = FreeFile

Open fileName For Input As #fileNo
document = Input$(LOF(fileNo), fileNo)
set matches = regex.Execute(document)

For Each theMatch in matches
    MsgBox(theMatch.Value)
Next theMatch

Close #fileNo

我已经在regex101 上测试了这个正则表达式,它似乎符合我的要求。我也没有分组测试过

-?\d.*?-

但是,当我运行代码时,theMatch.Value 只包含一个“-”。在弄乱了正则表达式之后,我让它显示第一行文本,但从不超过第一行。

我已经检查了 theMatch.Value 的长度:

MsgBox(len(theMatch.Value))

并将theMatch.Value的内容放在工作表的一个单元格中,看看它是否在消息框中被切断,但两种理论都被证明是错误的。

我现在完全不知所措,我开始怀疑这可能是 VBA 的事情,而不是正则表达式的事情。不需要使用正则表达式,我只是认为这是最简单的事情。

这些段落包含我要提取的数据。所以想法是将每个段落正则表达式放在一个字符串中,然后运行其他正则表达式来获取我需要的信息。有些段落不包含我需要的数据,所以想法是循环遍历每个单独的段落,然后如果我需要的数据不在该段落中,则错误处理得更好(即,尽我所能,用错误消息删除其余部分)

这是截图:

【问题讨论】:

  • 我认为它在 regex101 上无法正常工作。您能否发布 regex101 结果的屏幕截图,显示它正在那里返回您的完整段落?另外,是否有理由需要使用正则表达式来完成?另外,您实际上对输出做了什么? (我认为目标不仅仅是在MsgBox's 中展示它们?
  • 添加了屏幕截图和问题的答案
  • 您的屏幕截图中的 RegEx 与您的代码中的不同。
  • 不,但这与我给出的第二个示例相同,也不起作用

标签: regex vba excel


【解决方案1】:

这种简单的方法不使用Regex。它假设数据在 A 列中,段落在 B 列中:

Sub paragraph_no_regex()
    Dim s As String
    Dim ary

    With Application.WorksheetFunction
        s = .TextJoin(" ", False, Columns(1).SpecialCells(2))
    End With

    ary = Split(s, "-")
    i = 1
    For Each a In ary
        Cells(i, 2) = a
        i = i + 1
    Next a
End Sub

【讨论】:

    【解决方案2】:
    Sub F()
    
        Dim re As New RegExp
        Dim sMatch As String
        Dim document As String
    
        re.Pattern = "-\n((.|\n)+?)\n-"
    
        'Getting document
        document = ...
    
        sMatch = re.Execute(document)(0).SubMatches(0)
    
    End Sub
    

    如果您需要破折号-,则只需将它们包含在捕获组中(外括号)。

    【讨论】:

      【解决方案3】:

      此 RegEx 匹配您的描述并成功提取段落(在 regex101.com 上测试):

      matchPara = "-\n\d+\.\s*((?:.|\n)+?)\s*\n-"
      

      它需要'global' 标志而不是'multiline' 标志。相反,行尾标记在正则表达式中匹配。要点是最里面的匹配组将匹配任何字符,包括行尾(作为替代),但以非贪婪方式(“+?”)匹配。它不关心单词边界,因为这里没有必要。此外,“-”不是正则表达式中使用的特殊字符,因此不必转义。

      由于附加的好处,前导和尾随空格被切断(组外的“\s*”)。

      【讨论】:

        猜你喜欢
        • 2023-01-27
        • 2017-05-09
        • 1970-01-01
        • 2017-09-22
        • 2016-01-13
        • 1970-01-01
        • 2012-01-14
        • 2014-08-05
        • 2017-01-18
        相关资源
        最近更新 更多