【问题标题】:MS Access: Filter/Search records in a form using main form and subform criteria from user inputMS Access:使用来自用户输入的主表单和子表单条件过滤/搜索表单中的记录
【发布时间】:2011-09-06 12:10:40
【问题描述】:

我目前正在开发一个相当复杂的数据库,至少就我的能力水平而言。本质上,它是一个项目、结构和联系人的数据库。在这些结构中有子结构,每个结构都具有独特的属性。

项目、结构和联系人在一个带有选项卡式窗格的主控件表单中连接在一起。在这些窗格中是具有多个子表单的表单。我正在尝试编写一个可以放置在每个表单上的搜索功能,该功能将允许用户选择多个条件来过滤结果。但是,某些标准或表单和其他标准是从多个子表单中提取的,并且最重要的是,子表单中的某些字段具有多个条目。我知道这听起来可能不像是非常完善的数据库设计,但有人告诉我要坚持特定的结构和布局,但我不够熟练,无法完成。

我一直在浏览 allen browne 的网站以了解搜索条件,但这只是一个单一的表单。我也尝试拼凑 Subquery 教程页面,但无济于事。本质上,我想知道是否有可能过滤信息说..主窗体上的结构类型,然后例如..一系列数字,例如存在于子窗体中的长度和对象接近度它存在于另一个子表单中,并拥有它,以便主表单仅显示满足子表单和主表单的标准组合的记录。

如果这含糊不清,我深表歉意,如果它会有所帮助,我可以发布迄今为止我为我的数据库所拥有的一般框架。感谢您提供的任何帮助。

编辑---添加了更多信息的截图 我无法发布图片,因为我的代表低于 10,但希望我可以包含链接

http://img829.imageshack.us/img829/1594/99258898.png http://img40.imageshack.us/img40/2186/27578829.png

在这里很难看到,但在组合框中有些是多值列表。而右边第一张图片上的组合框,是根据左上角组合框中的类型选择切换的,具有不同的属性。理想情况下,我希望能够搜索主要表单和子表单。并导致仅满足所有用户输入数据的记录。现在我已经尝试使用过滤器,每个条件一个,但所做的只是清除子表单中与过滤条件不对应的信息。

【问题讨论】:

    标签: ms-access search filter vba


    【解决方案1】:

    您有任何可以发布的屏幕截图吗?

    在我看来,这听起来像是一个更大的设计问题,可能主要在您的 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     
    

    这几乎完善了我通常使用的多条件过滤解决方案。

    【讨论】:

    • @HK1 我已包含指向我的数据库的一些屏幕截图的链接,它旨在成为一个工程数据库,用于存储从联系人、公司、角色到结构类型特定信息的各种属性。
    • 感谢您的帮助。我会试试这个。
    • 我的代码中有一些错误会阻止它正常工作。我已经修复了它们,我还将 Option2 过滤与 Option3 过滤分开,这样你就可以看到不同之处。一旦你得到它,一切都非常简单。
    • @HK1 你的方法很好用,除了我的一些字段是 ID #,它使用查找表将数字转换为 companyID 1 = "some Company Name" 为文本以显示在屏幕。我不完全确定如何将用户输入的通配符说“城市”,然后找到潜在的等效 company_ID 号码并将其拉起以显示其中包含这些 company_ID 的记录。另外,是否可以将 SQL 字符串输入到上面的过滤器结构中?我一直在尝试弹出一些 SQL 字符串,但它要么什么都不做,要么抛出错误。
    • 您可以在过滤器中包含 SQL 字符串,只要它们不包含 WHERE 关键字。这就是过滤字符串。
    【解决方案2】:

    我为几乎所有的 Access 应用程序创建了复杂的表单查询界面。为什么?因为我的用户想要他们!我的网站上有some screenshots of some older examples,但没有一个真的很清楚。关键是我正在即时编写 SQL,并根据是否有针对该表的条件来选择是否查询特定表。

    我可以说更多,但它很快就会变成专有信息。如果这些看起来是您想要的方向,您为什么不创建一个包含足够信息的新问题,以建议如何根据这些原则完成。

    【讨论】:

    • 感谢 David 的投入,当我进一步进入设计过程并更熟悉 SQL 语句创建时,我一定会提出一个新问题。您的 DB Schema 看起来与我想要达到的目标相似,但是我在 SQL 和 VBA 方面非常不熟练,因为到目前为止我唯一的正规教育是关于数据库理论的单一 3 年 cpsc 大学课程。
    • 我只有一个学期的计算机课程,即 1982 年施乐 Sigma IX 上的大型机 BASIC。没有课程也可以学习这些东西。
    猜你喜欢
    • 2015-05-27
    • 2018-12-11
    • 1970-01-01
    • 2020-10-15
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多