65.9K
CodeProject 正在变化。 阅读更多。
Home

输出DataSet到Excel

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.65/5 (15投票s)

2009年1月6日

CPOL

1分钟阅读

viewsIcon

104875

downloadIcon

1

允许导出多个表,并适当地标记文本列。使用 Excel 的 XML 格式。

引言

我这样做是因为我想快速将整个 DataSet(多个表)导出到 Excel。我没有为字段添加任何额外的自定义,但我想确保日期、布尔值、数字和文本都格式正确。

这段代码实现了这一点。

在某个时候,我想创建一个 GridView 类型的组件,以便我可以更详细地描述每个项目。例如,我最近的项目需要我创建一个使用给定条形码字体(“Free 3 of 9”)格式化的列,该字体要求我在项目编号前后加上 *。下面的解决方案并不容易做到这一点,所以... 并不完美。如果有人做过类似的事情,请告诉我 :)

有关将 Excel 导入到 XML 的信息,请参阅这篇文章。

注意:此方法不需要在服务器上安装 Excel。

背景

我希望数据集中的每个表都有命名。

ds.Tables[0].TableName = "Colors";
ds.Tables[1].TableName = "Shapes";

我修改了它,允许你传入一个 List<Table>,以防你没有将它们放在 DataSet 中。无论哪种方式都没有什么大问题。

为什么我使用 XmlTextWriter,而似乎只使用了 WriteRaw?我希望它能够使用“x.WriteString(row[i].ToString());”修复任何特殊字符。请注意,这仍然可能对某些字符存在问题,因为我没有对其进行太多测试。

Using the Code

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Xml;

public void Convert(DataSet ds, string fileName) {
    Convert(ds.Tables, fileName);
}
public void Convert(IEnumerable tables, string fileName) {
    Response.ClearContent();
    Response.ClearHeaders();
    Response.Buffer = true;
    Response.Charset = "";
    Response.ContentType = "application/vnd.ms-excel";
    Response.AddHeader("content-disposition", 
             "attachment; filename=" + fileName + ".xls");

    using (XmlTextWriter x = new XmlTextWriter(Response.OutputStream, Encoding.UTF8)) {
        int sheetNumber = 0;
        x.WriteRaw("<?xml version=\"1.0\"?><?mso-application progid=\"Excel.Sheet\"?>");
        x.WriteRaw("<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\" ");
        x.WriteRaw("xmlns:o=\"urn:schemas-microsoft-com:office:office\" ");
        x.WriteRaw("xmlns:x=\"urn:schemas-microsoft-com:office:excel\">");
        x.WriteRaw("<Styles><Style ss:ID='sText'>" + 
                   "<NumberFormat ss:Format='@'/></Style>");
        x.WriteRaw("<Style ss:ID='sDate'><NumberFormat" + 
                   " ss:Format='[$-409]m/d/yy\\ h:mm\\ AM/PM;@'/>");
        x.WriteRaw("</Style></Styles>");
        foreach (DataTable dt in tables) {
            sheetNumber++;
            string sheetName = !string.IsNullOrEmpty(dt.TableName) ? 
                   dt.TableName : "Sheet" + sheetNumber.ToString();
            x.WriteRaw("<Worksheet ss:Name='" + sheetName + "'>");
            x.WriteRaw("<Table>");
            string[] columnTypes = new string[dt.Columns.Count];

            for (int i = 0; i < dt.Columns.Count; i++) {
                string colType = dt.Columns[i].DataType.ToString().ToLower();

                if (colType.Contains("datetime")) {
                    columnTypes[i] = "DateTime";
                    x.WriteRaw("<Column ss:StyleID='sDate'/>");

                } else if (colType.Contains("string")) {
                    columnTypes[i] = "String";
                    x.WriteRaw("<Column ss:StyleID='sText'/>");

                } else {
                    x.WriteRaw("<Column />");

                    if (colType.Contains("boolean")) {
                        columnTypes[i] = "Boolean";
                    } else {
                        //default is some kind of number.
                        columnTypes[i] = "Number";
                    }

                }
            }
            //column headers
            x.WriteRaw("<Row>");
            foreach (DataColumn col in dt.Columns) {
                x.WriteRaw("<Cell ss:StyleID='sText'><Data ss:Type='String'>");
                x.WriteRaw(col.ColumnName);
                x.WriteRaw("</Data></Cell>");
            }
            x.WriteRaw("</Row>");
            //data
            bool missedNullColumn = false;
            foreach (DataRow row in dt.Rows) {
                x.WriteRaw("<Row>");
                for (int i = 0; i < dt.Columns.Count; i++) {
                    if (!row.IsNull(i)) {
                        if (missedNullColumn) {
                            int displayIndex = i + 1;
                            x.WriteRaw("<Cell ss:Index='" + displayIndex.ToString() + 
                                       "'><Data ss:Type='" + 
                                       columnTypes[i] + "'>");
                            missedNullColumn = false;
                        } else {
                            x.WriteRaw("<Cell><Data ss:Type='" + 
                                       columnTypes[i] + "'>");
                        }

                        switch (columnTypes[i]) {
                            case "DateTime":
                                x.WriteRaw(((DateTime)row[i]).ToString("s"));
                                break;
                            case "Boolean":
                                x.WriteRaw(((bool)row[i]) ? "1" : "0");
                                break;
                            case "String":
                                x.WriteString(row[i].ToString());
                                break;
                            default:
                                x.WriteString(row[i].ToString());
                                break;
                        }

                        x.WriteRaw("</Data></Cell>");
                    } else {
                        missedNullColumn = true;
                    }
                }
                x.WriteRaw("</Row>");
            }
            x.WriteRaw("</Table></Worksheet>");
        }
        x.WriteRaw("</Workbook>");
    }
    Response.End();
}

历史

  • 2009 年 1 月 7 日:添加了关于导入的链接(请参阅简介)。
  • 2009 年 1 月 8 日:更新了关于导入的链接(请参阅简介)。
  • 2009 年 1 月 21 日:添加了关于服务器上不需要 Excel 的说明
© . All rights reserved.