java动态生成word文档

一、动态模板处理

使用jar包以及工具,freemark.jar notepad++
1.在word中需要动态填充的地方写上变量名(填充的数据为map,写的变量为map的key),例如动态生成简历模板中在对应的姓名列中写入name,涉及到循环的地方只需要写一行,涉及到图片,先随便找一张图片放在需要动态显示的地方。这里的name在后续需要改成${name},有些资料提到可以在这一步骤的时候就写成${name},但是在使用过程中发现${name}会在另存为xml格式文件的时候会分开,反而增加工作量,因此建议使用name,而不是${name}
2.将word另存为xml
3.在安装notepad++插件用于后续替换处理:使用Notepad++的XML Tools插件格式化XML文件_notepad++ xml-CSDN博客
4.在notepad++中打开xml
5.如果有图片处理,搜索<pkg:binaryData>、</pkg:binaryData>并将其中间内容替换为<pkg:binaryData>${img}</pkg:binaryData>,其中img为map中存储图片数据的key,图片的数据处理后续会提到。
6.选择 插件 - XML Tools - Pretty print(XML only - with line breaks)格式化xml文件
7.将模板中需要动态填充的数据用${key}替换,例如,name用${name}替换,如果有循环的地方,找到需要循环填充数据的地方在<w:tr w:rsidR="00642C40" w:rsidRPr="00667E05" w:rsidTr="00EB5C66">上写<#list workList2 as worklist>
用${worklist.workName}替换需要遍历的变量,在标记的结尾添加</#list>
8.替换完成后点击另存为.ftl格式的文件,保存可能报错“XML Parsing error at line 707:Extra content at the end of the document”,忽略。
这个时候动态模板就创建好了,下面是动态数据的处理

二、填充数据处理

数据存储在Map<String, Object>中,主要说下图片数据的处理,list数据存储在List<Object>中,其中Object为实体类。

图片处理

package cn.com.xyl;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import sun.misc.BASE64Encoder;
/**
 * 填充动态word的图片数据处理示例
 * @author xuyl 2018-3-20 下午3:47:33
 *
 */
public class ImageHandle {
	public static void main(String[] args) {
		File file = new File("C:\\Users\\xuyl\\Desktop\\===temp===\\Hydrangeas.jpg");
		InputStream is = null;
		ByteArrayOutputStream out = null;
		String rst = "";
		try {
			is = new FileInputStream(file);
			out = new ByteArrayOutputStream();
			//将图片写入out中
			byte[] b = new byte[1024];
			int i = 0;
			while((i = is.read(b)) != -1){
				out.write(b, 0, i);
	        }
			//对out流做base64处理
			BASE64Encoder encoder = new BASE64Encoder();
			rst = encoder.encode(out.toByteArray());
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		System.out.println(rst);
	}
}

三、根据模板和数据生成动态模板

package cn.com.xy.servlet;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.com.jnpc.utils.CommonUtils;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;

public class CreateDynamicWord extends HttpServlet{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,
		IOException {
		try {
			//1.创建word获取填充信息
			createDoc("/cn/com/xyl/signTableTemp", "signTable.ftl", new HashMap<String, Object>(), "tempSignTable", request);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
     * 根据Doc模板生成word文件
     * @param templatePath	ftl放的路径		放在包resumeTemplate下,为包的全路径/cn/com/xyl/signTableTemp
     * @param fileName 		flt模板名称包含扩展名	signTable.ftl		
     * @param tempData 		需要填入模板的数据
     * @param savePath 		生成的word保存的文件夹	可以放在盘符中例如D:\\leaderResume\
     * 											可以放在项目文件中 
     * 											WebRoot/leaderResume/eachLeaderResume 要在eachLeaderResume文件夹下新建一个空的文件,否则会报错
     */
    public void createDoc(String templatePath, String fileName, Map<String,Object> tempData, String savePath, HttpServletRequest request) throws Exception{
    	//模板配置
    	Configuration configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
    	//模板对象
        Template template = null;
        //加载模板文件
        configuration.setClassForTemplateLoading(this.getClass(), templatePath);
        //设置异常处理器
        configuration.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
        //定义Template对象,注意模板类型名字与fileName要一致
        template = configuration.getTemplate(fileName);
        String realFileName = tempData.get("meetingName") + getCurrentTime() +  ".doc";
        System.out.println("========realFileName===========" + realFileName);
        request.setAttribute("FILE_NAME", realFileName);
        String tempSavePath = CommonUtils.getWebInfFilePath(savePath) + realFileName;
        File outFile = new File(tempSavePath);
        Writer out = null;
        out=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"));
        template.process(tempData, out);
        out.close();
    }
    public static String getCurrentTime(){
		String str = "";
		Date date = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		str = sdf.format(date);
		return str;
	}
}

至此就在生成了动态word,可以将路径返回到前台,然后下载或其他处理

================================

2019-04-11补充

再word使用变量填充模板时,可以直接加上${},如姓名一列${name},这里需要注意,如果直接写在word中,在转化为xml文件时$,{,}可能会分开,这样反而会更麻烦。可以这样处理,可以先写在notepad++中,然后直接拷贝过去即可。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值