您的位置:首页 > 其它

docx4j创建word文档

2017-12-16 11:13 337 查看
案例.根据模版用docx4j生成doc文档,并将doc文档转成pdf文档再下载下来

1.模版



2.docx4j操作类

package com.hdkj.common.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
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.jaxb.Context;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.Br;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.ObjectFactory;
import org.docx4j.wml.P;
import org.docx4j.wml.STBrType;
import org.docx4j.wml.Tbl;
import org.docx4j.wml.Text;
import org.docx4j.wml.Tr;

public class Docx4jUtils {
private static ObjectFactory factory;

private WordprocessingMLPackage template;

private String target;

/**
* @return
*
*/
public void connection(String source, String target) throws Docx4JException, FileNotFoundException {
// TODO Auto-generated constructor stub
this.template = getTemplate(source);
this.target = target;
}

/**
* @param name
* @return
* @throws Docx4JException
* @throws FileNotFoundException
*/
private static 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<Object> getAllElementFromObject(Object obj, Class<?>
// toSearch)
// {
// List<Object> result = new ArrayList<Object>();
// 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;
// }
// 获取对象元素
private static List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
List<Object> result = new ArrayList<Object>();
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;
}

// private void test(Map<String, String> replacements, Map<String, String>
// pgReplacements) throws Docx4JException, JAXBException {
// // TODO Auto-generated method stub
//
// //要替换的表格
// // Map<String,String> repl0 = new HashMap<String, String>();
// // repl0.put("[table-index1-name]", "yanglw");
// // repl0.put("[table-index1-bh]", "32");
// // repl0.put("[table-index1-sj]", "chenx");
//
//
// }

public void replaceTable(String[] placeholders, List<Map<String, String>> textToAdd) throws Exception {
List<Object> tables = getAllElementFromObject(template.getMainDocumentPart(), Tbl.class);

if(tables == null || tables.size() == 0){
throw new Exception("模板文档里没有表格,不能进行表格内容替换!!");
}

// 1. find the table
Tbl tempTable = getTemplateTable(tables, placeholders[0]);
if(tempTable == null){
throw new Exception("模板文档里没有表格占位符" + placeholders[0] + ",请检查模板是否正确!!");
}
List<Object> 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<String, String> replacements : textToAdd) {
// // 2 and 3 are done in this method
// addRowToTable(tempTable, templateRow, replacements);
// }
//
// // 4. remove the template row
// tempTable.getContent().remove(templateRow);
// }

// 我们现在的模板里面是个很复杂的表格, 首先我们要找到 模板行, 就是第一列是[NO]
// 一行一行的遍历, 找包含[NO]的Text
Tr templateRow = null;
outterLoop: for (int rowIndex = 0; rowIndex < rows.size(); rowIndex++) {
Tr row = (Tr) rows.get(rowIndex);
// 找到表格里面的所有Text对象
List<?> textElements = getAllElementFromObject(row, Text.class);
for (Object text : textElements) {
Text textElement = (Text) text;
if (textElement.getValue() != null && textElement.getValue().equals(placeholders[0])) {
templateRow = row;             //placeholders[0]是包含几个元素的数组,为什么可以相等?
break outterLoop;
}
}
}

if (templateRow == null) {
System.out.println("没有找到模板行, 请检查");
}

for (Map<String, String> replacements : textToAdd) {
// 2 and 3 are done in this method
// 原先的这个方法是在表格的最后新增行, 但我们的模板里, 要添加数据的位置不是在最后
// addRowToTable(tempTable, templateRow, replacements);
insertRowToTable(tempTable, templateRow, replacements); // 替换字段
}

// 4. remove the template row
tempTable.getContent().remove(templateRow);
}

// 获取表格对象
private static Tbl getTemplateTable(List<Object> tables, String templateKey) throws Docx4JException, JAXBException {
for (Iterator<Object> iterator = tables.iterator(); iterator.hasNext();) {
Object tbl = iterator.next();
// 找到表格里面的所有Text对象
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;
}

// 增加表格
private static void addRowToTable(Tbl reviewtable, Tr templateRow, Map<String, String> 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);
}

// 插入表格
private static void insertRowToTable(Tbl reviewtable, Tr templateRow, Map<String, String> 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);
}

int templateIndex = reviewtable.getContent().indexOf(templateRow);
reviewtable.getContent().add(templateIndex, workingRow);
}

public void processPgTexts(Map<String, String> pgReplacements) {
// TODO Auto-generated method stub
// paragraph
for (Map.Entry<String, String> entry : pgReplacements.entrySet()) {
String placeholder = entry.getKey();
String textToAdd = (String) entry.getValue();
replaceParagraph(placeholder, textToAdd, template);
}
}

public void processTexts(Map<String, String> replacements) {
// TODO Auto-generated method stub
// 进行文本占位符替换
for (Map.Entry<String, String> entry : replacements.entrySet()) {
String placeholder = entry.getKey();  // 字段
String textToAdd = (String) entry.getValue(); // 实际数据
replacePlaceholder(placeholder, textToAdd, template); // 替换字段
}
}

public void writeDocxToStream() throws FileNotFoundException, Docx4JException {
// connection(source, target);
File f = new File(this.target);
try {
template.save(f);
} catch (Docx4JException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

private static void replaceParagraph(String placeholder, String textToAdd, WordprocessingMLPackage template) {

// 1. get the paragraph
List<Object> paragraphs = getAllElementFromObject(template.getMainDocumentPart(), P.class);

P toReplace = null;
for (Object p : paragraphs) {
List<Object> texts = getAllElementFromObject(p, Text.class);
for (Object t : texts) {
Text content = (Text) t;
content.getValue();
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
if (null == toReplace) {
// doNothing
return;
}
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);// 将原来文本删除,用了add的方法添加新的段落

// File newFile = new File("C://Users/杨璐玮/Desktop/派工单_模板_处理后pg.doc");
// template.save(newFile);
}

private static void replacePlaceholder(String placeholder, String textToAdd, WordprocessingMLPackage template) {
// TODO Auto-generated method stub

List<Object> texts = getAllElementFromObject(template.getMainDocumentPart(), Text.class);

for (Object text : texts) {

Text textElement = (Text) text;
if (textElement.getValue().contains(placeholder)) {
String a = textElement.getValue().toString().replace(placeholder, textToAdd);
textElement.setValue(a);
}
}
// File newFile = new File("C://Users/杨璐玮/Desktop/派工单_模板_处理后text.doc");
// try {
// template.save(newFile);
// } catch (Docx4JException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
}
//
// public static Map getYWData()
// {
// Map<String, Object> map = new HashMap<String, Object>();
// map.put("[text-no]", "0001");
// map.put("[text-date]", "2016/8/19");
//
// return map;
// }

/**
* 向文档添加一个换行符
*/
public  void addPageBreak() {
factory = Context.getWmlObjectFactory();

this.template.getMainDocumentPart().addParagraphOfText("Hello Word!");

MainDocumentPart documentPart = this.template.getMainDocumentPart();
Br breakObj = new Br();
breakObj.setType(STBrType.PAGE);

P paragraph = factory.createP();
paragraph.getContent().add(breakObj);
documentPart.getJaxbElement().getBody().getContent().add(paragraph);

}

}
3.doc转pdf类
package com.hdkj.common.util;
import java.io.File;
import java.io.IOException;
import java.util.Date;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;

public class Word2PdfUtil {

static final int wdDoNotSaveChanges = 0;// 不保存待定的更改。
static final int wdFormatPDF = 17;// word转PDF 格式

//    public static void main(String[] args) throws IOException {
//        String source1 = "d:\\aaa.docx";
//        String target1 = "d:\\"+new Date()+".pdf";
//        Word2PdfUtil pdf = new Word2PdfUtil();
//        pdf.word2pdf(source1, target1);
//    }

public static boolean word2pdf(String source, String target) {
System.out.println("Word转PDF开始启动...");
long start = System.currentTimeMillis();
ActiveXComponent app = null;
try {
app = new ActiveXComponent("Word.Application");
app.setProperty("Visible", false);
Dispatch docs = app.getProperty("Documents").toDispatch();
System.out.println("打开文档:" + source);
Dispatch doc = Dispatch.call(docs, "Open", source, false, true).toDispatch();
System.out.println("转换文档到PDF:" + target);
File tofile = new File(target);
if (tofile.exists()) {
tofile.delete();
}
Dispatch.call(doc, "SaveAs", target, wdFormatPDF);
Dispatch.call(doc, "Close", false);
long end = System.currentTimeMillis();
System.out.println("转换完成,用时:" + (end - start) + "ms");
return true;
} catch (Exception e) {
System.out.println("Word转PDF出错:" + e.getMessage());
return false;
} finally {
if (app != null) {
app.invoke("Quit", wdDoNotSaveChanges);
}
}
}
}
4.调用方法如下

/**
* 打印采购供货单
* @param request
* @param response
*/
@RequestMapping(params = "exportWord")
public void exportWord(HttpServletRequest request, HttpServletResponse response){
try {
String[] Ids = request.getParameterValues("Ids");
String[] IdArray=Ids[0].split(",");
//项目定义号
String PURCHASE_SUPPLY_NO=request.getParameter("PURCHASE_SUPPLY_NO");

Docx4jUtils testText = new Docx4jUtils();

String source ="";
//1.连接模板
String realPath = request.getSession().getServletContext().getRealPath("\\") ;// 文件的硬盘真实路径
source=realPath+"WEB-INF\\classes\\com\\hdkj\\template\\采购供货单.docx";

//创建导出地址
String target = "C:\\export" ;// 文件的硬盘真实路径

//创建相应目录
File dir = new File(target);
if(!dir.exists()){
dir.mkdirs();
}
target="C:\\export\\采购供货单_"+PURCHASE_SUPPLY_NO+".docx";
String target2 = "C:\\export\\采购供货单_"+PURCHASE_SUPPLY_NO+".pdf";
Word2PdfUtil pdf = new Word2PdfUtil();

testText.connection(source,target);

//2.替换字段
Map<String, String> replacements = new HashMap<String, String>();
Map map=this.tPurchaseSupplyService.getDataBySupplyNo(PURCHASE_SUPPLY_NO);
String sgdw=map.get("contract_cxdwms")==null?"":map.get("contract_cxdwms").toString();
String mf=map.get("supplier_name")==null?"":map.get("supplier_name").toString();
String htbh=map.get("contrac_bh")==null?"":map.get("contrac_bh").toString();
String xxjg=map.get("zfpzj")==null?"0":map.get("zfpzj").toString();

replacements.put("[bh]", PURCHASE_SUPPLY_NO);
replacements.put("[sgdw]", sgdw);
replacements.put("[mf]", mf);
replacements.put("[htbh]", htbh);
replacements.put("[xxjg1]", xxjg);
replacements.put("[xxjg2]", xxjg);
//大写金额
String dxje=MoneyUtil.toChinese(xxjg);
replacements.put("[dxjg1]", dxje);
replacements.put("[dxjg2]", dxje);
testText. processTexts(replacements);

Map<String,String> repl1;
List<Map<String,String>> maplist=new ArrayList();
if(IdArray.length>0){
for(int i=0;i<IdArray.length;i++){
String id=IdArray[i];
Map maptemp=this.tPurchaseSupplyService.getData(id);
String xh=maptemp.get("xh").toString();
//合同执行单位名称
String xmdw=maptemp.get("contract_cxdwms")==null?"0":maptemp.get("contract_cxdwms").toString();
//单体工程名称
String xmmc=maptemp.get("monimer_project_name")==null?"0":maptemp.get("monimer_project_name").toString();
//货物名称
String hwmc=maptemp.get("material_description").toString();
//规格/型号
String gg="";
String sl=maptemp.get("cgsl").toString();
//单位
String dw=maptemp.get("jldw").toString();
//含税单价
String hsdj=maptemp.get("zfpdj").toString();
//含税总价
String hszj=maptemp.get("zfpzj").toString();
//交货时间
String jhsj=maptemp.get("delivery_date").toString();
//交货地点
String delivery_place=maptemp.get("delivery_place").toString();
//交货方式
String delivery_mode=maptemp.get("delivery_mode").toString();
repl1 = new HashMap<String, String>();
repl1.put("[xh]", xh);
repl1.put("[xmdw]", xmdw);
repl1.put("[xmmc]", xmmc);
repl1.put("[hwmc]", hwmc);
repl1.put("[gg]", gg);
repl1.put("[sl]", sl);
repl1.put("[dw]", dw);
repl1.put("[hsdj]", hsdj);
repl1.put("[hszj]", hszj);
repl1.put("[jhsj]", jhsj);
repl1.put("[ddjfs]", delivery_place+","+delivery_mode);
maplist.add(repl1);

}
testText.replaceTable(new String[]{"[xh]","[xmdw]","[xmmc]","[hwmc]","[gg]","[sl]","[dw]","[hsdj]","[hszj]","[jhsj]","[ddjfs]"}, maplist);
}
/*
//4.替换表格 多个表格时需要重复写
Map<String,String> repl1 = new HashMap<String, String>();
repl1.put("[sp]", "1");
repl1.put("[spnr]", "枪机");
Map<String,String> repl2 = new HashMap<String, String>();
repl2.put("[sp]", "2");
repl2.put("[spnr]", "枪机2");
Map<String,String> repl3 = new HashMap<String, String>();
repl3.put("[sp]", "3");
repl3.put("[spnr]", "枪机3");

testText.replaceTable(new String[]{"[sp]","[spnr]"}, Arrays.asList(repl1,repl2,repl3));
*/
//5.生成新的doc文件
testText.writeDocxToStream();

//6.生成新的pdf文件
pdf.word2pdf(target, target2);

//7.下载
File file = new File(target2);
if(file != null){
// 以流的形式下载文件。
InputStream fis = new BufferedInputStream(new FileInputStream(file));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();
// 设置response的Header, 汉字要转义
String fileNameEncoded="采购供货单_"+PURCHASE_SUPPLY_NO+".pdf";
fileNameEncoded = new String(fileNameEncoded.getBytes(), "ISO-8859-1");
response.addHeader("Content-Disposition", "attachment;filename=" + fileNameEncoded);
response.addHeader("Content-Length", "" + file.length());

OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
toClient.write(buffer);
toClient.flush();
toClient.close();
}
response.flushBuffer();
//			JSONObject succ = new JSONObject();
//			succ.put("success", true);
//			succ.put("message", "请在桌面上查看导出的文件!");
//			ServletUtils.printJsonData(succ.toString(), response);
} catch (Exception e) {
e.printStackTrace();
logger.warn(e.getMessage());
JSONObject error = new JSONObject();
error.put("success", false);
error.put("message", e.getMessage());
ServletUtils.printJsonData(error.toString(), response);
}
}


5.docx4j需要下载docx4j-3.3.0.jar
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: