連線字串對照表
| Excel 版本 | Provider | Extended Properties | 適用副檔名 |
| Excel 97-2003 | Microsoft.Jet.OLEDB.4.0 | Excel 8.0 | .xls |
| Excel 2007+ | Microsoft.ACE.OLEDB.12.0 | Excel 12.0 Xml;HDR=YES | .xlsx, .xlsm, .xlsb |
| 通用 (建議) | Microsoft.ACE.OLEDB.12.0 | Excel 12.0;HDR=YES | .xls, .xlsx 皆可 (需安裝 ACE 驅動程式) |
基本讀取範例
using System;
using System.Data;
using System.Data.OleDb;
public class ExcelReader
{
public DataTable ReadSheet(string filePath, string sheetName = "Sheet1")
{
// 自動偵測 Provider (需機器安裝 ACE 12.0 或更新版本)
string connStr = $@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={filePath};Extended Properties='Excel 12.0;HDR=YES;IMEX=1';";
using (var conn = new OleDbConnection(connStr))
{
conn.Open();
// 取得實際工作表名稱 (避免 Sheet1$ 不存在)
var schema = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string actualSheet = sheetName + "$";
if (schema != null && !schema.Rows.Cast<DataRow>().Any(r => r["TABLE_NAME"].ToString().Equals(actualSheet, StringComparison.OrdinalIgnoreCase)))
{
actualSheet = schema.Rows[0]["TABLE_NAME"].ToString(); // 使用第一個工作表
}
string query = $"SELECT * FROM [{actualSheet}]";
using (var adapter = new OleDbDataAdapter(query, conn))
{
var dt = new DataTable();
adapter.Fill(dt);
return dt;
}
}
}
}
關鍵參數解析
HDR=YES:第一列為標題,欄位名稱取自第一列;HDR=NO 則自動命名 F1, F2...。
IMEX=1:混合模式,強制將欄位視為文字讀取,避免「數字欄位前幾列為數值,後面出現文字導致讀成 null」的經典問題。
ReadOnly=True:唯讀開啟,避免鎖定檔案,適合多人共用或僅讀取場景。
寫入/更新資料
public void UpdateCell(string filePath, string sheetName, string cellAddress, object value)
{
// 例: cellAddress = "A1" 或 "R1C1"
string connStr = $@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={filePath};Extended Properties='Excel 12.0;HDR=NO;';";
using (var conn = new OleDbConnection(connStr))
{
conn.Open();
// OleDb 不支援直接 UPDATE 儲存格,需透過 OleDbCommand 執行 SQL
// 注意:Excel SQL 支援有限,建議改用 EPPlus/ClosedXML/NPOI 進行儲存格級操作
string sql = $"UPDATE [{sheetName}$] SET F1 = ? WHERE F1 = 'TargetKey'"; // 範例
using (var cmd = new OleDbCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@val", value);
cmd.ExecuteNonQuery();
}
}
}
常見錯誤與解決方案
| 錯誤訊息 | 原因 | 解決 |
Microsoft.ACE.OLEDB.12.0 provider is not registered | 未安裝 Access Database Engine | 下載安裝 Access Database Engine 2010/2016/365 (選擇 x64 或 x86 與應用程式位元數一致) |
External table is not in the expected format | Provider 與檔案版本不符 | .xls 用 Jet 4.0;.xlsx 用 ACE 12.0+;或統一用 ACE 12.0 讀所有版本 |
No value given for one or more required parameters | SQL 欄位名稱錯誤/參數未綁定 | 檢查工作表名稱 (需加 $)、欄位名稱 (含空白需用 ` ` 或 [])、參數標記 ? 對應順序 |
| 資料型別錯誤 (數值讀成 null) | 型別推測失敗 | 加上 IMEX=1 強制文字模式 |
| 檔案被鎖定/獨佔錯誤 | Excel 應用程式開啟中 | 關閉 Excel;或加 ReadOnly=True;或複製檔案到暫存目錄再讀取 |
效能優化建議
- 僅讀取必要欄位:
SELECT Col1, Col3 FROM [Sheet$] 而非 SELECT *。
- 分頁讀取大量資料:OleDb 不支援
LIMIT/OFFSET,需在記憶體中過濾或改用 EPPlus 串流讀取。
- 批次寫入:OleDb 寫入極慢,大量資料請改用 EPPlus、ClosedXML、NPOI 純 .NET 程式庫,不需安裝 Office/ACE,效能優 10-100 倍。
- 連線池:OleDb 不支援連線池,頻繁開關連線開銷大,建議單次作業開啟一次連線完成所有操作。
現代替代庫推薦 (無需安裝 Office/ACE)
| 庫 | 授權 | 特色 | NuGet |
| EPPlus | Polyform Noncommercial 1.0 (商業需付費) | 功能最完整、效能佳、支援樞紐分析表、圖表、樣式 | EPPlus |
| ClosedXML | MIT | API 直覺、記憶體效率好、支援 .xlsx 僅 | ClosedXML |
| NPOI | Apache 2.0 | 支援 .xls/.xlsx、Java POI 移植、功能全、免費商用 | NPOI |
| ExcelDataReader | MIT | 唯讀、極快、低記憶體、支援串流 | ExcelDataReader |
結語
OleDb 是舊專案相容的選擇,新專案**強烈建議直接使用 EPPlus/ClosedXML/NPOI**,擺脫驅動程式相容性地獄,獲得更好效能、更豐富功能與跨平台能力。