數據處理之以OLEDB方式讀取Excel數據丟失的緣由及解決方法

1.引言

在應用程序的設計中,常常須要讀取Excel數據或將Excel數據導入轉換到其餘數據載體中,C#讀取Excel的方式有兩種,一種是經過OLEDB方式讀取,另外一種爲經過COM組件方式讀取。近段時間有客戶反映,讀取到程序中的Excel表,出現部分數據丟失的狀況,筆者在此採用的是第一種方式讀取(第二種讀取比較慢,且不易控制),因而檢查代碼還有各類找資料,終於解決了該問題,在此記錄致使丟失的緣由及解決方法。框架

2.丟失緣由

問題的根源與Excel ISAM(Indexed Sequential Access Method,即索引順序存取方法)驅動程序的限制有關,Excel ISAM 驅動程序經過檢查前幾行中實際值肯定一個 Excel 列的類型,而後選擇可以表明其樣本中大部分值的數據類型。也即Excel ISAM查找某列前幾行(默認狀況下是8行),把佔多的類型做爲其處理類型。例如若是數字佔多,那麼其它含有字母等文本的數據項就會置空;相反若是文本居多,純數字的數據項就會被置空。 ide

3.解決方式

(1)OLEDB鏈接字串

若Excel爲Excel997-2003版本(後綴爲「.xls」),讀取的驅動爲Jet,鏈接語句以下:spa

"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties='Excel 8.0;HDR={1};IMEX={2}'"

 若Excel爲Excel 2007及以後版本(後綴爲「.xlsx」),讀取的驅動爲ACE,鏈接語句以下:設計

「Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 12.0;HDR={1};IMEX={2}'」

其中:excel

當 IMEX=0 時爲「匯出模式」,這個模式開啓的 Excel 檔案只能用來作「寫入」用途;code

當 IMEX=1 時爲「匯入模式」,這個模式開啓的 Excel 檔案只能用來作「讀取」用途;blog

當 IMEX=2 時爲「連接模式」,這個模式開啓的 Excel 檔案可同時支援「讀取」與「寫入」用途;索引

當 HDR=Yes,這表明第一行是標題;string

當 HDR=No,第一行做爲數據內容。it

(2)解決一:修改源數據

當咱們設置IMEX=1時將強制混合數據轉換爲文本,但僅僅這種設置並不可靠,IMEX=1只確保在某列前8行數據至少有一個是文本項的時候才起做用,它只是把查找前8行數據中數據類型佔優選擇的行爲做了略微的改變。例如某列前8行數據全爲純數字,那麼它仍然以數字類型做爲該列的數據類型,隨後行裏的含有文本的數據仍然變空。 

(3)解決二:改動註冊表

設置IMEX=1,修改註冊表值TypeGuessRows(TypeGuessRows 值決定了ISAM 驅動程序從前幾條數據採樣肯定數據類型,默認爲「8」)爲0,程序就會默認行數爲最大。

對於修改註冊表不熟悉的讀者,具體步驟以下:

開始菜單,輸入「Regedit」,打開註冊表,找到「HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\」項,按下「Ctrl+F」鍵,輸入「TypeGuessRows」選擇「值」項,以下圖所示。

點擊【查找下一個】按鈕,查到找結果以下圖所示,筆者Office版本爲Office 2016 64bit。

右鍵該項,修改「TypeGuessRows」的值爲「0」便可,以下圖所示。

 

4.C#讀取Excel代碼

在此貼出C#讀取Excel表到DataTable的方法代碼:

public static DataTable GetExcelTableByOleDb(string excelPath, string tableName)
        {
            try
            {
                DataTable excelTable = new DataTable();     //數據表  
                DataSet ds = new DataSet();     //獲取文件擴展名    //Excel的鏈接
                OleDbConnection objConn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excelPath + ";Extended Properties='Excel 12.0;HDR=Yes;IMEX=1;'");
 if (objConn == null) { return null; } objConn.Open(); string strSql = "select * from [" + tableName + "]";//獲取Excel指定Sheet表中的信息
                OleDbDataAdapter myData = new OleDbDataAdapter(strSql, objConn); myData.Fill(ds, tableName);//填充數據 
                objConn.Close();      //dtExcel即爲excel文件中指定表中存儲的信息 
                excelTable = ds.Tables[tableName]; return excelTable; } catch { return null; } }

5.總結

至此,不完美的解決了該問題,由於兩種方法各有優缺點,受制於框架,這是沒法避免的,後邊有時間會寫一篇經過開源庫NPOI讀取及建立Excel(不須要安裝Office),以此完全解決限制問題。若是該篇博文對你有幫助,但願點個關注支持下。

相關文章
相關標籤/搜索