java 通过模板替换pdf_java通过模板生成docx,docx再转pdf

这篇博客介绍了如何使用Java通过模板生成docx文档,然后将其转换为PDF。首先,通过Freemarker和XML处理将数据动态填入docx模板。接着,利用工具将docx转换为PDF。主要涉及的步骤包括:解压docx获取document.xml,使用Freemarker替换模板数据,重新打包docx,最后将docx转换为PDF。
摘要由CSDN通过智能技术生成

后面两篇对导出做出来改进以及详细操作:

第二篇:  java通过模板生成docx(2)

第三篇:java 导出word 利用freemarker指令更改xml 导出word docx文档 (3)

本篇思路:通过模板导出word doc容易,网上资料很多,大概就是将doc后缀改成xml文本打开通过freemarker指令标记${} 通过java代码动态写入。

导出docx用以上方法不行,docx本质为压缩文件,通过解压取出document.xml(和doc用xml打开中间部分一样) ,取出后修改在写入,生成docx 最后通过工具将docx 转成pdf

流程: docx文档------取出docx中的document.xml ---------xml中的数据替换

freemarker指令标记${}----------通过freemarker和map填充数据到xml ----------生成docx文件 --------------docx转pdf

1.

新建一个docx文档,放在D盘命名test_template.docx

2.用winrar打开

test_template.docx,取出word/document.xml

3.代码:这个类是把内容填充到xml

import freemarker.template.Configuration;

import freemarker.template.Template;

import freemarker.template.TemplateException;

import java.io.File;

import java.io.IOException;

import java.io.Writer;

import java.util.Map;

public class XmlTplUtil {

private static XmlTplUtil tplm = null;

private Configuration cfg = null;

private XmlTplUtil() {

cfg = new Configuration();

try {

// 注册tmlplate的load路径

// 这的路径是xml的路径

cfg.setDirectoryForTemplateLoading(new File("d:/"));

} catch (Exception e) {

}

}

private static Template getTemplate(String name) throws IOException {

if (tplm == null) {

tplm = new XmlTplUtil();

}

return tplm.cfg.getTemplate(name);

}

/**

*

* @param templatefile 模板文件

* @param param 需要填充的内容

* @param out 填充完成输出的文件

* @throws IOException

* @throws TemplateException

*/

public static void process(String templatefile, Map param, Writer out) throws IOException, TemplateException {

// 获取模板

Template template = XmlTplUtil.getTemplate(templatefile);

template.setOutputEncoding("UTF-8");

// 合并数据

template.process(param, out);

if (out != null) {

out.close();

}

}

}

4.xml转成docx

import freemarker.template.TemplateException;

import java.io.*;

import java.util.*;

import java.util.zip.ZipEntry;

import java.util.zip.ZipException;

import java.util.zip.ZipFile;

import java.util.zip.ZipOutputStream;

/**

* 其实docx属于zip的一种,这里只需要操作word/document.xml中的数据,其他的数据不用动

*

* @author

*

*/

public class XmlToDocx {

/**

*

* @param xmlTemplate xml的文件名

* @param docxTemplate docx的路径和文件名

* @param xmlTemp 填充完数据的临时xml

* @param toFilePath 目标文件名

* @param map 需要动态传入的数据

* @throws IOException

* @throws TemplateException

*/

public static void toDocx(String xmlTemplate, String docxTemplate,String xmlTemp ,String toFilePath,Map map) {

try {

// 1.map是动态传入的数据

Writer w = new FileWriter(new File(xmlTemp));

// 2.把map中的数据动态由freemarker传给xml

XmlTplUtil.process(xmlTemplate, map, w);

// 3.把填充完成的xml写入到docx中

XmlToDocx xtd = new XmlToDocx();

xtd.outDocx(new File(xmlTemp), docxTemplate, toFilePath);

}catch (Exception e) {

e.printStackTrace();

}

}

/**

*

* @param documentFile 动态生成数据的docunment.xml文件

* @param docxTemplate docx的模板

* @param toFilePath 需要导出的文件路径

* @throws ZipException

* @throws IOException

*/

public void outDocx(File documentFile, String docxTemplate, String toFilePath) throws ZipException, IOException {

try {

File docxFile = new File(docxTemplate);

ZipFile zipFile = new ZipFile(docxFile);

Enumeration extends ZipEntry> zipEntrys = zipFile.entries();

ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(toFilePath));

int len = -1;

byte[] buffer = new byte[1024];

while (zipEntrys.hasMoreElements()) {

ZipEntry next = zipEntrys.nextElement();

InputStream is = zipFile.getInputStream(next);

// 把输入流的文件传到输出流中 如果是word/document.xml由我们输入

zipout.putNextEntry(new ZipEntry(next.toString()));

if ("word/document.xml".equals(next.toString())) {

InputStream in = new FileInputStream(documentFile);

while ((len = in.read(buffer)) != -1) {

zipout.write(buffer, 0, len);

}

in.close();

} else {

while ((len = is.read(buffer)) != -1) {

zipout.write(buffer, 0, len);

}

is.close();

}

}

zipout.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

5.将docx 转pdf

import fr.opensagres.xdocreport.utils.StringUtils;

import org.apache.commons.collections.MapUtils;

import org.apache.poi.xwpf.converter.pdf.PdfConverter;

import org.apache.poi.xwpf.converter.pdf.PdfOptions;

import org.apache.poi.xwpf.usermodel.*;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

/**

* Created by dengxy on 2018/1/4.

*/

public class DocxToPdf {

protected static final Logger logger = LoggerFactory.getLogger(DocxToPdf.class);

/**

*

* @param docxFilepath docx文件

* @param outPdfpath 输出的PDF文件

* @throws Exception

*/

public static void toPdf(String docxFilepath,String outPdfpath) {

try {

InputStream source = new FileInputStream(docxFilepath);

OutputStream target = new FileOutputStream(outPdfpath);

Map params = new HashMap();

PdfOptions options = PdfOptions.create();

wordConverterToPdf(source, target, options, params);

}catch (Exception e) {

e.printStackTrace();

}

}

/**

* 将word文档, 转换成pdf, 中间替换掉变量

* @param source 源为word文档, 必须为docx文档

* @param target 目标输出

* @param params 需要替换的变量

* @throws Exception

*/

public static void wordConverterToPdf(InputStream source,OutputStream target, Map params) throws Exception {

wordConverterToPdf(source, target, null, params);

}

/**

* 将word文档, 转换成pdf, 中间替换掉变量

* @param source 源为word文档, 必须为docx文档

* @param target 目标输出

* @param params 需要替换的变量

* @param options PdfOptions.create().fontEncoding( "windows-1250" ) 或者其他

* @throws Exception

*/

public static void wordConverterToPdf(InputStream source, OutputStream target,PdfOptions options,Map params) throws Exception {

XWPFDocument doc = new XWPFDocument(source);

paragraphReplace(doc.getParagraphs(), params);

for (XWPFTable table : doc.getTables()) {

for (XWPFTableRow row : table.getRows()) {

for (XWPFTableCell cell : row.getTableCells()) {

paragraphReplace(cell.getParagraphs(), params);

}

}

}

PdfConverter.getInstance().convert(doc, target, options);

}

/** 替换段落中内容 */

private static void paragraphReplace(List paragraphs, Map params) {

if (MapUtils.isNotEmpty(params)) {

for (XWPFParagraph p : paragraphs){

for (XWPFRun r : p.getRuns()){

String content = r.getText(r.getTextPosition());

logger.info(content);

if(StringUtils.isNotEmpty(content) && params.containsKey(content)) {

r.setText(params.get(content), 0);

}

}

}

}

}

}

6.main方法测试

public static void main(String[] args) throws IOException, TemplateException {

try {

// xml的文件名

String xmlTemplate = "test.xml";

// docx的路径和文件名

String docxTemplate = "d:\\test_template.docx";

// 填充完数据的临时xml

String xmlTemp = "d:\\temp.xml";

// 目标文件名

String toFilePath = "d:\\test.docx";

// 1.map为需要动态传入的数据

//转Docx

XmlToDocx.toDocx(xmlTemplate, docxTemplate, xmlTemp, toFilePath, map);

//pdf文件

String outPdfFilePath = "test.pdf";

//docx 转pdf

DocxToPdf.toPdf(toFilePath,outPdfFilePath);

File file = new File(outPdfFilePath);

//删除docx文件

new File(toFilePath).delete();

//删除临时xml文件

new File(xmlTemp).delete();

return file;//返回pdf文件

} catch (Exception e) {

e.printStackTrace();

}

}

参考链接 ;http://blog.csdn.net/u010588262/article/details/53666644

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值