令人驚豔的Excel程式庫 - ClosedXML

處理ReportViewer匯出檔的比武大會上,NPOI與EPPlus都敗下陣來,Open XML SDK雖然勝出,但在應用呼叫上繁瑣難搞,用起來總覺礙手礙腳。在研究Open XML SDK設定工作表保護的過程,發現新大陸 - 另一套Open Source的Excel程式庫,ClosedXML

簡單整理ClosedXML特色如下:

  1. 程式庫很俏皮地命名為ClosedXML,事實它高度依賴Open XML SDK,在引用時,程式必須一併參考DocumentFormat.OpenXml.dll。ClosedXML切入的角度是為Open XML SDK提供容易操作的程式介面,而事實證明它做得很成功,程式介面的確非常簡潔易用。
  2. 以Open XML SDK為基礎,所以只支援xlsx,不支援xls格式。
  3. CodePlex上就文件與範例,內容十分完整,很容易上手。
  4. 支援NuGet安裝,加入時會一併帶入Open XML SDK參照,安裝簡單。
  5. ClosedXML的很多Method在設計上仿照Excel VBA慣例,例如: sheet.Cell("A1").Value = "Boo"、sheet.Range("A1:C5")選取範圍,用起來相當簡單直覺。
  6. 很重要的一點,先前讓EPPLUS及NPOI灰頭土臉的ReportViewer匯出檔測試,ClosedXML輕易過關,產出結果與Excel相容,程式碼又比Open XML SDK簡短易理解,大勝!  (以下範例順便展示了保護工作表功能,一行搞定。)
        //ClosedXML
        var wb = new XLWorkbook(src);
        var ws = wb.Worksheets.First();
        ws.Cells("A1").Value = "已修改";
        ws.Protect("LetMeEdit");
        wb.SaveAs(@"d:\temp\closedXml.xlsx");

初步評估,ClosedXML支援不少Excel VBA風格的簡潔API,在ReportViewer匯出檔案相容性測試又比NPOI及EPPlus好,看起來很值得一試!

最後不能免俗地,比照NPOIEPPlus,要用ClosedXML試做網站檔案結構轉Excel的範例:

    /// <summary>
    /// 將目錄下的目錄檔案結構匯出成Excel工作表
    /// </summary>
    /// <param name="dirPath">要匯出的目錄路徑</param>
    /// <param name="excelPath">匯出Excel路徑</param>
    /// <param name="filter">過濾函數,傳入Path進行判斷,傳回true時表排除</param>
    /// <returns></returns>
    public static void WebTreeToExcel(
        string dirPath, string excelPath,
        Func<string, bool> filter = null)
    {
        //將目錄結構整理成清單
        List<WebItem> list = new List<WebItem>();
        explore(list, dirPath, 0);
        //建立Excel
        XLWorkbook workbook = new XLWorkbook();
        var sheet = workbook.Worksheets.Add("Site Tree");
        int colIdx = 1;
        foreach (string colName in "Path;File;Description".Split(';'))
        {
            sheet.Cell(1, colIdx++).Value = colName;
        }
        //修改標題列Style
        var header = sheet.Range("A1:C1");
        header.Style.Fill.BackgroundColor = XLColor.Green;
        header.Style.Font.FontColor = XLColor.Yellow;
        header.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
 
        int rowIdx = 2;
        foreach (var item in list)
        {
            //若bypass檢測傳回true,則略過該筆
            if (filter != null && filter(item.Path))
                continue;
            //將Path放在第一欄(稍後隱藏)
            sheet.Cell(rowIdx, 1).Value = item.Path;
            //存入檔名或目錄名
            sheet.Cell(rowIdx, 2).Value =
                new String(' ', item.Layer * 4) + item.Name;
            if (item.IsFolder)
            {
                sheet.Cell(rowIdx, 2).Style.Font.FontColor = XLColor.Blue;
            }
            rowIdx++;
        }
        //第一欄隱藏
        sheet.Column(1).Hide();
        //自動伸縮欄寬
        sheet.Column(2).AdjustToContents();
        sheet.Column(2).Width += 2;
        sheet.Column(3).Width = 50;
        //寫入檔案
        workbook.SaveAs(excelPath);
    }

程式簡潔度與EPPlus相近,結果也正確無誤,ClosedXML勝出之處在於產出檔與Excel相容度較高,是一套值得推薦的Excel程式庫。

歡迎推文分享:
Published 28 December 2012 08:38 AM 由 Jeffrey
Filed under: ,



意見

# 阿信 said on 17 December, 2014 08:36 PM

暗黑大,你好

我在使用ClosedXML時遇到一個問題

drive.google.com/.../view

連結是我公司的一個Excel檔案,原本裡面有許多工作表,已經被我全部刪除然後新增了一個工作表,然後這個Excel如果經過 ClosedXML 的處理後,第一次開啟是正常的,但是如果存檔後再開啟就會出現 Excel 在 XXX中找到無法讀取的內容這個錯誤訊息

我的程式碼只有用↓ 也是會這樣,想請問這是Excel檔案的問題還是ClosedXML的問題?

XLWorkbook workbook = new LWorkbook(@"D:\test.xlsx");

workbook.Save();

# Jeffrey said on 18 December, 2014 07:07 PM

to 阿信,我做了XLWorkbook workbook = new XLWorkbook(@"D:\test.xlsx"); workbook.Save();測試,未能重現你說的問題。我用的版本:ClosedXML版本0.76.0,Excel 2010。懷疑會不會跟Excel環境有關,建議換台機器測試對照一下。

# 阿信 said on 18 December, 2014 08:31 PM

感謝大大的回覆及測試

我的環境也跟大大一樣,是只有使用連結的Excel檔案才會有這個狀況發生耶

我說明一下我的操作流程

步驟一

使用ClosedXML處理該Excel檔案(連結內的Excel,而且只有用.Save();....|||Orz)

步驟二

開啟處理完後Excel並編輯裡面的資料,然後存檔

步驟三

再次開啟該Excel檔案 就會出現那些訊息了  @@!

會發現這樣的問題,主要是因為我們公司有個固定格式的Excel,裡面有同事在裡面編輯好的函數跟巨集,主要都是先Copy那份Excel再依據工作表名稱把資料加進去

連結內的Excel就是我把那份Excel檔案的工作表跟巨集都刪除後的,可是它"看起來"明明就很乾淨了,可是就是會出現那個問題...|||Orz

# Jeffrey said on 18 December, 2014 09:06 PM

to 阿信,懂了,ClosedXML存檔後要再用Excel編輯存檔一次,再次開啟才會出錯,已成功重現錯誤,我再研究看看有什麼奧妙之處。

# Jeffrey said on 18 December, 2014 09:38 PM

to 阿信,找到問題根源,XL/style.xml中timelineStyles節點附近的XML格式有誤,在ClosedXML討論區找到相關文章(closedxml.codeplex.com/.../403797),似乎都發生在「Excel 2013建立xlsx->ClosedXML處理->Excel 2010開啟」的情境,我測試如果ClosedXML Save()後改用Excel2013編輯存檔再開啟,並不會出錯。看起來是Bug,但不確定這要算在Excel 2010還是ClosedXML頭上? :P 以上資訊供你參考。

# 阿信 said on 18 December, 2014 09:58 PM

好的

感謝大大~@@!

原本我還在猜是不是因為 ClosedXML 處理後的 Excel檔 的 XML 都會變成 <x: 開頭...

可是想想就算是變成這樣也不應該影響到什麼啊...

感謝大神的解說。

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<December 2012>
SunMonTueWedThuFriSat
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345
 
RSS
【工商服務】
OrcsWeb: Windows Server Hosting
twMVC

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication