NPOI 实现Excel模板导出

embedded/2024/11/20 9:34:25/

 记录一下使用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/embedded/139040.html

相关文章

视频直播5G CPE解决方案:ZX7981PG/ZX7981PMWIFI6网络覆盖

方案背景 视频直播蓬勃发展的当下&#xff0c;传统直播网络联网方式的局限性越来越明显。目前传统直播的局限性主要集中在以下几个方面&#xff1a; 传统直播间网络架构条件有限&#xff0c;可连接WIFI数量少&#xff0c;多终端同时直播难以维持&#xff1b;目前4G网络带宽有限…

《物理学进展》

投稿指南 《物理学进展》是中国物理学会主办的物理类刊物&#xff0c;双月刊&#xff0c;为国家中文核心期刊。刊稿内容包括物理学的各分支学科&#xff0c;着重反映物理学前沿领域的重大突破和新兴方向中的活跃状态&#xff0c;以及传统和交叉学科的最新进展。稿件类型包括对某…

2025考研政治徐涛背诵手册(电子版pdf)无套路免费分享

每天都在努力为大家搜集和整理优质的资源&#xff0c;内容涵盖学习、生活、娱乐等方方面面。这些资源可能不会立即改变你的生活&#xff0c;但我希望它们能够为你带来新的视角、新的知识&#xff0c;甚至一点点启发。无论你是为了提升自我、丰富日常&#xff0c;还是在忙碌之余…

【后端速成Vue】Vue 的生命周期

前言&#xff1a; 本期将会介绍 Vue 的声明周期对应的钩子&#xff0c;以及理解什么时候该用什么钩子函数。 篮球哥找工作专属IT岗位内部推荐&#xff1a; 专属内推链接&#xff1a;内推通道 1、了解 Vue 的生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xf…

Android集成FCM(Firebace Cloud Messaging )

集成FCM官方文档 Firebace主页面 将 Firebase 添加到您的 Android 应用 1、进入Firebace页面&#xff0c;创建自己的项目 2、点击自己创建好的项目&#xff0c;在右侧选择Cloud Messaging 3、点击Android去创建 google-services.json 4、将下载的 google-services.json 文件…

Chroma致茂Chroma61815回收式电网模拟电源

Chroma致茂 Chroma61815回收式电网模拟电源 产品特色 功率规格&#xff1a; 61809&#xff1a;9kVA 61812&#xff1a;12kVA 61815&#xff1a;15kVA 电压规格&#xff1a;0~350V 频率规格&#xff1a;30Hz~100Hz/DC 3U高度具备最大15kVA之高功率密度设计 全触控面板搭配直观的…

DataStream编程模型之数据源、数据转换、数据输出

Flink之DataStream数据源、数据转换、数据输出&#xff08;scala&#xff09; 0.前言–数据源 在进行数据转换之前&#xff0c;需要进行数据读取。 数据读取分为4大部分&#xff1a; &#xff08;1&#xff09;内置数据源&#xff1b; 又分为文件数据源&#xff1b; socket…

【开源风云】从若依系列脚手架汲取编程之道(七)

&#x1f4d5;开源风云系列 本篇文字量巨大&#xff0c;甚至在发表编辑之时造成编辑器卡顿&#xff0c;哈哈&#xff0c;最近在忙人生的另一项规划&#xff0c;文章更新就逐渐缓慢了&#xff0c;希望我们都逐渐走向自己的道路呀&#xff01; &#x1f34a;本系列将从开源名将若…