(中行雷威2018.3.8)
(同一个世界,同一个梦想,交流学习C++Builder XE10,传承c++builder的魅力!欢迎各地朋友加入我的QQ群484979943,进群密码“BCB”,同时也请将该群号广为宣传,希望能够广集各方高手,共同进步。欢迎访问我的博客http://blog.****.net/dlboy2018)
说明:
1、本演示程序使用了数据库访问控件UniDAC访问数据库,如果不了解该控件的安装与使用,请参考我的博文:http://blog.****.net/dlboy2018/article/details/79329047
2、FastReport5.6.2资源下载:https://download.****.net/download/dlboy2018/10276363
一、FastReport的安装
1、 编译
下载FastReport5.6.2的源代码程序,并拷贝到你的C++Builder的安装目录下C:\ProgramFiles (x86)\Embarcadero\Studio\19.0,解压后重新命名为FastReport562,进入C:\ProgramFiles (x86)\Embarcadero\Studio\19.0\FastReport562,右键以管理员权限运行Recompile.exe,如下图所示,第1步选择10.2版本,第4步选择Recompileall packages,开始编译。
一、FastReport的安装
1、 编译
下载FastReport5.6.2的源代码程序,并拷贝到你的C++Builder的安装目录下C:\ProgramFiles (x86)\Embarcadero\Studio\19.0,解压后重新命名为FastReport562,进入C:\ProgramFiles (x86)\Embarcadero\Studio\19.0\FastReport562,右键以管理员权限运行Recompile.exe,如下图所示,第1步选择10.2版本,第4步选择Recompileall packages,开始编译。
2、 安装
打开你的开发环境,新建一个VCL Forms Application项目,项目名称为testReport,保存在d:\testReport目录下
主菜单:Component-》install packages,安装bpl文件,如下图打开编译后产生的bpl文件所在目录,选择所有dcl*.bpl文件,选“打开”开始安装。
安装后如下图,将出现FastReport程序包,同时在窗口右下角将出现可用的控件组,说明已经安装成功。
主菜单:project-》options,在include path目录和library path两处同时添加两个目录:
C:\Program Files(x86)\Embarcadero\Studio\19.0\FastReport562\LibD25
C:\Program Files (x86)\Embarcadero\Studio\19.0\FastReport562\Source
如果没有按上述配置目录,编译时将报错如下:
按照一般项目的常识,设置不使用动态链接库和不使用动态包,这样子编译结果运行时才不需要提供相关的库文件或者包文件。
二、基础数据库
本例通过查询一个项目阶段表phase,演示如何访问数据库和通过报表模板生成可以打印数据报表。
三、程序设计
1、 建立主窗口FormMain,将其Position属性设置为poScreenCenter运行时屏幕居中显示,添加一个DBGrid表格控件、一个UniConnection数据库连接控件、一个OracleUniProvider数据库驱动控件、一个UniDataSource数据源控件、两个UniQuery数据库查询控件,添加一个frxReport报表模板控件、一个frxDBDataset报表关联数据源控件,两个Button按钮控件,一个查询数据表生成表格,一个查询数据生成打印报表。
注意:表格展示和报表打印可以只用一个UniQuery控件,但是如果使用同一个控件,在生成打印报表期间,表格上将出现逐条更换记录行的缓慢过程,单独使用一个UniQuery控件用于报表展示,将提高展示效率,客户体验较好。
1)DBGrid1、DataSource1、UniQuery1三者联动显示表格数据:
DBGrid1的DataSource属性设为UniDataSource1
DataSource1的DataSet属性设为UniQuery1
UniQuery1的Connection属性为UniConnection1
2)UniQuery2的Connection属性为UniConnection1
3)UniConnection1的ProviderName属性为Oracle,LoginPrompt属性为False
4)FrxReport1控件的DataSet属性为frxDBDataset1,将报表模板和数据集控件关联。
四、打印模板设计
双击frxReport1控件,打开打印模板设计窗口,主设计窗口分为左、中、右三个区域,最左侧区域是ObjectInspector对象查看区域,中间是ReportTree报表组件树区域,右侧是报表页面设计区域。其实,在最左侧屏幕边缘还有一列按钮,所有设计组件都在这里。
主菜单:report-》data,选择数据源
在最左侧红色字母A上面有一个图标,点该图标可以弹出上述红色区域,即band条带设计选择窗口,里面有ReportTitle报表标题、ReportSummary报表总结、PageHeader页头、PageFooter页尾、MasterData主数据带、DetailData明细数据带等丰富的条带控件,本例拖放一个ReportTitle、一个PageHeader、一个MasterData、一个PageFooter到页面区域,各个条带将自动对齐,可以手动调节各个带区的高度。
1、 ReportTitle设计
点击最左侧红色A图标,该图标为一般字段标签和关联数据字段的复合体。将该标签放到ReportTitle区域里。,双击控件,在里面输入“项目阶段一览”。
注意:各控件拖入条带区域时不要超出边界范围,否则将导致打印预览显示异常。
2、 PageHeader设计
如同上面1的方法,添加三个列头,分别是“项目阶段名称”“项目阶段类型”“项目阶段序号”。
然后点击主窗口最左侧那一列图标的倒数第二个,图像选择按钮,选择直线,在列标题上面画两条直线。
3、 MasterData设计(关键点)
双击右侧模板设计页面的黄色区域,选择数据集来源
如同上面1的方法,点击最左侧红色A图标,拖放到黄色的数据条带区,把弹出的界面直接关闭。然后在左侧,将其属性DataSet设置为frxDBDataset1,将其DataField设置为你要显示的数据表查询返回的字段名(支持中文),各个字段都如法炮制。
4、 PageFooter设计
如同1的方法,添加一个A,在其中输入“第[Page]页”,用于显示页编号,Page是FastReport报表设计系统的默认变量,可以直接引用。
5、 配置几个关键点
在下图右侧ReportTree树结构上选择Report,将左侧DataSet属性设置为“(Notassigned)”。
注意:如果设置不成功请先保存文件,关闭后重新打开再看情况修改。
在下图右侧ReportTree树结构上选择Page1,将左侧DataSet属性设置为“(Notassigned)”。
注意:如果设置不成功请先保存文件,关闭后重新打开再看情况修改。
配置好后点击主菜单栏下左数第四个打印预览小按钮,如果上述两个DataSet配置不取消,可能报错如下:
如果没有上述报错,仅仅报错frxDBDataset1未关联数据源,则基本没问题可以继续了。
6、保存你设计好的报表模板文件
由于报表模板设计器会将你设计的报表模板默认保存(暂未研究默认存在哪里),并且我们后续的代码是动态加载模板文件,因此,请用主菜单File->Save As菜单,将你的打印模板保存在你的项目编译后的可执行文件所在的目录下,本文保存为D:\testReport\Win32\Debug\report01.fr3
注意:程序发布时,要带上这个报表文件,放到可执行代码同级别目录下,当然也可以根据你的代码写法放在对应目录下。
五、功能代码实现
1、MainForm.h文件增加几个变量
//---------------------------------------------------------------------------
#ifndef UnitMainH
#define UnitMainH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include "DBAccess.hpp"
#include "MemDS.hpp"
#include "OracleUniProvider.hpp"
#include "Uni.hpp"
#include "uniBasicGrid.hpp"
#include "uniDBGrid.hpp"
#include "uniGUIBaseClasses.hpp"
#include "uniGUIClasses.hpp"
#include "UniProvider.hpp"
#include <Data.DB.hpp>
#include "frxClass.hpp"
#include "frxDBSet.hpp"
#include <Vcl.DBGrids.hpp>
#include <Vcl.Grids.hpp>
//---------------------------------------------------------------------------
class TFormMain : public TForm
{
__published: // IDE-managed Components
TUniConnection*UniConnection1;
TUniQuery*UniQuery1;
TUniQuery*UniQuery2;
TUniDataSource*UniDataSource1;
TOracleUniProvider*OracleUniProvider1;
TfrxReport*frxReport1;
TfrxDBDataset*frxDBDataset1;
TButton*Button1;
TButton*Button2;
TDBGrid*DBGrid1;
void__fastcall FormCreate(TObject *Sender);
void__fastcall Button1Click(TObject *Sender);
void__fastcall FormActivate(TObject *Sender);
void__fastcall Button2Click(TObject *Sender);
private: //User declarations
public: //User declarations
__fastcallTFormMain(TComponent* Owner);
AnsiString dbIp,dbPort,dbSid,dbUser,dbPass;//定义数据库连接参数
AnsiString mainPath,rptFileName;//定义程序运行主路径和报表文件名称
AnsiString mySql,rowId;//定义数据库查询语句变量
};
//---------------------------------------------------------------------------
extern PACKAGE TFormMain *FormMain;
//---------------------------------------------------------------------------
#endif
2、MainFrom.cpp主程序文件
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "UnitMain.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "DBAccess"
#pragma link "MemDS"
#pragma link "OracleUniProvider"
#pragma link "Uni"
#pragma link "uniBasicGrid"
#pragma link "uniDBGrid"
#pragma link "uniGUIBaseClasses"
#pragma link "uniGUIClasses"
#pragma link "UniProvider"
#pragma link "frxClass"
#pragma link "frxDBSet"
#pragma resource "*.dfm"
TFormMain *FormMain;
//---------------------------------------------------------------------------
__fastcall TFormMain::TFormMain(TComponent*Owner)
:TForm(Owner)
{
}
//---------------------------------------------------------------------------
//在FormMain的OnCreate事件中添加链接数据库的代码
//---------------------------------------------------------------------------
void __fastcallTFormMain::FormCreate(TObject *Sender)
{
AnsiString tmpStr;
mainPath=ExtractFilePath(Application->ExeName);//获取执行程序的绝对路径
dbIp="22.36.12.17";//初始化数据库连接参数
dbPort="1521";
dbSid="ORCL";
dbUser="project";
dbPass="******";
UniConnection1->Disconnect();
UniConnection1->ProviderName="Oracle";
UniConnection1->SpecificOptions->Add("direct=true");
//UniConnection1->SpecificOptions->Add("Charset=ZHS16GBK");
UniConnection1->Username=dbUser;
UniConnection1->Password=dbPass;
UniConnection1->Server=dbIp+":"+dbPort+":"+dbSid;
try
{
UniConnection1->Connect();
Vcl::Dialogs::ShowMessage("连接数据库["+dbIp+"]成功!");
}
catch(...)
{
Vcl::Dialogs::ShowMessage("连接数据库["+dbIp+"]失败!");
FormMain->Close();
}
}
//---------------------------------------------------------------------------
//在Button1按钮添加查询表数据功能
//---------------------------------------------------------------------------
void __fastcallTFormMain::Button1Click(TObject *Sender)
{
UniQuery1->Close();
UniQuery1->SQL->Clear();
mySql="select * from phase wherephase_type=:w1";
UniQuery1->SQL->Add(mySql);
UniQuery1->ParamByName("w1")->Value="一般项目";
UniQuery1->Open();
}
//---------------------------------------------------------------------------
//在FormMain的OnActivate事件中添加自动调用Button1按钮点击事件的功能
//---------------------------------------------------------------------------
void __fastcallTFormMain::FormActivate(TObject *Sender)
{
Button1->Click();//自动调用查询看结果
}
//---------------------------------------------------------------------------
//在Button2按钮增加调用打印功能的代码
//---------------------------------------------------------------------------
void __fastcall TFormMain::Button2Click(TObject*Sender)
{
UniQuery2->Close();
UniQuery2->SQL->Clear();
mySql="select * from phase wherephase_type=:w1";
UniQuery2->SQL->Add(mySql);
UniQuery2->ParamByName("w1")->Value="一般项目";
UniQuery2->Open();
if(UniQuery2->RecordCount==0)
{
Vcl::Dialogs::ShowMessage("没有记录,打印失败!");
return;
}
rptFileName="report01.fr3";//定义打印模板文件名称
if(!FileExists(mainPath+"\\"+rptFileName))
{
Vcl::Dialogs::ShowMessage("打印格式文件文件"+rptFileName+"不存在!");
return;
}
frxReport1->Clear();
frxDBDataset1->UserName="frxDBDataset1";//指定打印数据集名称
frxReport1->LoadFromFile(mainPath+"\\"+rptFileName);//加载打印模板目录+名称
frxReport1->DataSets->Clear();
frxDBDataset1->DataSet=UniQuery2;//指定数据集来自哪个查询控件
frxReport1->DataSets->Add(frxDBDataset1);//添加数据集
frxReport1->PrintOptions->ShowDialog=false;
frxReport1->PrepareReport();
frxReport1->ShowPreparedReport();//打印预览语句
//打印
//frxReport1->Print();//直接打印语句,和上面的打印预览语句根据需要二选一即可。
}
//---------------------------------------------------------------------------
六、运行结果
七、我的感触
FastReports是一款功能超级强大的报表设计控件,本文只是研究使用了其最基本的报表功能,早年就使用过其早期版本,时隔几年,重新捡起来,竟然又耗费了我一整天的时间,为赏后者,特撰写此文,如果想深入研究其丰富的功能,请安装C++Builder的同门师兄Delphi 10.2.2,在FastReport的安装目录C:\Program Files (x86)\Embarcadero\Studio\19.0\FastReport562\Demos有官方演示程序。