1.引入docx4j
使用maven仓库引入jar包
```java
org.docx4j
docx4j
6.1.2
```
2.docx4j配置
可以不添加配置文件,但debug日志会提示找不到docx4j配置文件
在src下创建docx4j.properties配置文件,maven项目请放在resources文件夹下
```java
# Page size: use a value from org.docx4j.model.structure.PageSizePaper enum
# eg A4, LETTER
docx4j.PageSize=LETTER
# Page size: use a value from org.docx4j.model.structure.MarginsWellKnown enum
docx4j.PageMargins=NORMAL
docx4j.PageOrientationLandscape=false
# Page size: use a value from org.pptx4j.model.SlideSizesWellKnown enum
# eg A4, LETTER
pptx4j.PageSize=LETTER
pptx4j.PageOrientationLandscape=false
# These will be injected into docProps/app.xml
# if App.Write=true
docx4j.App.write=true
docx4j.Application=docx4j
docx4j.AppVersion=6.1.2
# of the form XX.YYYY where X and Y represent numerical values
# These will be injected into docProps/core.xml
docx4j.dc.write=true
docx4j.dc.creator.value=docx4j
docx4j.dc.lastModifiedBy.value=docx4j
#
#docx4j.McPreprocessor=true
# If you haven't configured log4j yourself
# docx4j will autoconfigure it. Set this to true to disable that
docx4j.Log4j.Configurator.disabled=false
```
3.构建WordProcessingMlPackage对象
docx格式文档可以理解为一个压缩包,若将其解压可看到一个类似前端的工程项目,其中document.xml用于全文的配置,详细解说请自行查阅资料
WordprocessingMLPackage是操作word文档包对象;
创建新的word文档
```java
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
/**
* 构建新word文件
*/
public static WordprocessingMLPackage build() throws Exception{
return WordprocessingMLPackage.createPackage();
}
加载存在的word文档
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
/**
* 读取存在的word文件
* @param wordFilePath word文件路径
*/
public static WordprocessingMLPackage load(String wordFilePath) throws Exception{
return WordprocessingMLPackage.load(new File(wordFilePath));
}
```
4.获取书签
书签:CTBookmark对象
```java
import org.docx4j.TraversalUtil;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.finders.RangeFinder;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import .apache.poi.util.IOUtils;
import org.docx4j.wml.*;
public static void main(String[] args) throws Exception {
String wordFilePath = "";
WordprocessingMLPackage wordMLPackage = load(wordFilePath);
// 提取正文
MainDocumentPart main = wordMLPackage.getMainDocumentPart();
Document doc = main.getContents();
Body body = doc.getBody();
// 获取段落
List paragraphs = body.getContent();
// 提取书签并获取书签的游标
RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
new TraversalUtil(paragraphs, rt);
// 遍历书签
for (CTBookmark bm : rt.getStarts()) {
System.out.println("name:"+bm.getName());
}
}
```
5.在书签位置加入图片
```java
import org.docx4j.TraversalUtil;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.finders.RangeFinder;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import .apache.poi.util.IOUtils;
import org.docx4j.wml.*;
public static void addImage(WordprocessingMLPackage wPackage,CTBookmark bm) throws Exception{
P p = (P) (bm.getParent());
ObjectFactory factory = Context.getWmlObjectFactory();
R run = factory.createR();
// 读入图片并转化为字节数组,因为docx4j只能字节数组的方式插入图片
// byte[] bytes = IOUtils.toByteArray(new FileInputStream("图片路径"));
byte[] bytes = getFileBytes("图片路径");
// 开始创建一个行内图片
BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wPackage, bytes);
// 最后一个是限制图片的宽度,缩放的依据
Inline inline = imagePart.createImageInline(null, null, 0, 1, false, 0);
// 构建绘图
Drawing drawing = factory.createDrawing();
// 加入图片段落
drawing.getAnchorOrInline().add(inline);
run.getContent().add(drawing);
// 清理书签所在数据
// p.getContent().clear();
// 加入图片信息
p.getContent().add(run);
}
public static byte[] getFileBytes(String filePath) throws Exception{
File file = new File(filePath);
if(!file.exists()){
throw new Exception("文件不存在!");
}
byte[] data = null;
try(FileInputStream fis = new FileInputStream(file);ByteArrayOutputStream baos = new ByteArrayOutputStream()){
int len;
byte[] buffer = new byte[1024];
while ((len = fis.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
data = baos.toByteArray();
}
return data;
}
```
6.保存文件
必须调用保存,否则更改无效
// 保存
// 方式一
```java
wordMLPackage.save(new File(wordFilePath));
```
// 方式二
```java
Docx4J.save(wordMLPackage, new File(wordFilePath));
```
7.完整代码
```java
import org.docx4j.TraversalUtil;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.finders.RangeFinder;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import .apache.poi.util.IOUtils;
import org.docx4j.wml.*;
import javax.xml.bind.JAXBElement;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class WordTest {
public static void main(String[] args) throws Exception {
String wordFilePath = "word文档路径";
WordprocessingMLPackage wordMLPackage = load(wordFilePath);
// 提取正文
MainDocumentPart main = wordMLPackage.getMainDocumentPart();
Document doc = main.getContents();
Body body = doc.getBody();
// 获取段落
List paragraphs = body.getContent();
// 提取书签并获取书签的游标
RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
new TraversalUtil(paragraphs, rt);
// 遍历书签
for (CTBookmark bm : rt.getStarts()) {
System.out.println("name:"+bm.getName());
// 替换image
if ("sign".equals(bm.getName())){
addImage(wordMLPackage, bm);
break;
}
}
save(wordMLPackage,wordFilePath);
}
public static void addImage(WordprocessingMLPackage wPackage,CTBookmark bm) throws Exception{
P p = (P) (bm.getParent());
ObjectFactory factory = Context.getWmlObjectFactory();
R run = factory.createR();
// 读入图片并转化为字节数组,因为docx4j只能字节数组的方式插入图片
// byte[] bytes = IOUtils.toByteArray(new FileInputStream("图片文件路径"));
byte[] bytes = getFileBytes("图片文件路径");
// 开始创建一个行内图片
BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wPackage, bytes);
// 最后一个是限制图片的宽度,缩放的依据
Inline inline = imagePart.createImageInline(null, null, 0, 1, false, 0);
// 构建绘图
Drawing drawing = factory.createDrawing();
// 加入图片段落
drawing.getAnchorOrInline().add(inline);
run.getContent().add(drawing);
// 清理书签所在数据
// p.getContent().clear();
// 加入图片信息
p.getContent().add(run);
}
/**
* 构建文件
*/
public static WordprocessingMLPackage build() throws Exception{
return WordprocessingMLPackage.createPackage();
}
/**
* 读取存在的word文件
* @param wordFilePath word文件路径
*/
public static WordprocessingMLPackage load(String wordFilePath) throws Exception{
return WordprocessingMLPackage.load(new File(wordFilePath));
}
/**
* 保存
* @param wordMLPackage word
*/
public static void save(WordprocessingMLPackage wordMLPackage,String wordFilePath) throws Exception{
wordMLPackage.save(new File(wordFilePath));
}
public static byte[] getFileBytes(String filePath) throws Exception{
File file = new File(filePath);
if(!file.exists()){
throw new Exception("文件不存在!");
}
byte[] data = null;
try(FileInputStream fis = new FileInputStream(file);ByteArrayOutputStream baos = new ByteArrayOutputStream()){
int len;
byte[] buffer = new byte[1024];
while ((len = fis.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
data = baos.toByteArray();
}
return data;
}
}
```