Java使用POI根据模板导出Word
0
最近从新写了一下根据Word模板导出Word。
注意:
Word只包含表格和段落,不使用表格布局。
图片样式也保留,但是预先需要知道图片的资源ID。
删除多余模块时,有顶部对不齐的问题。
可能还存在其他细节问题。
首先模板样式:
下面是导出来的Word:
下面贴上代码:
package com.acgist.word;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRelation;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.xmlbeans.XmlCursor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPicture;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
public class WordUtils {
private WordData wordData = null;
private XWPFDocument document = null;
private static final String TEXT_PATH = "declare namespace w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"; $this//w:t";
private Map<String, XWPFParagraph> xwpfParagraphs = new HashMap<String, XWPFParagraph>(); // 多项
private static final String[] BASE_TAGS = {"${age}", "${job}", "${name}", "${email}", "${mobile}", "${address}"};
private static final String NEW_LINE = "\\\\r\\\\n|\\\\n|\\\\r|\\r\\n|\\n|\\r";
private static final String TAG_REGEX = "\\$\\{[a-z_]+\\}"; // 标签正则表达式
public static void main(String[] args) {
WordUtils utils = new WordUtils();
utils.build("e:/company/word/JM0001.docx");
// utils.build("e:/company/word/JM0001YA.docx");
WordData wordData = new WordData();
wordData.setAge("23岁");
wordData.setJob("工作");
wordData.setName("喻胜");
wordData.setAddress("广东广州");
wordData.setMobile("13888888888");
wordData.setEmail("8888@qq.com");
wordData.setHead("e:/company/word/sign.png");
Map<String, String> item = new TreeMap<String, String>();
item.put("技能证书", "北大、擎华");
item.put("兴趣爱好", "动漫、游戏动漫、游戏动漫、游戏动漫、游戏动漫\r\n、游戏动漫、游戏动漫、游戏动漫、游戏动漫、游戏动漫、游戏动漫、游戏动漫、游戏动漫、游戏动漫、游戏");
Map<String, List<WordDataItem>> items = new TreeMap<String, List<WordDataItem>>();
List<WordDataItem> lista = new ArrayList<WordDataItem>();
lista.add(new WordDataItem("2012-2012", "五百丁", "程序员", "zheshishiyigeceshi"));
lista.add(new WordDataItem("2013-2013", "百度", "程序员", "zheshishiyigeceshi"));
items.put("教育背景", lista);
wordData.setHeadId("rId8");
wordData.sorts.add("教育背景");
wordData.sorts.add("技能证书");
wordData.sorts.add("兴趣爱好");
// List<WordDataItem> listb = new ArrayList<WordDataItem>();
// listb.add(new WordDataItem("123", "北大", "北大"));
// listb.add(new WordDataItem("123", "北大", "北大"));
// items.put("工作经历", listb);
wordData.setItems(items);
wordData.setItem(item);
utils.write("e:/company/word/t.docx", wordData);
}
/**
* 多项信息分栏
*/
public enum Items_col_type {
all_in_one, // 全部在一行
time_post_in_one,
unit_post_in_one,
time_unit_in_one,
all_aplit // 全部分开
}
private Items_col_type items_col_type;
private static final String TAG_AGE = "${age}";
private static final String TAG_JOB = "${job}";
private static final String TAG_NAME = "${name}";
private static final String TAG_EMAIL = "${email}";
private static final String TAG_MOBILE = "${mobile}";
private static final String TAG_ADDRESS = "${address}";
private static final String TAG_ITEM_TITLE = "${item_title}";
private static final String TAG_ITEM_CONTENT = "${item_content}";
private static final String TAG_ITEMS_TIME = "${items_time}";
private static final String TAG_ITEMS_UNIT = "${items_unit}";
private static final String TAG_ITEMS_POST = "${items_post}";
private static final String TAG_ITEMS_TITLE = "${items_title}";
private static final String TAG_ITEMS_CONTENT = "${items_content}";
/**
* 处理2007+的WORD
* @param filePath 文件地址
* @return word内容
* @throws IOException
*/
public void build(String filePath) {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(new File(filePath));
document = new XWPFDocument(inputStream);
XWPFParagraph xwpfParagraph = null;
Iterator<XWPFParagraph> iterator = document.getParagraphs().iterator();
while(iterator.hasNext()) {
xwpfParagraph = iterator.next();
if(xwpfParagraph != null) {
String tagName = "";
String tagNameTemp = null;
for(XWPFRun xwpfRun : xwpfParagraph.getRuns()) {
tagNameTemp = xwpfRun.getCTR().newCursor().getTextValue();
if(StringUtils.isNotEmpty(tagNameTemp)) {
tagName += tagNameTemp;
setXwpfParagraphs(tagNameTemp, xwpfParagraph);
}
}
if(StringUtils.isNotEmpty(tagName))
setXwpfParagraphs(tagName.trim(), xwpfParagraph);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(inputStream);
}
if(xwpfParagraphs.get(TAG_ITEMS_TIME) == xwpfParagraphs.get(TAG_ITEMS_UNIT) && xwpfParagraphs.get(TAG_ITEMS_UNIT) == xwpfParagraphs.get(TAG_ITEMS_POST))
items_col_type = Items_col_type.all_in_one;
else if(xwpfParagraphs.get(TAG_ITEMS_TIME) == xwpfParagraphs.get(TAG_ITEMS_UNIT))
items_col_type = Items_col_type.time_unit_in_one;
else if(xwpfParagraphs.get(TAG_ITEMS_TIME) == xwpfParagraphs.get(TAG_ITEMS_POST))
items_col_type = Items_col_type.time_post_in_one;
else if(xwpfParagraphs.get(TAG_ITEMS_UNIT) == xwpfParagraphs.get(TAG_ITEMS_POST))
items_col_type = Items_col_type.unit_post_in_one;
else
items_col_type = Items_col_type.all_aplit;
}
/**
* 设置 标签和内容的对应
* @param key 标签
* @param xwpfParagraph 对应的段落
*/
private void setXwpfParagraphs(String key, XWPFParagraph xwpfParagraph) {
if(key.matches(TAG_REGEX))
this.xwpfParagraphs.put(key, xwpfParagraph);
}
/**
* 写出
* @throws IOException
* @throws FileNotFoundException
*/
public void write(String path, WordData wordData) {
if(StringUtils.isEmpty(path))
return;
if(wordData == null)
return;
this.wordData = wordData;
this.modifyBase();
this.modifyHead();
this.modifySort();
this.modifyItem();
this.modifyItems();
remove(TAG_ITEM_TITLE);
remove(TAG_ITEM_CONTENT);
switch (this.items_col_type) {
case all_in_one:
remove(TAG_ITEMS_TIME);
break;
case time_post_in_one:
case time_unit_in_one:
remove(TAG_ITEMS_UNIT);
remove(TAG_ITEMS_POST);
break;
case unit_post_in_one:
remove(TAG_ITEMS_TIME);
remove(TAG_ITEMS_UNIT);
break;
case all_aplit:
remove(TAG_ITEMS_TIME);
remove(TAG_ITEMS_POST);
remove(TAG_ITEMS_UNIT);
break;
}
remove(TAG_ITEMS_TITLE);
remove(TAG_ITEMS_CONTENT);
Iterator<XWPFParagraph> iterator = document.getParagraphs().iterator();
while(iterator.hasNext()) {
XWPFParagraph xwpfParagraph = iterator.next();
if(xwpfParagraph.getCTP().isNil())
continue;
XmlCursor xmlCursor = xwpfParagraph.getCTP().newCursor();
if(xwpfParagraph.getCTP().getPPr().getSectPr() != null)
xmlCursor.removeXml();
}
try {
document.write(new FileOutputStream(path));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 删除段落
*/
private void remove(String tag) {
if(StringUtils.isEmpty(tag))
return;
List<XWPFParagraph> xwpfParagraphs = document.getParagraphs();
for (int index = 0; index < xwpfParagraphs.size(); index++) {
if(xwpfParagraphs.get(index) == this.xwpfParagraphs.get(tag)) {
document.removeBodyElement(index);
break;
}
}
}
/**
* 设置排序的
*/
private void modifySort() {
List<String> sorts = wordData.sorts;
for (String sort : sorts) {
if(wordData.getItem().keySet().contains(sort)) {
createItem(sort, wordData.getItem().get(sort));
wordData.getItem().remove(sort);
} else if (wordData.getItems().keySet().contains(sort)) {
createItems(sort, wordData.getItems().get(sort));
wordData.getItems().remove(sort);
}
}
}
/**
* 基本信息
*/
private void modifyBase() {
for (String key : BASE_TAGS) {
XWPFParagraph xwpfParagraph = xwpfParagraphs.get(key);
String content = null;
if(TAG_AGE.equals(key))
content = this.wordData.getAge();
else if(TAG_JOB.equals(key))
content = this.wordData.getJob();
else if(TAG_NAME.equals(key))
content = this.wordData.getName();
else if(TAG_EMAIL.equals(key))
content = this.wordData.getEmail();
else if(TAG_MOBILE.equals(key))
content = this.wordData.getMobile();
else if(TAG_ADDRESS.equals(key))
content = this.wordData.getAddress();
setText(key, content, xwpfParagraph);
}
}
/**
* 单项信息
*/
private void modifyItem() {
Map<String, String> itemMap = wordData.getItem();
Iterator<Entry<String, String>> iterator = itemMap.entrySet().iterator();
while(iterator.hasNext()) {
Entry<String, String> entry = iterator.next();
String key = entry.getKey();
String value = entry.getValue();
createItem(key, value);
}
}
/**
* 创建单项
*/
private void createItem(String key, String value) {
if(key == null || value == null)
return;
XWPFParagraph title = xwpfParagraphs.get(TAG_ITEM_TITLE);
XWPFParagraph newTitle = new XWPFParagraph((CTP) title.getCTP().copy(), title.getBody());
setText(TAG_ITEM_TITLE, key, newTitle);
document.createParagraph();
document.setParagraph(newTitle, document.getParagraphs().size() - 1);
XWPFParagraph content = xwpfParagraphs.get(TAG_ITEM_CONTENT);
XWPFParagraph newContent = new XWPFParagraph((CTP)content.getCTP().copy(), content.getBody());
setText(TAG_ITEM_CONTENT, value, newContent);
document.createParagraph();
document.setParagraph(newContent, document.getParagraphs().size() - 1);
}
/**
* 多项信息
*/
private void modifyItems() {
Map<String, List<WordDataItem>> itemMap = wordData.getItems();
Iterator<Entry<String, List<WordDataItem>>> iterator = itemMap.entrySet().iterator();
while(iterator.hasNext()) {
Entry<String, List<WordDataItem>> entry = iterator.next();
String key = entry.getKey();
List<WordDataItem> values = entry.getValue();
this.createItems(key, values);
}
}
private void createItems(String key, List<WordDataItem> values) {
XWPFParagraph title = xwpfParagraphs.get(TAG_ITEMS_TITLE);
XWPFParagraph newTitle = new XWPFParagraph((CTP) title.getCTP().copy(), title.getBody());
setText(TAG_ITEMS_TITLE, key, newTitle);
document.createParagraph();
document.setParagraph(newTitle, document.getParagraphs().size() - 1);
for(WordDataItem wordDataItem : values) {
switch (this.items_col_type) {
case all_in_one: {
XWPFParagraph oldParagraph = xwpfParagraphs.get(TAG_ITEMS_TIME);
XWPFParagraph newParagraph = new XWPFParagraph((CTP) oldParagraph.getCTP().copy(), oldParagraph.getBody());
setText(TAG_ITEMS_TIME, wordDataItem.getTime(), newParagraph);
setText(TAG_ITEMS_UNIT, wordDataItem.getUnit(), newParagraph);
setText(TAG_ITEMS_POST, wordDataItem.getPost(), newParagraph);
document.createParagraph();
document.setParagraph(newParagraph, document.getParagraphs().size() - 1);
}
break;
case time_post_in_one: {
XWPFParagraph oldUnitParagraph = xwpfParagraphs.get(TAG_ITEMS_UNIT);
XWPFParagraph newUnitParagraph = new XWPFParagraph((CTP) oldUnitParagraph.getCTP().copy(), oldUnitParagraph.getBody());
setText(TAG_ITEMS_UNIT, wordDataItem.getUnit(), newUnitParagraph);
document.createParagraph();
document.setParagraph(newUnitParagraph, document.getParagraphs().size() - 1);
XWPFParagraph oldPostParagraph = xwpfParagraphs.get(TAG_ITEMS_POST);
XWPFParagraph newPostParagraph = new XWPFParagraph((CTP) oldPostParagraph.getCTP().copy(), oldPostParagraph.getBody());
setText(TAG_ITEMS_POST, wordDataItem.getPost(), newPostParagraph);
setText(TAG_ITEMS_TIME, wordDataItem.getTime(), newPostParagraph);
document.createParagraph();
document.setParagraph(newPostParagraph, document.getParagraphs().size() - 1);
}
break;
case time_unit_in_one: {
XWPFParagraph oldPostParagraph = xwpfParagraphs.get(TAG_ITEMS_POST);
XWPFParagraph newPostParagraph = new XWPFParagraph((CTP) oldPostParagraph.getCTP().copy(), oldPostParagraph.getBody());
setText(TAG_ITEMS_POST, wordDataItem.getPost(), newPostParagraph);
document.createParagraph();
document.setParagraph(newPostParagraph, document.getParagraphs().size() - 1);
XWPFParagraph oldUnitParagraph = xwpfParagraphs.get(TAG_ITEMS_UNIT);
XWPFParagraph newUnitParagraph = new XWPFParagraph((CTP) oldUnitParagraph.getCTP().copy(), oldUnitParagraph.getBody());
setText(TAG_ITEMS_UNIT, wordDataItem.getUnit(), newUnitParagraph);
setText(TAG_ITEMS_TIME, wordDataItem.getTime(), newUnitParagraph);
document.createParagraph();
document.setParagraph(newUnitParagraph, document.getParagraphs().size() - 1);
}
break;
case unit_post_in_one: {
XWPFParagraph oldTimeParagraph = xwpfParagraphs.get(TAG_ITEMS_TIME);
XWPFParagraph newTimeParagraph = new XWPFParagraph((CTP) oldTimeParagraph.getCTP().copy(), oldTimeParagraph.getBody());
setText(TAG_ITEMS_TIME, wordDataItem.getTime(), newTimeParagraph);
document.createParagraph();
document.setParagraph(newTimeParagraph, document.getParagraphs().size() - 1);
XWPFParagraph oldUnitParagraph = xwpfParagraphs.get(TAG_ITEMS_UNIT);
XWPFParagraph newUnitParagraph = new XWPFParagraph((CTP) oldUnitParagraph.getCTP().copy(), oldUnitParagraph.getBody());
setText(TAG_ITEMS_UNIT, wordDataItem.getUnit(), newUnitParagraph);
setText(TAG_ITEMS_POST, wordDataItem.getPost(), newUnitParagraph);
document.createParagraph();
document.setParagraph(newUnitParagraph, document.getParagraphs().size() - 1);
}
break;
case all_aplit: {
XWPFParagraph oldTimeParagraph = xwpfParagraphs.get(TAG_ITEMS_TIME);
XWPFParagraph newTimeParagraph = new XWPFParagraph((CTP) oldTimeParagraph.getCTP().copy(), oldTimeParagraph.getBody());
setText(TAG_ITEMS_TIME, wordDataItem.getTime(), newTimeParagraph);
document.createParagraph();
document.setParagraph(newTimeParagraph, document.getParagraphs().size() - 1);
XWPFParagraph oldUnitParagraph = xwpfParagraphs.get(TAG_ITEMS_UNIT);
XWPFParagraph newUnitParagraph = new XWPFParagraph((CTP) oldUnitParagraph.getCTP().copy(), oldUnitParagraph.getBody());
setText(TAG_ITEMS_UNIT, wordDataItem.getUnit(), newUnitParagraph);
document.createParagraph();
document.setParagraph(newUnitParagraph, document.getParagraphs().size() - 1);
XWPFParagraph oldPostParagraph = xwpfParagraphs.get(TAG_ITEMS_POST);
XWPFParagraph newPostParagraph = new XWPFParagraph((CTP) oldPostParagraph.getCTP().copy(), oldPostParagraph.getBody());
setText(TAG_ITEMS_POST, wordDataItem.getUnit(), newPostParagraph);
document.createParagraph();
document.setParagraph(newPostParagraph, document.getParagraphs().size() - 1);
}
break;
}
XWPFParagraph content = xwpfParagraphs.get(TAG_ITEMS_CONTENT);
XWPFParagraph newContent = new XWPFParagraph((CTP) content.getCTP().copy(), content.getBody());
setText(TAG_ITEMS_CONTENT, wordDataItem.getContent(), newContent);
document.createParagraph();
document.setParagraph(newContent, document.getParagraphs().size() - 1);
}
}
/**
* 修改头像
*/
private void modifyHead() {
if(StringUtils.isEmpty(wordData.getHeadId()))
return;
String head = wordData.getHead();
String OLD_RID = wordData.getHeadId();
if(StringUtils.isEmpty(head))
return;
File file = new File(head);
if(!file.isFile() || !file.exists())
return;
byte[] imagebis = null;
InputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
imagebis = new byte[inputStream.available()];
inputStream.read(imagebis);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(inputStream);
}
String rid;
try {
rid = document.addPictureData(imagebis, XWPFDocument.PICTURE_TYPE_JPEG);
document.getPackagePart().removeRelationship(OLD_RID);
document.getPackagePart().addRelationship(
document.getRelationById(rid).getPackageRelationship().getTargetURI(),
TargetMode.INTERNAL,
XWPFRelation.IMAGES.getRelation(),
OLD_RID
);
} catch (InvalidFormatException e) {
e.printStackTrace();
}
}
/**
* 设置内容
* @param key 标签
* @param content 内容
* @param xwpfParagraph 段落
*/
private void setText(String key, String content, XWPFParagraph xwpfParagraph) {
if(content == null)
content = "";
if (xwpfParagraph == null)
return;
boolean update = false;
List<CTR> ctrs = xwpfParagraph.getCTP().getRList(); // 文本框内容
for (CTR ctr : ctrs) {
List<CTPicture> ctPictures = ctr.getPictList();
if(CollectionUtils.isNotEmpty(ctPictures)) {
CTPicture ctPicture = ctPictures.get(0);
XmlCursor cursor = ctPicture.newCursor();
if(cursor.getTextValue().equals(key)) {
update = true;
cursor.selectPath(TEXT_PATH);
if(cursor.toNextSelection())
cursor.setTextValue(content);
while(cursor.toNextSelection())
cursor.removeXml();
}
}
}
if(update)
return;
if(key.equals(xwpfParagraph.getText())) {
List<CTR> ctrs_ = xwpfParagraph.getCTP().getRList();
boolean update_ = false;
for (CTR ctr : ctrs_) {
XmlCursor cursor = ctr.newCursor();
cursor.selectPath(TEXT_PATH);
if(cursor.toNextSelection() && StringUtils.isNotEmpty(cursor.getTextValue()) && !update_) {
String[] contents = content.split(NEW_LINE);
update_ = true;
if(contents.length == 1)
cursor.setTextValue(content);
else {
for (int i = 0; i < contents.length; i++) { // 多行问题
if(i == 0)
cursor.setTextValue(contents[0]);
else {
ctr.addNewBr();
ctr.addNewT().setStringValue(contents[i]);
}
}
}
} else if(StringUtils.isNotEmpty(cursor.getTextValue())) {
cursor.removeXml();
}
while(cursor.toNextSelection())
cursor.removeXml();
}
}
}
}
本代码存在细节问题:如果时间三个信息不在一栏需要另行判断和删除。