假設我們有如下一個Excel表格:
現在要使用C#程序讀取其內容:
該程序的運行結果如下:
看來在讀取單元格“B3”時返回了“DBNull”,而不是正確的“1768”。使用我的博客園發表的一篇隨筆“數據庫小工具(C#)”中給出的 OleDb.exe 查看了一下:
確實,該 Execl 表格中有 2 個“DBNull”值,再用該工具查看一下其結構:
發現其第一列“ID”的數據類型是“double”,第二列“NAME”的數據類型是“string”。經分析,“DBNull”都出現在其數據類型與列的數據類型不相符的單元格中。看來,問題的症結就在這裡了。我們知道,Excel 表格並是不真正的數據庫,不像真正的數據庫一樣每個字段(列)都有一個特定的數據類型,而是由ADO.NET通過掃描該表格的開頭幾行來推測其每一列的數據類型,這樣,當某列中有些單元格的數據類型與該列數據類型不一致時,就出問題了,該單元格的值就變成的“DBNull”。
這個問題來源於我的實際工作。在工作中,需要分析一張業務部門提供的 Excel 表格中的數據,該表格有好幾千個數據行,其中有些列絕大部分的值是數字型,但其中有一些數字存儲為文本格式。而有些列絕大部分的值是字符型,但有少數單元格的值是數字。這樣,我的分析程序就不能工作了。我目前的解決方案是將該 Excel 表格另存為文本文件(制表符分隔),然後在 C# 程序中讀取該文本文件。
還有一種方法就是在 Excel 表格中選中整列,然後“將存為文本的數字轉換為數字”,如下所示:
但是,我並沒有找到一個簡便的方法來“將數字轉換為文本”。
不知在 ADO.NET 中有沒有辦法在不改變原始 Excel 表格的情況下,正確讀取其列中有單元格的數據類型不一致的 Excel 表格中的數據?如果誰知道的話,懇請告訴我。謝謝!
不知道要通過什麼途徑向 Microsoft 報告這個 BUG ?
我認為這個 BUG 的解決方案有兩個:
1. 如果某一列被推測為數字型的話,如果在該列中出現字符型的數據,如果該數據是存儲為文本的數字,就直接轉換為數字返回給調用者好了。如果該數據不能轉換為數字,可以返回“DBNull”,或者拋出異常。
如果某一列被推測為字符型的話,只要該列中的單元格不為空,就轉換為字符型返回給調用者。
2. 在 ADO.NET 的 OleDb 連接串中提供一個屬性強制指定 Excel 表格中的所有列的數據類型都為“string”,只要單元格的內容不為空,就不返回“DBNull”,而返回“string”。然後由調用者自己使用 Convert.ToXXX() 方法轉換到合適的數字類型。
不知大家以為然否?