XuGang

记录一个程序员的成长

 

关于ASP.NET 将数据导出成Excel 的总结[中]

直接将DataSet 输出成 Excel,这样解决了网格控件只显示分页的部分数据的问题。

Introduction

I did this when I wanted to do a quick export of an entire DataSet (multiple tables) to Excel. I didn't add any additional customization to the fields, but I did want to make sure that dates, boolean, numbers, and text were all formatted correctly.

This code does that.

At some point, I'd like to make a GridView type component that would allow me to detail more about each item. For example, my latest project required me to make a column formatted with a given barcode font ("Free 3 of 9") that required that I put an * before and after the item number. The solution below doesn't make this easy to do, though... So yeah, not perfect. If anyone else has done something like this, let me know :)

For importing Excel to XML, see this post.

NOTE: This method does NOT require Excel to be installed on the Server.

Background

I prefer to see each table in the DataSet to be named.

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

I changed it to allow you to pass in a List<Table> in case you don't put them in a DataSet. No big deal either way.

Why did I use an XmlTextWriter when I seem to be only using the WriteRaw? I wanted to be able to have it fix any special characters with the "x.WriteString(row[i].ToString());". Note, this still may have problems with certain characters, since I haven't tested it much.

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();
}
复制代码
来源:http://www.codeproject.com/KB/office/OutputDatasetToExcel.aspx

我将这段代码和上一篇《关于ASP.NET 将数据导出成Excel 的总结[上]》中的代码结合起来,做了一个比较完善的Demo,使用起来还是很不错的。

Demo下载

posted on   钢钢  阅读(751)  评论(0编辑  收藏  举报

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?

导航

统计

点击右上角即可分享
微信分享提示