当前位置: 首页 > news >正文

在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的组件&#xff0c;但只支持新格式xlsx&#xff0c;有需求要导出旧格式xls文件&#xff0c;因此只能考虑转换的方案&#xff0c;经多种方案尝试和查找相关解决方案&#xff0c;在一份使用NPOI转换的xlsx到xls的文章到找到相关代码&#xff…...

面试经典 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 树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集…...

刘京城:我的《软件方法》学习经历(有彩蛋)

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 写在前面&#xff08;潘加宇&#xff09; 下面是刘京城写的关于他学习《软件方法》的经历。我在前面啰嗦几句。 我做软件建模方面的研究和普及工作已经24年了&#xff0c;和各行各业…...

浏览器详解(四) 渲染

大家好&#xff0c;我是半虹&#xff0c;这篇文章来讲浏览器渲染 1、基本介绍 浏览器是多进程多线程的架构&#xff0c;包括有浏览器进程、渲染器进程、GPU 进程、插件进程等 在上篇文章中我们介绍过浏览器进程&#xff0c;作为浏览器主进程&#xff0c;负责浏览器基本界面的…...

idea新建一个module时,文件夹显示灰色/pom.xml文件显示灰色且中间有条横线

1.问题 2.解决方法 File->Settings->Ignored Files->找到勾选的pom.xml文件&#xff0c;取消勾选&#xff0c;点击ok即可。 3.已解决...

NoSQL数据库(林子雨慕课课程)

文章目录 5.1 NoSQL数据库5.2 NoSQL和关系数据库的比较5.3 四大类型NoSQL数据库5.3.1 键值数据库和列族数据库5.3.2 文档数据库、图数据库、以及不同数据库比较分析 5.4 NoSQL数据库的理论基石CAP理论&#xff1a;BASE理论&#xff1a;Eventual consistency&#xff08;最终一致…...

模拟器运行在AndroidStudio内部,设置其独立窗口显示

在窗口内部运行 设置成独立窗口 Android Studio->Settings或Preferences->Tools->Emulator->取消勾选Launch in the Running Devices tool window --->点击右下角的OK按钮 ---> 重启Android Studio 再次启动模拟器...

计算机网络 | 体系结构

计算机网络 | 体系结构 计算机网络 | 体系结构概念及功能计算机网络简介计算机网络的功能因特网发展阶段小结 组成与分类计算机网络的组成计算机网络的分类小结 标准化工作及相关组织速率相关性能指标速率带宽吞吐量小结 时延相关性能指标时延时延带宽积往返时延RTT利用率小结 …...

ELK 处理 SpringCloud 日志

在排查线上异常的过程中&#xff0c;查询日志总是必不可缺的一部分。现今大多采用的微服务架构&#xff0c;日志被分散在不同的机器上&#xff0c;使得日志的查询变得异常困难。工欲善其事&#xff0c;必先利其器。如果此时有一个统一的实时日志分析平台&#xff0c;那可谓是雪…...

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自动化部署,解放双手

项目打包 ​ 在部署项目前需要对源码进行打包&#xff0c;一个简单的SpringBoot项目默认是打包为jar包&#xff0c;也就是在pom.xml中的<packaging>jar</packaging>方式&#xff0c;当然也会有一些打包成war包方式&#xff0c;使用外置的Tomcat应用服务器部署war包…...

NNDL:作业3

在Softmax回归的风险函数(公式(3.39))中如果加上正则化项会有什么影响? (1) 在 Softmax 回归的风险函数中加入正则化项会对模型的训练产生影响。正则化项的作用是对模型的复杂度进行惩罚&#xff0c;防止过拟合的发生。 (2) 原书公式为&#xff1a; 在加入正则化后损失函数…...

dockers --cap-add 哪些值可以设置

--cap-add 参数可以用于向 Docker 容器添加不同的权限。除了 NET_ADMIN&#xff0c;还有一些其他常用的权限值&#xff0c;包括&#xff1a; SYS_ADMIN&#xff1a;添加系统管理员权限&#xff0c;允许容器内的进程执行系统级别的管理操作&#xff0c;如挂载文件系统、设置时间…...

golang常用库之-HTTP客户端请求库 grequests

文章目录 golang常用库之-HTTP客户端请求库 grequests什么是grequests使用 golang常用库之-HTTP客户端请求库 grequests 什么是grequests 官网&#xff1a;github.com/levigross/grequests A Go “clone” of the great and famous Requests library Go语言的grequests库是一…...

17基于matlab卡尔曼滤波的行人跟踪算法,并给出算法估计误差结果,判断算法的跟踪精确性,程序已调通,可直接运行,基于MATLAB平台,可直接拍下。

17基于matlab卡尔曼滤波的行人跟踪算法&#xff0c;并给出算法估计误差结果&#xff0c;判断算法的跟踪精确性&#xff0c;程序已调通&#xff0c;可直接运行&#xff0c;基于MATLAB平台&#xff0c;可直接拍下。 17matlab卡尔曼滤波行人跟踪 (xiaohongshu.com)...

SpringCloud之Stream框架集成RocketMQ消息中间件

Spring Cloud Stream 是一个用来为微服务应用构建消息驱动能力的框架。它可以基于 Spring Boot 来创建独立的、可用于生产的 Spring 应用程序。Spring Cloud Stream 为一些供应商的消息中间件产品提供了个性化的自动化配置实现&#xff0c;并引入了发布-订阅、消费组、分区这三…...

与创新者同行!Apache Doris 首届线下峰会即将开启,最新议程公开!|即刻预约

点击此处 即刻报名 Doris Summit Asia 2023 回顾人类的发展史&#xff0c;地球起源于 46 亿年前的原始星云、地球生命最初出现于 35 亿年前的原始海洋、人类物种诞生于数百万年前&#xff0c;而人类生产力的真正提升源于十八世纪六十年代的工业革命&#xff0c;自此以后&#…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...