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;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/918886.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TCP/IP--Socket套接字--JAVA

目录 一、概念 二、分类 1.流套接字 2.数据报套接字 三、UDP数据报套接字编程 1.API介绍 2.基于UDP实现简单回显服务器 一、概念 Socket套接字&#xff0c;是由系统提供⽤于⽹络通信的技术&#xff0c;是基于TCP/IP协议的⽹络通信的基本操作单元。 基于Socket套接字的⽹络…

从大数据到大模型:现代应用的数据范式

作者介绍&#xff1a;沈炼&#xff0c;蚂蚁数据部数据库内核负责人。2014年入职蚂蚁&#xff0c;承担蚂蚁集团的数据库架构职责&#xff0c;先后负责了核心链路上OceanBase&#xff0c;OceanBase高可用体系建设、NoSQL数据库产品建设。沈炼对互联网金融、数据库内核、数据库高可…

2024雪浪小镇·京东科技上海产业对接会

11月15日下午对接会由京东科技主办在上海南翔温德姆酒店顺利召开,来自上海本地的AIoT及工业互联网优秀企业、投资人、京东生态合作伙伴齐聚一堂,共同探讨技术赋能和产业协同之路,加速企业发展和促进产业升级。 无锡经开区是无锡最年轻、最具创新动力、产业张力、宜居魅力和开放…

Vue3踩坑记录

目录 一、定义常变量 1.1、ref和reactive到底用谁&#xff1f; 二、双向绑定 2.1、直接改变表格该行数据 2.1、在弹窗改变表格该行数据 一、定义常变量 1.1、ref和reactive到底用谁&#xff1f; 已知&#xff1a;使用ref定义基础类型数据&#xff1b;使用reactive定义复…

ROM修改进阶教程------安卓14去除修改系统应用后导致的卡logo验证步骤 适用安卓13 14 安卓15可借鉴参考

上期的博文解析了安卓14 安卓15去除系统应用签名验证的步骤解析。我们要明白。修改系统应用后有那些验证。其中签名验证 去卡logo验证 与可降级安装应用验证等等的区别。有些要相互结合使用。今天的博文将对修改系统应用后卡logo验证做个步骤解析。 通过博文了解💝💝�…

2024.11.18晚Linux复习课笔记

第一章 cat -n显示行号 -b不显示空行号 pwd 打印当前的工作目录 cd ls 打印当前工作的所有文件 -a -A -l:显示当前文件的详细信息 -r:递归显示 passwd:修改密码 ip a 查看ip地址 poweroff shutdown -h 关机 reboot shutdown -r 第二章 man --help …

数据可视化如何帮助企业提升数据洞察力?

数据驱动时代&#xff0c;企业每天都在面对数据的洪流。一方面&#xff0c;拥有海量数据意味着蕴藏着无尽的机会&#xff1b;另一方面&#xff0c;如果无法提炼这些数据背后的价值&#xff0c;它们只会成为业务发展的负担。例如&#xff0c;许多企业手握丰富的销售数据&#xf…

报错java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not ...解决方法

在运行项目时出现java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field com.sun.tools.javac.tree.JCTree qualidzz这样的报错 解决方法 1.第一步&#xff1a;在pom文件中将lombok的版本改成最新的 此时1.18.34是新…

MyBatisPlus(Spring Boot版)的基本使用

1. 初始化项目 1.1. 配置application.yml spring:# 配置数据源信息datasource:# 配置数据源类型type: com.zaxxer.hikari.HikariDataSource# 配置连接数据库信息driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/mybatis_plus?characterEncodi…

【MongoDB】MongoDB的集群,部署架构,OptLog,集群优化等详解

文章目录 一、引入复制集的原因二、复制集成员&#xff08;一&#xff09;基本成员&#xff08;二&#xff09;主节点&#xff08;Primary&#xff09;细化成员 三、复制集常见部署架构&#xff08;一&#xff09;基础三节点&#xff08;二&#xff09;跨数据中心 四、复制集保…

Golang | Leetcode Golang题解之第564题寻找最近的回文数

题目&#xff1a; 题解&#xff1a; func nearestPalindromic(n string) string {m : len(n)candidates : []int{int(math.Pow10(m-1)) - 1, int(math.Pow10(m)) 1}selfPrefix, _ : strconv.Atoi(n[:(m1)/2])for _, x : range []int{selfPrefix - 1, selfPrefix, selfPrefix …

git根据远程分支创建本地新分支

比如我当前本地仓库有4个 remote 仓库&#xff0c;我希望根据其中的一个 <remote>/<branch> 创建本地分支&#xff1a; 先使用 github fetch <remote> 拉取 <remote> 的分支信息&#xff0c;然后在 git checkout -b 创建新分支时使用 -t <remote>…

r-and-r——提高长文本质量保证任务的准确性重新提示和上下文搜索的新方法可减轻大规模语言模型中的迷失在中间现象

概述 随着大规模语言模型的兴起&#xff0c;自然语言处理领域取得了重大发展。这些创新的模型允许用户通过输入简单的 "提示 "文本来执行各种任务。然而&#xff0c;众所周知&#xff0c;在问题解答&#xff08;QA&#xff09;任务中&#xff0c;用户在处理长文本时…

Redis 概 述 和 安 装

安 装 r e d i s: 1. 下 载 r e dis h t t p s : / / d o w n l o a d . r e d i s . i o / r e l e a s e s / 2. 将 redis 安装包拷贝到 /opt/ 目录 3. 解压 tar -zvxf redis-6.2.1.tar.gz 4. 安装gcc yum install gcc 5. 进入目录 cd redis-6.2.1 6. 编译 make …

Android 项目依赖库无法找到的解决方案

目录 错误信息解析 解决方案 1. 检查依赖版本 2. 检查 Maven 仓库配置 3. 强制刷新 Gradle 缓存 4. 检查网络连接 5. 手动下载依赖 总结 相关推荐 最近&#xff0c;我在编译一个 Android 老项目时遇到了一个问题&#xff0c;错误信息显示无法找到 com.gyf.immersionba…

北航软件算法C4--图部分

C4上级图部分 TOPO!步骤代码段TOPO排序部分 完整代码 简单的图图题目描述输入输出样例步骤代码段开辟vector容器作为dist二维数组初始化调用Floyd算法查询 完整代码 负环题目描述输入输出样例步骤代码段全局变量定义spfa1函数用于判断是否有负环spfa2用于记录每个点到1号点的距…

ks 小程序sig3

前言 搞了app版的快手之后 &#xff08;被风控麻了&#xff09; 于是试下vx小程序版的 抓包调试 小程序抓包问题 网上很多教程&#xff0c; github也有开源的工具代码 自行搜索 因为我们需要调试代码&#xff0c;所以就用了下开源的工具 &#xff08;可以用chrome的F12功能&a…

docker:docker: Get https://registry-1.docker.io/v2/: net/http: request canceled

无数次的拉镜像让人崩溃&#xff1a; rootnode11:~/ragflow/docker# more rag.sh #export HTTP_PROXYhttp://192.168.207.127:7890 #export HTTPS_PROXYhttp://192.168.207.127:7890 #export NO_PROXYlocalhost,127.0.0.1,.aliyun.com docker compose -f docker-compose-gpu-C…

基于java Springboot高校失物招领平台

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…

菜鸟驿站二维码/一维码 取件识别功能

特别注意需要引入 库文 ZXing 可跳转&#xff1a; 记录【WinForm】C#学习使用ZXing.Net生成条码过程_c# zxing-CSDN博客 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using static System.Net.…