程式
# 程式
程式是一種用高級語言編寫的程式,它是報表的一部分。報表運行時,程式也會運行。程式可以使用FastReport核心的正常操作無法處理數據;例如,程式可以根據預定義的條件隱藏冗餘數據。程式還可用於控制作為報表一部分的對話表單的屬性。
程式使用程式引擎支援的一種語言(FastScript)編寫。
FastScript引擎支援以下功能:
- 標準語言集:變數,常量,過程,函式(可以巢狀並具有變數,常量,預設參數),所有標準
- 運算子(包括
case
,try
,finally
,except
,with
),型別(整數,分數,邏輯,字元,行,多維陣列,變體),類(包含方法,事件,屬性,索引和預設屬性) - 型別相容性檢查
- 訪問任何報表的對象
但是,FastScript不支援以下內容:
- 這些型別的聲明:記錄,類
- 指針,集合(但'IN'運算子可用於表達式,例如「a'['a'...'c','d']中的a」)
- 短字元型
- 無條件跳躍(
GOTO
)
可以在FastReport設計器中建立程式,該設計器包含段語法突出顯示的程式編輯器。還有一個嵌入式偵錯程式,它具有以下功能:「Step」,「Breakpoint」,「Run to cursor」和「Evaluate」。
# 1. 程式初試
程式的工具位於FastReport設計器的「程式碼」選項卡中。切換到此選項卡時,界面如下所示:
上述標籤的說明如下:
「程式碼」標籤
程式編輯器窗格
用於選擇編寫程式的語言的下拉選單
除錯工具欄
圖示 說明 在除錯模式下運行報表F9 運行到游標F4 追蹤至,執行一行F7 結束程式Ctrl+F2 表達式求值Ctrl+F7 放置斷點F5 觀察面板,輸出除錯資訊。
書籤和斷點顯示區。
此外,這裡可以突出顯示執行程式碼的行。
以下是可以在程式編輯器中使用的快捷鍵列表。
按鍵名稱 | 說明 |
---|---|
游標箭頭按鍵 | 移動游標 |
PageUpPageDown | 轉到上一頁、下一頁 |
Ctrl+PageUp | 轉至文字的開頭 |
Ctrl+PageDown | 轉至文字的末尾 |
Home | 游標移至行首 |
End | 游標移至行尾 |
Enter | 轉至下一行 |
Delete | 刪除游標位置的符號; 刪除所選文字 |
Backspace | 刪除游標左側的符號 |
Ctrl+Y | 刪除目前行 |
Ctrl+Z | 撤銷上次的操作(最多32個事件) |
Shift+游標箭頭按鍵 | 選擇一個文字塊 |
Ctrl+A | 選擇全文 |
Ctrl+U | 將所選塊向左移動兩個符號 |
Ctrl+I | 將所選塊向右移動兩個符號 |
Ctrl+C,Ctrl+Insert | 將所選塊複製至剪下板 |
Ctrl+V,Shift+Insert | 貼上剪下板中的文字 |
Ctrl+X,Shift+Delete | 將所選塊剪下到剪下板 |
Ctrl+Shift+數字按鍵 | 在目前行上設定編號為0~9的書籤 |
Ctrl+編號 | 跳轉至指定編號的書籤 |
Ctrl+F | 搜索一行 |
Ctrl+R | 替換一條線 |
F3 | 從游標位置重複搜索/替換 |
F4 | 設定要運行的程式的斷點(運行到遊標) |
Ctrl+F2 | 重置程式 |
Ctrl+F7 | 變數的預覽值 |
F9 | 運行程式(運行) |
F7 | 執行程式碼行(Step into) |
Ctrl+空格按鍵 | 顯示對象的方法和屬性列表 |
Ctrl+Shift+Delete | 刪除游標右側的單詞 |
Ctrl+Shift+Backspace | 刪除游標左側的單詞 |
# 2. 程式結構
以PascalScipt
結構的程式示例如下。
#language PascalScript // 可選項
program MyProgram; // 可選項
// 「uses」 段落應當在其他段落前
uses 'unit1.pas', 'unit2.pas';
var // 變數章節可放置於程式任意位置
i, j: Integer;
const // 常量章節
pi = 3.14159;
procedure p1; // 程式和功能
var
i: Integer;
procedure p2; // 巢狀程式
begin
end;
begin
end;
begin // 主程式
end.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
稍後我們將看一下用PascalScript
語言編寫的程式示例。建立新報表時,預設情況下會選擇此語言。
# 3. "Hello World"程式
打開設計器,切換到「程式碼」選項卡並編寫以下程式:
begin
ShowMessage('Hello, World!');
end.
2
3
之後運行報表。正如預期的那樣,FastReport會顯示一個段問候語的小對話:
我們來解釋一些細節。我們建立了一個由單個begin..end
塊組成的程式。所以我們的程式結構非常簡單; 它只包含一個主程式(參見上面的「程式結構」部分)。報表運行后立即執行主程式。
在這種情況下,它顯示了問候對話; 該程式在對話結束后立即結束。主程式運行完畢后,正常的報表構建開始。
# 4. 在程式中使用對像
可以從程式訪問任何報表對象。因此,如果存在Page1
頁面和Memo1
對象,則可以在程式中使用它們,並按名稱呼叫它們:
Memo1.Color := clRed
可從程式訪問的報表對像列表顯示在「報表樹」窗格中。程式可以使用哪些對像屬性?答案很簡單:在對像檢查器中可見的所有內容。對像檢查器還顯示底部每個屬性的提示。使用程式時,兩個窗格(報表樹和對像檢查器)都可用。
這是一個簡單的例子。將名為「MyTextObject」幷包含「Test」的文字對像放在報表設計頁面上。然後寫這個程式:
begin
MyTextObject.Color := clRed
end.
2
3
運行報表,看到對象的顏色為紅色。
# 5. 從報表的變數列表中呼叫變數
可以在程式中引用報表變數列表中定義的任何變數(報表-變數...
功能表項)。變數的名稱應該用尖括號括起來:
if <my variable> = 10 then ...
另一種方法是使用Get
函式:
if Get('my variable') = 10 then ...
變數的值僅通過Set
程式更改:
Set('my variable', 10);
值得注意的是,要為變數分配字串值,您必須在值周圍新增引號:
Set('my variable', '''' + 'String' + '''');
系統變數,例如Page#
,應以完全相同的方式引用:
if <Page#> = 1 then ...
# 6. 引用資料庫欄位
與變數一樣,在引用報表中的資料庫欄位時應使用尖括號:
if <Table1."Field1"> = Null then...
或者,Get
函式也可用於訪問數據可欄位(實際上,當計算括在尖括號中的表達式時,FastReport會隱式使用此函式)。
# 7. 在程式中使用聚合函式
聚合函式的一個特性是它們必須在文字對像中使用; 一旦以這種方式使用,它們就可以在程式本身中使用。如果聚合函式僅出現在程式中(不出現在文字對像中),則會產生錯誤訊息。這是因為聚合函式必須連線到特定的段; 一旦這樣連線它將正常工作。
# 8. 在報表中顯示變數的值
可以在程式中本地聲明和使用變數。聲明后,程式變數可以賦值給它。以下是正在使用的程式變數的簡單示例:
var
MyVariable: String;
begin
MyVariable := 'Hello!';
end.
2
3
4
5
變數的值可以顯示在文字對像中,例如,通過在對像中鍵入[MyVariable]
。變數的名稱必須是唯一的。這意味著名稱不得複製任何其他報表對象,標準函式或常量的名稱。如果程式中存在錯誤,則在運行報表時將顯示一條訊息,並且將停止報表建立。
# 9. 事件
到目前為止,我們只檢視了一個主程式的程式,該程式在報表開始運行時執行。在主程式中,可以進行初始設定並初始化變數。但是,這還不足以完全控制報表產生過程。爲了在報表產生上實現儘可能多的控制,每個對象都有幾個事件可以分配處理程式(即程式中的程式)。例如,將處理程式連線到數據段使得能夠過濾記錄,從而可以根據滿足的特定條件隱藏或顯示該段。
讓我們演示報表建立過程以及通過包含一個頁面並具有一個主數據集段的簡單報表觸發的事件,段上有兩個文字對像:
如上所述,在運行報表的最開始呼叫程式的主過程。之後,開始進行報表的建立。首先呼叫Report
對象的OnStartReport
事件。然後,在建立輸出頁面之前,呼叫OnBeforePrint
頁面事件。對於報表模板中的每個設計頁面,都會呼叫此事件一次(不應將設計頁面與報表的輸出頁面混淆!)。在我們的示例中,事件被呼叫一次,因為報表設計只包含一個設計頁面。
然後按以下順序呼叫數據段的事件:
- 段的
OnBeforePrint
事件被觸發。 - 呼叫包含在段中的每個對象的
OnBeforePrint
事件。 - 每個對象都填充了數據(在我們的示例中,包含
FTypeID
與FName
的欄位)。 - 呼叫每個對象的
OnAfterData
事件。 - 諸如在段子上定位物體的動作(如果它們之間有可伸縮的物體),計算段高度並拉伸它(如果它是可拉伸的)被執行。
- 段的
OnAfterCalcHeight
事件被呼叫。 - 如果段在頁面的空白處沒有足夠的空間,則會建立一個新的輸出頁面。
- 段及其所有對象都顯示在輸出頁面上。
- 呼叫每個段中對象的
OnAfterPrint
事件。 - 呼叫段本身的
OnAfterPrint
事件。
只要連線到段的源有數據,段就會繼續列印。在該報表列印停止之後,將呼叫報表頁面的OnAfterPrint
事件,最後呼叫Report
對的OnStopReport
事件。
因此,通過使用不同對象的事件,幾乎可以管理報表建立過程的每個步驟。使用事件的關鍵是對段輸出過程的全面瞭解,這將在接下來的部分中進行討論。大多數動作只能使用段的OnBeforePrint
事件來執行; 對對像所做的任何修改都會立即顯示。但是,如果段是可伸縮的,則在這種情況下無法說明段將在哪個頁面列印,因為段高度的計算是在步驟5中執行的。但是,可以在步驟6中的OnAfterCalcHeight
或步驟9中的OnAfterPrint
事件中完成。請注意,在最後一個事件中,已經輸出了段,因此在此事件中對對象的修改將不會產生任何可見效果。必須清楚地理解輸出段以及各段內對象的順序,並瞭解每個事件的觸發順序。
# 10. 使用OnBeforePrint事件的示例
要演示此事件,請使用7.9節建立的報表示例來進行演示。
在此示例中,選擇主數據集段並切換到對像檢查器中的「事件」選項卡:
要建立OnBeforePrint
事件處理程式,請雙擊事件名稱右側的空白欄位:
這會向程式新增一個空白處理程式,設計器會切換到「程式碼」選項卡。
現在需要的只是在處理程式的主體中鍵入以下程式碼:
if Copy(<B."FTypeID">, 1, 1) = '1' then
MasterData1.Visible := True
else
MasterData1.Visible := False;
2
3
4
運行報表並確保程式正常工作:
我們來解釋幾件事。可以將一個處理程式分配給多個對象的事件, Sender
參數顯示哪個對像已啟動事件。要將現有處理程式分配給事件,請將其直接鍵入對像
檢查器,或從下拉選單中選擇它:
可以輕鬆刪除指向處理程式的鏈接。在對像檢查器中選擇已分配的處理程式,然後按Delete鍵。
# 11. 在群組首段中列印組的和
此方法經常使用並且需要使用程式,因為只有在處理了組中的所有記錄之後才知道組和的值。要在群組首中顯示總和(即在將組輸出到報表之前),使用以下方法:
- 打開
兩遍過程
選項(報表
-選項...
功能表項)。 - 在第一遍中,計算每個組的總和並將它們儲存在一個陣列中。
- 在第二遍中,從陣列中提取值並將其顯示在組標題中。
我們還是以上面使用的Basic_CommonDataType
與Basic_CommonData
為例,在報表管理界面中設定好數據源,進入報表設計界面,按照下圖的方式設定好各段及對象。
打開設計器並將數據源連線到報表。在報表的設定中啟用兩遍過程
(報表
-選項...
功能表項)。在報表表中新增兩個段:「群組首」和「主數據集」。在「群組首」頻段的編輯器中,輸入FTypeID
。FDataName
數據欄位。將數據段連線到B
數據源,然後按以下方式排列一些對像:
爲了顯示總和,我們在設計中使用了箭頭對像(此處項指示為Memo4
)。
- 第一種方式,我們使用
TStringList
類作為儲存和的陣列。程式如下圖所示。
var
List: TStringList;
i: Integer;
procedure frxReport1OnStartReport(Sender: TfrxComponent);
begin
List := TStringList.Create;
end;
procedure frxReport1OnStopReport(Sender: TfrxComponent);
begin
List.Free;
end;
procedure Page1OnBeforePrint(Sender: TfrxComponent);
begin
i := 0;
end;
procedure GroupHeader1OnBeforePrint(Sender: TfrxComponent);
begin
if Engine.FinalPass then
Memo4.Text :='Sum:' + List[i];
end;
procedure GroupFooter1OnBeforePrint(Sender: TfrxComponent);
begin
if not Engine.FinalPass then
List.Add(FloatToStr(SUM(<B."FInterID">,MasterData1)));
Inc(i);
end;
begin
end.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
程式中的過程名稱顯示了我們使用過的事件。 它們是:Report.OnStartReport
,Report.OnStopReport
, Page1.OnBeforePrint
,GroupHeader1.OnBeforePrint
和 GroupFooter1.OnBeforePrint
。前兩個事件分別在報表的開頭和結尾呼叫。要為這兩個事件建立處理程式,請在對像檢查器的下拉選單中選擇報表對象,其屬性將顯示在對像檢查器中。然後切換到對像檢查器的「事件」選項卡並建立處理程式。
為什麼我們不在程式的主程式中建立List
變數?我們在OnStartReport
事件中建立它,因為在報表完成後應該銷燬動態建立的變數。在OnStartReport
事件中建立動態變數並在OnStopReport
事件中銷燬它們是合乎邏輯的。在其他情況下(當程式完成時不需要釋放記憶體時)可以使用程式的主過程來初始化變數。List
變數的建立和銷燬是直截了當的。現在讓我們看看程式是如何工作的。在頁面的開頭,目前組的計數器(變數i
)被重置為零,並且在每個組列印后(在GroupFooter1.OnBeforePrint
事件中)遞增。在計數器之前,計算的總和將新增到此事件中的列表中遞增 。GroupHeader1.OnBeforePrint
事件在第一次傳遞期間不執行任何操作( 如 果 是Engine.FinalPass
條件),但在第二次傳遞期間(當List
填充了值時),從List
中檢索對應于目前組的總和「並輸出到」Memo8「對像以顯示組頭中的總和。在完成的報表中,它顯示如下:
- 第二種方式:我們將使用報表變數的集合作為儲存組和的陣列。請記住,可以通過
Get
和Set
來訪問報表變數。使用這些函式還可以使我們不必顯式建立和銷燬這些變數。程式如下:
procedure GroupHeader1OnBeforePrint(Sender: TfrxComponent);
begin
if Engine.FinalPass then
Memo4.Text := 'Sum:'+ FloatToStr(Get(<B."FTypeID">));
end;
procedure GroupFooter1OnBeforePrint(Sender: TfrxComponent);
begin
Set(<B."FTypeID">,
SUM(<B."FInterID">,MasterData1));
end;
begin
end.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
如您所見,此程式稍微簡單一些。GroupFooter1.OnBeforePrint
處理程式中的程式碼設定具有從客戶端編號派生的名稱的變數的值(或者可以使用明確標識客戶端的任何其他識別符號,例如<B."FTypeID">
)。如果沒有已存在該名稱的變數,則程式會自動建立它;否則,如果確實存在則更新其值,在GroupHeader1.OnBeforePrint
處理程式中,檢索適當變數的值。
# 12. OnAfterData事件
在報表對像填充了與其連線的源的數據后,將觸發此事件。使用此事件可以訪問資料庫欄位值或對像中包含的表達式。此值放在Value
系統變數中,該變數僅在此事件中可用。因此,如果兩個文字對像包含表達式[Table1."Field1"]
和[<Table2."Field1」>+10]
這些表達式的值可以通過引用對象的Value
變數來使用:
if Value > 3000 then
Memo1.Color := clRed
2
這會比寫這樣的東西簡單:
if <Table1."Field1"> > 3000 then
Memo1.Color := clRed
2
使用Value
而不是表達式可以為編寫一個多用途處理程式OnAfterData
事件可以連線到多個對象。如果對像包含多個表達式(例如'[expr1] [expr2]'),則它是傳遞給Value
變數的最後一個表達式的值。
OnAfterData
事件非常適合計算對象的高度和寬度,比如文字對象。也就是說,如果程式中需要包含表達式的拉伸文字對象的確切高度,則可以在OnAfterData
事件中使用此程式碼:
var
MemoHeight: Extended;
begin
MemoHeight := TfrxMemoView(Sender).CalcHeight;
end;
2
3
4
5
# 13. 服務對像
除了普通的報表對像(如頁面,段,文字和其他對像)之外,還有一些其他系統對象可以在程式中使用。它們可能有助於報表構建的管理。前一章中使用的Engine
對象就是這樣一個對象,所有這些對象都列在這裡:
Report
:報表對象。Engine
:報表引擎的鏈接。Outline
:預覽報表中報表樹元素的鏈接。
讓我們看一下這些對象。
# 13.1. Report對像
此對像表示目前報表的鏈接。在「報表樹」視窗中選擇「報表」元素時,可以看到此對象的屬性。
# 13.1.1. Calc
function Calc(const Expr: String): Variant;
返回Expr
的值,這是一個表達式,例如,Report.Calc('1 + 2')
返回「3」,任何有效的FastReport表達式都可以在參數中傳遞。
# 13.1.2. GetDataSet
function GetDataSet(const Alias: String): TfrxDataSet;
返回具有指定名稱的數據集,數據集必須出現在報表的數據集列表中(報表-數據...
對話方塊)。
# 13.2. Engine對像
這是最有用和最有趣的對象,它代表了引擎的鏈接(FastReport的核心,它管理報表構建)。通過使用引擎的屬性和方法,可以建立不同尋常的報表設計佈局。
- 屬性
屬性 | 型別 | 描述 |
---|---|---|
CurColum | integer | 多列報表中目前列的索引可以將值分配給此屬性 |
CurX | Extended | X軸上的當前列印位置,可以為此屬性分配值 |
CurY | Extended | Y軸上的當前列印位置,可以為此屬性分配值 |
DoublePass | Boolean | 如果報表是類似於Report.EngineOptions.DoublePass的兩遍,則等於「True」。 |
FinalPass | Boolean | 在兩遍報表的最後一次傳遞中等於「真」 |
PaperHeight | Extended | 可列印區域的高度,以畫素為單位 |
PaperWidth | Extended | 可列印區域的寬度,以畫素為單位 |
StartDate | TDateTime | 報表運行的時間,與<Date>相同 |
StartTime | TDateTime | 報表運行的時間,與<Time>系統變數相同 |
TotalPages | Integer | 報表中的頁數,與<TotalPages>系統變數相同 |
SecondScriptcall | Boolean | flag返回事件的'repeat-call'狀態(在某些情況下,可以在分組期間重複呼叫事件),如果為True則程式已被呼叫 |
- 方法
procedure AddAnchor(const Text: String);
將文字新增到錨點列表中。
procedure NewColumn;
在最後一列自動分頁后,在多列報表中建立一個新列插入。
procedure ShowBand(Band: TfrxBand);
顯示具有指定名稱的段,顯示段后,CurY
位置自動遞增。
function FreeSpace: Extended;
返回頁面上剩餘的空白高度(以畫素為單位)。
function GetAnchorPage(const Text: String): Integer;
返回已放置指定錨點的頁碼。
# 13.3. Outline對像
此對像表示預覽報表中的「報表樹」控制元件元素。
「大綱」顯示完成報表的樹狀結構。單擊任何樹節點時,預覽窗格將跳轉到顯示此節點的頁面。要顯示「大綱」,它應該是通過單擊預覽視窗工具欄中的按鈕或將Report.PreviewOptions.OutlineVisible
屬性設定為True
來啟用 。 也可以在那裡設定Outline
的寬度(以畫素為單位):Report.PreviewOptions.OutlineWidth
。
- 方法
procedure AddItem(const Text: String);
在目前樹位置新增具有文字名稱的元素,頁面上的當前報表頁面和位置被鏈接對元素。
procedure LevelRoot;
將樹中的當前位置移動到根級別。
procedure LevelUp;
將樹中的當前位置向上移動一級。
# 14. 使用Engine對像
「Engine」對像代表報表的引擎,它管理報表的構建。可以使用引擎的屬性和方法來管理在頁面上排列數據段的過程。首先是一些理論。
下圖顯示了報表頁面的各個維度。
頁面的物理尺寸是PaperWidth
和PaperHeight
屬性,在選擇頁面時在對像檢查器中可見。A4頁面的尺寸為210 x 297mm。
PageWidth
和PageHeight
是可列印區域的尺寸,通常小於頁面的物理尺寸。可列印區域的大小取決於報表頁面屬性LeftMargin
,TopMargin
,RightMargin
和BottomMargin
。可列印區域的大小(以畫素為單位)由Engine.PageWidth
和Engine.PageHeight
函式返回。
最後,FreeSpace
是頁面上可用空間的高度。如果有一個「頁尾」段在頁面上,計算FreeSpace
時會考慮其高度。Engine.FreeSpace
函式以畫素為單位返回此高度。請注意,在顯示下一個段后,頁面上的可用空間會減少,這在計算FreeSpace
時會被考慮在內。
報表頁面是如何構建的?只要有足夠的可用空間,報表引擎核心就會在頁面上顯示段。當沒有剩餘可用空間時,列印「頁尾」段(如果需要)並建立一個新的空白頁。如上所述,在顯示下一個段后,可用空間的高度減小。此外,顯示下一個段從目前位置開始,該位置由X軸和Y軸上的座標定義。目前位置分別由Engine.CurX
和Engine.CurY
返回。列印完下一個段后,CurY
自動增加列印段的高度。建立新頁面后,CurY
等於「0」。列印多列報表時,CurX
會更改。
Engine.CurX
和Engine.CurY
不僅可讀還可寫。這意味著可以通過遞增或遞減這些值來移動數據段。
例如,在如下的報表中:
它顯示的報表格式如下:
通過編寫程式實現。
procedure MasterData1OnBeforePrint(Sender: TfrxComponent);
begin
Engine.CurX := Engine.CurX + 5;
end;
begin
end.
2
3
4
5
6
7
8
更改CurY
可以使段重疊,例如:
通過編寫程式實現。
procedure MasterData1OnBeforePrint(Sender: TfrxComponent);
begin
Engine.CurY := Engine.CurY - 15;
end;
begin
end.
2
3
4
5
6
7
8
Engine.NewPage
方法在報表中的任何所需位置插入分頁符,然後從新輸出頁面的頂部繼續列印。可以在列印第二條記錄后插入一個break:
procedure MasterData1OnAfterPrint(Sender: TfrxComponent);
begin
if <Line> = 2 Then
Engine.NewPage;
end;
2
3
4
5
請注意,我們使用了OnAfterPrint
事件(也就是說,在列印段之後)。另請注意,「Line」系統變數返回記錄的序號。
Engine.NewColumn
方法在多列報表中插入分欄符。如果頁面上沒有剩餘的空閑列,則會建立一個新頁面。
# 15. 錨(Anchor)
Anchor
是超鏈接系統中的一個元素,它可以通過單擊(在預覽視窗中)跳轉到連線到已完成報表對象的任何元素。
可以通過Engine.AddAnchor
方法設定錨點。Anchor
在報表頁面中具有名稱和位置。要跳轉到具有指定名稱的錨點,請在任何報表對象的URL屬性中鍵入#錨點的名稱
或者#[錨點的名稱]
。
在第二種情況下,FastReport會替換表達式的值。
單擊該對像將執行跳轉到新增錨點的報表部分。在構建內容表時使用錨點,例如使用指向相應章節的鏈接。讓我們在下面的例子中說明這一點。首先,我們需要熟悉的「客戶」表。
我們的報表將是一個多頁面(有兩個設計頁面)。我們將內容表放在第一頁上,將另外一個列表放在第二頁上。單擊任何內容行將執行跳轉到相應的報表元素。第一個設計頁面:
將以下文字放在數據段中包含的文字對象的URL屬性中。
#[B."FName"]
並將字型屬性設定為藍色和段下劃線,以模擬超鏈接的外觀。
第二個設計頁面:
要新增錨點,請在程式中建立MasterData2.OnBeforePrint
事件處理程式:
procedure MasterData2OnBeforePrint(Sender: TfrxComponent);
begin
Engine.AddAnchor(<B."FName">);
end;
2
3
4
這就是所需要的。預覽報表並確保「超鏈接」有效。
最後要提到的是Engine.GetAnchorPage
函式。此函式返回新增了相應錨點的頁面編號,在建立「內容」表時非常有用。報表必須啟用兩遍過程(報表-選項...
)的,否則不能使用此功能。
# 16. 使用Outline對像
如前所述,Outline
對像表示可以在預覽視窗中顯示的報表樹。單擊樹中的元素將跳轉到包含相應元素的報表輸出頁面。沒有必要使用程式來處理「大綱」,因為一些段可以自動建立樹。讓我們看兩個例子,展示如何在段和程式的幫助下使用「大綱」。
幾乎所有段都具有OutlineText
屬性,以包含自動建立樹的文字表達式。在建立報表時評估表達式,並在列印段時將其值新增到樹中。因此,樹中元素的層次結構類似於報表中的段的層次結構,
這意味著樹將具有與報表中的主要和從屬段相對應的主要和從屬元素(例如,報表具有兩個級別的數據或有組)。我們將使用示例來顯示在具有組的報表中顯示大綱。
將GroupHeader1.OutlineText
的屬性的值設定為<B."FDataName">
。要在預覽視窗打開后立即顯示樹,請設定報表(報告)對象的PreviewOptions.OutlineVisible
屬性為True
。在預覽報表時,您將看到以下內容:
單擊樹中的任何元素將跳轉到報表中的相應頁面,視窗頂部將顯示所選元素。
讓我們將第二級新增到報表樹中。只需將MasterData
段的OutlineText
屬性設定為<B."FName">
,樹將更改為:
很明顯,導航到訂單號是可能的,並且樹中元素的層次結構類似於報表中的元素。
現在我們將建立一個類似的樹,但使用程式而不是OutlineText
屬性。在報表中清除兩個段的OutlineText
屬性並建立兩個事件處理程式 :GroupHeader1.OnBeforePrint
和MasterData1.OnBeforePrint
:
procedure GroupHeader1OnBeforePrint(Sender: TfrxComponent);
begin
Outline.LevelRoot;
Outline.AddItem(<B."FDataName">);
end;
procedure MasterData1OnBeforePrint(Sender: TfrxComponent);
begin
Outline.AddItem(<B."FName">);
Outline.LevelUp;
end;
begin
end.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
預覽報表以確保它的工作方式與之前自動建立樹的方式相同。讓我們看看程式是如何建立樹的。
Outline.AddItem
方法將子節點新增到目前樹節點,然後使子節點成為目前節點。因此,如果連續多次呼叫AddItem
,它將建立此處顯示的梯形圖:
Item1
Item2
Item3
...
2
3
4
LevelUp
和LevelRoot
設定大綱方法用於控制哪個元素是目前元素。第一種方法將游標移動到位於一級的元素。所以這個程式:
Outline.AddItem('Item1');
Outline.AddItem('Item2');
Outline.AddItem('Item3');
Outline.LevelUp;
Outline.AddItem('Item4');
2
3
4
5
構造成為這樣的樹:
Item1
Item2
Item3
Item4
2
3
4
這表明Item4
是Item2
元素的子元素。另一方面,LevelRoot
方法將游標向上移動到樹的根。例如,程式:
Outline.AddItem('Item1');
Outline.AddItem('Item2');
Outline.AddItem('Item3');
Outline.LevelRoot;
Outline.AddItem('Item4');
2
3
4
5
構造這個樹:
Item1
Item2
Item3
Item4
2
3
4
瞭解這一點很清楚報表是如何運作的。在輸出每個組標題之前,樹的根成為目前元素。之後,輸出明細列表,每個明細標被新增為分類的子元素。確保所有明細都位於正確的分類上。
如果沒有顯示為梯形圖,則在每次新增后呼叫Outline.LevelUp
方法,將游標移回上一級別。
# 17. OnManualBuild頁面事件
報表引擎核心通常負責報表構建。它按特定順序顯示報表段,這是數據所需的次數,從而建立完整的報表。有時需要以非標準形式顯示報表引擎核心無法完成的報表。在這種情況下,可以使用報表設計頁面的OnManualBuild
事件手動構建報表。如果定義了此事件的處理程式,則報表引擎核心在需要數據輸出時將控制權轉移給它。同時報表引擎核心自動處理位於頁面上的那些段的顯示,例如「報表標題」,「頁面標題」,「列標題」,「報表頁尾」,「頁尾」,「列頁尾「和」背景「。核心還處理新頁面和列的建。OnManualBuild
事件處理程式的目的是以使用者控制的順序顯示數據段,它們的標題和頁尾。
也就是說,OnManualBuild
處理程式的本質是向報表引擎核心發出命令,以便在特定時間顯示段。核心完成剩下的工作:只要目前沒有空閑空間,處理附加到事件的程式等,它就會建立新頁面。
以報表建立的例子繼續執行,在頁面中插入第二個主數據段,不設定其連線的數據集。在這種情況下,直接執行列印是無法輸出內容的。故在此處使用手動建立。
處理程式將以交替順序顯示這些段(每個段六次)。顯示六個段后,將插入一個小間隙。
procedure Page1OnManualBuild(Sender: TfrxComponent);
var
i: Integer;
begin
for i := 1 to 6 do
begin
Engine.ShowBand(MasterData1);
Engine.ShowBand(MasterData2);
if i = 3 then
Engine.CurY := Engine.CurY + 10;
end;
End;
2
3
4
5
6
7
8
9
10
11
12
# 18. 在程式中建立對像
可以使用程式將新對像新增到報表中。讓我們用一個簡單的例子來說明這是如何完成的。建立一個空白報表,並在程式的主過程中輸入以下程式碼:
var
Band: TfrxReportTitle;
Memo: TfrxMemoView;
begin
Band := TfrxReportTitle.Create(Page1);
Band.Height := 20;
Memo := TfrxMemoView.Create(Band);
Memo.SetBounds(10, 0, 200, 20);
Memo.Text := 'This memo is created in code';
end.
2
3
4
5
6
7
8
9
10
請注意,我們沒有銷燬我們在此示例中建立的FastReport對象。這不是必需的,因為報表完成後,應用程式會自動銷燬FastReport對象。另請注意,當我們在程式中建立標準對像(例如TStringList
)時,我們還必須在程式中銷燬它們,因為這不會由應用程式自動完成。