C#讀取excel文件數據丟失問題


 最近在處理C#讀取excel文件時碰到了個BT問題,有部分數據讀取失敗了,翻看了不少資料,終於找到了問題的所在,所以在這里跟大伙分享下:

簡要問題分析:

用C#讀取excel文件數據時,出現數據丟失現象。

經查資料,發現產生這種問題的根源與Excel ISAM[3](Indexed Sequential Access Method,即索引順序存取方法)驅動程序的限制有關,Excel ISAM 驅動程序通過檢查前幾行中實際值確定一個 Excel 列的類型,然后選擇能夠代表其樣本中大部分值的數據類型[4]。也即Excel ISAM查找某列前幾行(默認情況下是8行),把占多的類型作為其處理類型。例如如果數字占多,那么其它含有字母等文本的數據項就會置空;相反如果文本居多,純數字的數據項就會被置空。

相關知識:

現具體分析HDR和IMEX所代表的含義。

HDR用來設置是否將Excel表中第一行作為字段名,“YES”代表是,“NO”代表不是即也為數據內容;

IMEX是用來告訴驅動程序使用Excel文件的模式,其值有0、1、2三種,分別代表導出、導入、混合模式。當我們設置IMEX=1時將強制混合數據轉換為文本,但僅僅這種設置並不可靠,IMEX=1只確保在某列前8行數據至少有一個是文本項的時候才起作用,它只是把查找前8行數據中數據類型占優選擇的行為作了略微的改變。例如某列前8行數據全為純數字,那么它仍然以數字類型作為該列的數據類型,隨后行里的含有文本的數據仍然變空。

網絡上大部分的解決方法:

1、修改連接字符串:

如原來的連接字符串為: string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Path + "; Extended Properties=Excel 8.0;";  

將其修改為:string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Path + ";Extended Properties=Excel 8.0;IMEX=1;";

2、我還看到的一些改進的措施是IMEX=1與注冊表值TypeGuessRows配合使用

TypeGuessRows 值決定了ISAM 驅動程序從前幾條數據采樣確定數據類型,默認為“8”。可以通過修改“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Excel”下的該注冊表值來更改采樣行數。但是這種改進還是沒有根本上解決問題,即使我們把IMEX設為“1”, TypeGuessRows設得再大,例如1000,假設數據表有1001行,某列前1000行全為純數字,該列的第1001行又是一個文本,ISAM驅動的這種機制還是讓這列的數據變成空。

故此,以上兩種解決方式都存在着一定的弊端。經過仔細的查閱資料,總結出如下方法:

解決辦法:

從以上的分析中可以得知,當某列數據中含有混合類型時,在.NET中使用Microsoft.Jet.OLEDB.4.0來讀取Excel文件造成數據丟失是不可避免的,要解決這個問題只能考慮采用其它數據讀取方法。 在.NET中讀取Excel文件的另外一種方法是回到使用傳統COM組件,這種方法在很多技術文章或論文中都有涉及,本文不作贅述。需要指出的是,使用COM組件來讀取Excel文件數據的效率較低,在作釋放的時候有可能碰到不可預知的錯誤,特別開發Web應用的程序應該慎重使用。  (不推薦使用)不過在網上查到了另外一種利用讀取CSV純文本格式解決此問題的方法。   (1)在讀取Excel的.xls類型的文本數據之前,先將其轉換為.csv格式,在Excel中直接另存為這種格式就可以達到轉換的目的。CSV文件又稱為逗號分隔的文件,是一種純文本文件,它以“,”分隔數據列,本文表1的數據表用CSV格式存儲后用純文本編輯器打開的表現形式如表3所示。   表3 采用CSV格式保存的表1數據   需要指出的是,CSV文件也可以用Ole DB或ODBC的方式讀取,但是如果采用這些方式讀取其數據又會回到丟失數據的老路上,ISAM機制同樣會發揮作用。   (2)采用普通的讀取文本文件的方法打開文件,讀取第一行,用“,”作為分隔符獲得各字段名,在DataTable中創建對應的各字段,字段的類型可以統一創建成“String”。   本文原文  (3)逐行讀取數據行, 用“,”作為分隔符獲得某行各列的數據並填入DataTable相應的字段中。   實現的簡化代碼如下:   String line;   String [] split = null;   DataTable table=new DataTable("Thylx");   DataRow row=null;   StreamReader sr=new StreamReader("c:/Thylx.csv",System.Text.Encoding.Default);   //創建與數據源對應的數據列   line = sr.ReadLine();   split=line.Split(',');   foreach(String colname in split){   table.Columns.Add(colname,System.Type.GetType("System.String")); }   //將數據填入數據表   int j=0;   while((line=sr.ReadLine())!=null){    j=0;    row = table.NewRow();    split=line.Split(',');    foreach(String colname in split){    row[j]=colname;    j++;}    table.Rows.Add(row);}    sr.Close();   //顯示數據   dataGrid1.DataSource=table.DefaultView;   dataGrid1.DataBind(); 總結: 在應用程序的設計中,需要訪問Excel數據的情況非常普遍,本文以在.NET中對訪問含有混合類型數據的Excel表格擬采取的方法進行探討。當然,如果不存在混合類型的數據使用Microsoft.Jet.OLEDB為較佳方案,也就是我上面提到的在網絡中查到的大部分做法。本文只是針對NET方面的一些研究,對於其他開發語言,可參照類似的做法來解決excel讀取時數據丟失的問題


免責聲明!

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



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