将DataTable导出为Excel (XML Spreadsheet)

news/2024/7/21 5:30:06 标签: spreadsheet, xml, excel, datatables, xsl, dataset

前阵子公司有同事需要将搜索页面的搜索结果导出成Excel文件. 用几个不同的办法做了出来. 最后部署时发现: 用COM+组件行不通, 服务器上没装OFFICE; 用OWC也不行, 因为服务器是64位的, OWC不支持; 导出成Excel2003支持的xml, 这招最灵活, 也是一个简单可行的办法.

首先用Excel 2003新建一个空白Wookbook, 然后保存为XML Spreadsheet. 然后打开看它生成的XML代码就能了解XML Spreadsheet的基本结构了.
我先把DataTable生成XML数据, 再使用一个XLS把XML数据转换成XML Spreadsheet的结构.

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Xsl;

namespace AProject
{
public class ExcelHelper
{
public static string ExportAsTempFile(DataTable dataTable, bool appendColumnNames)
{
if(dataTable == null)
{
return null;
}

return ExportAsTempFile(new DataTable[] { dataTable }, appendColumnNames);
}

public static string ExportAsTempFile(DataSet dataSet, bool appendColumnNames)
{
string fileName = Path.GetTempFileName();

if(ExportFile(dataSet, fileName, appendColumnNames))
{
return fileName;
}

return null;
}

public static string ExportAsTempFile(DataTable[] dataTables, bool appendColumnNames)
{
string fileName = Path.GetTempFileName();

if(ExportFile(dataTables, fileName, appendColumnNames))
{
return fileName;
}

return null;
}

public static bool ExportFile(DataTable dataTable, string fileName, bool appendColumnNames)
{
if(dataTable == null)
{
return false;
}

return ExportFile(new DataTable[] { dataTable }, fileName, appendColumnNames);
}

public static bool ExportFile(DataSet dataSet, string fileName, bool appendColumnNames)
{
if(dataSet == null)
{
return false;
}

DataTable[] dataTables = new DataTable[dataSet.Tables.Count];
dataSet.Tables.CopyTo(dataTables, 0);
return ExportFile(dataTables, fileName, appendColumnNames);
}

public static bool ExportFile(DataTable[] dataTables, string fileName, bool appendColumnNames)
{
if(dataTables == null || dataTables.Length == 0 || string.IsNullOrEmpty(fileName))
{
return false;
}

XmlDocument xmlDoc = GetXmlDataTables(dataTables, appendColumnNames);
XmlDocument xlsDoc = TransformXml(xmlDoc);

try
{
xlsDoc.Save(fileName);
return true;
}
catch
{
return false;
}
}

private static XmlDocument GetXmlDataTables(DataTable[] dataTables, bool appendColumnNames)
{
if(dataTables == null)
{
return null;
}

XmlDocument xmlDoc = new XmlDocument();
XmlElement rootNode = xmlDoc.CreateElement("DTS");
XmlElement tableNode;
XmlElement rowNode;
XmlElement colNode;
DataTable dt;

for(int i = 0; i < dataTables.Length; i++)
{
dt = dataTables[i];

if(dt == null)
{
break;
}

if(dt.TableName.Trim() == string.Empty)
{
dt.TableName = "DataTable" + i.ToString();
}

tableNode = xmlDoc.CreateElement("DT");
tableNode.SetAttribute("N", dt.TableName);

if(appendColumnNames)
{
rowNode = xmlDoc.CreateElement("DR");

foreach(DataColumn dc in dt.Columns)
{
colNode = xmlDoc.CreateElement("DC");
colNode.SetAttribute("N", dc.ColumnName);
colNode.SetAttribute("T", "String");
colNode.AppendChild(xmlDoc.CreateTextNode(dc.ColumnName));
rowNode.AppendChild(colNode);
}

tableNode.AppendChild(rowNode);
}


foreach(DataRow dr in dt.Rows)
{
rowNode = xmlDoc.CreateElement("DR");

foreach(DataColumn dc in dt.Columns)
{
colNode = xmlDoc.CreateElement("DC");
colNode.SetAttribute("N", dc.ColumnName);
colNode.SetAttribute("T", GetDataType(dc.DataType));
colNode.AppendChild(xmlDoc.CreateTextNode(GetTextValue(dc.DataType, dr[dc.ColumnName])));
rowNode.AppendChild(colNode);
}

tableNode.AppendChild(rowNode);
}

rootNode.AppendChild(tableNode);
}

xmlDoc.AppendChild(rootNode);
return xmlDoc;
}

private static string GetTextValue(Type type, object value)
{
string text;

if(type == typeof(DateTime))
{
text = ((DateTime)value).ToString("yyyy-MM-ddTHH:mm:ssZ");
}
else
{
text = value.ToString();
}

return text;
}

private static string GetDataType(Type type)
{
string dataType;

if(type == typeof(string))
{
dataType = "String";
}
else if(type == typeof(DateTime))
{
dataType = "DateTime";
}
else if(type == typeof(bool))
{
dataType = "Boolean";
}
else
{
dataType = "Number";
}

return dataType;
}

private static XmlDocument TransformXml(XmlDocument xmlDoc)
{
XmlDocument xlsDoc = new XmlDocument();
XslCompiledTransform xslt = new XslCompiledTransform();
Assembly assembly = Assembly.GetExecutingAssembly();

using(Stream s = assembly.GetManifestResourceStream("AProject.Resources.XmlSpreadsheet.xsl"))
{
if(s != null)
{
xslt.Load(XmlReader.Create(s));
MemoryStream output = new MemoryStream();
XmlTextWriter xmlWriter = new XmlTextWriter(output, Encoding.UTF8);
xslt.Transform(xmlDoc, xmlWriter);
output.Position = 0;
xlsDoc.Load(output);
xlsDoc.PrependChild(xlsDoc.CreateXmlDeclaration("1.0", null, null));
output = null;
}
}

return xlsDoc;
}
}
}
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
<xsl:output method='xml' version='1.0'/>
<xsl:template match="DTS">
<ss:Workbook >
<ss:Styles>
<ss:Style ss:ID="Default">
<ss:NumberFormat ss:Format="General"/>
</ss:Style>
<ss:Style ss:ID="DateTime">
<ss:NumberFormat ss:Format="General Date"/>
</ss:Style>
</ss:Styles>
<xsl:apply-templates select="DT" />
</ss:Workbook>
</xsl:template>

<xsl:template match="DT">
<ss:Worksheet>
<xsl:attribute name="ss:Name">
<xsl:value-of select="@N"/>
</xsl:attribute>
<ss:Table>
<xsl:apply-templates select="DR" />
</ss:Table>
</ss:Worksheet>
</xsl:template>

<xsl:template match="DR">
<ss:Row>
<xsl:apply-templates select="DC" />
</ss:Row>
</xsl:template>

<xsl:template match="DC">
<ss:Cell>
<xsl:choose>
<xsl:when test="@T = 'DateTime'">
<xsl:attribute name="ss:StyleID">
<xsl:text>DateTime</xsl:text>
</xsl:attribute>
</xsl:when>
</xsl:choose>
<ss:Data>
<xsl:attribute name="ss:Type">
<xsl:value-of select="@T"/>
</xsl:attribute>
<xsl:choose>
<xsl:when test="@T = 'String'">
<xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
<xsl:value-of select="."/>
<xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</ss:Data>
</ss:Cell>
</xsl:template>
</xsl:stylesheet>

 


http://www.niftyadmin.cn/n/1412304.html

相关文章

Python常用内置函数(一)

1. lambda匿名函数&#xff1a;定义函数过程&#xff0c;让代码更简洁a lambda x,y:xya(2,3)52. reduce&#xff1a;循环reduce(lambda x,y:xy, xrange(1,101))5050# 相当((((12)3)4)5)....100)__builtin__.内置函数3. abs: 返回参数的绝对值abs(-10) 104. max: 返回序列的最大…

《redis入门看这系列就够了》第四章 redis的数据类型 - list

redis 第四章 redis的数据类型 - list list 列表 常用的入门命令 1.lpush&#xff0c;rpush&#xff0c;lrange &#x1f4cc;lpush key x y z 从左侧设置key的列表值value为[x,y,z] 127.0.0.1:6379> lpush list1 1 2 3 3 4 5 (integer) 5 OK&#x1f4cc;rpush key x y…

Office 2007或Office 2010套件初始安装中断后无法重新启动安装程序,错误“Microsoft Office xxx在安装过程中出错”...

大家好&#xff0c;不知道大家在安装Office2007或Office2010时有没有遇到过这样的现象&#xff0c;在您第一次安装Office2007或Office2010套件时&#xff0c;因为某种原因安装中断&#xff0c;当您试图重新安装相同的Office套件时&#xff0c;安装失败并且收到如下的错误提示Mi…

UpdatePanel的妙用:Incremental Content

Incremental Content是我随意取的名字&#xff0c;我有时候会希望&#xff0c;把一些常见的场景&#xff0c;总结出ASP.NET AJAX一些比较固定的使用模式。Incremental Content是我为现在这个“模式”取的名字。这个模式的作用&#xff0c;就是使用UpdatePanel来不断地在页面上增…

mysql数据备份-mysqldump,shell导入导出mysql数据

1. shell脚本-导出mysql数据 #! /bin/bash #数据库信息 mysql_userroot # mysql密码 mysql_password"" # mysql的IP mysql_host"" # mysql 端口 mysql_port"6306" # 数据存放路径 backup_dir"/home/data1/taishi/app/mysqlback" # 库…

为多态基类声明一个虚析构函数

使用一个基类指针删除派生类对象&#xff0c;同时基类的析构函数是非虚的&#xff0c;那么这个指针只会删除派生类对象中的基类的部分&#xff0c;其派生部分不会被删除。造成资源泄漏。而如果一个类并不用作基类&#xff0c;则没必要把析构函数声明为虚的&#xff0c;否则会浪…

IDEA中 @SpringBootApplication 注解无法引入依赖

问题&#xff1a; IDEA中 SpringBootApplication注解无法引入依赖 最终解决方案: mvn idea:idea &#x1f525;这个命令可以检查并继续下载未下载完整的依赖jar!!! cd 进入项目根目录执行 mvn idea:idea 排查&#xff1a; 1.查看pom文件是否引入springBoot必要依赖 经查看没有…

就是不行

1.tarjan正确性证明&#xff0c;求割点为什么不用mark即横叉边情况。 2.高精&#xff0c;各种高精的重载及高精乘低精的万进制优化。 3.cdq分治 4.树状数组 5.主席树&#xff0c;带修主席树 6.treap.splay 7.带修莫队 8.kmp,ac自动机 9.prime最小生成树 10.矩阵图论. 11.斜率优…