了解了RDLC报表的结构后,我们就来把传递进来的数据转变成符合RDLC报表结构的xml格式文档,用一个类的形式来做,方便以后调用。
这个报表是按我项目的需要来做的,基本要求:
1、可以设置页面大小、边距、字体、数据表样式;
2、可以做多维表头和统计;
3、可以添加多个数据表和标题;
4、可以自动签名、盖章。
基础的代码如下:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Xml;
- using System.Data;
- using Microsoft.Reporting.WinForms;
- using System.Text;
- using System.Collections;
- using System.IO;
- using System.Reflection;
- using System.Xml.Serialization;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Drawing.Printing;
- using System.Drawing.Imaging;
-
- namespace RDLC
- {
- public class DynamicReport : IDynamicReport
- {
- //需要一个ReportViewer来接收送递进来的ReportViewer加载RDLC
- private ReportViewer _report;
- private string languageCode = "zh_CHS";
- private string totalString = "合计:";
- private string notesString = "备注:";
- //设置字体和大小
- private string fontString = "微软雅黑";
- private int fontSize = 9;
- //设置页面大小
- private float pageWidth = 21.0F;
- private float pageHeight = 29.7F;
- //设置上边距和左边距,右边和下边就不用设置了,一般是对称的
- private float topMargin = 0.8F;
- private float leftMargin = 1.5F;
-
- #region 参数设置
- public string LanguageCode
- {
- get { return languageCode; }
- set
- {
- languageCode = value;
- if (languageCode == "zh_CHT")
- {
- totalString = "合計:";
- notesString = "備註:";
- }
- else if (languageCode == "en")
- {
- totalString = "Total:";
- notesString = "Remark:";
- }
- else
- {
- totalString = "合计:";
- notesString = "备注:";
- }
- }
- }
- public string FontString
- {
- get { return fontString; }
- set { fontString = value; }
- }
- public int FontSize
- {
- get { return fontSize; }
- set { fontSize = value; }
- }
- public float PageHeight
- {
- get { return pageHeight; }
- set { pageHeight = value; }
- }
- public float PageWidth
- {
- get { return pageWidth; }
- set { pageWidth = value; }
- }
- public float LeftMargin
- {
- get { return leftMargin; }
- set { leftMargin = value; }
- }
- public float TopMargin
- {
- get { return topMargin; }
- set { topMargin = value; headerHeight = value; }
- }
- #endregion
-
- public DynamicReport()
- {
- }
- }
- }
这里继承了一个IDynamicReport接口
- public interface IDynamicReport
- {
- void SetReport(ReportViewer reportViewer, DisplayMode displayMode = DisplayMode.PrintLayout, ZoomMode zoomMode = ZoomMode.PageWidth);
- void AddData(DataTable dataTable, string totalColumn);
- void ShowReport();
- void LoadReport(string reportPath);
- void SetColoumStyle(List
coloumStyle ); - }
需要为表格的样式增加一个辅助类和枚举,这样主涌方便地设置表格的样式。
- public class ReportColoumStyle
- {
- public string ColoumName { get; set; }
- public float ColoumWidth { get; set; }
- public TextAlign TextAlign { get; set; }
- public ConsoleColor ConsoleColor { get; set; }
- public Boolean IsShortDate { get; set; }
-
- public ReportColoumStyle()
- {
- ColoumWidth = DynamicReport.ColoumWidth;
- }
- }
-
- public enum TextAlign
- {
- Left,
- Center,
- Right
- }
接下来就是主体部分了,先来定义一个空白的包含RDLC所需节点的xml文档来做模板,模板中用@XXX来表示相应的节点内容,比如@DataSets、@Tablix分别代表要设置的数据源中的数据表和
中要显示的数据表格,后面会用传递进来的数据替换。- protected string _docTemplate =
- "" +
- "<Report xmlns:rd=\"http://schemas.microsoft.com/SQLServer/reporting/reportdesigner\" xmlns=\"http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition\">" +
- "<DataSources>" +
- " <DataSource Name=\"DummyDataSource\">" +
- " <ConnectionProperties>" +
- " <DataProvider>SQLDataProvider>" +
- " <ConnectString />" +
- " ConnectionProperties>" +
- " <rd:DataSourceID>3eecdab9-6b4b-4836-ad62-95e4aee65ea8rd:DataSourceID>" +
- " DataSource>" +
- "DataSources>" +
- "<DataSets>@DataSetsDataSets>" +
- "<Body>" +
- "<ReportItems>@Tablix" +
- "ReportItems>" +
- "<Style />" +
- "<Height>1cmHeight>" +
- "Body>" +
- "<Width>3cmWidth>" +
- "<Page>" +
- " <PageHeader>" +
- " <Height>@HeaderHeightcmHeight>" +
- " <PrintOnFirstPage>truePrintOnFirstPage>" +
- " <PrintOnLastPage>truePrintOnLastPage>" +
- " <ReportItems>@PageHeaderReportItems>" +
- " <Style>" +
- " <Border>" +
- " <Style>NoneStyle>" +
- " Border>" +
- " Style>" +
- " PageHeader>" +
- " <PageFooter>" +
- " <Height>@FooterHeightcmHeight>" +
- " <PrintOnFirstPage>truePrintOnFirstPage>" +
- " <PrintOnLastPage>truePrintOnLastPage>" +
- " <ReportItems>@PageFooterReportItems>" +
- " <Style>" +
- " <Border>" +
- " <Style>NoneStyle>" +
- " Border>" +
- " Style>" +
- " PageFooter>" +
- " <PageWidth>21.0cmPageWidth>" +
- " <PageHeight>29.7cmPageHeight>" +
- " <LeftMargin>0.0cmLeftMargin>" +
- " <RightMargin>0.0cmRightMargin>" +
- " <TopMargin>0.0cmTopMargin>" +
- " <BottomMargin>0.0cmBottomMargin>" +
- " <ColumnSpacing>0.13cmColumnSpacing>" +
- " <Style />" +
- "Page>" +
- "<EmbeddedImages>@LogoImageDataEmbeddedImages>" +
- "<rd:ReportID>809f16cf-ea78-4469-bf43-965c4afe69d0rd:ReportID>" +
- "<rd:ReportUnitType>Cmrd:ReportUnitType>" +
- "Report>";
同样地分别给页眉里标签中用到的Textbox、标题中用到的Textbox和签名中的图片定义一个格式
- //标签中用到的Textbox
- protected string LabelPattern =
- " <Textbox Name=\"Name@TextboxName\"> "
- + @"<CanGrow>trueCanGrow>
- <KeepTogether>trueKeepTogether>
- <Paragraphs>
- <Paragraph>
- <TextRuns>
- <TextRun>
- <Value>@NameTextValue>
- <Style><FontFamily>@FontStringFontFamily><FontSize>9ptFontSize>Style>
- TextRun>
- TextRuns>
- <Style><TextAlign>RightTextAlign>Style>
- Paragraph>
- Paragraphs>
- <rd:DefaultName>Name@TextboxNamerd:DefaultName>
- <Top>@TopPositioncmTop>
- <Left>@NamePositioncmLeft>
- <Height>0.5cmHeight>
- <Width>@NameWidthcmWidth>
- <ZIndex>1ZIndex>
- <Style>
- <Border>
- <Style>NoneStyle>
- Border>
- <VerticalAlign>MiddleVerticalAlign>
- <PaddingLeft>0ptPaddingLeft>
- <PaddingRight>2ptPaddingRight>
- <PaddingTop>0ptPaddingTop>
- <PaddingBottom>0ptPaddingBottom>
- Style>
- Textbox>" +
- " <Textbox Name=\"Split@TextboxName\"> "
- + @"<CanGrow>trueCanGrow>
- <KeepTogether>trueKeepTogether>
- <Paragraphs>
- <Paragraph>
- <TextRuns>
- <TextRun>
- <Value>:Value>
- <Style><FontFamily>@FontStringFontFamily><FontSize>9ptFontSize>Style>
- TextRun>
- TextRuns>
- <Style><TextAlign>LeftTextAlign>Style>
- Paragraph>
- Paragraphs>
- <rd:DefaultName>Split@TextboxNamerd:DefaultName>
- <Top>@TopPositioncmTop>
- <Left>@SplitPositioncmLeft>
- <Height>0.5cmHeight>
- <Width>0.3cmWidth>
- <ZIndex>1ZIndex>
- <Style>
- <Border>
- <Style>NoneStyle>
- Border>
- <VerticalAlign>MiddleVerticalAlign>
- <PaddingLeft>0ptPaddingLeft>
- <PaddingRight>0ptPaddingRight>
- <PaddingTop>0ptPaddingTop>
- <PaddingBottom>0ptPaddingBottom>
- Style>
- Textbox>" +
- " <Textbox Name=\"Value@TextboxName\"> "
- + @"<CanGrow>trueCanGrow>
- <KeepTogether>trueKeepTogether>
- <Paragraphs>
- <Paragraph>
- <TextRuns>
- <TextRun>
- <Value>@ValueTextValue>
- <Style><FontFamily>@FontStringFontFamily><FontSize>9ptFontSize><Color>@ColorColor>Style>
- TextRun>
- TextRuns>
- <Style><TextAlign>LeftTextAlign>Style>
- Paragraph>
- Paragraphs>
- <rd:DefaultName>Value@TextboxNamerd:DefaultName>
- <Top>@TopPositioncmTop>
- <Left>@ValuePositioncmLeft>
- <Height>0.5cmHeight>
- <Width>@ValueWidthcmWidth>
- <ZIndex>1ZIndex>
- <Style>
- <Border>
- <Style>NoneStyle>
- Border>
- <VerticalAlign>MiddleVerticalAlign>
- <PaddingLeft>0ptPaddingLeft>
- <PaddingRight>0ptPaddingRight>
- <PaddingTop>0ptPaddingTop>
- <PaddingBottom>0ptPaddingBottom>
- Style>
- Textbox>";
-
- //标题中用到的Textbox
- protected string TitlePattern =
- " <Textbox Name=\"Title@TextboxName\"> "
- + @"<CanGrow>trueCanGrow>
- <KeepTogether>trueKeepTogether>
- <Paragraphs>
- <Paragraph>
- <TextRuns>
- <TextRun>
- <Value>@TitleValue>
- <Style><FontFamily>@FontStringFontFamily><FontSize>@FontSizeptFontSize><FontWeight>@FontWeightFontWeight><Color>@ColorColor>Style>
- TextRun>
- TextRuns>
- <Style><TextAlign>@TextAlignTextAlign>Style>
- Paragraph>
- Paragraphs>
- <rd:DefaultName>Title@TextboxNamerd:DefaultName>
- <Top>@TopPositioncmTop>
- <Left>@LeftPositioncmLeft>
- <Height>@HeightcmHeight>
- <Width>@WidthcmWidth>
- <ZIndex>1ZIndex>
- <Style>
- <Border>
- <Style>NoneStyle>
- Border>
- <VerticalAlign>BottomVerticalAlign>
- <PaddingLeft>0ptPaddingLeft>
- <PaddingRight>0ptPaddingRight>
- <PaddingTop>0ptPaddingTop>
- <PaddingBottom>0ptPaddingBottom>
- Style>
- Textbox>";
-
- //签名中的图片
- string signaturePattern = " <Image Name=\"EmployeeSignature\">" +
- " <Source>EmbeddedSource>" +
- " <Value>SignatureImgValue>" +
- " <MIMEType>image/pngMIMEType>" +
- " <Sizing>AutoSizeSizing>" +
- " <Top>@TopPositioncmTop>" +
- " <Left>@LeftPositioncmLeft>" +
- " <Height>3.9cmHeight>" +
- " <Width>3.9cmWidth>" +
- " <ZIndex>1ZIndex>" +
- " <Visibility>" +
- " <Hidden>=IIF(First(Fields!Reviewed.Value, \"DataLogoData\")=\"√\", False, True)Hidden>" +
- " Visibility>" +
- " <Style>" +
- " <Border><Style>NoneStyle>Border>" +
- " Style>" +
- " Image>";
当然也对DataSets和Tablix定义一个格式
- internal class ReportItemPattern
- {
- public string DataSetName { get; set; }
- public string DataSetString { get; set; }
- public string TablixString { get; set; }
- public dynamic Data { get; set; }
-
-
- public string DataSetPattern
- {
- get
- {
- return "
\" @DataSetNameData\">" + - "
@Fields " + - "
" + - "
DummyDataSource " + - "
" + - " " +
- " ";
- }
- }
-
- public string TablixPattern
- {
- get
- {
- return "
\" Tablix@DataSetName\">" + - "
" + - "
@TablixColumns " + - "
" + - "
" + - "
0.5cm " + - "
@TablixHeader " + - " " +
- "
" + - "
0.5cm " + - "
@TablixCells " + - " " +
- "@TotalRow" +
- " " +
- " " +
- "
" + - "
@TablixMember " + - " " +
- "
" + - "
" + - "@MergeMember" +
- "
" + - "
After " + - "
true " + - " " +
- "
" + - "
\" 详细信息@DataSetName\" />" + - " " +
- "@TotalMember" +
- " " +
- " " +
- "
@DataSetNameData " + - "
@TopPositioncm " + - "
@LeftPostioncm " + - "
0.5cm " + - "
1.0cm " + - " " +
- " " +
- " " +
- "";
- }
- }
- }
之前已经说了这里的数据列的数据类型全部用字符System.String,可数据库里可不止有字符类别啊,那就用下面的方法来转换,部分值也相应转换一下,比如Bool字段的”True“转换成”√“,数字空值转换成0等等。
- internal static class DynamicReportExtension
- {
- public static dynamic RemoveZeroData(this object data)
- {
- if (data is DataTable) return ((DataTable)data).ChangeEachColumnTypeToString();
- return data;
- }
-
- public static DataTable ChangeEachColumnTypeToString(this DataTable dt)
- {
- DataTable tempdt = new DataTable();
- foreach (DataColumn dc in dt.Columns)
- {
- DataColumn tempdc = new DataColumn();
- tempdc.ColumnName = dc.ColumnName;
- tempdc.DataType = typeof(String);
- tempdt.Columns.Add(tempdc);
- //System.Windows.Forms.MessageBox.Show(dc.DataType.ToString());
- }
- int coloumCount = dt.Columns.Count;
- foreach (DataRow dr in dt.Rows)
- {
- var newrow = tempdt.NewRow();
- for (int i = 0; i < coloumCount; i++)
- {
- var value = dr[i].ToString();
- switch (value)
- {
- case "":
- if (dt.Columns[i].DataType.ToString().IndexOf("System.Int") > -1) newrow[i] = "0";
- if (dt.Columns[i].DataType.ToString().IndexOf("System.Decimal") > -1) newrow[i] = "0.00";
- break;
- case "True":
- newrow[i] = "√";
- break;
- case "False":
- newrow[i] = "-";
- break;
- case "0.00%":
- newrow[i] = "-";
- break;
- default:
- newrow[i] = value;
- break;
- }
- }
- tempdt.Rows.Add(newrow);
- }
- return tempdt;
- }
- }
到此,主体的基础部分已经完成,下面就是操作相应的节点处理了。