1

我在行可能包含一个或多个匹配项的字段上使用正则表达式函数运行查询,但我无法让 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

这是我的访问 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 代码是否错误。

4

3 回答 3

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运行它。

于 2013-07-05T17:37:13.590 回答
0

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

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
于 2013-07-05T15:27:47.730 回答
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 个月内重新使用此功能)提供更多信息,并防止出现 supid 编码错误。如果真的Variant是这个意思,请指定... As Variant以便您的意图变得清晰。

于 2013-07-05T15:34:38.783 回答