假设您正在使用微软访问设计销售报告。您有2个参数:Startdate和EndDate。
在运行报告时,我可以想到三种方法来提示最终用户输入这些参数。
使用2个文本框和一个按钮创建一个表单。按钮运行报告,报告按名称返回表单以获取开始日期和结束日期。
创建一个包含2个文本框和一个按钮的表单。该按钮运行报告,但通过docmd.openreport命令设置适当的过滤器。
将报告基于查询并定义查询参数。 Access将自动逐个提示这些参数。
哪种方式最好?
答案 0 :(得分:7)
哪个最好取决于许多因素。首先,如果要运行不带参数的报表,则不希望在报表的记录源中定义它们。这也是你的第一个建议的问题,它将报告与表单联系起来(从Access / Jet的角度来看,在记录源的SQL中声明的PARAMETER与表单控件引用之间几乎没有区别;实际上,如果你做得对,每次使用表单控件引用时,都会将其定义为参数!)。
在这三个中,最灵活的是您的第二个建议,这意味着无需打开表单即可运行报表,无需在运行时提供参数。
你遗漏了两种可能性,这就是使用Form的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 :(得分:1)
我以前使用Docmd.Openreport Where子句,你的选项2.但是我已经切换到在报告Open事件中使用报告过滤器,你的选项1,因为它支持创建Where子句没有的PDF文件。请参阅我的网站上的Microsoft Access Report Printing Criteria Selection Form。
至于SQL字符串中的日期,我使用格式语句Return Dates in US #mm/dd/yyyy# format
此外,您可以通过在报告记录源SQL查询中的条件中添加以下示例来处理您的选项三。窗体!FORM_NAME!Control_Name。对于那些不想进入VBA的人来说,这通常更简单。