本帖最后由 Suriyel 于 2014-06-20 02:10:47 编辑

解决方案 »

  1.   


    郑笑彬 08:35:05
     public DataSet ImportFromExcel(string FilePath)
            {
                System.Data.DataTable dt = new System.Data.DataTable();
                ArrayList TablesList = new ArrayList();            System.Data.DataSet ds = new DataSet();            OleDbConnection dbcon = null;
                Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
                string ss = excelApp.Version;
                switch (ss)
                {
                    case "12.0":
                        dbcon = new OleDbConnection("Provider=Microsoft.ACE." + "OLEDB.12.0;Extended Properties=\"Excel 8.0\";Data Source=" + FilePath);
                        break;
                    default:
                        dbcon = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + FilePath + ";Extended Properties=Excel 8.0");
                        break;
                }            try
                {
                    TablesList = GetExcelTables(FilePath);                try
                    {
                        for (int i = 0; i < TablesList.Count; i++)
                        {
                            string str = "select * from [" + TablesList[i] + "$]";                        System.Data.DataTable table;                        OleDbCommand cmd = new OleDbCommand(str, dbcon);
                            OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);
                            table = new System.Data.DataTable(TablesList[i].ToString());                        adapter.Fill(table);
                            ds.Tables.Add(table);
                        }
                    }
                    catch (Exception exp)
                    {
                        MessageBox.Show(exp.Message, "读取EXCEL工作簿出错");
                    }
                }
                finally
                {
                }
                return ds;
            }
    使用Microsoft.Office.Interop.Excel.Apllication可以直接读取整个文档到dataset啊
    也可以指定单个sheet读取到datatable
    怎么可能只能按Range读取呢
      

  2.   

    从代码上来看,好像你只用application判断了下Excel版本,还是使用的oledb进行Excel数据读取,那么还是会有内存泄露问题。
      

  3.   

    NPOI呢?
    额,我们这边对开源项目审核的比较厉害,所以能不用开源的尽量没有用,哎
      

  4.   

            private static void KillExcel()
            {
                Process killer = new Process();
                try
                {
                    foreach (Process thisproc in Process.GetProcessesByName("EXCEL"))   //循环查找
                    {
                        string str = thisproc.MainWindowTitle; //发现程序中打开跟用户自己打开的区别就在这个属性
                        //用户打开的str 是文件的名称,程序中打开的就是空字符串
                        if (string.IsNullOrEmpty(str))
                        {
                            thisproc.Kill();
                        }
                    }
                }
                catch
                {
                    string msg = "关闭失败";
                    MessageBox.Show(msg);
                }
            }
    有没有看进程里是否多了很多EXCEL进程?每次操作完杀死多余的没有界面的EXCEL进程试试.
      

  5.   

    我回复的就是针对:
    2,直接使用Microsoft.Office.Interop.Excel.Apllication进行Excel操作,并在操作后直接杀掉Excel进程。
    但是该方法因为Microsoft.Office.Interop.Excel.Apllication进行Excel读取,每个Range每个Range的读取,都是进程间进行数据交换,性能太渣。唯一可行的是,一大块一大块的读数据,但是没有找到对应的方法可以整个文档读取啊.
      

  6.   


    谢谢你的回复,这贴的关键讨论点,就是使用OleDb会导致内存泄露,这就是我使用application而不使用OleDb(你贴的代码里使用的方式)的原因,您贴的这个第2点,是在这个基础上说,application操作Excel性能消耗太大,不可用。我希望的是能够解决OleDb的内存泄露,但是您代码里直接使用的是OleDb,是不能解决这个问题的。
      

  7.   

    理下楼主的主要需求
    1,不能直接在当前进程中进行OleDb读取Excel。因为按楼主说的,OleDb存在内存泄露。
    那么解决思路应该有以下几个方向:
    1,能否用其他的方法进行Excel的读取。
    2,能否再其他进程进行Excel的读取,然后将结果传给当前进程。思路1,要么使用开源的Excel读取程序,要么使用Excel的Application,但按楼主的意思,这两个都不行。
    那么只能采用第2种思路了。对于思路2,最关键的应该是,采用什么的形式将结果传给当前进程。
    需要注意以下的约束:
    1,是否需要考虑较大的Excel文件。
    2,是通过进程间通信传,还是通过转为文本,主程序读取获得。考虑到以上的约束,我建议楼主另外开个进程,使用OleDb把Excel里所需的数据,转为csv或者txt,主线程可以使用Reader逐行读取解析。既可以规避你说的内存泄露问题,又最大限度的不影响性能和内存开销。
      

  8.   

    刚做了ADODB读取EXCEL功能,可以将EXCEL当数据库读
    数据库连接串就是版本号那一套,跟OLEDB一样
    用户名密码为空
    唯一缺点就是必须事先知道Sheet名称或者可以用第三方插件,比如NOPI?
      

  9.   

    就是ADO,OleDb读取Excel,存在内存泄露啊,你用一个大一点的Excel,只是Open再Close试试,内存是没有回退到原有水平的,调了Gc都没用。我感觉Shannon的方法比较可行。
      

  10.   

    这个是老毛病了,换个高版本的,或者把excel文件先改成只读,再读取,然后改回来就行了
      

  11.   


    改成只读,内存还是有泄露啊
    换个高版本指的的是Framework还是office?
      

  12.   

    还是改用NPOI算了,还方便,不用考虑用户安装的OFFICE版本,也不用考虑用户是否用的WPS
      

  13.   

    http://club.excelhome.net/thread-464455-1-1.html或者
    Provider=Microsoft.ACE.OLEDB.12.0试试吧
      

  14.   

    很明显,如果你搞不明白基本概念,那么就算你瞎用什么软件来代替,都脱离不了基本的托管程序系统的内存分配策略的制约。不管用什么PPOO的软件,你都会说它“内存泄露”的。而且另一个问题是,不管用什么软件,如果你要在内存里将多个 900M 的Excel文件内容同时读取到内存里,都一样会崩溃。