jar包:http://www.docx4java.org/docx4j/docx4j-3.1.0-community.zip
参考http://www.smartjava.org/content/create-complex-word-docx-documents-programatically-docx4j
package com.longshine.components.office;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import org.apache.commons.lang.StringUtils;
import org.docx4j.XmlUtils;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.P;
import org.docx4j.wml.Tbl;
import org.docx4j.wml.Text;
import org.docx4j.wml.Tr;
public class MakeTemplateWord {
private WordprocessingMLPackage template;
private String target;
/**
*
*/
public MakeTemplateWord(String source,String target)throws Docx4JException, FileNotFoundException
{
this.template=getTemplate(source);
this.target = target;
}
/**
*
* @param name
* @return
* @throws Docx4JException
* @throws FileNotFoundException
*/
private WordprocessingMLPackage getTemplate(String name) throws Docx4JException, FileNotFoundException {
WordprocessingMLPackage template = WordprocessingMLPackage.load(new FileInputStream(new File(name)));
return template;
}
/**
*
* @param obj
* @param toSearch
* @return
*/
private static List getAllElementFromObject(Object obj, Class> toSearch) {
List result = new ArrayList();
if (obj instanceof JAXBElement) obj = ((JAXBElement>) obj).getValue();
if (obj.getClass().equals(toSearch))
result.add(obj);
else if (obj instanceof ContentAccessor) {
List> children = ((ContentAccessor) obj).getContent();
for (Object child : children) {
result.addAll(getAllElementFromObject(child, toSearch));
}
}
return result;
}
/**
*
* @param template
* @param name
* @param placeholder
*/
private void replacePlaceholder(String name, String placeholder ) {
List texts = getAllElementFromObject(template.getMainDocumentPart(), Text.class);
for (Object text : texts) {
Text textElement = (Text) text;
if (textElement.getValue().equals(placeholder)) {
textElement.setValue(name);
}
}
}
/**
*
* @param placeholder
* @param textToAdd
* @param template
* @param addTo
*/
private void replaceParagraph(String placeholder, String textToAdd) {
// 1. get the paragraph
List paragraphs = getAllElementFromObject(template.getMainDocumentPart(), P.class);
P toReplace = null;
for (Object p : paragraphs) {
List texts = getAllElementFromObject(p, Text.class);
for (Object t : texts) {
Text content = (Text) t;
if (content.getValue().equals(placeholder)) {
toReplace = (P) p;
break;
}
}
}
// we now have the paragraph that contains our placeholder: toReplace
// 2. split into seperate lines
String as[] = StringUtils.splitPreserveAllTokens(textToAdd, '\n');
for (int i = 0; i < as.length; i++) {
String ptext = as[i];
// 3. copy the found paragraph to keep styling correct
P copy = (P) XmlUtils.deepCopy(toReplace);
// replace the text elements from the copy
List> texts = getAllElementFromObject(copy, Text.class);
if (texts.size() > 0) {
Text textToReplace = (Text) texts.get(0);
textToReplace.setValue(ptext);
}
// add the paragraph to the document
// template.getMainDocumentPart().getContent().add(copy);
((ContentAccessor)toReplace.getParent()).getContent().add(copy);
}
// 4. remove the original one
((ContentAccessor)toReplace.getParent()).getContent().remove(toReplace);
}
/**
*
* @param tables
* @param templateKey
* @return
* @throws Docx4JException
* @throws JAXBException
*/
private Tbl getTemplateTable(List tables, String templateKey) throws Docx4JException, JAXBException {
for (Iterator iterator = tables.iterator(); iterator.hasNext();) {
Object tbl = iterator.next();
List> textElements = getAllElementFromObject(tbl, Text.class);
for (Object text : textElements) {
Text textElement = (Text) text;
if (textElement.getValue() != null && textElement.getValue().equals(templateKey))
return (Tbl) tbl;
}
}
return null;
}
/**
*
* @param placeholders
* @param textToAdd
* @param template
* @throws Docx4JException
* @throws JAXBException
*/
private void replaceTable(String placeholders, List> textToAdd) throws Docx4JException, JAXBException {
List tables = getAllElementFromObject(template.getMainDocumentPart(), Tbl.class);
// 1. find the table
Tbl tempTable = getTemplateTable(tables, placeholders);
List rows = getAllElementFromObject(tempTable, Tr.class);
// first row is header, second row is content
if (rows.size() == 2) {
// this is our template row
Tr templateRow = (Tr) rows.get(1);
for (Map replacements : textToAdd) {
// 2 and 3 are done in this method
addRowToTable(tempTable, templateRow, replacements);
}
// 4. remove the template row
tempTable.getContent().remove(templateRow);
}
}
/**
*
* @param reviewtable
* @param templateRow
* @param replacements
*/
private static void addRowToTable(Tbl reviewtable, Tr templateRow, Map replacements) {
Tr workingRow = (Tr) XmlUtils.deepCopy(templateRow);
List> textElements = getAllElementFromObject(workingRow, Text.class);
for (Object object : textElements) {
Text text = (Text) object;
String replacementValue = (String) replacements.get(text.getValue());
if (replacementValue != null)
text.setValue(replacementValue);
}
reviewtable.getContent().add(workingRow);
}
/**
*
* @param template
* @param target
* @throws IOException
* @throws Docx4JException
*/
public void writeDocxToStream() throws IOException, Docx4JException {
File f = new File(this.target);
template.save(f);
}
/**
*
* @param inputFile
* @param outputFile
* @param replacements
*/
public void test(Map replacements,Map tblReplacements,Map pgReplacements)throws Exception
{
writeDocxToStream();
}
public void processTexts(Map replacements)
{
//进行文本占位符替换
for(Map.Entry entry: replacements.entrySet())
{
replacePlaceholder(entry.getValue(), entry.getKey());
}
}
public void processTables(Map tblReplacements) throws Docx4JException, JAXBException
{
//表格替换
for(Map.Entry entry: tblReplacements.entrySet())
{
String placeholder=entry.getKey();
List> textToAdd=(List> )entry.getValue();
replaceTable(placeholder, textToAdd);
}
}
public void processPgTexts(Map pgReplacements)
{
//文本段落替换
for(Map.Entry entry: pgReplacements.entrySet())
{
String placeholder=entry.getKey();
String textToAdd=(String )entry.getValue();
replaceParagraph(placeholder, textToAdd);
}
}
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
String source="c:\\tmp\\docs\\template.docx";
String target="c:\\tmp\\docs\\ouput.docx";
MakeTemplateWord make=new MakeTemplateWord(source,target);
Map repl1 = new HashMap();
repl1.put("SJ_FUNCTION", "function1");
repl1.put("SJ_DESC", "desc1");
repl1.put("SJ_PERIOD", "period1");
Map repl2 = new HashMap();
repl2.put("SJ_FUNCTION", "function2");
repl2.put("SJ_DESC", "desc2");
repl2.put("SJ_PERIOD", "period2");
Map repl3 = new HashMap();
repl3.put("SJ_FUNCTION", "function3");
repl3.put("SJ_DESC", "desc3");
repl3.put("SJ_PERIOD", "period3");
Map replacements=new HashMap();
replacements=getYWData();
//replacements.put("", "");
//
List tabList=new ArrayList();
Map tblReplacements=new HashMap();
Map copy=new HashMap();
copy.put("FIELD0", "复奉直流");
copy.put("FIELD1", "0");
copy.put("FIELD2", "0");
copy.put("FIELD3", "双极停运");
tabList.add(copy);
copy=new HashMap();
copy.put("FIELD0", "锦苏直流");
copy.put("FIELD1", "4367");
copy.put("FIELD2", "2862");
copy.put("FIELD3", "双极四阀组大地回线");
tabList.add(copy);
copy=new HashMap();
copy.put("FIELD0", "天中直流");
copy.put("FIELD1", "800");
copy.put("FIELD2", "900");
copy.put("FIELD3", "双极四阀组大地回线");
tabList.add(copy);
tblReplacements.put("FIELD0",tabList);
Map pgReplacements=new HashMap();
pgReplacements.put("LAST_WEEK", "1.继续跟踪复奉直流年度检修消缺,协调复龙站4.1和4.2阀侧套管(换下的400kV换流变)运往沈阳传奇修复。\n2.继续跟踪宾金直流调试工作。按照国网运检部要求,编制报送宾金直流生产准备费分解计划。\n5.按照国网法律部要求,组织开展国网公司第四批通用制度修改意见的征求工作。");
pgReplacements.put("CURR_WEEK", "7.继续组织开展运维管理提升作业标准编制工作。\n10.参加哈郑工程GRTS避雷器技术讨论会、溪浙工程双龙换流站穿墙套管技术讨论会。组织ABB变压器组件公司技术交流会。");
make.test(replacements, tblReplacements,pgReplacements);
}
public static Map getYWData()
{
Map map = new HashMap();
map.put("WEEK_NO", "2014年第10周");
map.put("DEPT_NAME", "运维部门");
map.put("REPORT_NO", "总第400期");
map.put("DURATION", "(2014-04-30至2014-05-04)");
Map tmp=null;
map.put("DC_TRANS_CAPACITY","截至2014年3月10日00:00,公司系统本年度直流输送电量为78.77亿千瓦时。");
map.put("ASSET_FLAW","3月6日,奉贤站发现极I低端Y/D-A相换流变10号冷却器渗油,经厂家、技术监督单位确认,3月9日对该冷却器进行了更换");
map.put("SYSTEM_FAULT","3月6日16:13,西锦III线B相故障,重合不成功跳闸,线路故障测距距离锦屏站57.6km,站内一、二次设备检查无异常。16:55按国调令将西锦III线转运行,16:58线路再次跳闸,18:56西锦III线转运行正常");
List lastWeekList=new ArrayList();
tmp=new HashMap();
tmp.put("content", "1.继续跟踪复奉直流年度检修消缺,协调复龙站4.1和4.2阀侧套管(换下的400kV换流变)运往沈阳传奇修复。梳理天中直流消缺后的工程遗留问题,目前还有中州站极2高端Y/Y-B换流变铁芯夹件间绝缘异常、高端换流变阀侧套管SF6密度继电器不满足非电量保护3取2配置要求、四阀组运行主泵的工频回路负荷开关换型未完成和天山站换流变充电时西门子阀控系统误报晶闸管无回报信号问题未彻底解决等31个问题未处理或在处理。");
tmp.put("focus", "Y");
lastWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", "2.继续跟踪宾金直流调试工作。按照国网运检部要求,编制报送宾金直流生产准备费分解计划。");
tmp.put("focus", "Y");
lastWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", "3.天山、中州站完成非电量保护定值清理并完成标准化定值单的编制、审批、执行和备案,组织各站全面推广此项工作,加强公司所辖各站非电量保护定值和定值单管理。以保护定值为突破口,组织开展站用电、阀水冷、非电量保护装置全面排查工作,避免“7.5”类似事件发生");
tmp.put("focus", "Y");
lastWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", "4.组织向公司生产管理信息系统关键用户通报PMS1.0应用情况,PMS2.0建设进展和下一步工作计划。");
tmp.put("focus", "Y");
lastWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", "5.按照国网法律部要求,组织开展国网公司第四批通用制度修改意见的征求工作。");
tmp.put("focus", "Y");
lastWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", "6.编制新工程生产准备工作月报和特高压换流站运行月报并在公司OA系统电子公告栏发布。");
tmp.put("focus", "N");
lastWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", "7.继续组织开展运维管理提升作业标准编制工作。");
tmp.put("focus", "N");
lastWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", "8.编制完成公司技改大修项目立项原则。协调国网运检部和浙江、江苏公司做好2014年项目计划下达。继续组织完善一体化在线监测平台,梳理讨论在线监测设备类型和数据告警规则");
tmp.put("focus", "N");
lastWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", "9.组织开展2014年度国网科技进步奖、专利奖推荐工作,组织征集电网设备状态检测技术应用案例。组织开展公司2014年运维工作会和第一次生产准备例会筹备工作。");
tmp.put("focus", "N");
lastWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", "10.参加哈郑工程GRTS避雷器技术讨论会、溪浙工程双龙换流站穿墙套管技术讨论会。组织ABB变压器组件公司技术交流会。");
tmp.put("focus", "N");
lastWeekList.add(tmp);
// map.put("LAST_WEEK", lastWeekList);
List currWeekList=new ArrayList();
tmp=new HashMap();
tmp.put("content", "1.继续跟踪2014年复龙、奉贤换流站年度检修,做好现场安全、质量、进度控制,做好检修总结的编报工作。");
tmp.put("focus", "Y");
currWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", " 2.参加宾金直流双极低端系统调试启动会议,继续跟踪宾金直流双极低端系统调试。");
tmp.put("focus", "Y");
currWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", " 3.现场检查大修期间备品备件使用、管理情况。");
tmp.put("focus", "Y");
currWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", " 4.继续组织开展公司2014第二批物资非招标采购前期准备工作。");
tmp.put("focus", "Y");
currWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", " 5.继续开展公司零星物资采购工作。");
tmp.put("focus", "Y");
currWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", " 6.筹备与许继集团技术交流会议。");
tmp.put("focus", "N");
currWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", " 7.继续开展公司招标资料档案整理工作。");
tmp.put("focus", "N");
currWeekList.add(tmp);
tmp=new HashMap();
tmp.put("content", " 8.开展前期调研,申报直流自动功率曲线控制技术咨询项目和特高压直流停电检修工期研究技术咨询项目。");
tmp.put("focus", "N");
currWeekList.add(tmp);
// map.put("CURR_WEEK", currWeekList);
return map;
}
}