在專案中,若有查詢清單功能,免俗不了有匯出的功能,匯出檔案格式最方便就是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開啟後,可能會出現下圖的錯誤
可以先檢查下列項目
- 副檔名是否有誤
- 回傳的MIME Content-type是否正確
可以參考這篇找對應的Content-type:Microsoft Office MIME Types - 將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,網路上也有蠻多人比較評比,就看各位客倌選擇了。
參考資料
- 比NPOI更討喜的Excel元件-EPPlus!
- Generating an excel file with EPPlus is failing
- 取得 Entity 類別 MetaData 所設定的 Display Name
本著作由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.