服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|JavaScript|易语言|

服务器之家 - 编程语言 - Java教程 - Java 实现word模板转为pdf

Java 实现word模板转为pdf

2021-08-08 14:42一个java小萌新的学习记录 Java教程

这篇文章主要介绍了Java 实现word模板转为pdf的方法,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下

1. pom相关依赖

工具poi-tl (操作word文档模板) + jacob (将操作后的word模板转为pdf)

?
1
2
3
4
5
6
<!-- poi-tl的pom依赖 -->
<dependency>
  <groupId>com.deepoove</groupId>
  <artifactId>poi-tl</artifactId>
  <version>1.9.1</version>
</dependency>
?
1
2
3
4
5
6
7
8
<!-- 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.

?
1
2
3
4
5
6
7
8
9
10
// 项目根路径
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需要操作的表格中的任意单元格添加标签“{{标签}}”

自定义渲染策略

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
 * 自定义渲染策略
 *
 * @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));
      }
    }
  }
}

把自定义渲染策略当做工具类, 在主逻辑中直接配置使用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  /**
 * 操作年度任务和考核指标表
 *
 * @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");
}

用到的一些实体类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 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文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*
  * 将 .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流将生成好的文件传到浏览器下载

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * 下载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整体代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
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的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/yoojyn/p/14386157.html

延伸 · 阅读

精彩推荐