Access 2010 Только возврат первого результата. Результат регулярного выражения от MatchCollection

Вопрос:

Я выполняю запрос, используя функцию регулярного выражения в поле, где строка может содержать одно или несколько совпадений, но я не могу получить 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.

Лучший ответ:

Кажется, вы намерены разделить несколько текстовых совпадений с полем в 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

Эта функция возвращает только одно значение, потому что это так, как вы его установили с помощью логики. Это всегда будет возвращать последнее сопоставимое значение.

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

Этот цикл

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 чтобы ваше намерение стало ясным.

Оцените статью
TechArks.Ru
Добавить комментарий