我的目标是将我正在运行的Python脚本逻辑转换为Excel VBA宏。由于我不熟悉VBA,因此我遇到了一些在Python中工作但不在此处的构造问题。作为背景,我的Python脚本读取Word文档,要求用户输入从包含正则表达式片段的预制变量创建模式,在docx上执行正则表达式并将这些结果返回到Excel单元格。以下代码是我目前使用Excel VBA的问题部分:
patterninput = InputBox("a1 = Title" & vbNewLine & "a2 = First Name" & vbNewLine & "a3 = Last Name" & vbNewLine & "b = Address" & vbNewLine & "c = Town, State Zip" & vbNewLine & "x = Line Omit", "Step #3: Enter Pattern")
Dim x As String
Dim a1 As String
Dim a2 As String
Dim a3 As String
Dim b As String
Dim c As String
x = "(?:.+)\s+"
a1 = "([\w\.]+)\s+"
a2 = "(\w+)\s+"
a3 = "(.+)[\s\n]+"
b = "(\d+\s.+)[\s\n]+"
c = "(.+)"
pattern = keyword & "[\s\n]+" & Application.Evaluate(patterninput)
Dim objMatches As MatchCollection
With regEx
.Global = False
.MultiLine = True
.IgnoreCase = False
.pattern = pattern
End With
Set objMatches = regEx.Execute(strInput)
Dim row As Long
Dim SubMatches As Variant
row = .Rows.Count + 1
For Each SubMatches In objMatches
Cells(row, 1).Value = objMatches(0).SubMatches(0)
Cells(row, 2).Value = objMatches(0).SubMatches(1)
Cells(row, 3).Value = objMatches(0).SubMatches(2)
Cells(row, 4).Value = objMatches(0).SubMatches(3)
Cells(row, 5).Value = objMatches(0).SubMatches(4)
row = row + 1
Next
我的第一个问题是我似乎无法评估模式输入,就像eval()在Python中如何工作一样,因此会导致错误。有没有一种方法可以评估和连接用户输入,同时为模式变量分配适当的片段?
如果我省略这篇文章并为演示目的硬编码模式,我会遇到第二个更重要的问题。我希望正则表达式找到一个匹配,然后取每个子匹配并将它放入同一行中的5个单独的列中(我希望它从最大行+ 1开始;基本上是第一个未写入的行)。一旦完成,我希望它移动到下一个匹配,执行相同的操作,但在下一行(因此行=行+ 1,因为VBA显然不能行+ = 1)。但是,它现在的工作方式,它正确地执行前两列,但然后将其余的文本(和可行的匹配)抛出到第三列并完成。我需要它来迭代,但我似乎无法让它工作。以下是我正在使用的演示文本"真诚"是关键字:
Dear Sir,
Hello
Sincerely,
Mr. Thomas Dahlmer
46 Alpine Street
Evanston, Il 60201
Dear Sir,
Hello
Sincerely,
Mr. Robert Thomas
1104 Madison Avenue
New York, NY 10021
任何帮助都将非常感谢,希望我能从中学习并更好地熟悉Excel VBA。谢谢!
答案 0 :(得分:1)
您必须将信件的正文文本放入我的str
变量中;为了演示目的,我只是将示例文本放入A2(实际上,A2:A17合并)。有很多关于将文本文件转换为此站点上的字符串变量的示例。
这使用Instr和Split来避免使用正则表达式模式。 TBPH,我对多线全局正则表达式模式并不擅长。
Option Explicit
Sub wqreqwq()
Dim b As Long, e As Long
Dim str As String, sal As String, con As String
Dim info As Variant
With Worksheets("sheet6")
ReDim info(4)
sal = "sincerely," & vbLf & vbLf
str = Replace(.Cells(2, "A").Value2, vbCrLf, vbLf) & vbLf & vbLf
b = InStr(1, str, sal, vbTextCompare)
Do While CBool(b)
b = b + Len(sal)
e = InStr(b, str, vbLf & vbLf, vbTextCompare)
'b = InStr(e + 2, str, sal, vbTextCompare)
con = Mid(str, b, e - b)
info = Split(con, vbLf)
ReDim Preserve info(4)
info(3) = Split(info(2), Chr(44) & Chr(32))(1)
info(2) = Split(info(2), Chr(44) & Chr(32))(0)
info(4) = Split(info(3), Chr(32))(1)
info(3) = Split(info(3), Chr(32))(0)
.Cells(.Rows.count, "C").End(xlUp).Offset(1, 0).Resize(1, 5) = info
b = InStr(e, str, sal, vbTextCompare)
Loop
End With
End Sub
我已将邮政编码保留为文本 - 看起来像一个数字。通常,我将etxt转换为数字并使用自定义数字格式,如[>99999]00000-0000;00000;[red]@
,显示zips-as-true-numbers,同时允许zips和zip + 4' s。任何拒绝成为真实数字的值都会以红色字体显示,以便让您知道失败。