程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> ADO.NET(OleDb)讀取Excel表格時的一個BUG

ADO.NET(OleDb)讀取Excel表格時的一個BUG

編輯:關於C#
 

假設我們有如下一個Excel表格:

現在要使用C#程序讀取其內容:
 

using System;
using System.Data.OleDb;

namespace Skyiv.Ben.Test
{
  sealed class ExcelTest
  {
    static void Main()
    {
      try
      {
        using (OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=\"Excel 8.0;HDR=yes\";Data Source=Std"))
        {
          conn.Open();
          OleDbCommand comm = new OleDbCommand("SELECT [ID],[NAME] FROM [Sheet1$]", conn);
          using (OleDbDataReader r = comm.ExecuteReader())
          {
            while (r.Read())
            {
               int id = Convert.ToInt32(r.GetValue(0));
               string name = Convert.ToString(r.GetValue(1));
               Console.WriteLine("{0}:\t{1}", id, name);
            }
          }
        }
      }
      catch (Exception ex)
      {
        Console.WriteLine("錯誤: " + ex.Message);
      }
    }
  }
}

該程序的運行結果如下:

看來在讀取單元格“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() 方法轉換到合適的數字類型。
不知大家以為然否?

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved