评论

收藏

[Java] Java 实现word模板转为pdf

编程语言 编程语言 发布于:2021-09-12 12:03 | 阅读数:471 | 评论:0

这篇文章主要介绍了Java 实现word模板转为pdf的方法,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
1. pom相关依赖
工具poi-tl (操作word文档模板) + jacob (将操作后的word模板转为pdf)
<!-- poi-tl的pom依赖 -->
<dependency>
  <groupId>com.deepoove</groupId>
  <artifactId>poi-tl</artifactId>
  <version>1.9.1</version>
</dependency>
<!-- jacob的pom依赖(需自行导入.jar包) -->
<dependency>
  <groupId>com.jacob</groupId>
  <artifactId>jacob</artifactId>
  <version>1.17</version>
  <scope>system</scope>
  <systemPath>${project.basedir}/src/main/resources/lib/jacob.jar</systemPath>
</dependency>
2. 对word模板进行插入数据操作
使用poi-tl操作word需要创建一个用于向word插入数据的Map<String, Object>集合, word模板中标签格式为"{{标签}}", 其中标签内容为Map<String, Object> 的key.
// 项目根路径
String abPath = new File("").getAbsolutePath() + "/src/main/resources";
// 创建用于插入数据的Map
Map<String, Object> map = new HashMap<>();
map.put(<k>, <v>);
...
// 填充word文档
XWPFTemplate template = XWPFTemplate.compile(abPath + "<模板路径>").render(map);
// 输出文档
template.writeAndClose(new FileOutPutStream("<输出路径>"));
3. 对word模板的表格执行插入数据操作(动态表格)
使用poi-tl操作word的表格,动态的插入数据,需要用到poi-tl的可选插件进行自定义渲染策略, 首先在word需要操作的表格中的任意单元格添加标签“{{标签}}”
自定义渲染策略
/**
 * 自定义渲染策略
 *
 * @author 
 */
public class DetailTablePolicy extends DynamicTableRenderPolicy {
  // 表格起始行行数
  int tableStartRow = 1;
 
  /**
   * 自定义渲染策略
   *
   * @data 传入的封装好的数据
   */
  @Override
  public void render(XWPFTable table, Object data) throws Exception {
  // 如果数据为空,直接返回
  if (null == data) return;
  // 封装数据List的数据封装对象
  NdrwhkhzbData detailData = (NdrwhkhzbData) data;
    // 获取当前列表行高
  int height = table.getRow(2).getHeight();
  // 从封装对象中获取数据集合
  List<RowRenderData> datas = detailData.getNdrwhkhzbs();
  if (null != datas) {
    // 循环移除空白表格中数据数量的空白行
    for (int i = 1; i < datas.size() + 2; i++) {
    table.removeRow(i);
    }
    // 循环插入数据
    for (int i = 0; i < datas.size(); i++) {
    // 新增一行空白行
    XWPFTableRow insertNewTableRow = table.insertNewTableRow(tableStartRow);
    // 设置行高
    insertNewTableRow.setHeight(height);
    // 循环添加单元格(4为每行单元格数量)
    for (int j = 0; j < 4; j++) {
      insertNewTableRow.createCell();
    }
    // 填充表格
    TableRenderPolicy.Helper.renderRow(table.getRow(tableStartRow), datas.get(i));
    }
  }
  }
}
把自定义渲染策略当做工具类, 在主逻辑中直接配置使用
/**
 * 操作年度任务和考核指标表
 *
 * @throws IOException 输入输出流异常
 */
private void createNdrwhkhzb(Integer uid, String dirPath) throws IOException {
  PageData datas = new PageData();
  NdrwhkhzbData detailTable = new NdrwhkhzbData();
  List<RowRenderData> nds = new ArrayList<>();
  // 根据uid查询年度任务和考核指标数据
  List<NdrwhkhzbEntity> list = ndrwhkhzbService.selectNdrwhkhzbByUid(uid);
  for (NdrwhkhzbEntity ndrwhkhzbEntity : list) {
  RowRenderData rrd = Rows.of(ndrwhkhzbEntity.getNd(), ndrwhkhzbEntity.getNdrw(), ndrwhkhzbEntity.getNdkhzb()
    , ndrwhkhzbEntity.getZyrwdsjjd()).center().create();
  nds.add(rrd);
  }
  detailTable.setNdrwhkhzbs(nds);
  datas.setNdrwhkhzbData(detailTable);
 
  // 配置表格
  Configure config = Configure.builder().bind("detail_table", new DetailTablePolicy()).build();
  // 调用渲染策略进行填充
  XWPFTemplate template =
    XWPFTemplate.compile(dirPath + "/" + uid + "_Complete.docx", config).render(datas);
  // 写入表格中
  template.writeToFile(dirPath + "/" + uid + "_Complete.docx");
}
用到的一些实体类
// PageData
public class PageData {
  @Name("detail_table")
  private NdrwhkhzbData ndrwhkhzbData;
 
  public NdrwhkhzbData getNdrwhkhzbData() {
  return ndrwhkhzbData;
  }
 
  public void setNdrwhkhzbData(NdrwhkhzbData ndrwhkhzbData) {
  this.ndrwhkhzbData = ndrwhkhzbData;
  }
}
 
// NdrwhkhzbData
public class NdrwhkhzbData {
  private List<RowRenderData> ndrwhkhzbs;
 
  public List<RowRenderData> getNdrwhkhzbs() {
  return ndrwhkhzbs;
  }
 
  public void setNdrwhkhzbs(List<RowRenderData> ndrwhkhzbs) {
  this.ndrwhkhzbs = ndrwhkhzbs;
  }
}
4. 将编辑好的Word转为pdf格式(jacob)
这里将word转为pdf时需要用到jacob, 这里需要将jacob的dll文件放到jdk和jre的bin目录下, 下载的jacob中dll文件一般为两个版本, X86为32位, X64为64位, 根据自己安装的jdk版本添加所对应的dll文件
/*
  * 将 .docx 转换为 .pdf
  */
ActiveXComponent app = null;
String wordFile = dirPath + "/" + uid + "_Complete.docx";
String pdfFile = dirPath + "/" + dirName + ".pdf";
 
System.out.println("开始转换...");
// 开始时间
long start = System.currentTimeMillis();
try {
  // 打开word
  app = new ActiveXComponent("Word.Application");
  // 设置word不可见,很多博客下面这里都写了这一句话,其实是没有必要的,因为默认就是不可见的,如果设置可见就是会打开一个word文档,对于转化为pdf明显是没有必要的
  //app.setProperty("Visible", false);
  // 获得word中所有打开的文档
  Dispatch documents = app.getProperty("Documents").toDispatch();
  System.out.println("打开文件: " + wordFile);
  // 打开文档
  Dispatch documentP = Dispatch.call(documents, "Open", wordFile, false, true).toDispatch();
  // 如果文件存在的话,不会覆盖,会直接报错,所以我们需要判断文件是否存在
  File target = new File(pdfFile);
  if (target.exists()) {
  target.delete();
  }
  System.out.println("另存为: " + pdfFile);
  // 另存为,将文档报错为pdf,其中word保存为pdf的格式宏的值是17
  Dispatch.call(documentP, "SaveAs", pdfFile, 17);
  // 关闭文档
  Dispatch.call(documentP, "Close", false);
  // 结束时间
  long end = System.currentTimeMillis();
  System.out.println("转换成功,用时:" + (end - start) + "ms");
} catch (Exception e) {
  e.getMessage();
  System.out.println("转换失败" + e.getMessage());
} finally {
  // 关闭office
  app.invoke("Quit", 0);
}
5. 通过lo流将生成好的文件传到浏览器下载
/*
 * 下载pdf
 */
String fileName = dirName + ".pdf";
File file = new File(dirPath + "/" + fileName);
if (file.exists()) {
  BufferedInputStream bis = null;
  FileInputStream fis = null;
  try {
  response.setHeader("Content-disposition", "attachment; filename=" + fileName);
  byte[] buff = new byte[2048];
  fis = new FileInputStream(file);
  bis = new BufferedInputStream(fis);
  OutputStream os = response.getOutputStream();
  int i = bis.read(buff);
  while (i != -1) {
    os.write(buff, 0, i);
    i = bis.read(buff);
  }
  os.close();
  } catch (Exception e) {
  e.printStackTrace();
  } finally {
  assert fis != null;
  fis.close();
  assert bis != null;
  bis.close();
  }
}
6. 最后的Controller整体代码
package org.example.controller;
 
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.Includes;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.data.Rows;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import org.example.entity.*;
import org.example.service.*;
import org.example.utils.DetailTablePolicy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
 
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
/**
 * 创建pdf控制器
 *
 * @author: yoojyn
 * @data: 2021/1/11
 */
@Controller
@RequestMapping("/createPdfController")
public class CreatePdfController {
  @Autowired
  private IKtfmService ktfmService;
  @Autowired
  private IKtjbxxService ktjbxxService;
  @Autowired
  private IKtbyxfxService ktbyxfxService;
  @Autowired
  private IZtmbhkhzbService ztmbhkhzbService;
  @Autowired
  private INdrwhkhzbService ndrwhkhzbService;
  @Autowired
  private IKtjfysjsmService ktjfysjsmService;
  @Autowired
  private IXjxhkxxfxService xjxhkxxfxService;
 
  /**
   * 生成word文件
   *
   * @param session 作用域
   */
  @Scope("prototype")
  @ResponseBody
  @RequestMapping("/createPdf")
  public void createPdf(HttpSession session, HttpServletResponse response) {
  // 获取当前用户id
  Userinfo loginedUser = (Userinfo) session.getAttribute("loginedUser");
  Integer uid = loginedUser.getUid();
  String dirName = DigestUtils.md5DigestAsHex((uid + "_国家重大专项任务合同申报").getBytes());
  String dirPath = "D:/" + dirName;
  String abPath = new File("").getAbsolutePath() + "/src/main/resources";
 
  try {
    // 创建用于存储中间文件的文件夹
    new File(dirPath).mkdirs();
    // 创建用于存储数据的map集合
    Map<String, Object> map = new HashMap<>();
    // 获取封面数据
    createKtfm(uid, map);
    // 获取基本信息数据
    createJbxx(uid, map);
    // 获取必要性分析
    createByxfx(uid, map);
    // 获取总体目标和考核指标
    createZtmbhkhzb(uid, map);
    // 获取经费预算及说明
    createJfysjsm(uid, map);
    // 查询附件
    XjxhkxxfxEntity xjxhkxxfxEntity = xjxhkxxfxService.selectXjxhkxxfxByUid(uid);
    // 设置下一步处理表格要用到的标签
    map.put("page9",
      Includes.ofLocal(abPath + "/static/file/upload/" + xjxhkxxfxEntity.getFilename()).create());
    map.put("detail_table", "{{detail_table}}");
    // 填充文档
    XWPFTemplate template = XWPFTemplate.compile(abPath + "/static/file/moban/moban.docx").render(map);
    // 输出文档
    template.writeAndClose(new FileOutputStream(dirPath + "/" + uid + "_Complete.docx"));
    // 操作年度任务和考核指标表
    createNdrwhkhzb(uid, dirPath);
  } catch (IOException e) {
    e.printStackTrace();
  }
 
  try {
    /*
     * 将 .docx 转换为 .pdf
     */
    ActiveXComponent app = null;
    String wordFile = dirPath + "/" + uid + "_Complete.docx";
    String pdfFile = dirPath + "/" + dirName + ".pdf";
 
    System.out.println("开始转换...");
    // 开始时间
    long start = System.currentTimeMillis();
    try {
    // 打开word
    app = new ActiveXComponent("Word.Application");
    // 设置word不可见,很多博客下面这里都写了这一句话,其实是没有必要的,因为默认就是不可见的,如果设置可见就是会打开一个word文档,对于转化为pdf明显是没有必要的
    //app.setProperty("Visible", false);
    // 获得word中所有打开的文档
    Dispatch documents = app.getProperty("Documents").toDispatch();
    System.out.println("打开文件: " + wordFile);
    // 打开文档
    Dispatch documentP = Dispatch.call(documents, "Open", wordFile, false, true).toDispatch();
    // 如果文件存在的话,不会覆盖,会直接报错,所以我们需要判断文件是否存在
    File target = new File(pdfFile);
    if (target.exists()) {
      target.delete();
    }
    System.out.println("另存为: " + pdfFile);
    // 另存为,将文档报错为pdf,其中word保存为pdf的格式宏的值是17
    Dispatch.call(documentP, "SaveAs", pdfFile, 17);
    // 关闭文档
    Dispatch.call(documentP, "Close", false);
    // 结束时间
    long end = System.currentTimeMillis();
    System.out.println("转换成功,用时:" + (end - start) + "ms");
    } catch (Exception e) {
    e.getMessage();
    System.out.println("转换失败" + e.getMessage());
    } finally {
    // 关闭office
    app.invoke("Quit", 0);
    }
 
    /*
     * 下载pdf
     */
    String fileName = dirName + ".pdf";
    File file = new File(dirPath + "/" + fileName);
    if (file.exists()) {
    BufferedInputStream bis = null;
    FileInputStream fis = null;
    try {
      response.setHeader("Content-disposition", "attachment; filename=" + fileName);
      byte[] buff = new byte[2048];
      fis = new FileInputStream(file);
      bis = new BufferedInputStream(fis);
      OutputStream os = response.getOutputStream();
      int i = bis.read(buff);
      while (i != -1) {
      os.write(buff, 0, i);
      i = bis.read(buff);
      }
      os.close();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      assert fis != null;
      fis.close();
      assert bis != null;
      bis.close();
    }
    }
  } catch (Exception e) {
    e.printStackTrace();
  } finally {
    delDir(new File(dirPath));
  }
  }
 
  /**
   * 删除文件夹
   *
   * @param file 文件夹对象
   */
  private void delDir(File file) {
  if (file.isFile()) {
    file.delete();
  }
  if (file.isDirectory()) {
    File[] files = file.listFiles();
    for (File f : files) {
    f.delete();
    }
    file.delete();
  }
  }
 
  /**
   * 储存经费预算及说明
   *
   * @param uid 用户id
   * @param map 储存数据的map集合
   */
  private void createJfysjsm(Integer uid, Map<String, Object> map) {
  // 根据用户编号查询经费预算及说明
  KtjfysjsmEntity ktjfysjsmEntity = ktjfysjsmService.getDatesByUid(uid);
  // 添加到map集合
  map.put("zjzyczzj", ktjfysjsmEntity.getZjzyczzj());
  map.put("zjdfczzj", ktjfysjsmEntity.getZjdfczzj());
  map.put("zjdwzczj", ktjfysjsmEntity.getZjdwzczj());
  map.put("zjqt", ktjfysjsmEntity.getZjqt());
  }
 
  /**
   * 操作年度任务和考核指标表
   *
   * @throws IOException 输入输出流异常
   */
  private void createNdrwhkhzb(Integer uid, String dirPath) throws IOException {
  PageData datas = new PageData();
  NdrwhkhzbData detailTable = new NdrwhkhzbData();
  List<RowRenderData> nds = new ArrayList<>();
  // 根据uid查询年度任务和考核指标数据
  List<NdrwhkhzbEntity> list = ndrwhkhzbService.selectNdrwhkhzbByUid(uid);
  for (NdrwhkhzbEntity ndrwhkhzbEntity : list) {
    RowRenderData rrd = Rows.of(ndrwhkhzbEntity.getNd(), ndrwhkhzbEntity.getNdrw(), ndrwhkhzbEntity.getNdkhzb()
      , ndrwhkhzbEntity.getZyrwdsjjd()).center().create();
    nds.add(rrd);
  }
  detailTable.setNdrwhkhzbs(nds);
  datas.setNdrwhkhzbData(detailTable);
 
  Configure config = Configure.builder().bind("detail_table", new DetailTablePolicy()).build();
  XWPFTemplate template =
    XWPFTemplate.compile(dirPath + "/" + uid + "_Complete.docx", config).render(datas);
  template.writeToFile(dirPath + "/" + uid + "_Complete.docx");
  }
 
  /**
   * 储存总体目标和考核指标
   *
   * @param uid 用户id
   * @param map 储存数据的map集合
   */
  private void createZtmbhkhzb(Integer uid, Map<String, Object> map) {
  // 根据用户编号查询总体目标和考核指标
  ZtmbhkhzbEntity ztmbhkhzbEntity = ztmbhkhzbService.selectZtmbhkhzbByUid(uid);
  // 添加到map集合
  map.put("page6", ztmbhkhzbEntity.getZtmbhkhzb());
  }
 
  /**
   * 储存必要性分析数据
   *
   * @param uid 用户id
   * @param map 储存数据的map集合
   */
  private void createByxfx(Integer uid, Map<String, Object> map) {
  // 根据用户编号查询必要性分析数据
  KtbyxfxEntityWithBLOBs ktbyxfxEntity = ktbyxfxService.selectKtbyxfxByUid(uid);
  // 添加到map集合
  map.put("page5_ktyzx", ktbyxfxEntity.getKtyzx());
  map.put("page5_ktysfgc", ktbyxfxEntity.getKtysf());
  map.put("page5_ktyq", ktbyxfxEntity.getKtyq());
  }
 
  /**
   * 储存基本信息数据
   *
   * @param uid 用户编号
   * @param map 储存数据的map集合
   */
  private void createJbxx(Integer uid, Map<String, Object> map) {
  // 根据用户编号查询基本信息数据
  KcjbxxEntity kcjbxxEntity = ktjbxxService.selectKtjbxxByUid(uid);
  // 添加到map集合
  map.put("page3_ktmc", kcjbxxEntity.getKtmc());
  map.put("page3_ktmj", kcjbxxEntity.getKtmj());
  map.put("page3_yjwcsj", kcjbxxEntity.getYjwcsj());
  map.put("page3_kyhdlx", kcjbxxEntity.getKthdlx());
  map.put("page3_yqcglx", kcjbxxEntity.getYqcglx());
  map.put("page3_dwmc", kcjbxxEntity.getDwmc());
  map.put("page3_dwxz", kcjbxxEntity.getDwxz());
  map.put("page3_txdz", kcjbxxEntity.getTxdz());
  map.put("page3_yzbm", kcjbxxEntity.getYzbm());
  map.put("page3_szdq", kcjbxxEntity.getSzdq());
  map.put("page3_dwzgbm", kcjbxxEntity.getDwzgbm());
  map.put("page3_lxdh", kcjbxxEntity.getLxdh());
  map.put("page3_zzjgdm", kcjbxxEntity.getZzjgdm());
  map.put("page3_czhm", kcjbxxEntity.getCzhm());
  map.put("page3_dwclsj", kcjbxxEntity.getDwclsj());
  map.put("page3_dzxx", kcjbxxEntity.getDzxx());
  }
 
  /**
   * 储存课题封面数据
   *
   * @param uid 用户编号
   * @param map 储存数据的map集合
   */
  private void createKtfm(Integer uid, Map<String, Object> map) {
  // 根据用户编号查询封面数据
  KtfmEntity ktfmEntity = ktfmService.selectKtfmByUid(uid);
  // 添加到map集合
  map.put("page1_zxmc", "5G总体及关键器件");
  map.put("page1_xmbh", "2016ZX03001_001");
  map.put("page1_xmmc", "新一代宽带无线移动通信网");
  map.put("page1_ktbh", "2016ZX03001_001_002");
  map.put("page1_ktmc", "5G高性能基站A/D、D/A转换器试验样片研发");
  map.put("page1_zrdw", "program_test");
  map.put("page1_ktzz", ktfmEntity.getKtfzr());
  map.put("page1_ktnx1", "2016-01-01");
  map.put("page1_ktnx2", "2017-12-31");
  map.put("page1_tbrq", "2020-12-28");
  map.put("page1_nian", "二一");
  map.put("page1_yue", "一");
  }
 
}
以上就是Java 实现word模板转为pdf的详细内容,更多关于Java word模板转为pdf的资料请关注CodeAE代码之家其它相关文章!
原文链接:https://www.cnblogs.com/yoojyn/p/14386157.html

关注下面的标签,发现更多相似文章