----Delphi を使用してデータベースを開発した著者の以前の作業で、ユーザーは、独自のクエリ結果に基づいてレポートを動的に生成し、印刷するという要件を提示しました。多くの検討を行った結果、作成者はユーザーのニーズを満たすために QuickReport コントロールを動的に生成する方法を使用しました。同じような仕事をしている友人に役立つヒントを提供できればと思い、この方法を以下で説明します。
1. 基本的な考え方
----まず、いくつかのクエリ パラメータ (SQL コマンド、フィールド名、フィールド幅など) を特定の形式で一時ファイルに書き込みます。レポートを生成するときは、一時ファイルに記録されたパラメーターに基づいてさまざまな QuickReport コントロールを動的に生成するだけです。
2. プログラムの実施
2.1 一時ファイルの形式
----一時ファイルの形式は必要に応じてカスタマイズできます。作成者は INI ファイル形式を使用します。 Delphi は、Delphi で INI 形式のファイルを操作するのに非常に便利な TInifile クラスを提供します。 INI ファイルの形式と具体的な操作については多くの記事があるため、ここでは詳しく説明しません。一時ファイルの形式は次のとおりです。
Report.ini
:レポート詳細
[担当者の詳細]
タイトル=XXXXX テーブル
:印刷用紙設定、1はA4用紙、2はB5用紙、3は16K
ページ=1
: 印刷モード。1 は水平印刷を意味し、0 は垂直印刷を意味します。
方向=1
:レポートに含まれるフィールドの数
列=8
:TQurey コンポーネント情報
[クエリデータ]
: 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]
キャプション=名前
DataFiled=V_XM
幅=60
…
…
2.2 QuickReport レポートを動的に生成する
--- レポートの主なコントロールとその主なプロパティ設定は次のとおりです。
コントロール名 | クラス名 | 財産 | 属性値 |
フォーム担当者 | Tフォーム | キャプション | 動的レポート |
クイックレップ | Tクイックレップ | データセット | REP_QUERY |
詳細バンド 1 | TQRバンド | バンドタイプ | rb詳細 |
列ヘッダーバンド 1 | TQRバンド | バンドタイプ | rb列ヘッダー |
REP_データソース | Tデータソース | データセット | Rep_Query |
Rep_Query | TQuery | データベース名 | REPデータベース |
担当者データベース | Tデータベース | 接続済み | 真実 |
Params.Strings | 'サーバー名=XXX 「ユーザーMAME=XXX」 「パスワード=XXX」 | ||
データベース名 | REPデータベース |
上の表に示されているコントロールは、プログラムで手動で作成されました。他のコントロールはプログラム内で動的に作成する必要があります。
2.2.2 主な手順
ユニット f_rep;
インタフェース
用途
ウィンドウ、メッセージ、SysUtils、バリアント、クラス、グラフィックス、コントロール、フォーム、
ダイアログ、ExtCtrls、QuickRpt、QRCtrls、DB、DBTables、PRINTERS、QRPrntr、inifiles、
TeeProcs、TeEngine、DbChart、QRTEE;
タイプ
TForm_rep = クラス(TForm)
クイックレップ: TQuickRep;
詳細バンド 1: TQR バンド;
列ヘッダーバンド 1: TQRBand;
REP_DataSource: TDataSource;
REP_QUERY: TQuery;
rep_Database: TDatabase;
procedure TForm_rep.QuickRepAfterPreview(Sender: TObject);//参照後、作成されたすべてのコンポーネントを解放します
プライベート
{プライベート宣言}
公共
{公的宣言}
終わり;
var Form_rep:TForm_Rep;
type //レポートの概要情報
C_rep_summary=レコード
Title:string;//レポートのタイトル
Page:TQRPaperSize;//レポートのページ設定、使用される用紙の種類
Orientation:TPrinterOrientation;//レポートのページ設定 (水平か垂直か)
Columns:integer;//レポートに含まれる列の数
終わり;
タイプ
C_Rep_Col_summary=record//レポート列の概要情報
Caption:string;//レポートの列名
DataFiled:string;//レポートの列に対応するデータベース内のフィールド名
width:integer;//レポートの列幅
終わり;
タイプ
C_Rep_Col_Sum_store=record //レポート列のストレージ概要情報
Caption_array:文字列の配列;
DataFiled_array:文字列の配列;
width_array: 整数の配列;
終わり;
変数
rep_サマリー:C_rep_サマリー;
Rep_Col_summary:C_Rep_Col_summary;
Rep_Col_Sum_store:C_Rep_Col_Sum_store;
Colum_Name: tQRichText の配列。
Colum_Data:TQRDBRichText の配列;
C_Query:TQuery;
プロシージャ Form_rep_init();
プロシージャ DynCreat_TQRDBText(Colum_Num:integer;Colum_Height:integer;DataSet_Name:TQuery);//TQRDBText コントロールを動的に作成します
procedure DynCreat_TQRRichtext(Colum_Num:integer);//TQRichtext コントロールを動的に作成
procedure DynCreat_TQuery(Inifile_Name:Tinifile);//TQuery コントロールを動的に作成する SQL ステートメント
プロシージャ Get_PageCount();// 印刷された総ページ数を取得する
function Open_IniFile():Tinifile;//一時ファイルを開く
プロシージャ Read_Col_summary(Inifile_Name:Tinifile);//レポート列の概要情報を読み取る
プロシージャ Read_Rep_summary(Inifile_Name:Tinifile);//レポートの概要情報を読み取る
function rep_chanslateOrientation(var Rep_Orientation:integer):TPrinterOrientation;//印刷モード設定を変換します
function rep_chanslatepage(var Rep_Page:integer):TQRPaperSize;//印刷ページ サイズ設定を変換します
実装
{$R *.dfm}
function rep_chanslatepage(var Rep_Page:integer):TQRPaperSize;//印刷ページ タイプ設定を変換します
始める
ケースのRep_ページ/
1:開始
結果:=A4;
Form_rep.QuickRep.PrinterSettings.PaperSize:=A4;
終わり;
2:開始
結果:=B5;
Form_rep.QuickRep.PrinterSettings.PaperSize:=B5
終わり;
3:開始
結果:= エグゼクティブ;
Form_rep.QuickRep.PrinterSettings.PaperSize:=Executive;
終わり;
終わり;
終わり;
function rep_chanslateOrientation(var Rep_Orientation:integer):TPrinterOrientation;//印刷モード設定を変換します
始める
case Rep_Orientation の
0:開始
result:=poPortrait;//0 は垂直です
Form_rep.QuickRep.PrinterSettings.Orientation:=poPortrait;
終わり;
1:開始
result:=poLandscape;//1 は水平です
Form_rep.QuickRep.PrinterSettings.Orientation:=poLandscape;
終わり;
終わり;
終わり;
function Open_IniFile():Tinifile;//一時ファイルを開く
var ファイル名: 文字列;
Ini_ファイル名:文字列;
始める
ファイル名:='レポート.ini';
Ini_Filename:=ファイルパス+ファイル名;
結果:=Tinifile.Create(Ini_Filename);
終わり;
プロシージャ Read_Rep_summary(Inifile_Name:Tinifile);//レポートの概要情報を読み取る
var Rep_Page,Rep_Orientation:integer;
始める
rep_Page:=Inifile_Name.Readinteger('rep_detail','ページ',1);
Rep_Orientation:=Inifile_Name.Readinteger('rep_detail','Orientation',0);
rep_summary を使用して実行します
始める
Columns:=Inifile_Name.Readinteger('rep_detail','columns',0);
Title:=Inifile_Name.Readstring('rep_detail','タイトル','名前のないレポート');
page:=rep_chanslatepage(Rep_Page);//印刷ページサイズを変換する
Orientation:=rep_chanslateOrientation(Rep_Orientation);//印刷モード設定を変換する
終わり;
終わり;
プロシージャ Read_Col_summary(Inifile_Name:Tinifile);//レポート列の概要情報を読み取る
変数 i_count:整数;
始める
//列情報を配列に保存
Rep_Col_Sum_store を使用して行う
始める
SetLength(Caption_array,rep_summary.Columns);
SetLength(DataFiled_array,rep_summary.Columns);
SetLength(Width_array,rep_summary.Columns);
終わり;
for i_count:=0 から rep_summary.Columns-1 まで
始める
Rep_Col_summary を使用して行う
始める
Caption:=Inifile_Name.Readstring('col_'+inttostr(i_count),'Caption','Unnamed');
DataFiled:=Inifile_Name.Readstring('col_'+inttostr(i_count),'DataFiled','');
width:=Inifile_Name.Readinteger('col_'+inttostr(i_count),'Width',0);
終わり;
Rep_Col_Sum_store を使用して行う
始める
Caption_array[i_count]:=Rep_Col_summary.Caption;
DataFiled_array[i_count]:=Rep_Col_summary.DataFiled;
width_array[i_count]:=Rep_Col_summary.Width;
終わり;
終わり;
終わり;
procedure DynCreat_TQRRichtext(Colum_Num:integer);//レポート内の各列の中国語名を表示するために使用される TQRRichtext コントロールを動的に作成します
var 列名リスト:TStrings;
始める
Colum_Name[Colum_Num]:=tQRRichtext.Create(application) //TQRichtext コントロールを作成します。
列名[列番号].Parent:=Form_rep.ColumnHeaderBand1;
列名[列番号].Frame.DrawTop:=true;
列名[列番号].Frame.DrawBottom:=true;
Form_rep.ColumnHeaderBand1.Height:=40;
列名[列番号].高さ:=40;
列名[列番号].Font.Height:=-14;
Colum_Name[Colum_Num].Font.Name:='地獄の本体';
列名[列番号].Top:=0;
列名[列番号].Alignment:=taCenter;
列名[列番号].AutoStretch:=false;
//テーブルの線を描画します
列名[列番号].Frame.Style:=psSolid;
列名[列番号].フレーム.幅:=1;
列名[列番号].Frame.DrawRight:=true;
列名[列番号].Frame.DrawBottom:=true;
Colum_Num=0 の場合
始める
列名[列番号].Frame.DrawLeft:=true;
終わり;
//レコード RRep_Col_Sum_store の情報を Colum_Name に代入します
列名リスト:=TStringList.Create;
列名リスト.Add(Rep_Col_Sum_store.Caption_array[列番号]);
列名[列番号].Lines:=列名リスト;
列名[列番号].幅:=Rep_Col_Sum_store.幅配列[列番号];
列名[列番号].Visible:=true;
//左境界を計算する
列番号>0の場合
列名[列番号].左:=列名[列番号-1].左+列名[列番号-1].幅
それ以外
列名[列番号].左:=0;
終わり;
注: TQRichtext コントロールは、名前が長すぎる場合に自動的に行を折り返すことができるため、ここでは TQRichtext コントロールが使用されています。
プロシージャ DynCreat_TQRDBText(Colum_Num:integer;Colum_Height:integer;DataSet_Name:TQuery);//各列の値を表示するために使用される TQRDBText コントロールを動的に作成します
始める
Colum_Data[Colum_Num]:=tQRDBText.Create(アプリケーション);
Colum_Data[Colum_Num].Parent:=Form_rep.DetailBand1;
//データセットを設定する
列データ[列番号].DataSet:=データセット名;
// 配列の 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];
列データ[列番号].高さ:=列高さ;
Form_rep.DetailBand1.Height:=Colum_Height;
列データ[列番号].Top:=0;
列データ[列番号].AutoSize:=false;
列データ[列番号].AutoStretch:=false;
列データ[列番号].WordWrap:=false;
列データ[列番号].Visible:=true;
//テーブルの線を描画します
Colum_Data[Colum_Num].Frame.Style:=psSolid;
Colum_Data[Colum_Num].Frame.DrawRight:=true;
Colum_Data[Colum_Num].Frame.DrawBottom:=true;
Colum_Num=0 の場合
Colum_Data[Colum_Num].Frame.DrawLeft:=true;
//左境界を計算する
列番号>0の場合
列データ[列番号].左:=列データ[列番号-1].左+列データ[列番号-1].幅
それ以外
列データ[列番号].左:=0;
終わり;
プロシージャ DynCreat_TQuery(Inifile_Name:Tinifile);//TQuery コントロールの SQL ステートメントを動的に設定します
変数
SQL_コマンド:文字列;
始める
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);
Form_rep.REP_QUERY.Prepared でない場合は、
Form_rep.REP_QUERY.Prepare;
試す
Form_rep.REP_QUERY.ExecSQL;
Form_rep.REP_QUERY.Active:=true;
Form_rep.REP_QUERY.AutoCalcFields:=true;
Flag_CreatQuery:=true;
を除外する
Application.MessageBox('SQL ステートメント エラー!','システム プロンプト',MB_ICONWARNING);
Flag_CreatQuery:=false;
終わり;
終わり;
プロシージャ Form_rep_init();
変数 i_count:整数;
Rep_IniFile:Tinifile;//