FastReport 打印模版页(TFrxReportpage)复制

遇到一个奇葩的需求。一般情况下我们打印单据,用FastReport设置打印格式,也就是就设一个模版页而己,就是一种单据格式。如果打印的单据数据多了就自动打印多页了,他们的格式是一样的。也就是读同一个模版页。

现的需求是,如果打印N页内容。每一页的格式除了表体外是一样的(也可能部份不同)。而表体取自不同的数据集(也就是读取不同的FDQuery),需要设置不同的表体格式(表体列的数量,列的名称)。

在各大论坛中找不到现成解决方案。经网友提示,FastReport的打印模版设置好了其实就是一个XML文件。所以我们只需要读取这个XML,然后取出Page部份,复制成N份,根据需求修改不同部份的内容,然后再写入这个打印模版就可以了。开发中发现Delphi里读取XML文件的控件是不少,但是都有或多或少的问题,导制不适用于这个方案,最终我选择了FastReport里自带的FrxXML。功能虽少,但是够用了。

以下分享的是Page页的复制的实现代码,修改内容部份根据实际需求自行编写。至于如何修改,可以参照以下代码。

与网友的交流中,有网友不明白我的需求,最终说我语文小学没毕业,表达不清楚。其实我虽然语文小学有毕业,但也是离毕业的不远。

1 1 unit frxHelp; 2 2 3 3 interface 4 4 5 5 uses frxClass,frxXML,System.SysUtils,Vcl.Dialogs; 6 6 type 7 7 TChangeProp=reference to procedure (aXML:TfrxXMLItem); 8 8 9 9 ///*******************根据FastReport设置好的打印模版(ReportPage)生成多页 10 10 /// 11 11 //procedure TForm1.FormCreate(Sender: TObject); 12 12 // 13 13 //const 14 14 // frxFile='G:\delphi\delphi\企业通ERP\DOERP\BIN\fr3\销售明细打印.fr3'; 15 15 //var 16 16 // cStream:TStream; 17 17 // I:integer; 18 18 // frXML:TfrxXMLDocument; 19 19 // frXItem:TfrxXMLItem; 20 20 // fdoprop:TChangeProp; 21 21 //begin 22 22 // I:=0; 23 23 // fdoprop:= procedure (aXML:TfrxXMLItem) 24 24 // begin 25 25 // if aXML.PropExists('DataSet') then 26 26 // ShowMessage(aXML.Prop['DataSet']); 27 27 // end; 28 28 // IF GetFrxpageTemple(frxFile,frXML,frXItem) then 29 29 // IF CopyfrxPage(frXML,frXItem,I,'Page3',fdoProp) then 30 30 // begin 31 31 // cStream:=TMemoryStream.Create; 32 32 // frXML.SaveToStream(cStream); 33 33 // cStream.Position:=0; 34 34 // frxReport1.LoadFromStream(cStream); 35 35 // frxReport1.DesignReport(); 36 36 // end; 37 37 //end; 38 38 procedure changeProp(aXML:TfrxXMLItem;iXML:Integer;Prop:TChangeProp=nil); 39 39 procedure CopyXML(S,D:TfrxXMLItem); 40 40 function CopyfrxPage(fXMLDoc:TfrxXMLDocument;sPageItem:TfrxXMLItem;ID:integer;cPname:String;Prop:TChangeProp=nil):Boolean; 41 41 function GetFrxpageTemple(cFile:String;out fXMLDoc:TfrxXMLDocument;out PageItem:TfrxXMLItem):Boolean; 42 42 implementation 43 43 procedure CopyXML(S,D:TfrxXMLItem); 44 44 var 45 45 I:Integer; 46 46 a,b:TfrxXMLItem; 47 47 begin 48 48 for I := 0 to S.Count-1 do 49 49 begin 50 50 a:=s.Items[i]; 51 51 b:=d.Add; 52 52 b.Name:=a.Name; 53 53 b.Text:=a.Text; 54 54 if a.Count>0 then 55 55 CopyXML(a,b); 56 56 57 57 end; 58 58 end; 59 59 procedure changeProp(aXML:TfrxXMLItem;iXML:Integer;Prop:TChangeProp); 60 60 var 61 61 I:Integer; 62 62 fXML:TfrxXMLItem; 63 63 begin 64 64 for I := 0 to aXML.Count-1 do 65 65 begin 66 66 fXML:=aXML.Items[I]; 67 67 //Name属性是必须改的,为避免没有传入属性修改 方法(Prop:TChange)默认强制修改Name 68 68 if fXML.PropExists('Name') then 69 69 fXML.Prop['Name']:=fXML.Prop['Name']+'N'+iXML.toString; 70 70 if Assigned(Prop) then 71 71 Prop(aXML); 72 72 if fXML.Count>0 then 73 73 changeProp(fxML,iXML,Prop); 74 74 Inc(iXml); 75 75 end; 76 76 end; 77 77 function GetFrxpageTemple(cFile:String;out fXMLDoc:TfrxXMLDocument;out PageItem:TfrxXMLItem):Boolean; 78 78 begin 79 79 if Not FileExists(cFile) then 80 80 begin 81 81 ShowMessagefmt('打印模版[%s]不存在!!',[cFile]); 82 82 Exit(False); 83 83 end; 84 84 try 85 85 fXMLDoc:=TfrxXMLDocument.Create; 86 86 fXMLDoc.LoadFromFile(cFile); 87 87 PageItem:=TfrxXMLItem.Create; 88 88 PageItem:=fXMLDoc.Root.FindItem('TfrxReportPage'); 89 89 except 90 90 on E:Exception do 91 91 begin 92 92 ShowMessage(E.Message); 93 93 Exit(false); 94 94 end; 95 95 end; 96 96 Result:=True; 97 97 end; 98 98 function CopyfrxPage(fXMLDoc:TfrxXMLDocument;sPageItem:TfrxXMLItem;ID:integer;cPname:String;Prop:TChangeProp):Boolean; 99 99 var 100100 fFrxItem:TfrxXMLItem; 101101 begin 102102 try 103103 fFrXItem:=fXMLDoc.Root.Add; 104104 fFrxItem.Name:='TfrxReportPage'; 105105 fFrxItem.Text:=sPageItem.Text; 106106 fFrxItem.Prop['Name']:=cPname; 107107 CopyXML(spageItem,fFrxItem); 108108 ChangeProp(fFrxItem,ID,Prop); 109109 except 110110 on E:Exception do 111111 begin 112112 ShowMessage(E.Message); 113113 Exit(false); 114114 end; 115115 end; 116116 result:=True; 117117 end; 118118 119119 end.
点赞
收藏

评论区

加载中...

相关推荐

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

前端实现在浏览器中打印网页

前端数据报表打印方案背景项目:vueelementui需求:web端连接打印机打印报表功能关键词:浏览器端连接打印机打印报表调研首先,前端调用打印只有两种方式,使用window.print()和调用网络打印机。window.print这个是浏览器开放的api一般快捷键ctrlp或右键都也能调用。可以通过媒体查询的方案进行局部打印,也就是隐

Vue刷新页面有哪几种方式

在Vue项目中,刷新当前页除了window.reload(),你还能想到什么办法?而且这种办法会重新加载资源出现短暂的空白页面。体验不是很好。在某个详情页面的时候,我们经常需要通过路由中的详情id去获取内容,当我们在不同的详情页来回切换的时候,打开的页面是同一个,只是需要通过监听路由中的参数id的变化去重新请求详情接口。如果这个详情页只需要一个接口

Django REST framework的分页

DRF分页组件为什么要使用分页我们数据表中可能会有成千上万条数据,当我们访问某张表的所有数据时,我们不太可能需要一次把所有的数据都展示出来,因为数据量很大,对服务端的内存压力比较大还有就是网络传输过程中耗时也会比较大。通常我们会希望一部分一部分去请求数据,也就是我们常说的一页一页获取数据并展示出来。DRF使用

Spread for Windows Forms高级主题(7)

表单打印的多个部分都可以进行自定义,大多数的自定义选项存在于PrintInfo对象中。大多数打印选项是在PrintInfo对象上进行设置,并在表单级别上应用。当你执行打印操作时,你将一个特定的表单发送给使用这些设置的打印机。如果你想为不同的表单使用不同的打印设置,那么你可能需要重置PrintInfo对象,然后在表单打印的间隔内做必要的修改。深入理解打

FastReport 打印模版页(TFrxReportpage)复制 - HelloWorld