将具有多个值的查阅列中的数据复制到新记录Access 2007

时间:2009-11-13 23:55:32

标签: arrays ms-access vba ms-access-2007 access-vba

我在Access 2007中将记录从一个表复制到另一个表。我遍历当前记录中的每个字段并将该值复制到新表中。它工作正常,直到我进入允许多个值的查阅列字段。查阅列的名称是“Favorite Sports”,用户可以从下拉列表中选择多个值。

我相信多值字段的值存储在一个数组中,但我无法访问VBA代码中的值!我已经尝试了 myRecordset.Fields(“myFieldName”)。值(索引)但它没有用。我不明白Access如何在一个字段中存储多个值。

我在另一个论坛上看到了有关ItemsSelected的内容,但我不知道哪个Object与该方法相关联。

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

我建议不要使用多值字段来准确地说明你遇到的原因,因为引用存储在这个简单易用的UI元素中的数据非常复杂(而且它是用于UI的,它是可用的,甚至虽然它是在表设计中创建的)。

在您提到“ItemsSelected”时,您似乎假设您在多值字段中访问数据的方式与在表单上的多选列表框中的方式相同。这是不正确的。相反,您必须通过DAO记录集使用它。 The documentation for working with multivalue fiels解释了如何在代码中执行此操作,如下所示:

  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

这应该有效,因为返回的记录集是一列记录集,列名为“Value”,你要求该列的值。

这有两个问题:

  1. 它实际上不起作用。这意味着Me.Recordset(“MyField”)。Value并不是一个完整的记录集对象,比如CurrentDB.OpenRecordset(“MyTable”)。这可以通过尝试返回此记录集的Recordcount来证明:

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

    这会导致错误,因此这意味着返回的内容实际上不是标准的记录集对象。

  2. 即使 工作,你也无法浏览记录集 - 你所能得到的只是来自首先在多值字段中选择的值。这是因为在这种快捷方式中,单行形式无法导航到您以这种方式引用的任何记录集中的特定记录。记录集与列表框不同,您可以使用.ItemData(0).Column(1)访问行和列,它将返回列表框第一行的第2列。

  3. 因此,唯一的方法是通过导航子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
    

    使用该模型,您还可以编写代码以将值连接到列表中,或者返回值的计数(因此,您可以先调用它,以便在索引超出值的数量时避免出现错误消息)。

    和所有这些一样酷,并且与呈现的UI一样好(如果他们将选择复选框添加为多选列表框的类型,那将非常好),我仍然建议不要正确地使用它是因为使用起来非常麻烦。这只是解决了标准查找字段的问题(参见The Evils of Lookup Fields in Tables)并使事情变得更糟。在我看来,要求DAO代码从这些字段中获取值是一个非常严重的障碍,需要克服一个能够让高级用户更轻松的UI元素。

答案 1 :(得分:0)

要快速而肮脏地获取多值(“复杂数据”)列的值 out ,您可以使用带有Connection连接的ADO 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

现在,多值类型列的类型为MEMOadLongVarWChar),每个值用分号;字符分隔。

但这只是问题的一半。如何将数据转换为多值列?

Access Team似乎忽略了增强Access数据库引擎SQL语法以适应多值类型。 “分号分隔符”技巧不起作用,例如

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

失败并显示错误“无法执行此操作”,尝试通过ADO记录集进行更新时也是如此:(