8其它8.1报表打印在这里,简单说一下报表。其实据说RPG设计之初,主要就是为了解决报表问题。不过发展到现在,在我接触过的系统中,觉得报表在RPG编程之中反而退居其次,大部分程序都是对数据库中磁盘文件(即PF文件)的操作。报表文件其实在某种意义上与普通的磁盘文件很类似,都是有记录格式(RecordFormat),都可以进行写操作(WRITE),RPGLE的程序对它们的操作方式也比较雷同。所不同的是普通的磁盘文件的数据是存储在数据库中,而报表文件WRITE了之后,是以脱机文件(SpoolFile)的形式存在。所以在一个库中,磁盘文件具有唯一性,即不能有同名的磁盘文件;而在同一个输出队列中,同名的报表文件(即生成的脱机文件),允许有多个。要做一个全新的报表打印,大致上可以分为画报表文件(PRTF),与编写打印程序这两部分。一、画报表文件(PRTF)1、新建立一个属性为PRTF的文件,然后使用19进入报表编辑状态。(即STRRLU)2、定义一个新的记录格式(RecordFormat):DR+F18+F10,注意看下方的功能键说明3、在一个记录格式之下,追加内容时,要在新的编辑行前加“CLC”,表示此行的内容,是属于上面记录格式的。4、编辑行前加:DC:定义常量CF:使当前行的内容居中5、常用功能键:F13:标记/取消标记(光标所指的字段)。多试一下就知道使用方法,可以将同一行的多个相连的字段标记成为一个块(对首尾两个字段操作F13即可)。高亮部分表示已被标记的块。F14:将已标记的块COPY到光标指定处。(其实这个我用得不多)F15:将已标记的块MOVE到光标指定处。(这个用得不少)F16:删除已标记的块。(这个用的频率也不少)F11:定义新变量F23:进入当前字段的功能菜单画面6、对新变量的定义,按F11之后,见到画面如下:Editedlength............:1Recordformat............:RCD001Numberofkeywords.........:0Numberofindicators........:0Typechoices,pressEnter.Field................FLD001NameOptionindicators..........01-99,N01-N99Moreindicators..........NY=Yes,N=NoStartingline............1-255Startingposition..........61-255,+nnLengthofdata...........11-378,+nn,-nn翻页,还有:Datatype..............11=Character2=Zoned3=Floatingpoint4=Open5=Graphic6=Date7=Time8=TimestampDecimalpositions..........0-31,+n,-nReferenceafield..........NY=Yes,N=NoUsereferencedvalues.......YY=Yes,N=No可以采用直接定义长度、类型的方法,即在第1页的最末尾,Lengthofdata处,填上字段长度;如果是字符型,就不需要再填其它内容;如果是数字型,在第2页Decimalpositions处填上小数位数。也可以采用参照字段的方法(即参照已存在的PF文件中的字段)。如果选用这种方法,就用需要在Lengthofdata以及Decimalpositions中填写内容,将Referenceafield项填为“Y”,然后按确认键(好象F10键也可以),然后可以看到该项高亮显示。此时再按F10,可进入该字段的功能菜单(也可以通过在报表编辑状态下,直接在当前字段处按F23进入):OptKeywordOptKeywordOptKeywordALIASDFTIGCCHRRTTBARCODEDLTEDTINDTXTBLKFOLDEDTCDEMSGCONCDEFNTEDTWRDPAGNBRCHRIDFLTFIXDECPRTQLTYCHRSIZFLTPCNREFFLDCOLORFNTCHRSETSKIPACPIFONTSKIPBCVTDTAHIGHLIGHTSPACEADATEIGCALTTYPSPACEBDATFMTIGCANKCNVTEXTDATSEPIGCCDEFNTTIME以上菜单中,标记为蓝色的,是我常用的几个选项。在这些选项前面,选2,即是对当前字段加注这些功能;选4,即是去掉这些功能。要参照已知字段定义变量,则在“REFFLD”选项前选2,可见Field...............Recordformat..........File...............Library.............*CURLIB各选项的含义:Field:当前变量所参照的字段RecordFormat:当前变量所参照字段,在PF文件中所属的记录格式File:PF文件名Library:PF文件所在的库名7、其它几个常用功能选项的含义:SKIPA:SkipAfter,在WRITE操作时,写该字段后,自动换页;SKIPB:SkipBefore在WRITE操作时,写该字段前,自动换页SPACEA:SpaceAfter写该字段后,再打印一个空格;SPACEB:SpaceBefore写该字段前,打印一个空格(可用来解决错行问题)EDTCDE:定义当前字段的显示方式,比如说当前字段为数字类型时,是否显示逗号,前面是补零等等。根据F1键,看Help中的说明:EditCodeDescriptionNoSignCRSign-Sign(R)-Sign(L)Commasandzerobalances1AJNCommas2BKOZerobalances3CLPNocommasorzerobalances4DMQUserdefinededitcodes5-9DatefieldeditWDateeditYSuppressleadingzerosZ二、编写打印报表的程序1.对报表文件的声明:FEF4322POEPRINTEROFLIND(*IN99)可以看到,操作方式是“O”,即只写;文件类型为“PRINTER”,即打印文件;后面的OFLIND关键字表示该报表文件的换页指示器为99;即写报表,当写满一页时,*IN99自动变为1;然后报表自动换页,*IN99再自动变回0;其实这一项我觉得控制起来有点不爽,所以我通常都是自行控制换页,不用这个指示器来判断;我常使用的自行控制换页的方法在下面会说明。2.对报表文件的处理和磁盘文件(DISK)一样,报表文件其实也有OPEN,CLOSE,WRITE的操作。不过使用OPEN,CLOSE操作时,不需要使用USROPN关键字。同时也因为生成的是脱机文件,所以不能进行CHAIN、UPDATE等定位、修改的操作。如果在程序中,只需要生成一份报表,那么可以不使用OPEN/CLOSE操作,因为程序在运行之初,以及运行结束时,已默认打开,关闭了一次所有已声明的文件,包括报表打印文件。但如果程序在运行时,需要生成多份报表,那么必须在每次生成报表前使用OPEN操作;在生成完报表后,使用CLOSE操作,以保证脱机文件的完整。在生成完当前报表前,还可能需要使用CHGPRTF的命令,将报表生成到指定的输出队列中。如果不更改,那么报表会生成到当前用户默认的脱机文件存放处。当一个RPGLE中,生成多份同名报表时,常会在生成报表前使用CHGPRTF,以便于管理,避免混乱。报表的操作,也与磁盘文件(普通PF文件)类似,在OPEN与CLOSE之间,对各字段进行赋值,赋值完之后再通过“WRITE记录格式名”的语句,来写指定的记录格式。3.自行控制换页在声明报表时,可以通过OFLINE关键字,定义换页指示器,不过可能是换页指示器的使用方法我摸索得还不够,所以使用起来总觉得不够自如。我通常是先在报表文件中,定义一个记录格式(RecordFormat),该记录格式下只有一个字段,同时这个字段的功能选项处要标识为“SKIPA”,然后该字段尽量做成不可见字符。在RPGLE程序中,当程序运行逻辑上判断需要换页时,WRITE这个记录格式,就可以实现换页了(也就是通过字段的SKIPA选项来实现换页,当然大家也可以使用其它更便捷的方法,这里只是介绍我常用的方法,因为我觉得这个方法比较稳定)。至于如何判断换页,当然要看具体报表的需求是如何要求的。最重要的,是不要忘记定义一个数字型变量用来统计当前页已打印过的行数,当大于等于60行,要进行换页处理(我通常会留出几行来做为冗余,大家可以自已选择,但肯定不能大于66行,否则会自动换页)三、几点补充呵呵,找出我以前写的关于报表打印的贴子,做为使用时补充1、关于记录格式其实这个本来没什么可说的,不过我就经常搞错,还是说说吧。同一个记录格式之下,格式应该如下:记录格式名0001.00+打印内容0002.00+打印内容0003.00+每行要有这个+,才归属于同一个记录格式。如果是个点的话,也就是说明这一行并不属于该记录格式,如果想让它属于这个记录格式,就要用CLC命令;当我们用19编辑的时候,如果是3来COPY记录行,系统经常会自动在COPY处新增一个记录格式,所以要注意。(说来简单,但是我最开始画报表的时候,就曾经被这个问题折磨)2、关于变量的命名不同的记录格式,可以使用相同的变量名。有的时候,为了少写赋值语句,可以直接将变量命名得与PF中的字段相同。(不过我不太喜欢这种做法)如果在RPGLE程序中,给某个变量赋值,但没有对相应的记录格式进行WRITE操作,编译会不通过,报4030字段未定义的错。3、关于打印时会错行的问题有的时候,打印会错行,比如记录格式定义0001.00+变量A(比如说10个字符长)0002.00+变量B(比如说5个字符长)变量A的起始处位于第一列变量B在变量A的下一行,且起始处位于第三列当变量A='AAAAAAAAAA',变量B='BBBBB'时,会打印出AAAAAAAAAABBBBB这很正常。但当A='A'或空时,本来我们是希望打印出:A(或者这里就是一空行)BBBBB这样的效果,但是系统就会打印成为BBBBBA或BBBBB(没有打印出空行)也就是说,当某一行的前面为空时,(好象空格也算空)如果下一行有数据,就会挤上来。解决办法是在将A字段的首位赋值为非空;如果想让客户看不见,可以考虑使用汉字指示器。想打印空行,也可以用这个办法。又或者是将该字段的功能选项加上“SPACEB”,即打印前空一格,也可以解决这个问题。(报表的这个特点困扰我最久)4、关于报表的测试其实这个东西最简单,不过我以前一向很少去留意。以前测试报表,尤其是测试换页的时候,都是老老实实的用打印机去打,打出来了再检查换页对不对,慢不说,还费纸。其实我们进入到SPLF里,查看刚生成的报表文件,右上角就有当前的页数,行数,如第1页第1行,右上角就是1/1,第2页第3行,就是3/2,好象页数在后面。在“positionto”这里,+1就是下一行,W+1就是向右移一列,慢慢+,就可以看到换页是否正确了。8.2SQLRPGLE在RPG/RPGLE程序中,也是可以使用SQL命令的,首先,需要将程序的类型设置为SQLRPG或SQLRPGLE,SQL语句的用法都一样,RPG/RPGLE是指非SQL语句使用什么格式。这类程序写完之后与普通的RPG/RPGLE程序一样编译,运行。不过需要注意,SQLRPG编译时有一个“COMMIT”参数,此参数如果没有使用“*NONE”,或“*NC”,那么SQL语句中更改的表将会由系统默认加一个COMMIT声明。如果执行RPG程序后没有执行COMMIT操作,那么当时数据是更改过来的,但当用户SIGNOFF之后,SQL更改的表数据将会回滚(这也是在维护阶段常见的维护失误之一)。不过这个参数只会影响到SQL语句中做了数据更改的表,不会影响到RPG/RPGL