案例 .根据模版用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 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;
// }
// 获取对象元素
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;
}
// private void test(Map replacements, Map
// pgReplacements) throws Docx4JException, JAXBException {
// // TODO Auto-generated method stub
//
// //要替换的表格
// // Map repl0 = new HashMap();
// // repl0.put("[table-index1-name]", "yanglw");
// // repl0.put("[table-index1-bh]", "32");
// // repl0.put("[table-index1-sj]", "chenx");
//
//
// }
public void replaceTable(String[] placeholders, List> textToAdd) throws Exception {
List 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 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);
// }
// 我们现在的模板里面是个很复杂的表格, 首先我们要找到 模板行, 就是第一列是[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 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 tables, String templateKey) throws Docx4JException, JAXBException {
for (Iterator 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 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 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 pgReplacements) {
// TODO Auto-generated method stub
// paragraph
for (Map.Entry entry : pgReplacements.entrySet()) {
String placeholder = entry.getKey();
String textToAdd = (String) entry.getValue();
replaceParagraph(placeholder, textToAdd, template);
}
}
public void processTexts(Map replacements) {
// TODO Auto-generated method stub
// 进行文本占位符替换
for (Map.Entry 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 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;
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 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 map = new HashMap();
// 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 replacements = new HashMap();
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 repl1;
List> maplist=new ArrayList();
if(IdArray.length>0){
for(int i=0;i();
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 repl1 = new HashMap();
repl1.put("[sp]", "1");
repl1.put("[spnr]", "枪机");
Map repl2 = new HashMap();
repl2.put("[sp]", "2");
repl2.put("[spnr]", "枪机2");
Map repl3 = new HashMap();
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