專案常需匯入 Excel 資料,本文提供使用 ADO.NET `OleDb` 讀取 Excel 的完整程式碼,包含連接字串設定、查詢語法、版本相容性注意事項。
<add key="ExcelConnectionString"
value="Provider=Microsoft.Jet.OLEDB.4.0;
Data Source='miroExcel/Info.xls';
Extended Properties='Excel 8.0;HDR=yes;IMEX=2'" />
string connStr = @"Provider=Microsoft.Ace.OLEDB.12.0;
Data Source='{0}';
Extended Properties='Excel 12.0;HDR=yes;IMEX=2'";
| 參數 | 說明 |
|---|---|
| HDR=yes | 第一列為標題列,欄位名稱以標題命名 |
| IMEX=2 | 混合資料類型模式,避免數字/文字混雜導致讀取為 null |
| Excel 8.0 | 對應 .xls (BIFF8) 格式 |
| Excel 12.0 | 對應 .xlsx (OpenXML) 格式 |
重要: 64 位元環境必須安裝 64 位元 ACE OLEDB Provider,否則會出現「未在本機電腦上註冊 'Microsoft.ACE.OLEDB.12.0' 提供者」錯誤。
using System.Data;
using System.Data.OleDb;
public class ExcelRepository
{
public DataSet QueryByCardId(string cardId, string excelPath)
{
try
{
string connStr = string.Format(
"Provider=Microsoft.Ace.OLEDB.12.0; Data Source='{0}'; Extended Properties='Excel 12.0;HDR=yes;IMEX=2'",
excelPath);
using (OleDbConnection conn = new OleDbConnection(connStr))
{
string sql = "SELECT * FROM [Sheet1$] WHERE CardId = @CardId";
using (OleDbCommand cmd = new OleDbCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@CardId", cardId); // 參數化防注入
using (OleDbDataAdapter adapter = new OleDbDataAdapter(cmd))
{
DataSet ds = new DataSet();
adapter.Fill(ds, "ExcelData");
return ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0 ? ds : null;
}
}
}
}
catch (Exception ex)
{
// 記錄日誌 ex.ToString()
return null;
}
}
}
| 問題 | 原因 | 解決 |
|---|---|---|
| 找不到工作表 | 工作表名稱不為 Sheet1、或含空格 | 先查詢 `conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null)` 取得實際名稱 |
| 數字欄位讀成 null | 前幾列為數字,後面混入文字,驅動程式誤判型別 | 加上 `IMEX=1` 或 `IMEX=2`,強制視為文字 |
| 標題列被當資料 | 未設定 `HDR=yes` | 連接字串加入 `HDR=yes` |
| 大量資料效能差 | OleDb 載入整張表到記憶體 | 分批讀取、或改用 OpenXML/EPPPlus 串流式讀取 |
<appSettings>
<add key="ExcelProviderXls" value="Microsoft.Jet.OLEDB.4.0" />
<add key="ExcelProviderXlsx" value="Microsoft.Ace.OLEDB.12.0" />
<add key="ExcelExtendedPropsXls" value="Excel 8.0;HDR=yes;IMEX=2" />
<add key="ExcelExtendedPropsXlsx" value="Excel 12.0;HDR=yes;IMEX=2" />
</appSettings>
程式碼中根據副檔名動態組合連接字串,避免硬編碼。
舊專案維護可繼續用 OleDb;新專案建議改用 NPOI 或 EPPlus,相依性更低、部署更簡單。