使用FastReport.net在使用者的應用程式中建立報表

Elyn發表於2017-08-03

FastReport .Net是一款強大且應用十分廣泛的報表工具,我最喜歡的特點之一是它直接從使用者應用程式中建立報表的能力。在這篇文章中,我們來看看這個功能的例子,當你不需要一堆的.exe檔案的時候它就能派上用場了。此外,你可以根據應用邏輯來完全掌控self-report的建立、改變報表物件的外觀。

首先,我將展示從使用者應用程式的程式碼中構建報表和在特殊設計器中報表模板經典開發的區別。
通常情況下,報表生成器提供了一個特殊的設計器來設計報表模板。這可能是IDE的元件或僅僅是外部程式。開發人員將元件放在報表的頁上,並指定它們的屬性,這類似於在窗體應用程式中設計表單。

除了這些經典的方法來建立一個報表模板外,FastReport允許你在應用程式程式碼的幫助下使用相同的元件來建立模板,你同樣能夠建立報表物件並新增元件以及配置資料來源。實踐表明,從程式碼中建立報表比在視覺化設計器中時間會稍稍長一點,但有趣的是,這樣得到的報表模板可以在同一個視覺化編輯器(設計器)中檢視並儲存到檔案中。

讓我們來看看例子。
用C#語言建立Windows窗體應用程式(當然你應該先安裝FastReport .Net),在表單上放置一個按鈕來啟動報表。接下來,我要說的是,我們不僅僅要在預覽模式下展示報表,還要讓它匯出到PDF檔案。因此新增核取方塊:
clipboard.png

建立一個按鈕單擊事件處理程式,這裡是整個應用程式的程式碼。
首先,新增應用到FastReport.dll(在FastReport .Net包中)。
同樣,新增FastReport庫、 FastReport.Utils以及FastReport.Data。

建立報表示例:

private void RunBtn_Click(object sender, EventArgs e)
 {
 //Create instance of class Report
 Report report = new Report();
 }

我們的報表將從資料庫中展示資料,因此需要建立資料來源:

//load data
DataSet ds = new DataSet();
ds.ReadXml(AppFolder + "\\nwind.xml");

現在需要在報表中註冊資料來源:

//Register data source
report.RegisterData(ds);

要使用已註冊的資料來源表,你需要給它授權:

//Enable data table
report.GetDataSource("Products").Enabled = true;

籌備工作做好了,現在轉移到報表模板的建立上來,建立報表頁面:

//Add report page
ReportPage page = new ReportPage();

並將其新增到報表中:

report.Pages.Add(page);

報表的所有物件都需要有一個特定的名稱,你可以用他們自帶的並指定屬性名稱,或者你可以使用一個函式生成一個唯一的名稱:

page.CreateUniqueName();

準備填充報表頁面。建立一個“Group Header”帶(band):

//Create GroupHeader band
GroupHeaderBand group = new GroupHeaderBand();

並將帶新增到頁面:

page.Bands.Add(group);
group.CreateUniqueName();

設定帶的高度:

group.Height = Units.Centimeters * 1;

分組條件和排序順序:

group.Condition = "[Products.ProductName].Substring(0,1)";
group.SortOrder = FastReport.SortOrder.Ascending;

現在用資料填充帶。要做到這一點,從資料來源建立一個文字物件以引用該欄位:

// create group text
TextObject groupTxt = new TextObject();

重要的父引數指示該帶,放置文字物件:

groupTxt.Parent = group;
groupTxt.CreateUniqueName();

設定文字物件的大小和範圍:

groupTxt.Bounds = new RectangleF(0, 0, Units.Centimeters * 10, Units.Centimeters * 1);

設定文字大小和範圍:

groupTxt.Font = new Font("Arial", 14, FontStyle.Bold);

其他設定視文字的外觀而定:

groupTxt.Text = "[[Products.ProductName].Substring(0,1)]";
groupTxt.VertAlign = VertAlign.Center;
groupTxt.Fill = new LinearGradientFill(Color.LightGoldenrodYellow, Color.Gold, 90, 0.5f, 1);

現在最有趣的部分是建立帶“資料”:

// create data band
DataBand data = new DataBand();

為該組分配資料帶:

group.Data = data;
data.CreateUniqueName();

為帶“資料”指定資料來源:

data.DataSource = report.GetDataSource("Products");
data.Height = Units.Centimeters * 0.5f;

在這裡你可以透過屬性過濾器設定過濾器帶。現在用文字物件填充帶:

// create product name text
TextObject productText = new TextObject();
productText.Parent = data;
productText.CreateUniqueName();
productText.Bounds = new RectangleF(0, 0, Units.Centimeters * 10, Units.Centimeters * 0.5f);
productText.Text = "[Products.ProductName]";

組頁尾最適宜特定的分組例項,即使有多個組頭也不會混淆。建立組頁尾:

// create group footer
 group.GroupFooter = new GroupFooterBand();
 group.GroupFooter.CreateUniqueName();
 group.GroupFooter.Height = Units.Centimeters * 1;

向組頁尾中新增總數,它將顯示該組的產品計數:

// create total
Total groupTotal = new Total();
groupTotal.Name = "TotalRows";

設定型別計算,計算所用的帶,以及顯示結果的帶,因為我們定義了專案的數量就不需要指定特定欄位來計算(使用groupTotal.Expression)。

groupTotal.TotalType = TotalType.Count;
 groupTotal.Evaluator = data;
 groupTotal.PrintOn = group.GroupFooter;

我們需要在報表彙總字典中新增總計的總數。註冊:

report.Dictionary.Totals.Add(groupTotal);

像任何表示式展示那樣,結果會透過文字物件展示:

// show total in the group footer
 TextObject totalText = new TextObject();
 totalText.Parent = group.GroupFooter;
 totalText.CreateUniqueName();
 totalText.Bounds = new RectangleF(0, 0, Units.Centimeters * 10, Units.Centimeters * 0.5f);
 totalText.Text = "Rows: [TotalRows]";
 totalText.HorzAlign = HorzAlign.Right;
 totalText.Border.Lines = BorderLines.Top;

報表準備好了,現在我們可以顯示它或者在設計器裡面執行,並且你可以立即將其匯出以自己想要的資料格式。讓我們用一個核取方塊,新增到窗體:

if (PDFCheckBox.Checked)
 {
 report.Prepare();
 FastReport.Export.Pdf.PDFExport export = new FastReport.Export.Pdf.PDFExport();
 export.Export(report);
 }
 else
 report.Show();

如果核取方塊被選中,你會獲得對話方塊儲存的PDF檔案,反之,該報表將在預覽模式下執行。這裡值得注意的是,即使不顯示對話方塊,也可以進行匯出,像某種“安靜模式”。匯出會像這樣:

export.Export(report, @"C:\Temp\ReportFromCode.pdf");

第一選項-報表示例以及第二選項-結果檔案。

我們得到的結果:

//Create instance of class Report
Report report = new Report();
 
//load data
DataSet ds = new DataSet();
ds.ReadXml(AppFolder + "\\nwind.xml");
 
//Register data source
report.RegisterData(ds);
 
//Enable data table
report.GetDataSource("Products").Enabled = true;
 
//Add report page
ReportPage page = new ReportPage();
report.Pages.Add(page);
page.CreateUniqueName();
 
//Create GroupHeader band
GroupHeaderBand group = new GroupHeaderBand();
page.Bands.Add(group);
group.CreateUniqueName();
group.Height = Units.Centimeters * 1;
group.Condition = "[Products.ProductName].Substring(0,1)";
group.SortOrder = FastReport.SortOrder.Ascending;
 
// create group text
TextObject groupTxt = new TextObject();
groupTxt.Parent = group;
groupTxt.CreateUniqueName();
groupTxt.Bounds = new RectangleF(0, 0, Units.Centimeters * 10, Units.Centimeters * 1);
 
groupTxt.Text = "[[Products.ProductName].Substring(0,1)]";
groupTxt.Font = new Font("Arial", 14, FontStyle.Bold);
groupTxt.VertAlign = VertAlign.Center;
groupTxt.Fill = new LinearGradientFill(Color.LightGoldenrodYellow, Color.Gold, 90, 0.5f, 1);
 
// create data band
DataBand data = new DataBand();
group.Data = data;
data.CreateUniqueName();
data.DataSource = report.GetDataSource("Products");
data.Height = Units.Centimeters * 0.5f;
 
// create product name text
TextObject productText = new TextObject();
productText.Parent = data;
productText.CreateUniqueName();
productText.Bounds = new RectangleF(0, 0, Units.Centimeters * 10, Units.Centimeters * 0.5f);
productText.Text = "[Products.ProductName]";
 
// create group footer
group.GroupFooter = new GroupFooterBand();
group.GroupFooter.CreateUniqueName();
group.GroupFooter.Height = Units.Centimeters * 1;
 
// create total
Total groupTotal = new Total();
groupTotal.Name = "TotalRows";
groupTotal.TotalType = TotalType.Count;
groupTotal.Evaluator = data;
groupTotal.PrintOn = group.GroupFooter;
report.Dictionary.Totals.Add(groupTotal);
 
// show total in the group footer
TextObject totalText = new TextObject();
totalText.Parent = group.GroupFooter;
totalText.CreateUniqueName();
totalText.Bounds = new RectangleF(0, 0, Units.Centimeters * 10, Units.Centimeters * 0.5f);
totalText.Text = "Rows: [TotalRows]";
totalText.HorzAlign = HorzAlign.Right;
totalText.Border.Lines = BorderLines.Top;
 
if (PDFCheckBox.Checked)
{
report.Prepare();
FastReport.Export.Pdf.PDFExport export = new FastReport.Export.Pdf.PDFExport();
export.Export(report);
//export.Export(report, @"C:\Temp\ReportFromCode.pdf");
}
else
report.Show();

報表本身:
clipboard.png

總結一下,從程式碼中建立報表是FastReport .Net的又一令人驚訝的功能。什麼時候有用呢?如果你不想產生一堆個人檔案的報告模板或要在應用程式內隱藏一個報告模板,以避免損壞或修改模板。同樣的它在應用程式的執行過程中更改報表模板也非常方便,這賦予了報表很大的靈活性以及使用單個模板的能力、根據程式邏輯修改它的能力。

希望此功能也可以為大家帶來便利,提升工作效率。

相關文章