1秒钟实现Springboot 替换/写入 word文档里面的文字、图片功能
作者:小目标青年 发布时间:2022-05-08 18:35:48
标签:Springboot,替换,word,文档
前言
图片加水印:
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);
}
代码简析:
运行一下,打开新文件看看效果:
来源:https://blog.csdn.net/qq_35387940/article/details/128235341
0
投稿
猜你喜欢
- 包括系统钩子和线程钩子,或者叫全局钩子和私有钩子。系统钩子需要一个单独的DLL,这个地方耽误了不少时间,网上有说可以不用单独DLL的。 现在
- 由于公司平台访问人数逐渐增多,公司项目的数据库已经几次出现宕机现象。为减轻数据库压力,我上个月对公司项目做了下调整。把新闻板块提取出来单独一
- 一、JDK中常见的异常情况1、常见异常总结图2、java中异常分类Throwable类有两个直接子类:(1)Exception:出现的问题是
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&
- 用途项目中使用了 dubbo,注册中心使用的 zookeeper,使用 zookeeper 实现了一个简单的分布式锁(依赖 curator)
- feign对象传参和普通传参及遇到的坑对象传参使用@RequestBody来指定传参对象@RequestMapping(value = &q
- springboot远程debug调试1.首先去编辑器打开项目2.打开Edit Configurations 选择remote选项
- Java 线程池原理Executor框架的两级调度模型在HotSpot VM的模型中,Java线程被一对一映射为本地操作系统线程。JAVA线
- 什么是线程池线程池(thread pool)是一种线程使用模式。线程过多或者频繁创建和销毁线程会带来调度开销,进而影响缓存局部性和整体性能。
- 有时候数据库文档需要整理,可是只能手动的复制粘贴,心中一万只草泥马奔腾而过。。。screw简洁好用的数据库表结构文档生成工具。1. 创建项目
- 此篇文章是我一个小白对委托的理解和总结,请高手多多评判指教。委托就是一种后期绑定机制,说的直白点就是在调用的时候才去传递业务逻辑的一种算法。
- 1.ACSII码加密//ACSII码加密 private static string
- 在C#的List集合操作中,有时候需要查找到List集合中的最大值,此时可以使用List集合的扩展方法Max方法,Max方法有2种形式,一种
- instanceof判断某个对象是否是某个类的实例或者某个类的子类的实例。它的判断方式大概是这样的:public<T> bool
- 1.概述在平时的开发中,有一些Jar包因为种种原因,在Maven的中央仓库中没有收录,所以就要使用本地引入的方式加入进来。2. 拷贝至项目根
- 使用ProcessBuilder踩到的坑最近使用ProcessBuilder执行命令,命令内容正确,但始终报错命令实行失败,是因为不熟悉Pr
- 首先,通过代码定义一个委托和下面三个示例将要调用的方法:public delegate int AddHandler(int a,int b
- 一、SpringBoot中的main方法注入service在springboot中使用main方法常规无法注入service,因为以后也可能
- 实现的功能1.导入非xls和xlsx格式的文件2.导入空数据的excel文件3.数据缺失4.导入的excel文件中有重复的数据5.导入的ex
- 本文实例讲述了java数据结构与算法之noDups去除重复项算法。分享给大家供大家参考,具体如下:public static void no