2013年10月3日 星期四

讀 Excel 資料時,我是該用 Sheet1 還是工作表1 ?

常常在網路上看到許多前輩介紹 C# 讀取 Excel 檔案內容時,會使用 OleDbConnection 方式,以下面語法來讀取 Excel 內的 Sheet1 內容。

SELECT * FROM [Sheet1$]



但當我使用較新的中文版 Excel 時,Excel 裡的 Sheet 名稱預設是 「工作表1」,如此我就得將上面的 SQL 語法改成

SELECT * FROM [工作表1$]

一旦開放讓使用者自行上傳 Excel 檔案以供讀取檔案內容時,我怎麼知道裡面的 Excel 內容是 Sheet1 還是 工作表1 呢?

遇到這兩難的情況時,可以試試 OleDbConnection 類別裡的 GetSchema() 方法,他可以回傳資料來源的結構描述資訊,其回傳的資料格式為 DataTable。接著就可以透過這 DataTable 來判斷使用者所上傳的 Excel 的 Sheet 名稱到底是叫「阿貓」還是「阿狗」了。我試著將這 DataTable 的內容整理如下,就可以很清楚的瞭解裡頭到底藏了些什麼內容。



透過上面的圖表,可以發現 GetSchema()所回傳的 DataTable 裡頭,有一個欄位 TABLE_NAME 。他主要是紀錄著 Excel 裡面每一個 Sheet 的名稱。如果我只需關心第一個 Sheet 的名稱,那只要取第一筆 TABLE_NAME 就可以正確得到我想要的資訊了。

試著完成讀取 Excel 內容的程式碼就如下所示:
protected void btnImport_Click(object sender, EventArgs e)
{
    DataTable tablesInFile;
    string currentTable;
    string xlsFullName = Server.MapPath("Test.xlsx");
    string OleConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + xlsFullName + ";Extended Properties='Excel 12.0 Xml;HDR=No;IMEX=1'";
    OleDbConnection OleCn = new OleDbConnection(OleConStr);
    OleDbCommand OleCmd = new OleDbCommand();
    OleCmd.Connection = OleCn;

    try
    {
        OleCn.Open();

        //透過 GetSchema 取得資料來源的結構描述資訊
        tablesInFile = OleCn.GetSchema("Tables");

        //只取第一筆 Sheet 名稱
        DataRow tableInFile = tablesInFile.Rows[0];
        currentTable = tableInFile["TABLE_NAME"].ToString();

        //調整後的 SQL 語法
        string strSQL = string.Format(@"SELECT * FROM [{0}]", currentTable);
        OleCmd.CommandText = strSQL;


        DataSet ds = new DataSet();
        OleDbDataAdapter odda = new OleDbDataAdapter(strSQL, OleCn);
        odda.Fill(ds, currentTable);           

        OleCn.Close();
        odda.Dispose();
          
    }
    catch(Exception ex)
    {
    }
}

參考:
01:OleDbConnection.GetSchema 方法
02:以指令碼工作處理 Excel 檔案

沒有留言:

張貼留言