前言使用Crystal Report在產生報表時,其實有很多功能是內建的,但是卻常因為使用者對它的使用方法跟結構不太熟悉,讓程式碼多了一大圈,所以,在此就以一個簡單的例子為範本,來介紹一些常用的功能。
範例介紹這裡選擇SQL server為資料庫,開一個Table來存放學生的姓名、班級、座號、小考以及大考成績..等等,接著使用Crystal Report來畫出學期分數總表,Table的Schema如下:
《圖一》ScoreTable的Schema
StudentNumber:學號Subject:科目,此例的1代表國文,2代表數學ExamType:考試類別,此例的1代表小考,2代表大考ExamNumber:考試編號,代表第幾次考試Grade:年級Class:班級ClassNumber:座號StudentName:姓名Score:分數《圖二》資料內容
最終報表結果如圖三:
《圖三》最終報表結果
報表製作圖四是Crystal Report開啟後樣子,左邊的資料庫欄位是以圖一為資料來源。
《圖四》
把資料庫欄位中要用到的欄位拉到報表中之後,想要把欄位的資料內容做一個轉換的話,可以在公式欄位上按右鍵新增一個公式欄位如圖五,以及編寫指令為規則來轉換資料內容,指令如下:
if({ScoreTable.Subject} = "1") then
"國文"
else if({ScoreTable.Subject} = "2") then
"數學"
《圖五》
如果想要畫出格線以及表格的話可以打開檢視中的工具箱,拖曳線條物件以及方塊物件就可以畫出如圖六的效果
《圖六》
接著報表的內容在資料庫中的順序也是需要整理的,這裡可以在畫面上直接按右鍵使用群組專家來排序如圖七
《圖七》
群組專家除了會把全部的排序條件排成一個巢狀式結構外,其實也提供了一個非常方便的功能,就是可以在這些新增出來的Section上方按右鍵使用區段專家可以來指定此Section中所有物件的顯示/隱藏條件,並且還能選擇是否以這個群組來當作換頁的依據。
範例中想把同一人的年級、班級、座號只要顯示一次出來即可:
Step 1 可以把不需要的Section以區段專家設為隱藏,如圖八;接著在ClassNumber的那個Section 下新增一個公式欄位以作為計數歸零的依據,放在這裡的作用就是在此Section群組條件下的資料會執行到此公式,指令如下:
WhilePrintingRecords;
Shared currencyVar StudentNumberIndex;
StudentNumberIndex := 0;
Step 2接著可以在細目的Scetion中新增一個用來計數的公式欄位,並且在格式物件中的一般來抑制顯示來達到隱藏的計數器功能,指令如下:
WhilePrintingRecords;
Shared currencyVar StudentNumberIndex;
StudentNumberIndex := StudentNumberIndex + 1;
Step 3 最後在Grade的物件上按右鍵選擇格式物件並且按下抑制顯示右方的按鈕以編寫指令為規則來控制是否要顯示/隱藏此物件,指令如下:
WhilePrintingRecords;
Shared currencyVar StudentNumberIndex;
if StudentNumberIndex = 1
then
false
else
true
《圖八》
範例的最後,想在每個人的當科目底下顯示出平均分數,並且大考跟小考的分數還要按照不同的比例來計算:
Step 1 在Subject的那個Section 下新增一個公式欄位以作為計數歸零的依據,放在這裡的作用就是在此Section群組條件下的資料會執行到此公式,指令如下:
WhilePrintingRecords;
Shared currencyVar ExamTypeIndex1;
ExamTypeIndex1 := 0;
Shared currencyVar ExamTypeIndex2;
ExamTypeIndex2 := 0;
Shared currencyVar ExamTypeIndexScore1;
ExamTypeIndexScore1 := 0;
Shared currencyVar ExamTypeIndexScore2;
ExamTypeIndexScore2 := 0;
Step 2 接著可以在細目的Scetion中新增一個用來計數的公式欄位,並且在格式物件中的一般來抑制顯示來達到隱藏的計數器功能,指令如下:
WhilePrintingRecords;
Shared currencyVar ExamTypeIndex1;
Shared currencyVar ExamTypeIndexScore1;
Shared currencyVar ExamTypeIndex2;
Shared currencyVar ExamTypeIndexScore2;
if({ScoreTable.ExamType} = "1") then
(
ExamTypeIndex1 := ExamTypeIndex1 + 1;
ExamTypeIndexScore1 := ExamTypeIndexScore1 + {ScoreTable.Score};
)
else if({ScoreTable.ExamType} = "2") then
(
ExamTypeIndex2 := ExamTypeIndex2 + 1;
ExamTypeIndexScore2 := ExamTypeIndexScore2 + {ScoreTable.Score};
Step 3 最後讓結束的Subject Scetion顯示出來,以達到只有不同科目的時候會顯示出來,如圖九,並且在同一個Section中新增一個編輯公式來算出大小考的分數比例以及顯示平均分數,指令如下:
WhilePrintingRecords;
Shared currencyVar ExamTypeIndex1;
Shared currencyVar ExamTypeIndexScore1;
Shared currencyVar ExamTypeIndex2;
Shared currencyVar ExamTypeIndexScore2;
(ExamTypeIndexScore1/ExamTypeIndex1)*0.4 + (ExamTypeIndexScore2/ExamTypeIndex2)*0.6
《圖九》
結論當一開始還不習慣Crystal Report的時候常常會一個功能找半天才發動其功能或者用很多Code在傳入資料之前處理資料,越用越熟之後就會覺得這些內建的功能對使用者相當好用、可節省很多時間。
參考資料http://www.dotblogs.com.tw/jackbgova/archive/2014/06/13/145525.aspx
http://www.dotblogs.com.tw/jackbgova/archive/2014/05/19/145169.aspx
http://wolfeyeworld.blogspot.tw/2013/11/crystal-report-crystal-report.html
HTTP://TSUOZOE.PIXNET.NET/BLOG/POST/28079545-CRYSTAL-REPORT-%E8%A8%AD%E8%A8%88_BEFOREREADINGRECORDS%E3%80%81WHILEREADINGREC