2017-05-06 18 views
1

私の目的は、私の動作するPythonスクリプトロジックをExcel VBAマクロに変換することです。私はVBAに精通していないので、Pythonで動作するコンストラクトにいくつか問題がありますが、ここでは問題はありません。背景として、私のPythonスクリプトはWord Docを読み込み、regexスニペットを含むpremade変数からパターンを作成し、docxで正規表現を実行し、その結果をExcelセルに返すようにユーザ入力を求めます。次のコードは、私はエクセルVBAで、これまで持っているものの問題一部です:問題エクセル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(のように、私はpatterninputを評価するように見えることができないということです)Pythonで動作しますので、それはトリップエラー。パターン変数に適切なスニペットを割り当てながら、ユーザーの入力を評価して連結する方法はありますか?

私はこの作品を省略し、デモのためのパターンをハードコードすると、私は第二の重要な問題にぶつかります。私は正規表現がマッチを見つけて、各サブダッチをとり、同じ行の5つの別々の列に入れたい(私はこれを最大行+ 1、基本的に最初の未書き込み行で開始したい)。これが終わると、次の行に移動したいが、次の行で同じ行を実行する(したがってVBAは行+ = 1を実行できないため行=行+ 1)。しかし、今のところ、最初の2つの列は正しく実行されますが、残りのテキスト(および実行可能な一致)が3番目の列にスローされて終了します。私はそれを反復する必要がありますが、私はこれを動作させるように見えることはできません。以下は、私が使用していますデモテキストです「敬具」のキーワードである:うまくいけば、私はこれから学ぶとExcelのVBAとのより良い知り合いになることができるよう

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 

任意の助けをいただければ幸いです。ありがとうございました!

+0

私の印象では、コードの数が少なすぎる行であまりを行うにしようとしているということです。 Python(とRubyなど)がトークンを変数にマッピングするためのかなり強力な構文解析能力を持っていることを認めましたが、VBAは古く、効率がはるかに低くなっています。あなたの入力行を解析して解析し、必要なすべての変数を 'ByRef'関数のパラメータに返す関数を提案します。ループ内でこれをラップすることで、結果行カウンタをインクリメントして結果をワークシートに適切に配置することができます。 – PeterT

+0

限られた例に基づいて、Instrを使ってvbLF& "Sincerely"&vbCRLF&vbCRLFを探している方が良いかもしれません。情報ブロックを取得した後、連絡先情報の要素を解析する正規表現を保存します。 – Jeeped

+0

@PeterT私はそれが "働く"として解決策がなければならないように感じます、私はそれを次の完全試合に移すことができません(私はそれが3番目のサブプログラムで混乱するので、 。それは奇妙なことです。 \ [\ s \ n] +([\ s \ n])\ s +(\ w +)\ s +(。+)のパターンを理解できないかのようになります。 +(\ 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を数字に変換し、zipsとzip + 4を許可しながらzips-as-true-numbersを表示する[>99999]00000-0000;00000;[red]@のようなカスタム番号形式を使用します。真の数字になることを拒否する値は、赤いフォントで表示され、失敗したことを知らせます。

enter image description here

+0

ありがとうございました!最初の問題はVBScriptのかなり単純な正規表現の能力によるものだとわかっていましたが、これは私がやろうとしていることの良い回避策です。私もそれを実装しようとします! –