C# 的一种简单的数据输出方式

起因

在开发中经常遇到一些数据导出成文件的需求,客户有时就是要个小表格。数据集导出为Excel格式的文件的方法太多了。估计常见的有十几种。这里是讲一个另类的简单方法。

结果

先上例子 :          

先创建一个测试用的数据集,生成4个字段15行的测试数据。

            DataTable dt = new DataTable();
            dt.Columns.AddRange(new[] {  
                new DataColumn("Name", typeof(string)),
                new DataColumn("Age", typeof(int)), 
                new DataColumn("Date", typeof(string)),
                new DataColumn("Active", typeof(bool)) });
            for (int i = 1; i <= 15; i++)
                dt.Rows.Add(  $"User{i}", new Random().Next(18, 65), DateTime.Now.AddDays(-i).ToString("yyyy-MM-dd"), i % 3 != 0);

然后生成导出的格式。导出的格式为rdlc报表,实际就是一个xml格式的文本。

然后 加载rdlc,并传入测试数据集。

            RdlcGenerator rg = new RdlcGenerator();//这个是一个简单的xml生成
            string rdlcXml = rg.GenerateRdlcXml(dt); //System.IO.File.WriteAllText(@"d:\1.rdlc", rdlcXml);

            var report = new LocalReport();
            report.LoadReportDefinition(new System.IO.StringReader(rdlcXml)); //加载rdlc
            report.DataSources.Add(new ReportDataSource("DataSet1", dt)); //传入数据集

            RdlcGenerator rg = new RdlcGenerator();
            string rdlcXml = rg.GenerateRdlcXml(dt); //System.IO.File.WriteAllText(@"d:\1.rdlc", rdlcXml);

            var report = new LocalReport();
            report.LoadReportDefinition(new System.IO.StringReader(rdlcXml));
            report.DataSources.Add(new ReportDataSource("DataSet1", dt)); 

 最后导出文件,这里列举了常见的几种格式,实际支持更多的格式。

            byte[] result = report.Render("EXCELOPENXML"); 
            System.IO.File.WriteAllBytes(@"d:\1.xlsx", result);

            result = report.Render("PDF");
            System.IO.File.WriteAllBytes(@"d:\1.pdf", result);

            result = report.Render("WORDOPENXML");
            System.IO.File.WriteAllBytes(@"d:\1.docx", result);  

            result = report.Render("IMAGE");
            System.IO.File.WriteAllBytes(@"d:\1.tiff", result); 

支持 常见的 xlsx、pdf、docx和图片

Web 或者 winform都支持 ,在nuget时现在不同的包。

设计

导出的文件的颜色、字体、边框啥的,可以随便改。

如果觉得直接改这个文本内容比较麻烦,其实有个简单的方法。

前面的代码里 ,俺有一行注释 //System.IO.File.WriteAllText(@"d:\1.rdlc", rdlcXml); 其实就是把rdlc的设计保存到文件,保存到文件之后就可以使用VS的 报表设计器 编辑样式,然后把 颜色、字体、边框啥的复制回去。

其实rdlc 就是个 xml文件。方便的很。所以这个例子就是一个动态生成rdlc的例子,例子只是简单的演示功能,真正使用时,可以自己设计一些rdlc模板。再在这些模版上动态添加内容。

代码

先 Nuget Microsoft.ReportingServices.Report...

Web 或者 winform都支持

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;

namespace WindowsFormsAppRPT
{
    public class RdlcGenerator
    {
        public List<ColDef> _collist = new List<ColDef>();
        public class ColDef
        {
            public string title = "";
            public string field = "";
            public double width_cm = 3.2;
        }

        public void AddCol(string title, string field,double width_cm)
        {
            _collist.Add(new ColDef() { title = title, field= field, width_cm= width_cm });
        }
        public string GenerateRdlcXml(DataTable dataTable )
        {
            if (_collist.Count <= 0)
            {
                foreach (DataColumn dc in dataTable.Columns)
                {
                    AddCol(dc.ColumnName, dc.ColumnName,2);
                }

            }
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(GetBlankRdlc());
            XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable);
            nsMgr.AddNamespace("ns", "http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition"); 
            XmlNode body = doc.SelectSingleNode("ns:Report/ns:Body", nsMgr);
            body.InnerXml = @"    <ReportItems>
      <Tablix Name=""Tablix1"">
        <TablixBody>
          <TablixColumns>
        
          </TablixColumns>
          <TablixRows>
            <TablixRow>
              <Height>0.6cm</Height>
              <TablixCells>

              </TablixCells>
            </TablixRow>
            <TablixRow>
              <Height>0.6cm</Height>
              <TablixCells>
               
              </TablixCells>
            </TablixRow>
          </TablixRows>
        </TablixBody>
        <TablixColumnHierarchy>
          <TablixMembers> 
          </TablixMembers>
        </TablixColumnHierarchy>
        <TablixRowHierarchy>
          <TablixMembers>
            <TablixMember>
              <KeepWithGroup>After</KeepWithGroup>
            </TablixMember>
            <TablixMember>
              <Group Name=""详细信息"" />
            </TablixMember>
          </TablixMembers>
        </TablixRowHierarchy>
        <DataSetName>DataSet1</DataSetName>
        <Height>1.2cm</Height>
        <Width>2.5cm</Width>
        <Style>
          <Border>
            <Style>None</Style>
          </Border>
        </Style>
      </Tablix>
    </ReportItems>
    <Height>0.47244in</Height>
    <Style />";

            XmlNode TablixColumns = doc.SelectSingleNode("//ns:*/ns:TablixColumns", nsMgr);
            XmlNode TablixMembers = doc.SelectSingleNode("//ns:*/ns:TablixMembers", nsMgr);

            StringBuilder sb_cols = new StringBuilder();
            StringBuilder sb_mems = new StringBuilder();
            foreach (ColDef col in _collist)
            { 
                sb_cols.AppendLine(@"<TablixColumn>
                      <Width>"+col.width_cm.ToString()+ @"cm</Width>
                    </TablixColumn>");
                sb_mems.AppendLine(@"<TablixMember />");
            }
            TablixColumns.InnerXml = sb_cols.ToString();
            TablixMembers.InnerXml = sb_mems.ToString();
            XmlNodeList TablixCells = doc.SelectNodes("//ns:*/ns:TablixCells", nsMgr);

            XmlNode header = TablixCells[0];
            XmlNode data_row = TablixCells[1];
            StringBuilder sb_header = new StringBuilder();
            int idx = 0;
            foreach(ColDef col in _collist)
            {
                idx++;
                sb_header.AppendLine(@"<TablixCell>
                  <CellContents>
                    <Textbox Name=""Textbox_header"+idx.ToString()+@""">
                      <CanGrow>true</CanGrow>
                      <KeepTogether>true</KeepTogether>
                      <Paragraphs>
                        <Paragraph>
                          <TextRuns>
                            <TextRun>
                              <Value>"+col.title+ @"</Value>
                              <Style>
                                  <FontWeight>Bold</FontWeight>
                              </Style>
                            </TextRun>
                          </TextRuns>
                          <Style>
                            <TextAlign>Center</TextAlign>
                          </Style>
                        </Paragraph>
                      </Paragraphs>
                      <rd:DefaultName>Textbox_header" + idx.ToString() + @"</rd:DefaultName>
                      <Style>
                        <Border>
                          <Color>LightGrey</Color>
                          <Style>Solid</Style>
                          <Width>0.5pt</Width>
                        </Border>
                        <BackgroundColor>PaleTurquoise</BackgroundColor>
                        <PaddingLeft>2pt</PaddingLeft>
                        <PaddingRight>2pt</PaddingRight>
                        <PaddingTop>2pt</PaddingTop>
                        <PaddingBottom>2pt</PaddingBottom>
                      </Style>
                    </Textbox>
                  </CellContents>
                </TablixCell>");
            }
            header.InnerXml = sb_header.ToString();

            StringBuilder sb_data_row = new StringBuilder();
             idx = 0;
            foreach (ColDef col in _collist)
            {
                idx++;
                sb_data_row.AppendLine(@"<TablixCell>
                  <CellContents>
                    <Textbox Name=""DataColumn"+idx.ToString()+@""">
                      <CanGrow>true</CanGrow>
                      <KeepTogether>true</KeepTogether>
                      <Paragraphs>
                        <Paragraph>
                          <TextRuns>
                            <TextRun>
                              <Value>=Fields!"+col.field+ @".Value</Value>
                              <Style />
                            </TextRun>
                          </TextRuns>
                          <Style />
                        </Paragraph>
                      </Paragraphs>
                      <rd:DefaultName>" + col.field + @"</rd:DefaultName>
                      <Style>
                        <Border>
                          <Color>LightGrey</Color>
                          <Style>Solid</Style>
                          <Width>0.5pt</Width>
                        </Border>
                        <PaddingLeft>2pt</PaddingLeft>
                        <PaddingRight>2pt</PaddingRight>
                        <PaddingTop>2pt</PaddingTop>
                        <PaddingBottom>2pt</PaddingBottom>
                      </Style>
                    </Textbox>
                  </CellContents>
                </TablixCell>");
            }
            data_row.InnerXml = sb_data_row.ToString();
            XmlNode fields = doc.SelectSingleNode("ns:Report/ns:DataSets/ns:DataSet/ns:Fields", nsMgr);
            StringBuilder sb_fields = new StringBuilder();
            foreach (DataColumn dc in dataTable.Columns)
            {
                sb_fields.AppendLine(@"<Field Name="""+dc.ColumnName+@""">");
                sb_fields.AppendLine(@"<DataField>" + dc.ColumnName + "</DataField>");
                sb_fields.AppendLine(@"<rd:TypeName>"+dc.DataType.FullName+"</rd:TypeName>");
                sb_fields.AppendLine(@"</Field>");
            }
            fields.InnerXml = sb_fields.ToString();

            using (StringWriter sw = new StringWriter())
            {
                using (XmlTextWriter writer = new XmlTextWriter(sw))
                {
                    writer.Formatting = Formatting.Indented;
                    writer.Indentation = 4;
                    doc.WriteTo(writer);
                    return sw.ToString();
                }
            } 
        }

        public static string GetBlankRdlc()
        {
            return @"<?xml version=""1.0"" encoding=""utf-8""?>
<Report xmlns=""http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition"" xmlns:rd=""http://schemas.microsoft.com/SQLServer/reporting/reportdesigner"">
  <Body>

  </Body>
  <Width>2.95276in</Width>
  <Page>
    <PageHeight>29.7cm</PageHeight>
    <PageWidth>21cm</PageWidth>
    <LeftMargin>1cm</LeftMargin>
    <RightMargin>1cm</RightMargin>
    <TopMargin>1cm</TopMargin>
    <BottomMargin>1cm</BottomMargin>
    <ColumnSpacing>0.13cm</ColumnSpacing>
    <Style />
  </Page>
  <AutoRefresh>0</AutoRefresh>
  <DataSources>
    <DataSource Name=""DataSet1"">
      <ConnectionProperties>
        <DataProvider>System.Data.DataSet</DataProvider>
        <ConnectString>/* Local Connection */</ConnectString>
      </ConnectionProperties>
      <rd:DataSourceID>"+Guid.NewGuid().ToString()+ @"</rd:DataSourceID>
    </DataSource>
  </DataSources>
  <DataSets>
    <DataSet Name=""DataSet1"">
      <Query>
        <DataSourceName>DataSet1</DataSourceName>
        <CommandText>/* Local Query */</CommandText>
      </Query>
      <Fields>
        
      </Fields>
      <rd:DataSetInfo />
    </DataSet>
  </DataSets>
  <rd:ReportUnitType>Cm</rd:ReportUnitType>
  <rd:ReportID>" + Guid.NewGuid().ToString() + @"</rd:ReportID>
</Report>";
        }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月巴月巴白勺合鸟月半

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值