Скопируйте данные из поискового столбца с несколькими значениями в новую запись Access 2007 - PullRequest
1 голос
/ 14 ноября 2009

Я копирую запись из одной таблицы в другую в Access 2007. Я перебираю каждое поле в текущей записи и копирую это значение в новую таблицу. Это работает нормально, пока я не доберусь до своего поля столбца поиска, которое допускает множественные значения. Название столбца поиска - «Любимые виды спорта», и пользователь может выбрать несколько значений из раскрывающегося списка.

Я считаю, что значения многозначного поля хранятся в массиве, но я не могу получить доступ к значениям в коде VBA! Я попытался myRecordset.Fields ("myFieldName"). Значение (индекс) , но это не сработало. Я не понимаю, как Access хранит несколько значений в одном поле.

Я видел что-то о ItemsSelected на другом форуме, но я не знаю, какой объект связан с этим методом.

Спасибо за любую помощь!

Ответы [ 2 ]

2 голосов
/ 15 ноября 2009

Я бы рекомендовал не использовать многозначные поля именно по той причине, с которой вы столкнулись, потому что чрезвычайно сложно ссылаться на данные, хранящиеся в этом простом в использовании элементе пользовательского интерфейса (и это для пользовательского интерфейса, который он сделал доступным, даже хотя это создано в дизайне таблицы).

Из вашего упоминания "ItemsSelected" вы, по-видимому, предполагаете, что обращаетесь к данным в многозначном поле так же, как в многоэлементном списке в форме. Это не правильно. Вместо этого вы должны работать с ним через набор записей DAO. Документация по работе с многозначными полями объясняет, как сделать это в коде, что-то вроде этого:

  Dim rsMyField As DAO.Recordset

  Set rsMyField = Me.Recordset("MyField").Value
  rsChild.MoveFirst
  Do Until rsChild.EOF
    Debug.Print rsChild!Value.Value
    rsChild.MoveNext
  Loop
  rsChild.Close
  Set rsChild = Nothing

Теперь, учитывая, что вы обычно можете получить доступ к свойствам объекта набора записей через его коллекции по умолчанию, вы ожидаете, что Me.Recordset ("MyField"). Value будет возвращать объект набора записей, по которому можно перемещаться по коллекции по умолчанию. набора записей, который является коллекцией полей. Вы могли бы подумать, что можете сделать это:

  Me.Recordset("MyField").Value!Value.Value

Это должно работать, потому что возвращенный набор записей представляет собой набор записей из одного столбца с именем столбца «Значение», и вы будете запрашивать значение этого столбца.

Есть две проблемы с этим:

  1. на самом деле это не работает. Это означает, что Me.Recordset («MyField»). Value не является действительно полноценным объектом набора записей, как, скажем, CurrentDB.OpenRecordset («MyTable»). Это можно продемонстрировать, пытаясь вернуть количество записей этого набора записей:

    Me.Recordset("MyField").Value.Recordcount
    

    Это вызывает ошибку, а это означает, что возвращаемое на самом деле не является стандартным объектом набора записей.

  2. даже если это сработало , у вас не будет возможности перемещаться по коллекции записей - все, что вы когда-либо сможете получить, это данные из первое выбранное значение в вашем многозначном поле. Это связано с тем, что в этой сокращенной однострочной форме нет способа перейти к определенной записи в любом наборе записей, на который вы ссылаетесь таким образом. Набор записей не похож на список, в котором вы можете получить доступ как к строкам, так и к столбцам, используя .ItemData (0) .Column (1), который будет возвращать 2-й столбец первой строки списка.

Таким образом, единственный способ сделать это - перемещаться по дочернему набору записей DAO, как в примере кода выше (смоделированном в цитируемой статье MSDN).

Теперь вы можете легко написать функцию-обертку, чтобы справиться с этим. Кажется, что-то вроде этого работает:

  Public Function ReturnMVByIndex(ctl As Control, intIndex As Integer) As Variant
    Dim rsValues As DAO.Recordset
    Dim lngCount As Long
    Dim intRecord As Integer

    Set rsValues = ctl.Parent.Recordset(ctl.ControlSource).Value
    rsValues.MoveLast
    lngCount = rsValues.RecordCount
    If intIndex > lngCount - 1 Then
       MsgBox "The requested index exceeds the number of selected values."
       GoTo exitRoutine
    End If
    rsValues.MoveFirst
    Do Until rsValues.EOF
      If intRecord = intIndex Then
         ReturnMVByIndex = rsValues(0).Value
         Exit Do
      End If
      intRecord = intRecord + 1
      rsValues.MoveNext
    Loop

  exitRoutine:
    rsValues.Close
    Set rsValues = Nothing
    Exit Function
  End Function

Используя эту модель, вы также можете написать код для объединения значений в список или возвратить количество значений (чтобы вы могли вызвать это сначала, чтобы избежать сообщения об ошибке, когда ваш индекс превысил количество значений).

Как бы круто это ни было, и как бы ни был хорош представленный пользовательский интерфейс (было бы очень хорошо, если бы они добавили флажки выбора в качестве типа для списка с множественным выбором), я все равно рекомендовал бы против использовать его именно потому, что с ним так трудно работать. Это просто снимает проблему стандартного поля поиска (см. Зло полей поиска в таблицах ) и делает ситуацию еще хуже. Мне кажется, что требование кода DAO для получения значений из этих полей является довольно серьезным препятствием, которое необходимо преодолеть с помощью элемента пользовательского интерфейса, который должен облегчить работу для опытных пользователей.

0 голосов
/ 17 ноября 2009

Для быстрого и грязного способа получения значений из многозначного столбца («комплексные данные») вы можете использовать ADO Connection со свойством соединения Jet OLEDB:Support Complex Data, установленным на False например строка подключения должна выглядеть примерно так:

Provider=Microsoft.ACE.OLEDB.12.0;
Data Source=C:\dbs\TestANSI92.accdb;
Jet OLEDB:Engine Type=6;
Jet OLEDB:Support Complex Data=False

Теперь столбец с несколькими значениями будет иметь тип MEMO (adLongVarWChar), каждое значение которого будет разделено точкой с запятой ;.

Но это только половина проблемы. Как получить данные в многозначный столбец?

Похоже, что команда разработчиков не учитывает синтаксис SQL в Access Database Engine для соответствия многозначным типам. Трюк «точка с запятой» не работает наоборот, например

INSERT INTO TestComplexData (ID, weekday_names_multivalued) 
   VALUES (5, 'Tue;Thu;Sat');

завершается с ошибкой «Невозможно выполнить эту операцию», то же самое при попытке обновления через набор записей ADO: (

...