java操作富文本插入到word模板
最近项目有个需求,大致流程是前端保存富文本(html的代码)到数据库,后台需要将富文本代码转成带格式的文字,插入到word模板里,然后将word转成pdf,再由前端调用接口下载pdf文件!
1、思路
这里的主要难点就是将html的格式带入到word里,所以这里要先将格式写入到html里。怎么写入到html里呢?这里提供一下思路,就是把你的word模板先转成html代码,为啥是代码不是html文件呢?因为我要用这个html代码去把富文本插进去,怎么插呢?首先要标记一个替换符在word模板里,这里有了替换符我们就可以用replace把富文本代码替换掉这个替换符,这样富文本就插进去了嘛!然后再把html代码转成word文档,再进行你的逻辑操作就可以了!
总结: 大致意思就是将word模板提取成html代码,再把富文本替换进去,然后把替换完的代码转成word。
2、依赖
主要就是用的aspose-words,因为好用所以一直在用,这里用aspose主要是文件的转换。我的业务逻辑需要把数据放到word指定的位置里,所以我要用替换的方式去替换数据,这里也用到了poi-tl。
贴一下我的版本,这里的aspose我是放到lib里了
依赖想下载的直接去下载:https://download.csdn.net/download/weixin_44953395/88565563
不要积分的
<!-- word转pdf-->
<dependency><groupId>com.aspose</groupId><artifactId>aspose-words</artifactId><version>15.8.0</version><scope>system</scope><systemPath>${project.basedir}/lib/aspose-words-15.8.0-jdk16.jar</systemPath>
</dependency>
<!--poi-tl-->
<dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.10.4</version>
</dependency>
3、代码
说了一堆废话,还是得看代码,谁也挡不住复制粘贴!
@Test
public void testDocToHtml() {String html = WordToPdfUtil.parseWord2Html("D:\\environment\\idea\\company\\ceshi\\test.docx");String fwb = "<ol><li>古诗</li></ol><p>《南歌子·似带如丝柳》</p><p><span style=\"color: rgb(212, 56, 13);\"><u>唐·温庭筠</u></span></p><p><span style=\"background-color: rgb(115, 209, 61);\">似带如丝柳,团酥握雪花。</span></p><p><span style=\"color: rgb(89, 126, 247);\">帘卷玉钩斜,九衢尘欲暮,逐香车。</span></p>";assert html != null;String fwbHtml = html.replaceAll("Fwb1", fwb);System.out.println(fwbHtml);WordToPdfUtil.htmlToWord(fwbHtml.getBytes(StandardCharsets.UTF_8), 20, "D:\\environment\\idea\\company\\ceshi\\ceshi.docx");
}
package com.byqh.utils;import com.aspose.words.*;import java.io.*;
import java.nio.charset.StandardCharsets;/*** word转Pdf帮助类* <p>* 备注:需要引入 aspose-words-15.8.0-jdk16.jar*/
public class WordToPdfUtil {private static boolean getLicense() {boolean result = false;try {InputStream is = WordToPdfUtil.class.getClassLoader().getResourceAsStream("license.xml");License asposeLic = new License();asposeLic.setLicense(is);result = true;} catch (Exception e) {e.printStackTrace();}return result;}/*** word转pdf* * @param wordPath 需要被转换的word全路径带文件名* @param pdfPath 转换之后pdf的全路径带文件名*/public static void docToPdf(String wordPath, String pdfPath) {// 验证License 若不验证则转化出的pdf文档会有水印产生if (!getLicense()) {return;}try {long old = System.currentTimeMillis();//新建一个pdf文档File file = new File(pdfPath);FileOutputStream os = new FileOutputStream(file);//wordPath是将要被转化的word文档Document doc = new Document(wordPath);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换doc.save(os, SaveFormat.PDF);long now = System.currentTimeMillis();os.close();//转化用时System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒");} catch (Exception e) {e.printStackTrace();}}/*** word转html文本** @param wordPath 需要转换的doc文件* @return html代码*/public static String parseWord2Html(String wordPath) {// 验证License 若不验证则转化出的pdf文档会有水印产生if (!getLicense()) {return null;}HtmlSaveOptions saveOptions = new HtmlSaveOptions();saveOptions.setExportHeadersFootersMode(ExportHeadersFootersMode.NONE); ByteArrayOutputStream htmlStream = new ByteArrayOutputStream();String htmlText = "";try {Document doc = new Document(wordPath);doc.save(htmlStream, saveOptions);htmlText = new String(htmlStream.toByteArray(), StandardCharsets.UTF_8);htmlStream.close();} catch (Exception e) {System.out.println(e.getMessage());}return htmlText;}/*** html字节数组转word字节数组** @param content html字节数组* @param toType 值为SaveFormat.DOCX-20或SavaFormat.Doc-10对应的值* @param filePath 转换完成之后的文件路径*/public static void htmlToWord(byte[] content, Integer toType, String filePath) {// 验证License 若不验证则转化出的pdf文档会有水印产生if (!getLicense()) {return;}try {File file = new File(filePath);FileOutputStream os = new FileOutputStream(file);InputStream is = new ByteArrayInputStream(content);Document doc = new Document();DocumentBuilder builder = new DocumentBuilder(doc);InputStreamReader streamReader = new InputStreamReader(is, StandardCharsets.UTF_8);BufferedReader reader = new BufferedReader(streamReader);String line;StringBuilder html = new StringBuilder();while ((line = reader.readLine()) != null) {html.append(line);}reader.close();builder.insertHtml(String.valueOf(html));doc.save(os, toType);System.out.println("html转word成功!");} catch (Exception e) {System.out.println(e.getMessage());}}}
效果:
替换之前:(这里的Fwb1就是一个标志符)

替换之后:

这里的富文本是用的wangeditor,网站是:https://www.wangeditor.com/
写在富文本的样子是下图这样的,总体来说还可以!

4、替换
替换用的是poi-tl,它的网址说明文档:http://deepoove.com/
@Test
public void testDocTh() throws IOException {Map<String, Object> map = new HashMap<>();map.put("sj01", "测试-test01");map.put("sj02", "测试-test02");List<PictureRenderData> list = new ArrayList<>();//这里的size设置的是宽和高list.add(Pictures.ofStream(new FileInputStream("D:\\environment\\idea\\company\\ceshi\\400X350.png")).size(400, 350).create());list.add(Pictures.ofStream(new FileInputStream("D:\\environment\\idea\\company\\ceshi\\400X400.png")).size(400, 400).create());for (int i = 0; i < list.size(); i++) {map.put("tp0" + (i + 1), list.get(i));}XWPFTemplate template = XWPFTemplate.compile("D:\\environment\\idea\\company\\ceshi\\test.docx").render(map);FileOutputStream out1 = new FileOutputStream("D:\\environment\\idea\\company\\ceshi\\out_template.docx");template.write(out1);out1.close();
}
替换之前:

替换之后:

说明一下,这里的两张图片一个是400X350的一个是400X400的两个大小差不太多,所以大小不太明显!
相关文章:
java操作富文本插入到word模板
最近项目有个需求,大致流程是前端保存富文本(html的代码)到数据库,后台需要将富文本代码转成带格式的文字,插入到word模板里,然后将word转成pdf,再由前端调用接口下载pdf文件! 1、思…...
JMeter---BeanShell实现接口前置和后置操作
在JMeter中,可以使用BeanShell脚本来实现接口的前置和后置操作。 下面是使用BeanShell脚本实现接口前置和后置操作的步骤: 1、在测试计划中添加一个BeanShell前置处理器或后置处理器。 右键点击需要添加前置或后置操作的接口请求,选择&quo…...
【Linux】共享内存
文章目录 一、共享内存的原理详谈共享内存的实现过程二、共享内存的接口函数1.shmget2. shmatshmdtshmctl 进程间使用共享内存通信三、共享内存的特性 关于代码 一、共享内存的原理 共享内存是由操作系统维护和管理的一块内存。 共享内存的本质是内核级的缓冲区。 一个进程向…...
五、双向NAT
学习防火墙之前,对路由交换应要有一定的认识 双向NAT1.1.基本原理1.2.NAT Inbound NAT Server1.3.域内NATNAT Server —————————————————————————————————————————————————— 双向NAT 经过前面介绍,…...
P1028 [NOIP2001 普及组] 数的计算
时刻记住一句话:写递归,1画图,2大脑放空!!! 意思是,自己写递归题目,先用样例给的数据画图,然后想一个超级简单的思路,直接套上去就可以了。 上题干ÿ…...
浅析三相异步电动机控制的电气保护
安科瑞 华楠 摘 要:要求三相异步电动机的控制系统不仅要保证电机正常启动和运行,完成制动操作,还要通过相关保护措施维护电动机的安全使用。基于此,本文以电动机电气保护作为研究对象,结合三相异步电动机的机械特点&…...
Java设计模式系列:单例设计模式
Java设计模式系列:单例设计模式 介绍 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法) 比如 Hiberna…...
开拓新天地:探讨数位行销对医药产业医病连结的影响
数字营销模式多元,主要围绕医生和患者。赛道各企业凭借各自优势(技术、学术、流量等)入局,提供各自差异化营销工具或服务。目前,围绕医生的数字营销旨在为医生提供全面学术解决方案从而提升对医药产品的认可࿰…...
[tsai.shen@mailfence.com].faust勒索病毒数据怎么处理|数据解密恢复
导言: [support2022cock.li].faust、[tsai.shenmailfence.com].faust、[Encrypteddmailfence.com].faust勒索病毒是一种具有恶意目的的勒索软件,其主要特点包括对受害者文件进行强力加密,然后勒索受害者支付赎金以获取解密密钥。攻击者通常通…...
Peter算法小课堂—前缀和数组的应用
桶 相当于计数排序,看一个视频 桶排序 太戈编程1620题 算法解析 #include <bits/stdc.h> using namespace std; const int R11; int cnt[R];//cnt[t]代表第t天新增几人 int s[R];//s[]数组是cnt[]数组的前缀和数组 int n,t; int main(){cin>>n;for(…...
线性表之链式表
文章目录 主要内容一.单链表1.头插法建立单链表代码如下(示例): 2.尾插法建立单链表代码如下(示例): 3.按序号查找结点值代码如下(示例): 4.按值查找表结点代码如下(示例): 5.插入节…...
[Docker]十.Docker Swarm讲解
一.Dokcer Swarm集群介绍 1.Dokcer Swarm 简介 Docker Swarm 是 Docker 公司推出的用来管理 docker 集群的工具, 使用 Docker Swarm 可以快速方便的实现 高可用集群 ,Docker Compose 只能编排单节点上的容器, Docker Swarm 可以让我们在单一主机上操作来完成对 整…...
相机机模组需求示例
产品需求名称摄像头采集图片数据补充说明产品需求描述 As:用户 I want to:通过相机模组获取到自定义格式图片数据,要求包括: 1、支持多种场景,如:手持相机拍摄舌苔 2、支持图片分辨率至少达到1920X1080 3、…...
Uniapp 微信登录流程解析
本文将介绍在 Uniapp 应用中实现微信登录的流程,包括准备工作、授权登录、获取用户信息等步骤。 内容大纲: 介绍Uniapp和微信登录: 简要介绍 Uniapp 框架以及微信登录的重要性和流行程度。 准备工作: 注册微信开发者账号创建应用…...
红旗Asianux Server Linux V8 安装万里数据库(GreatSQL)
红旗Asianux Server Linux V8 安装万里数据库(GreatSQL) 红旗Asianux介绍: 红旗Asianux Server Linux 8.0是为云时代重新设计的操作系统,为云时代的到来引入了大量新功能,包括用于配置管理、快速迁移框架、编程语言和…...
一文2000字使用JMeter进行接口测试教程!(建议收藏)
安装 使用JMeter的前提需要安装JDK,需要JDK1.7以上版本目前在用的是JMeter5.2版本,大家可自行下载解压使用 运行 进入解压路径如E: \apache-jmeter-5.2\bin,双击jmeter.bat启动运行 启动后默认为英文版本,可通过Options – Cho…...
Spark---介绍及安装
一、Spark介绍 1、什么是Spark Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。Spark是UC Berkeley AMP lab (加州大学伯克利分校的AMP实验室)所开源的类Hadoop MapReduce的通用并行计算框架,Spark拥有Hadoop MapReduce所具有的优点;但…...
uni-app:实现request请求的递归(设置request请求的访问次数),并且调用自定义方法给出返回值
一、效果展示 失败效果 成功效果 二、写入后端请求部分 分析 ①自定义一个模块common.js主要用于封装所有的请求函数 ②核心代码 function requestWithRetry(cmd, username, password, retryCount) {return new Promise((resolve, reject) > {uni.request({url: ip sys…...
数据结构-归并排序+计数排序
1.归并排序 基本思想: 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个…...
Qml使用cpp文件的信号槽
文章目录 一、C文件Demo二、使用步骤1. 初始化C文件和QML文件,并建立信号槽2.在qml中调用 一、C文件Demo Q_INVOKABLE是一个Qt元对象系统中的宏,用于将C函数暴露给QML引擎。具体来说,它使得在QML代码中可以直接调用C类中被标记为Q_INVOKABLE的…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
