作者:Cathy Pountney,Visual FoxPro MVP,www.frontier2000.com
翻译:张洪举,Visual FoxPro MVP,www.vfptop.com
应用于:Visual FoxPro 9.0
概述: 学习Visual FoxPro 9.0报表书写器的新增功能包括新增的可重用数据环境、报表保护和用户界面增强。你可以从中学习到对布局对象的增强、对国际用户的改进、对打印和对数据分组的增强。此外,也可以学习到报表书写器的两个最大改进:多细节带区和报表的可扩展功能。最后,你将学习到Visual FoxPro报表文件(FRX)的详细结构。
目录
前言
可扩展功能
数据环境
保护
用户界面增强
布局对象增强
国际化功能
打印增强
数据分组增强
多细节带区
FRX
结论
前言
微软在当前基于FRX结构的报表上投入了众多的开发者,在很大程度上改进了VFP 9.0的报表书写器。VFP 9.0的报表书写器与先前的VFP版本兼容,它是一个对新版本和老版本的成功融合。
可扩展功能
在VFP 9.0之前,报表引擎处理的事情包括:处理数据、对象位置、绘制、打印和预览,并没有挂钩到报表引擎和定制报表的方法,但是这在VFP别的应用领域中却可以。对于VFP 9.0报表书写器的最大改进就是新增的可扩展功能,报表设计器、报表引擎和预览容器都公开给了开发者。
报表生成器
VFP 9.0报表书写器包含了一个新增的设计时功能,叫做Builder Hooks(生成器挂钩)。公开了几个报表设计器事件和一个叫做Report Builder(报表生成器)的独立Xbase组件,这个组件可以被调用后处理这些报表设计器事件。这个组件也可以被用来调用你自己的对话框,扩展本地报表设计器的行为或者覆盖本地行为。
VFP为设计报表包含了一个可扩展的报表生成器应用程序,其包含有各种新增功能,并提供了一个很友好的用户界面。报表生成器由一个新增的系统变量_REPORTBUILDER控制。如果该变量为空,则显示原来版本的对话框。要调用生成器挂钩,可以设置该变量为一个适当的应用程序。例如,要使用VFP 9.0附送的报表生成器,可以执行下列命令:
_REPORTBUILDER = HOME() + "REPORTBUILDER.APP"
该文章中的某些部分假定使用原来版本的对话框,并且_REPORTBUILDER系统变量为空,其他某些地方则假定使用新对话框,并且_REPORTBUILDER系统变量设置为REPORTBUILDER.APP。如果你没有经历过我们描述的这种行为或没有看见过这个对话框,可以改变_REPORTBUILDER的值来体验一下。
报表引擎
在新的输出系统中(Object-Assisted Output),报表引擎用于处理数据中心的事务,如移动整个范围和表达式求值。但是,当建立输出时,它延迟对叫做ReportListener的新增基类的工作,该新增基类使用GDI+以一种更加高级的方法来绘制报表内容,并且它也给Xbase用户一个与输出过程相互作用的机会。图1显示了这些部分如何搭配在一起工作的。
图1 使用新增的ReportListener类来操纵报表
要使用ReportListener类,可以使用REPORT FORM命令的新增子句,如下所示:
oListener = CREATEOBJECT("ReportListener")
oListener.ListenerType = 1 && 预览,或设置为0进行打印
REPORT FORM <name> <clauses> OBJECT oListener
VFP 9.0也提供了第二种使用ReportListener类的方式,你可以设置新增系统变量_REPORTOUTPUT的值为一个基于ReportListener类的应用程序名称。
当使用Object-Assisted Output时,报表会根据它的ListenerType属性值设置,使用两种方式中的某个方式进行处理。你可以认为这两种方式是print-appropriate和preview-appropriate,或者是page-at-a-time和all-pages-at-once。在第一种方式中,在准备每页时,Listener触发一个OutputPage事件,例如在发送每页到打印机或打印队列时。
在第二种方式中,Listener为绘制和高速缓存报表准备所有的页面,在完成时,可以调用OutputPage方法来询问是按页号输出所有的页面还是输出其中的任意一个页面。
预览容器
在VFP 9.0中,另一个可扩展功能难题是预览容器。对于此挂钩,你可以使用由VFP 9.0附送的新预览容器,或者书写自己的预览容器。在不使用新增的object-assiste输出时,旧的预览容器仍旧可用。
新增的系统变量_REPORTPREVIEW可以用来包含预览容器的应用程序名称。缺省情况下,该变量指向ReportPreview.app。该应用程序比旧的预览程序包含了大量的改进,包括更多的缩放级别、工具栏控制、标题控制、多页预览和使用GDI+而带来的更加优良的显示品质。图2和图3显示了旧预览界面和新预览界面的差异。
图2 在旧预览容器中输出很不柔和
图3 新的预览容器含有更多优良性能和更多完善选项
注意旧预览容器和新预览容器之间在品质方面的差异。新容器比旧容器具有更加柔和的字体,这要归功于使用GDI+来输出信息;同时也要注意所停靠工具栏的差别,在新预览容器上的工具栏具有更多选项,包含多页布局按钮等。
传统输出
新增的SET REPORTBEHAVIOR命令可以用于打开或关闭Object-Assisted Output,新的输出绘制引擎和预览界面与旧类型的输出有相当大的差异,对齐、字母紧排和间距在GDI和GDI+之间是不同的,这会在很大程度上改变现存报表的查看结果。因此,REPORTBEHAVIOR默认设置值为80,即关闭Object-Assisted Output输出,报表处理按照VFP 9.0之前的方式进行。
如果你要全局性的打开Object-Assisted Output,可以在Options对话框中改变这个设置值(如图4所示),或者执行下面的命令:
SET REPORTBEHAVIOR 90
图4 使用Options对话框中的Run-time behavior(运行时行为)选项改变SET REPORTBEHAVIOR设置
在REPORTBEHAVIOR设置90时, REPORT FORM命令会与使用OBJECT子句一样来执行,而不需要改变代码,VFP使用_REPORTOUTPUT系统变量为每个REPORT FORM命令指定基于ReportListener类的应用程序。
通过VFP 9.0报表书写器中的新增扩展功能,你可以使用报表生成器、报表引擎和预览界面,你既可以全局地打开这些新增功能,也可以为各个报表逐个单独打开。也可以关闭这些新增功能,就象在先前VFP版本中运行一样。
数据环境
VFP 9.0报表书写器现在可以与其他报表共享数据环境,数据环境也可以被作为一个类进行保存,然后加载到所需要的报表中,这为定义公共报表需求提供了一个很好的数据重用解决方案。
另存为类
要将一个数据环境存储为类,可以在报表中定义数据环境时进行。当数据环境窗口处于活动状态时,从File菜单中选择新增的Save As Class...选项(参考图5)。
图5 当数据环境为活动窗口时,新增的Save As Class...选项会出现在File菜单上
在选择Save As Class...选项后,出现如图6所示的Save As Class 对话框。在保存一个报表的数据环境时,Save选项组DataEnvironment是惟一可用的选项按钮。
图6 为存储报表的数据环境,使用Save As Class对话框来声明新建类和类库的名称
在Name文本框中为类输入一个名称,接下来在File文本框中输入要保存的新建类的类库名称。如果所输入的类库名称不存在,则创建新类库文件,也可以使用省略(...)按钮来定位到一个已存在的类库。最后,你还可以输入对新建类的说明。
加载一个数据环境
除了手动为一个新建报表定义数据环境外,VFP 9.0也提供了从已有报表或已存储的DataEnvironment类中加载数据环境的选项。Report菜单上的Load Data Environment(加载数据环境)...选项(如图7所示)允许选择一个数据环境加载到当前报表中。
图7 使用Load Data Environment...选项从已有报表或DataEnvironment类中加载数据环境
注意:Load Data Environment功能仅在新增的ReportBuilder对话框中可用,你应当通过设置_REPORTBUILDER = HOME() + "ReportBuilder.app"来使用此功能
从报表加载数据环境
要从其他报表加载数据环境时,所有原数据环境的代码和成员会被复制到新报表中,这里的含义是:在复制后,再对原报表的数据环境的改变不会再影响到所建立的报表中。
可以从Report菜单中选择Load Data Environment...后打开如图8所示的Report Properties对话框,选择所要复制数据环境的报表到当前报表中。
图8 使用Report Properties对话框的Data Environment选项卡来选择你要复制数据环境的的报表
选择Copy from another report file(从其他报表文件复制)选项按钮后并选择Select...按钮,这会打开Open对话框,可以从中选择要复制的报表,一旦选择一个报表后,将出现一个确认对话框(如图9所示)。
图9 使用此对话框来确认要复制一个数据环境到当前报表中
VFP 9.0要从其他报表复制数据环境到当前报表,会通知你会覆盖当前数据环境,并且要单击Yes才可以继续执行,这说明你在当前报表数据环境中定义的任何内容都将被覆盖掉。如果单击No,报表不会发生变化并终止此过程,单击Yes时,数据环境被复制并出现如图10所示的提示对话框。
图10 该对话框确认数据环境已被成功复制到当前报表中
现在完成了复制数据环境,就可以按照程序需求来操作数据环境了。但是,需要注意的是,在这之后再对原来报表数据环境做的改变,并不会影响当前报表的数据环境。
从DataEnvironment类加载数据环境
当从一个类中加载数据环境时,一些代码会被添加到新建报表的数据环境中,用于绑定到指定的DataEnvironment类,并在运行时实例化这个类。这里的含义是:以后再对DataEnvironment类所做的改变会影响到所有使用这个类的报表。
使用如图8所示的Report Properties 对话框,单击Link to a visual DE class(连接到可视数据环境类)按钮,接下来单击Select...按钮来打开Open对话框,可以从中选择类库和要使用的类。在选择了一个类后,将会出现与图9同样的确认对话框,确认后,数据环境被更新,并且显示如图10所示的对话框,通知加载数据环境成功。
在此时,一些代码会被添加到数据环境的某些方法中,在一些方法中只具有十分简单的代码,如只有一个DODEFAULT()命令,其原因是在方法中只少要包含一行代码,否则BindEvents()函数不能运转。
数据环境代码
从一个类加载数据环境后,会自动添加一些代码到下面描述的几个方法中。
Init方法
在Init方法中的下列代码用于保证BindEvents()能按预定目标工作。
*-----------------------------------------------------*
* 此方法代码由报表生成器插入 *
*-----------------------------------------------------*
DODEFAULT()
BeforeOpenTables方法
下列代码在数据环境上建立了几个新属性,来支持被加载的DataEnvironment类的对象引用。接下来将该数据环境中的事件绑定到在DataEnvironment类中的相对应事件,但是,Init和Destroy事件不绑定。最后,DataEnvironment类的BeforeOpenTables事件被触发。
*-----------------------------------------------------*
* 此方法代码由报表生成器插入 *
*-----------------------------------------------------*
LOCAL loMember, laDEEvents[1], liMember, liMembers, loBoundMember
THIS.AddProperty( "BoundDE", NEWOBJECT( "de_insurance", "c:\vfp9\rwde.vcx" ))
IF VARTYPE( THIS.BoundDE ) = "O" AND UPPER( THIS.BoundDE.BaseClass ) = "DATAENVIRONMENT"
* 在这里绑定事件,跳过Init和Destroy事件
* FRX DE和它的成员只能具有基本事件,所以许多PEMSTATUS不是必需的
liMembers = AMEMBERS( laDEEvents, THIS, 3 )
FOR liMember = 1 TO liMembers
IF INLIST( UPPER( laDEEvents[ liMember, 1] ), "INIT", "DESTROY" )
LOOP
ENDIF
IF INLIST( UPPER( laDEEvents[ liMember, 2] ), "EVENT", "METHOD" )
BINDEVENT( THIS, ;
laDEEvents[ liMember, 1], ;
THIS.BoundDE, ;
laDEEvents[ liMember, 1] )
ENDIF
ENDFOR
* 现在做私有成员的检查,再次跳过Init和Destroy事件
FOR EACH loMember IN THIS.Objects
IF PEMSTATUS( THIS.BoundDE, loMember.Name, 5 ) AND ;
UPPER( PEMSTATUS( THIS.BoundDE, loMember.Name, 3 ) = "OBJECT"
loBoundMember = EVAL( "THIS.BoundDE." + loMember.Name )
IF ( loBoundMember.BaseClass == loMember.BaseClass )
liMembers = AMEMBERS( laDEEvents, loMember, 3 )
FOR liMember = 1 to liMembers
IF INLIST( UPPER( laDEEvents[ liMember, 1] ), "INIT", "DESTROY" )
LOOP
ENDIF
IF INLIST( UPPER( laDEEvents[ liMember, 2] ), "EVENT", "METHOD" )
BINDEVENT( THIS, ;
laDEEvents[ liMember, 1], ;
loBoundMember, ;
laDEEvents[ liMember, 1] )
ENDIF
ENDFOR
ENDIF
ENDIF
ENDFOR
THIS.BoundDE.BeforeOpenTables()
ENDIF
AfterCloseTables方法
在AfterCloseTables方法中的下列代码用于保证BindEvents()按预定目标工作。
*-----------------------------------------------------*
* 此方法代码由报表生成器插入 *
*-----------------------------------------------------*
DODEFAULT()
Destroy方法
添加到Destroy方法中的下列代码,用来解除报表数据环境方法与DataEnvironment类之间的绑定,该代码也移除对DataEnvironment类的对象引用。
*-----------------------------------------------------*
* 此方法代码由报表生成器插入 *
*-----------------------------------------------------*
LOCAL loMember
UNBIND( THIS )
FOR EACH loMember in THIS.Objects
UNBIND( loMember )
ENDFOR
IF PEMSTATUS( THIS, "BoundDE", 5 ) AND UPPER( PEMSTATUS( THIS, "BoundDE", 3 )) = "PROPERTY"
THIS.BoundDE = NULL
ENDIF
Error方法
在Error方法中的下列代码用于保证BindEvents()按预期目标工作。
*-----------------------------------------------------*
* 此方法代码由报表生成器插入 *
*-----------------------------------------------------*
LPARAMETERS nError, cMethod, nLine
DODEFAULT( nError, cMethod, nLine )
保护
在VFP 9.0中使用报表设计器或标签设计器时,可以为一个或多个布局对象建立保护。这就允许用户来修改一个报表,但是却可以保持某些对象不被改变。
设置保护标记
布局对象有5种可以设置的不同保护模式,Field(字段)对象具有一个额外的保护选项,Bands(带区)具有2个可以设置的保护模式,报表自身还具有多种可以设置的保护模式。
注意:新增的保护功能只能通过新增的ReportBuilder对话框进行设置,可以设置_REPORTBUILDER = HOME() + "ReportBuilder.app"来使用这些保护功能。
保护对象
要在报表设计器中保护一个布局对象,应当打开对象的Properties对话框进行设置。在选定对象后,可以从Report菜单中选择Properties打开Properties对话框。也可以单击右键后从对象的上下文菜单中选择,或者双击对象自动打开Properties对话框。图11展示了一个字段对象的Properties对话框的Protection(保护)选项卡。
图11 可以使用Properties对话框的Protection选项卡来设置布局对象的保护模式
可以为布局对象设置如下5种保护模式:
为Object cannot be moved or resized加上复选标记,可以防止用户在设计界面中移动布局对象到其他位置和防止用户调整对象的大小。
为Object cannot be edited加上复选标记,可以防止用户对对象的属性做任何改变。
为Object cannot be deleted加上复选标记,可以防止用户删除此对象。
为Object cannot be selected加上复选标记,可以防止用户选择此对象,在选择了此选项时,Object cannot be moved or sized、Object cannot be edited和Object cannot be deleted保护模式会被同时选定。
为Object is not visible in Designer加上复选标记,可以防止在保护模式的报表设计器中出现此对象,在选定该选项时,则其他4个选项的保护模式也会被同时选定。
该对话框的Design-time caption(设计时标题)部分仅用于Field对象,在该文本框中输入的字符串将在报表设计器中代替Field的Expression显示,这样做的好处是可以显示一些友好易用的信息,从而替代某些复杂的表达式显示。
保护带区
要在报表设计器中保护带区,可以选择带区的Properties对话框。可以从Report菜单中选择Edit Bands...菜单项打开Properties对话框,也可以从带区的上下文菜单中选择,或者双击带区中的灰色带区条来打开。图12显示了一个带区的Properties对话框的Protection选项卡。
图12 可以使用带区的Properties对话框的Protection选项卡来设置带区的保护模式
可以为带区设置如下两种保护模式:
为Band cannot be edited加上复选标记,可以防止用户见到Band Properties对话框。
为Band cannot be resized加上复选标记,可以防止用户调整带区大小。
保护报表
要设置整体的报表保护,可以打开Report Properties对话框进行设置。可以从Report菜单中选择Properties菜单项,或者从报表的上下文菜单中打开Report Properties对话框。图13显示了Report Properties对话框的Protection选项卡。
图13 可以使用Report Properties对话框的Protection选项卡来设置报表的整体保护模式
在对话框的上部,可以允许定义Report Properties对话框的哪个选项卡对于用户不可用。对于在该区域中的每个选择,Report Properties对话框的相应选项卡会禁止使用。Protection选项总是处于选定状态,并且不可用。Ruler/Grid选项不可用是因为该选项卡不能被保护,该选项之所以出现在这里,是为了和Report Properties对话框上的选项卡保持一致。
该对话框的下部允许哪个菜单选项对于用户不可用,对于在该区域中的每个选择,相应的菜单项会禁止使用。
使用保护标识
要在与报表设计器或标签设计器会话期间调用保护功能,必须在命令中使用如下所示的PROTECTED关键字:
CREATE REPORT MyReport PROTECTED
MODIFY REPORT MyReport PROTECTED
CREATE LABEL MyLabel PROTECTED
MODIFY LABEL MyLabel PROTECTED
如果没有使用PROTECTED关键字,则报表设计器不启用对于布局对象的保护功能。
用户界面增强
对于用户界面做的许多修改,可以使设计报表更加容易和直观。VFP 9.0彻底更新了菜单、上下文菜单,并在报表设计器工具栏上增加了许多新选项。Expression Builder对话框和Expression Builder Options对话框也增加了新功能,以及一些其他用户界面增强也被添加到VFP 9.0报表书写器中。
菜单
VFP 9.0中的菜单已被彻底更新,以适应新增的选项。此外,为了更加明确,一些原有菜单选项被重新标注,并且为了更加容易访问,一些选项被重复放置在几个菜单中。图14至图16展示了新菜单的变化。
图14 在File菜单上新增的“Save As Class...(另存为类)”选项
图15 为报表设计器工具栏新增的Report Designer Toolbar选项,并把Grid Lines、Show Position选项与其他选项进行分割开
图16 Report菜单上的更多变化,包括重新标注选项、新增选项和新增的Print Preview重复选项
上下文菜单
现在的上下文菜单也增加了一些菜单项,这样可以与所调用的对话框更加一致。在报表设计器中的一些项目,先前并不具有上下文菜单,但是现在可以了。图17至图19展示了这些新变化。
图17 全局上下文菜单所具有的新增选项和一个重新标注选项
图18 通过右键单击任何带区的灰色带区条可以打开新增的带区上下文菜单
图19 通过右键单击任何布局对象可以打开布局对象上下文菜单
工具栏
报表设计器工具栏也有一些新增的按钮,如图20所示。
图20 为页面设置和字体属性新增的按钮
Expression Builder(表达式生成器)对话框
Report Expression对话框具有了一些小改变,图21展示了这种变化,现在的对话框为输入报表表达式提供了更大的区域。
图21 在当前更高的Expression for Field on Report文本框中可以输入较长的表达式
在_REPORTBUILDER系统变量为空时,Expression Builder对话框原来的行为如下:仅在数据环境中定义的表的字段显示在Fields列表框中,但是在数据环境外打开的表在列表框中并不可用。
当_REPORTBUILDER系统变量设置为ReportBuilder.app时,Expression Builder的行为却大不相同。首先,在_GETEXPR中定义的Expression Builder会替代原来的Expression Builder。图22显示了默认的Expression Builder对话框。
图22 使用"From table"组合框从打开的表中选择字段
Expression Builder对话框现在具有了一个为Fields列表框中的字段选择数据表的组合框,但是,只有当前使用的数据表在组合框中才会列出。记住这一点是至关重要的,因为在数据环境中定义的表不会被报表设计器自动打开,因此,它们不会自动出现在组合框中。
之所以这样做,是因为当在应用程序中允许用户修改报表时,你可以控制哪些表对最终用户可用。如:你可能在数据环境中定义了一些你所需要的数据表,但是却不希望用户可以访问它们,所以,你可以明确地打开想让用户访问的表,而忽略掉那些要保护的表。
Expression Builder Options(表达式生成器选项)对话框
在Expression Builder Options对话框中的Field aliases选项组现在可用了,如图23所示。该选项组用于指定在从Expression Builder对话框中选择字段时是否添加表的别名到报表表达式中。
图23 使用Field aliases选项组可以指定在从Expression Builder对话框中选择字段时是否添加表的别名到报表表达式中
Always add alias(总是添加别名)和Never add alias(不添加别名)选项按钮指定VFP 9.0是否为所有字段自动添加表的别名,Add non-selected alias only(仅添加未选定的别名)选项按钮的行为受_REPORTBUILDER系统变量的值影响。如果_REPORTBUILDER系统变量为空,任何不是从数据环境InitialSelectedAlias属性所指定表中选择的字段将使用表别名作为前缀,从InitialSelectedAlias指定表中选择的字段则不使用表别名前缀。
如果_REPORTBUILDER系统变量设置为ReportBuilder.app,Add non-selected alias only选项的使用略有不同,在确定是否以表别名作为字段的前缀时,将以当前所选择的表别名代替InitialSelectedAlias指定的表别名。
除了从Expression Builder对话框选择字段之外,也可以从数据环境中拖放字段到报表设计器中,这会使用Field aliases选项组中的设置。与此相同,在Options对话框的Report选项卡中也新增了一个选项,如图24所示。该选项决定了为所有新建立的报表使用什么样的Field aliases默认设置。
图24 使用Options对话框的Report选项卡上的Expression Builder选项来设置默认Expression Builder行为
其他用户界面增强
几个对于用户界面的其他增强也改进了报表设计方式,详述如下。
鼠标形状
现在当对象可以被调整大小时,鼠标形状会进行相应变化,给予提示。如图25所示。
图25 使用新增的鼠标形状变化可以知道对象在什么时候可调整大小
Multiple Selection(多重选择)对话框
VFP 9.0现在具有了一个Multiple Selection对话框,可以一次为多个布局对象设置Protection和Print when属性,自然也可以改变其中任何单个布局对象的其他属性。要使用这个新增功能,可以在选择多个布局对象后,双击其中的任何一个对象来打开Multiple Selection对话框,如图26所示。
图26 使用Multiple Selection对话框的Selection选项卡选择要操作的布局对象
所选择的布局对象会在对话框打开时显示在对话框的第一个选项卡中,要对报表中的所有对象进行操作,可以在打开该对话框之前按CTRL+A来选择所有布局对象。
Sort by(排序)选项允许对布局对象列表按在报表中的Type(类型)或Location(位置)进行排序,Remove from list(从列表中删除)按纽从列表中删除选定的布局对象,双击列表中的任何项目,则打开与该对象对应的Properties对话框。Multiple Selection对话框的Properties选项卡,用于改变在Selection选项卡中所列出全部项目的属性,如图27所示。
图27 使用Multiple Selection对话框的Properties选项卡一次改变所有选定对象的Protection属性和Print when逻辑条件
选择Apply these protection settings to the selected objects(应用保护设置到选定对象)复选框来打开Protection选项;选择Apply this condition to the selected objects upon saving(应用下面的条件到选定对象)复选框来打开Print when选项,在改变了Protection和Print when的设置后,可以单击OK按钮关闭对话框并保存这些改变到所有Selection选项卡中列出的布局对象中。
更多缩放级别
Preview窗口具有了更多的缩放级别,如图28所示。
图28 为了更好的可视性,可以使用在VFP 9.0预览新增的缩放级别
VFP 9.0对用户界面进行了许多改进,包括菜单、上下文菜单和工具栏。对Expression Builder对话框和Expression Builder Options对话框也增加了一些有效的选项,其他改进包括鼠标形状、Multiple Selection对话框以及更多报表预览的缩放级别。
布局对象增强
在布局对象中增加了一些小改进,包括控制模板字符的选项、对于字符表达式的剪裁模式,以及相对和绝对位置。
注意:要使用增强的剪裁模式,应当使用新增的 Object Assisted Output,或者直接通过ReportListener对象,或者通过间接的SET REPORTBEHAVIOR 90命令。
模板字符
Field Properties对话框现在具有了一个新增部分-Template characters,如图29所示,两个可用选项是Overlay(覆盖)和Interleave(插入)。这决定了如何使用在Format expression文本框中指定的字符串。
图29 Template characters决定了如何将格式化字符用于字段数据
在使用Overlay选项时,指定的格式化字符作为数据的一部分来对待,并且覆盖在格式化字符给定位置上的任何字符。例如,在Format expression为“999-999”时,并且字段数据包含“123456”,则报表显示为“123-56”,请注意其中的“4”是如何被Format expression表达式中的破折号给替换掉的。
在使用Interleave选项时,指定的格式化字符将插入到当前数据中。例如,在Format expression为“999-999”时,并且字段数据中包含“123456”,则报表显示“123-456”,请注意Format expression表达式中的破折号如何插入到了“3”和“4”之间。
为Character表达式指定剪裁方式
在VFP 9.0之前,在文本过长时,字段对象总是被剪裁到最近的单词。在VFP 9.0中,在Field Properties对话框上的一个新增选项可以指定剪裁文本的方式,如图30所示。
图30 使用Trim mode for character expressions来指定剪裁超长文本的方式
对6个剪裁选项说明如下:
选择Default trimming,将使用默认行为,与Trim to nearest word, append ellipsis选项是相同的,该行为类似VFP的先前版本,但是在字符后添加省略号。
选择Trim to nearest character,文本将被剪裁到恰好填充指定空间的最后完整字符。
选择Trim to nearest word,文本被剪裁到恰好填充指定空间的最后完整单词。
选择Trim to nearest character, append ellipsis,文本被剪裁到恰好填充指定空间的最后完整字符,并在打印文本的后面添加一个省略号(...)。
选择Trim to nearest word, append ellipsis,文本被剪裁到恰好填充指定空间的最后完整单词,并在打印文本的后面添加一个省略号(...) 。
选择Filespec: Show inner path as ellipsis,在全部文本不能被填充进指定空间时,长路径和文件名内的目录名会替换为省略号(...)。
大小和位置
布局对象的另一个新增功能是可以更好地控制对象的大小和位置,如图31所示。
图31 使用在Properties对话框上的Size and position in layout(大小和布局位置)选项来控制相对和绝对位置
在对象被添加到报表上时,From page top、From left、Height和Width的值是自动设置的,注意From page top属性值是相对于报表设计器中页顶部的位置,对象上方的所有灰色带区条的高度也会被考虑在内,改变From page top属性可能会不经意地移动对象到其他带区。
相对位置
From page top属性值和Height属性值将共同来确定是使用绝对位置还是相对位置。当From page top属性是一个报表设计器页面大小范围内的一个值时,并且Height的属性值小于或等于对象其所在带区的高度,则使用相对位置。相对位置需要对象在带区中,但是页标头和页脚注带区除外。
绝对位置
当From page top属性设置成了一个报表设计器页面范围大小之外的一个值,或者Height属性的值超过了对象所在带区的高度,则使用绝对位置,绝对位置的含义是对象将在每页中相同的精确位置进行打印。
绝对位置可以用于在报表上建立水印,例如,在页标头带区中放置一个图像,并设置为Scale contents, retain shape(缩放图片,保留形状)。改变From page top和From left属性来指定水印开始的左上角位置,改变Height和Width属性来指定水印的大小,并确认水印没有超出打印机的可打印区域。
国际化功能
在VFP 9.0中,报表在国际化支持方面有着更好的表现,特别是可以为字体设置字符集或语言脚本。网格单位具有了更多选项,并且STRCONV()函数也具有了更多选项。
FontCharSet
字体的字符集或语言脚本可以在Font对话框中设置,如图32所示。这可以为报表上的一个特定对象或整个报表设置默认字体。
图32 可以使用Script组合框选择一个字符集或语言脚本
网格单位
Set Grid Scale对话框现在增加了3个Ruler Scale(标尺刻度)选项来允许设置刻度为inches(英寸)或metric/centimeters(米/厘米),或者关闭标尺。这为具有不同系统默认设置的客户给予了更好的控制需求,图33显示了在Set Grid Scale对话框中的新增选项。
图33 为更好地控制标尺刻度,可以在Set Grid Scale对话框中使用新增的下拉组合框
与Set Grid Scale对话框相同的功能增强也被添加到Options对话框的Report选项卡中。
STRCONV()
VFP 9.0另一个对国际化报表的改进是修改了STRCONV()函数,现在可以使用该函数变化Locale ID的代码页和fontcharset(字符集)的值,下面的帮助文档解释了STRCONV()的新增功能。
STRCONV(cExpression, nConversionSetting [,nRegionalIdentifier[,nRegionalIDType]])
nRegionalIDType:
0 - 默认值, nRegionalIdentifier为Locale ID.
1 - nRegionalIdentifier为代码页
2 - nRegionalIdentifier为字符集
对于nConversion的设置值1、2、3、4、7和8,只有在nRegionalIdentifier=0时支持。
对于设计非英文报表,FontCharSet、网格单位和STRCONV()函数的改进在报表设计时更具灵活性。
打印增强
为了实现更好的打印功能,一些命令和对话框都被进行了增强和改进。SYS(1037)函数现在新增了一个参数,并且具有了返回值;GetFont()函数的对话框使用了新样式;APrinters()函数生成的数组现在具有3列元素。
SYS(1037)函数用于打开Print Setup对话框,以及用于改变VFP的默认打印机。在VFP 9.0的以前版本中,SYS(1037)函数没有实际意义的返回值,不管用户如何操作,总是返回一个空串。即使用户按下了Cancel按钮,你也无法捕获这个操作的信息。
在VFP 9.0中,一个新参数被添加到SYS(1037)中,并且函数具有了返回值,如表1所示。
表1 SYS(1037)的新增参数和返回值
参数 描述 返回值
SYS(1037) 除了可以返回一个具有实际意义的值,其行为与先前版本一样。 0 = 用户取消了操作
1 = 用户选择了OK按钮
SYS(1037,1) 如果当前工作区包含一个与FRX匹配的结构,并且没有打印机信息存储在当前工作区中,则打开页面设置对话框。如果用户在对话框中选择了OK按钮,VFP会在临时表的第一条记录的EXPR、TAG和TAG2字段中写入打印机信息,然后恢复临时表到先前的RECNO()记录位置。
如果当前工作区没有包含相应的结构,则没有对话框被激活,并且返回0。
0 = 用户取消了操作或表结构无效。
1 = 用户选择了OK按钮,对FRX进行了相应的更新。
SYS(1037,2) 如果当前工作区包含一个与FRX匹配的结构,VFP的默认打印机信息被写入到第一条记录的EXPR、TAG和TAG2字段中,然后恢复临时表到先前的RECNO()记录位置。
如果当前工作区不包含与FRX匹配的结构,则没有信息被写入到临时表中,并返回0。
0 = 表结构无效,无动作发生。
1 = VFP的默认打印机信息成功写入到FRX中。
SYS(1037,3) 如果当前工作区包含一个与FRX匹配的结构,FRX中的打印环境信息被作为VFP的默认打印机,此外,并将打印环境信息重新写入到FRX中,这就可以防止无效信息的发生。
如果当前工作区不包含与FRX匹配的结构,则没有信息被写入到临时表中,并返回0。
0 = 无动作发生。
1 = VFP从FRX中读取并设置默认打印机信息。
GetFont()
GetFont()函数有如下的一些小改动。
只显示可打印字体
GetFont()的第三个参数现在新增了一个可选值,可以传递P给函数,通知VFP只显示对于默认打印机的可打印字体,如下所示:
=GetFont(' ', 0, 'P')
FontCharSet(字符集)
在以前的VFP版本中,GetFont()的第4个参数用于识别FontCharSet。但是,现在传递0和1给第4个参数的含义有了一些变化。
传递0,允许使用字符集组合框,明确设置组合框的值为“西方,并返回FontCharSet和其他数据。
传递1,允许使用字符集组合框,设置组合框的值为用户的地区设置值,并返回FontCharSet和其他数据。
在以前的版本中,会忽略第4个参数,并禁止字符集组合框,并且返回值中不包含FontCharSet部分。
APrinters()
APrinters()新增了一个参数,用来搜集打印机的信息。使用可选的第2个参数,会使生成的数组比以前多出3个附加列,如下所示:
lnPrinters = APrinters(laPrinters, 1)
前面的两列与以前版本相同,是打印机名称和打印机端口。新增的3列分别是驱动程序、注释和位置。
调用APrinters(),如果不包含可选的第2个参数,则提供与先前版本相同的行为,即:只返回两列。
更具现代化的对话框
Print Setup对话框现在已经被更名为Page Setup,并且更具现代化。Print对话框在Windows 2000和以后的操作系统中也更具现代化。
Page Setup对话框
Page Setup对话框如图34所示,可以使用如下方法打开:
当报表设计器不是WONTOP()时,从File菜单选择Page Setup。
当报表设计器是WONTOP()时,从Report Page Setup对话框选择Page Setup按钮。
使用SYS(1037)命令。
图34 新Page Setup对话框代替了旧Print Setup对话框
Print对话框
Print对话框如图35所示,可以使用如下方法打开:
从File菜单选择Print。
在命令中使用TO PRINTER PROMPT子句,如REPORT FORM。
图35 在Windows 2000或更后期的系统中,新的Print对话框更具现代化
数据分组增强
VFP 9.0报表书写器在数据分组方面有一些小的增强。
数据分组最大值
数据分组的最大值已经从20增加到74。
水平列
在以前,报表中超过一列的位置被定义为一个数据分组水平面,浪费了许多空间。第一个位置(第1行,第1列)留下了许多空白,并且数据在第1行的第2列开始。同样的,在每个数据分组之间浪费了一个空白带,如图36所示。即使组标头带区的高度为0,VFP仍旧保留这个空间,如图37所示。带区条
图36 以前版本的VFP,在使用数据分组和水平列时浪费了许多的空间
图37 VFP的以前版本为组标头保留了空间,即使没有定义任何对象,也是这样
在VFP 9.0中,数据分组和水平列的行为发生了改变。当遇到一个数据分组时,将在下一个整行的第1列打印分组表达式的内容,该行的剩余部分作为遗留空白,并且不再用于打印细节内容。属于该数据分组的细节内容在分组打印行的后面的第1列开始打印,如图38所示。同样的,如果组标头的高度为0,则不再保留任何额外空间,如图39所示。
图38 在使用水平列和数据分组时,VFP 9.0不再象以前版本那样浪费空间
图39 在组标头带区设置为0高度时,VFP 9.0不再保留额外的空间
这种新行为,虽然避免了先前描述的浪费空间情况,但是可能会损坏一些已存在报表。不过,新行为的一个额外好处是:数据分组带区可以伸展为所有列的宽度,如图40所示。
图40 在VFP 9.0中,可以伸展组标头带区为多个列的宽度
多细节带区
除了在VFP 9.0报表书写器中的这些扩展性增强,新增的多细节带区功能是最大的改变,并且在报表中经常需要使用到这样的功能。该新增功能允许为父表的每条记录处理多个子表,一个这种类型报表的示例如图41所示。
图41 这个多细节带区示例报表的每个客户具有3个独立的细节带区
表和关系
作为多细节带区,理解父表和子表如何一起工作是理解如何使用这些新增功能的关键。假设要写一个如图41所示的报表,对于这种情况的数据库如图42所示。
图42 一个保险公司的Customer(客户)、Members(成员)、Vehicles(车辆)和Homes(住址)数据库
Customer表是父表,并且为保险公司的每个客户包含一条记录,Members、Vehicles和Homes表是Customer的子表。Members表为每个客户的家庭成员保留一条记录,Vehicles表为每个客户投保的车辆保留一条记录,Homes表为每个客户的住址保留一条记录。
驱动报表
将其中的一个报表用于驱动报表是必需的,在这个示例中,Customer表是驱动表,如果要使用报表的数据环境来定义表,可以设置InitialSelectedAlias属性为该表,如果要使用代码来定义表,要确认在报表运行时Customer表在当前工作区中。
Target Alias(目标别名)
目标别名是用于为一个特定细节带区描述哪个表是驱动表的术语,在这个示例中,Members表是细节带区1的目标别名,Vehicles表是细节带区2的目标别名,Homes表是细节带区3的目标别名。
如果没有为细节带定义目标别名,将使用VFP以前版本的行为,换句话说,细节带区将处理每个父表的记录。但是,如果输入了父表的名称作为目标别名,却会得到非常不同的结果。对于父表中的每条记录,VFP处理父表中的所有记录,即在细节带区打印父表的每个记录。因此,如果有一个具有10条记录的父表,并设置细节带区的目标别名为这个父表,则最终报表会打印10遍这10条记录,总共100条记录。
关系
了解关系在一个多细节带区中如何运作是相当重要的,VFP使用父表和子表之间的关系来定位所有记录,可以使用SET RELATION或SET SKIP来定义这些关系。如果在数据环境中打开了表,并且关系已经被定义在数据库中,则会自动使用这些关系。
如果使用代码打开表,下面的代码演示了如何为Insurance Customer Listing(保险客户列表)来设置表,如图41所示。
*-- 打开子表
USE Members IN 0 ORDER CustomerFK
USE Vehicles IN 0 ORDER CustomerFK
USE Homes IN 0 ORDER CustomerFK
*-- 打开父表
SELECT 0
USE customer ORDER CustomerPK
*-- 设置父表和子表之间的关系
SET RELATION TO CustomerPK INTO Members
SET RELATION TO CustomerPK INTO Vehicles ADDITIVE
SET RELATION TO CustomerPK INTO Homes ADDITIVE
*-- 运行报表
REPORT FORM Insurance PREVIEW
定义多细节带区
缺省情况下,新建立的报表只具有一个细节带区。
添加附加细节带区
附加细节带区可通过如图43所示的Optional Bands对话框添加,要调用这个对话框,可以从Report菜单中选择Optional Bands...。这是与以前Title/Summary相同的对话框,现在被重命名为Optional Bands,该名称更加符合添加附加选项。
图43 使用Optional Bands对话框上的Details微调控制来调节细节带区的总数
可以使用Details微调控制来添加报表所需要的细节带区数量,最多可以为每个报表定义20个细节带区。图44显示了选择3个细节带区后的报表设计器效果。
图44 该示例报表具有3个细节带区
定义Target Alias(目标别名)
目标别名通过Detail对话框赋值给一个细节带区(如图45所示)。该对话框可以从Report菜单中选择Edit Bands...,然后选择适当的细节带区来调用。也可以通过双击细节带区的灰色带区条来打开这个对话框。
图45 在Detail对话框上为每个细节带区定义Target alias
Target alias是一个表达式,因此,应当将表的名称放置在引号中,一旦定义了目标别名,表示细节带区的灰色带区条将显示目标别名,如图46所示。
图46 报表设计器把每个细节带区和一个数值以及与其关联的目标别名结合在一起,所以可以很容易地识别不同细节带区
在建立多细节带区报表时,在字段名称前面加上相应的别名是十分重要的,这可以防止产生字段是来自于哪个表的混乱情况。
标头和脚注
多细节带区的另一个增强功能是可以为每个细节带区增加标头和脚注,这在某些方面类似于组标头和组脚注。对于每个被处理的父记录,发生如下事件:
细节1的标头带区被处理。
细节1带区为与相关联目标别名中的每个子记录处理一次。
细节1的脚注带区被处理。
细节2的标头带区被处理。
细节2带区为与相关联目标别名中的每个子记录处理一次。
细节2的脚注带区被处理。
细节3的标头带区被处理。
细节3带区为与相关联目标别名中的每个子记录处理一次。
细节3的脚注带区被处理。
要打开细节标头和细节脚注带区,可以在每个细节带区的Detail对话框中复选Detail Header/Footer,如图45所示。为了帮助从其他带区中分辨出细节带区,细节带区前面的三角是实心的,其他三角则是空心的,如图47所示。
图47 细节带区标以实心三角,其他带区标以空心三角
除了在报表设计器中标识每个细节带区外,Edit Bands对话框也使用带区的连续数字来标明每个细节标头带区、细节脚注带区和细节带区。Edit Bands对话框可以从Report菜单中选择Edit Bands...进行调用,如图48所示。
图48 Edit Bands对话框使用每个细节带区的连续数字来帮助识别每个细节带区、细节标头带区和细节脚注带区
需要注意的是:对于一个特定的细节带区,即使没有细节带区记录存在,相应的细节标头和细节脚注带区仍旧打印,如果不希望细节标头和细节脚注出现这种情况,可以对带区中的每个布局对象使用下面的Print when逻辑条件来屏蔽这种打印操作,并要确认为这些布局对象复选 Remove line if blank选择框。
NOT EOF(<target alias>)
与组标头和组脚注类似,细节标头和细节脚注具有一些相同的选项,如图45所示。Detail对话框具有一些新增选项:
Start on a new column(从新列开始): 使用此选项使细节带集从报表的新列开始,注意此选项不允许显式地分配一个细节带集到一个指定列,如果一个细节带集的信息溢出了当前列,它将在下列中继续打印。
Start on a new page(从新页开始): 使用此选项使细节带集从一个新页开始打印。
Reset page number to 1 for each detail set(每个细节带集重置页号为1):使用此选项和Start on a new page选项,可以为每个新细节带集重置页号为1。
Start detail set on new page when less than(在空间不足时细节带集从新页开始): 使用此选项可以防止细节带孤立现象的发生,如果标明的空间总数不可用,细节带集从一个新页开始。
Detail Header/Footer(细节带标头/脚注): 使用此选项可以为细节带添加细节标头和细节脚注带区。
Reprint detail header on each page(在每页上重复打印细节标头): 使用此选项和Detail Header/Footer选项,每当细节带集溢出到一个新页时,将重复打印细节标头带区。
报表变量和计算
多细节带区的引入,报表变量和计算对此有一些的新变动。为了更好地使用它们,你需要完全了解它们是如何被处理的,否则,你可能不会得到所希望的结果。
Report Variables对话框上的Reset at提示已经被重命名为Reset based on(重置),这可以更加清晰地定义变量是随着哪个选定选项的值的变化而进行重置的。如果在报表中定义的细节带多于1个,则每个细节带被添加到下拉列表中,如图49所示。
图49 计算报表变量具有新增的Reset based on选项
选择细节带区作为Reset based on值,就是告诉VFP只在这个细节带区的目标别名中处理细节记录时处理这个计算,当记录在其他目标别名中被处理时,报表变量不发生改变,这就允许你可以连接一个报表变量到一个特定的细节带区,报表变量的值直到同一细节带区的细节标头改变为下一条父表记录进行处理时才被清除。
如果选择了一个细节带区之外的Reset based on值,则计算在下面几个地方被处理:首先,对于每条父记录,计算被进行,其次,计算在第一个细节带区的目标别名中进行,然后,计算在第二个细节带区的目标别名中进行,等等。
在如图50所示的两页报表中,你可以见到一个与特定细节带区相关联的计算报表变量的示例,你也可以见到在报表的末尾的Total records processed显示了一个值18,这个数值表示Members总计处理了7次,加上Vehicles总计处理了7次,加上Homes处理了4次。
图50 计算报表变量可以与一个细节带区关联或者可以用于所有记录
FRX 存储
带区存储在FRX文件中,OBJTYPE的值为9,并且OBJCODE的值用于确定带区的类型,细节标头带区的OBJCODE值是9,细节脚注带区的OBJCODE值是10。
新增的目标别名表达式存储在相应细节带区记录的EXPR字段中。
SUMMARY问题
使用REPORT FORM命令的SUMMARY子句可以阻止细节带区的打印,但是所有的页标头和脚注、列标头和脚注、组标头和脚注仍旧打印。在使用SUMMARY子句时,任何细节带区中的On Entry和On Exit表达式都不被处理。在一个多细节带报表中使用SUMMARY子句时,则细节标头、细节脚注和细节带区都不被处理。
更多需要学习的地方
动手处理多细节带区报表需要许多的时间,你需要理解所有的表是如何一起工作的,知道什么是目标别名(target alias),以及理解表与表之间的关系。你也需要知道变量和计算是如何受多细节带区影响的,在完全了解这些知识前,你需要多次通读这篇文章。
FRX
为保持向后的兼容性,VFP 9.0报表书写器仍旧使用与以前版本相同的FRX结构,OBJTYPE和OBJCODE字段共同用于定义记录中所包含的数据的类型,在FRX中的所有字段并不是都适用于所有的记录类型,因此,要接纳VFP 9.0报表书写器中的所有新增功能,现在的表结构是超负荷运转的。
VFP 9.0报表的另外一个关键的变化是USER字段的处理方式,在VFP 9.0之前,任何存储在USER字段中的数据会被删除,这种行为使得USER字段失去了意义,并且不可用。在VFP 9.0中,任何存储在USER字段中的数据会被保留,也可以在FRX中建立附加字段,只要将它们添加在FRX的末尾即可,任何附加字段会被VFP保留并且不会被删除掉。
除了保留USER字段之外,VFP 9.0报表书写器现在可以保留任何未知类型的记录,而不会从FRX中删除它们,报表书写器在FRX的末尾保留这些记录并在处理期间忽略这些记录,这给予了你为特定处理添加自己记录类型的能力。
理论上,在VFP 9.0中设计的报表,只要不使用任何新增功能,就可以在以前的Visual FoxPro版本中运行。自然,如果添加了新字段或记录到FRX中,并在一个先前的VFP版本中编辑和保存报表,这些字段将会被损坏。
记录
报表数据中存储有几种不同类型的记录,OBJTYPE字段用于标识每个记录的类型,并且根据OBJTYPE的标识,记录中的其余信息变化也非常大。换句话说,即表中的字段具有多个使用目的,需要通过OBJTYPE来解释其余字段的含义,OBJTYPE的有效类型如下所示:
报表定义 (OBJTYPE = 1): 表中的第一条记录是对于报表的定义记录,其中包含关于报表的总体常用信息,如打印机信息和页面设置信息。
报表对象: 几个不同的对象类型分别用于描述报表上的文本、数据和图形,所有这些对象作为报表对象被引用,它们有以下5种类型构成:
Label (OBJTYPE = 5): Label(标签)对象是用于描述报表上静态文本的术语,通常用于报表标题、列标题、公司名称和其他在每次报表打印时不需要改变的信息,报表上的每个label对象在表中由一条记录来表示。
Line (OBJTYPE = 6): Line(线条)对象用来表示报表上的垂直和水平线条,报表上的每个line对象在表中由一条记录来表示。
Shape (OBJTYPE = 7): Shape(形状)对象用于表示报表上的一个长方形和圆角矩形,报表上的每个shape对象在表中由一条记录来表示。
Field (OBJTYPE = 8): Field(字段)对象是报表上最常用的对象,用于在报表上打印数据,数据可以是来自于一个表的字段,或者是一个表达式的计算结果,甚至可以使用由VFP报表书写器提供的内部计算来得到结果。报表上的每个field对象在表中由一条记录来表示。
Picture (OBJTYPE = 17): Picture(图片)对象表示报表上的图片/ActiveX绑定控件,报表上的每个图片/ActiveX绑定控件在表中由一条记录来表示。
带区(OBJTYPE = 9): Band对象用于表示报表上的一个独立带区,报表上最少将具有3个带区对象:页标头、细节和页脚注带区。报表中也可以包含几个可选带区:标题、列标头、组标头、列脚注、组脚注、总结、细节标头和细节脚注带区。
分组(OBJTYPE = 10): Group对象用于表示一个报表对象的组,其含义是在报表设计器中,使用Format菜单中的Group选项将一些对象划分为一组,不要与数据分组混肴。
变量(OBJTYPE = 18): Variable对象用于表示一个单独的报表变量,报表中的每个变量在表中由一条记录来表示。
字体(OBJTYPE = 23): Font对象用于报表上的某些地方的惟一字体,用于报表上的每种不同字体在表中由一条font对象记录来表示,表中至少存在有一个font对象,即默认字体。
数据环境(OBJTYPE = 25): Data environment对象用于表示报表的数据环境,数据环境的所有属性和方法代码存储在该记录中。每个表中只有一个数据环境记录。
数据(OBJTYPE = 26): Data对象用于表示一个cursor对象或relation对象,每个定义在报表数据环境中的cursor或relation在表中由一条记录来表示。
存储在表中的记录按照一个特定的物理排序进行排列,如果你计划增加新记录,遵守这个排序是十分重要的。可以使用SORT命令复制记录到一个临时表中,然后按照正确的排序复制回报表,排序方式如下:
报表定义记录(OBJTYPE=1)
带区记录(OBJTYPE=9),带区按照OBJCODE字段的升序添加到表中,但是下列情况除外:
在报表上定义了多个数据分组时...
...组标头带区(objcode = 3)按它们出现在Data Grouping对话框中相同的顺序进行添加。
...组脚注带区(objcode = 5)按它们出现在Data Grouping对话框中相反的顺序进行添加。
在报表上定义了多个细节带区时,第一个细节带区的细节标头、细节和细节脚注作为一个集合来添加,然后是第2个细节带区集合,等等。
报表对象(OBJTYPE = 5、6、7、8和17)按照Z-顺序添加,最下面的对象首先添加。
分组记录(OBJTYPE = 10)
报表变量记录(OBJTYPE = 18),报表记录按照它们出现在Report Variable对话框中相同的顺序添加。
字体记录(OBJTYPE = 23)。
数据环境记录(OBJTYPE = 25)。
数据记录(OBJTYPE = 26)按照它们添加到数据环境的顺序添加。
度量单位
当引用报表上对象的大小和位置时,Visual FoxPro使用自己的度量单位-FoxPro Report Units(FRU)。如果你的系统设置为英寸,度量单位是1英寸的1/10,000,如果你的系统设置为厘米,度量单位是1厘米的1/1,000。
位置
在表中没有字段来表示对象属于什么带区,相反,Visual FoxPro通过计算每个带区定义的高度来确定带区、对象的VPOS,然后确定从哪个带区的VPOS开始。
在看到的每个带区的高度的同时,当通过报表设计器显示报表时,VFP也考虑用于表示每个带区的水平灰色条的高度。在使用英寸时,灰色条的高度是2083.33333333,使用厘米时,高度是529.16666667。
字段
要说明每个字段表示什么是很困难的,因为这些字段可以被用于不同的目的,字段表示的含义基于特定记录的OBJTYPE字段的值,表2列出了表中的每个字段和不同类型对象的含义。
除了表2,微软还提供了一个包含FRX表信息的DBF,位于HOME() + 'tools\filespec'目录中。
表2 VFP 9.0报表(FRX)的表结构
字段 OBJTYPE字段的值 说明
PLATFORM 全部 总是为WINDOWS
UNIQUEID 除了如下之外:
0-注释
23-字体
25-数据环境
26-数据
这是为记录建立的惟一标识符,你可以在想添加记录时,使用SYS(2015)来建立惟一值。
TIMESTAMP 除了如下之外:
21-打印机驱动程序 (2.x)
23-字体
25-数据环境
26-Data
记录最后修改的时间戳
OBJTYPE 0-49 仅为原来报表使用保留
50-99 用于自定义使用
0 = 注释
1 = 报表定义
2 = 工作区 (2.x 报表)
3 = 索引 (2.x 报表)
4 = 关系 (2.x 报表)
5 = 标签
6 = 线条
7 = 形状
8 = 字段
9 = 带区
10 = 分组对象 (不是数据分组)
17 = 图片/OLE 绑定
18 = 变量
21 = 打印机驱动程序设置 (2.x 报表)
23 = 字体
25 = 数据环境
26 = 数据 (临时表、关系或CursorAdapter)
OBJCODE 当OBJTYPE字段单独不能满足标识一个记录类型时,可以使用OBJCODE字段来进一步标识一个记录的类型。
1-报表定义 总是为53。
2-工作区 (2.x) 表的工作区
3-索引 (2.x) IDX的工作区
4-关系 (2.x) 子表的工作区
5-标签
6-线条
8-字段
10-分组
17-图片
总是为0。
7-形状 总是为4。
9-带区 带区类型说明:
0 = 标题
1 = 页标头
2 = 列标头
3 = 组标头
4 = 细节
5 = 组脚注
6 = 列脚注
7 = 页脚注
8 = 总结
9 = 细节标头
10 = 细节脚注
NAME 2-工作区 (2.x) 表的文件名称
3-索引 (2.x) IDX文件的文件名称
8-字段 Design-time caption(设计时标题)
17-图片 如果以Picture from File定义,并且选择了一个图片文件,此字段为空。
如果以Picture from File定义,并且输入了一个表达式,则字段中保存着这个表达式。
如果以Picture from Field定义,则字段中保存着通用字段的名称。
18-变量 变量名称
21-打印机驱动程序 (2.x) 安装的名称
25-数据环境 “dataenvironment”
26-数据 临时表保存为“cursor”
关系保存为“relation”
临时表适配器保存为“cursoradapter”
EXPR 1-报表定义 打印机驱动程序和打印机安装信息
3-索引 (2.x) 排序表达式
4-关系 (2.x) 关系表达式
5-标签 标签对象的文本
8-字段 字段对象的表达式
9-带区/组标头 数据分组表达式
9-带区/细节 目标别名表达式
18-变量 Value to store表达式
25-数据环境
26-数据
数据环境或数据对象的属性
VPOS 1-报表定义 列集合的数目
10-分组 这个数值表示包含在这个组中的第一个对象,按照报表对象的Z-顺序排序。但是,分组的对象可以属于另一个分组对象,发生这种情况时,在确定这个数值时,整个组仅被计算一次
23-字体 字符的像素高度,FONTMETRIC(1)
报表对象 对象的垂直位置,使用FRU作为计量单位
HPOS 1-报表定义 以FRU为单位的左边距。如果选择了Printable page(可打印页),则是相对于可打印边的距离;如果选择了Whole page(整页),则是相对于物理纸边的距离
10-分组 这个数值表示在组中报表对象的总数,但是,如果分组对象包含在其他组中,则整个组作为一个对象来计算
23-字体 平均字符像素宽度,FONTMETRIC(6)
报表对象 以FRU为单位的对象的水平位置
HEIGHT 1-报表定义 以FRU为单位的列间距
9-Band 以FRU为单位的带区的高度
23-字体 以像素为单位的字符提升值,FONTMETRIC(2)
报表对象 以FRU为单位的对象的高度
WIDTH 1-报表定义 以FRU为单位的每列的宽度
9-带区/细节
9-带区/组标头
相当于Data Grouping对话框或Detail对话框上的Start group on new page when less than(当过小时,组从新一页上开始打印)的值,以FRU为单位
23-字体 以像素为单位的字符最大宽度,FONTMETRIC(7)
报表对象 以FRU为单位的对象的宽度
STYLE 1-报表定义 如果报表使用了一个DataEnvironment类或从其他报表中复制了一个数据环境,这里保存着关于数据环境的XML数据
2.x 报表对象 B = 黑体
I = 斜体
R = 提升
L = 降低
J = 右对齐
C = 居中对齐
PICTURE 5-标签 包含对齐格式符
8-字段 相当于在Report Expression对话框上Format文本框中输入的表达式。如果选择了Interleave(插入) ,则格式表达式使用@R作为前导。
17-图片 如果以Picture from File定义,并且选择了一个图片文件,这里将保存该文件的相对路径名称
如果以Picture from File定义,并且输入了表达式,字段为空
如果以Picture from Field定义,字段为空
ORDER 全部—VFP 9.0之前 未使用
全部—VFP 9.0 包含一个表示数字值(二进制标记的和)的字符值来标识保护功能
对象(位,值,含义)
0, 1, 锁定(移动或调整大小)
1, 2, 隐藏(可视)
2, 4, 不允许删除
3, 8, 不允许编辑
6, 64, 不允许选择
带区(位,值,含义)
4, 16, 不允许编辑
14, 16384, 不允许调整大小
报表(位,值,含义)
7, 128, 不允许预览
8, 256, 不允许选择带区
9, 512, 不允许数据分组
10, 1024, 不允许使用变量
11, 2048, 不允许改变报表布局
12, 4096, 不允许多选
13, 8192, 不允许使用数据环境
15, 32768, 不允许打印
16, 65536, 不允许快速报表
UNIQUE 1-报表定义 .T. = 临时向导生成的报表
.F. = 永久性报表
2-工作区 (2.x) .T. = 有索引用于该工作区
.F. = 没有索引用于该工作区
18-变量 相当于Report Variables对话框上的Release after report选择框
COMMENT 全部 相当于Comments编辑框
ENVIRON 25-数据环境 .T. = 私有数据会话
.F. = 默认数据会话
BOXCHAR 全部 未使用
FILLCHAR 8-字段 C 字符型字段
N 数值型字段
D 日期型字段
TAG 1-报表定义 二进制打印机驱动程序信息
2-工作区 (2.x) 工作区的别名
9-带区 On Entry表达式
18-变量 Initial value(初始值)
25-数据环境
26-数据
包含事件和方法代码
TAG2 1-报表定义 二进制打印机驱动程序信息
9-带区 On Exit表达式
25-数据环境
26-数据
包含编译后的事件和方法代码
PENRED 23-字体 以像素为单位的字符降低值,FONTMETRIC(3)
报表对象 RGB()中的前景红色值
PENGREEN 23-字体 以象素为单位的附加前置空间,FONTMETRIC(5)
报表对象 RGB()中的前景绿色值
PENBLUE 报表对象 RGB()中的前景蓝色值
FILLRED 报表对象 RGB()中的背景红色值
FILLGREEN 报表对象 RGB()中的背景绿色值
FILLBLUE 报表对象 RGB()中的背景蓝色值
PENSIZE 6-线条
7-形状
绘图笔大小(从Format菜单中选择Pen,然后从中选择一个实线进行设置)
0 = 细线
1 = 1 磅
2 = 2 磅
4 = 4 磅
6 = 6 磅
只有将线条宽度设置为(PENSIZE x 104.167),线条才是可见的
PENPAT 6-线条
7-形状
绘图笔样式(从Format菜单中选择Pen,然后从中选择一个非实线时进行设置)
0 = 无
1 = 点线
2 = 虚线
3 = 点划线
4 = 双点划线
8 = 正常/实线
FILLPAT 7-形状 填充图案(从Format菜单选择Fill)
0 = 无
1 = 实心
2 = 水平线
3 = 垂直线
4 = 左斜对角线
5 = 右斜对角线
6 = 网格(水平和垂直线)
7 = 影线(左和右对角线)
FONTFACE 1-报表定义 默认字体的字体名称
5-标签
8-字段
23-字体
字体名称
FONTSTYLE 1-报表定义
5-标签
8-字段
23-字体
0 = 正常
1 = 粗体
2 = 斜体
4 = 下划线
128 = 删除线
上面的数值可以被结合在一起来得到多种字体类型
FONTSIZE 1-报表定义
5-标签
8-字段
23-字体
字体大小
MODE 报表对象 方式
0 = 不透明
1 = 透明
读取顺序
0 = 从左至右
2 = 从右至左
4 = 上下文
方式和读取顺序值一起添加
RULER 1-报表定义 0 = 无标尺
1 = 标尺刻度为英寸
2 = 标尺刻度为米
3 = 标尺刻度为像素
4 = 标尺刻度为字符(1/12")
5 = 标尺遵守当前系统设定值
RULERLINES 1-报表定义 0 = 在报表设计器中不显示网格线
1 = 在报表设计器中显示网格线
8-字段 相当于Format对话框上的Trim mode for character expressions选项
0 = 默认对齐方式
1 = 对齐到最近的字符
2 = 对齐到最近的单词
3 = 对齐到最近的字符,附加省略号
5 = 以省略号来显示内部的路径
6 = 对齐到最近的单词,附加省略号
GRID 1-报表定义 .T. = 打开对齐网格线
.F. = 关闭对齐网格线
GRIDV 1-报表定义 以像素为单位的网格线的垂直间距
GRIDH 1-报表定义 以像素为单位的网格线的水平间距
FLOAT 报表对象 相当于对象的Property对话框上的Float选项
STRETCH 6-线条
7-形状
相当于对象的Property对话框上的Stretch relative to height of band(相对于带区高度伸展)选择框
8-字段 相当于对象的Property对话框上的Stretch with overflow(溢出时伸展)选择框
STRETCHTOP 6-线条
7-形状
相当于对象的Property对话框上的Stretch relative to tallest object in group(相对于组中的最高对象伸展)选择框
TOP 1-报表定义 .T. = 打印区域是Whole page(整页)
.F. = 打印区域是Printable page(可打印页)
报表对象 相当于对象Property对话框上的Fix relative to top of band(相对于带区顶端固定)选项
BOTTOM 1-报表定义 .T. = 多个列集合按从左至右的顺序打印
.F. = 多个列集合按从上至下的顺序打印
报表对象 相当于对象的 Property对话框上的Fix relative to bottom of band(相对于带区底端固定)选项
SUPTYPE 全部 未使用
SUPREST 全部 未使用
NOREPEAT 报表对象 相当于Print when对话框上的Remove line if blank(若是空白行则删除)选择框
9-带区/细节 相当于Detail对话框上的Repeat detail header on each page(在每页上重复打印细节标头)选择框
RESETRPT 全部 未使用
PAGEBREAK 9-带区/标题 在单独一页上打印标题页
9-带区/组标头 相当于Data Grouping对话框上的Start each group on a new page(每组从新的一页上开始)选择框
9-带区/组脚注 匹配相应的组标头记录
9-带区/总结 在单独一页上打印总结页
9-带区/细节标头 相当于Detail对话框上的Start on a new page(从新的一页上开始)选择框
9-带区/细节脚注 匹配相应的细节标头记录
COLBREAK 9-带区/组标头 相当于Data Grouping对话框上的Start group on new column(组从新的一页上开始)选择框
9-带区/组脚注 匹配相应的组标头带区
9-带区/细节标头 相当于Detail对话框上的Start on a new column(从一个新列上开始)选择框
9-带区/细节脚注 匹配相应的细节标头记录
RESETPAGE 9-带区/组标头 相当于Data Grouping对话框上的Reset page number to 1 for each group(每组的页号重新从1开始)选择框
9-带区/组脚注 匹配相应的组标头记录
9-带区/细节标头 相当于Detail对话框上的the Reset Page Number to 1 for each Detail Set(每个细节集的页号重新从1开始)选择框
9-带区/细节脚注 匹配相应的细节标头记录
GENERAL 17-图片 剪裁/缩放设置:
0 = 剪裁图片
1 = 缩放图片,保留形状
2 = 缩放图片,填充图文框
SPACING 5-标签 0 = 单倍
1 = 1.5
2 = 双倍
8-字段 总是设置为0
DOUBLE 17-图片 相当于对象的Property对话框上的Center picture(居中图片)选择框
1-报表定义
报表对象
.T.,表示FontCharSet应用于该对象(参考RESOID)
SWAPHEADER 全部 未使用
SWAPFOOTER 全部 未使用
EJECTBEFOR 9-带区/总结 打印页标头
EJECTAFTER 9-带区/总结 打印页脚注
PLAIN 1-报表定义 相当于在Expression Builder Options对话框中的Add non-selected alias only(仅添加未选定的别名)选项按钮(.T.值比ADDALIAS的值优先)
9-带区 .T. = 固定的带区高度
SUMMARY 全部 未使用
ADDALIAS 1-报表定义 相当于Expression Builder Options对话框中的Aliases选项组
.T.,表示选择了Always add alias(总是添加别名)选项按钮
.F.,表示选择了Never add alias(从不添加别名)选项按钮,(PLAIN字段中的.T.值优先于该值)
OFFSET 6-线条 总是为1
7-形状 用于圆角矩形的半径(缺省地使用12、16、24、32和99)
8-字段 0 = 左对齐
1 = 右对齐
2 = 居中对齐
17-图片 表示文件或通用字段
0 = 文件(存储在PICTURE字段中)
1 = 通用字段(存储在NAME字段中)
2 = 表达式(存储在NAME字段中)
TOPMARGIN 全部 未使用
BOTMARGIN 全部 未使用
TOTALTYPE 8-字段
18-变量
计算类型:
0 = 不计算
1 = 计数
2 = 总和
3 = 平均值
4 = 最小值
5 = 最大值
6 = 标准偏差
7 = 方差
RESETTOTAL TOTALTYPE<>0 时
8-字段
18-变量
确定计算在何时被重置:
1 = 在报表尾
2 = 在页尾
3 = 在列尾
5+ = 在数据分组尾,即在数据分组号中,如:6在数据分组1重置计算,7在数据分组2重置计算,等等
79+ = 在细节带集尾,即细节带区号中,如:80在细节带集1重置计算,81在细节带集2重置计算,等等
TOTALTYPE=0 时
8-字段
如果存在一个细节带区:
1 = 在组/带区的最内层重置
如果存在多个细节带区:
1 = 在对象的细节带区重置
TOTALTYPE=0 时
18-变量
1 = 在表尾重置
RESOID 1-报表定义
报表对象
表示应用于此对象(或整个报表)的FontCharSet
CURPOS 1-报表定义 .T. = 打开“显示位置”
.F. = 关闭“显示位置”
SUPALWAYS 7-形状 相当于Print when对话框上的Print repeated values(打印重复值)选项组,但是此设置不优先(注意:该字段和SUPVALCHG字段是为形状设置的)
.T. = 否
.F. = 是
SUPOVFLOW 报表对象 相当于Print when对话框上的When detail overflows to new page/column(当细节区数据溢出到新页/列时打印)选择框
SUPRCOL 报表对象 相当于Print when对话框上的In first whole band of new page/column(在新页/列的第一个完整信息带内打印)选择框
SUPGROUP 报表对象 相当于When this group changes(当此组改变时打印)下拉组合框
组号是5+组的编号,如 6是数据分组1, 7是数据分组2,等等
SUPVALCHG 报表对象 相当于Print when对话框上的Print repeated values选项组,但是此设置不优先
.T. = 否
.F. = 是
SUPEXPR 报表对象 与Print when对话框上的the Print only when expression is true(仅当表达式为真时打印)文本框相对应
USER 全部 开发者使用
结论
VFP 9.0报表书写器具有的诸多新增功能可以帮助你建立功能更加强大的报表,其所具有的可扩充性功能向你展露了VFP报表书写器的内部工作原理;新增的可重用数据环境则允许在报表之间共享数据环境;报表的各个方面(如对象和带区)可以被保护;新的用户界面为你建立了一个更好的开发环境;对象的布局增强、国际功能、打印增强和数据分组增强较以前版本给予了更多的可用选择;最后,新增的多细节带区功能则带来了更多的报表功能选项,同时,所有这些改进和增强给予了你建立比以前版本更加复杂报表的能力。