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

讲一个自己写的 excel 转 html 的 java 工具

由来

这是一个从开发需求中诞生的工具,在工作中因为有一个 excel 转 html 的任务,又没找到一个专门做这方面的工具(其他工具几乎都是简单的转换,无法还原 excel 样式,而且转换的宽高有点儿差距),所以干脆自己动手写了一个。几乎能够还原 excel 样式,且宽高几乎一致。

用法

需要注意的是,仅支持 xlsx 格式,且默认 dpi 是 96,因为不同屏幕的 dpi 可能不太一样(大多数是 96),所以尽量前端传过来,前端获取屏幕 DPI 参考:https://blog.csdn.net/jl15988/article/details/144737210

引入依赖

<dependency><groupId>com.jl15988.excel2html</groupId><artifactId>excel2html</artifactId><version>0.0.1</version>
</dependency>

使用

 List<HtmlPage> htmlPages = new Excel2Html(new File(respVO.getTempPath())).setDpi(dpi).setCellHandler(new ICellHandler() {@Overridepublic void handleStyle(ParserdStyleResult parserdStyleResult, Cell cell, int rowIndex, int cellIndex) {// 去掉第一行单元格顶部边框if (rowIndex == 4) {parserdStyleResult.cellStyle.remove("border-top");}}}).buildHtmlWithSheetIndex(4, null, 4, 46, 0, 29);
List<String> wbContent = htmlPages.stream().map(htmlPage -> htmlPage.setHasHtmlContainer(false).toHtmlString()).collect(Collectors.toList());

支持自定义单元格处理器(setCellHandler),单元格内容格式化处理(setCellValueFormater)

还有其他构建 html 方法

  • buildHtml(Sheet sheet, Integer startRowIndex, Integer endRowIndex, Integer startColIndex, Integer endColIndex)
  • buildHtmlWithSheetIndex(int sheetIndex, Integer startRowIndex, Integer endRowIndex, Integer startColIndex, Integer endColIndex)
  • buildHtmlWithSheetIndex(Integer startSheetIndex, Integer endSheetIndex, Integer startRowIndex, Integer endRowIndex, Integer startColIndex, Integer endColIndex)
  • buildHtml(Sheet sheet)
  • buildHtmlWithSheetIndex(int sheetIndex)
  • buildHtmlWithSheetIndex(Integer startSheetIndex, Integer endSheetIndex)

难点(均实现)

难点是实现的时候比较难,不代表没有实现。因为使用的是 apache.poi 依赖读取 excel,该依赖仍有某些不足,成为转 html 难点。

  1. 读取 excel 图片。excel 中图片有两种,第一种是浮动式,第二种是嵌入式,浮动式还好说 poi 能读取到,但是嵌入式只能自己解析 excel 内容,然后找到对应图片。excel 其实是一个压缩包,将其解压读取 xml 配置即可;
  2. 渲染图片位置。因为获取到的浮动式图片位置为 emu 单位,且是所在单元格坐标的信息,单位转换和坐标计算有所难点;
  3. 列宽。poi 读取到的列宽不准确,poi 中默认列宽写死了一个 8(字符宽度),这个 8 只是大概值,准确值需要自己计算;而且 poi 像素值都是乘了一个写死的 7.001699924468994(字符像素大小),这个值也是不准确的,这个值应该是 excel 默认字体的像素大小(一般国内都是默认宋体,像素大小为 8,差距也有点儿大),这个需要建立映射表,通过脚本将系统所有字体像素大小放到映射中,使用的时候再读取;
  4. 富文本解析。富文本是指在同一个单元格使用不同的字体样式。这个需要对单元格内容单独解析,构造 html 样式,这个难点不算太大;
  5. 空白字符处理。在 excel 中,连续空白字符是保留的,html 默认只显示一个,需要单独写样式,这个比较简单;如果单元格内容尾部含有空白字符且自动换行,空白字符是不占用空间的(目前看是这样),这个需要单独判断。

相关文章:

讲一个自己写的 excel 转 html 的 java 工具

由来 这是一个从开发需求中诞生的工具&#xff0c;在工作中因为有一个 excel 转 html 的任务&#xff0c;又没找到一个专门做这方面的工具&#xff08;其他工具几乎都是简单的转换&#xff0c;无法还原 excel 样式&#xff0c;而且转换的宽高有点儿差距&#xff09;&#xff0…...

前端往后端传递参数的方式有哪些?

文章目录 1. URL 参数1.1. 查询参数&#xff08;Query Parameters)1.2. 路径参数&#xff08;Path Parameters&#xff09; 2. 请求体&#xff08;Request Body&#xff09;2.1. JSON 数据2.2. 表单数据2.3. 文件上传 3. 请求头&#xff08;Headers&#xff09;3.1. 自定义请求…...

Vue axios 异步请求,请求响应拦截器

在 Vue.js 中使用 axios 进行网络请求是非常常见的做法&#xff0c;因为它提供了比原生的 Fetch API 更丰富的功能&#xff0c;并且更易于处理错误和配置。结合 Axios 的拦截器功能&#xff0c;你可以对所有的请求或响应进行预处理&#xff0c;比如添加认证头信息、统一处理错误…...

yarn install 安装报错:Workspaces can only be enabled in private projects.

在本地运行项目的时候&#xff0c;使用yarn install 安装模块依赖的时候&#xff0c;遇到报错&#xff1a;Workspaces can only be enabled in private projects. 一、原因分析 报这个错误是因为你使用了yarn的workspace&#xff0c;但并未将工程标记为private。 二、解决办法 …...

http 请求总结get

关于get请求传递body的问题 错误代码 有400 , 415 等情况 <!doctype html><html lang"zh"><head><title>HTTP Status 400 – 错误的请求</title><style type"text/css">body {font-family:Tahoma,Arial,sans-seri…...

TCP 和 UDP 的区别:解析网络传输协议

引言 在计算机网络的世界中&#xff0c;TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;和 UDP&#xff08;User Datagram Protocol&#xff0c;用户数据报协议&#xff09;是两种极为重要且应用广泛的传输层协议。它们在功能、特性以及适…...

【已解决】pyinstaller打包ico图片报错:OSError: [WinError 225] 无法成功完成操作,因为文件包含病毒或潜在的垃圾软件。

起因&#xff1a; pyinstaller加上 --icon 参数打包时报错。 命令如下&#xff1a; 解决&#xff1a; 关闭 Windows 的病毒防护即可&#xff0c;步骤如下。 点屏幕右下角通知栏&#xff0c;进入“病毒和威胁防护”&#xff1a; 打开&#xff1a; 关闭实时保护&#xff08…...

SpringBoot项目配置文件的优先级

从外部讲 内部讲 所以优先级是:外部的config里的application.yml最高 然后是外部与jar包同目录下的application.yml 再到内部的classpath下config下的application.yml 最后到classpath下的application.yml 最后来个优先级最高的 启动时候 指定spring.config.location…...

JS中类型化数组(Typed Arrays)详解和常见应用场景

在JavaScript中&#xff0c;类型化数组&#xff08;Typed Arrays&#xff09; 是用于处理二进制数据的对象。它们允许我们以一种高效的方式操作和存储大量的数值数据&#xff0c;特别适合处理类似于图像、音频、视频等场景的原始二进制数据。 类型化数组的基本概念 类型化数组…...

虚幻引擎是什么?

Unreal Engine&#xff0c;是一款由Epic Games开发的游戏引擎。该引擎主要是为了开发第一人称射击游戏而设计&#xff0c;但现在已经被成功地应用于开发模拟游戏、恐怖游戏、角色扮演游戏等多种不同类型的游戏。虚幻引擎除了被用于开发游戏&#xff0c;现在也用于电影的虚拟制片…...

LabVIEW生物医学信号虚拟实验平台

介绍了一款基于LabVIEW的多功能生物医学信号处理实验平台的设计和实现。平台通过实践活动加强学生对理论的理解和应用能力&#xff0c;特别是在心电图(ECG)和脑电图(EEG)的信号处理方面。实验平台包括信号的滤波、特征提取和频谱分析等功能&#xff0c;能直观体验和掌握生物医学…...

【软件工程】十万字知识点梳理 | 期末复习专用

原创文章,禁止转载。 文章目录 图CRC卡片用例图类图状态图活动图泳道图软件质量因素自顶向下集成自底向上集成人员与工作量之间的关系时序图关键路径软件结构基本路径测试判定表数据流图(DFD)体系结构设计问题数据字典挣值分析等价划分程序流程图PAD | N-S燃尽图甘特图对象模…...

Android --- 在AIDL进程间通信中,为什么使用RemoteCallbackList 代替 ArrayList?

1.RemoteCallbackList vs ArrayList RemoteCallbackList 是一个特殊的 List&#xff0c;它用来管理跨进程的回调&#xff0c;特别是当回调对象是在不同进程中时。它在 AIDL&#xff08;Android Interface Definition Language&#xff09;通信中常常用来处理跨进程的通信。 Arr…...

ADC(二):外部触发

有关ADC的基础知识请参考标准库入门教程 ADC&#xff08;二&#xff09;&#xff1a;外部触发 1、TIM1的CC1事件触发ADC1DMA重装载2、TIM3的TRGO事件(的更新事件)触发ADC1DMA重装载3、TIM3的TRGO事件(的捕获事件)触发ADC1DMA重装载4、优化TIM3的TRGO事件(的捕获事件)触发ADC1D…...

数仓开发那些事(8)

程序员圣经 为什么刚刚能运行&#xff0c;现在就不行 为什么刚刚不运行&#xff0c;现在就可以 为什么他的可以跑&#xff0c;我的不能跑 为什么我的可以跑&#xff0c;他的就不行 为什么这台电脑能&#xff0c;那台就不行 为什么这台电脑不行&#xff0c;那台就行 神州员工&a…...

【CSS in Depth 2 精译_096】16.4:CSS 中的三维变换 + 16.5:本章小结

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第五部分 添加动效 ✔️【第 16 章 变换】 ✔️ 16.1 旋转、平移、缩放与倾斜 16.1.1 变换原点的更改16.1.2 多重变换的设置16.1.3 单个变换属性的设置 16.2 变换在动效中的应用 16.2.1 放大图标&am…...

【连续学习之ResCL算法】2020年AAAI会议论文:Residual continual learning

1 介绍 年份&#xff1a;2020 会议&#xff1a; AAAI Lee J, Joo D, Hong H G, et al. Residual continual learning[C]//Proceedings of the AAAI Conference on Artificial Intelligence. 2020, 34(04): 4553-4560. 本文提出的算法是Residual Continual Learning (ResC…...

【zookeeper核心源码解析】第二课:俯瞰QuorumPeer启动核心流程,实现选举关键流程

系列文章目录 【zookeeper核心源码解析】第一课&#xff1a;zk启动类核心流程序列图 【zookeeper核心源码解析】第二课&#xff1a;俯瞰QuorumPeer启动核心流程&#xff0c;实现选举关键流程 【zookeeper核心源码解析】第三课&#xff1a;leader与follower何时开始同步&#…...

数据流图和流程图的区别

在结构化建模中&#xff0c;数据流图和流程图都是非常重要的工具&#xff0c;它们为开发人员提供了强大的手段来分析和设计系统。尽管两者在表面上看起来有些相似&#xff0c;但它们在功能、用途和表达方式上存在显著的区别。本文将详细探讨数据流图和流程图的区别&#xff0c;…...

关于内网服务器依托可上网电脑实现访问互联网

关于内网服务器依托可上网电脑实现访问互联网 背景&#xff1a;在实验室内网的一个服务器&#xff0c;没有配置 NAT &#xff0c;无法使用外网&#xff0c;只能在局域网内进行访问&#xff0c;但是呢&#xff0c;我们自己的电脑是可以访问互联网的&#xff0c;那么怎么通过让自…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

c++第七天 继承与派生2

这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分&#xff1a;派生类构造函数与析构函数 当创建一个派生类对象时&#xff0c;基类成员是如何初始化的&#xff1f; 1.当派生类对象创建的时候&#xff0c;基类成员的初始化顺序 …...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...