运行时动态创建报表(三)rdlc报表文件结构与ReportDefinition类

来源:互联网 发布:精仿苹果6s淘宝网 编辑:程序博客网 时间:2024/05/18 21:10

用记事本打开rdlc报表文件,可以看出文件是xml文件。文件前两行为<?xml version="1.0"?>
<Report xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition">,最后面的xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition是文件的命名空间,我们的类ReportDefinition就是从这个命名空间转换过来的,如何转换网上有说明。可以简单的说,rdlc文件就是ReportDefinition类的实例xml序列化后的结果。下面我们通过对比两个文件来分析。

首先看一下rdlc文件的结构

<?xml version="1.0"?>
<Report xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition">
  <DataSources>
    <DataSource Name="DummyDataSource">
      <ConnectionProperties>
        <ConnectString />
        <DataProvider>SQL</DataProvider>
      </ConnectionProperties>
    </DataSource>
  </DataSources>
  <Body>
    <ReportItems>
      <Matrix Name="Matrix1">
        <ColumnGroupings>
          <ColumnGrouping>
            <Height>11pt</Height>
            <DynamicColumns>
              <Grouping Name="Matrix1_Group1">
                <GroupExpressions>
                  <GroupExpression>=Fields!wastation.Value</GroupExpression>
                </GroupExpressions>
              </Grouping>
              <Subtotal>
                <ReportItems>
                  <Textbox Name="Textbox1">
                    <Value>总计</Value>
                    <CanGrow>true</CanGrow>
                    <Style>
                      <BackgroundColor>#DAE9F3</BackgroundColor>
                      <BorderColor>
                        <Default>#74A4D4</Default>
                      </BorderColor>
                      <BorderStyle>
                        <Default>Solid</Default>
                      </BorderStyle>
                      <FontFamily>Tahoma</FontFamily>
                      <FontSize>8pt</FontSize>
                      <TextAlign>Center</TextAlign>
                      <VerticalAlign>Middle</VerticalAlign>
                      <BorderWidth>
                        <Default>0.5pt</Default>
                      </BorderWidth>
                    </Style>
                  </Textbox>
                </ReportItems>
              </Subtotal>
              <ReportItems>
                <Textbox Name="Textbox2">
                  <Value>=Fields!wastation.Value</Value>
                  <CanGrow>true</CanGrow>
                  <Style>
                    <BackgroundColor>#DAE9F3</BackgroundColor>
                    <BorderColor>
                      <Default>#74A4D4</Default>
                    </BorderColor>
                    <BorderStyle>
                      <Default>Solid</Default>
                    </BorderStyle>
                    <FontFamily>Tahoma</FontFamily>
                    <FontSize>8pt</FontSize>
                    <TextAlign>Center</TextAlign>
                    <VerticalAlign>Middle</VerticalAlign>
                    <BorderWidth>
                      <Default>0.5pt</Default>
                    </BorderWidth>
                  </Style>
                </Textbox>
              </ReportItems>
            </DynamicColumns>
          </ColumnGrouping>
        </ColumnGroupings>
        <RowGroupings>
          <RowGrouping>
            <Width>0.75in</Width>
            <DynamicRows>
              <Grouping Name="Matrix1_Group2">
                <GroupExpressions>
                  <GroupExpression>=Fields!regdate.Value</GroupExpression>
                </GroupExpressions>
              </Grouping>
              <Subtotal>
                <ReportItems>
                  <Textbox Name="Textbox3">
                    <Value>总计</Value>
                    <CanGrow>true</CanGrow>
                    <Style>
                      <BackgroundColor>#DAE9F3</BackgroundColor>
                      <BorderColor>
                        <Default>#74A4D4</Default>
                      </BorderColor>
                      <BorderStyle>
                        <Default>Solid</Default>
                      </BorderStyle>
                      <FontFamily>Tahoma</FontFamily>
                      <FontSize>8pt</FontSize>
                      <TextAlign>Center</TextAlign>
                      <VerticalAlign>Middle</VerticalAlign>
                      <BorderWidth>
                        <Default>0.5pt</Default>
                      </BorderWidth>
                    </Style>
                  </Textbox>
                </ReportItems>
              </Subtotal>
              <ReportItems>
                <Textbox Name="Textbox4">
                  <Value>=Fields!regdate.Value</Value>
                  <CanGrow>true</CanGrow>
                  <Style>
                    <BackgroundColor>#DAE9F3</BackgroundColor>
                    <BorderColor>
                      <Default>#74A4D4</Default>
                    </BorderColor>
                    <BorderStyle>
                      <Default>Solid</Default>
                    </BorderStyle>
                    <FontFamily>Tahoma</FontFamily>
                    <FontSize>8pt</FontSize>
                    <TextAlign>Center</TextAlign>
                    <VerticalAlign>Middle</VerticalAlign>
                    <BorderWidth>
                      <Default>0.5pt</Default>
                    </BorderWidth>
                  </Style>
                </Textbox>
              </ReportItems>
            </DynamicRows>
          </RowGrouping>
        </RowGroupings>
        <MatrixRows>
          <MatrixRow>
            <Height>11pt</Height>
            <MatrixCells>
              <MatrixCell>
                <ReportItems>
                  <Textbox Name="Textbox5">
                    <Value>=Count(Fields!barcode.Value)</Value>
                    <CanGrow>true</CanGrow>
                    <Style>
                      <BorderColor>
                        <Default>#74A4D4</Default>
                      </BorderColor>
                      <BorderStyle>
                        <Default>Solid</Default>
                      </BorderStyle>
                      <FontFamily>Tahoma</FontFamily>
                      <FontSize>8pt</FontSize>
                      <VerticalAlign>Middle</VerticalAlign>
                      <Format>0</Format>
                      <BorderWidth>
                        <Default>0.5pt</Default>
                      </BorderWidth>
                    </Style>
                  </Textbox>
                </ReportItems>
              </MatrixCell>
            </MatrixCells>
          </MatrixRow>
        </MatrixRows>
        <MatrixColumns>
          <MatrixColumn>
            <Width>0.75in</Width>
          </MatrixColumn>
        </MatrixColumns>
        <Corner>
          <ReportItems>
            <Textbox Name="Textbox6">
              <Value>日期/窗口</Value>
              <CanGrow>true</CanGrow>
            </Textbox>
          </ReportItems>
        </Corner>
        <Left>5pt</Left>
        <Top>5pt</Top>
      </Matrix>
    </ReportItems>
    <Height>1in</Height>
  </Body>
  <DataSets>
    <DataSet Name="MyData">
      <Query>
        <DataSourceName>DummyDataSource</DataSourceName>
        <CommandText />
      </Query>
      <Fields>
        <Field Name="barcode">
          <DataField>barcode</DataField>
        </Field>
        <Field Name="regdate">
          <DataField>regdate</DataField>
        </Field>
        <Field Name="category">
          <DataField>category</DataField>
        </Field>
        <Field Name="wastation">
          <DataField>wastation</DataField>
        </Field>
        <Field Name="printer">
          <DataField>printer</DataField>
        </Field>
        <Field Name="catename">
          <DataField>catename</DataField>
        </Field>
        <Field Name="logname">
          <DataField>logname</DataField>
        </Field>
      </Fields>
    </DataSet>
  </DataSets>
  <Width>10in</Width>
</Report

上面是一个包含了一个matrix(矩阵)的报表文件。每一报表文件包含的基本元素有DataSources、DataSets、Body。DataSources、和DataSets是数据源的定义,包括怎样连接数据库、有哪些字段,不过在动态创建报表中我们只需要知道有哪些字段就可以了。最主要的是如何创建body。body下包含多个   ReportItems,每个   ReportItems包含一个报表方式如table、matrix、chart。

下面再看一下ReportDefinition文件,


    /// <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;
       
        private ItemsChoiceType37[] itemsElementNameField;
       
        private System.Xml.XmlAttribute[] anyAttrField;
       
        /// <remarks/>
        [System.Xml.Serialization.XmlAnyElementAttribute()]
        [System.Xml.Serialization.XmlElementAttribute("Author", typeof(string))]
        [System.Xml.Serialization.XmlElementAttribute("AutoRefresh", typeof(uint))]
        [System.Xml.Serialization.XmlElementAttribute("Body", typeof(BodyType))]
        [System.Xml.Serialization.XmlElementAttribute("BottomMargin", typeof(string), DataType="normalizedString")]
        [System.Xml.Serialization.XmlElementAttribute("Classes", typeof(ClassesType))]
        [System.Xml.Serialization.XmlElementAttribute("Code", typeof(string))]
        [System.Xml.Serialization.XmlElementAttribute("CodeModules", typeof(CodeModulesType))]
        [System.Xml.Serialization.XmlElementAttribute("CustomProperties", typeof(CustomPropertiesType))]
        [System.Xml.Serialization.XmlElementAttribute("DataElementName", typeof(string))]
        [System.Xml.Serialization.XmlElementAttribute("DataElementStyle", typeof(ReportDataElementStyle))]
        [System.Xml.Serialization.XmlElementAttribute("DataSchema", typeof(string))]
        [System.Xml.Serialization.XmlElementAttribute("DataSets", typeof(DataSetsType))]
        [System.Xml.Serialization.XmlElementAttribute("DataSources", typeof(DataSourcesType))]
        [System.Xml.Serialization.XmlElementAttribute("DataTransform", typeof(string))]
        [System.Xml.Serialization.XmlElementAttribute("Description", typeof(string))]
        [System.Xml.Serialization.XmlElementAttribute("EmbeddedImages", typeof(EmbeddedImagesType))]
        [System.Xml.Serialization.XmlElementAttribute("InteractiveHeight", typeof(string), DataType="normalizedString")]
        [System.Xml.Serialization.XmlElementAttribute("InteractiveWidth", typeof(string), DataType="normalizedString")]
        [System.Xml.Serialization.XmlElementAttribute("Language", typeof(string))]
        [System.Xml.Serialization.XmlElementAttribute("LeftMargin", typeof(string), DataType="normalizedString")]
        [System.Xml.Serialization.XmlElementAttribute("PageFooter", typeof(PageHeaderFooterType))]
        [System.Xml.Serialization.XmlElementAttribute("PageHeader", typeof(PageHeaderFooterType))]
        [System.Xml.Serialization.XmlElementAttribute("PageHeight", typeof(string), DataType="normalizedString")]
        [System.Xml.Serialization.XmlElementAttribute("PageWidth", typeof(string), DataType="normalizedString")]
        [System.Xml.Serialization.XmlElementAttribute("ReportParameters", typeof(ReportParametersType))]
        [System.Xml.Serialization.XmlElementAttribute("RightMargin", typeof(string), DataType="normalizedString")]
        [System.Xml.Serialization.XmlElementAttribute("TopMargin", typeof(string), DataType="normalizedString")]
        [System.Xml.Serialization.XmlElementAttribute("Width", typeof(string), DataType="normalizedString")]
        [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]
        public object[] Items {
            get {
                return this.itemsField;
            }
            set {
                this.itemsField = value;
            }
        }
       
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("ItemsElementName")]
        [System.Xml.Serialization.XmlIgnoreAttribute()]
        public ItemsChoiceType37[] ItemsElementName {
            get {
                return this.itemsElementNameField;
            }
            set {
                this.itemsElementNameField = value;
            }
        }
       
        /// <remarks/>
        [System.Xml.Serialization.XmlAnyAttributeAttribute()]
        public System.Xml.XmlAttribute[] AnyAttr {
            get {
                return this.anyAttrField;
            }
            set {
                this.anyAttrField = value;
            }
        }
    }

上面是report类的定义,可以看到此类是可以序列化的。report包含很多XmlElementAttribute,每个XmlElementAttribute都有自己的类型,有些是基本类型,有些是reportdefinition文件中定义的类型。System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]告诉我们何以选择性的实现这些XmlElementAttribute的一部分。刚才我已经将了redlc报表文件基本的元素包括DataSources、DataSets、Body,那么我们只要实现DataSources、DataSets、Body这三个元素基本上就可以创建一个报表文件了,如下

        private Rdl.Report CreateReport(int reportType)
        {
            Rdl.Report report = new Rdl.Report();
            report.Items = new object[]
                {
                    CreateDataSources(),
                    CreateBody(reportType ),
                    CreateDataSets(),
                    m_widthInches + "in",
                };
            report.ItemsElementName = new Rdl.ItemsChoiceType37[]
                {
                    Rdl.ItemsChoiceType37.DataSources,
                    Rdl.ItemsChoiceType37.Body,
                    Rdl.ItemsChoiceType37.DataSets,
                    Rdl.ItemsChoiceType37.Width,
                };
            return report;
        }

                   CreateDataSources(),                  CreateBody(reportType ),                    CreateDataSets(),在我上传的资源中有。我先介绍一下CreateBody(reportType ),reporttype是报表类型(table、matrix、chart

在前面我讲了每个body里包含很多ReportItems,看一下reportdefinition文件中BodyType 的定义

   /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition")]
    public partial class BodyType {
       
        private object[] itemsField;
       
        private ItemsChoiceType30[] itemsElementNameField;
       
        private System.Xml.XmlAttribute[] anyAttrField;
       
        /// <remarks/>
        [System.Xml.Serialization.XmlAnyElementAttribute()]
        [System.Xml.Serialization.XmlElementAttribute("ColumnSpacing", typeof(string), DataType="normalizedString")]
        [System.Xml.Serialization.XmlElementAttribute("Columns", typeof(uint))]
        [System.Xml.Serialization.XmlElementAttribute("Height", typeof(string), DataType="normalizedString")]
        [System.Xml.Serialization.XmlElementAttribute("ReportItems", typeof(ReportItemsType))]
        [System.Xml.Serialization.XmlElementAttribute("Style", typeof(StyleType))]
        [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]
        public object[] Items {
            get {
                return this.itemsField;
            }
            set {
                this.itemsField = value;
            }
        }
       
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("ItemsElementName")]
        [System.Xml.Serialization.XmlIgnoreAttribute()]
        public ItemsChoiceType30[] ItemsElementName {
            get {
                return this.itemsElementNameField;
            }
            set {
                this.itemsElementNameField = value;
            }
        }
       
        /// <remarks/>
        [System.Xml.Serialization.XmlAnyAttributeAttribute()]
        public System.Xml.XmlAttribute[] AnyAttr {
            get {
                return this.anyAttrField;
            }
            set {
                this.anyAttrField = value;
            }
        }
    }

在众多XmlElementAttribute我们可以选择性的实现reportitmes,如下代码

       private Rdl.BodyType CreateBody(int reportType)
        {
            Rdl.BodyType body = new Rdl.BodyType();
            body.Items = new object[]
                {
                    CreateReportItems(reportType ),
                    "1in",
                };
            body.ItemsElementName = new Rdl.ItemsChoiceType30[]
                {
                    Rdl.ItemsChoiceType30.ReportItems,
                    Rdl.ItemsChoiceType30.Height,
                };
            return body;
        }
这样我们就将body创建好了,而如何实现CreateReportItems()呢,我们在首先看ReportItems的定义

    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition")]
    public partial class ReportItemsType {
       
        private object[] itemsField;
       
        private System.Xml.XmlAttribute[] anyAttrField;
       
        /// <remarks/>
        [System.Xml.Serialization.XmlAnyElementAttribute()]
        [System.Xml.Serialization.XmlElementAttribute("Chart", typeof(ChartType))]
        [System.Xml.Serialization.XmlElementAttribute("CustomReportItem", typeof(CustomReportItemType))]
        [System.Xml.Serialization.XmlElementAttribute("Image", typeof(ImageType))]
        [System.Xml.Serialization.XmlElementAttribute("Line", typeof(LineType))]
        [System.Xml.Serialization.XmlElementAttribute("List", typeof(ListType))]
        [System.Xml.Serialization.XmlElementAttribute("Matrix", typeof(MatrixType))]
        [System.Xml.Serialization.XmlElementAttribute("Rectangle", typeof(RectangleType))]
        [System.Xml.Serialization.XmlElementAttribute("Subreport", typeof(SubreportType))]
        [System.Xml.Serialization.XmlElementAttribute("Table", typeof(TableType))]
        [System.Xml.Serialization.XmlElementAttribute("Textbox", typeof(TextboxType))]
        public object[] Items {
            get {
                return this.itemsField;
            }
            set {
                this.itemsField = value;
            }
        }
       
        /// <remarks/>
        [System.Xml.Serialization.XmlAnyAttributeAttribute()]
        public System.Xml.XmlAttribute[] AnyAttr {
            get {
                return this.anyAttrField;
            }
            set {
                this.anyAttrField = value;
            }
        }
    }

reportitems包含了报表的元素如table、matrix、chart、textbox,我们可以实现一个也可以实现多个元素,我们目前只根据实现其中的一种,如table,我们通过CreateTable()来实现,如何实现呢,大家通过上面的介绍应该可以看出一些门道,我们只要按照reportdefinition的定义来实现就可以了。

       private Rdl.ReportItemsType CreateReportItems(int reportType)
        {
            Rdl.ReportItemsType reportItems = new Rdl.ReportItemsType();
            switch (reportType)
            {
                case 1:

                    MatrixRdlGenerator matrixGen = new MatrixRdlGenerator();
                    matrixGen.ColumnFields = m_columnFields;
                    matrixGen.RowFields = m_rowFields;
                    matrixGen.SummarizedFields = m_summarizedFields;
                    matrixGen.CornerText = m_cornerText;
                    matrixGen.CellExpression = m_cellExpression;
                    matrixGen.CellFormat = m_cellFormat;
                    matrixGen.ColSubtotal = m_colSubtotal;
                    matrixGen.RowSubtotal = m_rowSubtotal;
                    matrixGen.SummarizedTitles = m_summarizedTitles;
                    matrixGen.Widht = m_ReportWidth;
                    matrixGen.Height = m_ReportHeight;
                    reportItems.Items = new object[] { matrixGen.CreateMatrix() };
                    break;
                case 0:
                    DynamicTable.TableRdlGenerator tablegen = new DynamicTable.TableRdlGenerator();
                    tablegen.Fields = m_columnFields ;
                    tablegen.HeaderFields = m_summarizedTitles;
                    tablegen.FooterFields = m_summarizedFields;
                    tablegen.Widht = m_ReportWidth;
                    tablegen.Height = m_ReportHeight;
                    reportItems.Items = new object[] { tablegen.CreateTable() };
                    break;
                case 2:
                    DynamicChart.ChartRdlGenerator chartgen = new DynamicChart.ChartRdlGenerator();
                    chartgen.CategoryAxisTitle = "category";
                    chartgen.SeriesFields = m_columnFields;
                    chartgen.ValueAxisTitle ="value";
                    chartgen.ChartType = Rdl.ChartTypeType.Column;
                    chartgen.ChartSubType = Rdl.ChartTypeSubtype.Plain;
                    chartgen.CategoryFields = m_rowFields;
                    chartgen.DataFields = m_summarizedFields;
                    chartgen.ChartTitle = m_ReportTitle;
                    chartgen.CategoryAxisTitle = m_ChartXTitle;
                    chartgen.ValueAxisTitle = m_ChartYTitle;
                    chartgen.Width = m_ReportWidth;
                    chartgen.Height = m_ReportHeight;
                    chartgen.ChartType =(Rdl.ChartTypeType ) Enum.Parse (typeof (Rdl.ChartTypeType  ), m_ChartType,true );
                    chartgen.ChartSubType = (Rdl.ChartTypeSubtype)Enum.Parse(typeof(Rdl.ChartTypeSubtype), m_ChartSubType, true);
                    reportItems.Items = new object[] { chartgen.CreateChart() };
                    break;
                default :
                    break;
            }
            return reportItems;

        }

 

rdlc的各元素创建完之后就可以生成文件了,代码如下

       public void WriteXml(Stream stream, int reportType)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Rdl.Report));
            serializer.Serialize(stream, CreateReport(reportType));

            //将stream输入到文件,如stream.WriteTo(fs);
        }

以上介绍了如何创建报表及使用reportdefinition文件。在我的资源中有我做好的各个文件。