2017/10/17

C# 利用 epplus 讀取 Excel xlsx 檔案

從古老時代開始,把Html兜出來的表格硬套上header與excel副檔名回傳下載,然後硬逼使用者接受那看起來有點詭異的開啟警告,好像是開發人員常做的事。不過,隨著epplus (http://epplus.codeplex.com/)的廣泛利用,開發者就不能再這樣打混了。

VS的使用者請從nuget 取得 epplus 的最新版本。不過有趣的是,在程式內using資源檔時是要引用  OfficeOpenXml 。它賦予程式讀寫新版Excel檔案的能力。以往讀取Exce檔,常常會發生某些欄位的前幾列空白(無資料), 匯入程式就主動認為底下無資料、不往下讀取的問題;eeplus在這方面的表現則好得多,取值的時候也相對比較不會發生Exception。

以前還遇過一個情形:承辦人喜歡在Excel內標示底色或拖曳公式,不知道為什麼,明明資料才500筆,匯入程式卻認為501以後的資料不為空,把65536列全讀完了,結果當然慢得要死。epplus 的判讀好像也聰明些,但開發程式時發現有多少列以上是全空的,要將其排除(停止往下讀),程式的執行會更有效率。

eeplus要取得某個儲存格的值時,則利用類似讀取陣列的方式,以[列,欄]的方式取得當中的值。但取值的序列是從1開始,而不是0,這是跟c#的慣例較為不同的地方。


以下以讀取檔案為例,假設檔案已經上傳到伺服器的某個實體路徑,然後有個方法去讀取它。先用資料流把檔案開啟,建立一個ExcelPackage實體,然後取得epplus的工作表。
匯出成Excel檔案的作法大同小異,不論Window form 或網站、MVC 皆已有許多先進分享,
待日後再另文補充。


using OfficeOpenXml;
using System.IO;


public void Import(string fullPath, bool isHeader)
        {
            using (FileStream fs = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                using (ExcelPackage excelPkg = new ExcelPackage(fs))
                {
                    ExcelWorksheet sheet = excelPkg.Workbook.Worksheets[1];//取得Sheet1

                    int startRowIndex = sheet.Dimension.Start.Row;//起始列
                    int endRowIndex = sheet.Dimension.End.Row;//結束列

                    int startColumn = sheet.Dimension.Start.Column;//開始欄
                    int endColumn = sheet.Dimension.End.Column;//結束欄

                    if (isHeader)//有包含標題
                    {
                        startRowIndex += 1;
                    }
                    for (int currentRow = startRowIndex; currentRow <= endRowIndex; currentRow++)
                    {
                        //抓出當前的資料範圍
                        ExcelRange range = sheet.Cells[currentRow, startColumn, currentRow, endColumn];

                       //全部儲存格是完全空白時則跳過
                        if (range.Any(c => !string.IsNullOrEmpty(c.Text)) == false)
                        {
                            continue;//略過此列
                        }
                        Response.Write(sheet.Cells[currentRow, 2].Text);
                        Response.Write("<br/>");
                        Response.Write(sheet.Cells[currentRow, 3].Text);
                        Response.Write("<br/>");
                        //族繁不及備載
                        Response.Write("<hr>");
                    }
                }
            }
        }

沒有留言:

張貼留言