Linq To Excel Provider
Linq To Excel Provider跟Linq To Excel開放源始碼函式庫一樣都是用來對Excel做查詢用途,不同的是Linq To Excel Provider使用方式跟Linq To SQL有些接近,2.5版以後更具備更新、插入、與刪除等功能,這是Linq To Excel開放源始碼函式庫目前尚無法做到的一塊,也因如此Linq To Excel Provider在使用上就變得比Linq To Excel開放源始碼函式庫來得複雜許多,也多了些限制存在。
Linq To Excel Provider在官網有公開下載Source Code,使用前需先至官網下載,並將其加入專案,再把LinqToExcel命名空間加入使用。下載下來的Source Code雖然只有一個檔案,但裡面卻內含有使用範例,像是Person類別與啟始函式Main,在使用時我們可開啟Source Code先將裡面的範例拿掉。
Linq To Excel Provider使用上必需了解的類別有ExcelProvider與ExcelSheet<T>,其重要的類別成員列表如下:
ExcelProvider Property
Name | Description |
Filepath | Excel檔案位置 |
ExcelProvider Method
Name | Description |
Create | 建立ExcelProvider物件實體 |
GetSheet<T> | 取得工作表 |
SubmitChanges | 接受工作表內容變更 |
ExcelSheet<T> Method
Name | Description |
DeleteOnSubmit | 將此資料表中的實體置於 pending delete 狀態,待ExcelProvider .SubmitChanges呼叫後刪除。 |
InsertOnSubmit | 將此資料表中的實體置於 pending insert狀態,待ExcelProvider .SubmitChanges呼叫後插入。 |
Linq To Excel Provider跟Linq To SQL一樣,皆需產生對應到資料的類別,這邊我們當然無法像Linq To SQL一樣透過Visual Studio去產生這樣的類別,而是要藉助作者提供的LINQ to Excel Code Generator網頁去產生。
在LINQ to Excel Code Generator網頁中我們可依序設定要產生的語言、類別名稱、對應到的工作表名稱、及各欄位的名稱與型態。
填完後按下下方的Generate按鈕,下方會生成你需要的類別程式碼。
//*********************************************************************************
//
//
//
// Person.cs
//
//*********************************************************************************
using System.Linq;
using System.ComponentModel;
[ExcelSheet(Name="Sheet1")]
public class Person: INotifyPropertyChanged
{
private double _id;
private string _firstname;
private string _lastname;
private DateTime _birthdate;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void SendPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
[ExcelColumn(Name="ID", Storage="_id")]
public double ID
{
get { return _id;}
set {
_id = value;
SendPropertyChanged("ID");
}
}
[ExcelColumn(Name="FirstName", Storage="_firstname")]
public string FirstName
{
get { return _firstname;}
set {
_firstname = value;
SendPropertyChanged("FirstName");
}
}
[ExcelColumn(Name="LastName", Storage="_lastname")]
public string LastName
{
get { return _lastname;}
set {
_lastname = value;
SendPropertyChanged("LastName");
}
}
[ExcelColumn(Name="BirthDate", Storage="_birthdate")]
public DateTime BirthDate
{
get { return _birthdate;}
set {
_birthdate = value;
SendPropertyChanged("BirthDate");
}
}
}
所產生的類別程式碼,說穿了只是為類別與屬性加些Attribute去修飾,讓Linq To Excel Provider能知道該類別的資料要從哪個工作表的哪個欄位去截取,並實作INotifyPropertyChanged介面讓Linq To Excel Provider能偵測到資料的改變。不過使用上我們不需要了解那麼多,LINQ to Excel Code Generator網頁工具已經處理掉了這塊,我們只要將產生的類別程式碼放入專案後,就可以開始使用Linq To Excel Provider了。
使用時我們可透過ExcelProvider.Create方法,帶入指定的Excel檔案位置,以產生ExcelProvider的物件實體。
ExcelProvider provider = ExcelProvider.Create(@"Data.xls");
透過ExcelProvider.GetSheet<T>取得資料去做Linq查詢。
ExcelProvider provider = ExcelProvider.Create(@"Data.xls");
var linq = from item in provider.GetSheet<Person>()
select item;
透過ExcelSheet<T>.DeleteOnSubmit、ExcelSheet<T>.InsertOnSubmit或是直接修改GetSheet<>後取出的資料,再搭配ExcelProvider .SubmitChanges去做插入、刪除與修改動作。
Person p = new Person();
p.Id = 10.0;
p.FirstName = "Alex";
p.LastName = "Zander";
p.BirthDate = new DateTime(1980, 4, 4);
ExcelProvider provider = ExcelProvider.Create(@"Data.xls");
provider.GetSheet<Person>().InsertOnSubmit(p);
provider.SubmitChanges();
Linq To Excel Provider算是滿好的Excel查詢與編輯的解決方案,但使用上具有一些限制,像是一定要先有對應Excel資料的類別,與無法用來產生資料,若Excel一開始是空的,在使用Linq To Excel Provider時,它會因為無法找到Column而掛掉,若一開始有欄位卻無資料,在取資料時可能會在塞值那邊掛掉。另外一提,追了一下Linq To Excel Provider的程式,感覺在效能上的處理並沒有最佳化,有些資料在使用時是重覆一直去取的,沒有套用一些快取的機制,像是它裡面的ExcelMapReader.GetColumnList,這邊在使用時若有這方面的問題可自行調整一下。
完整範例
Program.cs
using System;
using System.Linq;
using LinqToExcel;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
ExcelProvider provider = ExcelProvider.Create(@"Data.xls");
var linq = from item in provider.GetSheet<Person>()
select item;
Console.WriteLine("現有資料...");
foreach (Person item in linq)
{
Console.WriteLine(item.ToString ());
}
Console.WriteLine();
Console.WriteLine("插入資料...");
Person p = new Person();
p.Id = 10.0;
p.FirstName = "Alex";
p.LastName = "Zander";
p.BirthDate = new DateTime(1980, 4, 4);
provider.GetSheet<Person>().InsertOnSubmit(p);
provider.SubmitChanges();
Console.WriteLine(p.ToString());
Console.WriteLine();
Console.WriteLine("插入後資料...");
foreach (Person item in linq)
{
Console.WriteLine(item.ToString());
}
}
}
[ExcelSheet(Name = "Sheet1")]
public class Person : System.ComponentModel.INotifyPropertyChanged
{
private double id;
private string fName;
private string lName;
private DateTime bDate;
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected virtual void SendPropertyChanged(string propertyName)
{
System.ComponentModel.PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
public Person()
{
id = 0;
}
[ExcelColumn(Name = "ID", Storage = "id")]
public double Id
{
get { return id; }
set { id = value; }
}
[ExcelColumn(Name = "FirstName", Storage = "fName")]
public string FirstName
{
get { return this.fName; }
set
{
fName = value;
SendPropertyChanged("FirstName");
}
}
[ExcelColumn(Name = "LastName", Storage = "lName")]
public string LastName
{
get { return this.lName; }
set
{
lName = value;
SendPropertyChanged("LastName");
}
}
[ExcelColumn(Name = "BirthDate", Storage = "bDate")]
public DateTime BirthDate
{
get { return this.bDate; }
set
{
bDate = value;
SendPropertyChanged("BirthDate");
}
}
public String ToString()
{
return string.Join(",", new string[] { id.ToString(), FirstName, LastName, BirthDate.ToShortDateString() });
}
}
}
運行後結果如下:
Download