Java读取Excel并生成Word&PDF

心已赠人 2024-04-01 16:14 260阅读 0赞
  1. 最近需要用Java处理Excel中的数据,并生成wordpdf格式的文档(其中wordpdf需要带背景图),所以在这里做下总结。
  2. 使用技术:FreeMarker + easyexcel + jacob
  3. FreeMarker大家应该会比较熟悉,一个模板引擎。
  4. easyexcel 是阿里巴巴开源,用于快速、简单避免OOMjava处理Excel工具。
  5. JACOB是一个JAVA-COM Bridge,允许您从Java调用COM Automation组件。它使用JNICOMWin32库进行本机调用。
  6. 使用easyexcel处理excel
  7. import com.alibaba.excel.annotation.ExcelProperty;
  8. import com.alibaba.excel.metadata.BaseRowModel;
  9. import lombok.AllArgsConstructor;
  10. import lombok.Data;
  11. import lombok.NoArgsConstructor;
  12. /**
  13. * JavaBean与Excel之间的关系映射
  14. */
  15. @Data
  16. @NoArgsConstructor
  17. @AllArgsConstructor
  18. public class ERReport extends BaseRowModel {
  19. @ExcelProperty(value = "省", index = 0)
  20. private String province;
  21. @ExcelProperty(value = "市", index = 1)
  22. private String city;
  23. @ExcelProperty(value = "学校", index = 2)
  24. private String school;
  25. @ExcelProperty(value = "班级", index = 3)
  26. private String classs;
  27. @ExcelProperty(value = "老师", index = 4
  28. private String teacher;
  29. }
  30. import com.alibaba.excel.context.AnalysisContext;
  31. import com.alibaba.excel.event.AnalysisEventListener;
  32. import com.alibaba.excel.metadata.BaseRowModel;
  33. import com.google.common.collect.Lists;
  34. /**
  35. * 自定义Listener继承AnalysisEventListener,重写invoke方法,为了方便获取值,添加了一个getData的方法
  36. */
  37. public class ExcelListener<T extends BaseRowModel> extends AnalysisEventListener<T> {
  38. private final List<T> data = Lists.newArrayList();
  39. @Override
  40. public void invoke(T t, AnalysisContext analysisContext) {
  41. data.add(t);
  42. }
  43. @Override
  44. public void doAfterAllAnalysed(AnalysisContext analysisContext) {
  45. }
  46. public List<T> getData(){
  47. return data;
  48. }
  49. public class ExcelUtils {
  50. /**
  51. * 读取excel的方法
  52. */
  53. public static <T extends BaseRowModel> List<T> readExcel(final InputStream inputStream, final Class<? extends BaseRowModel> clazz) {
  54. if (null == inputStream) {
  55. throw new NullPointerException("the inputStream is null!");
  56. }
  57. AnalysisEventListener listener = new ExcelListener();
  58. ExcelReader reader = new ExcelReader(inputStream, null, listener);
  59. reader.read(new com.alibaba.excel.metadata.Sheet(1, 1, clazz));
  60. return ((ExcelListener) listener).getData();
  61. }
  62. public static void main(String[] args) throws Exception {
  63. String filePath = "C:\\Users\\Administrator\\Desktop\\test.xlsx";
  64. List<ERReport> datas = ExcelUtils.readExcel(new FileInputStream(new File(filePath)), ERReport.class);
  65. datas.forEach(System.out::println);
  66. }

新建一个word文件,把固定不变的地方写好,将要替换的值改用${xxx}占位符的方式,然后把后缀

名改为.ftl。(注:如果此条路行不通,可以先将word另存为xml文件,再将xml转为ftl格式),放到

项目的resource/templates目录下,便于读取。

在这里插入图片描述

如果需要设置图片,打开ftl文件后,搜索<w:binData></w:binData>标签(我用的是wps,如果是

office word,可能并不一定是这个标签),这里正常显示的会是一长串base64编码后的字符串。因

为这里我需要替换图片,所以用了占位符。

在这里插入图片描述

  1. 转为word的代码如下:
  2. import freemarker.template.Configuration;
  3. import freemarker.template.Template;
  4. import freemarker.template.TemplateException;
  5. import sun.misc.BASE64Encoder;
  6. import java.io.*;
  7. import java.util.HashMap;
  8. import java.util.Map;
  9. public class WordUtils {
  10. public static void main(String[] args) throws Exception {
  11. String imgPath = "C:\\Users\\Administrator\\Desktop\\timg.jpg";
  12. BASE64Encoder encoder = new BASE64Encoder();
  13. String imgStr = encoder.encode(encode(imgPath));
  14. System.out.println(imgStr);
  15. // 这里只是一个示例,key=value的格式,这里的key对应的ftl文件占位符{}中的字符串。
  16. Map<String, Object> dataMap = new HashMap<String, Object>() {
  17. {
  18. put("imgStr",imgStr);
  19. put("province","北京市");
  20. put("city","海淀区");
  21. put("school","");
  22. put("class","二三班");
  23. }};
  24. //处理excel,将其中的数据填充至模板中,最后生成word。
  25. List<ERReport> datas = ExcelUtils.readExcel(new FileInputStream(new File(filePath)), ERReport.class);
  26. datas.forEach((ERReport e) -> {
  27. try {
  28. processTemplate(e, Your File Name”);
  29. System.out.println("转换成功");
  30. } catch (Exception ex) {
  31. LOGGER.error("Excel转换Word错误.", ex);
  32. }
  33. });
  34. }
  35. private static byte[] encode(String imagePath) throws IOException {
  36. InputStream in = null;
  37. byte[] data = null;
  38. try {
  39. in = new FileInputStream(imagePath);
  40. data = new byte[in.available()];
  41. in.read(data);
  42. in.close();
  43. } catch (Exception e) {
  44. e.printStackTrace();
  45. } finally {
  46. if (in != null) {
  47. in.close();
  48. }
  49. return data;
  50. }
  51. }
  52. public static void processTemplate(Object dataMap, String fileName) throws IOException, TemplateException {
  53. Configuration configuration = new Configuration();
  54. configuration.setDefaultEncoding("utf-8");
  55. configuration.setClassForTemplateLoading(WordUtils.class, "/templates");
  56. Template template = configuration.getTemplate("template.ftl");
  57. File file = new File("C:\\Users\\Administrator\\Desktop\\" + fileName + ".docx");
  58. BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "utf-8"));
  59. template.process(dataMap, bufferedWriter);
  60. }
  61. }

word转pdf(使用jacob)

  1. 所需依赖我放在百度云盘上了,如果有用到的朋友遇到问题,可以来微博或者github上面找我: https://pan.baidu.com/s/1uV54gViWt9x3eDYB0OAM0w 提取码: yy95
  2. 解压后会是下图所示,将两个dll文件放在jdkbin目录下, jacob.jar导入项目中。

20190325163201276.png

  1. wordpdf的代码如下:
  2. public class PDFUtils {
  3. public static void main(String[] args) {
  4. String wordFile = "C:\\Users\\Administrator\\Desktop\\二年级五班.docx";
  5. String pdfFile = "C:\\Users\\Administrator\\Desktop\\二年级五班.pdf";
  6. processWordToPdf(wordFile,pdfFile);
  7. }
  8. public static void processWordToPdf(String wordFile,String pdfFile){
  9. ActiveXComponent app = null;
  10. System.out.println("开始转换...");
  11. // 开始时间
  12. long start = System.currentTimeMillis();
  13. try {
  14. // 打开word
  15. app = new ActiveXComponent("Word.Application");
  16. // 获得word中所有打开的文档
  17. Dispatch documents = app.getProperty("Documents").toDispatch();
  18. System.out.println("打开文件: " + wordFile);
  19. // 打开文档
  20. Dispatch document = Dispatch.call(documents, "Open", wordFile, false, true).toDispatch();
  21. // 如果文件存在的话,不会覆盖,会直接报错,所以我们需要判断文件是否存在
  22. File target = new File(pdfFile);
  23. if (target.exists()) {
  24. target.delete();
  25. }
  26. System.out.println("另存为: " + pdfFile);
  27. // 另存为,将文档报错为pdf,其中word保存为pdf的格式宏的值是17
  28. Dispatch.call(document, "SaveAs", pdfFile, 17);
  29. // 关闭文档
  30. Dispatch.call(document, "Close", false);
  31. // 结束时间
  32. long end = System.currentTimeMillis();
  33. System.out.println("转换成功,用时:" + (end - start) + "ms");
  34. } catch (Exception e) {
  35. System.out.println("转换失败" + e.getMessage());
  36. } finally {
  37. // 关闭office
  38. app.invoke("Quit", 0);
  39. }
  40. }
  41. }

总结

总体思路:利用easyexcel读取excel里面的数据,然后利用事先定义好的freemarker模板,往里面

填充值,最后生成word,再利用jacob根据word生成pdf。(代码中用到了lombok和google

guava,所以可能直接复制以上代码并不能直接使用)

https://blog.csdn.net/Anthony\_1223/article/details/88799100/

发表评论

表情:
评论列表 (有 0 条评论,260人围观)

还没有评论,来说两句吧...

相关阅读