注意事项
word需.docx格式,.doc格式不适用此方案。
书签
书签是word里的一种标记元素,poi能很好的读出标签并进行文字替换、图片替换等。此方案利用书签进行操作,同时也更推荐用书签进行word操作,而不是使用${name}等语法进行替换。
准备工作
书签概念
书签只有一种,但书签可以指定空白区域,也可以指定一段文字,同样可以指定图片等,书签用于标记位置。
差别为,如书签未选择文字,则向书签输入文字时,文字会插入到光标位置。如书签选择了文字,则向书签输入文字时,文字会替换光标所选择的文字。(注意:书签不要放在空行,即如果想在文档末尾追加数据,请写打一个空格,再用书签标记该空格)。
插入书签
点击菜单栏->插入->书签->输入书签名->添加即可。此office版本为2019,其他版本请自行研究如何插入书签。插入书签后保存文件即可。
代码
maven依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.0.0</version>
</dependency>
书签替换文字
public static void refreshBooks(XWPFDocument doc, Map<String, String> dataMap) {
List<XWPFParagraph> paragraphs = doc.getParagraphs();
for (XWPFParagraph xwpfParagraph : paragraphs) {
CTP ctp = xwpfParagraph.getCTP();
for (int dwI = 0; dwI < ctp.sizeOfBookmarkStartArray(); dwI++) {
CTBookmark bookmark = ctp.getBookmarkStartArray(dwI);
String data = dataMap.get(bookmark.getName());
if (data != null) {
XWPFRun run = xwpfParagraph.createRun();
run.setText(data);
Node firstNode = bookmark.getDomNode();
Node nextNode = firstNode.getNextSibling();
while (nextNode != null) {
String nodeName = nextNode.getNodeName();
if (nodeName.equals(BOOKMARK_END_TAG)) {
break;
}
Node delNode = nextNode;
nextNode = nextNode.getNextSibling();
ctp.getDomNode().removeChild(delNode);
}
if (nextNode == null) {
ctp.getDomNode().insertBefore(run.getCTR().getDomNode(), firstNode);
} else {
ctp.getDomNode().insertBefore(run.getCTR().getDomNode(), nextNode);
}
}
}
}
}
演示代码
public static void main(String[] args) {
try {
FileInputStream is = new FileInputStream("e:/test.docx");
XWPFDocument doc = new XWPFDocument(is);
Map<String,String> dataMap = new HashMap<>();
dataMap.put("name","大白");
DocUtil.refreshBooks(doc,dataMap);
doc.write(new FileOutputStream("e:/test01.docx"));
}catch (Exception e){
e.printStackTrace();
}
}
书签替换图片
替换图片和替换文字原理一致,均是搜索到书签,对书签进行操作。
public static void refreshBooks(XWPFDocument doc, Map<String, InputStream> dataMap) throws IOException, InvalidFormatException {
List<XWPFParagraph> paragraphs = doc.getParagraphs();
for (XWPFParagraph xwpfParagraph : paragraphs) {
CTP ctp = xwpfParagraph.getCTP();
for (int dwI = 0; dwI < ctp.sizeOfBookmarkStartArray(); dwI++) {
CTBookmark bookmark = ctp.getBookmarkStartArray(dwI);
InputStream picIs = dataMap.get(bookmark.getName());
if(picIs != null){
XWPFRun run = xwpfParagraph.createRun();
//bus.png为鼠标在word里选择图片时,图片显示的名字,400,400则为像素单元,根据实际需要的大小进行调整即可。
run.addPicture(picIs,XWPFDocument.PICTURE_TYPE_PNG,"bus.png,", Units.toEMU(400), Units.toEMU(400));
}
}
}
}
演示代码
public static void main(String[] args) {
try {
FileInputStream is = new FileInputStream("e:/test.docx");
XWPFDocument doc = new XWPFDocument(is);
Map<String,InputStream> dataMap = new HashMap<>();
dataMap.put("name",new FileInputStream("e:/test.png"));
DocUtil.refreshBooks(doc,dataMap);
doc.write(new FileOutputStream("e:/test01.docx"));
}catch (Exception e){
e.printStackTrace();
}
}
友情提示:图片最好使用替换模式,即原先的在原先的图片上设置书签,而不是在空白处设置书签,这样可以很好的保证图片替换后的显示效果。