FastReport報表設計

FastReport報表設計

原文地址:FastReport報表設計做者:小黑html

目錄數據庫

5.1 前言編程

5.2 基本概念及操做設計模式

5.3 報表設計與範例數據結構

5.4 經常使用功能及函數編輯器

5.5 報表設計經常使用技巧ide

5.1 前言函數

汽車業務管理系統(VBMS)使用FastReport3.0報表系統設計報表。
    本文主要描述使用FastReport設計報表的基本概念、使用方法、設計技巧和範例,不是FastReport的用戶手冊所以並不針對每一個細節進行闡述。立足於創建設計報表的概念和實用技巧範例的講解,面對的是具備必定計算機操做水平的用戶。
在VBMS中使用FastReport設計報表應該掌握如下知識:
一、 熟悉SQL語言,爲設計報表準備數據源。
二、 掌握VBMS的數據結構,可參考相關資料。
三、 掌握FastReport報表的設計使用方法。工具


體系結構
    學習報表設計前應當首先弄清楚VBMS系統與FastReport報表設計之間的關係。報表設計的目的是將VBMS數據庫(Firebird1.5)中的數據按照須要的視圖方式顯示、統計出來,而且能夠打印、導出。
    VBMS數據庫與VBMS管理系統以及FastReport報表設計之間的關係是:
    Firebird數據庫系統是報表的數據源,它存儲着客戶的業務數據。但該數據的存儲方式並不必定是客戶但願直接看到的。
    VBMS管理系統是中間層,它負責鏈接Firebird數據庫和FastReport報表系統,將數據庫信息(例如數據庫的位置)傳入到報表系統中供設計報表時使用。
    FastReport報表系統是報表設計的主體,它負責接收或建立數據源,經過設計報表完成須要的功能。所以在VBMS管理系統的打印模塊中存在兩種數據源:一種是VBMS系統數據源,即在各模塊中將設計好的數據源傳入到打印模塊中。優勢是無須用戶干預使用方便,缺點是不夠靈活,更改數據源須要升級程序。例如各種單據的打印報表採用的就是系統數據源。另外一種是自行設計數據源,功能強大但對用戶的要求較高。例如報表中心中的各種報表。學習


設計步驟
完成一張報表的設計主要包括如下幾個步驟:
一、 肯定報表的需求,查閱VBMS關於數據庫結構的文檔,確認該需求的全部內容在VBMS中均有數據字段記錄(即VBMS必須記錄了相關數據,不然報表設計無從談起)。
二、 根據報表的需求,肯定報表應該顯示的模式。例如:是簡單報表、主從報表或是分組報表等等。由於這涉及的自定義數據源時SQL語言的構成方式。
三、 利用數據庫工具(例如:IBExpert),使用SQL語言嘗試獲取報表但願的數據集。這裏有可能不能經過SQL語言一步到位獲取到但願的結果,但你仍可能經過FastReport報表系統對數據集進行二次加工。
四、 在FastReport報表中自定義數據源(經過上步獲取的SQL語句),利用報表系統中提供的各類控件構造出但願的報表格式。
五、 對於設計好的報表進行測試。

5.2 基本概念及操做

本節主要講述FastReport報表系統的基本概念、基本操做方法、基本控件使用等內容。

基本概念

最主要的概念是FastReport報表的組成方式和控件主要用途,它通常包括如下方面: 
*頁面(Page) --- 默認爲Page1
    與咱們現實中使用的紙張類似。但它不只僅指的是一張紙,而是用於咱們設計報表的容器。打印出來能夠是一張紙也能夠是多張。頁面(Page)能夠有多個(你能夠新增頁面New Page),便可以有多個報表容器。利用這一點,你能夠設計出複合報表(Composite Report)。 
利用頁面設置能夠定義大小、方向、邊界、打印方式、分欄等參數。這裏再也不詳述,只特別強調分欄的做用。你能夠將頁面分紅多欄,這樣打印時數據將按照從上到下,再從左往右的方式顯示。這就是咱們一般說的分欄報表(Splite Report)。 
*區域(Band)
    FastReport將整個頁面劃分紅若干個區域。而每一個區域有着各自不一樣的功能,這些功能由FastReport自動加載。一個頁面中能夠沒有區域,也能夠只有其中的某些區域,這根據報表的需求而定。放置在頁面中的區域有範圍,落入區域範圍內的控件(例如:TextObject)才具備區域的功能。 
重要的區域包括: 
#報表擡頭(ReportTitle)

僅在第一頁顯示在紙張的上部。通常用於打印報表的標題等信息。

#報表合計(ReprotSummary)
僅顯示在全部數據的最後末尾。通常用於打印統計信息等。 
#頁首(PageHeader)
顯示在每頁的最上部。經過設置你可讓它置於報表擡頭之上或者之下。通常用於打印頁眉信息等。 
#頁腳(PageFooter)
顯示在每頁的最底部。通常用於打印頁序等信息。 
#主數據(MasterData)
用於顯示數據源的數據,是最重要的區域。在該區域中能夠定義鏈接哪個數據源,那麼該數據源的數據將會按順序依次將記錄打印出。 
數據區域還有明細數據(DetailData)等,一共支持6階數據。利用明細數據能夠設計出主從報表、主-細-子細報表等。例如:各種單據的打印報表就是由單據頭(主數據)和單據體(明細數據)共同完成的。 
在打印時,明細一級的數據是受上一級主數據的控制,所以須要進行相關設置。 
#頭(Header)
顯示在全部數據源的最上部,僅打印一次。通常用於顯示相關摘要信息。 
#尾(Footer)
顯示在全部數據源的最下部,僅打印一次。通常用於顯示全部數據的合計信息。 
#欄首(ColumnHeader)
顯示在每頁數據源的上部,它在每頁均顯示。所以通常用於打印數據源字段的欄目信息。 
#欄尾(ColumnHeader)
顯示在每頁數據源的下部,它在每頁均顯示。通常可用於統計顯示每頁數據的頁合計信息。 
#羣組首(GroupHeader)
用於顯示分組數據,在每個分組開始顯示。通常可用於顯示分組索引數據。例如:將商品檔案按商品分類分組顯示,在羣組首你能夠顯示商品分類名稱。利用羣組首能夠設計出分組報表,關鍵是數據源必須按分組索引的字段排序才能達到分組的效果。羣組首能夠有多個,便可以嵌套使用。 
另外,能夠設置讓分組索引數據在報表預覽時顯示在左側的樹型列表框(OutLine)中。 
#羣組尾(GroupFooter)
與羣組首一一對應。通常用於顯示分組數據的統計信息。 
#子(Child)
是一個獨立的區域。你能夠設置子區域隸屬於上述區域中的任何一個。在打印時,打印完父區域後,子區域將會跟隨打印。通常可用於打印裝飾線、調整高度或者打印子報表(SubReport)。 
#重疊(overlay)
該區域內包含的內容將從頁的開始位置計算打印,而不受其餘功能區域的影響。通常用於沒法在其餘功能區域打印的內容的顯示。 
*對話框(DialogPage)
你能夠經過設計對話框完成對數據源進行動態控制的目的,這也是設計複雜報表的重要手段。 
對話框主要經過各類輸入數據控件來接受客戶的查詢請求,所以能夠學習幾種主要的控件。 
#標籤(Label Control) --- 用於顯示文字信息。使用Caption屬性修改文字信息。 
#文本編輯框(Edit Control) --- 用於接收用戶錄入的文字信息。使用Text屬性修改文字信息。 
#按鈕(Button Control) --- 通常用於肯定和取消。使用Caption屬性修改文字信息。 
#多選框(CheckBox Control) --- 用於用戶對條件的選擇。使用Checked屬性肯定是否。 
#單選框(RadioButton Control) --- 用於用戶對條件的單一選擇。使用Checked屬性肯定是否。 
#下拉框(ComboBox Control) --- 用於用戶對多個數據列表的選擇。使用Text屬性修改當前文字信息,使用Items屬性填充列表信息。 
#時間框(DateEdit Control) --- 用於用戶對時間的選擇。利用Date屬性改變時間。 

在Code頁中,使用Pacal Script(就是類Pascal)語言進行編程,將大大發揮報表的功能。

  



*文本對象(Text Object)
這是FastReport報表中使用最頻繁的控件。可用它完成以下主要功能:

  1. 顯示通常文字信息 --- 直接錄入便可。
  2. 顯示數據字段信息 --- 通常格式:[數據源."字段名稱"]。
  3. 顯示變量內容 --- 通常格式:[<變量名>]。
  4. 顯示裝飾線等。

文本對象能夠進行文字對齊、格式轉化、文本着色、字體改變、畫邊框線等許多功能,這與MicrosoftWord中的操做有諸多相同特徵。所以這裏再也不一一贅述。

在文本對象中引用數據字段或者變量須要用中括號包含,並且引用變量名時還須要用尖括號包含,這樣系統就知道這是一個變量名稱而不是其餘什麼。

  



*子報表(Subreport Object)
放置子報表後,系統會自動增長一個頁面,你能夠在此頁面上設計須要的報表。系統在打印處理時,先按主報表打印,當碰到子報表時會自動轉入子報表的頁面進行打印處理,完成後繼續執行主報表打印的工做,因此咱們又稱之爲嵌套報表。
設計子報表與主報表基本上相同,惟一的區別是有些功能區域不能在子報表中實現,例如:報表擡頭、羣組。
*交叉報表(DB cross-tab)
又稱動態報表,便可以實現橫向和縱向都不能肯定時的報表。該報表的實現須要數據源按必定規格組織數據方能實現。 
*數據感知控件(FIB Query)
利用該控件進行數據源的設計,能夠完成設計SQL語句、測試結果、字段別名等工做。

在FIBQuery控件的SQL屬性對話框中有一個QueryBuilder工具。利用該工具你能夠查看到目前數據庫中全部的數據表以及數據字段信息。而且能夠在工具中利用嚮導功能(Model)能夠更好的完成SQL語句的編制工做,並能夠測試結果(Result)。不過這裏列出的僅是數據表(Table),還有視圖(View)沒有列出。若是須要使用視圖或存儲過程(Procedure)能夠查閱相關資料,FIBQuery一樣支持視圖和過程。 
在FieldAlias屬性中,你還能夠將全部數據字段名稱修改爲中文名稱。 
在Master屬性中,你能夠定義本數據源隸屬於另外哪個數據源(即受哪個數據源控制)。 
若是你在數據源的SQL語句中定義了變量,那麼在Params屬性中,你能夠設置這些變量的類型和值。

   

FastReport報表系統中還包含了一些其餘控件,這些控件大部分是用於裝飾報表的,比較容易理解,使用起來也比較簡單,這裏也再也不說明了。

基本操做

FastReport中的操做與MicrosoftWord中的操做很是類似,再也不詳述。下面僅對一些經常使用功能及操做技巧進行提示。 
*熱鍵 
Arrow --- 在Object之間移動 
Del --- 刪除一個Object
Enter --- 調出選擇的Object的編輯器 
Shift+Arrow --- 改變Object的尺寸大小 
Ctrl+Arrow --- 移動Object的位置 
Alt+Arrow --- 移動選擇的Object到相鄰的Object的旁邊而且對齊 
*鼠標 
Left button --- 選擇、移動一個Object,對於多選的一組Object,能夠拖動右下角的紅點同時改變所選的Object的尺寸大小 
Right button --- 調出右鍵菜單 
Shift+left button --- 多選Object
Ctrl+left button --- 按住Ctrl鍵不放用鼠標左鍵能夠拖出一個虛線矩形框,釋放鼠標按鈕能夠將該矩形框內全部Object選中,而後使用left button將選中的Object移動到所需位置 
Alt+left button --- 若是針對Text Object使用,將能夠直接編輯內容,無需彈出編輯窗

   

5.3 報表設計與範例

根據報表需求的不一樣,你能夠利用多種報表方式完成報表。下面我將結合VBMS中已經實現的報表範例講述各類報表的設計方法和思路。

簡單報表(Simple list)

*報表格式 
通常由報表擡頭、頁首、頁腳(或者欄首、欄尾,或者頭、尾)、主項數據組成。 
*報表範例 
#商品檔案列表 
步驟以下:

  1. 新建數據源(FIB Components->FIB Query),起名tblProduct。(修改Name屬性)
  2. 獲取所需數據(tblProduct->SQL)。
  3. 依次添加ReportTitle、PageHeader、MastData、PageFooter區域。
  4. 設置MastData區域鏈接的數據源->tblProduct。(雙擊MastData區域)
  5. 在ReportTitle中添加文本對象,錄入報表名稱。
  6. 在PageHeader中添加若干文本對象,錄入字段中文名稱。
  7. 在MastData中添加若干文本對象,並鏈接該文本對象至對應數據字段。(能夠從下拉框中選取)
  8. 在PageFooter中添加文本對象,錄入頁碼。(使用FastReport中的系統變量 [Page])

SQL語句:
SELECT * FROM TB_PRODUCT;

通常報表都是從簡單開始構建,而後逐步細化後得出的。所以能夠利用FastReport報表中的新建報表嚮導功能(菜單->文件->新建…->標準報表嚮導)快速搭建起一個報表的雛形,並且他會自動將各個字段排列整齊,這樣能夠節約一些時間。 
若是但願在報表擡頭打印本公司的名稱以及電話等信息,可使用自定義變量(Custom)中的相關變量,該變量內容爲VBMS在參數設置中定義的本公司資料。 
在向PageHeader中添加中文欄目和向MastData中添加數據字段時,你能夠直接用鼠標從右側的數據列表框中拖拽相應字段到相應的區域中。你能夠將欄目和字段一塊兒創建,固然數據列表框下方的多選框要打勾。 
能夠在PageFooter中添加頁碼(Page)和總頁數(TotalPages)。通常在文本對象中的格式爲:共[TotalPages]頁 第[Page]頁。可是須要聲明的是,必須將報表設置成兩遍報表(Double pass)模式後TotalPages變量才起做用不然爲0。這很好理解,當報表引擎(Engine)執行第一遍時並不知道數據將充滿幾頁紙,只有當第一遍完成後才計算得出,所以須要二遍報表才能打印出總的頁數。所以兩遍報表在FastReport中是一個重要概念,對於某些特殊報表可能會用到。例如:須要將統計的合計值打印在全部明細以前而不是以後。


技巧: 
    前面說過,你能夠利用字段別名修改英文的字段名稱爲中文名稱,這樣對於系統不很熟悉的人也能夠看得懂報表。這裏介紹另外一個方法,使用該方法既能夠達到修改中文名稱的目的,又能夠令報表製做更加快捷。例如仍是上面這張商品檔案列表。咱們能夠直接在SQL語句中加入中文別名。 
SQL語句:(中文別名須要用雙引號包含)
SELECT
PRODUCTNUMBER AS "商品編號",
PRODUCTNAME AS "品名規格",
PRODUCTUNIT AS "單位",
SELLPRICE AS "零售價"
FROM TB_PRODUCT
這樣作的好處,一是報表中的數據字段均爲中文容易理解,二是在執行上面六、7步驟時,你能夠拖拽右側的數據字段同時創建欄目頭和字段,而此時欄目頭中也跟隨着變成了中文,避免了從新修改爲中文的麻煩。固然因爲vbms中的報表數量龐大,所以並未採用這種方法。 

*報表中的變量

FastReport中的變量分爲三種。 
#系統變量 
系統定義的一些與報表打印相關的變量,這裏介紹幾個經常使用的變量。 
Date --- 系統當前日期 
Time --- 系統當前時間 
TotalPages --- 總頁數(必須設置Double pass) 
Page --- 當前頁碼 
Line --- 當前行序號 
Line# --- 也是當前行序號,但區別是在一個新的數據區域(Band)內該變量將從新計數。 
#自定義變量(Custom)
自定義變量是由VBMS系統傳入到報表系統中的。 
#編程(Code)中使用的全局變量 
你能夠在Code頁的起始處定義一些須要的全局變量。 
例如: 
var
S: string;
這裏S就成了一個全局的字符型變量,你能夠對它進行賦值、取值。也能夠在文本對象中引用它,格式爲:[<S>]。 

其實在FastReport報表系統中,全部對象諸如 頁(Page)、區域(Band)、文本對象(TextObject)、對話框控件、數據源字段、系統變量、自定義變量等,你都可以在文本對象中顯示他們的值,只是引用他們的方式不一樣罷了。 
例如:經過文本對象(TextObject)
打印文本編輯框的內容能夠引用Text屬性,格式:[Edit1.Text]。 
打印公司名稱能夠引用自定義變量,格式:[CompanyName]。 
打印數據字段值,格式:[tblProduct."商品編號"]。其實數據字段也能夠當作變量。 
打印自定義的全局變量,格式:[<S>]。這裏S須要用尖括號包含,其實通常狀況下對於變量而言均須要用尖括號包含,只是FastReport對於非自定義的變量(不是在Code中定義的)有了一個預先判斷,容許省略尖括號而已,你加上尖括號也不會出錯。但在編程(Code)中全部變量被引用就必定須要有尖括號。 
特別提醒:在文本對象中打印全部變量都必須用中括號[]將變量包含起來。

 

主從報表(Master Detail)

*報表格式 
通常由報表擡頭、頁首、頁腳(或者欄首、欄尾,或者頭、尾)、主項數據、細項數據組成。 
*報表範例 
#銷售單據列表 
步驟以下:

  1. 新建2個數據源(FIB Components->FIB Query),起名tblOrder、tblItem。
  2. 獲取所需數據(tblOrder->SQL、tblItem->SQL)。
  3. 依次添加ReportTitle、PageHeader、MastData、Header、DetailData、Footer、PageFooter區域。
  4. 設置MastData區域鏈接的數據源->tblOrder,DetailData->tblItem。
  5. 在ReportTitle中添加文本對象,錄入報表名稱。
  6. 在PageHeader中添加若干文本對象,錄入字段中文名稱(單據頭)。
  7. 在MastData中添加若干文本對象,並鏈接該文本對象至對應數據字段。
  8. 在Header中添加若干文本對象,錄入字段中文名稱(單據體)。
  9. 在DetailData中添加若干文本對象,並鏈接該文本對象至對應數據字段。
  10. 在Footer中添加System Text對象,用於顯示金額合計。
  11. 在PageFooter中添加文本對象,錄入頁碼。(使用FastReport中的系統變量 [Page])

SQL語句:
#tblOrder
SELECT * FROM TB_ORDER WHERE ORDERTYPE='銷售出庫';
#tblItem
SELECT * FROM TB_ITEM WHERE ORDERID=:ORDERID;

主從報表的關鍵是須要關聯主數據源和從數據源。通常狀況須要經過如下方式關聯: 
#從數據源的SQL語句中通常須要有用於關聯的關鍵字段(外鍵)。例如上例中的ORDERID=:ORDERID。前面的ORDERID爲tblItem的外鍵,即明細數據經過ORDERID與某一條主項數據關聯。而:ORDERID爲一個變量(在SQL語句中使用<冒號+變量名稱>表示一個變量)。而通常這個變量的名稱(ORDERID)的定義與tblOrder(主項數據)中的主鍵的名稱相同,即變量名稱定義爲:ORDERID而不是:O或者其餘。這樣作的目的是系統能夠自動進行匹配。 
#定義tblItem的屬性Master等於tblOrder。這樣明細數據就被主項數據所控制了。 
#定義tblItem的屬性Params中的變量ORDERID的類型爲整型(Integer),值爲變量<tblOrder."ORDERID">。當你打開Params時,ORDERID變量已經默認存在了,這是由於你在tblItem的SQL中定義了這個變量的緣故。未來你可能會在一個數據源中定義多個變量,操做方法是相同的。設置值等於<tblOrder."ORDERID">表示當須要獲取:ORDERID變量的值時,將會從主項數據中獲取。這樣當主項數據的ORDERID發生變化時,明細數據也隨之變化。這個值的選取你能夠經過按鈕(fx)更方便的獲取。


*SystemText對象 
該對象與文本對象(TextObject)基本上相同,區別在於使用SystemText能夠更加方便的對一個數據集進行求和或者其餘的操做。雖然你也能夠直接在文本對象(TextObject)中使用求和函數對數據集進行求和,不過使用SystemText能夠令你不須要記憶許多函數,由於它幫你作了,基本上它就是一個構建函數嚮導的工具。固然若是你對FastReport中的函數比較熟悉,徹底能夠沒必要使用SystemText而直接使用TextObject更加快捷。 
SystemText的用法以下: 
#放置一個SystemText對象到Footer中,用於對銷售明細數據中的金額進行求和。 
#系統會當即彈出一個對話嚮導框。你能夠選擇三種方式中的一種:系統變量、求和、文本。這裏主要將求和,另外兩種方式很好理解(系統變量用於打印時間、頁碼等,而文本與TextObject中同樣)。 
#選擇求和(Ageregate value)。選擇函數->SUM(其餘爲最大值、最小值、平均值、數量),數據Band->DetailData1(設置你須要求和的數據區域,這裏固然是明細數據),數據庫->tblItem(上一步選擇好後,系統自動會設定爲該數據區域鏈接的數據源),下一步你能夠從數據字段中選擇須要求和的字段(例如:TotalTaxSum)。或者在表達式中構造更爲複雜的求和內容(這裏暫不講述)。 
#按肯定後,SystemText中的文本自動生成爲[SUM(<tblDetail."TOTALTAXSUM">,MasterData2)]。當你再次雙擊該SystemText,你會發現對話框中系統默認爲文本,而文本內容就是上面的內容。因而可知,SystemText其實就是TextObject加上函數嚮導。 

你們若是仔細會發如今求和嚮導對話框中有兩個選項,一個是"計算不可見Band的數據",一個是"執行總數"。這兩個選項是作什麼用的呢? 
"計算不可見Band的數據":有時候在報表中咱們會對數據源作一些設置,例如知足某些條件的數據不顯示出來(例如:維修結算單打印中僅打印自付內容)。那麼這個選項可使得系統在求和時只計算可見的數據。 
"執行總數":咱們知道,對於主從報表中明細的求和,例如銷售明細中商品的銷售金額。該金額是表示本單據的合計。當單據變化時,這個合計值也隨之變化。而有些時候,咱們可能不但願這樣,而是但願有一個值一直在累加合計金額,而不是隨着單據的變化這個合計值被重置。那麼這個選項可使得系統一直累計合計值直到最後一張單據。 
上面兩個選項對於不少報表是頗有用處的。


*SUM函數 
完整定義:SUM(Expr,Band,Flags);
Expr:你須要求和的變量或者更加複雜的函數,例如:<tblItem."TOTALTAXSUM">。 
Band:你須要求和的數據區域名稱,例如:DetailData1。 
Flags:默認爲0,能夠省略。 
1 --- 計算不可見Band數據 
2 --- 執行總數 
3 --- 1 而且2(計算不可見Band數據 而且 執行總數)

分組報表(Group)

*報表格式 
通常由報表擡頭、羣組首、主項數據、羣組尾組成。 
*報表範例 
#商品檔案報表(按商品分類分組)
步驟以下:

  1. 新建1個數據源(FIB Components->FIB Query),起名tblProduct。
  2. 獲取所需數據(tblProduct->SQL)。
  3. 依次添加ReportTitle、GroupHeader、MastData、GroupFooter區域。
  4. 設置MastData區域鏈接的數據源->tblProduct。
  5. 在ReportTitle中添加文本對象,錄入報表名稱。
  6. 雙擊GroupHeader,設置分組條件,選擇數據字段tblProduct->PRODUCTSORT。
  7. 在MastData中添加若干文本對象,並鏈接該文本對象至對應數據字段。
  8. 在GroupHeader中添加若干文本對象,錄入字段中文名稱。
  9. 在GoupHeader中添加一個文本對象,錄入<tblProduct."PRODUCTSORT">。用於顯示商品分類名稱。
  10. 在GroupFooter中添加System Text對象,用於顯示合計數。
  11. 在PageFooter中添加文本對象,錄入頁碼。(使用FastReport中的系統變量 [Page])

SQL語句:
SELECT * FROM TB_PRODUCT ORDER BY PRODUCTSORT;

所謂分組報表,就是按某一個字段進行分組顯示,該字段具備相同的值的數據記錄將被歸類顯示在一塊兒。例如:上例中將商品檔案按照商品分類歸類顯示。 
要達到分組的目的,其中一個關鍵是該數據集必須按分組條件排序。即SQL語句中必定要有ORDER BY這樣的排序語句,而排序字段就是分組的字段。 
分組是能夠多級的,也就是能夠嵌套分組。例如:商品檔案定義時可能用商品分類表示大類,商品類型表示小類。分組顯示時但願按大類包含小類這樣嵌套方式顯示。那你可讓數據集按ORDER BY PRODUCTSORT,PRODUCTSTYLE這樣來排序。排序時,排在前面的字段首先被排序,在相同的條件下,對排在後面的字段再進行排序。一樣的這種狀況下,你須要增長兩個羣組首尾,讓他們嵌套排列。居於外層的設置分組條件爲商品分類,居於內層的設爲商品類型。


*分組條件設置中的選項 
在你設置GroupHeader的分組條件時,有如下幾個選項,他們的用途以下: 
#保持與羣組在一塊兒 --- 這個選項表示,FastReport報表系統老是試圖將一個羣組的內容打印在一張紙上而不作分割。例如:有一個羣組的內容比較多,而這個羣組的開始打印位置居於紙的中部,所以本頁將沒法將所有該羣組的內容顯示完畢。那麼FastReport將把這個羣組打印在新的一頁上,這樣上頁紙的底部將會留出空白。固然若是這個羣組在新的一頁仍然沒法顯示完畢,那FastReport就接着顯示,再也不作其餘處理了。 
#換頁 --- 這個選項與上面這個選項基本概念相同,只是他老是將新的分組內容打印在新的一頁上,而無論這個分組的內容有多少。固然這樣紙張的空白也更多更浪費。但這種方式對於某些客戶來講仍然多是須要的。 
#顯示在大綱 --- 若是選擇本選項,那麼在你預覽報表時,你可使用綱要功能(有一個綱要按鈕)。他能夠將分組的名稱顯示在左邊的樹型框中,這樣你能夠更加方便的定位到相應的分組。 

若是你想預覽時老是顯示綱要(不須要老是按綱要按鈕)。你能夠選擇左側Page1中的Report對象,在屬性PreviewOptions->OutlineVisibe設置爲True。



*Reprint On NewPage
    若是你選擇GroupHeader區域,而後點擊鼠標右鍵彈出菜單(Context PopupMenu)。你會發現有一個選項Reprint On NewPage,這個在其餘區域的右鍵菜單中是沒有的。他是起什麼做用呢? 
    咱們知道,通常分組報表設計時,老是將分組條件和中文字段名稱顯示在羣組首。這樣打印時,碰到一個新的分組,FastReport先是打印羣組首中的內容,例如:商品分類的名稱等。而後再打印該分組的數據。但若是數據較多時不能在一頁中顯示,那麼剩餘內容將打印在後面的一頁中。這帶來一個問題就是,若是獨立看待後面一頁紙,上面顯示的數據咱們不知道是屬於哪個商品分類的(分組),必須返回去查看上一頁中的羣組首才知道。而使用Reprint On NewPage,則FastReport將在新的一頁中將羣組首中的內容再打印一遍(Reprint)。這樣你就能夠清楚知道本組數據的歸屬了。固然這樣的話,羣組首中的內容將可能會被打印超過一遍,這取決於數據的多少。

分欄報表

待續...

多列報表

待續...

子報表

待續...

交叉報表

待續...

   

5.4 經常使用功能及函數

經常使用功能

*報表設置 
何時須要兩遍報表(Double pass)? 
應用1 用於顯示總的頁數(TotalPages),例如:頁腳顯示 第1頁/共20頁。系統第一遍掃描報表時計算出TotalPages,而後第二遍實際生成報表。若是不使用Double pass,則TotalPages返回0。 
應用2 用於將明細項的合計值打印在報表起始位置,而不是在末尾。這須要在第一遍掃描報表時計算出而後在第二遍生成報表時顯示在起始位置。 
密碼 --- 用於將報表加密,這樣在設計或者顯示報表時須要輸入密碼。 
*頁面設置 
分欄 --- 能夠將報表在一張紙上分紅若干列來打印,比較利於節省紙張。這與在主項數據的Band中設置多個列(Column)不一樣,分欄打印順序是從上往下,而後從左往右。多列打印順序是從左往右,再從上往下。

函數

ListValue --- 根據SQL語句自動填充一個列表的值; 
procedure ListValue(ASQL: string;AList: TStrings);
begin
tblList.Close;
tblList.SQL.Text := ASQL;
tblList.Open;
tblList.First;
while not tblList.Eof do
begin
AList.Add(tblList.Fields[0].AsString);
tblList.Next;
end;
end;

   

ShowLoginSector --- 登錄分公司列表自動選擇,若是不是管理部門則不容許選擇; 
procedure ShowLoginSector(L: TfrxComboBoxControl);
var
S: string;
begin
S := VarToStr(Get('LoginSector'));
if S = '' then S := '管理部門';
L.ItemIndex := L.Items.IndexOf(S);
L.Enabled := S = '管理部門';
end;

   

   

5.5 報表設計經常使用技巧

A 爲系統數據源增長自定義數據源,達到擴展數據的目的

    在VBMS中的報表中心咱們能夠本身設計數據源而後設計本身須要的報表。 其實,咱們在其餘的模塊中同樣能夠本身設計數據源(原來覺得不能夠)。 
設計方法與報表中心中是同樣的。 
下面我舉一個例子: 
在客戶檔案模塊中的打印報表中,增長每一個客戶的對應的車輛資料的顯示。 
原報表中已經有了一個系統傳入的數據源dsCustomer。 
1.  FIB->FIB Query,新增一個數據源 dsVehicle。 
SQL語句爲: 
SELECT * FROM TB_VEHICLE WHERE CLIENTID=:CLIENTID; 
其中:CLIENTID爲變量,是隨着dsCustomer的變化而變化的。 
(注意:若是你但願這個變量由主數據源來控制,則該變量的命名必須與主數據源中的字段名稱一致。) 
2. 設置dsVehicle的以下屬性: 
Master -> dsCustomer;(設置主數據源) 
Params -> CLIENTID,數據類型 Integer,值 <dsCustomer."CLIENTID">
(設置參數:設置值時能夠選擇按鈕fx來選擇) 
3. 插入一個Band(明細數據)。 
設置鏈接數據庫爲dsVehicle。而後放入相關的字段(Text Object)。 
4. 鼠標右鍵設置MastData1的 Print if Detail Empty。目的是若是該客戶沒有車輛依然須要打印出來。

總結: 
    如今,咱們既能夠在報表中心,也能夠在任何位置的打印報表中設計本身的數據源,而且能夠將本身的數據源與vbms系統傳入的數據源進行關聯。這樣的應用可使報表設計更加靈活、更增強大。

   

B 爲報表增長分組顯示功能 
在vbms系統的設計報表功能中,有一個羣組頭、羣組尾的功能。 
    若是將羣組頭和羣組尾分別置於主項數據的上面和下面,則能夠對該主項數據進行分組統計功能,設置羣組頭時,系統會詢問對哪個字段進行分組。而後你能夠在該羣組頭上放置一個該字段的TextObject來顯示分組內容,在羣組尾放置一個用於求和的SystemText。這樣就能夠按照該字段來分組統計了。 
注意:要讓相同組別的記錄顯示在一塊兒,必須使數據源按該字段排序。所以,在通常報表中,若是你但願按照某個字段來分組統計,必須在打印所在的窗體上點擊數據列表的該字段項(即排序,能夠正排和逆排),而後再進入打印對話框來打印;若是是在報表中心中設計的報表,則在SQL中必須加上ORDER BY語句來排序。 
另外,在羣組頭的屬性中有一個OutLine,若是等於True。則能夠在預覽中使用列表導航。

   

C 將對話框(DialogForm)中的信息顯示在報表中。 
例如:對話框中錄入開始日期和結束日期,你但願將該時間範圍顯示在報表頭上。 
方法是,在報表頭上加一個Text Object,而後錄入[edtBD.Text];edtBD就是開始日期編輯框的Name,記住要用中括號括起來。其餘的類推。 
*在對話框中的下拉框中顯示一個列表。 
例如,在對話框中你可能須要用一個下拉框讓用戶選擇某一個供應商,下拉框中存儲了全部供應商。 
方法是,首先建一個數據源(tblProvider),該數據源返回了全部供應商。在對話框中放一個下拉框(cmbClientName),在對話框的OnShow事件中編寫以下代碼: 
tblProvider.Open;
tblProvider.First;
while not tblProvder.Eof do
begin
cmbClientName.Items.Add(tblProvider.FieldByName('CLIENTNAME').AsString);
tblProvder.Next;
end;
該方法通用,只須要替換相應的數據源就能夠實現其餘的內容。

   

D 在分組腳或者欄尾顯示多個數據項的合計。 
例如,對於導購人員統計表,有銷售金額、項目金額、其餘金額三項,我但願在欄尾顯示三項的合計值(不是每一項的合計)。 
若是要分別統計每一項的合計,你只需這樣。 
SUM(<tblBMAccount."SELLSUM">)就能夠統計銷售金額了。 
將三項加起來,則寫以下代碼 
SUM(<tblBMAccount."SELLSUM">+<tblBMAccount."SERVICESUM">+<tblBMAccount."OTHERSUM">)

*這裏講一下一些語法格式。 
取一個字段的格式, 
格式:TableName."FieldName"
表名+逗號+字段名,字段名用雙引號引發來。

若是你但願在一個TextObject中顯示某一個字段內容, 
格式是:[TableName."FieldName"]
用中括號括起來,中間是字段。

若是該字段內容做爲參數參加運算或者做爲一個函數的參數,則須要用<>尖括號將字段括起來。 
格式:SUM(<TableName."FieldName">)
好比:SUM(<tblBMAccount."SELLSUM">); 
或者 <tblBMAccount."SELLSUM">+<tblBMAccount."SERVICESUM">; 
一樣的,若是但願將他們放在Text Object中顯示,還必須加上中括號。 
例如:[SUM(<TableName."FieldName">)]

這裏關鍵記住,若是想在TextObject中顯示要用[]中括號,要在函數的參數中引用字段或者使用字段進行運算,須要用<>尖括號將字段括起來。

   

E 如何將報表底部的合計顯示在報表頭 
若是直接將合計的TextObject放在主項數據的前面,將不能統計值,由於此時還沒有解析出全部數據。 
利用FastReport的兩遍報表和臨時變量功能實現。 
首先設置該報表爲兩遍報表(Double Pass)。 
在底部的某一個Band中的OnBeforePrint事件中加入如下代碼: 
例如: 
Set(<tblBMAccount."BM">,SUM(<tblBMAccount."SELLSUM">+<tblBMAccount."SERVICESUM">+<tblBMAccount."OTHERSUM">));
說明:Set是一個函數,他將一個值存入了一個變量中。 
Set(var,value);其中變量var能夠利用數據表中的某一個字段,Value是你的合計值。 
在主項數據(MastData)的上面的某一個Band中放一個TextObject(例如:memTotal) 
而後在該TextObject的OnBeforePrint事件中加入以下代碼: 
例如: 
if Engine.FinalPass then
memTotal.Text := Format('%8.2f',[Get(<tblBMAccount."BM">)]);
說明:Engine是FastReport管理報表的對象,FinalPass表示最後一遍報表。 
Get(var)將變量var的值返回。Format是一個格式化數字的函數。

   

F 在底部顯示多個數據源某個字段的合計值 
例如:將三個明細的合計相加後顯示總的合計。 
方法一: 
公式以下: 
[SUM(<dsServiceItem."TOTALTAXSUM">,MasterData1)+SUM(<dsProductItem."TOTALTAXSUM">,MasterData2)+SUM(<dsOtherItem."TOTALTAXSUM">,MasterData3)]

但有一個問題是,當三個明細不是所有存在時,打印時會發生Variant Operate操做錯誤。 
我分析該錯誤產生的的緣由是當其中一個明細不存在時,此時SUM後的結果爲NULL(空值)而不是0,因此當一個NULL值與其餘一個數值相加時會發生上述錯誤。 
解決的方法是,判斷一下:若是SUM後爲NULL,則給它賦值0。剛好FastReport中有一個函數IIF(Expression,TureValue,FalseValue);該函數能夠經過判斷條件,若是條件爲True,則返回True值,爲False則返回False值。 
因此將上述表達式進行一些改造。 
IIF(SUM(<dsServiceItem."TOTALTAXSUM">,MasterData1)<>null,SUM(<dsServiceItem."TOTALTAXSUM">,MasterData1),0)
上面這個表達式表示:若是合計值不爲空,則返回合計值,不然返回0。

所以,整個表達式以下: 
[IIF(SUM(<dsServiceItem."TOTALTAXSUM">,MasterData1)<>null,SUM(<dsServiceItem."TOTALTAXSUM">,MasterData1),0)+IIF(SUM(<dsProductItem."TOTALTAXSUM">,MasterData2)<>null,SUM(<dsProductItem."TOTALTAXSUM">,MasterData2),0)+IIF(SUM(<dsOtherItem."TOTALTAXSUM">,MasterData3)<>null,SUM(<dsOtherItem."TOTALTAXSUM">,MasterData3),0)]

方法二: 
在Code頁的最頂部定義三個變量,例如: 
var
V1,V2,V3: Double;

在每一個數據源的主項腳的OnBeforePrint的事件中分別錄入: 
主項腳1的OnBeforePrint:
V1 := SUM(<dsServiceItem."TOTALTAXSUM">,MasterData1);
主項腳2的OnBeforePrint:
V2 := SUM(<dsProductItem."TOTALTAXSUM">,MasterData2);
主項腳3的OnBeforePrint:
V3 := SUM(<dsOtherItem."TOTALTAXSUM">,MasterData3);

在須要顯示合計的TextObject中使用: 
[<V1>]或者[<V2>]或者[<V3>]或者[<V1+V2+V3>]便可。

   

G 在報表中引入本身的數據源 
有客戶需求:但願打印條碼時同時打印出商品的品名規格和零售價(或其它商品相關信息),但條碼庫數據表中沒有相應的數據字段。如何進行設計呢? 
其實利用條碼庫數據表中的商品序號(ProductID),能夠本身增長一個數據源(dsBarCodeEx),經過ProductID做爲主鍵來鏈接數據表TB_BARCODE和TB_PRODUCT,將TB_PRODUCT表中的某些字段引入(根據須要)。 
數據源多是以下內容: 
SELECT
TB_BARCODE.PRODUCTID,
TB_BARCODE.BARCODE,
TB_PRODUCT.PRODUCTNUMBER,
TB_PRODUCT.PRODUCTNAME,
TB_PRODUCT.SELLPRICE
FROM
TB_BARCODE
LEFT JOIN TB_PRODUCT
ON TB_PRODUCT.PRODUCTID=TB_BARCODE.PRODUCTID

這樣,你能夠利用本身設計的數據源(原來的數據源dsBarCode不去管他)設計出相應的條碼打印報表(能夠打印零售價等)。

   

H 在報表中實現可變數據源 
在報表中能夠根據對話框中的條件實時調整數據源中的參數。 
例如:在庫存情況表中導出到條碼庫後(全部商品均導出),有時須要只打印某些商品的條碼。你能夠設計一個對話框,能夠按照商品編號篩選,若是篩選條件爲空,則打印全部商品,不然打印篩選出的商品。 
設計數據源以下: 
SELECT
BA.PRODUCTID,
BA.BARCODE,
PR.PRODUCTNUMBER,
PR.PRODUCTNAME,
PR.SELLPRICE
FROM
TB_BARCODE BA
LEFT JOIN TB_PRODUCT PR
ON PR.PRODUCTID=BA.PRODUCTID
WHERE PR.PRODUCTNUMBER = :N

而後在數據源的Params中設置N的參數。

此時,若是篩選條件爲空,則查詢出來的數據也爲空。 
這是由於條件 WHERE PR.PRODUCTNUMBER = :N 致使的。 
篩選條件爲空時,數據源應該去掉該條件。此時須要根據條件動態調整數據源。

在btnOK(對話框中的肯定按鈕)的OnClick事件中加入如下代碼: 
procedure btnOKOnClick(Sender: TfrxComponent);
var
S: string;
begin
S := 'SELECT BA.PRODUCTID,BA.BARCODE,PR.PRODUCTNUMBER,PR.PRODUCTNAME,PR.SELLPRICE'+
' FROM TB_BARCODE BA'+
' LEFT JOIN TB_PRODUCT PR'+
' ON PR.PRODUCTID=BA.PRODUCTID';
if edtProductNumber.Text<>'' then
begin
S := S + ' WHERE PR.PRODUCTNUMBER = :N';
dsBarCodeEx.ParamByName('N').Value := edtProductNumber.Text;
end;
dsBarCodeEx.SQL.Text := S;
end;
該代碼根據篩選條件不一樣,對數據源的SQL語句進行不一樣的設置。 
這樣就能夠達到要求了。


I 在對話框中,顯示開始日期和結束日期。 

在DialogPage1的OnShow事件中加入如下代碼: 
方式1: 
procedure DialogPage1OnShow(Sender: TfrxComponent);
begin
edtBD.Text := DateToStr(Date); 
edtED.Text := DateToStr(Date);
end;

說明: 
edtBD,edtED爲開始日期、結束日期的編輯框。 
DateToStr()函數將日期型變量轉爲字符串。 
如今,開始日期和結束日期默認爲今日。

方式2: 
procedure DialogPage1OnShow(Sender: TfrxComponent);
var
Y,M,D: Integer;
begin
Y := YearOf(Date);
M := MonthOf(Date);
D := DaysInMonth(Y,M);
edtBD.Text := DateToStr(EnCodeDate(Y,M,1));
edtED.Text := DateToStr(EnCodeDate(Y,M,D));
end;

說明: 
YearOf()函數返回某個日期的年份; 
MonthOf()函數返回某個日期的月份; 
DaysInMonth()函數返回某月的天數; 
EnCodeDate()函數將年、月、日整型數轉爲日期型;

如今,開始日期爲本月的1號,結束日期爲本月的最後一天。

   

J 在對話框DialogPage1中使用警告框提醒輸入相關內容

例如:你可能須要用戶必須錄入某些查詢內容,不然提醒用戶輸入。 
在btnOK(肯定按鈕)的OnClick事件中加入如下代碼:

procedure btnOKOnClick(Sender: TfrxComponent);
begin
if edtDepotName.Text = '' then
begin
ShowMessage('請輸入倉庫!');
edtDepotName.SetFocus;
DialogPage1.ModalResult := mrNone;
Exit;
end else
DialogPage1.ModalResult := mrOK;
end;

說明: 
ShowMessage()函數用於顯示一條警告信息。 
edtDepotName.SetFocus 表示該編輯框獲取輸入焦點; 
DialogPage1.ModalResult := mrOK    表示經過; 
DialogPage1.ModalResult := mrNone  表示不經過;

   

K 單據打印中如何實現空表格填滿剩餘的空行,達到指定的行數。

在原來的報表基礎上,增長一個子Band(Child1),在這個Band上設計空白行。 
能夠將Footer1的高度Height設置爲0;

在Code頁中錄入如下代碼:

var
PageLine: Integer;         //在如今頁打印到第幾行 
PageMaxRow: Integer = 8;   //指定的每頁固定行數 你能夠修改

//在MasterData1的OnBeforePrint事件中加入如下內容 
procedure MasterData1OnBeforePrint(Sender: TfrxComponent);
begin
PageLine := <Line#> mod PageMaxRow;
if (PageLine = 1) and (<Line#> > 1) then
Engine.NewPage;
end;

//在Footer1的OnBeforePrint事件中加入如下內容 
procedure Footer1OnBeforePrint(Sender: TfrxComponent);
var
i: Integer;
begin
i := iif(PageLine=0,PageMaxRow,PageLine);
while i < PageMaxRow do
begin
i := i + 1;
Engine.ShowBand(Child1);  //增長一個子Band,在該Band上設計空白的行 
end;
end;

   

L 在報表中使用金額大寫 
在FastReport的設計模式下,在Code頁中加入如下函數:

function SumToCaps(const Value : Double): string;
const
d = '零壹貳叄肆伍陸柒捌玖分角元拾佰仟萬拾佰仟億';
var
m,k : string;
j   : Integer;
begin
k :='';
m :=FloatToStr(int(Value*100));
for j:=length(m) downto 1 do
k := k+d[(strtoint(m[Length(m)-j+1])+1)*2-1]+
d[(strtoint(m[Length(m)-j+1])+1)*2]+d[(10+j)*2-1]+d[(10+j)*2];
result := k;
end;

當你須要將一個金額轉換爲金額大寫時能夠以下操做: 
一、在Code頁的開始處定義一個字符串。 
Var
TOTALSUM_CAPS: string;

二、在相應的事件(多是OnBeforePrint)中加入 
TOTALSUM_CAPS := SumToCaps(TOTALSUM);
注:這裏的TOTALSUM多是一個變量,也能夠是數據源中的字段或者合計值。例如: 
<tblMaster."TOTALSUM">或者SUM(<tblMaster."TOTALSUM",MasterData1,1>)。

三、在須要顯示大寫金額的TextObject中鍵入[<TOTALSUM_CAPS>]。

   

M 如何隱藏某些主項數據記錄

一般當某個數值爲零時,咱們不但願這條記錄被打印或者顯示。 
步驟以下: 
一、選擇主項數據MastData1的OnBeforePrint時間。 
二、在OnBeforePrint事件中填寫代碼 
if <tblMaster."TotalSum">=0 then
MastData1.Visible := False else
MastData1.Visible := True;
其中<tblMaster."TotalSum">=0是條件,你能夠定義爲本身的條件。

   

N 如何強調某些主項數據的內容 有時咱們但願當知足必定條件時,某些數據的字體或者顏色顯示不一樣,以達到強調的目的。 步驟以下: 1 選擇須要強調的TextObject。 2 選擇工具欄中的強調按鈕。 3 在對話框中錄入須要強調時的條件。例如:<tblMasterData."TotalSum"> >= 10004 選擇強調的字體,顏色。

相關文章
相關標籤/搜索