Есть ли способ передать многозначное поле непосредственно в функцию VBA из инструкции SQL? Нет, к сожалению.
Однако существуют различные альтернативные методы, которые вы можете реализовать, чтобы получить список значений, хранящихся в поле. Легко рассуждать о плюсах и минусах многозначных полей Access. Я не буду подробно останавливаться на этом, но стоит отметить, что основным преимуществом многозначного поля является удобство и очевидная простота интерфейса доступа, позволяющего автоматически перечислять и разрешать выбор , кратного ценности отношения один ко многим. Попытка подражать такому поведению в Access может быть очень неловкой и громоздкой (а зачастую и невозможной). Многие детали реализации для многозначных полей являются «скрытыми» (то есть плохо документированы или не доступны стандартным программным интерфейсам SQL или VBA). Это включает в себя возможность передавать многозначное поле в функцию VBA из оператора SQL. Независимо от того, насколько интуитивно понятным кажется предполагаемое поведение, Access не просто передает тот же составной список значений, который он отображает, другой функции. Но бывают случаи, когда просто нужен список значений, доступный в простом списке. Информация , на которую ссылается Густав , полезна и должна быть хорошо понята для запроса многозначных полей, но она по-прежнему не касается других вполне разумных действий, требуемых для нескольких значений. Надеемся, что следующие указатели полезны.
- Если значения необходимы в стандартном операторе SQL, я предлагаю передать значения первичного ключа в функцию VBA. Затем попросите функцию VBA просмотреть запись и извлечь значения многозначных полей, используя наборы записей DAO .
- Поскольку это вызовет функцию VBA для каждой строки , это может быть (очень) медленно. Можно оптимизировать функцию, используя различные методы, такие как открытие объекта статического набора записей. Дальнейшие подробности выходят за рамки этого ответа.
- Поскольку на данный момент вы уже находитесь в коде и можете структурировать VBA и запросы так, как вам удобно, наиболее эффективный запрос обойдет само многозначное поле и использует стандартные объединения SQL, чтобы получить то, что вам нужно. Например, если вы хотите получить все связанные имена пользователей, откройте и перечислите следующий набор записей, чтобы построить свой список имен:
sSQL = "SELECT table2.key, table2.multifield.value, UserTable.Username " & _
" FROM UserTable INNER JOIN table2 ON UserTable.ID = table2.multifield.Value" & _
" WHERE (table2.key = [KeyParameter])"
Set qry = CurrentDb.CreateQueryDef(, sSQL)
qry.Parameters("KeyParameter") = keyPassedToFunction
Set rs = qry.OpenRecordset
- Если SQL-запрос может / будет открыт как набор записей DAO в контексте кода и , вам все равно нужно извлечь многозначное поле в виде единственного поля , существует способ перечислить многозначное поле в VBA.
- Если код заканчивается многократным открытием и закрытием нескольких наборов записей, особенно в нескольких вложенных циклах, вероятно, вы могли бы повысить эффективность, реструктурировав SQL с помощью соответствующих объединений и изменив порядок обработки данных.
- Rant: Как вы могли заметить, несколько противоречиво, что базовый объект набора записей оператора SQL действительно возвращает объект, который может быть перечислен в коде, хотя механизм SQL Access отказывается передавать такой объект в функцию VBA. , Механизм SQL уже имеет дело с упаковкой и распаковыванием данных в тип варианта VBA, поэтому кажется разумным, чтобы при реализации многозначных полей они могли иметь механизм SQL, просто упаковавший объект многозначного набора записей и передавший его в функцию VBA для обработки. похож на следующий код ... поэтому первоначальная попытка в этом вопросе не была необоснованной.
- Следующий фрагмент кода показывает, что многозначное поле возвращается как объект DAO.Field, содержащий объект DAO.Recordset2:
Dim rs as Recordset2
Set rs = CurrentDB.OpenRecordset("SELECT table2.multifield ... FROM ...")
Dim sList As String
sList = ""
If TypeOf rs![multifield] Is Recordset2 Then
Dim rsMVF As Recordset2
Set rsMVF = rs![multifield]
Dim bFirst As Boolean
bFirst = True
rsMVF.MoveFirst
Do Until rsMVF.EOF
If bFirst Then
sList = rsMVF.Fields(0)
bFirst = False
Else
sList = sList & "," & rs.Fields(0)
End If
rsMVF.MoveNext
Loop
'* DO NOT CLOSE the Recordset based on the Multivalue field.
'* Access will close it automatically.
End If
'* sList will contain comma-separated list of values