Linq To Excel


Linq to Excel為一Open Source函式庫,該函式庫能讓我們使用Linq去對Excel與CSV做查詢的動作。



使用前需先將LinqToExcel.dll與Remotion.Data.Linq.dll這兩個組件檔給加入參考,並加入LinqToExcel命名空間就可以開始使用Linq to Excel了。



開始使用前需了解到ExcelQueryFactory為Linq to Excel的主要類別,我們主要都是對該類別下去做操作,因此我們必需要了解其內部的成員,這邊將其成員整理列表如下:



屬性

















Name

Description

FileName

檔案名稱

StrictMapping

是否限制AddMapping所有設定的對應都要正確



方法









































Name

Description

Worksheet

取得工作表中的資料

WorksheetNoHeader

取得工作表中不含標題的資料

WorksheetRange

取得工作表中特定範圍的資料

WorksheetRangeNoHeader

取得工作表中不含標題的特定範圍資料

AddMapping

設定Excel欄位與物件屬性的對應

AddTransformation

設定Excel欄位塞給物件屬性所要做的轉換動作

GetWorksheetNames

取得所有工作表名稱

GetColumnNames

取得所有欄位名稱



建立ExcelQueryFactory物件時我們有兩種選擇,一種是直接將Excel檔案位置帶入建構子建構。



var excel = new ExcelQueryFactory(“Data.xls”);



一種是使用預設建構子建立後,再透過FileName屬性設定Excel檔案位置。



var excel = new ExcelQueryFactory();
excel.FileName = “Data.xls”;



建立ExcelQueryFactory物件後,可以使用GetWorksheetNames方法可以取得所有工作表名稱 。



void ShowWorkSheetNames(string excelFile)
{
var excel = new ExcelQueryFactory(excelFile);
var workSheetNames = excel.GetWorksheetNames();
foreach (var item in workSheetNames)
{
System.Console.WriteLine(item.ToString());
}
}


image





GetColumnNames方法可取得指定工作表中所有欄位的名稱。



void ShowColumnNames(string excelFile,string sheetName)
{
var excel = new ExcelQueryFactory(excelFile);
var columnNames = excel.GetColumnNames(sheetName);
foreach (var item in columnNames)
{
System.Console.WriteLine(item.ToString());
}
}



這邊個人是發現在不同版本的Excel下,這道方法會取得的值會不有所不同,取得的值在某些條件下都會怪怪的,要特別留意一下。像是我在2003的Excel打入下列資料:


image



使用GetColumnNames方法取得的值會像下面這樣,只要Column打的是數值,取出來都會走樣。


image



同樣的資料在Excel 2007下,跑起來就正常許多,但在空行的部份仍是跟我預期的不同。


image



Worksheet、WorksheetNoHeader、WorksheetRange、WorksheetRangeNoHeader等方法可取得工作表內的資料,我們可藉這些方法取得回傳值後對這些工作表內的資料做Linq查詢。



...
var excel = new ExcelQueryFactory(excelFile);

   //自己可自行加要過濾的條件,這邊只是示範
   var linq = from item in excel.Worksheet(sheetName)                       
              select item;
...</pre>



這些WorkSheet開頭方法多半會具有不含參數的多載版本,可用以取得”Sheet1”工作表內的資料,這邊需注意該方法取得的是”Sheet1”工作表內的資料,而非第一個工作表內的資料,工作表改名後使用該多載版本方法就會取不到。



...
var excel = new ExcelQueryFactory(excelFile);

    //這邊會取使用Sheet1的工作表內容去做查詢動作
    var linq = from item in excel.Worksheet()                       
               select item;
...</pre>



或是具有帶入工作表索引或工作表名稱的多載版本,用以取得指定索引或名稱的工作表內的資料。有的還會含有泛型的多載版本,可帶入資料對應的物件類型,取得Excel資料時Linq To Excel會自動幫我們將資料塞成指定的類別。



...
var excel = new ExcelQueryFactory(excelFile);

    var linq = from item in excel.Worksheet&lt;Blogger&gt;(sheetName)  
               where item.Sex==SexType.Boy 
               select item;
...</pre>



在使用泛型多載版本時,要是用以填值的類別其屬性跟Excel欄位名稱不符,我們可以透過AddMapping設定兩者間的對應關係。



...
var excel = new ExcelQueryFactory(excelFile);
excel.AddMapping<Blogger>(item => item.FirstName, “First Name”);
excel.AddMapping<Blogger>(item => item.LastName, “Last Name”);
...



若是設定完欄位與屬性的對應後,有些屬性的資料與欄位內的資料或是型態有所差異時,可加設AddTransformation去做兩者間的轉換。



...
var excel = new ExcelQueryFactory(excelFile);
excel.AddMapping<Blogger>(item => item.FirstName, “First Name”);
excel.AddMapping<Blogger>(item => item.LastName, “Last Name”);
excel.AddTransformation<Blogger>(item => item.Sex, item => (item == “Boy”) ? SexType.Boy : SexType.Girl);
...



另外一提,Linq to Excel在使用上會自動去找尋第一個符合的資料,就算內容不是從Excel最左上的A1欄位開始,Linq to Excel都會幫我們自動找尋,多半我們可以不指定要抓取的範圍,除非工作表內的資料是分成好幾塊。



完整範例


若有需要範例程式可至larrynung / LinqToExcelDemo這邊下載。


Data.xls


image


image



SexType.cs



namespace ConsoleApplication1
{
enum SexType
{
Boy,
Girl
}
}



Blogger.cs



using System;

namespace ConsoleApplication1
{
class Blogger
{
public int ID { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
public SexType Sex { get; set; }
public int Age { get; set; }
public String Blog { get; set; }

    public override string ToString()
    {
        return string.Join(",", new string[] { ID.ToString(), FirstName, LastName, Sex.ToString(), Age.ToString(), Blog });
    }
}

}



Program.cs



using LinqToExcel;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
const string EXCEL_FILE = “Data.xls”;
const string FIRST_SHEET = “BlogData1”;
const string SECOND_SHEET = “BlogData2”;

        var excel = new ExcelQueryFactory(EXCEL_FILE);
        System.Console.WriteLine("Excel File: {0}", excel.FileName);

        System.Console.WriteLine();
        System.Console.WriteLine("WorksheetNames...");
        var workSheetNames = excel.GetWorksheetNames();
        foreach (var item in workSheetNames)
        {
            System.Console.WriteLine(item.ToString());
        }

        System.Console.WriteLine();
        System.Console.WriteLine("BlogData's Columns...");
        var columnNames = excel.GetColumnNames(FIRST_SHEET);
        foreach (var item in columnNames)
        {
            System.Console.WriteLine(item.ToString());
        }

        System.Console.WriteLine();
        System.Console.WriteLine("BlogData1 With ExcelQueryFactory.Worksheet...");
        excel.AddMapping&lt;Blogger&gt;(item =&gt; item.FirstName, "First Name");
        excel.AddMapping&lt;Blogger&gt;(item =&gt; item.LastName, "Last Name");
        excel.AddTransformation&lt;Blogger&gt;(item =&gt; item.Sex, item =&gt; (item == "Boy") ? SexType.Boy : SexType.Girl);

        foreach (var item in excel.Worksheet&lt;Blogger&gt;(FIRST_SHEET))
        {
            System.Console.WriteLine(item.ToString());
        }

        System.Console.WriteLine();
        System.Console.WriteLine("BlogData2 With ExcelQueryFactory.Worksheet...");

        foreach (var item in excel.Worksheet&lt;Blogger&gt;(SECOND_SHEET))
        {
            System.Console.WriteLine(item.ToString());
        }

        System.Console.WriteLine();
        System.Console.WriteLine("BlogData2 With ExcelQueryFactory.WorksheetRange...");

        foreach (var item in excel.WorksheetRange&lt;Blogger&gt;("B2", "G3", SECOND_SHEET))
        {
            System.Console.WriteLine(item.ToString());
        }

    }
}

}



運行後結果如下:


image



Link



  • 讀取 Excel 你還在用 NPOI 嗎?快來試試 LinqToExcel


  • Linq to Excel