簡單使用LinqToExcel讀取Excel檔案資料
前言
在專案開發時,常會面臨到使用者希望保有操作Excel文件習慣來同步系統資料,因此有Excel上傳及讀取需求產生;筆者實務上大多透過強大的NPOI來完成所有操作Excel的任務,但當需求就只需讀取Excel資料時,是不是可以使用更簡易的方式來完成呢? 沒錯殺雞是不需要用到牛刀的,我們可以使用LinqToExcel來簡化讀取Excel的工作,並且自動mapping到相對應類別物件中以便後續資料的操作。以下介紹。
安裝LinqToExcel
NuGet中LinqToExcel預設是32-bit ( x86 ) 版本,若伺服器是 64-bit 則需使用64位元版本,否則若將32-bit版本佈署到預設以 64-bit 執行的 IIS 站台時,會有「無法載入檔案或組件」問題發生;筆者有切身之痛所以要特別說明一下,至於細節可參考保哥 如何解決 LinqToExcel 發生「無法載入檔案或組件」問題 文章。
要在NuGet中找到64位元版本的LinqToExcel時,需要輸入LinqToExcel_x64才可被搜尋到喔
環境問題排除
如果操作Microsoft Office Excel 2007 (.xlsx ) 以上版本時,發生「'Microsoft.ACE.OLEDB.12.0' 提供者並未登錄於本機電腦上」錯誤訊息,請服用 2007 Office system 驅動程式:資料連線元件來排除此問題。
實作介紹
以下筆者將使用LinqPad來進行實作。主要針對既定格式之Excel進行資料的讀取,而實作會以2種不同的Excel格式進行測試,希望有興趣的朋友可藉由以下範例了解LinqToExcel讀取資料的控制細節。
簡易表格
主要就是在訂貨清單表單中,僅放置"一個"表格來列出訂購資訊。
面對這種簡單的表格,首先我們可以先定義Order類別來mapping到表格中各訂購資訊欄位。而LinqToExcel操作方式相當簡單,首先就是透過ExcelQueryFactory載入指定Excel檔案,接著直接使用Worksheet撈出訂貨清單表單中的表格,並且將資料mapping到Order類別中。 示意圖如下所示。
完整測試代碼如下
void Main()
{
// Load excel file
var excel = new ExcelQueryFactory(@"D:\Sample.xlsx");
// Query
var orders = from x in excel.Worksheet<Order>("訂貨清單")
where x.OrderId != null
select x;
// Show Data
orders.Dump();
}
public class Order
{
public string OrderId {get;set;}
public string ProductName {get;set;}
public int Amount {get;set;}
public double Price {get;set;}
}
最後成功地從Excel撈出所有orders資料
複雜表格
在使用者清單表單中,包括一個獨立資料(Date)及下方使用者表格。在LinqToExcel可以指定讀取的範圍,因此要順利取得下方表格資料不會有太大的困難;至於上方獨立資料(Date)則可以利用Excel中"定義名稱"功能來標記該資料位置,方便讓LinqToExcel透過此定義名稱獲得該資料內容。
在Excel中使用"定義名稱"功能相當簡單,只要在該Cell上按下滑鼠右鍵,在選單中點選"定義名稱"
接著就可以輸入此定義功能的名稱及範圍,而LinqToExcel就可使用此名稱來取得對應資料。
按下 Ctrl + F3 後可顯示名稱管理員,可確認剛剛加入的新名稱是否列於其中。
使用LinqToExcel面對稍微複雜的Excel格式時,取值技巧約略以下三點:
1. 可使用 NamedRangeNoHeader 來依據Excel"定義功能"中所設定"名稱"進行取值。
2. 面對Excel欄位名稱與類別屬性名稱不一致時,可透過AddMapping來建立映射關聯。
3. 可使用 WorksheetRange 來指定表單範圍(左上位置為B4,右下位置則為E0,其中0表示無筆數下限)
完整測試代碼如下
void Main()
{
// Load excel file
var excel = new ExcelQueryFactory(@"D:\Sample.xlsx");
// Query by Range Name
var createDate = from x in excel.NamedRangeNoHeader("CreateDate")
select x[0].Cast<DateTime>();
// Mapping class's property to column name
excel.AddMapping<User>( u=>u.UserId, "User ID");
// Query by Sheet Name
var users = from x in excel.WorksheetRange<User>("B4","E0","使用者清單")
where x.UserId != null
select x;
createDate.Dump();
users.Dump();
}
public class User
{
//[ExcelColumn("User ID")]
public string UserId {get;set;}
public string Name {get;set;}
public DateTime Birthday {get;set;}
public int Height {get;set;}
}
最後成功地從Excel所撈出createDate及users資料
參考資訊
https://github.com/paulyoder/LinqToExcel
希望此篇文章可以幫助到需要的人
若內容有誤或有其他建議請不吝留言給筆者喔 !