C#徹底解決Oledb連接Excel數(shù)據(jù)類型不統(tǒng)一的問題
在使用Microsoft.Jet.OLEDB.4.0連接Excel,進行讀取數(shù)據(jù),相對使用傳統(tǒng)的COM來讀取數(shù)據(jù),效率是很高的。但相對傳統(tǒng)COM操作Excel來說,及存在數(shù)據(jù)類型轉(zhuǎn)換的問題。
因為使用OLEDB連接Excel讀取數(shù)據(jù)時,需要確定數(shù)據(jù)的類型。默認情況使用連接字符串:
view source
print ?
1. string connStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + excelFile + ";Extended Properties='Excel 8.0;'";
使用上面的連接字符串連接Excel時,可能會遇到數(shù)據(jù)類型不一致的問題。所謂數(shù)據(jù)類型不一致,是指同一列里面數(shù)據(jù)類型可能出現(xiàn)多種,如浮點數(shù)、字符串、日期等;當出現(xiàn)此類情況時,讀取出來的數(shù)據(jù)就為空,甚至會報錯,如“非法的日期格式”等異常。出現(xiàn)這種問題,我們大家都會想到把數(shù)據(jù)全部都按字符數(shù)據(jù)來讀取,但是按什么數(shù)據(jù)類型來讀取不是我們能控制的,是OLEDB控制的,至少暫時我還沒有找到能控制輸出數(shù)據(jù)類型的方法。因為我當初也嘗試使用convert,cast函數(shù)對輸出的列進行類型轉(zhuǎn)換,但oledb連接Excel時,使用的SQL不支持這些函數(shù)。因此只能從其他角度來解決該問題。我也在網(wǎng)上搜索了很多解決方法,最全面的解決方法是:http://www.douban.com/note/18510346/。下面列出了網(wǎng)上出現(xiàn)解決該問題方法的比較:
這里提供一個更加方便的辦法,不過前提是***行必須是作為字段名或者***行的數(shù)據(jù)類型就為字符型。這樣一說,大家就明白了。首先修改連接字符串為:
- view source
 - print ?
 - //2003(Microsoft.Jet.Oledb.4.0)
 - string strConn = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties='Excel 8.0;HDR=Yes;IMEX=1;'", excelFilePath);
 - //2010(Microsoft.ACE.OLEDB.12.0)
 - string strConn = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 8.0;HDR=Yes;IMEX=1;'", excelFilePath);
 
這里將HDR設為NO,因為我就是將***行做為數(shù)據(jù)讀取,而IMEX=1就表示根據(jù)前8行判斷列的數(shù)據(jù)類型,如果有字符型數(shù)據(jù),那么就強制混合數(shù)據(jù)轉(zhuǎn)換為 文本。這里就明白為什么要保證***行為字符型的原因了。能將列的數(shù)據(jù)類型強制設為字符型,那么列中出現(xiàn)什么類型的數(shù)據(jù)都不怕了。需要做的工作就是,在獲取 完數(shù)據(jù)后,將字段名重新設置,并刪除***條記錄即可。代碼如下:
- view source
 - print ?
 - 01. DataTable dt = new DataTable();
 - 02.
 - 03. using(OleDbCommand cmd = new OleDbCommand()){
 - 04. cmd.Connection = conn;
 - 05. cmd.CommandType = CommandType.Text;
 - 06. cmd.CommandTimeout = 6;
 - 07. cmd.CommandText = string.Format("select * from [{0}$]", sheetName);
 - 08.
 - 09. OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);
 - 10. adapter.Fill(dt);
 - 11. }
 - 12.
 - 13. if (dt.Rows.Count > 0) {
 - 14. DataRow dr = dt.Rows[0];
 - 15.
 - 16. for (int col = 0; col < dt.Columns.Count; col++) {
 - 17. dt.Columns[col].ColumnName = dr[col].ToString();
 - 18. }
 - 19.
 - 20. dt.Rows[0].Delete();
 - 21. dt.AcceptChanges();
 - 22. }
 



















 
 
 




 
 
 
 