JAVA下载word(可保留模板样式)

本文讲述读取word模板的制作和模板读取动态插入数据生成word

1.首先制作模板

找我们需要的word模板文件,打开他,然后选另存为,保存成XML格式
在这里插入图片描述
在这里插入图片描述
然后用Notepad++打开对应的XML,用XML Tools插件序列化数据(插件下载地址: 点这.)
在这里插入图片描述
序列化后处理数据占位符,删除${}包裹的中间不需要的格式标签字符.在这里插入图片描述
然后保存,模板制作完成.

2.数据结合模板调用API生成文档实现下载

步骤大致如下:
1.设置下载响应头
2.处理数据,数据格式一般为Map<String,Object>格式
3.调用 freemarker的API方法完成下载.
参考代码如下:

//controller部分
  @RequestMapping(value = "download/{caseId}", method = RequestMethod.GET)
  public void downloadSimilarCase(HttpServletRequest request, HttpServletResponse response,
      @RequestParam(value = "caseNo", required = false, defaultValue = "") String caseNo,
      @PathVariable("caseId") String caseId) throws UnsupportedEncodingException {

    // 文件名
    caseNo = URLDecoder.decode(caseNo, "utf-8");
    String fileName = AppUtils.encodeFileName(request.getHeader("User-Agent"), caseNo + ".doc");

    service.getSimilarCaseById(response, caseId, fileName);
  }
//service实现部分
 public void getSimilarCaseById(HttpServletResponse response, String caseId, String fileName) {
    //response.setContentType("application/vnd.ms-word;charset=UTF-8");
    response.setContentType("application/msword;charset=UTF-8");
    response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
    response.setHeader("Content-Type", "application/force-download");
    response.setCharacterEncoding("utf-8");
 //condition 为动态写入的数据,他的键是占位符${}中介的字符,他的值就是对应需要替换改占位符的数据
    Map<String, Object> condition = new HashMap<>();
    condition.put("caseId", caseId);
    Object result = getSimilarCaseById(condition);//调用方法获取数据,具体内容无需展开,自己按自己需求处理数据为Map<String, Object>格式即可
    Map<String, Object> lawCase = null;
    if(result instanceof Map) {
      lawCase = (Map<String, Object>)result;
    }
    //这是清理脏数据的,如果你动态写入的内容里有一些特殊字符比如&,#等,可能会导致生成的文档无法打开,所以这里进行处理下
    removeSpecChar(lawCase);
    //这里就是拿处理好的数据和response相应流去实现浏览器响应下载,具体后面会展开说
    CaseDocXmlUtils.create(response, lawCase);
  }
// CaseDocXmlUtils.create(response, lawCase)方法详细内容
package com.futuredata.court.guide.web.util;

import com.futuredata.base.core.config.AppConfig;
import com.futuredata.base.core.util.AppUtils;
import com.futuredata.base.core.util.ZipUtils;

import com.futuredata.court.guide.web.model.LawsuitInfo;
import freemarker.template.Configuration;
import freemarker.template.Template;

import org.apache.commons.io.FileUtils;
import org.apache.http.util.TextUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletResponse;

public class CaseDocXmlUtils {

  private static final Logger logger = LoggerFactory.getLogger(CaseDocXmlUtils.class);

  private static final String REG_LAW_TAG = "<\\s*/?law([^>]*)>";

  private static Configuration configuration = null;

  static {
    configuration = new Configuration();
    configuration.setDefaultEncoding("utf-8");
    //通过这个工具类的相对路径去找到存放模板xml的路径并读取
    configuration.setClassForTemplateLoading(ReportUtils.class, "/template/");
  }


  public static void create(HttpServletResponse response, Map<String, Object> content) {
    PrintWriter pw = null;
    try {
      pw = response.getWriter();
      //这个是对数据的加工,本来data里面的值就是普通字符串文字,这里可以通过给文字加上一些word里面的xml标签,来实现文字样式格式的变化,这里具体不展开,插入的标签我举个例子,如下一个代码块里面的两个方法
      Map<String, Object> data = getCaseDocData(content);
      Template template = configuration.getTemplate((String)data.get("template"));
      template.process(data, pw);
    } catch (Exception ex) {
      logger.error("生成word报表发生错误", ex);
    } finally {
      if (pw != null) {
        pw.close();
      }
    }
  }
  }

//这就是给文字加样式格式的方法,将文字content加上上面标签再返回,到时候这一大串都会替换原来的占位符,成功进入xml文档,然后就能样式和文字生效展示
/**
   * word换行.
   */
//  private static String getWordText(String content) {
//    return "<w:p>" + "<w:pPr>"
//        + "<w:spacing w:before='100' w:after='100' w:line='380' w:lineRule='exact'/>"
//        + "<w:ind w:firstLine='632'/>" + "<w:jc w:val='both'/>" + "<w:rPr>"
//        + "<w:rFonts w:ascii='宋体' w:eastAsia='宋体' w:hAnsi='宋体' w:cs='宋体'/><w:color w:val='000000'/>"
//        + "<w:sz w:val='28'/>" + "<w:u w:val='single'/>" + "</w:rPr>" + "</w:pPr>" + "<w:r>"
//        + "<w:rPr>"
//        + "<w:rFonts w:ascii='宋体' w:eastAsia='宋体' w:hAnsi='宋体' w:cs='宋体' w:hint='eastAsia'/><w:color w:val='000000'/>"
//        + "<w:sz w:val='28'/>" + "</w:rPr>" + "<w:t>" + content + "</w:t>" + "</w:r>"
//        + "<w:bookmarkStart w:id='0' w:name='_GoBack'/>" + "<w:bookmarkEnd w:id='0'/>" + "</w:p>";
//  }

  private static String getWordText(String content) {
    return "<w:p><w:pPr><w:ind w:first-line='600'/><w:jc w:val='left'/></w:pPr><w:r><w:rPr>"
        + "<w:rFonts w:ascii='宋体' w:eastAsia='宋体' w:hAnsi='宋体' w:cs='宋体'/><w:color w:val='000000'/>"
        + "<w:sz w:val='32'/></w:rPr><w:t>"
        + content + "</w:t></w:r></w:p>";
  }

  /**
   * word换行. 文字居右
   * @param content
   * @return
   */
  private static String getWordTextRight(String content) {
    return "<w:p>" + "<w:pPr>"
        + "<w:spacing w:before='100' w:after='100' w:line='380' w:lineRule='exact'/>"
        + "<w:jc w:val='right'/>" + "<w:rPr>"
        + "<w:rFonts w:ascii='宋体' w:eastAsia='宋体' w:hAnsi='宋体' w:cs='宋体'/><w:color w:val='000000'/>"
        + "<w:sz w:val='32'/>" + "<w:u w:val='single'/>" + "</w:rPr>" + "</w:pPr>" + "<w:r>"
        + "<w:rPr>"
        + "<w:rFonts w:ascii='宋体' w:eastAsia='宋体' w:hAnsi='宋体' w:cs='宋体' w:hint='eastAsia'/><w:color w:val='000000'/>"
        + "<w:sz w:val='32'/>" + "</w:rPr>" + "<w:t>" + content + "</w:t>" + "</w:r>"
        + "<w:bookmarkStart w:id='0' w:name='_GoBack'/>" + "<w:bookmarkEnd w:id='0'/>" + "</w:p>";
  }

**结尾:**不知不觉写的有点啰嗦可能还不清晰哎,就先这样把,不懂可以留言问我,欢迎交流.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值