在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 亿年前的原始海洋、人类物种诞生于数百万年前,而人类生产力的真正提升源于十八世纪六十年代的工业革命,自此以后&#…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
