网上资料太多了,按照他们的文章基本上是 不能用,我自己结合他们的方法写了一遍;
不保证代码多么好看,但保证你们按我的 代码 放在项目中可以运行起来,能看到效果;
读入模板: test.docx
java:
package com.example.wordpoi.poi; import org.apache.poi.POIXMLProperties; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.xwpf.extractor.XWPFWordExtractor; import org.apache.poi.xwpf.usermodel.*; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlToken; import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc; import java.io.*; import java.math.BigInteger; import java.util.*; /** * Created By: hdx * Date: 2020-04-09 09:13 */ public class XwpfTest { protected static List<XWPFPictureData> pictures = new ArrayList<XWPFPictureData>(); /** * 通过XWPFWordExtractor访问XWPFDocument的内容 * @throws Exception */ public static void main(String[] args) throws Exception{ // testReadByExtractor(); Map<String, Object> param = new HashMap<String, Object>(); param.put("${apple}", "学院1"); param.put("${data}", "2020-04-09"); param.put("${banana}", "专业1"); Map<String, Object> header = new HashMap<String, Object>(); header.put("width", 100); header.put("height", 50); header.put("type", "png"); header.put("content", "F:\\123.png"); param.put("${aaa}", header); XWPFDocument doc = testReadByDoc2(param); FileOutputStream fopts = new FileOutputStream("F:\\1111\\2.docx"); doc.write(fopts); fopts.close(); //testReadByDoc(); // testSimpleWrite(); // testWriteTable(); } public static XWPFDocument testReadByDoc2(Map<String, Object> param) throws Exception { InputStream is = new FileInputStream("F:\\1111\\test.docx"); XWPFDocument doc = new XWPFDocument(is); try { if (param != null && param.size() > 0) { //处理段落 List<XWPFParagraph> paragraphList = doc.getParagraphs(); processParagraphs(paragraphList, param, doc); //处理表格 Iterator<XWPFTable> it = doc.getTablesIterator(); while (it.hasNext()) { XWPFTable table = it.next(); List<XWPFTableRow> rows = table.getRows(); for (XWPFTableRow row : rows) { List<XWPFTableCell> cells = row.getTableCells(); for (XWPFTableCell cell : cells) { List<XWPFParagraph> paragraphListTable = cell.getParagraphs(); processParagraphs(paragraphListTable, param, doc); } } } } } catch (Exception e) { e.printStackTrace(); } return doc; } /** * 处理段落 * @param paragraphList * @throws FileNotFoundException * @throws InvalidFormatException */ public static void processParagraphs(List<XWPFParagraph> paragraphList,Map<String, Object> param,XWPFDocument doc) throws InvalidFormatException, FileNotFoundException{ if(paragraphList != null && paragraphList.size() > 0){ for(XWPFParagraph paragraph:paragraphList){ List<XWPFRun> runs = paragraph.getRuns(); for (XWPFRun run : runs) { String text = run.getText(0); System.out.println("text=="+text); if(text != null){ boolean isSetText = false; for (Map.Entry<String, Object> entry : param.entrySet()) { String key = entry.getKey(); if(text.indexOf(key) != -1){ isSetText = true; Object value = entry.getValue(); if (value instanceof String) {//文本替换 System.out.println("key=="+key); text = text.replace(key, value.toString()); } else if (value instanceof Map) { //图片替换 text = text.replace(key, ""); Map pic = (Map)value; int width = Integer.parseInt(pic.get("width").toString()); int height = Integer.parseInt(pic.get("height").toString()); int picType = getPictureType(pic.get("type").toString()); String byteArray = (String) pic.get("content"); System.out.println("=="+byteArray); //ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray); //int ind = doc.getAllPictures().size() - 1; //doc.createPicture(ind, width , height,paragraph); CTInline inline = run.getCTR().addNewDrawing().addNewInline(); insertPicture(doc,byteArray,inline, width, height); } } } if(isSetText){ run.setText(text,0); } } } } } } /** * insert Picture * @param document * @param filePath * @param inline * @param width * @param height * @throws InvalidFormatException * @throws FileNotFoundException */ private static void insertPicture(XWPFDocument document, String filePath, CTInline inline, int width, int height) throws InvalidFormatException, FileNotFoundException { document.addPictureData(new FileInputStream(filePath),XWPFDocument.PICTURE_TYPE_PNG); int id = document.getAllPictures().size() - 1; final int EMU = 9525; width *= EMU; height *= EMU; String blipId = document.getAllPictures().get(id).getPackageRelationship().getId(); String picXml = getPicXml(blipId, width, height); XmlToken xmlToken = null; try { xmlToken = XmlToken.Factory.parse(picXml); } catch (XmlException xe) { xe.printStackTrace(); } inline.set(xmlToken); inline.setDistT(0); inline.setDistB(0); inline.setDistL(0); inline.setDistR(0); CTPositiveSize2D extent = inline.addNewExtent(); extent.setCx(width); extent.setCy(height); CTNonVisualDrawingProps docPr = inline.addNewDocPr(); docPr.setId(id); docPr.setName("IMG_" + id); docPr.setDescr("IMG_" + id); } /** * get the xml of the picture * @param blipId * @param width * @param height * @return */ private static String getPicXml(String blipId, int width, int height) { String picXml = "" + "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" + " <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" + " <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" + " <pic:nvPicPr>" + " <pic:cNvPr id=\"" + 0 + "\" name=\"Generated\"/>" + " <pic:cNvPicPr/>" + " </pic:nvPicPr>" + " <pic:blipFill>" + " <a:blip r:embed=\"" + blipId + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" + " <a:stretch>" + " <a:fillRect/>" + " </a:stretch>" + " </pic:blipFill>" + " <pic:spPr>" + " <a:xfrm>" + " <a:off x=\"0\" y=\"0\"/>" + " <a:ext cx=\"" + width + "\" cy=\"" + height + "\"/>" + " </a:xfrm>" + " <a:prstGeom prst=\"rect\">" + " <a:avLst/>" + " </a:prstGeom>" + " </pic:spPr>" + " </pic:pic>" + " </a:graphicData>" + "</a:graphic>"; return picXml; } public static List<XWPFPictureData> getAllPictures() { return Collections.unmodifiableList(pictures); } /** * @param id * @param width 宽 * @param height 高 * @param paragraph 段落 */ public static void createPicture(int id, int width, int height,XWPFParagraph paragraph) { final int EMU = 9525; width *= EMU; height *= EMU; String blipId = getAllPictures().get(id).getPackageRelationship().getId(); CTInline inline = paragraph.createRun().getCTR().addNewDrawing().addNewInline(); System.out.println(blipId+":"+inline); String picXml = "" + "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" + " <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" + " <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" + " <pic:nvPicPr>" + " <pic:cNvPr id=\"" + id + "\" name=\"Generated\"/>" + " <pic:cNvPicPr/>" + " </pic:nvPicPr>" + " <pic:blipFill>" + " <a:blip r:embed=\"" + blipId + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" + " <a:stretch>" + " <a:fillRect/>" + " </a:stretch>" + " </pic:blipFill>" + " <pic:spPr>" + " <a:xfrm>" + " <a:off x=\"0\" y=\"0\"/>" + " <a:ext cx=\"" + width + "\" cy=\"" + height + "\"/>" + " </a:xfrm>" + " <a:prstGeom prst=\"rect\">" + " <a:avLst/>" + " </a:prstGeom>" + " </pic:spPr>" + " </pic:pic>" + " </a:graphicData>" + "</a:graphic>"; inline.addNewGraphic().addNewGraphicData(); XmlToken xmlToken = null; try { xmlToken = XmlToken.Factory.parse(picXml); } catch (XmlException xe) { xe.printStackTrace(); } inline.set(xmlToken); inline.setDistT(0); inline.setDistB(0); inline.setDistL(0); inline.setDistR(0); CTPositiveSize2D extent = inline.addNewExtent(); extent.setCx(width); extent.setCy(height); CTNonVisualDrawingProps docPr = inline.addNewDocPr(); docPr.setId(id); docPr.setName("图片" + id); docPr.setDescr("测试"); } /** * 根据图片类型,取得对应的图片类型代码 * @param picType * @return int */ private static int getPictureType(String picType){ int res = XWPFDocument.PICTURE_TYPE_PICT; if(picType != null){ if(picType.equalsIgnoreCase("png")){ res = XWPFDocument.PICTURE_TYPE_PNG; }else if(picType.equalsIgnoreCase("dib")){ res = XWPFDocument.PICTURE_TYPE_DIB; }else if(picType.equalsIgnoreCase("emf")){ res = XWPFDocument.PICTURE_TYPE_EMF; }else if(picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")){ res = XWPFDocument.PICTURE_TYPE_JPEG; }else if(picType.equalsIgnoreCase("wmf")){ res = XWPFDocument.PICTURE_TYPE_WMF; } } return res; } /** * 匹配传入信息集合与模板 * @param value 模板需要替换的区域 * @param textMap 传入信息集合 * @return 模板需要替换区域信息集合对应值 */ public static Object changeValue(String value, Map<String, Object> textMap){ Set<Map.Entry<String, Object>> textSets = textMap.entrySet(); Object valu = ""; for (Map.Entry<String, Object> textSet : textSets) { //匹配模板与替换值 格式${key} String key = textSet.getKey(); if(value.indexOf(key)!= -1){ valu = textSet.getValue(); } } return valu; } /** * 判断文本中时候包含$ * @param text 文本 * @return 包含返回true,不包含返回false */ public static boolean checkText(String text){ boolean check = false; if(text.indexOf("$")!= -1){ check = true; } return check; } // 读取文件 public static void testReadByExtractor() throws Exception { InputStream is = new FileInputStream("F:\\1111\\test.docx"); XWPFDocument doc = new XWPFDocument(is); XWPFWordExtractor extractor = new XWPFWordExtractor(doc); String text = extractor.getText(); System.out.println(text); POIXMLProperties.CoreProperties coreProps = extractor.getCoreProperties(); printCoreProperties1(coreProps); close1(is); } /** * 输出CoreProperties信息 * @param coreProps */ private static void printCoreProperties1(POIXMLProperties.CoreProperties coreProps) { System.out.println(coreProps.getCategory()); //分类 System.out.println(coreProps.getCreator()); //创建者 System.out.println(coreProps.getCreated()); //创建时间 System.out.println(coreProps.getTitle()); //标题 } /** * 关闭输入流 * @param is */ private static void close1(InputStream is) { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 通过XWPFDocument对内容进行访问。对于XWPF文档而言,用这种方式进行读操作更佳。 * @throws Exception */ public static void testReadByDoc() throws Exception { InputStream is = new FileInputStream("F:\\1111\\test.docx"); XWPFDocument doc = new XWPFDocument(is); List<XWPFParagraph> paras = doc.getParagraphs(); for (XWPFParagraph para : paras) { //当前段落的属性 // CTPPr pr = para.getCTP().getPPr(); System.out.println(para.getText()); } //获取文档中所有的表格 List<XWPFTable> tables = doc.getTables(); List<XWPFTableRow> rows; List<XWPFTableCell> cells; for (XWPFTable table : tables) { //表格属性 // CTTblPr pr = table.getCTTbl().getTblPr(); //获取表格对应的行 rows = table.getRows(); for (XWPFTableRow row : rows) { //获取行对应的单元格 cells = row.getTableCells(); for (XWPFTableCell cell : cells) { System.out.println(cell.getText()); } } } close1(is); } /** * 基本的写操作 * @throws Exception */ public static void testSimpleWrite() throws Exception { //新建一个文档 XWPFDocument doc = new XWPFDocument(); //创建一个段落 XWPFParagraph para = doc.createParagraph(); //一个XWPFRun代表具有相同属性的一个区域。 XWPFRun run = para.createRun(); run.setBold(true); //加粗 run.setText("加粗的内容"); run = para.createRun(); run.setColor("FF0000"); run.setText("红色的字。"); OutputStream os = new FileOutputStream("F:\\1111\\simpleWrite.docx"); //把doc输出到输出流 doc.write(os); close(os); } /*** * 写一个表格 * @throws Exception */ public static void testWriteTable() throws Exception { XWPFDocument doc = new XWPFDocument(); //创建一个5行5列的表格 XWPFTable table = doc.createTable(5, 5); //这里增加的列原本初始化创建的那5行在通过getTableCells()方法获取时获取不到,但通过row新增的就可以。 // table.addNewCol(); //给表格增加一列,变成6列 table.createRow(); //给表格新增一行,变成6行 List<XWPFTableRow> rows = table.getRows(); //表格属性 CTTblPr tablePr = table.getCTTbl().addNewTblPr(); //表格宽度 CTTblWidth width = tablePr.addNewTblW(); width.setW(BigInteger.valueOf(8000)); XWPFTableRow row; List<XWPFTableCell> cells; XWPFTableCell cell; int rowSize = rows.size(); int cellSize; for (int i=0; i<rowSize; i++) { row = rows.get(i); //新增单元格 row.addNewTableCell(); //设置行的高度 row.setHeight(500); //行属性 // CTTrPr rowPr = row.getCtRow().addNewTrPr(); //这种方式是可以获取到新增的cell的。 // List<CTTc> list = row.getCtRow().getTcList(); cells = row.getTableCells(); cellSize = cells.size(); for (int j=0; j<cellSize; j++) { cell = cells.get(j); if ((i+j)%2==0) { //设置单元格的颜色 cell.setColor("ff0000"); //红色 } else { cell.setColor("0000ff"); //蓝色 } //单元格属性 CTTcPr cellPr = cell.getCTTc().addNewTcPr(); cellPr.addNewVAlign().setVal(STVerticalJc.CENTER); if (j == 3) { //设置宽度 cellPr.addNewTcW().setW(BigInteger.valueOf(3000)); } cell.setText(i + ", " + j); } } //文件不存在时会自动创建 OutputStream os = new FileOutputStream("F:\\1111\\table.docx"); //写入文件 doc.write(os); close(os); } /** * 关闭输出流 * @param os */ private static void close(OutputStream os) { if (os != null) { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } }
pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>wordpoi</artifactId> <version>0.0.1-SNAPSHOT</version> <name>wordpoi</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <!--<repositories>--> <!--<repository>--> <!--<id>com.e-iceblue</id>--> <!--<name>e-iceblue</name>--> <!--<url>http://repo.e-iceblue.com/nexus/content/groups/public/</url>--> <!--</repository>--> <!--</repositories>--> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <!--<dependency>--> <!--<groupId>org.apache.poi</groupId>--> <!--<artifactId>poi-ooxml</artifactId>--> <!--<version>3.14</version>--> <!--</dependency>--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-excelant</artifactId> <version>3.14</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-examples</artifactId> <version>4.0.0</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>3.10-FINAL</version> </dependency> <!--<dependency>--> <!--<groupId>org.apache.poi</groupId>--> <!--<artifactId>poi-ooxml</artifactId>--> <!--<version>4.0.0</version>--> <!--</dependency>--> <!--<!–Apache poi 在word中的表格中插入表格,图片等操作 开始–>--> <!--<dependency>--> <!--<groupId>org.apache.poi</groupId>--> <!--<artifactId>poi</artifactId>--> <!--<version>4.0.0</version>--> <!--</dependency>--> <!--<dependency>--> <!--<groupId>org.apache.poi</groupId>--> <!--<artifactId>poi</artifactId>--> <!--<version>3.11</version>--> <!--</dependency>--> <!--<dependency>--> <!--<groupId>org.apache.poi</groupId>--> <!--<artifactId>poi-ooxml</artifactId>--> <!--<version>3.9</version>--> <!--</dependency>--> <!--<dependency>--> <!--<groupId>org.apache.xmlbeans</groupId>--> <!--<artifactId>xmlbeans</artifactId>--> <!--<version>3.1.0</version>--> <!--</dependency>--> <dependency> <groupId>com.deepoove</groupId> <artifactId>poi-tl</artifactId> <version>1.6.0-beta1</version> </dependency> <!--结束--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>3.9</version> </dependency> <!--<dependency>--> <!--<groupId>org.apache.poi</groupId>--> <!--<artifactId>poi-ooxml</artifactId>--> <!--<version>3.7</version>--> <!--</dependency>--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.9</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.9</version> </dependency> <dependency> <groupId>org.apache.xmlbeans</groupId> <artifactId>xmlbeans</artifactId> <version>2.3.0</version> </dependency> <!--<dependency>--> <!--<groupId>org.apache.xmlbeans</groupId>--> <!--<artifactId>xmlbeans</artifactId>--> <!--<version>2.6.0</version>--> <!--</dependency>--> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-commons</artifactId> <version>RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.4</version> </dependency> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.9.4</version> </dependency> <dependency> <groupId>jacob</groupId> <artifactId>jacob</artifactId> <scope>system</scope> <systemPath>${basedir}/lib/jacob.jar</systemPath> </dependency> <dependency> <groupId>ooxml-schemas</groupId> <artifactId>ooxml-schemas</artifactId> <scope>system</scope> <systemPath>${basedir}/lib/ooxml-schemas-1.1.jar</systemPath> </dependency> <dependency> <groupId>spire.doc.free-2.7.3</groupId> <artifactId>spire.doc.free-2.7.3</artifactId> <scope>system</scope> <systemPath>${basedir}/lib/spire.doc.free-2.7.3.jar</systemPath> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.9</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
输出效果:
代码中这三个方法也可以运行 testReadByDoc(); testSimpleWrite(); testWriteTable();