原文 http://www.cnblogs.com/thanks/p/DynamicReport.html
在实际工作中,当需要进行大批量查询和生成报表的时候,可以使用我写的类。
特点:
我没有采用使用操纵微软报表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();