分享一个动态生成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();
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值