从包含 155K 记录的表中获取仅在组合框中列出的 65K 记录

Posted

技术标签:

【中文标题】从包含 155K 记录的表中获取仅在组合框中列出的 65K 记录【英文标题】:get 65K records only listed in combo box from a table of 155K records 【发布时间】:2008-11-10 20:59:33 【问题描述】:

我有一个包含 155K 记录的表。我只能在具有带有查询或 sql 的记录源的表单的组合框中滚动 65K 记录,从该表中选择三个字段。为什么它没有列出所有 155K 记录,即使是我用作记录源的查询也显示了表单之外的所有记录。

【问题讨论】:

这个组合框在哪里列出?是访问表单吗? 【参考方案1】:

也许项目索引是一个 16 位整数

一个更好的问题是,您真的希望用户在组合框中滚动浏览 155,000 个项目吗?

【讨论】:

这是正确的。 Excel/Access 有一个限制:16 位整数。我猜他想对这些数据做一些事情,比如从整个数据集的那个 UI 中搜索/替换——这不会完全加载。【参考方案2】:

最简单的方法是仅在您在其中键入一些字符后分配组合框的行源。您可以在组合框的 OnChange 事件中执行此操作:

  Dim strRowSource As String

  strRowSource = "SELECT MyID, MyField FROM MyTable"
  If Len(Me!cmbMyCombo.Text)=3 Then
     strRowSource = strRowSource & " WHERE MyField Like '" 
     strRowSource = strRowSource & Me!cmbMyCombo.Text
     strRowSource = strRowSource & "*'"
     Me!cmbMyCombo.RowSource = strRowSource
     Me!cmbMyCombo.DropDown
  End If

当您在组合框中键入内容时,在您键入 3 个字符(或 2 个或 4 个字符或任何适合将下拉列表过滤为人类可用记录数的任何内容)之前,什么都不会发生,此时行源已分配(并且,如果您愿意,您可以在该点下拉列表,使其更加用户友好)。从那时起,它将像任何普通的组合框一样工作。

如果您需要使用相同的组合框来显示未输入的记录中的数据,那么您可以将组合框的默认 Rowsource 设置为:

  PARAMETERS [Forms]![MyForm]![MyField] Text ( 255 );
  SELECT MyID, MyField FROM MyTable WHERE MyField = [Forms]![MyForm]![MyField];"

然后在你的 OnChange 事件中,你会这样做:

  Dim strRowSource As String

  strRowSource = "PARAMETERS [Forms]![MyForm]![MyField] Long; "
  strRowSource = strRowSource & "SELECT MyID, MyField FROM MyTable "
  strRowSource = strRowSource & "WHERE MyField = [Forms]![MyForm]![MyID]"
  strRowSource = strRowSource & "UNION SELECT MyID, MyField FROM MyTable"
  If Len(Me!cmbMyCombo.Text)=3 Then
     strRowSource = strRowSource & " WHERE MyField Like '" 
     strRowSource = strRowSource & Me!cmbMyCombo.Text
     strRowSource = strRowSource & "*'"
     Me!cmbMyCombo.RowSource = strRowSource
     Me!cmbMyCombo.DropDown
  End If

然后在表单的 OnCurrent 事件中,你会这样做:

  Dim strRowSource As String

  strRowSource = "PARAMETERS [Forms]![MyForm]![MyField] Text ( 255 ); "
  strRowSource = strRowSource & "SELECT MyID, MyField FROM MyTable "
  strRowSource = strRowSource & "WHERE MyField = [Forms]![MyForm]![MyField]"
  Me!cmbMyCombo.RowSource = strRowSource

这样做的目的是确保已分配给组合框绑定到的字段的任何值仍将显示。如果您有一个空白的 RowSource,那将不起作用,因此对该字段的表单当前值的引用并将其与过滤列表联合起来。

【讨论】:

【参考方案3】:

另一个人同意这将是一种让用户访问这些数据的疯狂方式。没有人会想要一次解析 100k + 条记录。我会提供一种预先过滤记录的方法,以便只显示当时感兴趣的记录。

【讨论】:

【参考方案4】:

所以您真正需要的是“自动完成”功能,就像在互联网浏览器中看到的那样?当您说组合框时,每个人都会在下拉菜单中看到用户选择项目的画面——您可能想澄清您的问题。

【讨论】:

Access 组合框已经具有自动完成功能。需要的是过滤返回的结果。【参考方案5】:

尝试诸如增量填充组合框之类的东西。例如标签搜索在 Stack Overflow 中的工作方式,或 Google Suggest 的工作方式。 65k 对于组合框来说已经足够了。普通用户会发现即使从 65 种东西中选择也很困难

【讨论】:

+1 表示“65k 是……足够了”。让人想起“640K 就够了……”。【参考方案6】:

作为一般规则,当您在通用且广泛使用的组件(如组合框)上遇到硬编码限制时,是时候重新考虑您的方法了。组合框不是为您的用例设计的,也不足以满足您的用例。从您的项目中退后几步,重新评估您的 UI。也许 ListView 或过滤的数据网格会更合适。

【讨论】:

Access 列表框与 Access 组合框具有相同的限制。 Access 中没有 ListView 或数据网格(您为什么要费心建议一些不存在的东西?),但对于许多记录来说,子表单都很好。这种情况下的问题是过滤问题,而不是选择使用的控件。【参考方案7】:

65536 确实是组合框项目数量的限制。

我建议使用带有搜索按钮的文本框从列表中查找某人,而不是在这种情况下使用组合框。

作为替代方案,您可以根据插入的文本动态加载项目。

您还可以尝试通过先前在表单上输入的值“预过滤”组合框,以使返回的记录数低于允许的最大值。例如,如果您的表有 100,000 个名称和地址,您将让用户输入(在使用组合框之前)一个邮政编码,或用于过滤组合框查询 RecordSource 返回的记录数的状态。


@Steven A. Lowe 和 amdfan:你知道combobox 是什么吗?为什么叫它组合框?它是一个与列表框相结合的文本框。您输入一个文本,列表框会显示与您的文本匹配的第一个条目。

所以,我想这是一个合理的问题。

【讨论】:

是的,我愿意 - 为了可用性,下拉列表部分不应超过几十个项目。 这完全取决于组合框中的加载是如何实现的。 你一定是在开玩笑 - (a) 列表中的 65535 行太多,即使它立即加载,(b) 组合框列表不会包含所有项目;现在,如果您的意思是“增量加载”,那就不同了……【参考方案8】:

创建一个文本框和列表框的组合并不难,在文本框的更改事件中重新查询列表框,逐步缩小选择的项目。这意味着您的用户仍然可以看到一个名称列表,而不是猜测,而是一个更短且更相关的列表。

以下是此类列表框的 RowSource 的示例 SQL:

SELECT tp.PersonKey, 
   tp.Surname & ", " & tp.Forename AS PersonName
FROM tblPersons tp
WHERE tp.Surname 
LIKE Forms!MyForm!txtSurname.Text
ORDER BY  tp.Surname, tp.Forename

注意使用文本框的Text属性,这样可以确保使用文本框的当前内容,但也意味着文本框不能被重新查询,除非txtSurname有焦点,这很好,因为重新查询应该只能在 txtSurname 的 change 事件中完成。

【讨论】:

更简单的方法是在组合框的 OnChange 事件中分配组合框的行源 -- 涉及的控件更少并且可以自我记录。 这可能会遇到很多困难,这可以从 Allen Browne 的示例 allenbrowne.com/ser-32.html 中看出【参考方案9】:

在现实世界中很难使用,组合框存储 155k 条记录,我认为如果将其更改为 [...] 浏览按钮或其他控件,我认为比这种方式更易于使用

【讨论】:

【参考方案10】:

如果您有一个巨大的列表框,那么我会将其替换为子表单对象内的表格(或表单)。组合框和列表框限制为 65,536 个对象,与子表单中的表、查询或表单相比,它们的加载速度较慢。我在一张表中有 100,000 条记录,它会在瞬间加载。它也很容易滚动,比列表框快得多,这意味着您不需要缩小选择范围。我的子表单下方通常也有一个简单的搜索框。

这有点棘手,因为您必须从父表单引用子表单,反之亦然,但是将所有组合/列表框代码转换为子表单代码非常容易。例如如果您想在单击子窗体中的条目时在主窗体中找到匹配的记录:-

Private Sub POLICY_NO_Click()
    Set Me.Parent.Recordset = CurrentDb.OpenRecordset("qryHPolicy")
    Me.Parent.Recordset.FindFirst "[POLICY_NO]=" & Me.POLICY_NO & ""
End Sub

或将子表单设置为与主表单相同的记录源:-

Forms(Me_FormTo).Form.RecordSource = Me_RecSource
Forms(Me_FormTo).Combo6.Form.RecordSource = Me_RecSource

您可以让新子表单的外观和工作方式与列表框完全一样,因此当您拥有超过 64k 条记录时,绝对值得一试。

【讨论】:

以上是关于从包含 155K 记录的表中获取仅在组合框中列出的 65K 记录的主要内容,如果未能解决你的问题,请参考以下文章

从组合框中获取数据并使用它来获取另一个组合框中的数据

使用 group by 从一个包含批量记录的表中获取一些统计数据并将结果放入第二个表中

在列表框中显示所有记录

从使用 LINQ 的 ID 引用的表中获取记录名称

从组合框中选择时,Access 添加新记录

将不同的表连接到 C# 组合框中的不同项目