ASP.NET中动态控制RDLC报表

来源:互联网 发布:淘宝名称大全卡通 编辑:程序博客网 时间:2024/05/22 20:29

在asp.net程序中,可以选择使用水晶报表,功能确实强大。但是web版的水晶报表好像存在版权的问题。如果所作报表不是复杂的一塌糊涂的话,可以使用微软自带的Rdlc报表。

  Rdlc优点:

  1:Rdlc报表设计简单

  2:结果存成xml,易于控制

  3:导出格式作的很不错

  这里所说的动态控制报表所指的是:在一些时候,制作了报表之后希望在运行中可以动态的做一些小修改,比如说列的位置,用户控制显示那些列等等。

  控制方法,尝试了这么几种:

  1:控制微软提供的报表对象的属性;

  2:报表全部自动生成

  3:修改报表源文件,然后加载。

  控制微软提供的报表对象的属性:基于这个功能需求,一开始我想到的方法是通过控制微软提供的这些报表对象的属性来实现。因为这种方法最人道了。但是事与愿违,微软的ReportViewer对象是用来显示Report的,自然不行;我使用的report是自己设计的,localReport,找到Report对象,里面方法有这个几个:report.GetDefaultPageSettings();report.GetDocumentMap()等,第一个是获取打印纸张德设置,第二个是获取doc文档(但是始终出错),都是只读属性;所以,第一种尝试失败。

  第二种方法就是报表全部自动生成。可以找到一个完整的例子,在这里:http://www.gotreportviewer.com/DynamicTable.zip
这个例子里面,他把xml结构的rdlc报表写成一个类ReportDefinition,然后通过自定义这个类的内容来得到一个报表。其实际还是为了自己构造一个报表对象的xml。这是加载自定义报表的过程:win下的代码 this.reportViewer1.Reset();

this.reportViewer1.LocalReport.LoadReportDefinition(m_rdl);
this.reportViewer1.LocalReport.DataSources.Add(new ReportDataSource("MyData", m_dataSet.Tables[0]));
this.reportViewer1.RefreshReport();这是自动生成xml的代码:
private MemoryStream GenerateRdl(List<string> allFields, List<string> selectedFields)
{
 MemoryStream ms = new MemoryStream();
 RdlGenerator gen = new RdlGenerator();
 gen.AllFields = allFields;
 gen.SelectedFields = selectedFields;
 gen.WriteXml(ms);
 ms.Position = 0;
 return 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("code")]
 [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
 [System.Xml.Serialization.XmlRootAttribute(Namespace=_
  "http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition", IsNullable=false)]
 public partial class Report {
  private object[] itemsField;

  但是几经考虑之后,这个方案也不让人满意,原因是:所有的报表对象都得自己生成,一下子回到了解放前,没有可视化工具的设计既繁琐又复杂。特别是如果设计几个line,然后再来上几个分组的话,工作量巨大。

  于是乎尝试第三种方法:ReportVivwer加载报表前在内存中修改报表源文件。这个方法比较狠,其实可以解决很多问题,包括设计自定义的打印纸张等(这里有另外一种设置打印纸张的方法http://waxdoll.cnblogs.com/archive/2006/03/03/342435.html)。

  设计思路是:首先加载rdlc文件到一个XmlDocument对象;然后修改xml内容;把xml序列化成字节流,交给ReportViewer显示。 这是这一段代码:

public MemoryStream GenerateRdlc()
{
 XmlDocument sourceDoc = new XmlDocument();
 string path = AppDomain.CurrentDomain.BaseDirectory + "Test/OrderList.rdlc";
 sourceDoc.Load(path);
 Hashtable reportColumns = GetReportColumns(sourceDoc.LastChild);
 //just remove
 for (int i = 0; i < reportColumns.Count; i++)
 {
  if (!FindReportCoulmns(reportColumns[i].ToString()))
  {
   RemoveColumnFromRdlc(sourceDoc.LastChild, i);
  }
 }

 MemoryStream ms = new 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 Hashtable();
 //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[i],"ReportItems/Textbox/DataElementName");
  cols[i] = cell.InnerText;
 }
 return cols;
}

  这是使用这一段的代码:

this.ReportViewer1.LocalReport.LoadReportDefinition(this.Report.GenerateRdlc());
this.ReportViewer1.LocalReport.DataSources.Add(new ReportDataSource("DataSet1", result.Tables[0]));
this.ReportViewer1.LocalReport.Refresh();

  这个方法终于成功了。

  附:rdlc文件的xml一段结构

  xml结构

1<?xml version="1.0" encoding="utf-8"?>
2<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">
3 <DataSources>
4 <DataSource Name="ConnectionString">
5 <ConnectionProperties>
6 <ConnectString />
7 <DataProvider>SQL</DataProvider>
8 </ConnectionProperties>
9 <rd:DataSourceID>073016a7-6cb0-4e06-a6fd-f5882a039188</rd:DataSourceID>
10 </DataSource>
11 </DataSources>
12 <BottomMargin>2.5cm</BottomMargin>
13 <RightMargin>2.5cm</RightMargin>
14 <PageWidth>21cm</PageWidth>
15 <rd:DrawGrid>true</rd:DrawGrid>
16 <InteractiveWidth>21cm</InteractiveWidth>
17 <rd:GridSpacing>0.25cm</rd:GridSpacing>
18 <rd:SnapToGrid>true</rd:SnapToGrid>
19 <Body>
20 <ColumnSpacing>1cm</ColumnSpacing>
21 <ReportItems>
22 <Chart Name="chart1">
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 2月幼犬不吃东西怎么办 小狗狗不吃狗粮怎么办 母猫不会照顾小猫怎么办 刚买的小狗拉稀怎么办 母兔子吃小兔子怎么办 照片照出来背亮景人是黑的怎么办 手机透明壳变黄了怎么办 ae视频渲染太慢怎么办 3ce口红太干了怎么办 中考误用0.38mm的笔怎么办 ps画笔都锁住了怎么办 削铅笔机坏了怎么办 幼儿园小朋友不听老师话怎么办 孩子在幼儿园不听老师话怎么办 幼儿园大班孩子上课不好好上怎么办 脸上挠了血印子怎么办 大班公开课烫伤了怎么办教案 孩子心理出现了问题该怎么办 幼师打孩子很多家长告怎么办 课堂上纪律不好的学生怎么办 孩子上幼儿园总感冒怎么办 孩子上幼儿园总生病怎么办 台湾人抗拒统大陆人中国人怎么办 如果一年的公休日耍不完怎么办 我一个月要歇三天班怎么办 学校没给报到证怎么办 员工休息一天老板拉着脸怎么办 换工作了报到证怎么办 幼儿园的孩子不写作业怎么办 幼儿园宝宝不写作业怎么办 幼儿园孩子不写作业怎么办 光盘数据面写字了怎么办 娃娃的手断了怎么办 联币金融跑路了怎么办 胃消化不了想吐怎么办 吃撑了恶心想吐怎么办 mac口红膏体晃动怎么办 excl图标和以前不一样了怎么办 冰箱显示板坏了怎么办 冰箱电脑显示屏坏了怎么办 冰箱的电子显示屏坏了怎么办