6

住所フィールドの単語を標準の米国郵政公社の略語に置き換えるVBA関数をAccessで作成しようとしています。これが完璧になることは決してないだろうと思いますが、少なくとも(住所フォーマットソフトウェアを購入することなく)簡単な略語を作成したいと思います

 input      output
 -------    -------------
 North   -> N
 Street  -> ST
 Drive   -> DR
 Lane    -> LN

単純なテーブルを使用して文字列と置換文字列を格納し、次にそのテーブル/レコードセットをループして単純な検索を実行し、Replace()関数を使用して置換することを考えimmediate windowました。

 ?Replace("123 North 3rd St", "North", "N", compare:=vbTextCompare)
 123 N 3rd St

ただし、この方法ではエラーが発生する可能性があります。

 ?Replace("123 Northampton St", "North", "N", compare:=vbTextCompare)
 123 Nampton St

私の当初の戦略は、正規表現パターンと置換文字列を使用して置換テーブルを作成し、そのテーブルをループして、より正確な検索と置換を行うことでした。

pattern                 abbrev
-------------------     ------------
{pattern for North}     N
{pattern for Street}    ST

特にデータベース内のアドレスフィールドを何度もループするため、ここでは正規表現が過剰である可能性があることに気付きましたが、関数を使用するだけの簡単な方法は考えられませんでしたReplace()更新:@mwolfe02からの応答を参照してください。 @Cylian、およびハイブリッドソリューション)。

上記の例では、NorthとStreetという単語が、文字列内の単語として存在する場合(つまり、2つの空白で区切られている場合)、または文字列の最後または文字列の先頭にある場合に検索します。これは、省略形が必要なほとんどの状況をカバーしています。例えば

address                       formatted
----------------------        --------------------------
123 North 3rd St           -> 123 N 3RD ST
123 ABC Street North       -> 123 ABC ST N
North 3rd Street           -> N 3RD ST
123 North Northampton St   -> 123 N NORTHAMPTON ST

これらの例のように、文字列内のパターンのすべてのインスタンスを置き換えたいと思います。また、すべてを大文字に変換しています(UCase()最終結果では問題なく使用できます)。

この種のことを行う既存のモジュールを知っている人はいますか?上記の例のように、誰かがパターンマッチングを手伝ってもらえますか?追加のクレジットとして、私書箱をフォーマットするためのルールをテーブルに作成することにも興味があります

address                   formatted
----------------------    --------------------------
P.O. Box 345           -> PO BOX 345
PO Box 345             -> PO BOX 345
Post Office Box 345    -> PO BOX 345
PO. Box 345            -> PO BOX 345
P. O. Box 345          -> PO BOX 345

このスタックオーバーフローの投稿は、いくつかの私書箱「^ \ s *P.?\s?O.?\sB[Oo][Xx]」を認識するために次のパターンを提供します。(確かに上記の3番目の例ではありません)。繰り返しになりますが、このより正確な置換関数を作成する方法を理解するためのマッチングセットと置換セットにはあまり慣れていません。支援できるRegEx/Accessの専門家はいますか?

4

4 に答える 4

5

この機能を試してください

Public Function FormatPO(inputString$)
'This example uses **Microsoft VBScript Regular Expressions 5.5**
Dim re As New RegExp, result$
With re
    .Pattern = "\bP(?:[. ]+|ost +)?O(?:ff\.?(?:ice))?[. ]+B(?:ox|\.) +(\d+)\b"
    .Global = True
    .IgnoreCase = True
    If .test(inputString) Then
        FormatPO = .Replace(inputString, "PO BOX $1")
    Else
        MsgBox "Data doesn't matched!"
    End If
End With

immediate window(から)と呼ぶことができます

?FormatPO("P.O. Box 563")

結果を出す

PO BOX 563

通りの名前と住所の一致パターンは、構築にさらに時間がかかります。ただし、ここにアクセスして、オンラインで正規表現を作成することもできます。

お役に立てれば。

于 2012-05-29T09:19:34.293 に答える
2

@Cylianは、あなたの質問の2番目の部分に対して良い答えを持っています。私は最初に対処しようとします。アドレス内の単語全体を置き換えることが唯一の懸念事項である場合は、次の関数が必要な処理を実行します。

Function AddressReplace(AddressLine As String, _
                        FullName As String, _
                        Abbrev As String)
    AddressReplace = Trim(Replace(" " & AddressLine & " ", _
                                  " " & FullName & " ", _
                                  " " & Abbrev & " "))
End Function

アドレス行を開始スペースと終了スペースで囲んでいるため、置換しようとしている各単語に開始スペースと終了スペースを要求できます。それはそれらの一時的なスペースを取り除くためにトリムで終わります。

次の手順では、コードをテストして、探している出力を生成します。

Sub TestAddressReplace()
    Debug.Print AddressReplace("123 North 3rd St", "North", "N")
    Debug.Print AddressReplace("123 Northampton St", "North", "N")
End Sub
于 2012-05-29T13:12:42.763 に答える
2

USPSには、アドレスを検証および標準化するための無料のルックアップAPIがあります。サービスに登録する必要があり(クイック)、APIでID/パスワードを使用してサイトにバウンスします。すべての作業を行い、サンプルコードがあります。カナダの郵便サービスにも同じことがあります(ただし、無料かどうかはわかりません)。

https://www.usps.com/business/web-tools-apis/welcome.htm

B.セビア

于 2016-02-17T14:50:22.887 に答える
0

オンラインのUSPS略語リストから非常に単純な参照テーブルref_USPS_abbrevを作成しました。最初に示した例に対応するエントリは次のとおりです。

WORD          ABBREV
------------  -------------
NORTH         N
STREET        ST

次に、元の投稿への応答を組み込んで、2つのヘルパー関数を作成しました。

@Cylianから:

    ' ----------------------------------------------------------------------'
    '  Formats string containing P.O. Box to USPS Approved PO BOX format    '
    ' ----------------------------------------------------------------------'
    '  Requires Microsoft VBScript Regular Expressions 5.5

    Public Function FormatPO(inputString As String) As String

        Static rePO As Object
        If rePO Is Nothing Then
            Set rePO = CreateObject("vbscript.regexp")
        With rePO
        .Pattern = "\bP(?:[. ]+|ost +)?O(?:ff\.?(?:ice))" & _
                   "?[. ]+B(?:ox|\.) +(\d+)\b"
        .Global = True
        .IgnoreCase = True
        End With
        End If

        With rePO
           If .Test(inputString) Then
              FormatPO = .Replace(inputString, "PO BOX $1")
           Else
              FormatPO = inputString
           End If
        End With
    End Function

そして、@ mwolfe02の優れたアイデアを使用して:

    ' ----------------------------------------------------------------------'
    '  Replaces whole word only with an abbreviation in address string      '
    ' ----------------------------------------------------------------------'

    Public Function AddressReplace(AddressLine As String, _
                    FullName As String, _
                    Abbrev As String)

    'Enclose address line in an opening and closing space, so that you 
    'can require an opening and closing space on each word you are trying 
    'to replace. Finish up with a trim to get rid of those temporary spaces.

    AddressReplace = Trim(Replace(" " & AddressLine & " ", _
                              " " & FullName & " ", _
                              " " & Abbrev & " "))
    End Function

次に、これらのヘルパー関数を組み込んで、次の関数を作成しました。

' ----------------------------------------------------------------------'
'  Format address using abbreviations stored in table ref_USPS_abbrev   '
' ----------------------------------------------------------------------'  
'  Requires Microsoft DAO 3.6 Object Library
'  Table ref_USPS_abbrev has two fields: WORD (containing the word to match) 
'  and ABBREV containing the desired abbreviated substitution.
'  United States Postal Services abbreviations are available at:
'  https://www.usps.com/ship/official-abbreviations.htm

Public Function SubstituteUSPS(address As String) As String

Static dba As DAO.Database
Static rst_abbrev As DAO.Recordset

    If IsNull(address) Then Exit Function

    'Initialize the objects 

    If dba Is Nothing Then
        Set dba = CurrentDb
    End If

    'Create the rst_abbrev recordset once from ref_USPS_abbrev. If additional
    'entries are added to the source ref_USPS_abbrev table after the recordset 
    'is created, since it is an dbOpenTable (by default), the recordset will 
    'be updated dynamically. If you use dbOpenSnapshot it will not update 
    'dynamically.

    If rst_abbrev Is Nothing Then
        Set rst_abbrev = dba.OpenRecordset("ref_USPS_abbrev",  _
                                           Type:=dbOpenTable)
    End If

    'Since rst_abbrev is a static object, in the event the function is called 
    'in succession (e.g. while looping through a recordset to update values), 
    'move to the first entry in the recordset each time the function is 
    'called.

    rst_abbrev.MoveFirst

    'Only call the FormatPO helper function if the address has the 
    'string "ox" in it.    

    If InStr(address, "ox") > 0 Then
        address = FormatPO(address)
    End If

    'Loop through the recordset containing the abbreviations
    'and use the AddressReplace helper function to substitute 
    'abbreviations for whole words only.

    Do Until rst_abbrev.EOF
        address = AddressReplace(address, rst_abbrev![WORD],  _
                                 rst_abbrev![ABBREV])
        rst_abbrev.MoveNext
    Loop

    'Convert the address to upper case and trim white spaces and return result
    'You can also add code here to trim out punctuation in the address, too.

    SubstituteUSPS = Trim(UCase(address))

End Function

テスト用のref_USPS_abbrevテーブルを作成するには:

Sub CreateUSPSTable()

Dim dbs As Database
Set dbs = CurrentDb

With dbs
    .Execute "CREATE TABLE ref_USPS_abbrev " _
        & "(WORD CHAR, ABBREV CHAR);"
    .Execute " INSERT INTO ref_USPS_abbrev " _
        & "(WORD, ABBREV) VALUES " _
        & "('NORTH', 'N');"
    .Execute " INSERT INTO ref_USPS_abbrev " _
        & "(WORD, ABBREV) VALUES " _
        & "('STREET', 'ST');"
    .Close
End With
End Sub

immediate window最後に、 :からこの関数をテストします。

 CreateUSPSTable
 ?SubstituteUSPS("Post Office Box 345 123 North Northampton Street")
 PO BOX 345 123 N NORTHAMPTON ST

私はプロのプログラマーではないので、コードをさらにクリーンアップするための提案を歓迎しますが、今のところこれはうまく機能します。みんな、ありがとう。

スタックオーバーフローがまたもやFTW!

于 2012-05-29T20:20:13.523 に答える