当前位置: 首页 > 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;自此以后&#…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

Qt的学习(一)

1.什么是Qt Qt特指用来进行桌面应用开发&#xff08;电脑上写的程序&#xff09;涉及到的一套技术Qt无法开发网页前端&#xff0c;也不能开发移动应用。 客户端开发的重要任务&#xff1a;编写和用户交互的界面。一般来说和用户交互的界面&#xff0c;有两种典型风格&…...