记一次动态导出excel并且转pdf的辛酸史。
前言:接到一个需求,需要把用户填写的资料,填写excel模板中。并且导出pdf
收到需求后,着手开干。
1.先将数据填写到excel
1.1. 选取了esaypoi 框架 ,因为该框架支持excel模板填充数据,只需要定义好参数,会根据设定的参数填充数据。并且支持 循环插入数据。操作简单。
但是,这个框架有个巨坑的地方。多个fe 标签。就会出现莫名其妙的BUG,,会报【for each 当中存在空字符串,请检查模板】。整整花了2
天的时间,后面实在没办法。直接放弃。
1.2.上面的框架不支持后,把目光转向了阿里的esayExcel 。但是发现它对单元格的合并很不友好。加上升级框架对于现有项目的改动很大,然后放弃。
1.3.最后,在同事的帮助下,找到了Jxls 。强大的嵌套循环支持,简易的语法。后面 数据成功填写到了excel。
附上导包jxls 的pom.xml
<!-- jxls begin --> <dependency> <groupId>org.jxls</groupId> <artifactId>jxls</artifactId> <version>2.8.0</version> <exclusions> <exclusion> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.jxls</groupId> <artifactId>jxls-poi</artifactId> <version>2.8.0</version> <exclusions> <exclusion> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> </exclusion> <exclusion> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.jxls</groupId> <artifactId>jxls-jexcel</artifactId> <version>1.0.9</version> </dependency> <!--根据jxls-cor-1.0.6修改,支持poi4.x版本--> <dependency> <groupId>net.sf.jxls</groupId> <artifactId>jxls-core</artifactId> <version>1.0.4</version> </dependency>
附上工具类
import org.jxls.common.Context; import org.jxls.transform.Transformer; import org.jxls.util.JxlsHelper; import java.io.*; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; public class JxlsUtils{ private static final String TEMPLATE_PATH="jxls-template"; public static void exportExcel(InputStream is, OutputStream os, Map<String, Object> model) throws IOException { Context context = new Context(); if (model != null) { for (String key : model.keySet()) { context.putVar(key, model.get(key)); } } JxlsHelper jxlsHelper = JxlsHelper.getInstance(); Transformer transformer = jxlsHelper.createTransformer(is, os); //JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator)transformer.getTransformationConfig().getExpressionEvaluator(); //Map<String, Object> funcs = new HashMap<>(); // funcs.put("utils", new JxlsUtils()); //添加自定义功能 // evaluator.getJexlEngine().setFunctions(funcs); jxlsHelper.processTemplate(context, transformer); } public static void exportExcel(File xls, File out, Map<String, Object> model) throws FileNotFoundException, IOException { exportExcel(new FileInputStream(xls), new FileOutputStream(out), model); } public static void exportExcel(String templateName, OutputStream os, Map<String, Object> model) throws FileNotFoundException, IOException { File template = getTemplate(templateName); if(template!=null){ exportExcel(new FileInputStream(template), os, model); } } //获取jxls模版文件 public static File getTemplate(String name){ String templatePath = JxlsUtils.class.getClassLoader().getResource(TEMPLATE_PATH).getPath(); File template = new File(templatePath, name); if(template.exists()){ return template; } return null; } // 日期格式化 public String dateFmt(Date date, String fmt) { if (date == null) { return ""; } try { SimpleDateFormat dateFmt = new SimpleDateFormat(fmt); return dateFmt.format(date); } catch (Exception e) { e.printStackTrace(); } return ""; } // if判断 public Object ifelse(boolean b, Object o1, Object o2) { return b ? o1 : o2; } }
2.excel转pdf
1.1.一开始使用的是Spire ,功能强大,直接几行代码转DF, 但是免费版只能转3页,超过3页会出现提示。。。
1.2.最后找到了aspose ,完美解决问题!!!!!
附上asposepom.xml(ps:这个jar需要自己下载下俩,然后放到项目里面引用的。)
<dependency> <groupId>com.aspose</groupId> <artifactId>aspose-cells</artifactId> <version>8.5.2</version> <scope>system</scope> <systemPath>${project.basedir}/../file/lib/aspose-cells-8.5.2.jar</systemPath> </dependency>
附上导出代码——将上面的excel转换成PDF
Map<String, Object> map = new HashMap<String, Object>(); //设置参数,excel是模板填充 map.put("services",service); // excel 路径 URL url=new URL("http://xxxxxxxx); String fileName = URLEncoder.encode("文件名.pdf", CharsetUtil.UTF_8); response.reset(); response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); response.setContentType("application/octet-stream;charset=UTF-8"); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); InputStream inputStream1 = url.openStream(); log.info("开始导出excel============================时间为:"+DateUtil.format(new Date(),"yyyy-MM-dd HH:ss:mm")); JxlsUtils.exportExcel(inputStream1,outputStream,map); log.info("结束导出excel============================时间为:"+DateUtil.format(new Date(),"yyyy-MM-dd HH:ss:mm")); log.info("开始导出pdf============================时间为:"+DateUtil.format(new Date(),"yyyy-MM-dd HH:ss:mm")); ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); ServletOutputStream responseOutputStream = response.getOutputStream(); Excel2Pdf.excel2pdf(inputStream,responseOutputStream); log.info("结束导出pdf============================时间为:"+DateUtil.format(new Date(),"yyyy-MM-dd HH:ss:mm")); responseOutputStream.flush(); responseOutputStream.close(); inputStream.close(); inputStream1.close(); outputStream.flush(); outputStream.close();
补上 Excel2Pdf 工具类
import com.aspose.cells.License; import com.aspose.cells.SaveFormat; import com.aspose.cells.Workbook; import javax.servlet.ServletOutputStream; import java.io.ByteArrayInputStream; import java.io.InputStream; /** * @author MRHuang * @version 1.0.0 * @ClassName Excel2Pdf * @Description * @createTime 2022年10月23日 */ public class Excel2Pdf { public static boolean getLicense() { boolean result = false; try { InputStream is = Excel2Pdf.class.getClassLoader().getResourceAsStream("xlsxlicense.xml"); // license.xml应放在..WebRootWEB-INFclasses路径下 License aposeLic = new License(); aposeLic.setLicense(is); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } public static void excel2pdf(ByteArrayInputStream inputStream, ServletOutputStream responseOutputStream) { if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生 return; } try { Workbook wb = new Workbook(inputStream);// 原始excel路径 wb.save(responseOutputStream, SaveFormat.PDF); } catch (Exception e) { e.printStackTrace(); } } }
以下是 xlsxlicense.xml
<License> <Data> <Products> <Product>Aspose.Total for Java</Product> <Product>Aspose.Words for Java</Product> </Products> <EditionType>Enterprise</EditionType> <SubscriptionExpiry>20991231</SubscriptionExpiry> <LicenseExpiry>20991231</LicenseExpiry> <SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber> </Data> <Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature> </License>
其实整体看下来,无非是导数据到excel,然后转pdf。愣是折腾了好几天。。
反思了一下。 1.遇到有坑的框架,没有及时放弃。白白浪费了好多时间。
2.对各种框架,工具的使用不够熟练。
3.碰到难题,不够沉着冷静。过于浮躁。
4.菜是原罪!!!!!