2017-05-06 106 views
1

我的目標是將我工作的Python腳本邏輯轉換爲Excel VBA宏。由於我不熟悉VBA,因此我在Python中使用的構造有一些問題,但不在這裏。作爲背景,我的Python腳本讀取Word文檔,要求用戶輸入以從包含正則表達式片段的預製變量創建模式,在docx上執行正則表達式並將這些結果返回到Excel單元格中。下面的代碼是什麼,我至今用Excel VBA的問題的一部分:問題在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 

我的第一個問題是,我似乎無法評估patterninput,怎麼樣的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

我的印象是,你試圖做太多與代碼太少行。當然,Python(以及Ruby和其他)具有相當強大的將標記映射到變量的解析能力,但VBA的效率較低且效率較低。我會建議一個函數,它接受你的輸入行並解析它,然後將所有需要的變量返回給'ByRef'函數參數。將其封裝在一個循環中,以便您可以增加目標行計數器以將結果適當放置在工作表上。 – PeterT

+0

根據你有限的例子,你可能會更適合使用Instr尋找vbLF和「真誠」&vbCRLF&vbCRLF。檢索信息塊後,保存用於解析聯繫人信息元素的正則表達式。 – Jeeped

+0

@PeterT我覺得必須有一個解決方案,雖然它「起作用」,但我無法讓它繼續下一個完整的比賽(我假設這是因爲它在第三個子比賽中亂七八糟) 。這是最奇怪的事情。這就好像它不能理解「真誠的[\ s \ n] +([\ w \。] +)\ s +(\ w +)\ s +(。+)[\ s \ n] +(\ d + \ s。+)[\ s \ n] +(。+)「,因爲在正則表達式檢查器上,它是正確的。 –

回答

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,同時允許使用zip和zip + 4。拒絕成爲真實數字的任何值都會以紅色字體顯示,以便讓您知道失敗。

enter image description here

+0

謝謝你的幫助!雖然我發現我最初的問題是由於VBScript的相當簡單的正則表達式的能力,這是一個很好的解決方法,我正在嘗試做什麼。我會盡力實現它! –