1秒鐘實(shí)現(xiàn)Springboot?替換/寫入?word文檔里面的文字、圖片功能
前言
圖片加水印:
Springboot 圖片需要添加水印,怎么辦? 1秒就實(shí)現(xiàn)
那么word文檔替換文字、插入圖片,當(dāng)然也是1秒鐘了(jar包引入,工具類代碼復(fù)制粘貼,調(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表示生成的文字是要從哪一個(gè)地方開始放置,設(shè)置文字從位置0開始 * 就可以把原來(lái)的文字全部替換掉了 */ 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>", "認(rèn)可"); map.put("<phone>", "136919xxxxx"); map.put("<地址>", "中國(guó)廣東省深圳市"); String srcPath = "D:\\test.docx"; String destPath = "D:\\mytestNew.docx"; searchAndReplace(srcPath, destPath, map); System.out.println("操作完畢"); } }
③ 調(diào)試
準(zhǔn)備一個(gè)簡(jiǎn)單的word內(nèi)容文檔, 假裝這就是我們業(yè)務(wù)需求使用的模板內(nèi)容:
可以看到 我這個(gè)模板內(nèi)容里面,有三個(gè)類似站位符的內(nèi)容(紅色標(biāo)識(shí))
然后對(duì)照看下怎么用這個(gè)工具類,傳參來(lái)替換這個(gè)模板內(nèi)容的文字:
public static void main(String[] args) { Map<String, String> map = new HashMap<>(); map.put("<v1>", "認(rèn)可"); map.put("<phone>", "136919xxxxx"); map.put("<地址>", "中國(guó)廣東省深圳市"); String srcPath = "D:\\test.docx"; String destPath = "D:\\mytestNew.docx"; searchAndReplace(srcPath, destPath, map); System.out.println("操作完畢"); }
代碼簡(jiǎn)析:
運(yùn)行方法,看看效果:
效果:
好了文字替換玩了一下,接下來(lái)玩下插入圖片:
先準(zhǔn)備一張 ‘公章’圖片:
然后在模板文檔里面, 需要蓋章的地方 ,設(shè)置一個(gè)占位標(biāo)識(shí) :
然后加下插入圖片的函數(shù)代碼:
/** * <b> Word中添加圖章 * </b><br><br><i>Description</i> : * String srcPath, 源Word路徑 * String storePath, 添加圖章后的路徑 * String sealPath, 圖章路徑(即圖片) * tString abText, 在Word中蓋圖章的標(biāo)識(shí)字符串,如:(簽字/蓋章) * 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);//設(shè)置圖片路徑 if (width <= 0) { width = 100; } if (height <= 0) { height = 100; } //創(chuàng)建Random類對(duì)象 Random random = new Random(); //產(chǎn)生隨機(jī)數(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 設(shè)置浮動(dòng)屬性 刪除inline屬性 CTAnchor anchor = getAnchorWithGraphic(graphicalobject, "Seal" + number, Units.toEMU(width), Units.toEMU(height),//圖片大小 Units.toEMU(leftOffset), Units.toEMU(topOffset), behind);//相對(duì)當(dāng)前段落位置 需要計(jì)算段落已有內(nèi)容的左偏移 drawing.setAnchorArray(new CTAnchor[]{anchor});//添加浮動(dòng)屬性 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); }
代碼簡(jiǎn)析:
運(yùn)行一下,打開新文件看看效果:
好了,該篇就到這吧。
到此這篇關(guān)于Springboot 替換/寫入 word文檔里面的文字、圖片,1秒鐘實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Springboot 替換word文檔文字內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之哈希算法實(shí)現(xiàn)
哈希表本質(zhì)是一種(key,value)結(jié)構(gòu),由此我們可以聯(lián)想到,能不能把哈希表的key映射成數(shù)組的索引index呢?如果這樣做的話那么查詢相當(dāng)于直接查詢索引,查詢時(shí)間復(fù)雜度為O(1),其實(shí)這也正是當(dāng)key為int型時(shí)的做法,將key通過某種做法映射成index,從而轉(zhuǎn)換成數(shù)組結(jié)構(gòu)2022-02-02java中volatile關(guān)鍵字的作用與實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于java中volatile關(guān)鍵字的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04詳談Java編程之委托代理回調(diào)、內(nèi)部類以及匿名內(nèi)部類回調(diào)(閉包回調(diào))
下面小編就為大家?guī)?lái)一篇詳談Java編程之委托代理回調(diào)、內(nèi)部類以及匿名內(nèi)部類回調(diào)(閉包回調(diào))。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2017-05-05Java?MyBatis傳出參數(shù)resultType和resultMap解讀
這篇文章主要介紹了Java?MyBatis傳出參數(shù)resultType和resultMap解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12SpringBoot根據(jù)目錄結(jié)構(gòu)自動(dòng)生成路由前綴的實(shí)現(xiàn)代碼
本文介紹如何根據(jù)目錄結(jié)構(gòu)給RequestMapping添加路由前綴,具體實(shí)現(xiàn)方法,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-08-08Logback配置文件這么寫,還說你不會(huì)整理日志?
logback框架會(huì)默認(rèn)加載classpath下命名為logback-spring.xml或logback.xml的配置文件。這篇文章主要介紹了Logback配置文件寫法,需要的朋友可以參考下2020-07-07