译者:Fbilo
VFP 开发组在对运行时增强工作的时候有几个目标,其中包括:
- 处理更多的报表输出类型,而不仅仅是打印和预览;
- 为报表输出使用 GDI+。这提供了一些显著的增强,比如精确得多的报表绘制、图像和字体的平滑缩放、以及象文本旋转那样的额外能力。
- 提供一个更灵活的多得、可扩展得报表系统;
在 VFP 9 以前,报表引擎是庞大的:它处理每一件事情-数据处理、对象定位、绘制、预览以及打印。此外,还有一些例外(字段中的UDF、组、变量表达式、带区的 OnEntry 和 OnExit 表达式等等),你不能在一个报表运行的过程中与它进行交互。
在 VFP 9 中新的报表引擎已经将责任拆分成了几块,报表引擎现在只负责数据处理和对象定位,一个新的对象 report listener 负责处理绘制和输出。由于 Report listener 是类,现在你可以以各种过去你只能梦想的方式来与报表输出过程进行交互。
VFP 9 同时包含了新旧两个报表引擎,因此你可以根据需要选择在哪个报表引擎下运行你的报表。不过,一旦你认识到了新报表引擎的好处,除非绝对必要,否则你是不会想再回头使用旧样式报表的。
新报表语法
VFP9支持使用就报表引擎运行报表;只要简单的使用跟过去一样的 REPORT 命令(尽管你可以使用一个新的命令来覆盖 REPORT 的行为,稍后你会看到)。为了获得新样式的报表行为,请给 REPORT 命令使用新的 OBJECT 子句。OBJECT 支持两种使用它的方式:通过指定一个 Report listener 或者指定一个报表类型。Microsoft 把它叫做“支持对象”的报表。
一个 Report listener 是一个提供新样式报表行为的对象。Report listener 基于的是 VFP 9 中一个新的基类 ReportListener。要告诉 VFP 去为一个报表使用一个指定的 listener,可以先建立这个 listener 类的实例,然后在 REPORT 命令的OBJECT子句中指定这个对象的名称。这里是一个例子:
loListener = createobject('MyReportListener')
report form MyReport object loListener
如果你不喜欢手动建立一个 listener 的实例,你可以通过指定一个 OBJECT TYPE 来让 VFP 自动为你生成一个:
report form MyReport object type 1
这些定义了的对象类型是:0 表示输出到一台打印机,1 为打印预览,4 为 XML 输出,5 为 HTML 输出。你还可以定义你自己的对象类型。
当你以这种方式运行一个报表的时候,在新的系统变量 _REPORTOUTPUT 中指定的那个应用程序(默认是 VFP 主目录下的 ReportOutput.APP)被调用,由这个应用程序来负责弄清楚应该为被指定的 OBJECT TYPE 建立哪个 listener 类的实例。
你可能就会想了:“可我的应用程序中有着成吨的报表。难道我得在整个应用程序中去搜索并修改每个 REPORT 命令吗?”。你走运了,有一个简单的办法可以避免这种麻烦:打开 SET REPORTBEHAVIOR 90 这个开关,可以将支持对象的报表设为默认。这就意味着当你使用 TO PRINT 子句的时候,REPORT 命令会表现得好像你指定了 OBJECT TYPE 0;当你使用了 PREVIEW 子句的时候,REPORT 命令会表现得好像你指定了 OBJECT TYPE 1。SET REPORTBEHAVIOR 80 则恢复到 VFP 8 以及更早版本的行为。如果在你应用程序中的大部分或者全部报表都能在支持对象模式下正常运行,那么可以选择在应用程序启动的时候 SET REPORTBEHAVIOR 90。由于新旧样式的报表在绘制方面的不同,你也许会需要对某些报表进行调整以使它们能在新样式报表系统下正常工作,因此或者对它们进行调整或者使用 SET REPORTHAVIOR 80 来运行这些报表。参见 VFP 帮助文件开头部分的“What’s New in Visual FoxPro”主题下的“Changes in Functionality for the Current Release”一节,以了解在向后兼容模式和支持对象模式两者在绘制上的区别。
ReportOutput.APP 主要是一个对象工厂(Object factory,一种设计模式);它为报表建立与其相配的 listener 的实例。它还包括一些提供 XML 和 HTML 输出的 listener。不过,由于它只是一个 VFP 应用程序,所以你可以通过设置 _REPORTOUTPUT 来把它替换成你自己的应用程序。请在发布你的应用程序给你的用户时确保带上了 ReportOutput.APP(或者你自己所做的对它的替代品),这样你的应用程序才能使用支持对象的报表。
- 在第七章“在运行时扩展报表系统”中会讨论更多关于 ReportOutput.APP 和 report listener 的细节。
现在让我们来看一下运行时增强的某些特点。
新的预览窗口
匆匆一看,在图25中显示的 VFP 9 预览窗口看上去好像跟过去版本中的它并没多少不同。不过,请仔细看一下这里面的工具栏。
注意这个工具栏里面现在有一些新的按钮允许你去指定一次显示几页。图26展示了一次显示四页的情况(你必须把这个报表的缩放比例调整到25%以一次看到全部这四页)。
还有你要注意的是:现在你可以将报表放到到超过100%了:200、300和500%都支持。这在新旧样式的预览窗口中都有效。不过在缩放比例很高的时候,旧样式预览窗口显示的是有锯齿的文本、而新样式预览窗口显示的是平滑的文本;这里正好演示了 GDI+ 相对于 GDI 的优点。另一个新特色是一个快捷菜单,它的菜单项重复了工具栏上这些功能,加上允许你显示或者隐藏工具栏。
最后,试一下下面这个:
_screen.Forms[2].Caption = 'This is my report'
这是对的——预览窗口是一个 VFP 表单而不是一个纯粹的窗口。这就意味着你可以完全控制它的表现,而想在过去版本中这么做可是有点痛苦的。当你在支持对象模式下运行一个报表的时候,该预览窗口将被使用;否则,被用到的将是以前版本 VFP 中的同一个窗口。
VFP 9 有一个新的系统变量 _REPORTPREVIEW,用于为报表指定一个提供预览窗口的 VFP 应用程序。默认情况下,该变量指向的是在 VFP 主目录下的 ReportPreview.APP,但你如果需要的话可以把它替换成你自己的应用程序。你也可以用其它方式指定用于输出的这个表单;不过要讨论具体怎么做就超出本章的范围了。跟其它新的 VFP 模块一样,如果你的应用程序要使用新的报表预览窗口,请确保为了它而在发布的安装包中包含 ReportPreview.APP 或者你自己对它的替代品。
进程反馈
当一个报表运行时间很长的时候,你也许需要有一种途径告诉你的用户正在发生什么事情。这个任务ReportOutput.APP 中内建的 UpdateListener 类可以做到,当报表正在处理中的时候它能显示其进度,并提供 Cancel 的能力(见图27)。你可以根据需要禁用这个功能、或者使用一个 report listener 来提供你自己的(进度控制)。在第七章“在运行时扩展报表系统”中有它的一个示例。
图27、UpdateListener 类显示一个报表的进度,并给予用户 Cancel 的能力
HTML 和 XML 输出
尽管从过去几个版本开始你就可以使用 GenHTML.PRG 来将一个报表输出到 HTML,可坦白的说,结果不怎么样。幸运的是,在 VFP 9 中,你可以使用在 ReportOutput.APP 中内建的某些 listener 来建立高质量的 HTML 和 XML 输出了。
Listener type 5 指定 HTML 输出,而 type 4 用于 XML 输出,因此你可以使用下面的命令来输出到 HTML:
report form MyReport object type 5
不过,这里并没有给予你对要建立的文件名称或者其它设置的控制。(如果你要控制的
下面的代码(取自XMLOutput.PRG)用 EmployeesMD 报表的开头六页建立一个名为 MyReport.XML 的 XML 文件,只包含数据。在这个案例里使用了 ReportOutput.App 中的 XMLListener 类(type 4)。
loListener = .NULL.
do (_reportoutput) with 4, loListener
loListener.TargetFileName = 'MyReport.xml'
loListener.QuietMode = .T.
loListener.XMLMode = 0 && 0 = data only, 1 = layout only, 2 = both
report form EmployeesMD object loListener range 1, 6
图28、VFP 9 提供了来自报表的高质量 HTML 输出
图29、使用 XMLListener 类,你可以为一个报表建立只包含数据、只包含报表布局、或者同时包含前两者的 XML
HTML 输出其实是先使用 XML Listener 来生成 XML,然后使用 XSLT 来生成最终的 HTML 结果。
这两种 listener 类都有着一些你可以用来更多的控制输出的其它属性。参见 VFP 帮助文档以了解更多详情。
图形文件输出
有了一个 Report listener,你还可以输出到一个图形文件。VFP 9 支持 EMF、TIFF(单页和多页)、JPG、BMP、PNG以及GIF。第三方的 listener 也可以支持其它格式的文件。
这里是一些简单的代码,取自 GraphicOutput.PRG,它输出 EmployeesMD 报表中的一页到一个 GIF 文件。图30 展示了这个生成的 GIF 文件。
loListener = createobjet('ReportListener')
loListener.ListenerType = 3
report form EmployeesMD object loListener range 1,1
loListener.OutputPage(1, 'MyReport.gif',104) && 104=GIF
比如这个 GIF 图像
参见第七章“在运行时扩展报表系统”以了解关于这个主题的详情。
PDF怎么办?
当然了,你现在该问“PDF怎么办?”了。VFP 9 支持的输出中还没包括 PDF。不过,目前有几种你可以从 VFP(包括9.0以及以前的版本)获得PDF输出的途径:
- 使用 Adobe Acrobat 或者象 Print2PDF 这样的别的PDF编辑器;
- 使用一个支持 PDF 输出的 VFP 专用第三方工具,比如 Mind’s Eye 报表引擎、XFRX、或者 FRX2Any。大多数这些工具的开发人员正在、或者已经完成了他们的工具的 VFP 9 版本。
- 通过指定打印到一个适当的驱动来输出一个 PostScript 文件,然后使用免费软件 GhostScript 工具来将它转换成一个 PDF 文件。
其它打印增强
在 VFP 9 中有着大量的其它通用打印增强。
显示页设置对话框的 SYS(1037) 有了一些新的功能。首先,这个对话框看上去就跟过去的不一样了:
图31、在 VFP 9 中(右边的图)的 SYS(1037)跟它在 VFP8 中的对应物(左边的图)相比,有着更摩登的界面
其次,它现在有了一个返回值,可以指示用户在这个对话框里是按下了 OK(“1”)还是 Cancel(“0”)。
然而,最大的变化是,现在你可以传递一个参数给它来告诉它该干什么。传递给它0或者不传递参数给它将显示默认的页设置对话框。要为一个特定的报表显示、并可能会改动页面设置,请将该报表作为一个表来打开(就是 USE MyReport.FRX),然后调用 SYS(1037,1)。你可以使用SYS(1037,2)(该命令将默认的打印机设置写入到被作为一个表打开在当前工作区中的一个FRX 文件中)和 SYS(1037,3)(该命令将默认的打印机设置设置为那些在一个打开在当前工作区中的FRX文件中的信息)来保存或者恢复默认打印机信息;这两个命令都不会显示页面设置对话框。它们通常被用来推入和弹出打印机设置。
APRINTERS()现在可以接收一个新的可选参数1,在这种情况下结果数组有三个列,分别显示驱动器、注释、和位置。
象 SYS(1037)对话框一样,当你在 REPORT 命令中使用 PROMPT 关键词时被显示的打印对话框有了一个更摩登的表现(图32)。
图32、在 VFP 9 中随 REPORT 命令的 PROMPT 子句显示的对话框(右边的图像)比 VFP 8 中的(左边的图)有着更摩登的界面
总结
VFP 9 在报表引擎上改动的数量令人难以置信。这些改动使你可以更轻松的使用报表编辑器、使得建立你过去无法或者很难做到的类型的报表成为了可能,并提供了新类型的输出。此外,VFP 开发组还为在设计时和运行时扩展报表引擎的能力提供了至关重要的钩子;我们将在接下来的两章中讨论这方面的细节。你可以期待着发现 VFP 报表的大量新用法,并且将来还会发现更多。
更多资料:www.sn58.cn