分享一个动态生成RDLC报表的类 - thanks

原文  http://www.cnblogs.com/thanks/p/DynamicReport.html

在实际工作中,当需要进行大批量查询和生成报表的时候,可以使用我写的类。

特点:

  • 无需报表设计器、无需为报表设置数据集
  • 只需要传入查询结果就可以全自动生成报表,传入的对象为Dynamic(目前支持DataTable和IEnumable<T>的传入参数)
  • 文字、数据表可以无限添加

我没有采用使用操纵微软报表Schema的方法,而是用了拼接字符串:(

将来想到的扩展功能有:

  • 支持图表
  • 支持数据分组

希望我写的工具能为大家工作中提供方便,也希望大家对我写的程序进行指正:)

源码:

接口:

using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using Microsoft.Reporting.WebForms;

 public interface IDynamicReport
 {
  void SetReport(ReportViewer reportViewer);
  void AddData<T>(IEnumerable<T> data);
  void AddData(DataTable dataTable);
  void ShowReport();
  void LoadReport(string reportPath);
  void SetColoumStyle(List<ReportColoumStyle> coloumStyle);
  void AddText(string title);
 }

辅助类和枚举:

 1     public class ReportColoumStyle
 2     {
 3         public string ColoumName { get; set; }
 4         public float ColoumWidth { get; set; }
 5         public TextAlign TextAlign { get; set; }
 6     }
 7 
 8     public enum TextAlign
 9     {
10         Left,Center,Right
11     }
12 
13     public enum ReportType
14     {
15         Tables, Chart, Finally
16     }
17 
18     public class ReportItemPattern
19     {
20         public string DataSetName { get; set; }
21         public string DataSetString { get; set; }
22         public string TablixString { get; set; }
23         public dynamic Data { get; set; }
24 
25         public string DataSetPattern
26         {
27             get
28             {
29                 return "    <DataSet Name=\"@DataSetNameData\">" +
30                        "       <Fields>@Fields</Fields>" +
31                        "       <Query>" +
32                        "           <DataSourceName>DummyDataSource</DataSourceName>" +
33                        "           <CommandText />" +
34                        "       </Query>" +
35                        "    </DataSet>";
36             }
37         }
38 
39         public string TablixPattern
40         {
41             get
42             {
43                 return " <Tablix Name=\"Tablix@DataSetName\">" +
44                        "   <TablixBody>" +
45                        "       <TablixColumns>@TablixColumns</TablixColumns>" +
46                        "       <TablixRows>" +
47                        "           <TablixRow>" +
48                        "               <Height>0.23622in</Height>" +
49                        "               <TablixCells>@TablixHeader</TablixCells>" +
50                        "           </TablixRow>" +
51                        "           <TablixRow>" +
52                        "               <Height>0.23622in</Height>" +
53                        "               <TablixCells>@TablixCells</TablixCells>" +
54                        "           </TablixRow>" +
55                        "       </TablixRows>" +
56                        "   </TablixBody>" +
57                        "   <TablixColumnHierarchy>" +
58                        "       <TablixMembers>@TablixMember</TablixMembers>" +
59                        "   </TablixColumnHierarchy>" +
60                        "   <TablixRowHierarchy>" +
61                        "       <TablixMembers>" +
62                        "           <TablixMember>" +
63                        "               <KeepWithGroup>After</KeepWithGroup>" +
64                        "           </TablixMember>" +
65                        "           <TablixMember>" +
66                        "               <Group Name=\"详细信息@DataSetName\" />" +
67                        "           </TablixMember>" +
68                        "       </TablixMembers>" +
69                        "   </TablixRowHierarchy>" +
70                        "   <DataSetName>@DataSetNameData</DataSetName>" +
71                        "   <Top>@TopPositioncm</Top>" +
72                        "   <Left>@LeftPostioncm</Left>" +
73                        "   <Height>1.2cm</Height>" +
74                        "   <Width>14.35207cm</Width>" +
75                        "   <Style>" +
76                        " <Border>" +
77                        " <Style>None</Style>" +
78                        "       </Border>" +
79                        "   </Style>" +
80                        "</Tablix>";
81             }
82         }
83     }
View Code
  1     public class DynamicReport : IDynamicReport
  2     {
  3         #region 空白文档
  4 
  5         /// <summary>
  6         /// 空白文档的xml文件
  7         /// </summary>
  8         protected string _docTemplate =
  9             "<?xml version=\"1.0\" encoding=\"utf-8\"?><Report xmlns:rd=\"http://schemas.microsoft.com/SQLServer/reporting/reportdesigner\" xmlns=\"http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition\">" +
 10             "<DataSources>" +
 11             "   <DataSource Name=\"DummyDataSource\">" +
 12             "       <ConnectionProperties>" +
 13             "           <DataProvider>SQL</DataProvider>" +
 14             "           <ConnectString />" +
 15             "       </ConnectionProperties>" +
 16             "       <rd:DataSourceID>3eecdab9-6b4b-4836-ad62-95e4aee65ea8</rd:DataSourceID>" +
 17             "   </DataSource>" +
 18             "</DataSources>" +
 19             "<DataSets>@DataSets</DataSets>" +
 20             "<Body>" +
 21             "<ReportItems>@Title@Tablix" +
 22             "</ReportItems>" +
 23             "<Style />" +
 24             "<Height>8cm</Height>" +
 25             "</Body>" +
 26             "<Width>17cm</Width>" +
 27             "<Page>" +
 28             "<PageHeight>29.7cm</PageHeight>" +
 29             "<PageWidth>21cm</PageWidth>" +
 30             "<LeftMargin>2cm</LeftMargin>" +
 31             "<RightMargin>2cm</RightMargin>" +
 32             "<TopMargin>2cm</TopMargin>" +
 33             "<BottomMargin>2cm</BottomMargin>" +
 34             "<ColumnSpacing>0.13cm</ColumnSpacing>" +
 35             "<Style />" +
 36             "</Page>" +
 37             "<rd:ReportID>809f16cf-ea78-4469-bf43-965c4afe69d0</rd:ReportID>" +
 38             "<rd:ReportUnitType>Cm</rd:ReportUnitType>" +
 39             "</Report>";  40 
 41         protected string TitlePattern =
 42             " <Textbox Name=\"Textbo@TextboxName\"> "
 43             + @"<CanGrow>true</CanGrow>  44  <KeepTogether>true</KeepTogether>  45  <Paragraphs>  46  <Paragraph>  47  <TextRuns>  48  <TextRun>  49  <Value>@Title</Value>  50  <Style>@FontStyle</Style>
 51               </TextRun>
 52             </TextRuns>
 53             <Style>@Style</Style>  54  </Paragraph>  55  </Paragraphs>  56  <rd:DefaultName>Textbo@TextboxName</rd:DefaultName>  57  <Top>@TopPositioncm</Top>  58  <Left>1cm</Left>  59  <Height>0.83813cm</Height>  60  <Width>14.35207cm</Width>  61  <ZIndex>1</ZIndex>  62  <Style>  63  <Border>  64  <Style>None</Style>  65  </Border>  66  <PaddingLeft>2pt</PaddingLeft>  67  <PaddingRight>2pt</PaddingRight>  68  <PaddingTop>2pt</PaddingTop>  69  <PaddingBottom>2pt</PaddingBottom>  70  </Style>  71  </Textbox>";  72 
 73         #endregion
 74 
 75         protected ReportViewer _report;  76         protected List<ReportColoumStyle> _coloumStyle = new List<ReportColoumStyle>();  77         protected List<ReportItemPattern> _reportItemPatterns = new List<ReportItemPattern>();  78         protected List<string> _reportTitlePatterns = new List<string>();  79         protected const float ColoumWidth = 2.0F; //行宽
 80         public ReportType ReportType { get; set; }  81 
 82         public DynamicReport()  83  {  84 
 85  }  86 
 87         /// <summary>
 88         /// 从现有报表中加载报表并进行修改  89         /// </summary>
 90         /// <param name="url"></param>
 91         public void LoadReport(string url)  92  {  93             try
 94  {  95                 _docTemplate = File.ReadAllText(url);  96  }  97             catch (Exception ex)  98  {  99 
100  } 101  } 102         
103         public void SetReport(ReportViewer reportViewer) 104  { 105             this._report = reportViewer; 106  } 107         
108         public void SetColoumStyle(List<ReportColoumStyle> coloumStyle) 109  { 110             this._coloumStyle = coloumStyle; 111  } 112 
113         public void AddText(string title) 114  { 115             if (!string.IsNullOrEmpty(title)) 116  { 117                 var pos = CaculatePlacePostion(); 118                 var titlePattern = TitlePattern 119                     .Replace("@Title", title) 120                     .Replace("@TopPosition", pos.ToString()) 121                     .Replace("@TextboxName", _reportTitlePatterns.Count.ToString()) 122                     .Replace("@FontStyle", "<FontFamily>微软雅黑</FontFamily><FontSize>12pt</FontSize>") 123                     .Replace("@Style", "<TextAlign>Center</TextAlign>"); 124  _reportTitlePatterns.Add(titlePattern); 125  } 126  } 127 
128         public void AddTitle(string title, int chapterGrade) 129  { 130             if (!string.IsNullOrEmpty(title)) 131  { 132                 var pos = CaculatePlacePostion(); 133                 var titlePattern = TitlePattern 134                     .Replace("@Title", title) 135                     .Replace("@TopPosition", pos.ToString()) 136                     .Replace("@TextboxName", _reportTitlePatterns.Count.ToString()); 137                 switch (chapterGrade) 138  { 139                     case 1: 140                         titlePattern = titlePattern.Replace("@FontStyle", 141                                                             "<FontFamily>宋体</FontFamily><FontSize>18pt</FontSize><Color>#000000</Color>") 142                                                             .Replace("@Style", "<TextAlign>Center</TextAlign>"); 143                         break; 144                     case 2: 145                         titlePattern = titlePattern.Replace("@FontStyle", 146                                                             "<FontFamily>黑体</FontFamily><FontSize>14pt</FontSize><Color>#000000</Color>") 147                                                             .Replace("@Style", "<TextAlign>Left</TextAlign>"); 148                         break; 149                     case 3: 150                         titlePattern = titlePattern.Replace("@FontStyle", 151                                                             "<FontFamily>宋体</FontFamily><FontSize>12pt</FontSize><FontWeight>Bold</FontWeight>") 152                                                             .Replace("@Style", "<TextAlign>Left</TextAlign>"); 153                         break; 154                     default: 155                     case 10: 156                         titlePattern = titlePattern.Replace("@FontStyle", 157                                                             "<FontFamily>宋体</FontFamily><FontSize>12pt</FontSize>") 158                                                             .Replace("@Style", "<LineHeight>22pt</LineHeight>"); 159                         break; 160  } 161  _reportTitlePatterns.Add(titlePattern); 162  } 163  } 164 
165         public void AddData<T>(IEnumerable<T> data) 166  { 167             if (data.Count() != 0) 168  { 169                 var properites = typeof(T).GetProperties();//得到实体类属性的集合
170                 AddReportItemPattern(properites.Select(p=>p.Name).ToArray(), data); 171  } 172  } 173 
174         public void AddData(DataTable dataTable) 175  { 176             if (dataTable!=null) 177  { 178                 var coloumNames = new List<string>(); 179                 foreach (DataColumn dataColumn in dataTable.Columns) 180  { 181                     var protertyName = dataColumn.ColumnName; 182  coloumNames.Add(protertyName); 183  } 184  AddReportItemPattern(coloumNames.ToArray(), dataTable); 185  } 186  } 187 
188         /// <summary>
189         /// 计算开始摆放的位置 190         /// </summary>
191         /// <returns></returns>
192         protected float CaculatePlacePostion() 193  { 194             float titleCount = _reportTitlePatterns.Count * 1f; 195             float itemCount = _reportItemPatterns.Count * 2f; 196             switch (ReportType) 197  { 198                     case ReportType.Tables: 199                         return titleCount + itemCount + 0.5f; 200                     case ReportType.Chart: 201                     case ReportType.Finally: 202                         return titleCount + itemCount + 25.7f; 203  } 204             return 0f; 205  } 206 
207         /// <summary>
208         /// 增加一个报表 209         /// </summary>
210         /// <param name="coloumName"></param>
211         protected void AddReportItemPattern(string[] coloumNames, dynamic data) 212  { 213             var fields = new StringBuilder(); 214             var coloums = new StringBuilder(); 215             var tablixHearders = new StringBuilder(); 216             var tablixCells = new StringBuilder(); 217             var tablixMembers = new StringBuilder(); 218             var currentNamePrefix = _reportItemPatterns.Count + 1; 219             var tableWidth = 0F; 220 
221             foreach (var coloumName in coloumNames) 222  { 223                 var coloumWidth = ColoumWidth; 224                 var reportColoumStyle = _coloumStyle.FirstOrDefault(r => r.ColoumName == coloumName); 225                 if (reportColoumStyle != null) 226                     coloumWidth = reportColoumStyle.ColoumWidth; 227                 tableWidth += coloumWidth; 228                 
229  fields.AppendFormat( 230                     "<Field Name=\"{0}\"><DataField>{0}</DataField><rd:TypeName>System.String</rd:TypeName></Field>", 231  coloumName); 232                 coloums.AppendFormat("<TablixColumn><Width>{0}cm</Width></TablixColumn>", coloumWidth); 233                 tablixHearders.AppendFormat("<TablixCell><CellContents>" +
234                                             "<Textbox Name=\"Textbox{0}{1}\"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph>" +
235                                             "<TextRuns><TextRun><Value>{0}</Value><Style /></TextRun></TextRuns><Style><TextAlign>Center</TextAlign></Style></Paragraph></Paragraphs>" +
236                                             "<rd:DefaultName>Textbox{0}{1}</rd:DefaultName><Style><Border><Color>LightGrey</Color><Style>Solid</Style></Border>" +
237                                             "<PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell>", coloumName, currentNamePrefix); 238                 tablixCells.AppendFormat("<TablixCell><CellContents><Textbox Name=\"{0}{1}1\"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether>" +
239                                           "<Paragraphs><Paragraph><TextRuns><TextRun><Value>=Fields!{0}.Value</Value><Style /></TextRun></TextRuns><Style /></Paragraph></Paragraphs>" + 240 "<rd:DefaultName>{0}{1}1</rd:DefaultName><Style><Border><Color>LightGrey</Color><Style>Solid</Style></Border>" +
241                                           "<PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell>", coloumName,currentNamePrefix); 242 
243                 tablixMembers.AppendFormat("<TablixMember />"); 244  } 245 
246             //计算表格应该离左边多少距离
247             var leftPosition = 0F; 248             if (tableWidth < 17) 249  { 250 leftPosition = (17F - tableWidth)/2; 251  } 252 253 var dataSetName = string.Format("Data{0}", _reportItemPatterns.Count + 1); 254 var reportItemPattern = new ReportItemPattern(); 255 reportItemPattern.Data = data; 256 reportItemPattern.DataSetName = dataSetName; 257 reportItemPattern.DataSetString = 258  reportItemPattern.DataSetPattern 259 .Replace("@DataSetName", dataSetName) 260 .Replace("@Fields", fields.ToString()); 261 reportItemPattern.TablixString = 262  reportItemPattern.TablixPattern 263 .Replace("@DataSetName", dataSetName) 264 .Replace("@TablixColumns", coloums.ToString()) 265 .Replace("@TablixHeader", tablixHearders.ToString()) 266 .Replace("@TablixCells", tablixCells.ToString()) 267 .Replace("@TablixMember", tablixMembers.ToString()) 268 .Replace("@TopPosition", CaculatePlacePostion().ToString()) 269 .Replace("@LeftPostion", leftPosition.ToString()); 270 271  _reportItemPatterns.Add(reportItemPattern); 272  } 273 274 public void ShowReport() 275  { 276 //将每一个patter转换 277 if (_reportItemPatterns.Count > 0 || _reportTitlePatterns.Count > 0) 278  { 279                 var dataSetsString = new StringBuilder(); 280                 var tablixString = new StringBuilder(); 281 
282                 foreach (var reportItemPattern in _reportItemPatterns) 283  { 284  dataSetsString.Append(reportItemPattern.DataSetString); 285  tablixString.Append(reportItemPattern.TablixString); 286  } 287 
288                 var reportTitleString = new StringBuilder(); 289                 foreach (var reportTitlePattern in _reportTitlePatterns) 290  { 291  reportTitleString.Append(reportTitlePattern); 292  } 293 
294                 //把文档中的文字替换掉
295                 switch (ReportType) 296  { 297                     case ReportType.Tables: 298                         _docTemplate = _docTemplate.Replace("@DataSets", dataSetsString.ToString()) 299                                                    .Replace("@Tablix", tablixString.ToString()) 300                                                    .Replace("@Title", reportTitleString.ToString()); 301                         break; 302                     case ReportType.Chart: 303                         break; 304                     case ReportType.Finally: 305                         //替换datasetstring
306                         var pos = _docTemplate.IndexOf("<Body>", StringComparison.Ordinal); 307                         _docTemplate = _docTemplate.Insert(pos, string.Format("<DataSources><DataSource Name=\"DummyDataSource\"><ConnectionProperties><DataProvider>SQL</DataProvider><ConnectString /></ConnectionProperties><rd:DataSourceID>3eecdab9-6b4b-4836-ad62-95e4aee65ea8</rd:DataSourceID></DataSource></DataSources><DataSets>{0}</DataSets>", dataSetsString)); 308                         //替换Tablix
309                         pos = _docTemplate.IndexOf("<ReportItems>", StringComparison.Ordinal); 310                         _docTemplate = _docTemplate.Insert(pos + 13, tablixString.ToString()); 311                         //替换title
312                         _docTemplate = _docTemplate.Insert(pos + 13, reportTitleString.ToString()); 313                         break; 314  } 315 
316                 var doc = new XmlDocument(); 317  doc.LoadXml(_docTemplate); 318                 Stream stream = GetRdlcStream(doc); 319 
320                 //加载报表定义
321  _report.LocalReport.LoadReportDefinition(stream); 322  _report.LocalReport.DataSources.Clear(); 323                 foreach (var reportItemPattern in _reportItemPatterns) 324  { 325  _report.LocalReport.DataSources 326                            .Add(new ReportDataSource(reportItemPattern.DataSetName + "Data", 327  reportItemPattern.Data)); 328  } 329                
330  _report.LocalReport.Refresh(); 331  } 332  } 333         
334         /// <summary>
335         /// 序列化到内存流 336         /// </summary>
337         /// <returns></returns>
338         protected Stream GetRdlcStream(XmlDocument xmlDoc) 339  { 340             Stream ms = new MemoryStream(); 341             XmlSerializer serializer = new XmlSerializer(typeof(XmlDocument)); 342  serializer.Serialize(ms, xmlDoc); 343 
344             ms.Position = 0; 345             return ms; 346  } 347     }
View Code


调用方法一(使用内置的空报表模板):

//new一个报表类对象
  var dynamicReport = new DynamicReport {ReportType = ReportType.Tables};
 //设置报表为本地报表
  dynamicReport.SetReport(this.ReportViewer1);
 //设置列宽度和对齐方式(可选)
  dynamicReport.SetColoumStyle(new List<ReportColoumStyle>()
     {
         new ReportColoumStyle(){ColoumName = "专业名称", ColoumWidth = 4F},
         new ReportColoumStyle() {ColoumName = "学院", ColoumWidth = 3.5F},
         new ReportColoumStyle(){ColoumName = "就业去向", ColoumWidth = 4F},
     });
 //加入标题
 dynamicReport.AddText(module.ModuleName);
 //加入数据
 dynamicReport.AddData(data);
 //设置导出报表的名称
  ReportViewer1.LocalReport.DisplayName = module.ModuleName;
 //处理报表数据并显示
  dynamicReport.ShowReport();


调用方法二(载入已有的报表,并且添加相关数据):

//new一个报表类对象
  var dynamicReport = new DynamicReport ();
 report.ReportType = ReportType.Finally;
 //读取报表模板(模板内不能有其他数据源等)
  report.LoadReport(Server.MapPath("~/ChapterReport/ReportView.rdlc"));
 //设置报表为本地报表
  dynamicReport.SetReport(this.ReportViewer1);
 //设置列宽度和对齐方式(可选)
  dynamicReport.SetColoumStyle(new List<ReportColoumStyle>()
     {
         new ReportColoumStyle(){ColoumName = "专业名称", ColoumWidth = 4F},
         new ReportColoumStyle() {ColoumName = "学院", ColoumWidth = 3.5F},
         new ReportColoumStyle(){ColoumName = "就业去向", ColoumWidth = 4F},
     });
 //加入标题
 dynamicReport.AddText(module.ModuleName);
 //加入数据
 dynamicReport.AddData(data);

 
 //加入其它标题
  dynamicReport.AddTitle("其它文字", 1);
 //加入其它数据
 dynamicReport.AddData(data2);

 ................

 //设置导出报表的名称
  ReportViewer1.LocalReport.DisplayName = "......";
 //处理报表数据并显示
  dynamicReport.ShowReport();

你可能感兴趣的:(报表,Reportview)