熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

ado.net 如何讀取 excel

2022-06-13   來源: .NET編程 
    經常需要在數據庫與Execl之間互導數據net時代ADONET可以使用使用MicrosoftJetOleDb訪問訪問Excel網上已經有很多類似的資源最典型也是最簡單的可能如下(環境)
    // 連接字符串
    string xlsPath = ServerMapPath(~/app_data/somefilexls); // 絕對物理路徑
    string connStr = PRovider=MicrosoftJetOLEDB; +
    Extended Properties=Excel ; +
    data source= + xlsPath;
    // 查詢語句
    string sql = SELECT * FROM [Sheet$];
    DataSet ds = new DataSet();
    OleDbDataAdapter da = new OleDbDataAdapter(sql connStr);
    daFill(ds);    // 填充DataSet
    // 在這裡對DataSet中的數據進行操作
    // 輸出綁定數據
    GridViewDataSource = dsTables[];
    GridViewDataBind();
    很簡單吧?!一切就像操作數據庫一樣只是需要注意的是
   數據提供程序使用Jet同時需要指定Extended Properties 關鍵字設置 Excel 特定的屬性不同版本的Excel對應不同的屬性值用於 Extended Properties 值的有效 Excel 版本
    對於 Microsoft Excel () () 和 () 工作簿請使用 Excel
    對於 Microsoft Excel () 工作簿請使用 Excel
    對於 Microsoft Excel 工作簿請使用 Excel
    對於 Microsoft Excel 工作簿請使用 Excel
    ref*url=/library/CHS/dv_vbcode/html/vbtskcodeexamplereadingexceldataintodatasetasp
   數據源路徑使用物理絕對路徑(同access)
   如何引用表名?
    對 Excel 工作簿中表(或范圍)的有效引用
    若要引用完全使用的工作表的范圍請指定後面跟有美元符號的工作表名稱例如
    select * from [Sheet$]
    若要引用工作表上的特定地址范圍請指定後面跟有美元符號和該范圍的工作表名稱例如
    select * from [Sheet$A:B]
    若要引用指定的范圍請使用該范圍的名稱例如
    select * from [MyNamedRange]
    ref*url=/library/CHS/dv_vbcode/html/vbtskcodeexamplereadingexceldataintodatasetasp
    說明
    可以引用Excel 工作簿中的三種對象
    * 整張工作表[Sheet$]  Sheet 就是工作表的名稱
    * 工作表上的命名單元格區域[MyNamedRange] (不需要指定工作表因為整個xls中命名區域只能唯一)
    XLS命名方法選中單元格范圍》插入》名稱》定義
    * 工作表上的未命名單元格區域 [Sheet$A:B]
    (在關系數據庫提供的各種對象中(表視圖存儲過程等)Excel 數據源僅提供相當於表的對象它由指定工作簿中的工作表和定義的命名區域組成命名區域被視為而工作表被視為系統表
    注意
    *必須使用[](方括號)否將報
    FROM 子句語法錯誤
    *必須跟$(美元符號)否則報
    Microsoft Jet 數據庫引擎找不到對象Sheet請確定對象是否存在並正確地寫出它的名稱和路徑
    *如果工作表名稱不對或者不存在將報
    Sheet$ 不是一個有效名稱請確認它不包含無效的字符或標點且名稱不太長
    *在 如何在 Visual Basic 或 VBA 中使用 ADO 來處理 Excel 數據   中提到可以使用
    ~  和 (波浪線和單引號)代替[]使用ADONET測試沒有成功
    FROM 子句語法錯誤
    *當引用工作表明名([Sheet$])時數據提供程序認為數據表從指定工作表上最左上方的非空單元格開始比如工作表從第 C 列開始C列之前以及第行全為空則只會顯示從第C列開始的數據以最後表最大范圍內的非空單元結束
    *因此如需要精確讀取范圍應該使用命名區域 [NamedRange]或者指定地址[Sheet$A:C]


   如何引用列名?
    *根據默認連接字符串中數據提供程序會將有效區域內的第一行作為列名如果此行某單元格為空則用FF表示其中序數跟單元格的位置一致開始
    *如果希望第一行作為數據顯示而非列名可以在連接串的 Extended Properties 屬性指定HDR=NO
    默認值為HDR=NO 格式如下
    string connStr = Provider=MicrosoftJetOLEDB; +
    Extended Properties=\Excel ;HDR=NO\; +
    data source= + xlsPath;
    注意 Excel ;HDR=NO  需要使用雙引號(這裡的反斜扛是C#中的轉義)
    refmshelp://MSVSCCv/MSMSDNv/MSVisualStudiovchs/WD_ADONET/html/cffb 中 《連接Excel》節(說明在我自己的MSDN中它的例子使用了兩個雙引號是錯的測試沒有通過原文這樣說的
    注意Extended Properties 所需的雙引號必須還要加雙引號
    )
    在這種情況下所有的列名都是以F開頭然後跟索引從F開始FF
    為什麼有效單元格數據不顯示出來?
    出現這種情況的可能原因是默認連接中數據提供程序根據前面單元格推斷後續單元個的數據類型
    可以通過 Extended Properties 中指定 IMEX=
    IMEX=;通知驅動程序始終將互混數據列作為文本讀取
    ref
    PS在baidu這個問題的時候有網友說將每個單元都加上引號這固然是格方案但是工作量何其大啊又不零活慶幸自己找到治本藥方
    more ref
    如何在 Visual Basic 或 VBA 中使用 ADO 來處理 Excel 數據
    /ShowDetailaspx*id=CECDFECEDBA
    應用程序經常需要與Excel進行數據交互以上闡述了基於ADONET 讀取Excel的基本方法與技巧現在要介紹是如何動態的讀取Excel數據這裡的動態指的是事先不知道Excel文件的是什麼樣的結構或者無法預測比如一張xls文件有多少張sheet而且每張sheet的結構可能都不一樣等等
    其實我們可以通過獲取Excel的架構信息來動態的構造查詢語句這裡的架構信息與數據庫領域的數據庫架構信息意義相同(也稱元數據對於整個數據庫這些元數據通常包括數據庫或可通過數據庫中的數據源表和視圖得到的目錄以及所存在的約束等而對於數據庫中的表架構信息包括主鍵列和自動編號字段等
    在上文中提到
    在關系數據庫提供的各種對象中(表視圖存儲過程等)Excel 數據源僅提供相當於表的對象它由指定工作簿中的工作表和定義的命名區域組成命名區域被視為而工作表被視為系統表
    這裡我們將Excel也當作一個數據庫來對待然後利用OleDbConnectionGetOleDbSchemaTable 方法
    要獲取所需的架構信息該方法獲取的架構信息與ANSI SQl是兼容的
    注意對於那些不熟悉 OLE DB 架構行集的人而言它們基本上是由 ANSI SQL 定義的數據庫構造的標准化架構每個架構行集具有為指定構造提供定義元數據的一組列(稱作 NET 文檔中的限制列這樣如果請求架構信息(例如列的架構信息或排序規則的架構信息)則您會明確知道可以得到哪種類型的數據如果希望了解更多信息請訪問 Appendix B:Schema Rowsets


    refx*mfr=true
    以下是讀取Excel文件內定義元數據並顯示出來的的程序片斷
    // 讀取Excel數據填充DataSet
    // 連接字符串
    string xlsPath = ServerMapPath(~/app_data/somefilexls);
    string connStr = Provider=MicrosoftJetOLEDB; +
    Extended Properties=\Excel ;HDR=No;IMEX=\; + // 指定擴展屬性為 Microsoft Excel () () ()並且第一行作為數據返回且以文本方式讀取
    data source= + xlsPath;
    string sql_F = SELECT * FROM [{}];
    OleDbConnection conn = null;
    OleDbDataAdapter da = null;
    DataTable tblSchema = null;
    IList<string> tblNames = null;
    // 初始化連接並打開
    conn = new OleDbConnection(connStr);
    connOpen();
    // 獲取數據源的表定義元數據
    //tblSchema = connGetSchema(Tables);
    tblSchema = connGetOleDbSchemaTable(OleDbSchemaGuidTables new object[] { null null null TABLE });
    GridViewDataSource = tblSchema;
    GridViewDataBind();
    // 關閉連接
    connClose();
    GetOleDbSchemaTable 方法的詳細說明可以參考
    CN/library/systemdataoledboledbconnectiongetoledbschematableaspx
    接著是一段利用架構信息動態讀取Excel內部定義的表單或者命名區域的程序片斷
    // 讀取Excel數據填充DataSet
    // 連接字符串
    string xlsPath = ServerMapPath(~/app_data/somefilexls);
    string connStr = Provider=MicrosoftJetOLEDB; +
    Extended Properties=\Excel ;HDR=No;IMEX=\; + // 指定擴展屬性為 Microsoft Excel () () ()並且第一行作為數據返回且以文本方式讀取
    data source= + xlsPath;
    string sql_F = SELECT * FROM [{}];
    OleDbConnection conn = null;
    OleDbDataAdapter da = null;
    DataTable tblSchema = null;
    IList<string> tblNames = null;
    // 初始化連接並打開
    conn = new OleDbConnection(connStr);
    connOpen();
    // 獲取數據源的表定義元數據
    //tblSchema = connGetSchema(Tables);
    tblSchema = connGetOleDbSchemaTable(OleDbSchemaGuidTables new object[] { null null null TABLE });
    //GridViewDataSource = tblSchema;
    //GridViewDataBind();
    // 關閉連接
    //connClose();
    tblNames = new List<string>();
    foreach (DataRow row in tblSchemaRows) {
    tblNamesAdd((string)row[TABLE_NAME]); // 讀取表名
    }
    // 初始化適配器
    da = new OleDbDataAdapter();
    // 准備數據導入DataSet
    DataSet ds = new DataSet();
    foreach (string tblName in tblNames) {
    daSelectCommand = new OleDbCommand(StringFormat(sql_F tblName) conn);
    try {
    daFill(ds tblName);
    }
    catch {
    // 關閉連接
    if (connState == ConnectionStateOpen) {
    connClose();
    }
    throw;
    }
    }
    // 關閉連接
    if (connState == ConnectionStateOpen) {
    connClose();
    }
    // 對導入DataSet的每張sheet進行處理
    // 這裡僅做顯示
    GridViewDataSource = dsTables[];
    GridViewDataBind();
    GridViewDataSource = dsTables[];
    GridViewDataBind();
    // more codes
    //
    這裡我們就不需要對SELEC 語句進行硬編碼可以根據需要動態的構造FROM 字句的表名
    不僅可以獲取表明還可以獲取每張表內的字段名字段類型等信息
    tblSchema = connGetOleDbSchemaTable(OleDbSchemaGuidColumns new object[] { null null null null });
    在ADOnET x 時候只有OleDb提供了GetOleDbSchemaTable 方法而SqlClient或者OrcaleClient沒有對應的方法因為對應數據庫已經提供了類似功能的存儲過程或者系統表供應用程序訪問比如對於Sql Server
    SELECT *
    FROM NorthwindINFORMATION_SCHEMACOLUMNS
    WHERE TABLE_NAME = NCustomers
    而在ADONET 中每個xxxConnenction都實現了基類SystemDataCommonDbConnection的 GetSchemal 方法
    來獲取數據源的架構信息


From:http://tw.wingwit.com/Article/program/net/201311/13390.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.