poi操作word模板(word2003,word2007)

时间:2021-12-25 06:22:12

近期老师给了个任务,要通过Word模版生成各类文档,主要就是将类似%title%,%name%,%content%等标签,通过类的方法,查询数据库并替换标签,上网查了一下,发现POI对文档操作比较不错,Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。Word2003的方法比较简单,大致通过Range替换文本,Word2007比较复杂点,遍历替换文本,参考了网上的案例,写了个demo,直接上代码。


package com.poi.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import com.poi.model.Person;

public class WordUtil {
private Map<String, String> map = new HashMap<String, String>();//存放标签与替换的值
private String templatePath;//模版路径

public WordUtil(String templatePath,Person person) {
this.templatePath = templatePath;
if (templatePath.endsWith("docx")) {
try {
@SuppressWarnings("resource")
XWPFWordExtractor docx = new XWPFWordExtractor(
POIXMLDocument.openPackage(templatePath));
String docxText = docx.getText();
getValueMap(docxText,person);
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
@SuppressWarnings("resource")
WordExtractor doc = new WordExtractor(new FileInputStream(
templatePath));
String docText = doc.getText();
getValueMap(docText,person);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//遍历获取标签与通过对象替代的值
private void getValueMap(String text,Person person) {
Pattern pattern = Pattern.compile("%(.*?)%");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
String key = matcher.group(1);
String value = person.getString(key);
if (value == null) {
value = "";
}
map.put(key, value);
}
}
public void createDoc(String newPath) {
if (templatePath.endsWith("docx")) {
replaceDoc2007(newPath);
} else {
replaceDoc2003(newPath);
}
}

public void replaceDoc2007(String newPath) {
try {
OPCPackage pack = POIXMLDocument.openPackage(templatePath);
XWPFDocument doc = new XWPFDocument(pack);
// 处理段落
List<XWPFParagraph> paragraphList = doc.getParagraphs();
processParagraphs(paragraphList, map);
// 处理表格
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, map);
}
}
}
FileOutputStream fos = new FileOutputStream(newPath);
doc.write(fos);
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}

public void replaceDoc2003(String newPath) {
String[] str = newPath.split(".doc");
newPath = str[0] + ".doc";
try {
FileInputStream fis = new FileInputStream(new File(templatePath));
HWPFDocument doc = new HWPFDocument(fis);
Range bodyRange = doc.getRange();
for (Map.Entry<String, String> entry : map.entrySet()) {
bodyRange.replaceText("%" + entry.getKey() + "%",
entry.getValue());
}
// 输出word文件
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
doc.write(ostream);
OutputStream outs = new FileOutputStream(newPath);
outs.write(ostream.toByteArray());
outs.close();
} catch (Exception e) {
e.printStackTrace();
}
}

private void processParagraphs(List<XWPFParagraph> paragraphList,
Map<String, String> map) {
for (XWPFParagraph paragraph : paragraphList) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
String text = run.getText(0);
boolean isSetText = false;
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
if (text.indexOf(key) != -1) {
isSetText = true;
text = text.replace("%" + entry.getKey() + "%",entry.getValue());
}
}
if (isSetText) {
run.setText(text, 0);
}
}
}
}


}