您有任何可以发布的屏幕截图吗?
在我看来,这听起来像是一个更大的设计问题,可能主要在您的 UI 中,但也可能在您的表格结构中。我尝试遵循的一个我自己的原则是限制单个屏幕/表单执行或显示的操作数量。你的描述听起来让我很困惑,我认为普通用户很容易被它淹没。
通常子表单是主表单的结果。也就是说,它们包含子记录,并通过子记录外键和主表单主键链接到主表单中的记录。并不是没有其他方法来设计您的表单,但这被认为是“正常”或“标准”设计。您的描述表明过滤主表单是由子表单上设置的过滤器确定的。我想我想不出任何可能需要通过像这样令人困惑和笨拙的东西来解决的问题。我没有遇到像您正在处理的那么困难或复杂的事情的可能性。
我认为您可能很难在这里获得更好的帮助,因为您的问题确实更适合 UtterAccess.com 等讨论论坛。您可以考虑在这样的网站上发布您的数据库副本,以便用户可以查看您的设计并可能推荐更可靠和标准的方法。
编辑1:
1)根据您的屏幕截图,我认为您试图以一种形式做太多事情。我通常会使用您的每个顶部选项卡(项目、结构、公司、联系人)并将每个选项卡设为自己的表单。 Access 2007 和 2010 允许您在本地使用选项卡式界面,我想不出使用选项卡式容器控件开发您自己的选项卡式界面有什么真正的好处。
2) 我认为搜索通常应在具有单个列表框、数据表视图子窗体或连续窗体子窗体的单个主窗体中执行。您选择这三个中的任何一个都不是很重要。执行搜索后,用户应该能够单击列表框或子表单中的结果记录以选择该记录并在类似于您在此处构建的详细信息视图表单上移动到该记录。可能需要几个不同的搜索屏幕才能让您的用户以您希望他们搜索的所有不同方式进行搜索。例如,您可以构建一个屏幕来搜索项目,一个来搜索结构,另一个来搜索联系人,第四个来搜索公司。应该可以将其中的一些组合到一个查询中,并允许用户根据多个条件进行搜索,但是如果您尝试允许他们一次搜索太多字段,尤其是如果他们正在搜索的字段是在单独的表格中。例如,如果您构建一个同时显示所有项目、结构和公司的查询,并将其用作数据表子表单的记录源,这可能允许用户按项目、结构或公司进行搜索。但是,如果一个项目有 10 个结构,则该项目将在查询/表单中列出 10 次,如果他们正在考虑按项目搜索,这可能会使用户感到困惑。如果他们改为按结构搜索,那么对他们来说,同一个项目有 10 个条目是完全合理的,因为他们会看到 10 个不同的结构。
我的基本建议是,小心不要尝试将太多函数构建到一个表单中。有些类型的任务或数据集确实需要具有多个子表单和大量控件的复杂表单,但通常您希望尽量避免这种情况。最好为每个表单构建一个非常专注的任务,然后简单地构建更多表单来完成所有必要的任务。当然,您也可以将这种方法做得过火,但您确实需要尽量减少复杂性,以免将来让自己头疼。
至于基于多个标准的过滤,我会看看是否能找到任何好的示例,或者将一个放在一起并使其可用。这并不难,但这是一个多步骤的构建过程,经验使我得到了一个令我满意的总体设计,并且在所有可能的情况下都几乎完美无缺。
编辑2:
以下是创建多字段过滤器/搜索的方法。
1) 构建您的查询。包括需要用户查看或用户搜索的所有表格和字段。您可以在此处包含将被搜索但用户无法查看的字段,尽管这可能会让用户感到困惑。保存您的查询并给它一个适当的名称。请务必包含您的 id/主键字段,因为在第 4 步中将需要这些字段。
2) 现在在导航窗格中突出显示您的查询,转到顶部菜单并选择创建 > 更多表单 > 数据表(我使用的是 Access 2007)。允许访问创建并向您展示我们将用作子表单的数据表表单。保存并给它一个适当的名称,例如 fsubProjectSearch 的 subformProjectSearch。
3) 获取刚刚创建的新表单的设计视图。更改属性以禁止添加、删除和编辑,除非您真的想允许任何这些操作。一般来说,我不允许在这些类型的搜索表单中输入任何数据,除非我有很好的计划和测试。
4)转到此表单的代码并添加代码以在双击时弹出相关的详细表单。例如,在 projectid 或项目名称字段中,允许您的用户双击以显示项目详细信息表单。将双击例程添加到用户可能想要弹出结构、公司或联系人的任何其他文本框,假设您已选择在查询中包含一个或多个。您的代码将类似于 DoCmd.OpenForm "ProjectDetails", , , "ProjectID = " & Me!ProjectID 现在再次保存您的表单并关闭它。
5) 现在创建一个新的空白表单并将您的第一个表单添加为子表单。在顶部留出空间以添加过滤控件。此表单不需要设置任何记录源。
转移:我通常采用两种不同的过滤方法之一。第一个是给用户一个他们可以输入的文本框。我认为使用他们输入的数据在一大堆不同的字段中进行模糊搜索。这是一种非常糟糕的方法性能明智,特别是当数据库增长超过大约 20,000 条记录时。它也可能导致一些混乱,因为对于简短的通用搜索可能会出现太多结果。如果他们只输入字母 s 并搜索它,他们可能会得到几乎所有的记录。
我使用的第二种方法可能更常见。为他们可能想要搜索的每个字段提供不同的文本框。如果适合他们正在搜索的字段,您还可以将其设为复选框或组合框。这些不会是绑定控件。这允许用户获得相当具体的信息,并且最有可能返回他们正在寻找的确切结果。就代码而言,我不认为一种方法真的比另一种简单得多。使用我在此处列出的任何一种方法,您确实需要检查他们输入的数据类型,然后再将其放入某些字段的过滤器语句中。例如,您不希望尝试使用其非日期文本输入来过滤日期字段。在第二种方法中,您可以通过使用验证规则、输入掩码或设置文本框格式属性来消除更多此问题。组合还有助于防止输入不正确的数据。
第三种选择在某种程度上是一种混合方法。您可以创建一个文本框来搜索多个字段,但不必搜索所有字段。例如,您可以创建一个文本框,用于搜索公司、名字或姓氏。您可以根据需要创建任意数量的这些文本框。如何使用这些文本框中的输入将完全由您在 VBA 代码中决定。
6) 既然您已决定要采用哪种方法,您可以继续添加控件。给他们适当的名字和标签。
7) 现在是时候创建将构建过滤语句的函数了。使用我在下面列出的两个想法之一。确保在用户按下搜索按钮或控件 AfterUpdate 事件时运行这些。
Private Sub txtSearch_AfterUpadate()
Call FilterSubformOption1
End Sub
Private Sub FilterSubformOption1()
Dim strFilter as String
Dim sSearch as String
sSearch = Replace(Nz(Me.txtSearch, ""), "'", "''")
If sSearch <> "" Then
If IsDate(sSearch) = False Then
strFilter = "(ProjectName LIKE '*" & sSearch & "*' OR "
strFilter = strFilter & "StructureName LIKE '*" & sSearch & "*' OR "
strFilter = strFilter & "CompanyName LIKE '*" & sSearch & "*')"
Else
strFilter = "ProjectDate = #" & CDate(sSearch) & "#"
End If
End If
If strFilter <> "" Then
Me.fsubProjectSearch.Form.Filter = strFilter
Me.fsubProjectSearch.Form.FilterOn = True
Else
Me.fsubProjectSearch.Form.Filter = ""
Me.fsubProjectSearch.Form.FilterOn = False
End If
End Sub
Private Sub FilterSubformOption2()
Dim strFilter as String
If Nz(Me.txtProjectName, "") <> "" Then
strFilter = "ProjectName LIKE '*" & Replace(Me.txtProjectName, "'", "''") & "*' AND "
End If
If Nz(Me.txtStructureName, "") <> "" Then
strFilter = strFilter & "StructureName LIKE '*" & Replace(Me.txtStructureName, "'", "''") & "*' AND "
End If
If Nz(Me.txtCompanyName, "") <> "" Then 'Search on multiple fields from one textbox
strFilter = strFilter & "CompanyName LIKE '*" & Replace(Me.txtCompanyName, "'", "''") & "*' AND "
End If
If IsNull(Me.txtProjectDate) = False Then
If IsDate(Me.txtProjectDate) = True Then
strFilter = strFilter & "ProjectDate = #" & Me.txtProjectDate & "#"
End If
End If
If Right(strFilter, 5) = " AND " THEN strFilter = Left(strFilter, Len(strFilter) - 5)
If strFilter <> "" Then
Me.fsubProjectSearch.Form.Filter = strFilter
Me.fsubProjectSearch.Form.FilterOn = True
Else
Me.fsubProjectSearch.Form.Filter = ""
Me.fsubProjectSearch.Form.FilterOn = False
End If
End Sub
Private Sub FilterSubformOption3()
Dim strFilter as String
If Nz(Me.txtProjectName, "") <> "" Then
strFilter = "ProjectName LIKE '*" & Replace(Me.txtProjectName, "'", "''") & "*' AND "
End If
If Nz(Me.txtStructureName, "") <> "" Then
strFilter = strFilter & "StructureName LIKE '*" & Replace(Me.txtStructureName, "'", "''") & "*' AND "
End If
If Nz(Me.txtName, "") <> "" Then 'Search on multiple fields from one textbox, the "hybrid" solution
strFilter = strFilter & "(CompanyName LIKE '*" & Replace(Me.txtName, "'", "''") & "*' OR "
strFilter = strFilter & "FirstName LIKE '*" & Replace(Me.txtName, "'", "''") & "*' OR "
strFilter = strFitler & "LastName LIKE '*" & Replace(Me.txtName, "'", "''") & "*') AND "
End If
If IsNull(Me.txtProjectDate) = False Then
If IsDate(Me.txtProjectDate) = True Then
strFilter = strFilter & "ProjectDate = #" & Me.txtProjectDate & "#"
End If
End If
If Right(strFilter, 5) = " AND " THEN strFilter = Left(strFilter, Len(strFilter) - 5)
If strFilter <> "" Then
Me.fsubProjectSearch.Form.Filter = strFilter
Me.fsubProjectSearch.Form.FilterOn = True
Else
Me.fsubProjectSearch.Form.Filter = ""
Me.fsubProjectSearch.Form.FilterOn = False
End If
End Sub
这几乎完善了我通常使用的多条件过滤解决方案。