建立自己的报表预览程序
作者:张洪举 Microsoft Visual FoxPro MVP (http://www.vfptop.com)
日期:2005年10月
应用于:Microsoft Visual FoxPro 9.0
目录
概述
Visual FoxPro 9.0 的报表预览应用程序接口
建立自己的报表预览程序
使用建立的报表预览程序预览报表
概述
可以通过 ReportListener 的 PreviewContainer 属性指定一个自定义报表预览程序,来代替 Visual FoxPro 默认的 ReportPreview.app 程序。
在 Visual FoxPro 的辅助对象模式下预览一个报表或标签时,ReportListener 需要一个附加的组件来提供预览界面,这个组件被称为预览容器。预览容器是用 Visual FoxPro 代码编写的,因此用户可以自己建立预览容器。
ReportListener 可以通过 ReportListener 的 PreviewContainer 属性指定一个预览容器对象,也可以通过 _REPORTPREVIEW 系统变量指向一个预览容器对象。_REPORTPREVIEW 的默认值为 ReportPreview.App,ReportPreview.App 是 Visual FoxPro 的默认报表预览程序。
Visual FoxPro 9.0 的报表预览应用程序接口
建立自定义报表预览程序一个很重要的问题,是如何获得对 ReportListener 对象的引用,从而控制 ReportListener 的行为。为了实现这个目的,在你建立的报表预览程序中必须包含一个名为 SetReport 的方法,ReportListener将通过该方法将自身引用传递给你的预览程序。该方法的语法格式如下:
PROCEDURE SetReport
LPARAMETER oListenerRef
oListenerRef 参数便是对 ReportListener 对象的引用,你可以通过该参数,将对 ReportListener 对象的引用保存到一个属性或变量中。
同时,在你建立的报表预览程序中还必须包含一个名为 Show 的方法,ReportListener 在报表绘制完毕后将调用该方法进行报表显示。假设已经建立了一个 ControlPreview 类作为我们的预览容器,下面是调用该类时的代码。
lcReport=HOME(2)+"Solution\Europa\EmployeesMD.frx"
oListener = CREATEOBJECT('ReportListener') &&建立ReportListener对象,并保存到oListener变量中
olistener.ListenerType = 1 &&设置输出模式
oListener.OutputType = 1
*!* 下面的代码用于指定预览容器
olistener.PreviewContainer=NEWOBJECT("ControlPreview","AdditionSamples.vcx")
*!* 下面的 REPORT FORM 命令将开始执行报表,同时将执行 ControlPreview 的 SetReport 方法,
*!* 传递 ReportListener 对象引用给 ControlPreview,但是由于此时报表还未绘制完毕,所以并不
*!* 能获得报表的总页数、页面高度等信息。在绘制完毕后,ReportListener 将调用 ControlPreview
*!* 的 Show 方法,进行预览输出,由于此时报表已经准备完毕,所以你可以在 Show 方法中获得
*!* 报表的页面高度等信息
REPORT FORM (lcreport) OBJECT oListener NOWAIT
建立自己的报表预览程序
我们将通过下面的示例来说明建立自己报表预览程序的方法,任何报表都可以使用该程序进行预览输出。为了更好地说明这个预览程序的功能,首先来看一下设计完成后的执行效果,如图1 所示。通过这个预览程序,可以设置报表的显示百分比、通过导航或直接定位要预览的页,以及指定报表的打印范围。
图1 报表预览程序界面
1)建立基于 Form 的类
在 Visual FoxPro 的 Command 窗口中执行 CREATE CLASS 命令,打开如图2 所示的 New Class(新建类)对话框。设置新建类的名称为 ControlPreview,基于 Form 类,存储在 AdditionSamples.vcx 类库中。
设置完成后单击 OK 按钮,将打开 Class Designer (类设计器)对话框,最终设计结果如图3 所示。
图2 New Class 对话框
图3 ControlPreview 类最终设计结果
2)表单的关键属性设置
表单的关键属性设置如表1所示。
表1
对象 | 属性 | 值 | 说明 |
ControlPreview (表单) | AllowOutput | .F. | 不允许将“?”等命令显示输出到该表单中 |
nCurrentPage | 1 | 自定义属性。储存当前正在显示的报表页号 | |
nPageHeight | 100 | 自定义属性。存储当前报表页面的高度 | |
nPageWidth | 100 | 自定义属性。存储当前报表页面的宽度 | |
oListener | .NULL. | 自定义属性。存储通过 SetReport 方法传递给该程序的对 ReportListener 对象的引用 | |
ScrollBars | 3 | 设置表单根据需要显示水平和垂直滚动条 | |
cboPer | RowSourceType | 1 | RowSourceType 和 RowSource 用于设置组合框中可用的报表显示百分比 |
RowSource | 25,50,100,150,200,500 | ||
cmdTop | Caption | |< | 该按钮用于导航到报表的第一页 |
cmdPrev | Caption | < | 该按钮用于导航到报表的上一页 |
cmdNext | Caption | > | 该按钮用于导航到报表的下一页 |
cmdBott | Caption | >| | 该按钮用于导航到报表的最后一页 |
cmdPage | Caption | 指定页 | 该按钮用于显示 txtPage 文本框中指定的报表页 |
txtPage | Value | 1 | 该文本框用于显示当前预览页面的页号,也可以在其中输入一个页号,然后单击 cmdPage 按钮定位到该页 |
optPrint | ButtonCount | 2 | 该对象是表单中的选项按钮组,具有2个按钮 |
BorderStyle | 0 | 不具备边框 | |
Value | 1 | 默认选定第一个按钮 | |
Option1.Caption | 打印所有页 | 选定该按钮后,表单中的 txtFrom 和 txtTo 文本框将变为禁止状态 | |
Option2.Caption | 打印指定页 | 选定该按钮后,表单中的 txtFrom 和 txtTo 文本框将变为可用状态 | |
txtFrom | Value | 1 | 默认值为1 |
Enabled | .F. | 在表单启动时,默认为禁止状态 | |
txtTo | Value | 1 | 默认值为1 |
Enabled | .F. | 在表单启动时,默认为禁止状态 | |
cmdPrint | Caption | 打印(\<P) | 该按钮根据打印选择输出报表到打印机中 |
cmdClose | Caption | 关闭 | 该按钮用于关闭表单 |
shpPreview | 用于显示报表的形状对象 |
3)预览程序的初始化设置
在预览程序的初始化部分,需要获得对 ReportListener 对象的引用,然后通过这个引用,获得报表的页面尺寸,进而设置表单中 shpPreview 对象的大小。
预览程序的初始化设置不能在表单的 Init 事件进行,因为在该类实例化的时候,有可能 ReportListener 对象还未建立,或者 ReportListener 还未进行报表处理,所以此时你无法获得报表的任何信息。根据前面的介绍,ReportListener 是通过预览程序的 SetReport 方法将 ReportListener 传递给预览程序的。因此,在表单中需要新建一个 SetReport 方法,代码如下:
LPARAMETERS oListenerRef
This.oListener = oListenerRef &&将对ReportListener对象的引用保存到表单的oListener属性中
ReportListener 在报表绘制完成后,将调用预览程序的 Show 方法显示表单。由于此时报表已经绘制完成,所以可以在此方法中获得报表页面的高度、宽度值,进而设置 shpPreview 对象的大小。由于表单对象默认地具有 Show 方法,因此,只需要在该方法中填入下列代码即可。
LPARAMETERS nStyle
WITH This
IF VARTYPE(.oListener) = "O"
.nPageHeight = .oListener.GetPageHeight() / 10 &&获得页面的像素高度(每英寸96DPI)
.nPageWidth = .oListener.GetPageWidth() / 10 &&获得页面的像素宽度
.shpPreview.Height = INT(.nPageHeight) &&设置形状的高度
.shpPreview.Width = INT(.nPageWidth) &&设置形状的宽度
.Caption = "报表预览程序-" + .oListener.CommandClauses.File &&标题中包含有报表的文件名称,见图13-68
.Refresh
ENDIF
ENDWITH
DODEFAULT(nStyle) &&执行默认的Show方法行为
4)报表显示比例设置
在表单的 cboPer 组合框的 InteractiveChange 事件中包含有下列代码,用于根据选择的显示比例设置 shpPreview 形状的大小,然后重新输出报表。
WITH Thisform
IF VARTYPE(.oListener) = "O"
.shpPreview.Height = INT(.nPageHeight * VAL(.cboPer.Value) /100)
.shpPreview.Width = INT(.nPageWidth * VAL(.cboPer.Value) /100)
.oListener.OutputPage(.nCurrentPage, .shpPreview, 2)
ENDIF
ENDWITH
5)报表导航设置
“|<”按钮用于导航到报表的第一页,其 Click 事件代码如下:
WITH Thisform
.nCurrentPage = 1
.oListener.OutputPage(1, .shpPreview, 2) &&显示第一页
.CmdRefresh() &&设置按钮的可用状态
.txtPage.Value = 1
ENDWITH
“<” 按钮用于导航到当前报表的上一页,其 Click 事件代码如下:
WITH Thisform
.nCurrentPage = .nCurrentPage - 1 &&当前报表页号减1
.oListener.OutputPage(.nCurrentPage, .shpPreview, 2) &&显示指定页
.CmdRefresh() &&设置按钮的可用状态
.txtPage.Value = .nCurrentPage
ENDWITH
“>”按钮用于导航到当前报表的下一页,其 Click 事件代码如下:
WITH Thisform
.nCurrentPage = .nCurrentPage + 1 &&当前报表页号减1
.oListener.OutputPage(.nCurrentPage, .shpPreview, 2) &&显示指定页
.CmdRefresh() &&设置按钮的可用状态
.txtPage.Value = .nCurrentPage
ENDWITH
“>|”按钮用于导航到报表的最后一页,其 Click 事件代码如下:
WITH Thisform
.nCurrentPage = .oListener.OutputPageCount
.oListener.OutputPage(.nCurrentPage, .shpPreview, 2) &&显示最后一页
.CmdRefresh() &&设置按钮的可用状态
.txtPage.Value = .nCurrentPage
ENDWITH
“指定页”按钮用于导航到在txtPage文本框中指定的页号,其 Click
WITH Thisform
IF .txtPage.Value >= 1 AND .txtPage.Value <= .oListener.OutputPageCount
.nCurrentPage = .txtPage.Value
.oListener.OutputPage(.nCurrentPage, .shpPreview, 2)
Thisform.CMDRefresh
ELSE
=MESSAGEBOX("页号无效或已经超出了总页数",0+48,"提示")
ENDIF
ENDWITH
在上面5个按钮的Click事件中都使用了表单的自定义方法 CMDRefresh 来控制“|<”、“<”、“>”和“>|”按钮的可用性,该方法的代码如下:
WITH This
.cmdPrev.Enabled = VARTYPE(.oListener) = 'O' and .nCurrentPage > 1
.cmdNext.Enabled = VARTYPE(.oListener) = 'O' and ;
.nCurrentPage < .oListener.OutputPageCount
.cmdTop.Enabled = VARTYPE(.oListener) = 'O' and .nCurrentPage > 1
.cmdBott.Enabled = VARTYPE(.oListener) = 'O' and ;
.nCurrentPage < .oListener.OutputPageCount
ENDWITH
6)打印设置
在选项按钮组 optPrint 的 InteractiveChange 事件中包含有下列代码,用于控制 txtFrom 和 txtTo
IF This.Value = 1
Thisform.txtFrom.Enabled = .F.
Thisform.txtTo.Enabled = .F.
ELSE
Thisform.txtFrom.Enabled = .T.
Thisform.txtTo.Enabled = .T.
ENDIF
“打印”按钮的 Click 事件代码如下所示。在执行打印后,将关闭表单。请注意其中的 .oListener.PreviewContainer = .NULL. 代码,在执行 RELEASE Thisform 命令前,必须首先使用该代码释放对预览程序对象的引用,否则是无法关闭表单的。对于打印页范围的选择,是通过 CommandClauses 属性的 PrintRangeFrom 和 PrintRangeTo 成员来实现的,有关这方面的信息请参考 Visual FoxPro 帮助。
WITH Thisform
DO CASE
CASE .optPrint.Value = 1 &&打印所有页
.oListener.CommandClauses.PrintRangeFrom = 1
.oListener.CommandClauses.PrintRangeTo = .oListener.OutputPageCount
.oListener.PreviewContainer = .NULL. &&取消对预览程序对象的引用
.oListener.OnPreviewClose(.T.) &&输出到打印机
.oListener = .NULL.
CASE .optPrint.Value = 2
IF .txtFrom.Value < 1 OR ;
.txtFrom.Value > .oListener.OutputPageCount
=MESSAGEBOX("开始页号设置无效!", 48, "提示")
RETURN
ENDIF
IF .txtTo.Value < 1 OR ;
.txtTo.Value > .oListener.OutputPageCount
=MESSAGEBOX("终止页号设置无效!", 48, "提示")
RETURN
ENDIF
IF .txtFrom.Value <= .txtTo.Value
.oListener.CommandClauses.PrintRangeFrom = .txtFrom.Value
.oListener.CommandClauses.PrintRangeTo = .txtTo.Value
.oListener.PreviewContainer = .NULL. &&取消对预览程序对象的引用
.oListener.OnPreviewClose(.T.) &&输出到打印机
.oListener = .NULL.
ELSE
=MESSAGEBOX("开始页号必须小于或等于终止页号!", 48, "提示")
ENDIF
ENDCASE
RELEASE Thisform &&关闭表单
ENDWITH
7)报表的重绘设置
在调整表单大小时,表单中的对象会被重新绘制,这时候需要重新输出报表到表单的形状对象 shpPreview
在表单的Paint事件中加入下列代码,用于重绘时的报表输出。
WITH This
IF VARTYPE(.oListener)="O"
.oListener.OutputPage(.nCurrentPage,.shpPreview,2)
ENDIF
ENDWITH
8)表单关闭设置
在表单关闭前,首先要释放 ReportListener 的 PreviewContainer 属性对报表预览程序对象的引用,否则,该表单无法关闭。在表单的 QueryUnload 事件中包含有下列代码,当单击表单标题栏的关闭框时,将执行该事件中的代码。
WITH This
IF VARTYPE(This.oListener) = 'O'
.oListener.PreviewContainer = .NULL. &&释放对报表预览程序对象的引用
.oListener.OnPreviewClose(.F.) &&关闭预览
ENDIF
.oListener = .NULL.
ENDWITH
表单中“关闭”按钮的 Click 事件与表单的 QueryUnload
IF VARTYPE(Thisform.oListener) = 'O'
Thisform.oListener.PreviewContainer = .NULL.
Thisform.oListener.OnPreviewClose(.F.)
ENDIF
Thisform.oListener = .NULL.
RELEASE Thisform
使用建立的报表预览程序预览报表
至此,这个报表预览程序就设计完毕了,使用这个报表预览程序进行输出的代码如下:
lcReport=HOME(2)+"Solution\Europa\EmployeesMD.frx"
oListener = CREATEOBJECT('ReportListener') &&建立ReportListener对象,并保存到oListener变量中
olistener.ListenerType = 1 &&设置输出模式
oListener.OutputType = 1
olistener.PreviewContainer=NEWOBJECT("ControlPreview","AdditionSamples.vcx") &&指定预览程序
REPORT FORM (lcreport) OBJECT oListener NOWAIT