Hutool操作excel相较于easyexcel更加的简单灵活,适合数据量小、格式不太复杂的excel操作

此excel导出格式较为复杂,较多的合并单元格。首先定义具体类,采用list集合封装,调用合并方法进行合并单元格即可。

导入依赖

<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.19</version>
</dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.0.0</version>
</dependency>
//导出excel    // 通过工具类创建writerExcelWriter writer = ExcelUtil.getWriter();int number = HutoolExcelUtil.setHeaderAlias(writer, DataTbbTableVO.class);// 默认的,未添加alias的属性也会写出,如果想只写出加了别名的字段,可以调用此方法排除之writer.setOnlyAlias(true);//标题字体样式Font font = HutoolExcelUtil.createFont(writer, true, false, "仿宋_GB2312", 22);//合并单元格后的标题行,使用默认标题样式CellStyle cellStyle = HutoolExcelUtil.createCellStyle(writer, font, true, VerticalAlignment.CENTER, HorizontalAlignment.CENTER);writer.merge(0, 0, 0, number - 1, dataTbbInfo.getTitle(), cellStyle);//跳过当前行  这里我也不知道为什么要调用,不调用内容表头不会显示writer.passCurrentRow();//写入标题writer.writeHeadRow(Arrays.asList(""));//全局字体默认样式Font font1 = HutoolExcelUtil.createFont(writer, false, false, "仿宋_GB2312", 12);//设置全局样式StyleSet styleSet = HutoolExcelUtil.setBaseGlobalStyle(writer, font1);//设置标题样式HutoolExcelUtil.createHeadCellStyle(styleSet, font1, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);//手动设置列宽HutoolExcelUtil.setSizeColumn(writer, Arrays.asList(5, 12, 16, 15, 14, 15, 30, 15, 15, 12), number - 1);//合并单元格    Map<String, Object> merge = this.merge(dataTbbInfo.getDataTbbTableVOS(), writer);//设置筛选下拉框HutoolExcelUtil.setFilter(writer, "A2:D" + merge.get("index"));//一次性写出内容,使用默认样式,强制输出标题writer.write((List<List<Object>>) merge.get("result"), true);//下载文件HutoolExcelUtil.downloadExcel(response, dataTbbInfo.getTitle(), writer);
/*** @author z* @Description 导出excel工具类* @date 2022/11/21 18:21*/
public class HutoolExcelUtil {/*** 方法描述: 全局基础样式设置* 默认 全局水平居中+垂直居中* 默认 自动换行* 默认单元格边框颜色为黑色,细线条* 默认背景颜色为白色** @param writer writer* @param font   字体样式* @return cn.hutool.poi.excel.StyleSet*/public static StyleSet setBaseGlobalStyle(ExcelWriter writer, Font font) {//全局样式设置StyleSet styleSet = writer.getStyleSet();//设置全局文本居中styleSet.setAlign(HorizontalAlignment.CENTER, VerticalAlignment.CENTER);//设置全局字体样式styleSet.setFont(font, true);//设置背景颜色 第二个参数表示是否将样式应用到头部styleSet.setBackgroundColor(IndexedColors.WHITE, true);//设置自动换行 当文本长于单元格宽度是否换行styleSet.setWrapText();// 设置全局边框样式styleSet.setBorder(BorderStyle.THIN, IndexedColors.BLACK);return styleSet;}/*** 方法描述: 设置标题的基础样式** @param styleSet            StyleSet* @param font                字体样式* @param horizontalAlignment 水平排列方式* @param verticalAlignment   垂直排列方式* @return org.apache.poi.ss.usermodel.CellStyle*/public static CellStyle createHeadCellStyle(StyleSet styleSet, Font font,HorizontalAlignment horizontalAlignment,VerticalAlignment verticalAlignment) {CellStyle headCellStyle = styleSet.getHeadCellStyle();headCellStyle.setAlignment(horizontalAlignment);headCellStyle.setVerticalAlignment(verticalAlignment);headCellStyle.setFont(font);return headCellStyle;}/*** 方法描述: 设置基础字体样式字体 这里保留最基础的样式使用** @param bold     是否粗体* @param fontName 字体名称* @param fontSize 字体大小* @return org.apache.poi.ss.usermodel.Font*/public static Font createFont(ExcelWriter writer, boolean bold, boolean italic, String fontName, int fontSize) {Font font = writer.getWorkbook().createFont();//设置字体名称font.setFontName(fontName);//设置是否斜体font.setItalic(italic);//设置字体大小 以磅为单位font.setFontHeightInPoints((short) fontSize);//设置是否加粗font.setBold(bold);return font;}/*** 方法描述: 设置行或单元格基本样式** @param writer              writer* @param font                字体样式* @param verticalAlignment   垂直居中* @param horizontalAlignment 水平居中* @return void*/public static CellStyle createCellStyle(ExcelWriter writer, Font font, boolean wrapText,VerticalAlignment verticalAlignment,HorizontalAlignment horizontalAlignment) {CellStyle cellStyle = writer.getWorkbook().createCellStyle();cellStyle.setVerticalAlignment(verticalAlignment);cellStyle.setAlignment(horizontalAlignment);cellStyle.setWrapText(wrapText);cellStyle.setFont(font);return cellStyle;}/*** 方法描述: 设置边框样式** @param cellStyle 样式对象* @param bottom    下边框* @param left      左边框* @param right     右边框* @param top       上边框* @return void*/public static void setBorderStyle(CellStyle cellStyle, BorderStyle bottom, BorderStyle left, BorderStyle right,BorderStyle top) {cellStyle.setBorderBottom(bottom);cellStyle.setBorderLeft(left);cellStyle.setBorderRight(right);cellStyle.setBorderTop(top);}/*** 方法描述: 获取对象需要导出的列和别名 这里按字段顺序来(可以在自定义注解上添加属性标识字段顺序,重写方法)* 在需要导出的字段上贴上注解 这里是@ExcelProperty,也可以用自定义注解* 注解需要有value 标识别名 order 标识字段顺序** @param clazz 对象类型* @return int 导出的字段个数*/public static int setHeaderAlias(ExcelWriter writer, ExcelReader reader, Class<?> clazz) {//需要导出的字段数TreeMap<Integer, Map<String, String>> headerAliasMap = new TreeMap<>();//判断类中字段类型和是否有别名注释HutoolExcelUtil.getResult(headerAliasMap, clazz);LinkedHashMap<String, String> linkedMap = new LinkedHashMap<>();for (Map.Entry<Integer, Map<String, String>> entry : headerAliasMap.entrySet()) {linkedMap.putAll(entry.getValue());}Optional.ofNullable(writer).ifPresent(w -> w.setHeaderAlias(linkedMap));Optional.ofNullable(reader).ifPresent(r -> r.setHeaderAlias(linkedMap));return linkedMap.size();}/*** 判断类中字段类型和是否有别名注释** @param headerAliasMap map集合* @param clazz          类*/private static void getResult(TreeMap<Integer, Map<String, String>> headerAliasMap, Class<?> clazz) {Field[] fields = clazz.getDeclaredFields();Arrays.stream(fields).forEach(f -> {//获取字段类型Class<?> type = f.getType();//判断字段类型是否是listif (type.equals(List.class)) {//获取集合的泛型对象Type genericType = f.getGenericType();if (genericType instanceof ParameterizedType) {ParameterizedType pt = (ParameterizedType) genericType;Class<?> aClass = (Class<?>) pt.getActualTypeArguments()[0];//递归调用HutoolExcelUtil.getResult(headerAliasMap, aClass);}}//判断是否有注解if (f.isAnnotationPresent(ExcelProperty.class)) {ExcelProperty annotation = f.getAnnotation(ExcelProperty.class);//别名String[] value = annotation.value();int order = annotation.order();Map<String, String> alisMap = new HashMap<>();String fieldName = f.getName();//字段名String headerAlias = value[0];alisMap.put(fieldName, headerAlias);headerAliasMap.put(order, alisMap);}});}/*** 方法描述: 自适应宽度(中文支持)** @param sheet 页* @param size  因为for循环从0开始,size值为 列数-1* @return void*/public static void setSizeAutoColumn(Sheet sheet, int size) {for (int columnNum = 0; columnNum <= size; columnNum++) {int columnWidth = sheet.getColumnWidth(columnNum) / 256;for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {Row currentRow;//当前行未被使用过if (sheet.getRow(rowNum) == null) {currentRow = sheet.createRow(rowNum);} else {currentRow = sheet.getRow(rowNum);}if (currentRow.getCell(columnNum) != null) {Cell currentCell = currentRow.getCell(columnNum);if (currentCell.getCellType() == CellType.STRING) {int length = currentCell.getStringCellValue().getBytes().length;if (columnWidth < length) {columnWidth = length;}}}}sheet.setColumnWidth(columnNum, columnWidth * 256);}}/*** 方法描述: 手动宽度(中文支持)*/public static void setSizeColumn(ExcelWriter excelWriter, List<Integer> list, int size) {for (int columnNum = 0; columnNum <= size; columnNum++) {excelWriter.setColumnWidth(columnNum, list.get(columnNum));}}/*** 方法描述: excel 导出下载** @param response 响应* @param fileName 文件名* @param writer   writer* @return void*/public static void downloadExcel(HttpServletResponse response, String fileName, ExcelWriter writer) {response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");// xxx.xlsx是弹出下载对话框的文件名ServletOutputStream out = null;try {// 设置请求头属性fileName = URLEncoder.encode(fileName, "UTF-8");response.setHeader("Content-Disposition","attachment;filename=" + new String((fileName + ".xlsx").getBytes(), StandardCharsets.ISO_8859_1));out = response.getOutputStream();// 写出到文件writer.flush(out, true);// 关闭writer,释放内存writer.close();// 此处记得关闭输出Servlet流IoUtil.close(out);} catch (IOException e) {throw new BusinessException("导出失败");}}/*** 方法描述: 最简单的导出,直接将数据放到excel* 导入的数据最好是List<map>格式数据,主要原因是List<Object> ,* 对象有字段是LocalDate或者是LocalDateTime类型的数据,* 时间格式化可能达不到想要的效果** @param data       对象集合 两种* @param globalFont 全局字体样式* @param clazz      导出的对应class类型* @return void*/public static ExcelWriter exportBaseExcel(ExcelWriter writer, List<?> data, Font globalFont, Class clazz) {Sheet sheet = writer.getSheet();writer.setStyleSet(setBaseGlobalStyle(writer, globalFont));int columnSize = setHeaderAlias(writer, clazz);writer.setOnlyAlias(true);writer.write(data);HutoolExcelUtil.setSizeAutoColumn(sheet, columnSize);return writer;}/*** 设置下拉列表框** @param writer   ExcelWriter* @param str      内容* @param firstRow 第一行* @param lastRow  第二行* @param firstCol 第一列* @param lastCol  第二列*/public static void setSelect(ExcelWriter writer, String[] str, int firstRow, int lastRow, int firstCol, int lastCol) {CellRangeAddressList addressList = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol);DataValidationHelper helper = writer.getSheet().getDataValidationHelper();DataValidationConstraint constraint = helper.createExplicitListConstraint(str);DataValidation dataValidation = helper.createValidation(constraint, addressList);writer.addValidationData(dataValidation);}/*** 设置筛选功能** @param writer ExcelWriter* @param str    要筛选的坐标  例如:A2:D6*/public static void setFilter(ExcelWriter writer, String str) {Sheet sheet = writer.getSheet();CellRangeAddress c = CellRangeAddress.valueOf(str);sheet.setAutoFilter(c);}}//注解类
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelProperty {String[] value();int order();
}
/**合并单元格方法
*/private Map<String, Object> merge(List<DataTbbTableVO> dataTbbTableVOS, ExcelWriter writer) {Map<String, Object> map = new HashMap<>(2);//有个字段要合并的就定义多少int index1 = 2;int index2 = 2;// 后面要用到的临时对象List<List<Object>> rows = new LinkedList<>();List<Object> rowA;//按照序号合并单元格Map<Integer, List<DataTbbTableVO>> reservoirNameMaps = dataTbbTableVOS.stream().collect(Collectors.groupingBy(DataTbbTableVO::getNumber, LinkedHashMap::new, Collectors.toList()));for (Map.Entry<Integer, List<DataTbbTableVO>> reservoirNameEntry : reservoirNameMaps.entrySet()) {List<DataTbbTableVO> reservoirNameValue = reservoirNameEntry.getValue();//根据数据条数设置合并单元格信息if (reservoirNameValue.size() == 1) {//一条数据不合并index1 = index1 + reservoirNameValue.size();} else {//规则编写writer.merge(index1, index1 + reservoirNameValue.size() - 1, 0, 0, null, true);writer.merge(index1, index1 + reservoirNameValue.size() - 1, 1, 1, null, true);index1 = index1 + reservoirNameValue.size();//按照二级指标合并单元格Map<String, List<DataTbbTableVO>> reservoirScaleMaps = reservoirNameValue.stream().collect(Collectors.groupingBy(DataTbbTableVO::getSecondLevel, LinkedHashMap::new, Collectors.toList()));for (Map.Entry<String, List<DataTbbTableVO>> reservoirScaleEntry : reservoirScaleMaps.entrySet()) {List<DataTbbTableVO> reservoirScaleValue = reservoirScaleEntry.getValue();//根据数据条数设置合并单元格信息if (reservoirScaleValue.size() == 1) {//一条数据不合并index2 = index2 + reservoirScaleValue.size();} else {//规则编写writer.merge(index2, index2 + reservoirScaleValue.size() - 1, 2, 2, null, true);writer.merge(index2, index2 + reservoirScaleValue.size() - 1, 3, 3, null, true);writer.merge(index2, index2 + reservoirScaleValue.size() - 1, 4, 4, null, true);writer.merge(index2, index2 + reservoirScaleValue.size() - 1, 5, 5, null, true);index2 = index2 + reservoirScaleValue.size();}}}//保存数据for (DataTbbTableVO dataTbbTableVO : reservoirNameValue) {rowA = CollUtil.newArrayList(dataTbbTableVO.getNumber(),dataTbbTableVO.getFirstLevel(),dataTbbTableVO.getSecondLevel(),dataTbbTableVO.getSecondLevelData(),dataTbbTableVO.getSecondLevelRank(),dataTbbTableVO.getSecondBest(),dataTbbTableVO.getThirdLevel(),dataTbbTableVO.getThirdLevelData(),dataTbbTableVO.getThirdLevelRank(),dataTbbTableVO.getThirdBest());rows.add(rowA);}}map.put("index", index2);map.put("result", rows);return map;}

Hutool工具excel封装相关推荐

  1. 利用hutool工具类导出Excel

    简单介绍 可以使用hutool工具类,简单的生成Excel.本质上还是使用的POI组件,只是对其进行了封装,避免开发人员重复造轮子 hutool工具类链接 maven导入 <!-- hutool ...

  2. hutool导出excel大数据_HuTool工具类使用之Excel文档的导入导出

    HuTool工具类使用之Excel文档的导入导出 前言 在日常的工作开发中,Excel的导入和导出是必不可少的,如果自己写相应的导入导出方法,会显得十分繁琐,本文采用Hutool工具类实现的Excel ...

  3. Hutool工具包Excel工具使用

    参考自:https://blog.csdn.net/qq_43230007/article/details/107216171 一.导入依赖 <!-- hutool工具类依赖--> < ...

  4. Java 利用hutool工具实现导出excel并合并单元格

    Java 利用hutool工具实现导出excel并合并单元格 controller层调用service,就一个核心方法,没错就下面这个代码就能实现了.前提是项目里面要引用hutool包.把我这个复制到 ...

  5. 使用hutool工具导出Excel标题自定义顺序

    使用hutool工具导出Excel标题自定义顺序 在自定义别名的时候,map要使用有顺序的 LinkedHashMap(hutool工具:MapUtil.newHashMap(true)) Map&l ...

  6. 用hutool工具类导出excel

    工作上有一个导出数据的需求,发现用hutool工具类可以非常简洁快捷的生成excel导出. 前期准备 引入hutool的依赖: <dependency><groupId>cn. ...

  7. hutool工具 导出excel

    hutool工具 导出excel 前言 一.pandas是什么? 二.步骤 1.依赖导入 每日鸡汤 前言 本周接到导出数据到excel的任务,第一次写还是很感兴趣的,写完感觉很简单 需求场景:根据时间 ...

  8. hutool工具多sheet自定义导出excel

    hutool工具多sheet自定义导出excel 大致需求 hutool工具导出excel简单说明 需要的功能及使用问题 合并单元格 设置表格列宽和行高 单元格内容及样式添加 样式赋值代码 样式获取代 ...

  9. hutool工具类导出Excel表格

    1.引入hutool和相关依赖 <dependency>         <groupId>cn.hutool</groupId>         <arti ...

最新文章

  1. php ci框架 模板输出,CodeIgniter模板引擎使用实例
  2. 【快乐水题】594. 最长和谐子序列
  3. PHP的静态方法与普通方法
  4. 对于***win2000 精彩过程实例!不可错过_出自:痞菜
  5. VS Code 即将迎来再一次的 logo 更新!已可在 Insiders 版本尝鲜
  6. Asp.NetCore轻松学-部署到 Linux 进行托管
  7. ubuntu没有指纹登录_ubuntu安装指纹识别驱动
  8. delete删除重复记录方法
  9. UnicodeDecodeError: 'ascii' codec can't decode byte 0xf6 in position 0: ordinal not in range(128)
  10. 2018年易语言FPS骨骼方框透视辅助开发
  11. COM组件注册DLL不成功
  12. vue使用tinymce富文本编辑器
  13. Windows10连接局域网打印机
  14. 谈如何归纳和分类美术风格比较合理
  15. win7配置TomCat环境
  16. 正睿OIday8-day10
  17. ADF4350调试笔记
  18. Gym - 101982E Cops And Robbers 网络流最小割
  19. Linux下使用游戏手柄
  20. Android基本界面元素的使用与讲解

热门文章

  1. Java同学找工作最懵圈的问题:到底啥是分布式系统开发经验?
  2. 浅析Tomcat结构以及自定义嵌入式Tomcat
  3. JAVA架构师之路十五:设计模式之策略模式
  4. dpresult在python中什么意思_Python十大装B语法!你会几种?
  5. SpringBoot通联支付接口实现案例之Httpclient(后端篇)
  6. 【博学谷学习记录】超强总结,用心分享 _ 前端开发 vue3
  7. 汉堡王什么汉堡好吃_汉堡王什么汉堡好吃?汉堡王哪个汉堡最好吃
  8. 浅论如何做一个漂亮的课件
  9. matlab trapz x y,请问matlab trapz函数 用法???????
  10. 遇到不认识的字怎么查?这几种方法都很好用