NPOI 实现Excel模板导出
记录一下使用NPOI实现定制的Excel导出模板,已下实现需求及主要逻辑
所需Json数据 对应参数 List<PurQuoteExportDataCrInput> listData
[
{
"ItemName": "电缆VV3*16+2*10",
"Spec": "电缆VV3*16+2*10",
"Uom": "米",
"Quantity": 10.0,
"MinPrice": 100.0,
"UseOrg": null,
"SumPrice": 3000.0,
"Desc": "\r\n备注: \r\n1、只有*拟签数量,*拟签含税单价(元)可修改: \r\n2、底色标记的价格为该物料行的最低报价: \r\n3、若不中标,将拟签数量及价格空着即可: \r\n4、平台拟签数量最多保留4位小数点、拟签含税单价最多保留4位小数点,可能会造成平台总价计算结果与EXCEL计算略有差异,请以平台页面为准\"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n",
"CardList": [
{
"Name": "供应商1",
"Price": 100.0,
"SumPrice": 1000.0
},
{
"Name": "供应商2",
"Price": 200.0,
"SumPrice": 2000.0
}
]
},
{
"ItemName": "电缆VV3*70+1*35",
"Spec": "电缆VV3*70+1*35",
"Uom": "米",
"Quantity": 10.0,
"MinPrice": 100.0,
"UseOrg": null,
"SumPrice": 3000.0,
"Desc": "\r\n备注: \r\n1、只有*拟签数量,*拟签含税单价(元)可修改: \r\n2、底色标记的价格为该物料行的最低报价: \r\n3、若不中标,将拟签数量及价格空着即可: \r\n4、平台拟签数量最多保留4位小数点、拟签含税单价最多保留4位小数点,可能会造成平台总价计算结果与EXCEL计算略有差异,请以平台页面为准\"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n",
"CardList": [
{
"Name": "供应商1",
"Price": 100.0,
"SumPrice": 1000.0
},
{
"Name": "供应商2",
"Price": 200.0,
"SumPrice": 2000.0
}
]
},
{
"ItemName": "电缆VV3*95+1*50",
"Spec": "电缆VV3*95+1*50",
"Uom": "米",
"Quantity": 10.0,
"MinPrice": 100.0,
"UseOrg": null,
"SumPrice": 3000.0,
"Desc": "\r\n备注: \r\n1、只有*拟签数量,*拟签含税单价(元)可修改: \r\n2、底色标记的价格为该物料行的最低报价: \r\n3、若不中标,将拟签数量及价格空着即可: \r\n4、平台拟签数量最多保留4位小数点、拟签含税单价最多保留4位小数点,可能会造成平台总价计算结果与EXCEL计算略有差异,请以平台页面为准\"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n",
"CardList": [
{
"Name": "ZH001",
"Price": 100.0,
"SumPrice": 1000.0
},
{
"Name": "ZH002",
"Price": 200.0,
"SumPrice": 2000.0
}
]
},
{
"ItemName": "电缆VV3*120+1*70",
"Spec": "电缆VV3*120+1*70",
"Uom": "米",
"Quantity": 10.0,
"MinPrice": 0.0,
"UseOrg": null,
"SumPrice": 0.0,
"Desc": "\r\n备注: \r\n1、只有*拟签数量,*拟签含税单价(元)可修改: \r\n2、底色标记的价格为该物料行的最低报价: \r\n3、若不中标,将拟签数量及价格空着即可: \r\n4、平台拟签数量最多保留4位小数点、拟签含税单价最多保留4位小数点,可能会造成平台总价计算结果与EXCEL计算略有差异,请以平台页面为准\"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n",
"CardList": [
{
"Name": "ZH001",
"Price": 0.0,
"SumPrice": 0.0
},
{
"Name": "ZH002",
"Price": 0.0,
"SumPrice": 0.0
}
]
}
]
调用方法
/// <summary>
/// 导出特定模板数据.
/// </summary>
/// <param name="tempFileName">模板名称.</param>
/// <param name="listData">模板数据.</param>
/// <returns></returns>
[NonAction]
private async Task<dynamic> ExportTempExcelData(string tempFileName, List<PurQuoteExportDataCrInput> listData)
{
//文件服务器地址
string addPath = Path.Combine("D:\\TemporaryFile", tempFileName);
// 创建一个新的工作簿
HSSFWorkbook workbook = new HSSFWorkbook();
ISheet sheet = workbook.CreateSheet("定制模版");
// 合并列
sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, 0, 5)); // 采购信息
sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(1, 2, 0, 0)); // 序号
sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(1, 2, 4, 4)); // 采购数量
sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(1, 2, 5, 5)); // 最低报价
// 设置单元格宽度
sheet.SetColumnWidth(1, 20 * 256); // 物料名称宽度
sheet.SetColumnWidth(2, 20 * 256); // 规格型号宽度
// 设置主要样式
var cellStyle = SetMainCellStyle();
// 创建行
var row1 = sheet.CreateRow(0);
var row2 = sheet.CreateRow(1);
var row3 = sheet.CreateRow(2);
// 设置行高
row1.Height = 30 * 30;
row2.Height = 30 * 20;
row3.Height = 30 * 20;
// 采购信息标题
var row1_cel = row1.CreateCell(0);
row1_cel.SetCellValue("采购信息");
row1_cel.CellStyle = cellStyle;
// 设置边框
row1.CreateCell(1).CellStyle = cellStyle;
row1.CreateCell(2).CellStyle = cellStyle;
row1.CreateCell(3).CellStyle = cellStyle;
row1.CreateCell(4).CellStyle = cellStyle;
// 序号标题
var cell2 = row2.CreateCell(0);
cell2.SetCellValue("序号");
cell2.CellStyle = cellStyle;
// 采购数量标题
var row2_cel4 = row2.CreateCell(4);
row2_cel4.SetCellValue("采购数量");
row2_cel4.CellStyle = cellStyle;
// 最低报价标题
var row2_cel5 = row2.CreateCell(5);
row2_cel5.SetCellValue("最低报价");
row2_cel5.CellStyle = cellStyle;
// 填充边框
row3.CreateCell(0).CellStyle = cellStyle;
// 物料名称标题
var row3_cel1 = row3.CreateCell(1);
row3_cel1.SetCellValue("物料名称");
row3_cel1.CellStyle = cellStyle;
// 规格型号标题
var row3_cel2 = row3.CreateCell(2);
row3_cel2.SetCellValue("规格型号");
row3_cel2.CellStyle = cellStyle;
// 计量单位标题
var row3_cel3 = row3.CreateCell(3);
row3_cel3.SetCellValue("计量单位");
row3_cel3.CellStyle = cellStyle;
// 填充边框
row3.CreateCell(4).CellStyle = cellStyle;
row3.CreateCell(5).CellStyle = cellStyle;
// 从第4行开始都是动态数据
int startRow4 = 3;
// 记录最有一列下标
int lastIndex = 0;
// 拟签含税总价
double sumAmount = 0;
// 动态渲染数据
for (var i = 0; i < listData.Count; i++)
{
ICellStyle dyCel_Style = SetMainCellStyle(false);
var dyRow = sheet.CreateRow(startRow4);
dyRow.Height = 30 * 20; // 设置行高
var dyCel0 = dyRow.CreateCell(0);
dyCel0.SetCellValue(i + 1); // 序号值
dyCel0.CellStyle = dyCel_Style;
var dyCel1 = dyRow.CreateCell(1);
dyCel1.SetCellValue(listData[i].ItemName); // 物料名称值
dyCel1.CellStyle = dyCel_Style;
var dyCel2 = dyRow.CreateCell(2);
dyCel2.SetCellValue(listData[i].ItemName); // 型号规格值
dyCel2.CellStyle = dyCel_Style;
var dyCel3 = dyRow.CreateCell(3);
dyCel3.SetCellValue(listData[i].Uom); // 计量单位值
dyCel3.CellStyle = dyCel_Style;
var dyCel4 = dyRow.CreateCell(4);
dyCel4.SetCellValue(listData[i].Quantity); // 采购数量值
dyCel4.CellStyle = dyCel_Style;
var dyCel5 = dyRow.CreateCell(5);
dyCel5.SetCellValue(listData[i].MinPrice); // 最低报价值
dyCel5.CellStyle = dyCel_Style;
startRow4++;
int startNum = 6;
int endNum = 7;
// 动态供应商信息从第六列开始遍历数据
var cardList = listData[i].CardList;
for (int k = 0; k < cardList.Count; k++)
{
if (i == 0)
{
// 合并列
sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, startNum, endNum)); // 供应名称
sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(1, 2, startNum, startNum)); // 单价
sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(1, 2, endNum, endNum)); // 总价
// 供应商
ICell cell = row1.CreateCell(startNum);
cell.SetCellValue(cardList[k].Name);
cell.CellStyle = cellStyle;
// 填充边框
ICell cell1 = row1.CreateCell(endNum);
cell1.CellStyle = cellStyle;
// 单价标题
var row2_cel_num = row2.CreateCell(startNum);
row2_cel_num.SetCellValue("单价");
row2_cel_num.CellStyle = cellStyle;
// 总价标题
var row2_cel_num1 = row2.CreateCell(endNum);
row2_cel_num1.SetCellValue("总价");
row2_cel_num1.CellStyle = cellStyle;
// 填充边框
row3.CreateCell(startNum).CellStyle = cellStyle;
row3.CreateCell(endNum).CellStyle = cellStyle;
}
// 单价值
var row4_cel_num = dyRow.CreateCell(startNum);
row4_cel_num.SetCellValue(cardList[k].Price);
row4_cel_num.CellStyle = dyCel_Style;
// 总价值
var row4_cel_num1 = dyRow.CreateCell(endNum);
row4_cel_num1.SetCellValue(cardList[k].SumPrice);
row4_cel_num1.CellStyle = dyCel_Style;
// 供应商单价、总价突出显示
if(listData[i].MinPrice == cardList[k].Price && listData[i].MinPrice > 0)
{
ICellStyle style1 = SetMainCellStyle(false);
style1.FillForegroundColor = IndexedColors.Red.Index; // 设置背景颜色为红色
style1.FillPattern = FillPattern.SolidForeground; // 填充模式为纯色
row4_cel_num.CellStyle = style1;
row4_cel_num1.CellStyle = style1;
sumAmount += cardList[k].SumPrice;
}
startNum += 2;
endNum = startNum + 1;
lastIndex = startNum;
}
// 使用单位值
var dyCeln = dyRow.CreateCell(lastIndex);
dyCeln.SetCellValue("使用单位" + i);
dyCeln.CellStyle = dyCel_Style;
}
// 处理边框
var row1_cel_last = row1.CreateCell(lastIndex);
row1_cel_last.CellStyle = cellStyle;
var row2_cel_last = row2.CreateCell(lastIndex);
row2_cel_last.CellStyle = cellStyle;
var row3_cel_last = row3.CreateCell(lastIndex);
row3_cel_last.CellStyle = cellStyle;
row3_cel_last.SetCellValue("使用单位");
// 合并拟签含税总价
sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(startRow4, startRow4, 0, lastIndex - 1));
// 合并备注
sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(startRow4 + 1, startRow4 + 1, 0, lastIndex - 1));
// 设置合并拟签含税总价
var row_sprice = sheet.CreateRow(startRow4);
row_sprice.Height = 30 * 15;
var cell_sprice = row_sprice.CreateCell(0);
cell_sprice.SetCellValue("拟签含税总价:" + sumAmount);
ICellStyle cell_sprice_style = SetMainCellStyle();
cell_sprice_style.Alignment = HorizontalAlignment.Left; // 垂直靠左
cell_sprice.CellStyle = cell_sprice_style;
// 设置备注
var row_desc = sheet.CreateRow(startRow4 + 1);
row_desc.Height = 30 * 50;
var cell_desc = row_desc.CreateCell(0);
cell_desc.SetCellValue(listData[0].Desc);
ICellStyle cell_desc_style = SetMainCellStyle();
cell_desc_style.Alignment = HorizontalAlignment.Left; // 垂直靠左
var cell_desc_style_font = workbook.CreateFont();
cell_desc_style_font.FontName = "SimSun";
cell_desc_style_font.FontHeightInPoints = 8; // 设置字体大小
cell_desc_style_font.Color = HSSFColor.Red.Index; // 设置字体颜色
cell_desc_style.SetFont(cell_desc_style_font);
cell_desc.CellStyle = cell_desc_style;
// 处理合并拟签含税总价样式、备注样式其余边框
for (var i = 1; i < lastIndex + 1; i++)
{
ICellStyle cellStyle2 = workbook.CreateCellStyle();
SetCellBorder(cellStyle2);
row_sprice.CreateCell(i).CellStyle = cellStyle2;
row_desc.CreateCell(i).CellStyle = cellStyle2;
}
MemoryStream fileStream = new MemoryStream();
workbook.Write(fileStream);
fileStream.Position = 0; // 确保流的位置重置为0
//文件上传到服务器本地
await _fileManager.UploadFileByType(fileStream, FileVariable.TemporaryFilePath, tempFileName);
//返回文件下载地址前端调用下载
return new { name = tempFileName, url = "/api/file/Download?file=" + tempFileName ) };
// 设置单元格边框
void SetCellBorder(ICellStyle _cellStyle)
{
// 设置单元格边框样式
_cellStyle.BorderTop = BorderStyle.Thin; // 上边框
_cellStyle.BorderBottom = BorderStyle.Thin; // 下边框
_cellStyle.BorderLeft = BorderStyle.Thin; // 左边框
_cellStyle.BorderRight = BorderStyle.Thin; // 右边框
// 设置边框颜色黑色
_cellStyle.TopBorderColor = IndexedColors.Black.Index;
_cellStyle.BottomBorderColor = IndexedColors.Black.Index;
_cellStyle.LeftBorderColor = IndexedColors.Black.Index;
_cellStyle.RightBorderColor = IndexedColors.Black.Index;
}
// 设置主要样式
ICellStyle SetMainCellStyle(bool fontBold = true)
{
// 创建单元格样式
ICellStyle cellStyle = workbook.CreateCellStyle();
SetCellBorder(cellStyle);
// 创建字体样式
var font = workbook.CreateFont();
font.IsBold = fontBold; // 设置字体加粗
font.FontName = "SimSun"; // 设置宋体
cellStyle.SetFont(font);
cellStyle.Alignment = HorizontalAlignment.Center; // 水平居中
cellStyle.VerticalAlignment = VerticalAlignment.Center; // 垂直居中
cellStyle.WrapText = true; // 自动换行
return cellStyle;
}