天天看點

導入Excel到DataTable中的兩種實作

导入Excel到数据库中是一个常见的操作,这里采用两种实现,一种比较简洁,一种侧重效率。

这里说明一下:导入的Excel可以包含多个sheet,最终都导入到dataset的同一个table中。

一、简洁实现:

        /// <summary>
        /// 导入Excel到DataSet中
        /// </summary>
        /// <param name="strFileSourse">文件的路径和文件全名,含扩展名</param>
        /// <returns></returns>
        public DataSet ExcelToDataSet(string strFileSourse)
        {
            DataSet ds = new DataSet();
            //Excel数据源(兼容03/10)
            string strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + strFileSourse + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\"";


            //连接
            OleDbConnection conn = new OleDbConnection(strConn);
            try
            {
                conn.Open();


                //获取Excel中所有的sheet
                DataTable dtSheet = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });




                //把Excel中所有的sheet数据读到一个Table中
                for (int i = 0; i < dtSheet.Rows.Count; i++)
                {
                    string strSheetName = dtSheet.Rows[i]["TABLE_NAME"].ToString();
                    OleDbDataAdapter OleDa = new OleDbDataAdapter("select * from [" + strSheetName + "]", conn);
                    OleDa.Fill(ds, "TableName");
                    conn.Close();
                }
            }
            catch (Exception)
            {
                //System.Windows.Forms.MessageBox.Show(e.ToString());
                throw;
            }
            finally
            {
                if (conn.State!=ConnectionState.Closed)
                {
                    conn.Close();
                }
            }
            
            return ds;
        }
           

二、侧重效率:

/// <summary>
        /// 导入Excel到DataSet中
        /// </summary>
        /// <param name="strFileUrl">文件的路径和文件全名,含扩展名</param>
        /// <returns></returns>
        public DataSet ImportExcel(string strFileUrl)
        {
           
            //创建进程
            Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.ApplicationClass();
            //获取Microsoft.Office.Interop.Excel进程启动结束的时间
            afterTime = DateTime.Now;  
            if (xlApp==null)
            {
                returnstatue = -1;
                returnmessage = "无法创建Microsoft.Office.Interop.Excel.Application对象,请先检查您的计算机是否安装了Office!";
                return null;
            }

            //判断要上传的文件是否正在被其他进程使用
            Microsoft.Office.Interop.Excel.Workbook workBook;
            try
            {
                workBook = xlApp.Workbooks.Open(strFileUrl, 0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, 1, 0);

            }
            catch (Exception)
            {

                returnstatue = -1;
                returnmessage = "Excel文件处于打开状态,请保存您的文件后关闭!";
                return null;
            }

            //获取所有Sheet名称
            int intSheetCount = workBook.Worksheets.Count;
            //根据sheet个数,定义字串数组
            string[] SheetSet = new string[intSheetCount];
            //System.Collections.ArrayList al = new System.Collections.ArrayList();
            //获取Excel中的sheet名数组
            for (int i = 0; i < intSheetCount; i++)
            {
                SheetSet[i - 1] = ((Microsoft.Office.Interop.Excel.Worksheet)workBook.Worksheets[i]).Name;

            }
            
            //释放Excel相关对象资源
            workBook.Close(null, null, null);

            xlApp.Quit();
            
          
            if (workBook!=null)
            {
                //系统中包含有很多释放com对象/cache等常见的所有资源的方法
                System.Runtime.InteropServices.Marshal.ReleaseComObject(workBook);
                workBook = null;
                
            }

            if (xlApp!=null)
            {
                //交由内存托管,马上释放资源(Interop互操作、Marshal整顿)
                System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
                xlApp = null;
            }

            //强制CLR执行内存回收
            GC.Collect();

            //获取了sheet数组后,作为数据源,将Excel中的数据读取到DataSet中
            DataSet ds = new DataSet();
            string strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + strFileUrl + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\"";
            using (OleDbConnection conn = new OleDbConnection(strConn))
            {
                conn.Open();
                OleDbDataAdapter da;
                for (int i = 0; i < intSheetCount; i++)
                {
                    string sql = "select * from ["+SheetSet[i-1]+"+$]";
                    da = new OleDbDataAdapter(sql, conn);
                    //将所有的数据集都填充到一个Table中
                    da.Fill(ds, "Table");
                    da.Dispose();
                }
                conn.Close();
                conn.Dispose();
            }


            TODO:销毁Excel进程
            Kill(xlApp);
            return ds;
        }
           

销毁进程:

[System.Runtime.InteropServices.DllImport("User32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        private static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
        /// <summary>
        /// 销毁Excel线程
        /// </summary>
        /// <param name="excel"></param>
        private void Kill(Microsoft.Office.Interop.Excel.Application excel)
        {
            //得到这个句柄,具体作用是得到这块内存入口
            IntPtr t = new IntPtr(excel.Hwnd);    

            int k = 0;
            //得到唯一标志k
            GetWindowThreadProcessId(t, out k);
            //k的引用
            System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(k);
            //关闭k
            p.Kill();
        }
           

以上是两种不同的实现,第二种更多的调用了操作系统的接口,这里只限于是Windows操作系统,包括销毁进程的方法,也是调用了系统的接口。