建立自己的报表预览程序
作者:张洪举 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
683

被折叠的 条评论
为什么被折叠?



