freemarker、docx4j 模板导出word 和 PDF文档

前期准备

freemarker相关jar包
	<dependency>
		<groupId>org.freemarker</groupId>
		<artifactId>freemarker</artifactId>
		<version>2.3.23</version>
	</dependency>
	<dependency>
		<groupId>org.xhtmlrenderer</groupId>
		<artifactId>flying-saucer-pdf</artifactId>
		<version>9.1.19</version>
	</dependency>
	<dependency>
		<groupId>org.apache.logging.log4j</groupId>
		<artifactId>log4j-core</artifactId>
		<version>2.12.1</version>
	</dependency>
docx4j相关jar包
	<dependency>
		<groupId>org.docx4j</groupId>
		<artifactId>docx4j</artifactId>
		<version>3.3.7</version>
	</dependency>
	<dependency>
		<groupId>org.apache.xmlgraphics</groupId>
		<artifactId>batik-util</artifactId>
		<version>1.10</version>
	</dependency>
	<dependency>
		<groupId>org.docx4j</groupId>
		<artifactId>docx4j-export-fo</artifactId>
		<version>3.3.6</version>
	</dependency>

模板文件制作(后缀为.ftl)

1、在word文档中编写你想要的文档,并在相应位置设置变量向相应位置填写变量
2、将word文档另存为xml格式
另存图片为xml格式
3、用编辑器检查XML中变量是否混乱(建议先格式化xml文件)

部分变量会被分割成字符串,例如:

在这里插入图片描述
这种情况直接删除变量中间的标签,修改后为:在这里插入图片描述
将所有变量都检查完毕后,将xml文件直接重命名为后缀为 ftl 的文件
例:普通模板.xml ——>> 普通模板.ftl

将模板文件放置到resources包下
在这里插入图片描述

工具类

package zyxhj.utils;

import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;

import org.docx4j.Docx4J;
import org.docx4j.convert.out.FOSettings;
import org.docx4j.fonts.IdentityPlusMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.fonts.PhysicalFonts;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.Version;
import sun.misc.BASE64Encoder;

/**
 * 
 * @author JXians 模板导出word文档与PDF文档
 *
 */
public class ExportOfficeUtils {

	private static Configuration config = null;
	static {
		config = new Configuration(new Version("2.3.0"));
		config.setClassForTemplateLoading(ExportOfficeUtils.class, "/template/");
		config.setDefaultEncoding("UTF-8");
	}

	/**
	 * 获取配置对象
	 * 
	 * @return
	 */
	public static Configuration getConfiguration() {
		return config;
	}

	/**
	 * 合成数据与模板
	 * 
	 * @param template 模板名称
	 * @param obj      模板需要填入的值
	 */
	public static String generate(String templateName, Object obj) throws IOException, TemplateException {
		Configuration config = getConfiguration();
		Template template = config.getTemplate(templateName, "utf-8");
		StringWriter stringWriter = new StringWriter();
		BufferedWriter writer = new BufferedWriter(stringWriter);
		template.process(obj, writer);
		String htmlStr = stringWriter.toString();
		writer.flush();
		writer.close();
		return htmlStr;
	}

	/**
	 * 根据模板生成word文档
	 * 
	 * @param templateName   模板名称
	 * @param dataMap        模板需求数据
	 * @param OutputFilePath 生成文件存放地址
	 */
	public static void generateWORD(String templateName, Map<String, Object> dataMap, String OutputFilePath) {
		try {
			// Configuration 用于读取ftl文件
			Configuration configuration = getConfiguration();
			// 输出文档路径及名称
			File outFile = new File(OutputFilePath);
			Template template = configuration.getTemplate(templateName, "utf-8");
			Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"), 10240);
			template.process(dataMap, out);
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 生成pdf文档
	 * 
	 * @param templateName 模版文件
	 * @param obj          数据
	 * @param os           输出流
	 * @throws Exception 
	 */
	public static void generatePDF(String templateName, Map<String, Object> dataMap, String PDFoutputFilePath)
			throws Exception {
		// 合并模板和数据模型 word doc os = ftl + obj
		String generate = ExportOfficeUtils.generate(templateName, dataMap);
		ByteArrayInputStream in = new ByteArrayInputStream(generate.getBytes());
		// 文字处理对象
		WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(in);
		// wordMLPackage -> pdf os
		FOSettings foSettings = Docx4J.createFOSettings();
		Mapper fontMapper = new IdentityPlusMapper();
        fontMapper.put("华文楷体", PhysicalFonts.get("STKaiti"));
        fontMapper.put("隶书", PhysicalFonts.get("LiSu"));
        fontMapper.put("宋体", PhysicalFonts.get("SimSun"));
        fontMapper.put("微软雅黑", PhysicalFonts.get("Microsoft Yahei"));
        fontMapper.put("黑体", PhysicalFonts.get("SimHei"));
        fontMapper.put("楷体", PhysicalFonts.get("KaiTi"));
        fontMapper.put("新宋体", PhysicalFonts.get("NSimSun"));
        fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai"));
        fontMapper.put("华文仿宋", PhysicalFonts.get("STFangsong"));
        fontMapper.put("仿宋", PhysicalFonts.get("FangSong"));
        fontMapper.put("幼圆", PhysicalFonts.get("YouYuan"));
        fontMapper.put("华文宋体", PhysicalFonts.get("STSong"));
        fontMapper.put("华文中宋", PhysicalFonts.get("STZhongsong"));
        fontMapper.put("等线", PhysicalFonts.get("SimSun"));
        fontMapper.put("等线 Light", PhysicalFonts.get("SimSun"));
        fontMapper.put("华文琥珀", PhysicalFonts.get("STHupo"));
        fontMapper.put("华文隶书", PhysicalFonts.get("STLiti"));
        fontMapper.put("华文新魏", PhysicalFonts.get("STXinwei"));
        fontMapper.put("华文彩云", PhysicalFonts.get("STCaiyun"));
        fontMapper.put("方正姚体", PhysicalFonts.get("FZYaoti"));
        fontMapper.put("方正舒体", PhysicalFonts.get("FZShuTi"));
        fontMapper.put("华文细黑", PhysicalFonts.get("STXihei"));
        fontMapper.put("宋体扩展",PhysicalFonts.get("simsun-extB"));
        fontMapper.put("仿宋_GB2312",PhysicalFonts.get("FangSong_GB2312"));
        fontMapper.put("新細明體",PhysicalFonts.get("SimSun"));
        //解决宋体(正文)和宋体(标题)的乱码问题
        PhysicalFonts.put("PMingLiU", PhysicalFonts.get("SimSun"));
        PhysicalFonts.put("新細明體", PhysicalFonts.get("SimSun"));
		
        wordMLPackage.setFontMapper(fontMapper);
        
		foSettings.setWmlPackage(wordMLPackage);
		foSettings.setApacheFopMime("application/pdf");
		Docx4J.toPDF(wordMLPackage, new FileOutputStream(PDFoutputFilePath));
	}

	/**
	 * 图片转码
	 */
	public static String getImageStr(String imgpath) {
		InputStream in = null;
		byte[] data = null;
		try {
			in = new FileInputStream(imgpath);
			data = new byte[in.available()];
			in.read(data);
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		BASE64Encoder encoder = new BASE64Encoder();
		return encoder.encode(data);
	}

}

主类

public static void main(String[] args) throws Exception {
	Map<String, Object> map = new HashMap<String, Object>();
	map.put("clientName", "JXians");
	map.put("deputyApplicantName", "JXians_NAS");
	map.put("address", "贵州遵义");
	map.put("phone","18685644226");
	map.put("Email", "zheng_xing_jiang@163.com");
	map.put("onAddress", "贵州遵义");
	map.put("onshore", " ");
	map.put("offshore", "√");
	map.put("intermediary", "中介代理人");
	map.put("marn","NBS_0989");
	map.put("visasType","移民签证");
	map.put("contractMoney","1000.00");
	map.put("advance", "500.00");
	map.put("interEmail", "187263542@qq.com");
	map.put("clientEmail", "27384922@qq.com");
	map.put("interTime", new SimpleDateFormat("yyyy年MM月dd日").format(new Date()));
	map.put("clientTime", new SimpleDateFormat("yyyy年MM月dd日").format(new Date()));
	map.put("img", ExportOfficeUtils.getImageStr("C:/Users/Admin/Desktop/111.img"));
	//模板文件名称
	String templateName = "普通合同.ftl";
	String PDFoutputFilePath = "C:/Users/Admin/Desktop/PDF_测试.pdf";
	String WORDoutputFilePath = "C:/Users/Admin/Desktop/WORD_测试.doc";
	ExportOfficeUtils.generatePDF(templateName, map, PDFoutputFilePath);
	ExportOfficeUtils.generateWORD(templateName, map, WORDoutputFilePath);
}

注:部分中文字体无法转换成PDF文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值