Excel的常用導出導入數據的實現


     說到Excel,那是叫個怕啊!一吧自己對Excel不熟悉,二吧大家都說Excel不好操作;心里上不知不覺就對它產生了畏懼。但是有句話說的好啊:你最怕的地方就是你最弱的地方。想要進步還是得想辦法提高自己,就去搞自己最怕的!

其實說到怕,也並不是真的怕,而是對這方面不熟悉造成的;想要解決怕的問題,就得把它整明白了,下次在遇見就不怕不怕了;最近幫同學做了個Excel處理的小程序;涉及到了一下Excel的操作,特此給大家分享一下。

1. Excel導入到數據庫的操作

 (1)、通過NPOI來實現。NPOI是個好東東,它能方便的讓你對Excel的控制達到單元格級別;而且使用起來也比較方便,不需要依賴office的什么組件;基本上引用了官方提供的那幾個dll就可以使用了。我在使用的過程中遇到了一個問題,NPOI提示缺少一個.dll,叫做:"ICSharpCode.SharpZipLib.dll",后來查了查資料,了解到Excel2007或2010的.xlsx格式的文件其實是壓縮文件,NPOI在處理.xlsx文件的時候需要先解壓縮,而解壓縮就用到了ICSharpCode.SharpZipLib.dll,這是個比較常用的dll,可能系統由於某種原因造成了dll的丟失,然后從網上找了好久才找到合適的dll文件,有需要的童鞋可以點擊"ICSharpCode.SharpZipLib.dll"下載我找的dll試試。

     NPOI的具體操作我就不再啰嗦了,大家可以點擊"學習NPOI"去仔細研究;通過NPOI操作Excel是個不錯的選擇,在數據量不是特別大的時候可以考慮使用;因為NPOI在加載Excel的時候需要讀取每個單元格的樣式、格式等信息,所以不太適合大數據量的操作。

 (2)、使用SqlBulkCopy類。類描述:使您可以用其他源的數據有效批量加載 SQL Server 表。吊,微軟的提供的類,想必很好用。通過程序測試了下,25W行的數量需要5秒左右;用法我大致說一下,不清楚的可以MSDN查查。

           思路:把Excel中的數據提取到內存DataTable中,然后通過SqlBulkCopy類寫入到數據庫,貼代碼:

public static void InsertDBFromExcelData(string excelFile, string tableName, SqlBulkCopyColumnMapping[] mappings)
        {
            string mystring = "Provider = Microsoft.Ace.OleDb.12.0 ; Data Source = '{0}';Extended Properties='Excel 12.0; HDR=Yes; IMEX=1'".With(excelFile);
            OleDbConnection cnnxls = new OleDbConnection(mystring);

            var allSheetNames = GetSheetNames(excelFile);
            foreach (string sheetName in allSheetNames)
            {
                OleDbDataAdapter myDa = new OleDbDataAdapter("select * from [{0}]".With(sheetName), cnnxls);
                DataTable dt = new DataTable();
                myDa.Fill(dt);
                if (dt.Rows.Count > 0)
                {
                    using (SqlBulkCopy copy = new SqlBulkCopy(DBConnectionStr))     //與目標服務器連接
                    {
                        copy.BulkCopyTimeout = 5000;
                        copy.DestinationTableName = tableName;                      //導入到數據庫的表名
                        if (mappings != null)
                        {
                            foreach (var item in mappings)
                            {
                                copy.ColumnMappings.Add(item);
                            }
                        }
                        copy.WriteToServer(dt);
                    }
                }
            }
        }
View Code

 

2.從數據庫導出到Excel

 (1)、使用NPOI寫入,具體用法我就不說了;測試的時候,循環寫入25W個單元格大致需要4~8秒,已經相當快了(未設置單元格的樣式等信息)。

 (2)、使用利用驅動來實現。比如Sqlserver數據庫,可以這么寫sql語句:  SELECT * FROM INTO [SheetName] TABLE in "" [ODBC;Driver=SQL SERVER;Data Source=.;DataBase=sa;Integrated security=true] ;然后這樣寫執行語句:

 string cnnString = "Provider = Microsoft.Ace.OleDb.12.0 ; Data Source = 'D:\Files\test.xlsx';Extended Properties='Excel 12.0; HDR=NO; IMEX=0'";

 using (OleDbConnection cnnxls = new OleDbConnection(cnnString)) { cnnxls.Open(); OleDbCommand cmd = new OleDbCommand(sql, cnnxls); cmd.ExecuteNonQuery(); cnnxls.Close(); } 

看sql語句和執行的鏈接串的寫法,大致也能猜出個什么意思。 Provider = Microsoft.Ace.OleDb.12.0  表示驅動程序是OleDb.12.0,Extended Properties='Excel 12.0; HDR=yes; IMEX=0' 表示的鏈接的擴展屬性:Excel12.0表示的是鏈接的Excel版本,如果是電腦中只安裝了Excel2003,則需修改為:Excel4.0;如果安裝了Excel2007或2010則不用修改了,一樣能處理.xls和.xlsx文件;"HDR=yes;"是說第一行是列名而不是數據,"HDR=no;"正好與前面的相反,把第一行也當成數據處理,這樣導入到數據庫表中的數據就會多出第一行的標題數據(如果你的Excel文件的第一行是標題);另外說明一下IMEX的意義,不寫了,抄了點兒,挺詳細的:

      當 IMEX=0 時為“匯出模式”,這個模式開啟的 Excel 檔案只能用來做“寫入”用途。
  當 IMEX=1 時為“匯入模式”,這個模式開啟的 Excel 檔案只能用來做“讀取”用途。
  當 IMEX=2 時為“連結模式”,這個模式開啟的 Excel 檔案可同時支援“讀取”與“寫入”用途。
     意義如下:
     0 ---輸出模式;
     1---輸入模式;
     2----鏈接模式(完全更新能力)
使用該方法可以快速的把Excel中的數據導入到數據庫中,我測試的是10列,25W行數據導入到Excel的時間只需要3秒即可;但是這個方法也有缺點,他不能對Excel的數據進行再加工;例如Excel數據格式的轉變,或者計算列等需要深加工的數據就沒什么辦法了;比如Excel中有一列是數字,但是當導入數據庫時可能就變成了科學表示法的文本了(10+E2),這樣的問題要么改Excel的單元格格式,要么在取的時候轉換一下。

 

另外遇到了一個奇怪的問題,就是去Excel所有工作簿的名字的問題,有時候明明一個工作簿,但是通過普通的方法總是能取到2個名字,比如:有一個工作簿:mysheet1;但是查詢到會存在兩個:mysheet1,mysheet1$,但其實不存在第二個工作簿。沒有深究,寫了方法干掉了第二個:

public static string[] GetSheetNames(string file)
        {
            List<string> names = new List<string>();
            string mystring = "Provider = Microsoft.Ace.OleDb.12.0 ; Data Source = '{0}';Extended Properties='Excel 12.0;'".With(file);
            using (OleDbConnection oleConn = new OleDbConnection(mystring))
            {
                oleConn.Open();
                DataTable dtOle = oleConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
                DataTableReader dtReader = new DataTableReader(dtOle);

                List<SheetName> allSheetNames = new List<SheetName>();
                foreach (DataRow row in dtOle.Rows)
                {
                    allSheetNames.Add(new SheetName(row));
                }
                allSheetNames = allSheetNames.Distinct(new SheetNameEquatilyCompare()).ToList();

                allSheetNames.ForEach(f =>
                {
                    names.Add(f.Name);
                });
                dtOle = null;
                oleConn.Close();
            }

            return names.Distinct().ToArray();
        }

//工作簿名稱自定義比較器
class SheetNameEquatilyCompare : IEqualityComparer<SheetName>
    {

        public bool Equals(SheetName x, SheetName y)
        {
            return x.ModifyTime == y.ModifyTime && x.CreateTime == y.CreateTime && x.Name.TrimEnd('$') == y.Name.TrimEnd('$');
        }

        public int GetHashCode(SheetName obj)
        {
            return 10;
        }
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM