【问题标题】:Complex text parsing in AccessAccess 中的复杂文本解析
【发布时间】:2016-05-15 15:26:00
【问题描述】:

一两年前,我非常熟练地使用 ArcGIS 中的数据模型来处理属性表。 ArcGIS 使用 Access 类型的数据库,使用户能够添加、删除和修改字段。在 ArcGIS 界面中,我可以创建一个新列,并使用 Python 使用称为“字段计算器”的东西在该列上运行脚本。例如,以下算法将“230 04th street”等输入字符串转换为“230 4th street”。它还做了一些适合该项目的其他替换。

def calc(f1,f2,f3):
#where f1 is address number, f2 is address name and f3 is address suffix
#Strip trailing and ending spaces from all fields 
    #Define list
    remove_list = ['01ST', '02ND', '03RD', '04TH', '05TH', '06TH', '07TH', '08TH', '09TH']

    #Homogenize single digit address names
    if f2 in remove_list:
        f2 = f2.replace('0','')
    else:
        f2 = f2

    f1 = str(f1).replace('.0','')
    #strip leading and trailing spaces
    f1 = f1.strip()
    f2 = f2.strip()
    f3 = f3.strip()     
    #adapt address number to string format

    #Concatenate full address name
    x = f1+' '+f2+' '+f3
    #Return Full address name
    return x

我希望在 Access 中具有类似的灵活性。 Access 中最接近 ArcGIS“字段计算器”的是“表达式生成器”。这个表达式构建器可以用于简单的修改,但对于更复杂的字符串解析算法来说比较麻烦。 Access 中的任何内容是否为各个字段提供这种脚本?我们可以在 Expression Builder 中使用 VBA 或其他语言吗?也许只有 SQL 是解决方案?

【问题讨论】:

  • 您的脚本片段在 Visual Basic 中是完全可行的。 VB 是 Access 的脚本语言。您不要在表达式生成器“内部”使用 VB,而是可以使用 VB 中的表达式生成器。我们可以为您的解析算法提供“更复杂的字符串”的示例吗?
  • @PaulOgilvie - 不是坚持不懈,但您的意思是 Visual Basic for Applications。 VBA 是 MS Office 的编码接口,而不是通用语言 VB。 VB 大师会适应这种误称。

标签: python ms-access vba


【解决方案1】:

如果您拥有完整的 UI .exe 程序,则可以将用户定义的功能集成到 MS Access 中。只需在 Module 对象中编写函数脚本,然后在 VBA 或 SQL 中调用它:

Public Function Calc(f1 As String, f2 As String, f3 As String) As String
    ' where f1 is address number, f2 is address name and f3 is address suffix '
    Dim remove_list() As Variant
    Dim r As Variant
    Dim x As String

    ' Define list '
    remove_list = Array("01ST", "02ND", "03RD", "04TH", "05TH", _
                        "06TH", "07TH", "08TH", "09TH")

    ' Homogenize single digit address names '
    For Each r In remove_list
        If f2 Like "*r*" Then
            f2 = Replace(f2, r, Right(r, 3))
        Else
            f2 = f2
        End If
    Next r

    f1 = Replace(f1, ".0", "")
    ' strip leading and trailing spaces '
    f1 = Trim(f1)
    f2 = Trim(f2)
    f3 = Trim(f3)

    ' Concatenate full address name '
    x = f1 & " " & f2 & " " & f3

    ' Return Full address name '
    Calc = x

End Function

VBA

Public Sub CleanAddress()
    Dim fullAddress As String
    Dim db As Database, rst As Recordset

    Set db = CurrentDb
    Set rst = db.OpenRecordset("TableName")

    If rst.RecordCount = 0 Then Exit Sub

    Do While Not rst.EOF

        fullAddress = Calc(rst!f1, rst!f2, rst!f3)
        rst.MoveNext

    Loop

    rst.Close
    Set rst = Nothing
    Set db = Nothing
End Sub

SQL

SELECT t.*, Calc(t.f1, t.f2, t.f3) As fullAddress
FROM TableName t

而且由于函数不是太复杂,你可以用嵌套的字符串函数在 SQL 中处理所有的事情:

SQL

SELECT t.*,
    Trim(t.f1, Replace(t.f1, '.0', '')) & 

    Replace(
        Replace(
            Replace(
                Replace(
                    Replace(
                        Replace(
                            Replace(
                                Replace(
                                    Replace(Trim(t.f2), '01ST', '1ST'), 
                                '02ND', '2ND'), 
                            '03RD', '3RD'),
                        '04TH', '4TH'),
                    '05TH', '5TH'),
               '06TH', '6TH'),
            '07TH', '7TH'),
        '08TH', '8TH'),
    '09TH', '9TH') &

    Trim(t.f3)  As FullAddress

FROM TableName As t

【讨论】:

    【解决方案2】:

    ...输入“230 04th street”之类的字符串并将其转换为“230 4th” 街道”

    可以在 Access 中使用使用正则表达式的自定义 VBA 函数来实现该示例。

    这是在 Access Immediate 窗口中测试的这样一个功能:

    ? Field_Calculator("230 04th street")
    230 4th street
    

    请注意,该模式不会匹配文本段,例如 "34th"、"045th" 或 "04abc"。所以这些不会被函数改变:

    ? Field_Calculator("230 34th street")
    230 34th street
    ? Field_Calculator("230 045th street")
    230 045th street
    ? Field_Calculator("230 04abc street")
    230 04abc street
    

    这是使用后期绑定编写的函数:

    Public Function Field_Calculator(ByVal pInput As String) As String
        Const cstrPattern As String = "\b(0)(\d\w{2})\b"
        Dim objRegExp As Object
        Set objRegExp = CreateObject("VBScript.RegExp")
        With objRegExp
            .Pattern = cstrPattern
            .IgnoreCase = True
            Field_Calculator = .Replace(pInput, "$2")
        End With
    End Function
    

    如果您喜欢早期绑定,请设置对“Microsoft VBScript 正则表达式”的引用并进行以下更改:

    'Dim objRegExp As Object
    'Set objRegExp = CreateObject("VBScript.RegExp")
    Dim objRegExp As RegExp
    Set objRegExp = New RegExp
    

    可以从另一个 VBA 过程调用该函数。从 Access 会话中运行时,它也可以在 Access SQL 中使用:

    UPDATE YourTable
    SET [street_address] = Field_Calculator([street_address]);
    

    但是,不能从 Access 会话外部运行使用自定义 VBA 函数的查询。

    【讨论】:

      猜你喜欢
      • 2018-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-27
      • 1970-01-01
      • 1970-01-01
      • 2018-06-07
      • 2019-07-01
      相关资源
      最近更新 更多