Springboot 替换/写入 word文档里面的文字、图片,1秒钟实现

news/2024/5/13 5:08:01/文章来源:https://blog.csdn.net/qq_35387940/article/details/128235341

前言

 图片加水印:
Springboot 图片需要添加水印,怎么办? 1秒就实现

那么word文档替换文字、插入图片,当然也是1秒钟了(jar包引入,工具类代码复制粘贴,调试,完事)。
 

事不宜迟,开始敲代码。


正文


本篇内容:

1.word文档 替换内容里面的文字 (模板占位符方式传参替换)

2.word文档 插入图片 (指定位置传参插入)


① pom.xml 引入依赖:


        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.15</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>3.15</version>
        </dependency>

② 工具类  MyDocxUtil.java

import org.apache.poi.POIXMLDocument;
import org.apache.poi.xwpf.usermodel.*;
import java.io.FileOutputStream;
import java.util.*;
import java.util.Map.Entry;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;public class MyDocxUtil {/*** 文字替换* @param srcPath* @param destPath* @param map*/public static void searchAndReplace(String srcPath, String destPath, Map<String, String> map) {try {//doc文件使用HWPFDocument读取,docx文件使用XWPFDocument读取。XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(srcPath));/*** 替换段落中的指定文字*/Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();while (itPara.hasNext()) {XWPFParagraph paragraph = (XWPFParagraph) itPara.next();Set<String> set = map.keySet();Iterator<String> iterator = set.iterator();while (iterator.hasNext()) {String key = iterator.next();List<XWPFRun> run=paragraph.getRuns();for(int i=0;i<run.size();i++){if(run.get(i).getText(run.get(i).getTextPosition())!=null &&run.get(i).getText(run.get(i).getTextPosition()).equals(key)){/*** 参数0表示生成的文字是要从哪一个地方开始放置,设置文字从位置0开始* 就可以把原来的文字全部替换掉了*/run.get(i).setText(map.get(key),0);}}}}/*** 替换表格中的指定文字*/Iterator<XWPFTable> itTable = document.getTablesIterator();while (itTable.hasNext()) {XWPFTable table = (XWPFTable) itTable.next();int count = table.getNumberOfRows();for (int i = 0; i < count; i++) {XWPFTableRow row = table.getRow(i);List<XWPFTableCell> cells = row.getTableCells();for (XWPFTableCell cell : cells) {for (Entry<String, String> e : map.entrySet()) {if (cell.getText().equals(e.getKey())) {cell.removeParagraph(0);cell.setText(e.getValue());}}}}}FileOutputStream outStream = null;outStream = new FileOutputStream(destPath);document.write(outStream);outStream.close();} catch (Exception e) {e.printStackTrace();}}public static void main(String[] args) {Map<String, String> map = new HashMap<>();map.put("<v1>", "认可");map.put("<phone>", "136919xxxxx");map.put("<地址>", "中国广东省深圳市");String srcPath = "D:\\test.docx";String destPath = "D:\\mytestNew.docx";searchAndReplace(srcPath, destPath, map);System.out.println("操作完毕");}
}

③ 调试

准备一个简单的word内容文档, 假装这就是我们业务需求使用的模板内容:


可以看到 我这个模板内容里面,有三个类似站位符的内容(红色标识)


 

 然后对照看下怎么用这个工具类,传参来替换这个模板内容的文字:

 

    public static void main(String[] args) {Map<String, String> map = new HashMap<>();map.put("<v1>", "认可");map.put("<phone>", "136919xxxxx");map.put("<地址>", "中国广东省深圳市");String srcPath = "D:\\test.docx";String destPath = "D:\\mytestNew.docx";searchAndReplace(srcPath, destPath, map);System.out.println("操作完毕");}

 代码简析:  

运行方法,看看效果:
 

 效果:

好了文字替换玩了一下,接下来玩下插入图片:

先准备一张 ‘公章’图片:
 

然后在模板文档里面, 需要盖章的地方 ,设置一个占位标识 :

然后加下插入图片的函数代码:
 

    /*** <b> Word中添加图章* </b><br><br><i>Description</i> :* String srcPath, 源Word路径* String storePath, 添加图章后的路径* String sealPath, 图章路径(即图片)* tString abText, 在Word中盖图章的标识字符串,如:(签字/盖章)* int width, 图章宽度* int height, 图章高度* int leftOffset, 图章在编辑段落向左偏移量* int topOffset, 图章在编辑段落向上偏移量* boolean behind,图章是否在文字下面** @return void* <br><br>Date: 2019/12/26 15:12     <br>Author : dxl*/public static void sealInWord(String srcPath, String storePath, String sealPath, String tabText,int width, int height, int leftOffset, int topOffset, boolean behind) throws Exception {File fileTem = new File(srcPath);InputStream is = new FileInputStream(fileTem);XWPFDocument document = new XWPFDocument(is);List<XWPFParagraph> paragraphs = document.getParagraphs();XWPFRun targetRun = null;for (XWPFParagraph paragraph : paragraphs) {if (!"".equals(paragraph.getText()) && paragraph.getText().contains(tabText)) {List<XWPFRun> runs = paragraph.getRuns();targetRun = runs.get(runs.size() - 1);}}if (targetRun != null) {InputStream in = new FileInputStream(sealPath);//设置图片路径if (width <= 0) {width = 100;}if (height <= 0) {height = 100;}//创建Random类对象Random random = new Random();//产生随机数int number = random.nextInt(999) + 1;targetRun.addPicture(in, Document.PICTURE_TYPE_PNG, "Seal" + number, Units.toEMU(width), Units.toEMU(height));in.close();// 2. 获取到图片数据CTDrawing drawing = targetRun.getCTR().getDrawingArray(0);CTGraphicalObject graphicalobject = drawing.getInlineArray(0).getGraphic();//拿到新插入的图片替换添加CTAnchor 设置浮动属性 删除inline属性CTAnchor anchor = getAnchorWithGraphic(graphicalobject, "Seal" + number,Units.toEMU(width), Units.toEMU(height),//图片大小Units.toEMU(leftOffset), Units.toEMU(topOffset), behind);//相对当前段落位置 需要计算段落已有内容的左偏移drawing.setAnchorArray(new CTAnchor[]{anchor});//添加浮动属性drawing.removeInline(0);//删除行内属性}document.write(new FileOutputStream(storePath));document.close();}/*** @param ctGraphicalObject 图片数据* @param deskFileName      图片描述* @param width             宽* @param height            高* @param leftOffset        水平偏移 left* @param topOffset         垂直偏移 top* @param behind            文字上方,文字下方* @return* @throws Exception*/public static CTAnchor getAnchorWithGraphic(CTGraphicalObject ctGraphicalObject,String deskFileName, int width, int height,int leftOffset, int topOffset, boolean behind) {System.out.println(">>width>>" + width + "; >>height>>>>" + height);String anchorXML ="<wp:anchor xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" "+ "simplePos=\"0\" relativeHeight=\"0\" behindDoc=\"" + ((behind) ? 1 : 0) + "\" locked=\"0\" layoutInCell=\"1\" allowOverlap=\"1\">"+ "<wp:simplePos x=\"0\" y=\"0\"/>"+ "<wp:positionH relativeFrom=\"column\">"+ "<wp:posOffset>" + leftOffset + "</wp:posOffset>"+ "</wp:positionH>"+ "<wp:positionV relativeFrom=\"paragraph\">"+ "<wp:posOffset>" + topOffset + "</wp:posOffset>" +"</wp:positionV>"+ "<wp:extent cx=\"" + width + "\" cy=\"" + height + "\"/>"+ "<wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"0\"/>"+ "<wp:wrapNone/>"+ "<wp:docPr id=\"1\" name=\"Drawing 0\" descr=\"" + deskFileName + "\"/><wp:cNvGraphicFramePr/>"+ "</wp:anchor>";CTDrawing drawing = null;try {drawing = CTDrawing.Factory.parse(anchorXML);} catch (XmlException e) {e.printStackTrace();}CTAnchor anchor = drawing.getAnchorArray(0);anchor.setGraphic(ctGraphicalObject);return anchor;}

调用一下函数玩下:
 

    public static void main(String[] args) throws Exception {sealInWord("D:\\mytestNew.docx","D:\\mytestWithImg.docx","D:\\gz.png", "(印章)", 0, 0,310, 110, false);}

 代码简析: 

运行一下,打开新文件看看效果:
 

好了,该篇就到这吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_232520.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[附源码]Python计算机毕业设计Djang基于vuejs的文创产品销售平台app

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

2022年国际工程行业研究报告

第一章 行业概况 国际工程是指一个工程项目从咨询、投资、招投标、承包(包括分包)、设备采购、培训到监理各个阶段的参与者来自不止一个国家&#xff0c;并且按照国际工程项目管理模式进行管理的工程。国际工程是一种综合性的国际经济合作方式&#xff0c;是国际技术贸易的一种…

2023年湖北监理工程师报考时间是什么时候?

2023年湖北监理工程师报考时间是什么时候&#xff1f; 监理工程师考试时间虽说是全国统一的&#xff0c;但是监理工程师报名时间不统一&#xff0c;每个省份自行安排报名时间&#xff0c;监理工程师报名时间基本都是在2.3月份开始报名&#xff0c;具体关注每个省人事考试院网站…

【爬虫5年保更新专栏】异步协程典型案例,一篇掌握~

最近收到 C 友反馈&#xff0c;说 《听说过 python 协程没&#xff1f;听说过 asyncio 库没&#xff1f;都在这一篇博客了》 这篇博客的目标图片站&#xff0c;已经不能使用了&#xff0c;橡皮擦查阅之后&#xff0c;发现是对方网站已经不运营了&#xff0c;所以更新一下案例。…

寻找适配网红很迷茫?最全秘笈来了

根据《2022年全球数字概览》报告显示&#xff0c;全球社交媒体用户超过46.2亿&#xff0c;相当于全球总人口的58.4%。全球用户每天在社交媒体上平均花费近2.5个小时&#xff0c;并且每天以2分钟的速度增长。 社交媒体成为全球网民生活中不可或缺的一部分&#xff0c;而对于跨境…

2022全年度冰箱十大热门品牌销量榜单

自2022年年初以来&#xff0c;各地纷纷部署支持包括冰箱在内的家电大宗消费政策措施&#xff0c;其中家电补贴政策是刺激家电消费的主旋律。宏观经济政策环境改善&#xff0c;利好冰箱行业的长期发展。 根据鲸参谋数据统计&#xff0c;今年京东平台冰箱的年度累计销量达到1400多…

有趣且重要的css知识合集(6)动态控制css伪元素【var()】

在vue里&#xff0c;js和css的属性可以随意控制&#xff0c;比如:class和:style&#xff0c;但是我们想要动态控制伪元素的属性该怎么做呢&#xff1f; 比如下图&#xff0c;右下角小圆圈就是通过伪元素定义上去的&#xff0c;那我们想要自由实现伪元素的显示和隐藏该怎么做呢…

研究一段WPF 3D 机械臂代码

网上下一段代码&#xff0c;运行如下&#xff1b;显示了一个3D机械臂&#xff1b; xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"&#xff0c;这是WPF命名空间&#xff0c;一般写在xaml头部&#xff0c;它的是这样的&#xff0c;<Viewport3D…

浅学Linux内核MMU

1 MMU基本知识 1.1 什么是MMU MMU是 MemoryManagementUnit 的缩写即&#xff0c;内存管理单元. 针对各种CPU, MMU是个可选的配件. MMU负责的是虚拟地址与物理地址的转换. 提供硬件机制的内存访问授权.&#xff08;现代 CPU 的应用中&#xff0c;基本上都选择了使用 MMU&#…

Kafka 为什么那么快?

有人说&#xff1a;他曾在一台配置较好的机子上对 Kafka 进行性能压测&#xff0c;压测结果是 Kafka 单个节点的极限处理能力接近每秒 2000万 条消息&#xff0c;吞吐量达到每秒 600MB。 那 Kafka 为什么这么快&#xff1f;如何做到这个高的性能&#xff1f; 本篇文章主要从这…

面试官:MySQL 中 varchar(n) 中 n 最大取值为多少?

前置知识 要回答这个问题&#xff0c;首先我们得先知道 MySQL 存储一条记录的格式长什么样子。 以 Compact 行格式作为例子&#xff0c;它长这样&#xff1a; 可以看到&#xff0c;一条完整的记录分为「记录的额外信息」和「记录的真实数据」两个部分。 这里重点讲讲记录的…

安卓APP源码和设计报告——健身系统

一、设计背景 1.需求分析 对于很多人来说拥有一副好身材能让自己增添不少魅力;对于爱吃而又担心自己发胖的人来说适当的运动健身是最好的选择。移动互联网时代&#xff0c;市场上“约跑”“约健身”健身APP软件成为新时代闺蜜朋友的互动模式&#xff0c;健身热潮的来临&#…

MySQL分区详解

目录 一、定义 1.1 概述 1.2 分区的优势 二、分区的类型 2.1 检查MySQL是否支持分区 2.2 类型 2.3 分区的其他操作 一、定义 1.1 概述 数据库分区是一种物理数据库设计技术。虽然分区技术可以实现很多效果&#xff0c;但其主要目的是为了在特定的SQL操作中减少数据读写…

第17章 事件和概率空间

第17章 事件和概率空间 17.1 做个交易吧 假设你有三扇门可供选择。其中一扇门背后是一辆汽车&#xff0c;另外两扇门背后是一只山羊。你选择了一扇门&#xff0c;比如1号门。然后知道门后面有什么的主持人&#xff0c;开启了另一扇后面有山羊的门&#xff0c;假设是3号门。现…

The reference to entity “useSSL“ must end with the ‘;‘ delimiter.

The reference to entity "useSSL" must end with the ; delimiter.& 替换为 &amp; < 替换为 < > 替换为 > " 替换为 &quot;替换为 &apos; jdbc:mysql://127.0.0.1:3306/dbname?characterEncodingutf8&amp;useSSLfalse&am…

Redis vs MongoDB

Redis vs MongoDB 通常情况下&#xff0c;应用系统的技术选型&#xff0c;对于如何选择非关系型数据库&#xff0c;是一个不小的挑战。这不仅考验架构师在技术上的广度和深度&#xff0c;同时也考究对业务细节了解和熟悉程度。只有将业务场景、业务特点、数据特征跟具体的技术…

Qt 多线程之QtConcurrent::map(处理序列容器)

QtConcurrent::map()、QtConcurrent::mapped() 和 QtConcurrent::mappedReduced() 函数对一个序列中&#xff08;例如&#xff1a;QList、QVector&#xff09;的项目并行地进行计算。 1、map函数 map函数的功能是在其他线程运行指定的函数&#xff0c;map函数有两个参数 第一…

玩好.NET高级调试,你也要会写点汇编

一&#xff1a;背景 1. 简介 .NET 高级调试要想玩的好&#xff0c;看懂汇编是基本功&#xff0c;但看懂汇编和能写点汇编又完全是两回事&#xff0c;所以有时候看的多&#xff0c;总手痒痒想写一点&#xff0c;在 Windows 平台上搭建汇编环境不是那么容易&#xff0c;大多还是…

web课程设计:HTML非遗文化网页设计题材【京剧文化】HTML+CSS+JavaScript

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

提高技术质量标准 | Google Play 持续打造优质平台

作者 / Google Play 统筹产品经理 Lauren Mytton在上一篇文章中&#xff0c;我们为大家总结了 Google Play 在近期将要推出多项新功能&#xff0c;接下来我们将会陆续展开逐一详细说明。应用质量是我们在 Google Play 所做一切努力的基础。Android 用户希望从他们下载的应用和游…