----筆者在前一段使用Delphi開發資料庫的工作中,使用者提出了這樣一個需求:要根據自己的查詢結果動態產生報表然後進行列印。幾經摸索,筆者使用動態產生QuickReport控制項的方法滿足了使用者的需求。現將此方法說明如下,希望能為有類似工作要做的朋友們提供一點有益的提示。
一、基本思路
----先將查詢的一些參數(如SQL指令,欄位名稱,欄位寬度等)依照一定格式寫入一個暫存檔案。在產生報表時,根據暫存檔案中所記錄的參數動態產生各種QuickReport控制項即可。
二、程式實現
2.1臨時文件格式
----臨時檔案的格式可以依需求自訂,筆者採用了INI的檔案格式。 Delphi提供了一個TInifile類,使得在Delphi中操作INI格式文件,非常方便。關於INI文件的格式和具體操作相關的文章有不少,我這裡不再贅述。臨時檔案格式如下:
Report.ini
:報表細節
[rep_detail]
Title=XXXXX表
:列印紙設置,1為A4紙,2為B5紙,3為16K
Page=1
:列印方式,1為橫打,0為豎打
Orientation=1
:報表包含的欄位數目
columns=8
:TQurey組件訊息
[QureyData]
:QuickReport元件中Tqurey元件的SQL指令的內容
Sql_command=select V_XM,V_JGZW,V_BMMC,V_DWMC,V_DWZW,V_ZY,V_ZC,V_BGDH from Hvzzjg where V_XM LIKE '李%'
[col_0]
Caption=姓名
DataFiled=V_XM
Width=60
……
……
2.2動態產生QuickReport報表
--- 報表的主要控制項及其主要屬性設定如下
控制項名稱 | 類別名 | 屬性 | 屬性值 |
Form_rep | TForm | caption | 動態報表 |
QuickRep | TQuickRep | DataSet | REP_QUERY |
DetailBand1 | TQRBand | BandType | rbDetail |
ColumnHeaderBand1 | TQRBand | BandType | rbColumnHeader |
REP_DataSource | TDataSource | DataSet | Rep_Query |
Rep_Query | TQuery | DatabaseName | REPDATABASE |
Rep_Database | TDatabase | Connected | True |
Params.Strings | 'SERVER NAME=XXX 'USER MAME=XXX' 'PASSWord=XXX' | ||
DatabaseName | REPDATABASE |
上表所示控制項是在程式中手動建立的。其他的控制項則要在程式中動態建立。
2.2.2主要程序
unit f_rep;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, QuickRpt, QRCtrls, DB, DBTables,PRINTERS,QRPrntr,inifiles,
TeeProcs, TeEngine, DbChart, QRTEE;
type
TForm_rep = class(TForm)
QuickRep: TQuickRep;
DetailBand1: TQRBand;
ColumnHeaderBand1: TQRBand;
REP_DataSource: TDataSource;
REP_QUERY: TQuery;
rep_Database: TDatabase;
procedure TForm_rep.QuickRepAfterPreview(Sender: TObject);//瀏覽完畢,釋放所有已建立的元件
private
{ Private declarations }
public
{ Public declarations }
end;
var Form_rep:TForm_Rep;
type //報表的摘要信息
C_rep_Summary=record
Title:string;//報表的標題
Page:TQRPaperSize;//報表的頁面設置,採用何種型號的紙
Orientation:TPrinterOrientation;//報表的頁面設置,是橫打還是垂直打
Columns:integer;//報表所包含的欄位數
end;
type
C_Rep_Col_Summary=record//報表列的摘要資訊
圖說:string;//報表的列名
DataFiled:string;//報表的欄位所對應的資料庫中的欄位名
Width:integer;//報表的列寬
end;
type
C_Rep_Col_Sum_store=record //儲存報表列的摘要信息
Caption_array:array of string;
DataFiled_array:array of string;
Width_array:array of integer;
end;
var
rep_Summary:C_rep_Summary;
Rep_Col_Summary:C_Rep_Col_Summary;
Rep_Col_Sum_store:C_Rep_Col_Sum_store;
Colum_Name:array of tQRRichText;
Colum_Data:array of TQRDBRichText;
C_Query:TQuery;
procedure Form_rep_init();
procedure DynCreat_TQRDBText(Colum_Num:integer;Colum_Height:integer;DataSet_Name:TQuery);//動態建立TQRDBText控件
procedure DynCreat_TQRRichtext(Colum_Num:integer);//動態建立TQRRichtext控制項
procedure DynCreat_TQuery(Inifile_Name:Tinifile);//動態建立TQuery控制項的SQL語句
procedure Get_PageCount();//取得列印總頁數
function Open_IniFile():Tinifile;//開啟暫存文件
procedure Read_Col_Summary(Inifile_Name:Tinifile);//讀取報表列的摘要信息
procedure Read_Rep_Summary(Inifile_Name:Tinifile);//讀取報表的摘要訊息
function rep_chanslateOrientation(var Rep_Orientation:integer):TPrinterOrientation;//將列印方式設定轉換
function rep_chanslatepage(var Rep_Page:integer):TQRPaperSize;//將列印頁尺寸設定轉換
implementation
{$R *.dfm}
function rep_chanslatepage(var Rep_Page:integer):TQRPaperSize;//將列印頁類型設定轉換
begin
case Rep_Page of
1:begin
result:=A4;
Form_rep.QuickRep.PrinterSettings.PaperSize:=A4;
end;
2:begin
result:=B5;
Form_rep.QuickRep.PrinterSettings.PaperSize:=B5
end;
3:begin
result:=Executive;
Form_rep.QuickRep.PrinterSettings.PaperSize:=Executive;
end;
end;
end;
function rep_chanslateOrientation(var Rep_Orientation:integer):TPrinterOrientation;//將列印方式設定轉換
begin
case Rep_Orientation of
0:begin
result:=poPortrait;//0為直
Form_rep.QuickRep.PrinterSettings.Orientation:=poPortrait;
end;
1:begin
result:=poLandscape;//1為水平
Form_rep.QuickRep.PrinterSettings.Orientation:=poLandscape;
end;
end;
end;
function Open_IniFile():Tinifile;//開啟暫存文件
var Filename:string;
Ini_Filename:string;
begin
Filename:='Report.ini';
Ini_Filename:=File_Path+Filename;
Result:=Tinifile.Create(Ini_Filename);
end;
procedure Read_Rep_Summary(Inifile_Name:Tinifile);//讀取報表的摘要訊息
var Rep_Page,Rep_Orientation:integer;
begin
rep_Page:=Inifile_Name.Readinteger('rep_detail','Page',1);
Rep_Orientation:=Inifile_Name.Readinteger('rep_detail','Orientation',0);
with rep_Summary do
begin
Columns:=Inifile_Name.Readinteger('rep_detail','columns',0);
Title:=Inifile_Name.Readstring('rep_detail','Title','未命名報表');
page:=rep_chanslatepage(Rep_Page);//將列印頁尺寸轉換
Orientation:=rep_chanslateOrientation(Rep_Orientation);//將列印方式設定轉換
end;
end;
procedure Read_Col_Summary(Inifile_Name:Tinifile);//讀取報表列的摘要信息
var i_count:integer;
begin
//將列資訊保存在陣列中
with Rep_Col_Sum_store do
begin
SetLength(Caption_array,rep_Summary.Columns);
SetLength(DataFiled_array,rep_Summary.Columns);
SetLength(Width_array,rep_Summary.Columns);
end;
for i_count:=0 to rep_Summary.Columns-1 do
begin
with Rep_Col_Summary do
begin
圖說:=Inifile_Name.Readstring('col_'+inttostr(i_count),'Caption','未命名');
DataFiled:=Inifile_Name.Readstring('col_'+inttostr(i_count),'DataFiled','');
Width:=Inifile_Name.Readinteger('col_'+inttostr(i_count),'Width',0);
end;
with Rep_Col_Sum_store do
begin
Caption_array[i_count]:=Rep_Col_Summary.Caption;
DataFiled_array[i_count]:=Rep_Col_Summary.DataFiled;
Width_array[i_count]:=Rep_Col_Summary.Width;
end;
end;
end;
procedure DynCreat_TQRRichtext(Colum_Num:integer);//動態建立TQRRichtext控制項,此控制項用來顯示報表每列的中文名稱
var Colum_Name_list:TStrings;
begin
Colum_Name[Colum_Num]:=tQRRichtext.Create(application); //建立TQRRichtext控制項
Colum_Name[Colum_Num].Parent:=Form_rep.ColumnHeaderBand1;
Colum_Name[Colum_Num].Frame.DrawTop:=true;
Colum_Name[Colum_Num].Frame.DrawBottom:=true;
Form_rep.ColumnHeaderBand1.Height:=40;
Colum_Name[Colum_Num].Height:=40;
Colum_Name[Colum_Num].Font.Height:=-14;
Colum_Name[Colum_Num].Font.Name:='黑體';
Colum_Name[Colum_Num].Top:=0;
Colum_Name[Colum_Num].Alignment:=taCenter;
Colum_Name[Colum_Num].AutoStretch:=false;
//畫表格線
Colum_Name[Colum_Num].Frame.Style:=psSolid;
Colum_Name[Colum_Num].Frame.Width:=1;
Colum_Name[Colum_Num].Frame.DrawRight:=true;
Colum_Name[Colum_Num].Frame.DrawBottom:=true;
if Colum_Num=0 then
begin
Colum_Name[Colum_Num].Frame.DrawLeft:=true;
end;
//將記錄RRep_Col_Sum_store中的資訊賦給Colum_Name
Colum_Name_list:=TStringList.Create;
Colum_Name_list.Add(Rep_Col_Sum_store.Caption_array[Colum_Num]);
Colum_Name[Colum_Num].Lines:=Colum_Name_list;
Colum_Name[Colum_Num].Width:=Rep_Col_Sum_store.Width_array[Colum_Num];
Colum_Name[Colum_Num].Visible:=true;
//計算左邊界
if Colum_Num>0 then
Colum_Name[Colum_Num].Left:=Colum_Name[Colum_Num-1].Left+Colum_Name[Colum_Num-1].Width
else
Colum_Name[Colum_Num].Left:=0;
end;
說明:此處採用TQRRichtext控制項是因為當名稱過長時,TQRRichtext控制項可以自動換行。
procedure DynCreat_TQRDBText(Colum_Num:integer;Colum_Height:integer;DataSet_Name:TQuery);//動態建立TQRDBText控制項,此控制項用來顯示每列的值
begin
Colum_Data[Colum_Num]:=tQRDBText.Create(application);
Colum_Data[Colum_Num].Parent:=Form_rep.DetailBand1;
//設定資料集
Colum_Data[Colum_Num].DataSet:=DataSet_Name;
//將陣列Colum_Data.DateField屬性設定為C_Rep_Col_Sum_store中的欄位名
Colum_Data[Colum_Num].DataField:=Rep_Col_Sum_store.DataFiled_array[Colum_Num];
Colum_Data[Colum_Num].Width:=Rep_Col_Sum_store.Width_array[Colum_Num];
Colum_Data[Colum_Num].Height:=Colum_Height;
Form_rep.DetailBand1.Height:=Colum_Height;
Colum_Data[Colum_Num].Top:=0;
Colum_Data[Colum_Num].AutoSize:=false;
Colum_Data[Colum_Num].AutoStretch:=false;
Colum_Data[Colum_Num].WordWrap:=false;
Colum_Data[Colum_Num].Visible:=true;
//畫表格線
Colum_Data[Colum_Num].Frame.Style:=psSolid;
Colum_Data[Colum_Num].Frame.DrawRight:=true;
Colum_Data[Colum_Num].Frame.DrawBottom:=true;
if Colum_Num=0 then
Colum_Data[Colum_Num].Frame.DrawLeft:=true;
//計算左邊界
if Colum_Num>0 then
Colum_Data[Colum_Num].Left:=Colum_Data[Colum_Num-1].Left+Colum_Data[Colum_Num-1].Width
else
Colum_Data[Colum_Num].Left:=0;
end;
procedure DynCreat_TQuery(Inifile_Name:Tinifile);//動態設定TQuery控制項的SQL語句
var
Sql_command:string;
begin
Flag_CreatQuery:=false;
Sql_command:=Inifile_Name.Readstring('QureyData','Sql_Command','');
Form_rep.REP_QUERY.Close;
Form_rep.REP_QUERY.SQL.Clear;
Form_rep.REP_QUERY.SQL.Append(Sql_command);
if not Form_rep.REP_QUERY.Prepared then
Form_rep.REP_QUERY.Prepare;
try
Form_rep.REP_QUERY.ExecSQL;
Form_rep.REP_QUERY.Active:=true;
Form_rep.REP_QUERY.AutoCalcFields:=true;
Flag_CreatQuery:=true;
except
Application.MessageBox('SQL語句錯誤!','系統提示',MB_ICONWARNING);
Flag_CreatQuery:=false;
end;
end;
procedure Form_rep_init();
var i_count:integer;
Rep_IniFile:Tinifile;//