一种基于.NET格式精确的OFFICE文档报表生成方案
一、 概述
由于OFFICE软件在办公软件业的垄断,Office文件格式也在报表文件格式占有相当重要的地位。在商业软件或企业开发中,我们经常会遇到生成Office报表的问题。
解决这个问题的方法有几种:
l 利用Office Automation的方法直接生成OFFICE文档;
l 利用ADO.NET的方法对Excel文件以数据源的方式读写;
l 利用第三方法插件(Crystal Report)开发。
以上几种各有利弊,而难于达到精确的格式的要求。故根据OFFICE 2003的新特性,我设计一种基于.NET Framework的OFFICE报表生成方法。
这种方法的优点:
l 能够支持格式较复杂的报表;
l 在执行效率也具有相当的优势;
l 使用的技术相对简单(.Net Framework、XML、Office Automation);
l 以后技术发展的趋势(XML技术)。
当然,这种方法也有不少的缺点:
l 不支持图表功能(在Office 12中应该得以改进);
l 没有可视化的工具编辑XSLT,使得开发流程相当耗时,尤其是对XSLT不太了解时;
l 需要对Office 2003的XML格式有所了解,这点可以参照Microsoft提供的Microsoft Office 2003 XML Reference Schemas Documentation。
综上所述,本方案应该是利弊参半。所以,本文也非向大家推销此方法,旨在以解决方案的形式,给大家作个参考。
二、 实施
上面对此方法作了概述,但未涉及技术实现,所以现在我想谈一下具体的实现方法。
本方案主要用到XML,要求读者对XML和.NET平台上的XML操作要有一定的认识。如果对这方面有兴趣的朋友可以http://www.w3.org了解一下XML和Microsoft发布的.NET Framework SDK文档了解一下XML在.Net Framework上的应用及其操作方法。
方案流程图如下:
对上图作一下解释:
1. 使用ADO.NET将数据以DataSet的形式从数据库中读出。代码实现如下:
|
string ConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=..\..\demo.mdb"; string CommandText = "select * from demo"; using(OleDbConnection myConnection = new OleDbConnection(ConnectionString)) { OleDbDataAdapter myCommand = new OleDbDataAdapter(CommandText, myConnection); DataSet ds = new DataSet(); } |
2. 将DataSet转化在XML文档,这步可以通过DataSet.WriteXml方法或XmlDataDocument类。代码实现如下:
|
ds.WriteXml(@"d:\temp.xml");//输出XML文档到硬盘 或 XmlDataDocument xmlDoc = new XmlDataDocument(ds);//输出XML到内存对象 |
3. 编写Office XML的XSLT。实现这一步的技巧,由于Office XML的代码很繁琐(动辄数千行),你可以先用Office制作模板,然后将其另存为“XML表格”,这样便可以得到大概的Office XML代码,再在其基础上修改。代码实现如下:
|
<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40"> <xsl:output method="xml" indent="yes" /> <xsl:template match="Profile"> <Worksheet ss:Name="档案"> <Table> <Row> <Cell ss:Index="3"> <Data ss:Type="String">姓名:</Data> </Cell> <Cell> <Data ss:Type="String"> <xsl:value-of select="./Name" /> </Data> </Cell> </Row> </Table> </Worksheet> </xsl:template> </xsl:stylesheet> |
4. 利用.NET Framework提供XslTransform类以第一步生成的XML文档作为数据,以第3步生成的XSLT文件作为模板,生成Office 2003 XML格式的XML文件。如果您的客户用的是Office 2003或上的版本,那么生成的文档直接可以被正确地读取,否则,请接着实施下一步。代码实现如下:
|
XslTransform xslTran = new XslTransform(); xslTran.Load(@"\xslt_profile.xslt"); FileStream fs = null; try { fs = new FileStream(xmlFile, FileMode.OpenOrCreate); xslTran.Transform(xmlDoc, null, fs, null); } finally { if(fs != null) fs.Close(); } |
5. 利用Office 2003提供的COM操作,读入第4步生成的XML文档,然后将其另存为普通的Office文档。
|
Excel.Application oXL = null; string xmlFile = "excel.xml"; string xlsFile = "excel.xsl"; Excel.Workbook oWB = null; try { oXL = new Excel.Application(); oWB = oXL.Workbooks.Open(xmlFile, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing); oWB.SaveAs(xlsFile, Excel.XlFileFormat.xlWorkbookNormal, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing); } finally { if(oWB != null) { oWB.Close(false, Type.Missing, Type.Missing); System.Runtime.InteropServices.Marshal.ReleaseComObject(oWB); } if(oXL != null) { oXL.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(oXL); } } |
三、 总结
随着XML技术的发展和普及,我相信该方案可以支持更多的格式的报表生成如PDF等。如果有一个可视化的GUI工具编写XSLT,则可以减轻开发者的劳动和加快开发周期,我认为本方案也是有一定的商业价值的。
浙公网安备 33010602011771号