FastReport 打印模版页(TFrxReportpage)复制

Stella981
• 阅读 792

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

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

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

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

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

  1 unit frxHelp;
  2 
  3 interface
  4 
  5  uses frxClass,frxXML,System.SysUtils,Vcl.Dialogs;
  6  type
  7   TChangeProp=reference to  procedure (aXML:TfrxXMLItem);
  8 
  9 ///*******************根据FastReport设置好的打印模版(ReportPage)生成多页
 10 ///
 11 //procedure TForm1.FormCreate(Sender: TObject);
 12 //
 13 //const
 14 // frxFile='G:\delphi\delphi\企业通ERP\DOERP\BIN\fr3\销售明细打印.fr3';
 15 //var
 16 // cStream:TStream;
 17 // I:integer;
 18 // frXML:TfrxXMLDocument;
 19 // frXItem:TfrxXMLItem;
 20 // fdoprop:TChangeProp;
 21 //begin
 22 //   I:=0;
 23 //   fdoprop:= procedure (aXML:TfrxXMLItem)
 24 //  begin
 25 //    if aXML.PropExists('DataSet') then
 26 //      ShowMessage(aXML.Prop['DataSet']);
 27 //  end;
 28 //  IF  GetFrxpageTemple(frxFile,frXML,frXItem) then
 29 //     IF CopyfrxPage(frXML,frXItem,I,'Page3',fdoProp) then
 30 //       begin
 31 //          cStream:=TMemoryStream.Create;
 32 //          frXML.SaveToStream(cStream);
 33 //          cStream.Position:=0;
 34 //          frxReport1.LoadFromStream(cStream);
 35 //          frxReport1.DesignReport();
 36 //       end;
 37 //end;
 38   procedure changeProp(aXML:TfrxXMLItem;iXML:Integer;Prop:TChangeProp=nil);
 39   procedure CopyXML(S,D:TfrxXMLItem);
 40   function CopyfrxPage(fXMLDoc:TfrxXMLDocument;sPageItem:TfrxXMLItem;ID:integer;cPname:String;Prop:TChangeProp=nil):Boolean;
 41   function GetFrxpageTemple(cFile:String;out fXMLDoc:TfrxXMLDocument;out PageItem:TfrxXMLItem):Boolean;
 42 implementation
 43  procedure CopyXML(S,D:TfrxXMLItem);
 44  var
 45    I:Integer;
 46    a,b:TfrxXMLItem;
 47   begin
 48     for I := 0 to S.Count-1 do
 49       begin
 50         a:=s.Items[i];
 51         b:=d.Add;
 52         b.Name:=a.Name;
 53         b.Text:=a.Text;
 54         if a.Count>0 then
 55          CopyXML(a,b);
 56 
 57       end;
 58   end;
 59  procedure changeProp(aXML:TfrxXMLItem;iXML:Integer;Prop:TChangeProp);
 60  var
 61    I:Integer;
 62    fXML:TfrxXMLItem;
 63   begin
 64     for I := 0 to aXML.Count-1 do
 65       begin
 66         fXML:=aXML.Items[I];
 67       //Name属性是必须改的,为避免没有传入属性修改 方法(Prop:TChange)默认强制修改Name
 68         if fXML.PropExists('Name') then
 69           fXML.Prop['Name']:=fXML.Prop['Name']+'N'+iXML.toString;
 70           if Assigned(Prop) then
 71             Prop(aXML);
 72         if fXML.Count>0 then
 73           changeProp(fxML,iXML,Prop);
 74           Inc(iXml);
 75       end;
 76   end;
 77 function GetFrxpageTemple(cFile:String;out fXMLDoc:TfrxXMLDocument;out PageItem:TfrxXMLItem):Boolean;
 78 begin
 79  if Not FileExists(cFile) then
 80    begin
 81      ShowMessagefmt('打印模版[%s]不存在!!',[cFile]);
 82      Exit(False);
 83    end;
 84   try
 85      fXMLDoc:=TfrxXMLDocument.Create;
 86      fXMLDoc.LoadFromFile(cFile);
 87      PageItem:=TfrxXMLItem.Create;
 88      PageItem:=fXMLDoc.Root.FindItem('TfrxReportPage');
 89   except
 90     on E:Exception do
 91       begin
 92         ShowMessage(E.Message);
 93         Exit(false);
 94       end;
 95   end;
 96   Result:=True;
 97 end;
 98 function CopyfrxPage(fXMLDoc:TfrxXMLDocument;sPageItem:TfrxXMLItem;ID:integer;cPname:String;Prop:TChangeProp):Boolean;
 99 var
100  fFrxItem:TfrxXMLItem;
101 begin
102   try
103    fFrXItem:=fXMLDoc.Root.Add;
104    fFrxItem.Name:='TfrxReportPage';
105    fFrxItem.Text:=sPageItem.Text;
106    fFrxItem.Prop['Name']:=cPname;
107    CopyXML(spageItem,fFrxItem);
108    ChangeProp(fFrxItem,ID,Prop);
109   except
110     on E:Exception do
111       begin
112         ShowMessage(E.Message);
113         Exit(false);
114       end;
115   end;
116    result:=True;
117  end;
118 
119 end.
点赞
收藏
评论区
推荐文章
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
编程范儿 编程范儿
3年前
Vue刷新页面有哪几种方式
在Vue项目中,刷新当前页除了window.reload(),你还能想到什么办法?而且这种办法会重新加载资源出现短暂的空白页面。体验不是很好。在某个详情页面的时候,我们经常需要通过路由中的详情id去获取内容,当我们在不同的详情页来回切换的时候,打开的页面是同一个,只是需要通过监听路由中的参数id的变化去重新请求详情接口。如果这个详情页只需要一个接口
不才 不才
2年前
前端实现在浏览器中打印网页
前端数据报表打印方案背景项目:vueelementui需求:web端连接打印机打印报表功能关键词:浏览器端连接打印机打印报表调研首先,前端调用打印只有两种方式,使用window.print()和调用网络打印机。window.print这个是浏览器开放的api一般快捷键ctrlp或右键都也能调用。可以通过媒体查询的方案进行局部打印,也就是隐
Stella981 Stella981
3年前
Django REST framework的分页
DRF分页组件为什么要使用分页我们数据表中可能会有成千上万条数据,当我们访问某张表的所有数据时,我们不太可能需要一次把所有的数据都展示出来,因为数据量很大,对服务端的内存压力比较大还有就是网络传输过程中耗时也会比较大。通常我们会希望一部分一部分去请求数据,也就是我们常说的一页一页获取数据并展示出来。DRF使用
Wesley13 Wesley13
3年前
Spread for Windows Forms高级主题(7)
表单打印的多个部分都可以进行自定义,大多数的自定义选项存在于PrintInfo对象中。大多数打印选项是在PrintInfo对象上进行设置,并在表单级别上应用。当你执行打印操作时,你将一个特定的表单发送给使用这些设置的打印机。如果你想为不同的表单使用不同的打印设置,那么你可能需要重置PrintInfo对象,然后在表单打印的间隔内做必要的修改。深入理解打
Wesley13 Wesley13
3年前
unigui+fastreport 打印【4】
1、建立一个uniForm,用于建立FastReport打印界面。在Form上增加uniFrame。和传统的的报表打印设计一样一样的。2、在beofeShow事情中:procedureTUniFrm_Report.UniFormBeforeShow(Sender:TObject);varrptFileName,ur
Wesley13 Wesley13
3年前
LEADTOOLS如何检测,读取和写入条形码
工作场所中存在许多多页的文件。能够加载、拆分和提取是许多应用程序的重要需求。一些最常见的多页文件类型是:PDF,TIFF和MicrosoftOffice格式,例如Docx,Doc,Xls和Xlsx。LEADTOOLS支持所有这些格式以及30多种其他多页格式。由于存在多种不同类型的多页格式,因此尝试支持常见的格式可能会让人头疼,而试图支持所有这些格式的也像一
Stella981 Stella981
3年前
Redis5.0之后的内存策略
前言:这八种算法是基于redis5.0版之后的,他新增了新增allkeyslfu,volatilelfu这两种算法,也就是多了LFU算法,而LFU与LRU算法不同在于;LRU是淘汰最近最长时间未使用的页面进行淘汰,而LFU是要求在页置换时置换引用计数最小的页,因为经常使用的页应该有一个较大的引用次数。但是有些页在开始时使用次数很多,但以后就不再使用,
一次单据图片处理的优化实践 | 京东物流技术团队
1引言日常开发中接到这样的需求,上游系统请求获取一张A4单据用于仓库打印及展示,要求PNG图片格式,但是我们内部得到的单据格式为PDF,需要提取PDF文档的元素并生成一张PNG图片。目前已经有不少开源工具实现了这一功能,我们找了网上使用比较多的Apache
taskbuilder taskbuilder
2天前
TaskBuilder_v1.3.45版更新说明
TaskBuilderv1.3.45版更新说明打印报表整个打印报表功能进行了重构,解决了原来存在的打印模糊、分页不准确等问题,并采用跟tfp页面设计器一样的设计界面,使用更加简便,功能更加强大。具体包括以下功能特性:1、整个打印页面分为页眉、表头、表体、表