Access 2010仅从MatchCollection返回第一个结果正则表达式结果

时间:2013-07-05 15:16:44

标签: sql regex vba ms-access

我在一个字段上使用正则表达式函数运行查询,其中一行可能包含一个或多个匹配但我无法获取Access以返回任何匹配,除了集合中的第一个或最后一个(显示为随机的)我)。

示例数据:

      tbl_1 (queried table)
row_1 abc1234567890 some text
row_2 abc1234567890 abc3459998887 some text
row_3 abc9991234567 abc8883456789 abc7778888664 some text

      tbl_2 (currently returned results)
row_1 abc1234567890
row_2 abc1234567890
row_3 abc7778888664

      tbl_2 (ideal returned results)
row_1 abc1234567890
row_2 abc1234567890
row_3 abc3459998887
row_4 abc9991234567
row_5 abc8883456789
row_6 abc7778888664

这是我的Access VBA代码:

Public Function OrderMatch(field As String)

Dim regx As New RegExp
Dim foundMatches As MatchCollection
Dim foundMatch As match

regx.IgnoreCase = True
regx.Global = True
regx.Multiline = True
regx.Pattern = "\b[A-Za-z]{2,3}\d{10,12}\b"

Set foundMatches = regx.Execute(field)

If regx.Test(field) Then
    For Each foundMatch In foundMatches
        OrderMatch = foundMatch.Value
    Next
End If

End Function

我的SQL代码:

SELECT OrderMatch([tbl_1]![Field1]) AS Order INTO tbl_2
FROM tbl_1
WHERE OrderMatch([tbl_1]![Field1])<>False;

我不确定我的正则表达式模式是否错误,我的VBA代码错误,或者我的SQL代码错误。

3 个答案:

答案 0 :(得分:1)

似乎您打算从tbl_1中的字段中拆分多个文本匹配项,并将每个匹配项存储为tbl_2中的单独行。使用Access查询执行此操作并不容易。请考虑使用VBA过程。在Access 2007中使用示例数据,此过程将您在tbl_2(在名为Order的文本字段中)中要求的内容存储起来。

Public Sub ParseAndStoreOrders()
    Dim rsSrc As DAO.Recordset
    Dim rsDst As DAO.Recordset
    Dim db As DAO.database
    Dim regx As Object ' RegExp
    Dim foundMatches As Object ' MatchCollection
    Dim foundMatch As Object ' Match

    Set regx = CreateObject("VBScript.RegExp")
    regx.IgnoreCase = True
    regx.Global = True
    regx.Multiline = True
    regx.pattern = "\b[a-z]{2,3}\d{10,12}\b"

    Set db = CurrentDb
    Set rsSrc = db.OpenRecordset("tbl_1", dbOpenSnapshot)
    Set rsDst = db.OpenRecordset("tbl_2", dbOpenTable, dbAppendOnly)
    With rsSrc
        Do While Not .EOF
            If regx.Test(!field1) Then
                Set foundMatches = regx.Execute(!field1)
                For Each foundMatch In foundMatches
                    rsDst.AddNew
                    rsDst!Order = foundMatch.value
                    rsDst.Update
                Next
            End If
            .MoveNext
        Loop
        .Close
    End With
    Set rsSrc = Nothing
    rsDst.Close
    Set rsDst = Nothing
    Set db = Nothing
    Set foundMatch = Nothing
    Set foundMatches = Nothing
    Set regx = Nothing
End Sub

将代码粘贴到标准代码模块中。然后将光标定位在过程体内并按 F5 运行它。

答案 1 :(得分:0)

此函数仅返回一个值,因为这是您使用逻辑设置它的方式。这将始终返回 last 匹配值。

For Each foundMatch In foundMatches
    OrderMatch = foundMatch.Value
Next

即使您的函数隐式返回Variant数据类型,它也不会返回数组,因为您没有为数组赋值。假设有2个以上的匹配,循环中的赋值语句OrderMatch = foundMatch.Value将覆盖第二个匹配,第二个匹配第三个匹配等。

假设您要返回一组匹配值:

Dim matchVals() as Variant
Dim m as Long

For Each foundMatch In foundMatches
    matchValues(m) = foundMatch.Value
    m = m + 1
    ReDim Preserve matchValues(m)
Next

OrderMatch = matchValues

答案 2 :(得分:0)

此循环

For Each foundMatch In foundMatches
    OrderMatch = foundMatch.Value
Next

依次将所有结果分配给同一个变量OrderMatch,它总是替换OrderMatch的旧值。因此,该函数将始终返回最后一个匹配。

如果要返回所有值,请返回一个数组

Public Function OrderMatch(field As String) As String()
    Dim results() As String
    Dim i As Long

    ... get matches

    ReDim results(0 To foundMatches.Count - 1) As String

    If regx.test(field) Then
        For i = 0 To foundMatches.Count - 1
            results(i) = foundMatches(i).Value
        Next
    End If
    OrderMatch = results
End Function

(我目前正在使用Access XP,因此我不知道索引是从1到Count还是从0到Count-1。)


<强>更新

始终指定函数的返回类型。这对于想要使用该功能的人(包括您,如果您必须在6个月内重新使用此功能)提供更多信息,并防止出现编码错误。如果真的是Variant,请指定... As Variant,以便明确您的意图。