做网站项目时,常需要将表格转化为 Excel 文件供用户下载,实现方法有很多种。如:
(1)将DataTable 直接进行 xml 序列化成文本
(2)将DataTable 转化为 Html table 格式
(3)将DataTable 转化为 Excel Xml 格式
(4)使用 Microsoft.Office.Interop.Excel.dll 创建Excel文件,再依次填写单元格数据
测试了这些方法,发现第3种简单且稳定,其它几种方法都有这样那样的小麻烦(如乱码和文件权限问题),我不在此一一提供这些方法的实现代码。以下为第3种方法的代码,本文参考了该篇文章:http://www.cnblogs.com/tsoukw/archive/2008/05/30/1210485.html,在此,我用静态函数实现了该功能。希望对大家有用。
excel xml 格式如:
Code
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook
xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
<Worksheet ss:Name="Sheet1">
<Table>
<Row>
<Cell ss:MergeAcross="1"><Data ss:Type="String">Excel xml</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">A2</Data></Cell>
<Cell><Data ss:Type="Number">0.112</Data></Cell>
</Row>
</Table>
</Worksheet>
</Workbook>
以下是生成 excel xml 的源代码:
Code
// datatable -> excel
public static void ExportExcel(DataTable dt, string fileName, string[] displayColumnNames, string[] displayColumnCaptions)
{
Response.ClearContent();
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.ContentType = "application/vnd.ms-excel; charset=utf-8";
Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
Response.Write(DataTableToExcelTable(dt, displayColumnNames, displayColumnCaptions));
Response.End();
}
// 将 DataTable 转化为 ExcelXml
public static string DataTableToExcelTable(DataTable dt, string[] displayColumnNames, string[] displayColumnCaptions)
{
// 表开始
StringBuilder sb = new StringBuilder();
sb.AppendLine("<?xml version=\"1.0\"?>");
sb.AppendLine("<?mso-application progid=\"Excel.Sheet\"?>");
sb.AppendLine("<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\">");
sb.AppendLine(" <Worksheet ss:Name=\"Sheet1\">");
sb.AppendLine(" <Table>");
//
// 输出标题
//
sb.AppendLine(" <Row>");
if (displayColumnCaptions != null)
{
// 输出指定列标题
for (int i = 0; i < displayColumnCaptions.Length; i++)
sb.AppendLine(" <Cell><Data ss:Type=\"String\">" + displayColumnCaptions[i] + "</Data></Cell>");
}
else if (displayColumnNames != null)
{
// 输出展示列标题
for (int i = 0; i < displayColumnNames.Length; i++)
sb.AppendLine(" <Cell><Data ss:Type=\"String\">" + displayColumnNames[i] + "</Data></Cell>");
}
else
{
// 输出所有列标题
for (int i = 0; i < dt.Columns.Count; i++)
sb.AppendLine(" <Cell><Data ss:Type=\"String\">" + dt.Columns[i].Caption + "</Data></Cell>");
}
sb.AppendLine(" </Row>");
//
// 输出数据
//
if (displayColumnNames != null)
{
// 输出指定列数据
foreach (DataRow dr in dt.Rows)
{
sb.AppendLine(" <Row>");
foreach (string colName in displayColumnNames)
sb.AppendLine(" <Cell><Data ss:Type=\"String\">" + dr[colName].ToString() + "</Data></Cell>");
sb.AppendLine(" </Row>");
}
}
else
{
//输出所有列数据
foreach (DataRow dr in dt.Rows)
{
sb.AppendLine(" <Row>");
Object[] ary = dr.ItemArray;
for (int i = 0; i <= ary.GetUpperBound(0); i++)
sb.AppendLine(" <Cell><Data ss:Type=\"String\">" + ary[i].ToString() + "</Data></Cell>");
sb.AppendLine(" </Row>");
}
}
// 表结束
sb.AppendLine(" </Table>");
sb.AppendLine(" </Worksheet>");
sb.AppendLine("</Workbook>");
return sb.ToString();
}
此外需注意,必须导出为 UTF-8格式的xml,否则excel 无法打开该文件,会报错滴~
注:此方案适用于中小数据量的情形,若数据量很大,必须考虑使用 DataReader 来读取数据,并使用流来写入文本文件。