1、使用TfrxReport 組件工做
一、加載並存儲報表
默認狀況下,報表窗體同項目窗體構存儲在同一個DFM文件中。多數狀況下,無須再操做,於是你就沒必要採用特殊方法加載報表。若是你決定在文件中存儲報表窗體或者是數據庫的數據庫
Blob字段(他提供了很是大的彈性,你可以在非編譯程序中修改),你必須使用「TfrxReport」提供的加載和存儲方法。
function LoadFromFile(const FileName: String; ExceptionIfNotFound: Boolean = False): Boolean;
從一個給定名字文件中加載報表。若是第二個參數等於「True」而且文件沒找到,那麼他會觸發一個異常。若是文件加載成功,他返回「True」。工具
procedure LoadFromStream(Stream: TStream);
從流中加載報表。this
procedure SaveToFile(const FileName: String);
用特殊名稱文件存儲報表。翻譯
procedure SaveToStream(Stream: TStream);
把報表存在流中。設計
例如:
Pascal:
frxReport1.LoadFromFile('c:\1.fr3');
frxReport1.SaveToFile('c:\2.fr3');component
C++:
frxReport1->LoadFromFile("c:\\1.fr3");orm
frxReport1->SaveToFile("c:\\2.fr3");對象
2.設計報表
經過「TfrxReport.DesignReport」方法調用報表設計器。你必須在你的項目中包含報表設計器(必要條件是:要麼使用「TfrxDesigner」組件,要麼增長「frxDesgn」單元到uses事件
列表)
「DesigReport」方法接受兩個默認參數:
procedure DesignReport(Modal: Boolean = True; MDIChild: Boolean = False);
Modal參數決定設計器是否被模態,MDIChild參數容許把設計器窗體做爲一個MDI子窗體。ci
例如:
frxReport1.DesignReport;
3.運行報表
應用下面兩個「TfrxReport」方法中的一個啓動報表:
procedure ShowReport(ClearLastReport: Boolean = True);
啓動報表並在預覽窗體中顯示。若是「ClearLastReport」參數等於「False」,報表將會增長先前的一個報表結果,不然清除前一個報表結構。
function PrepareReport(ClearLastReport: Boolean = True): Boolean;
啓動報表,沒有打開預覽窗體,參數賦值與「ShowReport」方法同名。若是報表構形成功,他返回「True」。
多數狀況下,使用第一種方法更爲方便一些。在報表被構造的同時,他會馬上顯示一個預覽窗體。
當須要增長另外一個報表到前一個報表中的時候,「ClearLastReport」參數顯得方便些。(此類技術用於批量報表打印)。
例如:
frxReport1.ShowReport;
4.預覽報表
使用兩種途徑顯示一個報表是可能的:二者都是調用「TfrxReport.ShowReport」方法(先前描述過了),或者使用「TfrxReport.ShowPreparedReport」方法來幫助實現。在第二
種狀況下,報表構造沒有被執行,但顯示了一個完成的報表。也就是說,你要麼在「PreparedReport」方法幫助下構造他,要麼在構造前從文件中加載報表(查看「加載/存儲完
成的報表」)
例如:
Pascal:
if frxReport1.PrepareReport then
frxReport1.ShowPreparedReport;
C++:
if(frxReport1->PrepareReport(true))
frxReport1->ShowPreparedReport();
在這種狀況下,報表構造器先被完成了,並顯示在預覽窗體中。構造一個龐大的報表可能要花費不少時間,那就是爲何使用「ShowReport」非等時同步方法會好於
「PrepareReport/ShowPreparedReport」方法。你能夠經過「TfrxReport.PreviewOptions」屬的缺省值設定預覽參數值。(這句翻譯的不夠好,請參考原文)
原文參考:In this case, report construction is finished first, and after that it is displayed in the preview window. Construction of a large report can take
a lot of time, and that is why it is better to use the 「ShowReport anisochronous」 method, than the 「PrepareReport/ShowPreparedReport」 one. One can assign
preview settings by default via the 「TfrxReport.PreviewOptions」 property.[SPAN]五、打印報表
大多數狀況下,你能夠從預覽窗體打印報表。要人工打印報表,你應該使用「TfrxReport.Print」方法,例如:
frxReport1.LoadFromFile(...);
frxReport1.PrepareReport;
frxReport1.Print;
同時,你能夠在顯示的打印對話框中設置打印參數,你也可使用默認設定值。取消打印對話框,請參考「TfrxReport.PrintOptions」屬性幫助
6.載入並存儲報表
這個功能能夠在預覽窗口中執行。也可使用手工方法執行,幫助參考「TfrxReport.PreviewPages」方法:
function LoadFromFile(const FileName: String; ExceptionIfNotFound: Boolean = False): Boolean;
procedure SaveToFile(const FileName: String);
procedure LoadFromStream(Stream: TStream);
procedure SaveToStream(Stream: TStream);
賦值和參數化相似與TfrxReport相應的方法。文件包含了完成的報表,默認狀況下以「FP3」爲擴展名。
例如:
Pascal:
frxReport1.PreviewPages.LoadFromFile('c:\1.fp3');
frxReport1.ShowPreparedReport;
C++:
frxReport1->PreviewPages->LoadFromFile("c:\\1.fp3");
frxReport1->ShowPreparedReport();
注意,完成的報表加載完畢後,預覽方法是經過「ShowPreparedReport」 方法執行的。
7.導出報表
他能夠從預覽窗口中執行。也能夠手動操做,經過「FfrxReport.Export」方法,及這個方法中的參數,你能夠導出你想要導出的文件類型:
frxReport1.Export(frxHTMLExport1);
導出過濾組件必須是有效的(你必須把他們放到你項目中的窗體上)並調整正確。
The export filter component must be available (you must put it on the form of your project) and be adjusted correctly.
8.建立自定義預覽窗體
FastReport在標準的預覽窗口中顯示報表。若是由於某些緣由而不適合你,你能夠建立一個自定義預覽窗體。爲了這個目的,須要設計FastReport組件面板中的「TfrxReport」組
件。要顯示報表,TfrxReport.Preview方法應該鏈接到這個組件。
在使用TfrxPreview組件的時候,有兩個典型的問題。他不會處理按鍵(箭頭,PgUp,PgDown等等)和鼠標滾輪(若是有的話)。要讓TfrxPreview同按鍵工做,設置焦點給他(他
是能夠作到的,例如,在窗體的OnShow事件句柄中)
frxPreview.SetFocus;
要讓TfrxPreview同鼠標滾輪工做,你必須建立OnMouseWheel事件句柄,而且調用TfrxPreview.MouseWheelScroll方法。
procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
begin
frxPreview1.MouseWheelScroll(WheelDelta);
end;
9.創建複合報表(批量打印)
在某些狀況下,須要馬上組織幾個報表打印,或者在一個打印預覽窗體中封裝並呈現幾個報表。要執行這些,在FastReport中有些工具可以容許創建一個新的報表附加在一個
已經存在的報表上。「TfrxReport.PrepareReport」方法中有一個選項「ClearLasReport」布爾類型參數,默認狀況下他等於True,這個參數定義了是否有必要在創建報表時清除
前一個報表。下面的方法展現瞭如何從兩個報表中創建一個批量報表:
Pascal:
frxReport1.LoadFromFile('1.fr3');
frxReport1.PrepareReport;
frxReport1.LoadFromFile('2.fr3');
frxReport1.PrepareReport(False);
frxReport1.ShowPreparedReport;
C++:
frxReport1->LoadFromFile("1.fr3");
frxReport1->PrepareReport(true);
frxReport1->LoadFromFile("2.fr3");
frxReport1->PrepareReport(false);
frxReport1->ShowPreparedReport();
咱們加載並創建第一個報表,但並無顯示他。而後咱們加載第二個報表到同一個TfrxReport對象,並使用「ClearLastReport」參數,讓他等於False。這就容許第二個報表
附加在先前創建的報表以後。接下來,咱們在預覽窗口中顯示一個完成的報表。
9.1 複合報表中的頁數
你可使用「Page」,「Page#」,「TotalPages」和「TotalPages#」系統變量顯示頁數或總頁數,在複合報表中,這些變量如下面的方式工做:
Page - 當前報表頁數
Page# - 批量報表頁數
TotalPages - 當前報表總頁數(報表必須兩遍)
Totalpages# - 批量報表總頁數
9.2 合併符合報表頁數
正如上面所說的,報表設計頁中的「PrintOnPrevousPage」方法讓你在打印報表的時候使用前一頁的剩餘空間接合報表。在複合報表中,容許你在前一個報表的最後一頁的剩
餘空間建立一個新的報表。要執行這個,要使能每個連續報表的第一個設計頁「PrintOnPreviousePage」屬性[SPAN]10.交互報表
在交互報表中,你能夠在預覽窗口定義任意報表對象的鼠標單擊反應。例如,一個用戶可以單擊數據線,結果運行一個帶有選擇線的明細數據。
任何報表都能交互。要執行他,你僅僅須要建立TfrxReport.OnClickObject事件句柄。下面代碼是這個事件句柄的示例:
Pascal:
procedure TForm1.frxReport1ClickObject(Page: TfrxPage; View: TfrxView;
Button: TMouseButton; Shift: TShiftState; var Modified: Boolean);
begin
if View.Name = 'Memo1' then
ShowMessage('Memo1 contents:' + #13#10 + TfrxMemoView(View).Text);
if View.Name = 'Memo2' then
begin
TfrxMemoView(View).Text := InputBox('Edit', 'Edit Memo2 text:', TfrxMemoView(View).Text);
Modified := True;
end;
end;
C++:
void __fastcall TForm1::frxReport1ClickObject(TfrxView *Sender,
TMouseButton Button, TShiftState Shift, bool &Modified)
{
TfrxMemoView * Memo;
if(Memo = dynamic_cast <TfrxMemoView *> (Sender))
{
if(Memo->Name == "Memo1")
ShowMessage("Memo1 contents:\n\r" + Memo->Text);
if(Memo->Name == "Memo2")
{
Memo->Text = InputBox("Edit", "Edit Memo2 text:", Memo->Text);
Modified = true;
}
}
}
在對象的單擊事件句柄上,你能夠作以下事情:
- 修改一個對象或頁的內容,傳遞句柄(結果,被修改的將被特殊標記,所以修改的內容應該引發重視);
- 因爲使用重構或從新創建報表,調用TfrxReport.PrepareReport方法
在此例中,點擊名字爲memo1對象的結果顯示這個對象內容的消息。當點擊memo2是顯示一個對話框,這個對象的內容可能被修改。設置Modified標誌爲True,容許保持和顯示變動
。
一樣的方法,單擊事件能夠被定義成不一樣的響應。例如,運行一個新報表。以下注釋是必要的。在FastReport3版本中,一個報表組件能夠在一個預覽窗口中顯示惟一的報表(不像
FastReport2.x版本)。那就是爲何一個報表預覽窗也會在分開的對象中運行一個報表,或者是同一個對象,但當前報表必須被抹除。
關於給終端用戶一個可單擊對象提示定位,在預覽窗口中,鼠標通過一個可單擊對象的時候,咱們能夠修改鼠標的光標。要作到這些,在報表設計器上選擇一個要設計的對象並設置
他的cursor屬性爲不一樣於crDefault的某個值。
更多的細節涉及到定義的單擊對象。在簡單報表中,能夠依照對象的名字或他的內容來定義。然而,這就不能更多的執行可修改的事例。例如,一個明細報表應當在一個數據選擇
行被建立。一個用戶單擊了內容爲12的memo1對象。數據行讓這個對象參考什麼?那就是爲何你應當知道主鍵了,主鍵用於明確的標識這一行。FastReport可以賦值一個字串,包
含任意數據(在咱們的事例主鍵數據中),對於每一個報表對象,這個字串存儲在TagStr屬性中。
讓咱們來經過一個報表的例子來舉例說明,這個報表包含在FastReportDemo.exe-'Simple list'示例中。這是一個公司的客戶列表,包含諸如客戶名稱,地址,聯繫人等數據。數
據源是來自DBDEMOS演示數據庫的Customer.db表。這個表有一個主鍵,CustNO字段,他沒有出如今報表中。咱們的任務是終止他經過參考單擊完成報表上的任意對象記錄他,這就
意味着要獲取主鍵的值,要執行此項操做,就要爲全部對象的TagStr屬性加入值,依賴於主數據欄:
[Customers."CustNo"]
在報表創建期間,使用相同的方法計算TagStr屬性內容,同時計算文本對象的內容;這就意味着變量值會替代全部變量的位置。變量細節使用方括號括起來。那就是爲何行值
是'1005', '2112'等相似值了。在報表創建後,包含TagStr屬性對象的類型取決與主數據欄。一個簡單的從字串到整形的轉換就會提供給咱們一個主鍵的值,這也是所需記錄可以
找到的主鍵。
若是主鍵是複合的(包含多個字段),TagStr屬性的內容多是以下值:
[Table1."Field1"];[Table1."Field2"]
在構造一個報表完成後,TagStr屬性包含「1000;1」類型值, 此值不一樣比相同要好。
11.從代碼中存取報表對象
報表對象(例如:report page, band, memo-object)是不能在你的代碼中直接存取的。這就意味着你不能經過名字尋址對象。例如,當你在你的窗體上尋址一個按鈕。要尋址一
個對象,在TfrxReport.FindObject方法中找到幫助:
Pascal:
var
Memo1: TfrxMemoView;
Memo1 := frxReport1.FindObject('Memo1') as TfrxMemoView;
C++:
TfrxMemoView * Memo =
dynamic_cast <TfrxMemoView *> (frxReport1->FindObject("Memo1"));
而後,你就可以尋址對象的屬性和方法。你也使用「TfrxReport.Pages」屬性尋址報表頁。
Pascal:
var
Page1: TfrxReportPage;
Page1 := frxReport1.Pages[1] as TfrxReportPage;
C++:
TfrxReportPage * Page1 = dynamic_cast <TfrxReportPage *> (frxReport1->Pages[1]);
12.從代碼中建立報表
做爲一項規則,你將在設計器中建立多數報表。然而,在某些狀況下(例如,當報表窗體未知的時候),使用代碼手工建立一個報表是是十分必要的。
想要手工建立一個報表,你須要執行下面的順序步驟:
- 清除報表組件
- 添加數據源
- 添加數據頁
- 添加報表頁
- 添加欄頁
- 設置欄屬性,接着把他們同數據相連
- 在每一個欄上加入對象
- 設置對象屬性,接着把他們同數據相連
讓咱們來檢查一下建立一個簡單報表的類型列表。假設咱們擁有以下組件:frxReport1: TfrxReport and frxDBDataSet1: TfrxDBDataSet(最後一個鏈接到DBDEMOS數據,
Customer.db表)。咱們的報表將包含一個帶有報表標題和主數據欄的頁。在報表標題欄上有一個帶有「Hellow FastReport」文本的對象,主數據欄包含一個帶有鏈接到「CustNo」
字段的對象。
Pascal:
var
DataPage: TfrxDataPage;
Page: TfrxReportPage;
Band: TfrxBand;
DataBand: TfrxMasterData;
Memo: TfrxMemoView;
{ 清除報表 }
frxReport1.Clear;
{ 爲報表添加數據集到可存取的列表中 }
frxReport1.DataSets.Add(frxDBDataSet1);
{ 添加"Data"頁 }
DataPage := TfrxDataPage.Create(frxReport1);
{ 添加頁 }
Page := TfrxReportPage.Create(frxReport1);
{ 建立惟一名稱 }
Page.CreateUniqueName;
{ 設置默認字段大小, 紙張和打印方向 }
Page.SetDefaults;
{ 修改紙張方向 }
Page.Orientation := poLandscape;
{ 添加一個報表標題欄 }
Band := TfrxReportTitle.Create(Page);
Band.CreateUniqueName;
{ it is sufficient to set the ?Top? coordinate and height for a band }
{ both coordinates are in pixels }
Band.Top := 0;
Band.Height := 20;
{ 爲標題欄添加一個對象 }
Memo := TfrxMemoView.Create(Band);
Memo.CreateUniqueName;
Memo.Text := 'Hello FastReport!';
Memo.Height := 20;
{ 這個對象將伸展座標到欄的寬度 }
Memo.Align := baWidth;
{ 添加主數據欄 }
DataBand := TfrxMasterData.Create(Page);
DataBand.CreateUniqueName;
DataBand.DataSet := frxDBDataSet1;
{ 頂端的調整應當比先前加入欄的頂部+高度大一些 }
DataBand.Top := 100;
DataBand.Height := 20;
{ 在主數據欄上添加一個對象 }
Memo := TfrxMemoView.Create(DataBand);
Memo.CreateUniqueName;
{ 鏈接數據 }
Memo.DataSet := frxDBDataSet1;
Memo.DataField := 'CustNo';
Memo.SetBounds(0, 0, 100, 20);
{ 調整文本到右側的對象邊緣 }
Memo.HAlign := haRight;
{ 顯示報表 }
frxReport1.ShowReport;
C++:
TfrxDataPage * DataPage;
TfrxReportPage * Page;
TfrxBand * Band;
TfrxMasterData * DataBand;
TfrxMemoView * Memo;
// 清除報表
frxReport1->Clear();
// 在報表上添加一個數據集到數據集存取列表
frxReport1->DataSets->Add(frxDBDataset1);
// 添加「數據」頁
DataPage = new TfrxDataPage(frxReport1);
// 添加一頁
Page = new TfrxReportPage(frxReport1);
// 建立一個不重複的名稱
Page->CreateUniqueName();
// 設置域大小, 紙張和默認的打印方向
Page->SetDefaults();
// 修改紙張的打印方向
Page->Orientation = poLandscape;
// 增長一個報表標題欄
Band = new TfrxReportTitle(Page);
Band->CreateUniqueName();
// 爲欄充分設置頂部座標和高度
// 在像素上包含座標
Band->Top = 0;
Band->Height = 20;
// 在報表標題欄加入一個對象
Memo = new TfrxMemoView(Band);
Memo->CreateUniqueName();
Memo->Text = "Hello FastReport!";
Memo->Height = 20;
// 此對象將會被按照欄的寬度延展
Memo->Align = baWidth;
// 添加主數據欄
DataBand = new TfrxMasterData(Page);
DataBand->CreateUniqueName();
DataBand->DataSet = frxDBDataset1;
// 頂部座標應該大於前邊添加欄的頂部座標+高度
DataBand->Top = 100;
DataBand->Height = 20;
// 主數據上加入一個對象
Memo = new TfrxMemoView(DataBand);
Memo->CreateUniqueName();
// 鏈接到數據
Memo->DataSet = frxDBDataset1;
Memo->DataField = "CustNo";
Memo->SetBounds(0, 0, 100, 20);
// 調整文本到右側對象的空白
Memo->HAlign = haRight;
// 顯示報表
frxReport1->ShowReport(true);
讓咱們來解釋一些細節:
全部在報表中使用的數據集都必須添加到數據源列表中,在咱們示例中,是用frxReport1.DataSets.Add(frxDBDataSet1)這一行執行的。不然,報表就不會工做。
數據頁對於插入內部數據集是必要的,例如TfrxADOTable。這些數據集只能放在數據頁。
調用Page.SetDefaults不是必須的,由於在這個案例中頁A4紙張設置和頁邊距都是0毫米。默認值設置10毫米頁邊距,並捕獲打印機頁大小和對齊方式。
在增長欄到頁面的同時,你要確認他們沒有互相重疊在一塊兒。要執行他,頂部和高度的座標是類似的。老是要在設計器中定位相同的位置的。
對象的座標和大小是以像素爲單位的,由於全部對象的left, Top, Width和Height屬性都擁有擴展類型,你可以指出非整形值。下面常量用於轉化像素到釐米和英寸:
fr01cm = 3.77953;
fr1cm = 37.7953;
fr01in = 9.6;
fr1in = 96;
例如,一個欄的高度等於5毫米以下設定:
Band.Height := fr01cm * 5;
Band.Height := fr1cm * 0.5;
12.代碼中建立對話框
咱們知道,報表能夠包含對話框窗體。下面的例子展現瞭如何建立一個帶有OK按鈕的對話框窗體:
Pascal:
{ for working with dialogue objects the following unit should be used }
uses frxDCtrl;
var
Page: TfrxDialogPage;
Button: TfrxButtonControl;
{ 添加頁 }
Page := TfrxDialogPage.Create(frxReport1);
{ 建立惟一名稱 }
Page.CreateUniqueName;
{ 設置大小 }
Page.Width := 200;
Page.Height := 200;
{ 設定位置 }
Page.Position := poScreenCenter;
{ 添加一個按鈕 }
Button := TfrxButtonControl.Create(Page);
Button.CreateUniqueName;
Button.Caption := 'OK';
Button.ModalResult := mrOk;
Button.SetBounds(60, 140, 75, 25);
{ 顯示報表 }
frxReport1.ShowReport;
C++:
//使用對話框對象工做,會用到下面的單元
#include "frxDCtrl.hpp"
TfrxDialogPage * Page;
TfrxButtonControl * Button;
//添加一頁
Page = new TfrxDialogPage(frxReport1);
//建立惟一名稱
Page->CreateUniqueName();
//設置大小
Page->Width = 200;
Page->Height = 200;
//設定位置
Page->Position = poScreenCenter;
// 添加一個按鈕
Button = new TfrxButtonControl(Page);
Button->CreateUniqueName();
Button->Caption = "OK";
Button->ModalResult = mrOk;
Button->SetBounds(60, 140, 75, 25);
//顯示報表 frxReport1->ShowReport(true);