在 microsoft access 中提示报告参数的最佳方式

Posted

技术标签:

【中文标题】在 microsoft access 中提示报告参数的最佳方式【英文标题】:Best way to prompt for report parameters in microsoft access 【发布时间】:2009-07-08 20:44:27 【问题描述】:

假设您正在 microsoft access 中设计销售报告。您有 2 个参数:Startdate 和 EndDate。

我可以想到 3 种方法来在报表运行时提示最终用户输入这些参数。

创建一个带有 2 个文本框和一个按钮的表单。 Button 运行报表,报表按名称引用表单以获取开始日期和结束日期。

创建一个包含 2 个文本框和一个按钮的表单。该按钮运行报告,但通过 docmd.openreport 命令设置适当的过滤器。

报告基于查询并定义查询参数。 Access 会自动一一提示输入这些参数。

最好的方法是什么?

【问题讨论】:

【参考方案1】:

哪个最好取决于许多因素。首先,如果你想在没有参数的情况下运行报表,你不想在报表的记录源中定义它们。这也是您的第一个建议的问题,它将报告与表单联系起来(从 Access/Jet 的角度来看,在记录源的 SQL 中声明的 PARAMETER 和表单控件引用之间几乎没有区别;实际上,如果你做得对,任何时候你使用表单控件引用,你都会将它定义为一个参数!)。

在这三个中,最灵活的是您的第二个建议,这意味着无需打开表单,也无需在运行时提供参数即可运行报表。

您忽略了一种介于两者之间的可能性,那就是使用表单的 OnOpen 事件在运行时设置记录源。为此,您将使用 acDialog 参数打开要收集日期的表单,在填写完表单后将其隐藏,然后即时编写记录源。像这样的:

Private Sub Report_Open(Cancel As Integer)
  Dim dteStart as Date
  Dim dteEnd As Date

  DoCmd.OpenForm "dlgGetDates", , , , , acDialog 
  If IsLoaded("dlgGetDates") Then
     With Forms!dlgGetDates
       dteStart = !StartDate
       dteEnd = !EndDate
     End With
     Me.Recordsource = "SELECT * FROM MyTable WHERE DateField Between #" _
        & dteStart & "# AND #" & dteEnd & "#;" 
     DoCmd.Close acForm, "dlgGetDates"
  End If
End Sub

[编辑:IsLoaded() 是 MS 提供的函数。它对我所有的 Access 编码都非常基础,我忘记了它不是内置函数。代码:]

Function IsLoaded(ByVal strFormName As String) As Boolean
 ' Returns True if the specified form is open in Form view or Datasheet view.
  Const conObjStateClosed = 0
  Const conDesignView = 0

  If SysCmd(acSysCmdGetObjectState, acForm, strFormName) <> conObjStateClosed Then
     If Forms(strFormName).CurrentView <> conDesignView Then
        IsLoaded = True
     End If
  End If
End Function

现在,这种方法有一些优势:

    您可以预先填写日期,这样用户只需单击“确定”即可。

    您可以在多个位置重复使用该表单来收集多个表单的日期值,因为该表单并不关心它在哪个报告中使用。

但是,没有条件选择是否打开表单。

因此,我经常使用类模块来存储报告的过滤条件,然后检查相关的类模块实例是否在 OnOpen 事件触发时设置了过滤器值。如果设置了条件,那么我会即时为记录源编写 SQL,如果没有设置,我只使用默认记录源(以及在 OpenReport 参数中传递的任何过滤器)。在此设置中,您仅在收集条件并设置类模块实例后才运行报告。这种方法的优点是报表可以在两种上下文中的任何一个中运行,并且任何部分都不需要了解彼此的任何信息——报表只需要了解类模块的接口即可。

【讨论】:

+1。选项#3 不好有几个原因,包括。无法捕获和处理问题条目(例如第二个日期早于第一个日期,条目不是有效日期等)。小观察:您不需要在记录源字符串中使用日期分隔符 (#)(除非您的表单将这些框作为字符串,但不建议这样做)。 对这些日期的补充说明:切勿将未格式化的日期直接输入 SQL。如果您的语言环境不使用美国格式的日期,那么您将会得到一些令人讨厌的惊喜。我总是使用 DateToSQL() 函数,它将给定的日期转换为可以安全地输入原始 SQL 的规范字符串。 关于日期分隔符,它们对于声明为数据类型的字段是强制性的。而且,是的,我同意,如果您不在美国语言环境中,则需要提供 SQL 明确的日期值。我认为非美国地区的任何人都会在很久以前遇到并解决这个问题,但对于新手来说,这当然值得一提。 @David W. Fenton:“日期分隔符,它们对于声明为数据类型的字段是强制性的”——大概你的意思是“声明为 DATETIME”......无论哪种方式,你都错了。我知道你热衷于人们在发布之前尝试一下,所以试试这个:SELECT * FROM MyTable WHERE MyDateTime > '1990-01-01 00:00:00'; “标准表达式中的数据类型不匹配。”我尝试使用默认的“SQL89”模式和“SQL92”,都返回相同的错误。也许您没有在正确的上下文中进行测试,在这篇文章中非常清楚的是在 Access 中(再次阅读问题),而不是使用 DAO 或 ADO 或 ODBC 来查询 Jet/ACE 数据文件中的数据。您是否在 Access 中尝试过?看来你很明显没有。【参考方案2】:

我曾经使用 Docmd.Openreport Where 子句,您的选项 2。但我已切换到在报告打开事件中使用报告过滤器,您的选项 1,因为它支持创建 Where 子句不支持的 PDF 文件。在我的网站上查看Microsoft Access Report Printing Criteria Selection Form。

就 SQL 字符串中的日期而言,我使用 Return Dates in US #mm/dd/yyyy# format 处的 Format 语句

您的选项三也可以通过在报告记录源 SQL 查询的条件中放入以下示例来处理。 Forms!Form_Name!Control_Name。对于不想接触 VBA 的人来说,这通常更简单。

【讨论】:

虽然一开始比较“简单”,但一旦您需要在没有硬连线引用记录源中的外部表单的情况下使用报表,事情就会变得复杂。我见过很多使用这种“更简单”的方法构建的 Access 应用程序,其中相同的报表布局被保存 8 或 10 次,它们之间的唯一区别是记录源。 没有参数。但是用户不必学习 VBA,这可能是一项不可逾越的任务并且非常令人沮丧。当然,我希望任何访问 *** 的人都应该对 VBA 有一点了解。

以上是关于在 microsoft access 中提示报告参数的最佳方式的主要内容,如果未能解决你的问题,请参考以下文章

在 Microsoft Access 报告中获取两个计数之间的差异

打印前在 Microsoft Access 报告中运行 VBA

Microsoft Access 报告中每 10 行额外的空间

在 Microsoft Access 报告中的每个组之后重新编号页码

Microsoft Access 网格/表格控件

更改 Microsoft Access 报告上所有控件的字体