c#中的Excel编程摸索总结

 
感谢 pc1024 CSDN 上的博客,文中很多是参考他的博客
ASP.NET 应用程序常常会遇到需要从 Excel 文件中读取数据或将数据写入 Excel 的需求。一般来讲,在 ASP.NET 中读写 Excel 文件有四种解决方案。
1 使用 OLE DB
使用 OLE DB 可以以查询数据库的方式来读取 Excel 文件,因为在某种程度上 Excel 表格可以看成是一张一张的数据表。其二者的主要区别在于所使用的数据引擎不一样。使用 OLE DB 访问 Excel 的要点是计算机上必须具有 Microsoft Access Data Component 2.6(MADC2.6) 以上版本,同时在连接字符串上必须声明 “Extended Properties=Excel 8.0” ,这里的指定 Excel 版本号如果高于 8.0 可能会出错,所以一般来讲必须使用 Excel 8.0
例如下面的实现代码:
// 创建一个数据链接
string strCon = " Provider = Microsoft.Jet.OLEDB.4.0 ; Data Source = c://sample.xls;Extended Properties=Excel 8.0" ;
OleDbConnection myConn = new OleDbConnection ( strCon ) ;
string strCom = " SELECT * FROM [Sheet1$] " ;
myConn.Open ( ) ;
// 打开数据链接,得到一个数据集
OleDbDataAdapter myCommand = new OleDbDataAdapter ( strCom , myConn ) ;
// 创建一个 DataSet 对象
myDataSet = new DataSet ( ) ;
// 得到自己的 DataSet 对象
myCommand.Fill ( myDataSet , "[Sheet1$]" ) ;
// 关闭此数据链接
myConn.Close ( ) ; 
使用这种解决方案的优点是不需要其他的服务器组件,部署非常方便,但是其缺点也是明显的,用它来读取 Excel 2003 格式以上的文件会存在数据丢失的情况,而且也无法生成 Excel 文件。
2 使用 Office 主互操作程序集
另外一种解决方案是使用 Office 主互操作程序集,采用这种方式需要在服务器上安装 Office 2003 。但是能够比较精细的控制 Excel 文件的方方面面,包括格式、字体、颜色等等。
下面的代码演示了如何读取 Excel 文件中某个单元格的值:
示例:
using System;
using Microsoft.Office.Interop.Excel;
using System.Reflection;
using System.Data;
public class ExcelApp
{
    private static ApplicationClass xApp;
    public static string TransferToExcelFile(string parentPath, string fileName, System.Data.DataTable data)
    {
 
        if (xApp == null)
        {
            xApp = new ApplicationClass();
            //xApp.Visible = true;
        }
 
        if (xApp != null)
        {
            try
            {
                WorkbookClass xBook = xApp.Workbooks.Add(Missing.Value) as WorkbookClass;
                if (xBook != null)
                {
                    //WorksheetClass xSheet = xBook.Sheets[1] as WorksheetClass;
                    Worksheet xSheet = xApp.ActiveSheet as Worksheet;
                    Range range = null;
                    if (xSheet != null)
                    {
                        int columnCount = data.Columns.Count;
                        for (int i = 0; i < columnCount; i++)
                        {
                            range = (Range)xSheet.Cells[1, i + 1];
                            if (range != null)
                                //range1.Value2 = "rang";
                                range.Value2 = data.Columns[i].ColumnName;
                        }
                        int rowsCount = data.Rows.Count;
                        for (int i = 0; i < rowsCount; i++)
                        {
                            for (int col = 0; col < columnCount; col++)
                            {
                                range = (Range)xSheet.Cells[i + 2, col + 1];
                                if (range != null)
                                    range.Value2 = (data.Rows[i][col] == null) ? "" : data.Rows[i][col].ToString();
                            }
                        }
                    }
                    fileName = fileName + DateTime.Now.Ticks.ToString() + ".xlsx";
                    string savePath = parentPath + "//" + fileName;
                    xBook.SaveAs(savePath,
                    Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, XlSaveAsAccessMode.xlNoChange, Missing.Value, Missing.Value, Missing.Value,
                    Missing.Value, Missing.Value);
                    xBook.Close(Missing.Value, Missing.Value, Missing.Value);
                    xSheet = null;
                    xBook = null;
                    return fileName;
                    // xApp.Quit();
                    // xApp = null;
                }
            }
            catch
            {
                return "";
            }
            finally
            {
                GC.Collect();
            }
        }
        return "";
 
    }  
    ~ExcelApp()
    {
 
        if (xApp != null)
        {
            xApp.Quit();
            xApp = null;
            GC.Collect();
        }
    }
}
实际上对于 ASP.NET 来讲,这并不是一个很好的解决方案,其原因是这个解决方案将客户端的组件用到了服务器上,这往往会带来很多的问题,如果在处理一个 Excel 文件的时候出错,那么整个线程就会死在那里,服务器上的 Excel 进程无法重启动, Excel 文件无法删除,后面的 Excel 文件也无法处理,只能重启服务器,还有如果使用单例模式生成 ExcelApp ,如上面的代码,如何有效地控制并发性也是很大的问题。
3 使用 ServerDocument
在上一个解决方案中,使用 Office 主互操作程序集存在很大的问题,究其原因是因为将本应在客户端使用的 Office 组件用在了服务器上导致的,因为这些 Office 组件在设计之初就没有考虑在服务中调用的情况。对于在服务器上使用 Excel 文件,微软推荐的解决方案是使用 ServerDocument
在具有 Microsoft Visual Studio 2005 Tools for the Microsoft Office System 自定义的 Microsoft Office Word 2003 文档或 Microsoft Office Excel 2003 工作簿中,可以将数据存储在嵌入的数据岛中,无需启动 Excel Word 即可访问数据岛。
数据岛是一个 XML 文档,其中包含 Office 文档中嵌入的数据;无需实例化 Office 文档即可访问该 XML 文档。数据实际存在于两个地方,即文档和单独的嵌入数据岛中。在数据岛与文档之间使用了数据绑定以使它们保持同步。如果服务器上运行的代码修改了数据岛,则在文档打开并且文档中的代码运行时, Office 文档会与数据岛进行同步。
此模型具有以下几项优势:
可以将验证代码添加到独立于文档的数据中。通过将验证与文档分离,可以将数据验证代码移植到其他文档中。
数据岛使用可脱机使用的数据填充。当文档中的缓存数据项包含数据时,该文档将与数据岛进行交互。
由于可以从外部访问数据岛,因此无需实例化 Office 就可以修改文档中嵌入的数据,从而支持服务器上文档的快速批处理。但是,只能访问缓存中的数据,而不是文档中的所有数据。
需要添加 Microsoft.VisualStudio.Tools.Applications.Runtime; 引用
下面的代码分别演示了如何使用 ServerDocument 访问数据和从数据生成 Excel 文档:
string expenseDoc = @"C:/ExpenseDocuments/Expenses0105.xls";
        ServerDocument sd1 = null;
        try
        {
            sd1 = new ServerDocument(expenseDoc);
            CachedDataHostItem dataHostItem1 = sd1.CachedData.HostItems["DataNamespace.DataWorksheet"];
            CachedDataItem dataItem1 = dataHostItem1.CachedData["DataCache"];
            System.IO.StringReader schemaReader = new System.IO.StringReader(dataItem1.Schema);
            System.IO.StringReader xmlReader = new System.IO.StringReader(dataItem1.Xml);
            ExpenseData.ReadXmlSchema(schemaReader);
            ExpenseData.ReadXml(xmlReader);
        }
        finally
        {
            if (sd1 != null)
            {
                sd1.Close();
            }
}
代码 7-4
  string name = @"C:/Documents/WordApplication3.doc";
        System.IO.FileStream fileStream = null;
        byte[] bytes = null;
        try
        {
            fileStream = new System.IO.FileStream(
                name, System.IO.FileMode.Open, System.IO.FileAccess.Read);
 
            bytes = new byte[(int)fileStream.Length];
            fileStream.Read(bytes, 0, (int)fileStream.Length);
        }
        finally
        {
            if (fileStream != null)
            {
                fileStream.Close();
            }
        }
        ServerDocument sd1 = null;
        try
        {
            sd1 = new ServerDocument(bytes, name);
            // Your data manipulation code goes here.
            sd1.Save();
            bytes = sd1.Document;
            // If you have a Word document, use the MIME string:
            Response.ContentType = "application/msword";
            // If you have an Excel workbook, use the MIME string:
            //Response.ContentType = "application/vnd.ms-excel";
            Response.AddHeader("Content-disposition", "filename=" + name);
            Response.Write(sd1);
        }
        finally
        {
            if (sd1 != null)
            {
                sd1.Close();
            }
        } 代码 7-5
 
相对来说,这是一个比较理想的解决方案,但是使用该方案有如下几个限制:
客户端必须安装 .NET Framework 2.0 Office Tools for Visual Studio 运行时和 Office 2003
开发嵌入于文档中的程序集,用于同步视图和数据岛中的数据,例如用数据岛数据中的某个值更新某单元格中的值,或者用某单元格中的值更新数据岛中的值。
使用专用的 Excel 模板。
4 对于 Office 2007 OpenXML 格式使用 OpenXML SDK
如果决定 ASP.NET 应用程序仅处理 Office 2007 生成的 OpenXML 格式文档,那么使用 OpenXML SDK 是一个更好的主意,因为它不需要在服务器上安装 Office ,对客户端也没有任何要求,只要用的是 OpenXML 格式的文档就可以了,因为 OpenXML 格式已提交国际标准化组织,所以,用户可以使用支持 OpenXML 的任何应用程序读取和编辑该文档。
使用该方案需要下载 OpenXML SDK 并使用其进行开发,目前该 SDK 还只是一个 CTP 版本。
具体的 SDK 和参考资料可以到 MSDN 上搜索
5.Excel2007 依靠开源代码编程,如 ExcelPackage 。可以在http://www.codeplex.com/搜索到。
 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值