用FASTREPORT实现WEB应用中自定义报表

44 篇文章 0 订阅
19 篇文章 0 订阅

用fastreport实现web应用中自定义报表_delphi教程

研发WEB应用系统通常都会遇见报表打印问题。简单应用可利用IE的页面打印功能,利用HTML标签控制格式来实现。但复杂的业务型应用系统,报表不仅是组成应用的重要部分,还常常是相当复杂的。目前非常多应用系统都需求提供自定义报表的功能??即客户能自行设计、修改报表。

在C/S结构系统中,报表问题有非常多成熟的解决方法。如DELPHI研发工具不仅自带有报表控件,还能利用第三方控件来实现快速灵活的报表制作和打印,其中有名的控件是FR-Software & A.Tzyganenko 的FastReport。FastReport提供了能和DELPHI无缝集成的从设计到打印的完整控件包,提供的设计界面友好灵活,对于研发可让用户自定义报表的C/S应用来说,是一种非常好的解决方式。

在B/S结构应用中,Crystal Report是一种大型报表系统常用和推荐的解决方案。但Crystal Report目前价格昂贵,而且该系统相当庞大。他的可制定性及精确控制打印效果方面尚不够完善。当然,在目前市场上,他仍是一种最佳选择的WEB应用的报表解决方案。

如果能将C/S应用中成熟的报表解决方案搬到B/S应用中,相信对于大部分研发人员来说,都是非常欢迎的。本文将讲述一个在JAVA环境中利用FastReport实现B/S应用中用户可自定义的报表解决方案。因为笔者近段时间正用DELPHI、JAVA做一些项目,所以样例代码就以DELPHI、JAVA编写。

本解决方案样例的基本环境是:WINDOWS 2000 SERVER+SQL SERVER 2000+TOMCAT 4.0。研发工具:IntelliJ IDEA 3.0,DELPHI 5.0。客户端为IE 5.0浏览器。

方案共需求用DELPHI编写两个程式,一个是将被包含在网页中并在浏览器中运行的ACTIVEX(.ocx),一个是运行在服务器端的报表处理程式,中间通过JAVA程式连接??或所有其他WEB语言都能,如ASP、PHP等。方案的基本原理图如下:

报表设计过程

报表打印过程

REPORT SERVER:能做成一个普通的WINDOWS程式,也能做成一个COM程式(Automation Object)。在报表设计过程中,用户端(ACTIVEX)向WEB SERVER发送报表设计请求,请求中包含要设计报表的名称;WEB SERVER 收到该请求后,调用REPORT SERVER请求设计的报表文件;REPORT SERVER收到请求后,先装载报表的数据环境,然后将报表设计文件(.frf)和该报表的数据环境文件压缩成一个包文件(.zip),将该包文件的完整路径名返回给WEB SERVER调用程式;WEB SERVER将包文件回送给用户端(ACTIVEX),用户端将接收到的包文件保存到本地硬盘上,并解压缩,从数据环境文件中恢复数据环境,通过FASTREPORT的相应控件打开报表文件给用户提供可视化设计。用户在ACTIVEX中设计报表时,虽然不能和数据库连接,但因数据环境已存在,所以用户仿如在通常的C/S应用结构下设计报表,能正常地看到报表的数据字典信息。在报表打印过程中,用户端(ACTIVEX)向WEB SERVER发送报表打印/预览请求,请求中包含要打印/预览的报表名称;WEB SERVER 收到该请求后,调用REPORT SERVER请求打印或预览的报表文件;REPORT SERVER收到请求后,先装载报表的数据环境,然后装载报表文件(.frf),接着在无界面状态下运行报表,最后将生成的已准备的报表文件(.frp)压缩成一个包文件(.zip),将该包文件的完整路径名返回给WEB SERVER调用程式;WEB SERVER将包文件回送给用户端(ACTIVEX),用户端将接收到的包文件保存到本地硬盘上,并解压缩,通过FASTREPORT的相应控件打开报表文件(.frp)给用户预览或打印或重新调整格式或输出为其他格式文件。用户在ACTIVEX中预览报表,仿如在通常的C/S应用结构下预览报表。

WEB SERVER:提供通常的WEB服务功能。

ACTIVEX:ActiveX是Microsoft提出的一组使用COM(Component Object Model,部件对象模型)使得软件部件可在网络环境中进行交互的技术集。他和具体的编程语言无关。作为针对Internet应用研发的技术,ActiveX被广泛应用于WEB服务器及客户端的各个方面。本方案中的ACTIVEX控件主要做两方面的事情,一是利用FASTREPORT控件进行报表处理,包括报表设计(.frf文件)和报表打印(.frp文件)。一是和WEB SERVER进行通信,请求和接收包文件。本文样例的ACTIVEX采用DELPHI 5.0编写。

下面分述各部分的一例具体实现(因为仅为说明方案的实现,所以非常多代码细节都进行了简省)。

一、             REPORT SERVER

REPORT SERVER既能做成一个普通的WINDOWS程式,也能做成一个COM程式(Automation Object)。本例中为简化见,采用普通的WINDOWS程式实现。

在DELPHI中NEW一个应用程式。在FORM中加入TfrReport、TfrDBDataSet、ADOConnection、TADOQuery等控件??为了使用FASTREPORT的控件,需要安装该控件包,可从站点http://www.fast-report.com 下载,国内非常多软件站点都提供该控件包的下载。其中TfrDBDataSet、TADOQuery控件视应用需要可加入多个,另外为了压缩文件,还要加入一个压缩控件,本例使用VCLZip。在Form1中加入三个函数:preDesignReport(rpFileName:String),prePrintReport(rpFileName:String),zipReportFiles(rpFileName:String),分别用于准备报表设计文件、准备报表打印文件、压缩报表文件 。Form1.Create方法为:

procedure TForm1.FormCreate(Sender: TObject);

var

        rpFileName,mode:String;

begin

        if paramCount>1 then

        begin

                mode:=paramStr(1);

                rpFileName:=paramStr(2);

                if mode=d then   //设计报表

                        if preDesignReport(rpFileName) then

                                zipReportFiles(rpFileName);

                if mode=r then   //打印报表

                        if prePrintReport(rpFileName) then

                                zipReportFiles(rpFileName);

        end;

        Application.Terminate;

end;

程式根据调用参数判断是准备报表设计文件还是准备报表打印文件,接着调用相应的过程来实现。最后的Application.Terminate 是让程式执行功能后即退出??因为这是服务端程式,是不能和用户交互的。

preDesignReport(rpFileName:String)方法:

function TForm1.preDesignReport(rpFileName:String):boolean;

var

……   //其他变量

        dtfFileName:String;

begin

        ……

dtfFileName:=StringReplace(rpFileName, ExtractFileExt(rpFileName),.dtf,

[rfReplaceAll, rfIgnoreCase]);

        try

rpAdoquery.SQL.Add(…);

                rpAdoquery.open;//打开报表的数据环境

                rpAdoquery.FieldList.SaveToFile(dtfFileName);

                result:=true;

        except

            on Exception do

                result:=false;

        end;

end;

函数preDesignReport的作用是准备报表设计文件。报表中能引用多个DataSet,本例假设报表只引用一个名为rpAdoquery的DataSet。rpFileName 为报表文件名(.frf),DtfFileName为保存数据环境的文件名(.dtf)。因为用户端不能连接数据库,所以将DataSet中的Fileds通过rpAdoquery.FieldList.SaveToFile(dtfFileName)保存到文件,和报表文件一起传送给用户端的ACTIVEX,ACTIVEX利用.dtf文件复现报表的数据环境。

prePrintReport(rpFileName:String)方法:

function TForm1.prePrintReport(rpFileName:String):boolean;

var

……

        repFileName:String;

begin

        ……

   repFileName:=StringReplace(rpFileName, ExtractFileExt(rpFileName),.frp,

[rfReplaceAll, rfIgnoreCase]);

        try

rpAdoquery.SQL.Add(…);

                rpAdoquery.open;//打开报表的数据环境

                frReport1.ShowProgress:=False;

                frReport1.Clear;

                frReport1.LoadFromFile(rpFileName);

                frDBDataSet1.DataSet :=rpAdoquery;

                frReport1.Dataset :=frDBDataSet1;

                frReport1.PrepareReport;

                frReport1.SavePreparedReport(repFileName);

                result:=true;

        except

            on Exception do

                result:=false;

        end;

end;

函数prePrintReport的作用是准备打印的报表文件,即先在服务器端装载报表并运行,将运行好的报表保存为文件,用于传送到用户端进行预览或打印。RepFileName是已准备好的报表文件名(.frp)。同样假设报表只引用一个名为rpAdoquery的DataSet。frReport1.ShowProgress:=False 使报表运行过程中不显示进度窗口(服务器端不能显示和用户交互的界面);接下来frReport1.Clear;…装载报表文件及设置相关数据属性;frReport1.PrepareReport 是在不显示预览窗口的情况下运行报表;frReport1.SavePreparedReport(repFileName) 将运行好的报表保存到文件,该文件传送给用户端的ACTIVEX,ACTIVEX能直接预览或显示该报表。

zipReportFiles(rpFileName:String)方法:

function TForm1.zipReportFiles(rpFileName:String):boolean;

var

……

        zipFileName,fileName:String;

        zipCount:Integer;

begin

        ……

zipFileName:=StringReplace(rpFileName, ExtractFileExt(rpFileName),.zip,

[rfReplaceAll, rfIgnoreCase]);

        fileName:= ExtractFileName(rpFileName);

        fileName:= ChangeFileExt(fileName,.*);

        try

                VCLZip1.ZipName:= zipFileName;

                VCLZip1.RootDir:= .\;

                VCLZip1.FilesList.Add(fileName);

                zipCount:= VCLZip1.Zip;

                if zipCount = 0 then

                        result:=false

                else

                        result:=true;

        except

            on Exception do

                result:=false;

        end;

end;

函数zipReportFiles的作用是把要传送给用户端的报表文件压缩为一个.zip文件,简化文件传送过程,而且压缩了数据量。ACTIVEX接收到.zip文件后,先解压出包中文件,再进行处理。



二、             WEB SERVER

方案中WEB SERVER的作用主要是根据ACTIVEX的请求调用REPORT SERVER,并将REPORT SERVER生成的.zip文件发送给ACTIVEX。样例通过一个report.jsp文件来处理:ACTIVEX通过get请求report.jsp文件,report.jsp文件调用REPORT SERVER处理后,将.zip文件发送给ACTIVEX。

Report.jsp文件:

<%@ page import="…"%>

<%@page contentType=" APPLICATION/OCTET-STREAM" %>

<%

    try

    {

        String reqFileName = request.getParameter("rpFileName");

String reqMode = request.getParameter("mode");//d为设计报表,r为打印报表

String rpFileName = xxxx.getRpFileName(reqFileName); //根据请求的报表名获得实际的报表文件名,如请求订单报表,而订单报表实际对应的报表文件为order.frf。

        String      l_cmd="reportserver.exe "+reqMode+" "+ reqFileName;

        Process l_ps=java.lang.Runtime.getRuntime().exec(l_cmd,null);

        byte[] l_b=new byte[100];

        while(l_ps.getInputStream().read(l_b,0,100)!=-1){

               ;

        }

       

//发送文件

String zipFileName = xxxx.getZipFileName(reqFileName); //获得压缩文件名

response.setHeader("Content-Disposition","attachment; filename=\"" +

zipFileName + "\"");

    java.io.FileInputStream fileInputStream =

new java.io.FileInputStream(zipFileName);

    int i;

    while ((i=fileInputStream.read()) != -1) {

     out.write(i);

    }

    fileInputStream.close();

    out.close();

    }

    catch(Exception e)

    {

        ……

    }

%>

String l_cmd="reportserver.exe "+reqMode+" "+ reqFileName; 组成调用REPORT SERVER的命令串。while(l_ps.getInputStream().read(l_b,0,100)!=-1){ ; } 等待REPORT SERVER执行完成,否则,程式在启动REPORT SERVER后即执行下一行语句。发送文件的方式有多种,比如也能由ACTIVEX通过ftp方式取得。




三、ACTIVEX

方案中的ACTIVEX控件主要做两方面的事情,一是报表利用FASTREPORT控件进行报表处理,包括报表设计(.frf文件)和报表打印(.frp文件)。一是和WEB SERVER进行通信,请求和接收包文件。

在DELPHI中NEW一个ActiveForm 应用,取名为reportAForm。在form中加入Combox、button、edit、label等和用户交互的控件;为了处理报表,加入FASTREPORT的多个frSpeedButton用于处理报表事件,如设计、预览、打印、翻页、保存等;加入frReport、frDBDataSet、frDesigner等用于在运行时设计报表;如果设计报表时要使用图像、复选框等内容,也要加入相应的控件;加入frPreview、frTextExport、frRTFExport等控件使能预览报表并能将报表输出为text、rtf等格式文件;加入ADOQuery(根据实际需要可加入多个)为报表设计提供数据环境,ADOQuery不OPEN,不和数据库连接;加入NMHTTP用于和WEB SERVER联系。加入四个函数:DesignReport(rpFileName:String),PrintReport(rpFileName:String),unzipReportFiles(rpFileName:String),getReportFile(rpFileName,mode:String)分别用于设计报表、打印报表、解压缩报表和向WEB SERVER发送请求以取得报表文件 。

getReportFile(rpFileName,mode:String)方法:

function TreportAForm.getReportFile(rpFileName,mode:String):boolean;

var

……

        zipFileName:String;

begin

    ……

zipFileName:=StringReplace(rpFileName, ExtractFileExt(rpFileName),.zip,

[rfReplaceAll, rfIgnoreCase]);

try

        NMHTTP1.inputFileMode := TRUE;

        NMHTTP1.body:=.\ + zipFileName;

NMHTTP1.Get(http://www…./../report.jsp?rpFileName=+

rpFileName+&mode=+mode);

Result:=true;

except

        on Exception do

        Result:=false;

        end;

end;

函数getReportFile的作用是向WEB SERVER发送报表请求(通过NMHTTP的Get方法),并将返回的压缩包文件保存到本地硬盘(zipFileName)。

unzipReportFiles(rpFileName:String)方法:

function TreportAForm.unzipReportFiles(rpFileName:String) :boolean;

var

……

        zipFileName,fileName:String;

        zipCount:Integer;

begin

        ……

        zipFileName:=StringReplace(rpFileName, ExtractFileExt(rpFileName),.zip,

[rfReplaceAll, rfIgnoreCase]);

        fileName:= ExtractFileName(rpFileName);

        fileName:= ChangeFileExt(fileName,.*);

        try

                VCLUnZip1.ZipName:= .\+ zipFileName;

                VCLUnZip1.DestDir:= .\;

                VCLUnZip1.OverwriteMode:= Always;

                VCLUnZip1.ReadZip;

                VCLUnZip1.FilesList.Add(fileName);

                zipCount:= VCLUnZip1.UnZip;

                if zipCount = 0 then

                        result:=false

                else

                        result:=true;

        except

            on Exception do

                result:=false;

        end;

end;

函数unzipReportFiles的作用是将压缩包中的文件解压出来,供ACTIVEX使用。他和REPORT SERVER程式中的zipReportFiles刚好是个相反的过程。

DesignReport(rpFileName:String)方法:

function TreportAForm. DesignReport (rpFileName:String) :boolean;

var

        dtfFileName,rpFileName:String;

        fldlist:TStringList;

        T: TStringField;

        i:Integer;

begin

        ……

        dtfFileName:=StringReplace(rpFileName, ExtractFileExt(rpFileName),.dtf,

[rfReplaceAll, rfIgnoreCase]);//获得数据环境文件名

        fldlist:=TStringList.Create;

        fldlist.LoadFromFile(dtfFileName);

        rpAdoquery.Fields.Clear;

        for i := 0 to fldlist.Count - 1 do

        begin

                T := TStringField.Create(nil);

                T.FieldName := fldlist[i];

                T.Name := rpAdoquery.Name + T.FieldName;

                rpAdoquery.Fields.add(T);

        end;

        FrReport1.LoadFromFile(rpFileName);

        FrReport1.DesignReport;

end;

函数DesignReport先从.dtf(由REPORT SERVER生成)文件中恢复报表的数据环境,接着使用FASTREPORT的FrReport控件设计报表。在FASTREPORT中,对DataSet中的Field只关心名称(全部通过Variant类型处理),而并不关心数据类型,所以恢复报表的数据环境时,所有字段都当作String类型加入。样例假设报表只有一个名为rpAdoquery的DataSet。报表设计运行时窗口在ACTIVEX进程空间运行。

用户端设计好报表并保存后,需要将保存的报表文件(.frf)回送给服务器存储。文件上传对于大部分研发人员来说应该都是熟悉而简单的,该部分程式本文就省略了。

PrintReport(rpFileName:String)方法:

function TreportAForm. PrintReport (rpFileName:String) :boolean;

var

        repFileName:String;

begin

        ……

        repFileName:=StringReplace(rpFileName, ExtractFileExt(rpFileName),.frp,

                [rfReplaceAll, rfIgnoreCase]);//获得已准备的报表文件名

        try

                frPreview1.clear;

                FrReport1.Preview:=nil;

                FrReport1.clear;

                FrReport1.LoadPreparedReport(repFileName);

                FrReport1.Preview :=frPreview1;

                FrReport1.ShowPreparedReport;

                result:=true;

        except

            on Exception do

                result:=false;

        end;

end;

函数PrintReport装入由REPORT SERVER运行好的报表.frp文件,通过调用FrReport的ShowPreparedReport方法在ACTIVEX端预览和打印。

方案实现方法的介绍结束。本方案具有的好处为:保持应用的结构形式不变(B/S),将C/S应用结构下已非常成熟的报表方案移植过来,使得在WEB应用中也可实现任意复杂的报表设计和打印,及对打印效果进行精确控制。


转载:http://blog.163.com/xu_shuhao/blog/static/525774872011102485032673/


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: FastReport.NET Web打印是一款基于FastReport.NET报表引擎的网页打印解决方案。它提供了一个简单而强大的工具,允许开发人员直接在Web应用程序生成和打印报表FastReport.NET Web打印有以下几个主要特点: 1. 强大的报表设计工具:FastReport.NET提供了一个直观、易于使用的报表设计器,开发人员可以通过拖放方式添加数据和控件,自定义报表样式和布局,轻松设计出符合需求的报表。 2. 多种数据源支持:FastReport.NET Web打印支持多种数据源,包括数据库、XML文件、JSON数据等,可以方便地从不同来源获取数据进行报表生成。 3. 支持多种输出格式:FastReport.NET Web打印支持多种输出格式,包括PDF、Excel、Word、图片等,用户可以将报表输出为多种常见的文件格式,方便保存和分享。 4. 可定制的报表模板:开发人员可以根据需求创建自定义报表模板,包括添加公司Logo、设置页眉页脚、调整字体颜色、样式等,实现报表的个性化定制。 5. 跨平台支持:FastReport.NET Web打印可以在各种操作系统和浏览器上运行,包括Windows、Linux、Mac等,兼容主流的浏览器,如Chrome、Firefox、IE等。 6. 安全性保障:FastReport.NET Web打印提供了安全的报表导出和打印功能,可以通过权限控制、加密处理等手段来保障报表数据的安全性。 总之,FastReport.NET Web打印是一种高效、灵活、易用的网页打印解决方案,可以帮助开发人员快速生成和打印各种类型的报表,提升工作效率,满足不同用户需求。 ### 回答2: FastReport.Net是一款优秀的报表生成工具,它不仅可以在桌面应用程序生成报表,还可以在web应用程序进行报表打印。 FastReport.Net Web打印功能允许我们在web浏览器直接打印报表,而无需将报表导出为PDF或其他格式再进行打印。这样可以大大简化打印流程,节省时间和工作量。 要使用FastReport.Net进行Web打印,我们需要在web应用程序引入FastReport.Net的相关库文件,并创建报表模板。报表模板的设计可以通过FastReport.Net提供的可视化设计器完成,也可以通过代码进行动态生成。 在Web应用程序,我们可以通过浏览器的打印按钮或者自定义的打印按钮来触发打印操作。当用户点击打印按钮时,FastReport.Net会将报表模板加载,并根据数据源的数据生成报表内容。 FastReport.Net提供了丰富的打印选项,包括打印份数、纸张类型、页眉页脚、页码等。我们可以根据需要自定义这些选项,以满足打印要求。 同时,FastReport.Net还支持导出报表为PDF、Excel、Word等格式,以满足不同的使用需求。导出的报表可以方便地保存、打印或分享给其他人。 总之,FastReport.Net的Web打印功能使得在web应用程序生成和打印报表变得简单高效。它的强大功能和简便操作为我们提供了一个便捷而强大的报表打印解决方案。 ### 回答3: FastReport.Net是一个用于创建报表的.NET框架。它具有强大的报表设计工具和丰富的功能,可以帮助开发人员快速而轻松地创建各种报表FastReport.Net支持Web打印的功能,可以将报表轻松地集成到Web应用程序。用户只需要通过Web浏览器访问应用程序,就可以查看和打印报表。这为用户提供了方便和灵活的报表访问方式。 使用FastReport.Net进行Web打印非常简单。开发人员只需设计好报表并将其与Web应用程序集成,然后将报表保存为指定的格式,如PDF或HTML。当用户在Web应用程序请求打印报表时,应用程序会动态地生成报表文件,并将其提供给用户进行打印。 通过FastReport.Net的Web打印功能,用户可以方便地打印报表,无需额外安装任何软件或工具。报表可以在任何设备上打印,包括计算机、平板电脑和手机等。 此外,FastReport.Net还提供了自定义打印设置和打印预览功能,用户可以根据自己的需求设置打印样式,并在打印之前预览报表的内容。这为用户提供了更加个性化和精确的报表打印体验。 总而言之,FastReport.Net的Web打印功能为用户提供了方便、灵活和个性化的报表打印方式。无论是开发者还是最终用户,都能够从受益并轻松地实现报表的访问和打印。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值