#abp框架Excel導出——基於vue #1.技術棧 ##1.1 前端採用vue,官方提供 UI套件用的是iview ##1.2 後臺是abp——aspnetboilerplate 即abp v1,https://github.com/aspnetboilerplate/aspnetboilerp ...
abp框架Excel導出——基於vue
目錄
1.技術棧
1.1 前端採用vue,官方提供
UI套件用的是iview
1.2 後臺是abp——aspnetboilerplate
即abp v1,https://github.com/aspnetboilerplate/aspnetboilerplate。 下載時選擇的是net core 3.1。
2. Excel導出需求
管理後臺系統,主要以圖表統計形式歸檔數據,用戶經常會有Excel導出報表的需求。可以以文件形式保存,更加地直觀,符合使用習慣。
3. 升級日誌Excel導出
物聯網中的設備是核心資產,而維護設備經常需要一些升級割接操作,因此,升級日誌(升級失敗,升級成功,升級時間)等是用戶比較關心的數據。
4. 技術實現方案
4.1 後臺
4.1.1 EPPlus導出靜態方法
需要nuget安裝EPPlus.Core庫。運用了委托的方法方便地實現了對導出表單進行添加標題,填充內容數據,渲染單元格樣式,委托的一大優勢就是方便調用,層次感很明顯。該方法如果看得還不是很明白,請耐心繼續往下看。
public abstract class EPPlusExcelExporterBase : AbpServiceBase
{
protected EPPlusExcelExporterBase( )
{}
public static byte[] CreateExcelPackage(string fileName, Action<ExcelPackage> creator)
{
var excelPackage = new ExcelPackage();
creator(excelPackage);
using (var stream = new MemoryStream())
{
excelPackage.SaveAs(stream);
excelPackage.Dispose();
return stream.ToArray();
}
}
public static void AddHeader(ExcelWorksheet sheet, params string[] headerTexts)
{
if (headerTexts.IsNullOrEmpty())
{
return;
}
for (var i = 0; i < headerTexts.Length; i++)
{
AddHeader(sheet, i + 1, headerTexts[i]);
}
}
protected static void AddHeader(ExcelWorksheet sheet, int columnIndex, string headerText)
{
sheet.Cells[1, columnIndex].Value = headerText;
sheet.Cells[1, columnIndex].Style.Font.Bold = true;
}
public static void AddObjects<T>(ExcelWorksheet sheet, int startRowIndex, IList<T> items, params Func<T, object>[] propertySelectors)
{
if (items.IsNullOrEmpty() || propertySelectors.IsNullOrEmpty())
{
return;
}
for (var i = 0; i < items.Count; i++)
{
for (var j = 0; j < propertySelectors.Length; j++)
{
sheet.Cells[i + startRowIndex, j + 1].Value = propertySelectors[j](items[i]);
}
}
}
}
4.1.2 生成升級日誌列表
此部分代碼與主業務相關,因為原本業務與區域許可權有關,簡化起見,故刪除其他無關代碼,主要就是從資料庫獲取了升級列表,並且按照了升級時間進行了倒序排列。讀者不同的業務可進行不同操作。需要轉義的轉義,聯表的聯表,過濾的過濾,排序的排序。
var dbQuery = from upgradeLog in _fsuUpgradeResultRepository.GetAll();
var UpgradeLogDtoList = await dbQuery
.OrderByDescending(x => x.Updatetime)
.ToListAsync();
4.1.3 將升級日誌列表放到Excel導出靜態方法中去
var data= EPPlusExcelExporterBase.CreateExcelPackage(
"UpgradeLog.xlsx",
excelPackage =>
{
var sheet = excelPackage.Workbook.Worksheets.Add("UpgradeLog");
sheet.OutLineApplyStyle = true;
EPPlusExcelExporterBase.AddHeader(
sheet,
"Fsu資產編碼",
"升級結果",
"是否反饋",
"Fsu IP地址",
"更新時間"
);
EPPlusExcelExporterBase.AddObjects(
sheet, 2, UpgradeLogDtoList,
_ => _.FsuId,
_ => _.Result,
_ => _.IsReport,
_ => _.FsuIp,
_ => _.Updatetime
);
//Formatting cells
var UpdatetimeColumn = sheet.Column(5);
UpdatetimeColumn.Style.Numberformat.Format = "yyyy-mm-dd-hh:mm:ss";
for (var i = 1; i <= 5; i++)
{
sheet.Column(i).AutoFit();
}
});
委托裡面流程分下:添加報表表頭,添加內容,設置顯示樣式(時間格式),添加樣式(設置單元格自適應內容大小)。
通過CreateExcelPackage方法放回了文件比特流。
4.1.4 abp框架中前後端分離模式文件流傳輸
以FileResult形式返回前端傳來的請求。需要註意的是FileResult是 Microsoft.AspNetCore.Mvc.Core中的一個類。
public async Task<FileResult> GetUpgradeReport()
{
var dbQuery = from upgradeLog in _fsuUpgradeResultRepository.GetAll();
var UpgradeLogDtoList = await dbQuery
.OrderByDescending(x => x.Updatetime)
.ToListAsync();
foreach (var item in UpgradeLogDtoList)
{
ConvertDto(item);//對升級結果,是否上報鐵塔平臺進行解析
}
var data= EPPlusExcelExporterBase.CreateExcelPackage(
"UpgradeLog.xlsx",
excelPackage =>
{
var sheet = excelPackage.Workbook.Worksheets.Add("UpgradeLog");
sheet.OutLineApplyStyle = true;
EPPlusExcelExporterBase.AddHeader(
sheet,
"Fsu資產編碼",
"升級結果",
"是否反饋",
"Fsu IP地址",
"更新時間"
);
EPPlusExcelExporterBase.AddObjects(
sheet, 2, UpgradeLogDtoList,
_ => _.FsuId,
_ => _.Result,
_ => _.IsReport,
_ => _.FsuIp,
_ => _.Updatetime
);
//Formatting cells
var UpdatetimeColumn = sheet.Column(5);
UpdatetimeColumn.Style.Numberformat.Format = "yyyy-mm-dd-hh:mm:ss";
for (var i = 1; i <= 5; i++)
{
sheet.Column(i).AutoFit();
}
});
var fileContentResult = new FileContentResult(data, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{
FileDownloadName = "升級日誌報表.xlsx"
};
return fileContentResult;
}
4.2 前端
4.2.1 vuex的action中添加請求方法
代碼如下:
actions = {
async getUpgradeLogReport(context: ActionContext<UpgradeLogState, any>) {
let data= await Ajax.get('/api/services/app/Upgrade/GetUpgradeReport',{
responseType: 'blob',
headers: {
'Content-Type': 'application/json'
}});
return data;
}
}
告訴後臺以blob形式返回。當然請求方法你也可以直接普通形式封裝,不一定封裝在vuex里,這裡封裝在vuex的一個好處是有些狀態數據可以保存在vuex,所有頁面可以共用該數據。
4.2.2 upgradeLog.vue升級頁面
4.2.2.1 增加下載方法
async downloadUpgradeLogReport(){
await this.$store.dispatch({
type: "upgradelog/getUpgradeLogReport"
}).then(res => {
if (res.status == "200") {
var excelBlob = new Blob([res.data], {
type: "application/vnd.ms-excel"
});
var fileName = "升級日誌報表.xlsx";
var oa = document.createElement("a");
oa.href = URL.createObjectURL(excelBlob);
oa.download = fileName;
document.body.appendChild(oa);
oa.click();
}
});
}
創建一個blob對象,以創建url方式將此對象下載。
4.2.2.2 點擊導出報表按鈕調用下載方法
<Button @click="downloadUpgradeLogReport()">導出升級日誌報表</Button>
5. 最終效果
5.1 點擊按鈕
5.2 報表展示
6.小結
- 筆者下載使用過多個開源方案導出Excel,此種方式方法比較輕量,使用比較簡潔;
- 在abp中返回Excel的形式需要思考,因為如果無法繼承ControllerBase,就無法使用ActionResult這種萬能返回形式(C#中只能繼承一個基類,可以繼承多個介面);
- vue中ajax接收Excel返回數據時需要註意設置返回類型為Blob,否則將會下載不成功;
- 這裡Excel導出是借鑒了Abp Zero 8.1的思路,他是類以瞬時模式註入容器,我是寫成了靜態方法。但是Abp Zero Excel導出的思路大有不同,首先是生成文件在Cache里,然後返迴文件GUID(Token),用戶再拿著GUID(Token)通過fileController從cache導出需要下載的文件。緩存有效期1分鐘,目的是為了防止有人拿到鏈接攻擊,不停下載。
版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://www.cnblogs.com/JerryMouseLi/p/13399027.html