[ASP.NET MVC]產生出EXCEL檔

在專案中,若有查詢清單功能,免俗不了有匯出的功能,匯出檔案格式最方便就是csv格式,只要用逗點分隔,超簡單。

但現行大家常用的,依然還是Microsoft Office的Excel為大宗,因此我們可以透過一些免費的套件將資料匯出成Excel(.xlsx檔)。

今天實作透過EPPlus將資料轉成Excel並讓使用者可以下載。

首先,透過Nuget下載EPPlus套件,直接取用最新版即可。

接著實作

public ActionResult Export()
{
    //取出要匯出Excel的資料
    List<RANGER> rangerList = db.RANGER.ToList();

    //建立Excel
    ExcelPackage ep = new ExcelPackage();

    //建立第一個Sheet,後方為定義Sheet的名稱
    ExcelWorksheet sheet = ep.Workbook.Worksheets.Add("FirstSheet");

    int col = 1;    //欄:直的,因為要從第1欄開始,所以初始為1

    //第1列是標題列 
    //標題列部分,是取得DataAnnotations中的DisplayName,這樣比較一致,
    //這也可避免後期有修改欄位名稱需求,但匯出excel標題忘了改的問題發生。
    //取得做法可參考最後的參考連結。
    sheet.Cells[1, col++].Value = DisplayAttributeHelper<RANGER>.GetDisplayName("Name");
    sheet.Cells[1, col++].Value = DisplayAttributeHelper<RANGER>.GetDisplayName("Grade");
    sheet.Cells[1, col++].Value = DisplayAttributeHelper<RANGER>.GetDisplayName("Type");
    sheet.Cells[1, col++].Value = DisplayAttributeHelper<RANGER>.GetDisplayName("AttackDistance");
    sheet.Cells[1, col++].Value = DisplayAttributeHelper<RANGER>.GetDisplayName("AttackArea");
    sheet.Cells[1, col++].Value = DisplayAttributeHelper<RANGER>.GetDisplayName("MovingSpeed");
    sheet.Cells[1, col++].Value = DisplayAttributeHelper<RANGER>.GetDisplayName("AttackSpacing");
    sheet.Cells[1, col++].Value = DisplayAttributeHelper<RANGER>.GetDisplayName("AttackTime");
    sheet.Cells[1, col++].Value = DisplayAttributeHelper<RANGER>.GetDisplayName("NormalCD");
    sheet.Cells[1, col++].Value = DisplayAttributeHelper<RANGER>.GetDisplayName("MasterDPS");
    sheet.Cells[1, col++].Value = DisplayAttributeHelper<RANGER>.GetDisplayName("MasterDEF");
    sheet.Cells[1, col++].Value = DisplayAttributeHelper<RANGER>.GetDisplayName("MasterHP");
    sheet.Cells[1, col++].Value = DisplayAttributeHelper<RANGER>.GetDisplayName("Mine");
    
    //資料從第2列開始
    int row = 2;    //列:橫的
    foreach (RANGER item in rangerList)
    {
        col = 1;//每換一列,欄位要從1開始
                //指定Sheet的欄與列(欄名列號ex.A1,B20,在這邊都是用數字),將資料寫入
        sheet.Cells[row, col++].Value = item.Name;
        sheet.Cells[row, col++].Value = item.Grade;
        sheet.Cells[row, col++].Value = item.Type;
        sheet.Cells[row, col++].Value = item.AttackDistance;
        sheet.Cells[row, col++].Value = item.AttackArea;
        sheet.Cells[row, col++].Value = item.MovingSpeed;
        sheet.Cells[row, col++].Value = item.AttackSpacing;
        sheet.Cells[row, col++].Value = item.AttackTime;
        sheet.Cells[row, col++].Value = item.NormalCD;
        sheet.Cells[row, col++].Value = item.MasterDPS;
        sheet.Cells[row, col++].Value = item.MasterDEF;
        sheet.Cells[row, col++].Value = item.MasterHP;
        sheet.Cells[row, col++].Value = item.Mine;
        row++;
    }

    //因為ep.Stream是加密過的串流,故要透過SaveAs將資料寫到MemoryStream,在將MemoryStream使用FileStreamResult回傳到前端
    MemoryStream fileStream = new MemoryStream();
    ep.SaveAs(fileStream);
    ep.Dispose();//如果這邊不下Dispose,建議此ep要用using包起來,但是要記得先將資料寫進MemoryStream在Dispose。
    fileStream.Position = 0;//不重新將位置設為0,excel開啟後會出現錯誤
    return File(fileStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "ExportRanger.xlsx");
}

遇到問題:excel開啟後,可能會出現下圖的錯誤

可以先檢查下列項目

  1.  副檔名是否有誤
  2.  回傳的MIME Content-type是否正確
    可以參考這篇找對應的Content-type:Microsoft Office MIME Types
  3.  將ep.Stream寫入MemoryStream後,MemoryStream要先把position先指到0,再return。

最後展現一下成果 

(資料來源為Line Ranger,僅限測試資料之用途)

 

總結:

這次實作只是簡單的將資料塞入,並沒有使用很多華麗的技術,例如給予欄位顏色、欄位置中、自動欄寬....等等,當然EPPlus都是可以做得到的,有興趣的朋友可以到官方網站下載SampleCode。

此套件並沒有正式的文件,以下引用官網之說明。

EPPlus Documentation

The best way to learn how to use this library is to download the sample project and step through the samples.

除了EPPlus,也有其他的套件,如NPOI,網路上也有蠻多人比較評比,就看各位客倌選擇了。

 

參考資料

 

創用 CC 授權條款
本著作由Chenting Weng製作,以創用CC 姓名標示 4.0 國際 授權條款釋出。
This work by Chenting Weng is licensed under a Creative Commons Attribution 4.0 International License.
Based on a work at https://dotblogs.com.tw/chentingw.

部分文章內容會引用到其他網站的簡介或圖片,若有侵犯到您的著作權,請留言告知,本人會儘快移除。
免責聲明:文章屬個人記事使用,僅供參考,若引用文章造成一切損失,本人不承擔任何責任。如有錯誤,歡迎留言告知。

Part of the content of the article will refer to the profile or picture of other websites.
If there is any infringement of your copyright, please leave a message and let me remove it as soon as possible.
Disclaimer:The article is for personal use and is for reference only. I will not bear any responsibility for any loss caused by quoting the article. If there is an error, please leave a message to inform.