FastReport .Net是一款强大且应用十分广泛的报表工具,我最喜欢的特点之一是它直接从用户应用程序中创建报表的能力。在这篇文章中,我们来看看这个功能的例子,当你不需要一堆的.exe文件的时候它就能派上用场了。此外,你可以根据应用逻辑来完全掌控self-report的创建、改变报表对象的外观。
首先,我将展示从用户应用程序的代码中构建报表和在特殊设计器中报表模板经典开发的区别。
通常情况下,报表生成器提供了一个特殊的设计器来设计报表模板。这可能是IDE的组件或仅仅是外部程序。开发人员将组件放在报表的页上,并指定它们的属性,这类似于在窗体应用程序中设计表单。
除了这些经典的方法来创建一个报表模板外,FastReport允许你在应用程序代码的帮助下使用相同的组件来创建模板,你同样能够创建报表对象并添加组件以及配置数据源。实践表明,从代码中创建报表比在可视化设计器中时间会稍稍长一点,但有趣的是,这样得到的报表模板可以在同一个可视化编辑器(设计器)中查看并保存到文件中。
让我们来看看例子。
用C#语言创建Windows窗体应用程序(当然你应该先安装FastReport .Net),在表单上放置一个按钮来启动报表。接下来,我要说的是,我们不仅仅要在预览模式下展示报表,还要让它导出到PDF文件。因此添加复选框:
创建一个按钮单击事件处理程序,这里是整个应用程序的代码。
首先,添加应用到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();
报表本身:
总结一下,从代码中创建报表是FastReport .Net的又一令人惊讶的功能。什么时候有用呢?如果你不想产生一堆个人文件的报告模板或要在应用程序内隐藏一个报告模板,以避免损坏或修改模板。同样的它在应用程序的执行过程中更改报表模板也非常方便,这赋予了报表很大的灵活性以及使用单个模板的能力、根据程序逻辑修改它的能力。
希望此功能也可以为大家带来便利,提升工作效率。