• .NET基础示例系列之十五:操作Excel


    Excel表格文档由于其简单易用,普遍应用于不少单位或部门,因而在编写应用程序过程中,有时会需要对Excel文档进行操作,最简单的情况通常有两种:(1)需要获取文档中一些单元格的值;(2)将文档导入至数据库。

     

    1).在操作Excel文档之前,需要添加对Excel对象库的引用:

    引用—COMMicrosoft Excel 11.0 Object Library(版本号可能不同)

     

    2).以下代码示意打开一个已有的Excel文档的第一个sheet页,获取单元格“B1的内容,并判断其值是否为“my”:

            private void Operate(string pFileName)
            
    {
                Excel.Application app 
    = new Excel.Application();//打开一个Excel应用
                if (app == null)
                
    {
                    
    return;
                }


                Workbooks wbs 
    = app.Workbooks;
                _Workbook wb 
    = wbs.Add(pFileName);//打开一个现有的工作薄
                Sheets shs = wb.Sheets;
                _Worksheet sh 
    = (_Worksheet)shs.get_Item(1);//选择第一个Sheet页
                if (sh == null)
                
    {
                    
    return;
                }


                Range r 
    = sh.get_Range("B1", Missing.Value);
                
    if (System.Convert.ToString(r.Value2).Trim().Equals("my"))
                
    {
                    
    //Do Something.
                }

            }

     

    3).

    不少人在打开Excel应用后,对如何在使用完成后释放它大感头痛,在网上我找到一种方法,经过实验证明是OK的:

            private void ReleaseCOM(object pObj)
            
    {
                
    try
                
    {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(pObj);
                }

                
    catch
                
    {
                    
    throw new Exception("释放资源时发生错误!");
                }

                
    finally
                
    {
                    pObj 
    = null;
                }

            }

    有了该方法,则只要在步骤2)代码之后添加以下代码,就可以完成对资源的释放:

            private void Operate(string pFileName)
            

    ……
    //释放资源
                ReleaseCOM(sh);
                ReleaseCOM(shs);
                ReleaseCOM(wb);
                ReleaseCOM(wbs);
                app.Quit();
                ReleaseCOM(app);
            }


    4).

    基于Excel中的函数可以编辑出相当复杂的公式,有时候在处理Excel文档时,希望使用Excel中的公式,以下结合FREQUENCYMATCH函数对B列计算distinct count,将其写入B100单元格(假定有数据的行不超过100行):

            string  count = sh.UsedRange.Rows.Count.ToString();
            Range r 
    = sh.get_Range("B100",Missing.Value);
            r.Formula 
    = "=SUM(IF(FREQUENCY(MATCH(B1:B" + count + ",B1:B" + count + ",0),MATCH(B1:B" + count + ",B1:B" + count + ",0))>0,1))";
            Console.WriteLine(System.Convert.ToString(r.Value2));


    5).

    Excel导入数据,可以先使用ODBC,以select查询时使用“[sheet页名称$]”作为“表名”,将数据以datatable形式载入到内存中,之后的事就比较简单了,可以根据datatable逐行构造insert语句,然后插入到目标数据库中:

            private DataTable LoadExcel(string pPath)
            
    {
                
    string connString = "Driver={Driver do Microsoft Excel(*.xls)};DriverId=790;SafeTransactions=0;ReadOnly=1;MaxScanRows=16;Threads=3;MaxBufferSize=2048;UserCommitSync=Yes;FIL=excel 8.0;PageTimeout=5;";
                connString 
    += "DBQ=" + pPath;
                OdbcConnection conn 
    = new OdbcConnection(connString);
                OdbcCommand cmd 
    = new OdbcCommand();
                cmd.Connection 
    = conn;
                
    //获取Excel中第一个Sheet名称,作为查询时的表名
                string sheetName = this.GetExcelSheetName(pPath);
                
    string sql = "select * from [" + sheetName.Replace('.''#'+ "$]";
                cmd.CommandText 
    = sql;
                OdbcDataAdapter da 
    = new OdbcDataAdapter(cmd);
                DataSet ds 
    = new DataSet();
                
    try
                
    {                
                    da.Fill(ds);
                    
    return ds.Tables[0];
                }

                
    catch (Exception x)
                
    {
                    ds 
    = null;
                    
    throw new Exception("从Excel文件中获取数据时发生错误!");
                }

                
    finally
                
    {
                    cmd.Dispose();
                    cmd 
    = null;
                    da.Dispose();
                    da 
    = null;
                    
    if (conn.State == ConnectionState.Open)
                    
    {
                        conn.Close();
                    }

                    conn 
    = null;
                }

            }


            
    private string GetExcelSheetName(string pPath)
            
    {
                
    //打开一个Excel应用
                Excel.Application app = new Excel.Application();
                
    if (app == null)
                
    {
                    
    throw new Exception("打开Excel应用时发生错误!");
                }

                Excel.Workbooks wbs 
    = app.Workbooks;
                
    //打开一个现有的工作薄
                Excel._Workbook wb = wbs.Add(pPath);
                Excel.Sheets shs 
    = wb.Sheets;
                
    //选择第一个Sheet页
                Excel._Worksheet sh = (Excel._Worksheet)shs.get_Item(1);
                
    string sheetName = sh.Name;

                ReleaseCOM(sh);
                ReleaseCOM(shs);
                ReleaseCOM(wb);
                ReleaseCOM(wbs);
                app.Quit();
                ReleaseCOM(app);
                
    return sheetName;
            }

    (string sql = "select * from [" + sheetName.Replace('.', '#') + "$]";”如果sheet页名称中含有“.”,则要将其替换为“#”,具体原因,没研究出来-_-。另外贴一张界面截图:)

     

    6).关于从Excel导入数据,网上应该有很多例子,这里补充一个关于数据导入时的效率问题。最初在从Excel导入数据到MySql中时,当文件达到50000行时,逐行导入花了10余分钟的时间。大量执行插入操作,逐条执行很慢原因可能在于:

    (1)每执行一条插入语句,客户端需要与服务器交互一次,这要有代价

    (2)一些数据库对每一条插入操作都执行事务,这也要有代价

    所以在大量执行插入操作时,应该尽量先多个insert语句拼接好,例如每次拼接好200insert语句,然后再一次执行它,这样可以大幅提高效率。

  • 相关阅读:
    dp,路径保存,最大公共上升子序列——ZOJ
    简单dp——HDU
    扫描线,线段树,离散化——HDU
    c++版本的opencv3.4.1里分类器输出值异常
    win10家庭版openssh连接远程服务器显示connetion reset
    生活感悟一
    Teradata简介
    kettle 无法正常启动问题
    kettle实现同构单表增量同步
    kettle数据库连接使用变量
  • 原文地址:https://www.cnblogs.com/morvenhuang/p/660147.html
Copyright © 2020-2023  润新知