在c#中使用NPOI结合Magicodes.IE.excel将xlsx文件内存中转换为xls文件
项目中使用Magicodes.IE作为导出excel的组件,但只支持新格式xlsx,有需求要导出旧格式xls文件,因此只能考虑转换的方案,经多种方案尝试和查找相关解决方案,在一份使用NPOI转换的xlsx到xls的文章到找到相关代码,但代码中只支持XSSFWorkbook转换以HSSFWorkbook,扩展后支持byte[]原始数据转换,可以在内存中直接处理。同时原来代码不能处理单元格格式,这里修复后加入单元格格式支持,暂时不支持样式。以下为xlsx转换xls工具类代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NPOI.HSSF.UserModel;
using NPOI.HSSF.Util;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.Util;
using NPOI.XSSF.UserModel;namespace Application.Util;
public static class ConvertXLSXToXLS
{/// <summary>/// 转换xlsx到xls/// </summary>/// <param name="source"></param>/// <returns></returns>public static byte[] ConvertWorkbookXSSFToHSSF(byte[] source){using (var stream = new MemoryStream(source)){XSSFWorkbook xwb = new XSSFWorkbook(stream);HSSFWorkbook hwb = ConvertWorkbookXSSFToHSSF(xwb);ByteArrayOutputStream bos = new ByteArrayOutputStream();hwb.Write(bos);return bos.ToByteArray();}}/// <summary>/// 转换xlsx到xls/// </summary>/// <param name="source"></param>/// <returns></returns>public static HSSFWorkbook ConvertWorkbookXSSFToHSSF(XSSFWorkbook source){//Install-Package NPOI -Version 2.0.6HSSFWorkbook retVal = new HSSFWorkbook();for (int i = 0; i < source.NumberOfSheets; i++){HSSFSheet hssfSheet = (HSSFSheet)retVal.CreateSheet(source.GetSheetAt(i).SheetName);XSSFSheet xssfsheet = (XSSFSheet)source.GetSheetAt(i);CopySheets(xssfsheet, hssfSheet, retVal);}return retVal;}private static void CopySheets(XSSFSheet source, HSSFSheet destination, HSSFWorkbook retVal){int maxColumnNum = 0;Dictionary<int, XSSFCellStyle> styleMap = new Dictionary<int, XSSFCellStyle>();for (int i = source.FirstRowNum; i <= source.LastRowNum; i++){XSSFRow srcRow = (XSSFRow)source.GetRow(i);HSSFRow destRow = (HSSFRow)destination.CreateRow(i);if (srcRow != null){CopyRow(source, destination, srcRow, destRow, styleMap, retVal);if (srcRow.LastCellNum > maxColumnNum){maxColumnNum = srcRow.LastCellNum;}}}for (int i = 0; i <= maxColumnNum; i++){destination.SetColumnWidth(i, source.GetColumnWidth(i));}}private static void CopyRow(XSSFSheet srcSheet, HSSFSheet destSheet, XSSFRow srcRow, HSSFRow destRow,Dictionary<int, XSSFCellStyle> styleMap, HSSFWorkbook retVal){// manage a list of merged zone in order to not insert two times a// merged zoneList<CellRangeAddress> mergedRegions = new List<CellRangeAddress>();destRow.Height = srcRow.Height;// pour chaque rowfor (int j = srcRow.FirstCellNum; j <= srcRow.LastCellNum; j++){XSSFCell oldCell = (XSSFCell)srcRow.GetCell(j); // ancienne cellHSSFCell newCell = (HSSFCell)destRow.GetCell(j); // new cellif (oldCell != null){if (newCell == null){newCell = (HSSFCell)destRow.CreateCell(j);}// copy chaque cellCopyCell(oldCell, newCell, styleMap, retVal);// copy les informations de fusion entre les cellulesCellRangeAddress mergedRegion = GetMergedRegion(srcSheet, srcRow.RowNum,(short)oldCell.ColumnIndex);if (mergedRegion != null){CellRangeAddress newMergedRegion = new CellRangeAddress(mergedRegion.FirstRow,mergedRegion.LastRow, mergedRegion.FirstColumn, mergedRegion.LastColumn);if (IsNewMergedRegion(newMergedRegion, mergedRegions)){mergedRegions.Add(newMergedRegion);destSheet.AddMergedRegion(newMergedRegion);}if (newMergedRegion.FirstColumn == 0 && newMergedRegion.LastColumn == 6 && newMergedRegion.FirstRow == newMergedRegion.LastRow){HSSFCellStyle style2 = (HSSFCellStyle)retVal.CreateCellStyle();style2.VerticalAlignment = VerticalAlignment.Center;style2.Alignment = HorizontalAlignment.Left;style2.FillForegroundColor = HSSFColor.Teal.Index;style2.FillPattern = FillPattern.SolidForeground;for (int i = destRow.FirstCellNum; i <= destRow.LastCellNum; i++){if (destRow.GetCell(i) != null)destRow.GetCell(i).CellStyle = style2;}}}}}}private static void CopyCell(XSSFCell oldCell, HSSFCell newCell, Dictionary<int, XSSFCellStyle> styleMap, HSSFWorkbook retVal){if (styleMap != null){int stHashCode = oldCell.CellStyle.Index;XSSFCellStyle sourceCellStyle = null;if (styleMap.TryGetValue(stHashCode, out sourceCellStyle)) { }HSSFCellStyle destnCellStyle = (HSSFCellStyle)newCell.CellStyle;if (sourceCellStyle == null){//sourceCellStyle = (XSSFCellStyle)oldCell.Sheet.Workbook.CreateCellStyle();sourceCellStyle = (XSSFCellStyle)oldCell.CellStyle;}//destnCellStyle.CloneStyleFrom(oldCell.CellStyle);CloneCellStyle(sourceCellStyle,ref destnCellStyle, retVal);if (!styleMap.Any(p => p.Key == stHashCode)){styleMap.Add(stHashCode, sourceCellStyle);}destnCellStyle.VerticalAlignment = VerticalAlignment.Top;newCell.CellStyle = (HSSFCellStyle)destnCellStyle;}switch (oldCell.CellType){case CellType.String:newCell.SetCellValue(oldCell.StringCellValue);break;case CellType.Numeric:newCell.SetCellValue(oldCell.NumericCellValue);break;case CellType.Blank:newCell.SetCellType(CellType.Blank);break;case CellType.Boolean:newCell.SetCellValue(oldCell.BooleanCellValue);break;case CellType.Error:newCell.SetCellErrorValue(oldCell.ErrorCellValue);break;case CellType.Formula:newCell.SetCellFormula(oldCell.CellFormula);break;default:break;}}private static CellRangeAddress GetMergedRegion(XSSFSheet sheet, int rowNum, short cellNum){for (int i = 0; i < sheet.NumMergedRegions; i++){CellRangeAddress merged = sheet.GetMergedRegion(i);if (merged.IsInRange(rowNum, cellNum)){return merged;}}return null;}private static bool IsNewMergedRegion(CellRangeAddress newMergedRegion,List<CellRangeAddress> mergedRegions){return !mergedRegions.Contains(newMergedRegion);}public static void CloneCellStyle(XSSFCellStyle sourceCellStyle, ref HSSFCellStyle destnCellStyle, HSSFWorkbook retVal){IDataFormat dataformat = retVal.CreateDataFormat();string cellStyleString = sourceCellStyle.GetDataFormatString();ICellStyle dateStyle = retVal.CreateCellStyle();dateStyle.DataFormat = dataformat.GetFormat(cellStyleString);destnCellStyle = (HSSFCellStyle)dateStyle;}
}
使用方式,使用了Magicodes.IE.excel,具体组件自行下载:
/// <summary>/// 导出XLS/// </summary>/// <returns></returns>[ApiDescriptionSettings(Name = "ExportXLS"), NonUnify][DisplayName("导出XLS")]public async Task<IActionResult> ExportXLS(RecordInput input){var query = QueryData(input);IExcelExporter excelExporter = new ExcelExporter();var res = await excelExporter.ExportAsByteArray(query.ToList());return new FileStreamResult(new MemoryStream(ConvertXLSXToXLS.ConvertWorkbookXSSFToHSSF(res)), "application/octet-stream") { FileDownloadName = "导出数据" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xls" };}
通过这种一行行转换的方案,理论上也可以将旧格式xls转换为新格式xlsx。
参考:
在c#中使用NPOI将xlsx文件转换为xls文件
https://www.itbaoku.cn/post/1946308.html?view=all
HSSFWorkbook对象转换成输入流
https://www.cnblogs.com/slzys/p/13590907.html
java实现修改excel中数据格式
https://blog.csdn.net/weixin_45706856/article/details/130328932
C# NPOI 导出Excel 日期格式
https://blog.51cto.com/u_15976398/6099632
相关文章:
在c#中使用NPOI结合Magicodes.IE.excel将xlsx文件内存中转换为xls文件
项目中使用Magicodes.IE作为导出excel的组件,但只支持新格式xlsx,有需求要导出旧格式xls文件,因此只能考虑转换的方案,经多种方案尝试和查找相关解决方案,在一份使用NPOI转换的xlsx到xls的文章到找到相关代码ÿ…...
面试经典 150 题 14 —(数组 / 字符串)— 134. 加油站
134. 加油站 方法一 class Solution { public:int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {int minSpare std::numeric_limits<int>::max(); // 初始化最小剩余汽油量为整型的最大值int spare 0; // 当前剩余汽油量int len g…...
如何设计一个安全的对外接口?
转载 https://blog.csdn.net/weixin_46742102/article/details/108831868?spm1001.2101.3001.6650.1&utm_mediumdistribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-108831868-blog-125359890.235%5Ev38%5Epc_relevant_anti_t3_base&depth_1-utm_…...
模拟pdf运行js脚本触发xss攻击及防攻击
一、引入pdfbox依赖 <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>3.0.0</version> </dependency> 二、生成一个带js脚本的pdf文件 //Creating PDF document object PDDocum…...
【数据结构】树和二叉树概念及其结构
目录 一 树概念及结构 1 树的概念 2 树的相关概念 3 树的表示 二 二叉树概念及结构 1 概念 2 特殊二叉树 3 二叉树的性质 一 树概念及结构 1 树的概念 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集…...
刘京城:我的《软件方法》学习经历(有彩蛋)
DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 写在前面(潘加宇) 下面是刘京城写的关于他学习《软件方法》的经历。我在前面啰嗦几句。 我做软件建模方面的研究和普及工作已经24年了,和各行各业…...
浏览器详解(四) 渲染
大家好,我是半虹,这篇文章来讲浏览器渲染 1、基本介绍 浏览器是多进程多线程的架构,包括有浏览器进程、渲染器进程、GPU 进程、插件进程等 在上篇文章中我们介绍过浏览器进程,作为浏览器主进程,负责浏览器基本界面的…...
idea新建一个module时,文件夹显示灰色/pom.xml文件显示灰色且中间有条横线
1.问题 2.解决方法 File->Settings->Ignored Files->找到勾选的pom.xml文件,取消勾选,点击ok即可。 3.已解决...
NoSQL数据库(林子雨慕课课程)
文章目录 5.1 NoSQL数据库5.2 NoSQL和关系数据库的比较5.3 四大类型NoSQL数据库5.3.1 键值数据库和列族数据库5.3.2 文档数据库、图数据库、以及不同数据库比较分析 5.4 NoSQL数据库的理论基石CAP理论:BASE理论:Eventual consistency(最终一致…...
模拟器运行在AndroidStudio内部,设置其独立窗口显示
在窗口内部运行 设置成独立窗口 Android Studio->Settings或Preferences->Tools->Emulator->取消勾选Launch in the Running Devices tool window --->点击右下角的OK按钮 ---> 重启Android Studio 再次启动模拟器...
计算机网络 | 体系结构
计算机网络 | 体系结构 计算机网络 | 体系结构概念及功能计算机网络简介计算机网络的功能因特网发展阶段小结 组成与分类计算机网络的组成计算机网络的分类小结 标准化工作及相关组织速率相关性能指标速率带宽吞吐量小结 时延相关性能指标时延时延带宽积往返时延RTT利用率小结 …...
ELK 处理 SpringCloud 日志
在排查线上异常的过程中,查询日志总是必不可缺的一部分。现今大多采用的微服务架构,日志被分散在不同的机器上,使得日志的查询变得异常困难。工欲善其事,必先利其器。如果此时有一个统一的实时日志分析平台,那可谓是雪…...
mac使用python递归删除文件夹下所有的.DS_Store文件
import osfolder_path "yourself file path"for root, dirs, files in os.walk(folder_path):for filename in files:if filename .DS_Store:file_path os.path.join(root, filename)os.remove(file_path)print("delete ok")...
Gitlab+Jenkins自动化部署,解放双手
项目打包 在部署项目前需要对源码进行打包,一个简单的SpringBoot项目默认是打包为jar包,也就是在pom.xml中的<packaging>jar</packaging>方式,当然也会有一些打包成war包方式,使用外置的Tomcat应用服务器部署war包…...
NNDL:作业3
在Softmax回归的风险函数(公式(3.39))中如果加上正则化项会有什么影响? (1) 在 Softmax 回归的风险函数中加入正则化项会对模型的训练产生影响。正则化项的作用是对模型的复杂度进行惩罚,防止过拟合的发生。 (2) 原书公式为: 在加入正则化后损失函数…...
dockers --cap-add 哪些值可以设置
--cap-add 参数可以用于向 Docker 容器添加不同的权限。除了 NET_ADMIN,还有一些其他常用的权限值,包括: SYS_ADMIN:添加系统管理员权限,允许容器内的进程执行系统级别的管理操作,如挂载文件系统、设置时间…...
golang常用库之-HTTP客户端请求库 grequests
文章目录 golang常用库之-HTTP客户端请求库 grequests什么是grequests使用 golang常用库之-HTTP客户端请求库 grequests 什么是grequests 官网:github.com/levigross/grequests A Go “clone” of the great and famous Requests library Go语言的grequests库是一…...
17基于matlab卡尔曼滤波的行人跟踪算法,并给出算法估计误差结果,判断算法的跟踪精确性,程序已调通,可直接运行,基于MATLAB平台,可直接拍下。
17基于matlab卡尔曼滤波的行人跟踪算法,并给出算法估计误差结果,判断算法的跟踪精确性,程序已调通,可直接运行,基于MATLAB平台,可直接拍下。 17matlab卡尔曼滤波行人跟踪 (xiaohongshu.com)...
SpringCloud之Stream框架集成RocketMQ消息中间件
Spring Cloud Stream 是一个用来为微服务应用构建消息驱动能力的框架。它可以基于 Spring Boot 来创建独立的、可用于生产的 Spring 应用程序。Spring Cloud Stream 为一些供应商的消息中间件产品提供了个性化的自动化配置实现,并引入了发布-订阅、消费组、分区这三…...
与创新者同行!Apache Doris 首届线下峰会即将开启,最新议程公开!|即刻预约
点击此处 即刻报名 Doris Summit Asia 2023 回顾人类的发展史,地球起源于 46 亿年前的原始星云、地球生命最初出现于 35 亿年前的原始海洋、人类物种诞生于数百万年前,而人类生产力的真正提升源于十八世纪六十年代的工业革命,自此以后&#…...
Java AI开发实战:基于ai4j的低版本JDK大模型集成与Agent构建指南
1. 项目概述与定位如果你是一个Java开发者,最近想在自己的项目里集成大模型能力,或者想搞点AI Agent的自动化流程,大概率会面临一个选择难题:是用Spring AI,还是LangChain4j?前者对Spring Boot 3.x和Java 1…...
每日 AI 研究简报 · 2026-05-10
(本文借助 AI 大模型及工具辅助整理) 一句话总结:Anthropic 新架构让模型「做梦」反思、MoE 专家池共享设计突破线性增长假设、AI Agent 工具栈开源井喷——今天的信号指向「模块化」与「可组合性」。 🌊 AI 动态与趋势 本周技…...
visionOS开发实战:从示例项目到空间应用构建全指南
1. 从零到一:如何高效利用 visionOS 示例项目库如果你和我一样,是个对 Apple Vision Pro 和 visionOS 开发充满好奇的开发者,那么你肯定经历过这样的阶段:面对一个全新的平台,既兴奋于其无限的可能性,又对如…...
ARM架构计数器-定时器寄存器原理与应用
1. ARM架构中的计数器-定时器寄存器深度解析在ARM处理器架构中,计数器-定时器寄存器是实现精确时间控制和事件触发的核心组件。这些寄存器不仅为操作系统提供时间基准,还在虚拟化、安全扩展和实时系统中扮演关键角色。本文将深入剖析CNTHCTL和CNTHP_CTL等…...
一本通题解——从递推公式到状态转移:破解“位数问题”中的数字计数
1. 从具体问题到通用模型:理解数字计数的本质 遇到"统计N位数中偶数个3的个数"这类问题时,很多初学者会陷入暴力枚举的思维陷阱。我刚开始刷题时也犯过这个错误——试图手动列出所有两位数来验证样例。这种方法的局限性在N1000时就会暴露无遗…...
Java数据结构6(队列和二叉树初步)
目录1,队列的性质2,循环队列3,队列链式存储4,树的性质5,二叉树的遍历6,代码实现一,队列的性质同样是线性表,队列有线性表的相关操作,不过不同的是队列的性质为先进先出&a…...
ATE PCB组装:半导体测试中的精密工艺与挑战解析
1. ATE PCB组装:半导体测试的基石与挑战 在半导体行业,一颗芯片从设计到最终封装出厂,其性能与可靠性的验证是决定产品成败的最后一环。随着芯片工艺节点不断微缩,集成度呈指数级增长,对测试环节的要求也达到了前所未有…...
【AI模型治理黄金标准】:SITS 2026认证框架首次披露——覆盖LLM/多模态/SFT模型的8维评估矩阵与23项强制基线
更多请点击: https://intelliparadigm.com 第一章:AI原生模型管理:SITS 2026 MLOps完整解决方案 SITS 2026 是面向AI原生工作负载设计的下一代MLOps平台,深度集成模型生命周期治理、动态推理编排与可信AI审计能力。其核心突破在于…...
kagent:把 Agent 当 Pod 来管,赌的是 Agent 的最终归宿是 K8s
我们写过用 kubectl apply -f deployment.yaml 起一个 Pod,写过用 Service 把它暴露出来,写过用 Operator 监听 CRD 自动调和状态。Solo.io 那群人 2025 年初做了一个看起来很自然、但没人提早做出来的事:把同一套思路平移到 AI Agent 上——…...
作业4:独立按键+数码管实操
文章目录 1.测试代码视频2.流水灯视频3.独立按键视频(点亮四个灯)4.独立按键视频(思考题点亮8个灯)5.数码管显示“111111”6.数码管显示“123456”7.数码管显示“11.12.13”8.数码管显示“HH8800.” 1.测试代码视频 测试2.流水灯视频 流水灯#include <reg51.h> // 包含…...
