1、北大青鸟中关村ASP.NET 中动态控制 RDLC 报表在 程序中,可以选择使用水晶报表,功能确实强大。但是 web 版的水晶报表好像存在版权的问题。如果所作报表不是复杂的一塌糊涂的话,可以使用微软自带的 Rdlc 报表。Rdlc 优点:1:Rdlc 报表设计简单2:结果存成 xml,易于控制3:导出格式作的很不错这里所说的动态控制报表所指的是:在一些时候,制作了报表之后希望在运行中可以动态的做一些小修改,比如说列的位置,用户控制显示那些列等等。控制方法,尝试了这么几种:1:控制微软提供的报表对象的属性;北大青鸟中关村2:报表全部自动生成3:修改报表源文件,然后加载。控制微软提供的报表对象的
2、属性:基于这个功能需求,一开始我想到的方法是通过控制微软提供的这些报表对象的属性来实现。因为这种方法最人道了。但是事与愿违,微软的ReportViewer 对象是用来显示 Report 的,自然不行;我使用的 report 是自己设计的,localReport,找到 Report 对象,里面方法有这个几个:report.GetDefaultPageSettings();report.GetDocumentMap()等,第一个是获取打印纸张德设置,第二个是获取 doc 文档(但是始终出错) ,都是只读属性;所以,第一种尝试失败。第二种方法就是报表全部自动生成。可以找到一个完整的例子,在这里:ht
3、tp:/ xml 结构的 rdlc 报表写成一个类ReportDefinition,然后通过自定义这个类的内容来得到一个报表。其实际还是为了自己构造一个报表对象的 xml。这是加载自定义报表的过程:win 下的代码 this.reportViewer1.Reset();北大青鸟中关村this.reportViewer1.LocalReport.LoadReportDefinition(m_rdl);this.reportViewer1.LocalReport.DataSources.Add(new ReportDataSource(“MyData“, m_dataSet.Tables0);th
4、is.reportViewer1.RefreshReport();这是自动生成 xml 的代码:private MemoryStream GenerateRdl(Liststring allFields, Liststring selectedFields)MemoryStream ms = new MemoryStream();RdlGenerator gen = new RdlGenerator();gen.AllFields = allFields;gen.SelectedFields = selectedFields;gen.WriteXml(ms);ms.Position = 0;r
5、eturn ms;这是完全 ReportDefinition 的一部分定义:namespace Rdl 北大青鸟中关村using System.Xml.Serialization;/*/ remarks/System.CodeDom.Compiler.GeneratedCodeAttribute(“xsd“, “2.0.50727.42“)System.SerializableAttribute()System.Diagnostics.DebuggerStepThroughAttribute()System.ComponentModel.DesignerCategoryAttribute(“c
6、ode“)System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)System.Xml.Serialization.XmlRootAttribute(Namespace=_“http:/ IsNullable=false)public partial class Report private object itemsField;北大青鸟中关村但是几经考虑之后,这个方案也不让人满意,原因是:所有的报表对象都得自己生成,一下子回到了解放前,没有可视化工具的设计既繁琐又复杂。特别是如果设计几个 line,然后再来上几个分组的话,工作量
7、巨大。于是乎尝试第三种方法:ReportVivwer 加载报表前在内存中修改报表源文件。这个方法比较狠,其实可以解决很多问题,包括设计自定义的打印纸张等(这里有另外一种设置打印纸张的方法http:/ 。设计思路是:首先加载 rdlc 文件到一个 XmlDocument 对象;然后修改 xml 内容;把 xml 序列化成字节流,交给ReportViewer 显示。这是这一段代码:public MemoryStream GenerateRdlc()XmlDocument sourceDoc = new XmlDocument();string path = AppDomain.CurrentDom
8、ain.BaseDirectory + 北大青鸟中关村“Test/OrderList.rdlc“;sourceDoc.Load(path);Hashtable reportColumns = GetReportColumns(sourceDoc.LastChild);/just removefor (int i = 0; i reportColumns.Count; i+)if (!FindReportCoulmns(reportColumns.ToString()RemoveColumnFromRdlc(sourceDoc.LastChild, i);MemoryStream ms = ne
9、w MemoryStream();XmlSerializer serializer = new XmlSerializer(typeof(XmlDocument);serializer.Serialize(ms, sourceDoc);ms.Position = 0;return ms;至于如何 GetReportColumns 和 RemoveColumnFromRdlc,北大青鸟中关村那就很简单了,就是一个操作 xml 对象的过程。比方说:private Hashtable GetReportColumns(XmlNode root)Hashtable cols = new Hashtab
10、le();/XmlNamespaceManager s=new XmlNamespaceManager(XmlNode cells = FindChildNode(root,“Body/ReportItems/Table/Header/TableRows/TableRow/TableCells“);for (int i = 0; i cells.ChildNodes.Count; i+)XmlNode cell =FindChildNode( cells.ChildNodes,“ReportItems/Textbox/DataElementName“);cols = cell.InnerTex
11、t;return cols;这是使用这一段的代码:this.ReportViewer1.LocalReport.LoadReportDefinition(this.Report.GenerateRdlc();北大青鸟中关村this.ReportViewer1.LocalReport.DataSources.Add(new ReportDataSource(“DataSet1“, result.Tables0);this.ReportViewer1.LocalReport.Refresh();这个方法终于成功了。附: rdlc 文件的 xml 一段结构xml 结构1 ?xml version=“
12、1.0“ encoding=“utf-8“?2 Report xmlns=“http:/ xmlns:rd=“http:/ DataSources4 DataSource Name=“ConnectionString“5 ConnectionProperties6 ConnectString /7 DataProvider SQL /DataProvider8 /ConnectionProperties北大青鸟中关村9 rd:DataSourceID 073016a7-6cb0-4e06-a6fd-f5882a039188 /rd:DataSourceID10 /DataSource11 /D
13、ataSources12 BottomMargin 2.5cm /BottomMargin13 RightMargin 2.5cm /RightMargin14 PageWidth 21cm /PageWidth15 rd:DrawGrid true /rd:DrawGrid16 InteractiveWidth 21cm /InteractiveWidth17 rd:GridSpacing 0.25cm /rd:GridSpacing18 rd:SnapToGrid true /rd:SnapToGrid19 Body20 ColumnSpacing 1cm /ColumnSpacing21 ReportItems22 Chart Name=“chart1“