1秒鐘實現(xiàn)Springboot?替換/寫入?word文檔里面的文字、圖片功能
前言

圖片加水?。?br />Springboot 圖片需要添加水印,怎么辦? 1秒就實現(xiàn)
那么word文檔替換文字、插入圖片,當然也是1秒鐘了(jar包引入,工具類代碼復制粘貼,調(diào)試,完事)。
事不宜遲,開始敲代碼。
正文
本篇內(nèi)容:
1.word文檔 替換內(nèi)容里面的文字 (模板占位符方式傳參替換)
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))
{
/**
* 參數(shù)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("操作完畢");
}
}
③ 調(diào)試
準備一個簡單的word內(nèi)容文檔, 假裝這就是我們業(yè)務需求使用的模板內(nèi)容:
可以看到 我這個模板內(nèi)容里面,有三個類似站位符的內(nèi)容(紅色標識)

然后對照看下怎么用這個工具類,傳參來替換這個模板內(nèi)容的文字:
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("操作完畢");
}代碼簡析:

運行方法,看看效果:

效果:

好了文字替換玩了一下,接下來玩下插入圖片:
先準備一張 ‘公章’圖片:

然后在模板文檔里面, 需要蓋章的地方 ,設置一個占位標識 :

然后加下插入圖片的函數(shù)代碼:
/**
* <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;
}
//創(chuàng)建Random類對象
Random random = new Random();
//產(chǎn)生隨機數(shù)
int number = random.nextInt(999) + 1;
targetRun.addPicture(in, Document.PICTURE_TYPE_PNG, "Seal" + number, Units.toEMU(width), Units.toEMU(height));
in.close();
// 2. 獲取到圖片數(shù)據(jù)
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);//相對當前段落位置 需要計算段落已有內(nèi)容的左偏移
drawing.setAnchorArray(new CTAnchor[]{anchor});//添加浮動屬性
drawing.removeInline(0);//刪除行內(nèi)屬性
}
document.write(new FileOutputStream(storePath));
document.close();
}
/**
* @param ctGraphicalObject 圖片數(shù)據(jù)
* @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;
}
調(diào)用一下函數(shù)玩下:
public static void main(String[] args) throws Exception {
sealInWord("D:\\mytestNew.docx",
"D:\\mytestWithImg.docx",
"D:\\gz.png", "(印章)", 0, 0,
310, 110, false);
}
代碼簡析:

運行一下,打開新文件看看效果:

好了,該篇就到這吧。
到此這篇關(guān)于Springboot 替換/寫入 word文檔里面的文字、圖片,1秒鐘實現(xiàn)的文章就介紹到這了,更多相關(guān)Springboot 替換word文檔文字內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之哈希算法實現(xiàn)
哈希表本質(zhì)是一種(key,value)結(jié)構(gòu),由此我們可以聯(lián)想到,能不能把哈希表的key映射成數(shù)組的索引index呢?如果這樣做的話那么查詢相當于直接查詢索引,查詢時間復雜度為O(1),其實這也正是當key為int型時的做法,將key通過某種做法映射成index,從而轉(zhuǎn)換成數(shù)組結(jié)構(gòu)2022-02-02
java中volatile關(guān)鍵字的作用與實例代碼
這篇文章主要給大家介紹了關(guān)于java中volatile關(guān)鍵字的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-04-04
詳談Java編程之委托代理回調(diào)、內(nèi)部類以及匿名內(nèi)部類回調(diào)(閉包回調(diào))
下面小編就為大家?guī)硪黄斦凧ava編程之委托代理回調(diào)、內(nèi)部類以及匿名內(nèi)部類回調(diào)(閉包回調(diào))。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05
Java?MyBatis傳出參數(shù)resultType和resultMap解讀
這篇文章主要介紹了Java?MyBatis傳出參數(shù)resultType和resultMap解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12
SpringBoot根據(jù)目錄結(jié)構(gòu)自動生成路由前綴的實現(xiàn)代碼
本文介紹如何根據(jù)目錄結(jié)構(gòu)給RequestMapping添加路由前綴,具體實現(xiàn)方法,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2021-08-08

