NPOI 实现Excel模板导出

devtools/2024/11/16 21:59:13/

 记录一下使用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;}


http://www.ppmy.cn/devtools/134535.html

相关文章

《硬件架构的艺术》笔记(二):时钟与复位

本章主要针对ASIC设计给出建议&#xff0c;独立于CAD工具以及工艺&#xff0c;主要针对模块设计和存储器接口。 同步设计 这是对时钟域控制最安全的方法&#xff0c;单个主时钟和单个主置位/复位信号驱动设计中所有时序器件。 避免使用行波计数器 行波计数器&#xff1a;用触…

LeetCode 491-非递减子序列

题目链接&#xff1a;LeetCod491 欢迎留言交流&#xff0c;每天都会回消息。 class Solution {//最终返回结果List<List<Integer>> rs new ArrayList<>();//递归路径中的值LinkedList<Integer> path new LinkedList<>();public List<List…

git简介和本地仓库创建,并提交修改。git config init status add commit

一、Git简介和本地仓库组成 1.1 git简介 视频教程在这 git简介&#xff0c;版本控制系统&#xff0c;工作区&#xff0c;暂存区&#xff0c;本地仓库_哔哩哔哩_bilibili 如下图&#xff0c;比如我们写毕业论文&#xff0c;要经常修改和完善&#xff0c;得靠自己保存&#x…

MyBatis缓存

目录 一、MyBatis缓存概述 二、一级缓存 三、二级缓存 四、自定义缓存 五、缓存策略与优化 MyBatis的缓存机制是其性能优化的重要组成部分&#xff0c;它通过缓存对象来存储查询结果&#xff0c;以减少数据库访问次数&#xff0c;从而提高查询性能。以下是对MyBatis缓存的…

「实战应用」如何用图表控件LightningChart .NET在WPF中制作表格?(二)

LightningChart .NET完全由GPU加速&#xff0c;并且性能经过优化&#xff0c;可用于实时显示海量数据-超过10亿个数据点。 LightningChart包括广泛的2D&#xff0c;高级3D&#xff0c;Polar&#xff0c;Smith&#xff0c;3D饼/甜甜圈&#xff0c;地理地图和GIS图表以及适用于科…

pyinstaller+upx给python GUI程序添加自定义图标

一、在线.ico图标生成 windows用48x48尺寸 https://www.ico51.cn/ 二、upx打包图标工具 https://upx.github.io/ 三、UI文件生成py代码 pyside2-uic window.ui > window.py 四、打包命令 1、–icon&#xff1a;这个是.ico图标路径 2、–upx-dir&#xff1a;upx打包工…

uniapp中多角色导致tabbar过多的解决方式

由于项目时间较紧张&#xff0c;找了很多却没找到特别合适的方法&#xff0c;最后使用了此方式。 一、自己封装tabbar组件 这里就不介绍怎么封装了&#xff0c;先说一下缺点&#xff1a; 1.跳转会有白屏问题&#xff08;并且搜了好多资料以及查看官网发现没有特别合适的方法…

求字符 ‘a‘ 和 ‘b‘ 组成的,最大长度为n的字符串中字典序第 k 个字符串

求字符 ‘a’ 和 ‘b’ 组成的&#xff0c;最大长度为n的字符串中字典序第 k 个字符串 先来解释一下这个题目&#xff0c;假设最大长度为3&#xff0c;那么由字符a和b组成的字符串有&#xff1a; a, b, ab, aaa, aba...把这些字符串按照字典序排序: aaaaaaaabababaabbbbabaab…