• Java读取Excel并生成Word&PDF


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

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

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

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

    在这里插入图片描述

    如果需要设置图片,打开ftl文件后,搜索标签(我用的是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 dataMap = new HashMap() {{
    17. put("imgStr",imgStr);
    18. put("province","北京市");
    19. put("city","海淀区");
    20. put("school","");
    21. put("class","二三班");
    22. }};
    23. //处理excel,将其中的数据填充至模板中,最后生成word。
    24. List datas = ExcelUtils.readExcel(new FileInputStream(new File(filePath)), ERReport.class);
    25. datas.forEach((ERReport e) -> {
    26. try {
    27. processTemplate(e, “Your File Name”);
    28. System.out.println("转换成功");
    29. } catch (Exception ex) {
    30. LOGGER.error("Excel转换Word错误.", ex);
    31. }
    32. });
    33. }
    34. private static byte[] encode(String imagePath) throws IOException {
    35. InputStream in = null;
    36. byte[] data = null;
    37. try {
    38. in = new FileInputStream(imagePath);
    39. data = new byte[in.available()];
    40. in.read(data);
    41. in.close();
    42. } catch (Exception e) {
    43. e.printStackTrace();
    44. } finally {
    45. if (in != null) {
    46. in.close();
    47. }
    48. return data;
    49. }
    50. }
    51. public static void processTemplate(Object dataMap, String fileName) throws IOException, TemplateException {
    52. Configuration configuration = new Configuration();
    53. configuration.setDefaultEncoding("utf-8");
    54. configuration.setClassForTemplateLoading(WordUtils.class, "/templates");
    55. Template template = configuration.getTemplate("template.ftl");
    56. File file = new File("C:\\Users\\Administrator\\Desktop\\" + fileName + ".docx");
    57. BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "utf-8"));
    58. template.process(dataMap, bufferedWriter);
    59. }
    60. }

     word转pdf(使用jacob)

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

    1. word转pdf的代码如下:
    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/

  • 相关阅读:
    什么是神经网络,它们是如何工作的?(神经网络架构基本指南)
    功能超全的微信小程序制作源码 含15大主流功能小程序 源码开源可二开 持续更新升级
    java计算机毕业设计vue基层社区管理服务网源码+mysql数据库+系统+lw文档+部署
    一文搞懂MobileNet v1网络
    Centos7的yum使用国内源阿里源163源等提高下载速度
    C#__使用流读取和写入数据的简单用法
    c/c++一个指针delete两次的后果
    SWT/ANR问题-- OTA 升级 从Android P 到 Q 发生 watchdog
    CSS中常见选择器的用法
    java项目-第147期ssm社区生活超市管理系统_(spring+springmvc+mybatis+jsp)_java毕业设计_计算机毕业设计
  • 原文地址:https://blog.csdn.net/ZHOU_VIP/article/details/127753624