easyExcel 文档不是很友好,所以转用hutool 工具导出excel,百度到的很多都没多少营养,略作总结,望君不吝赐教。
该篇博客可以让你画出不是太复杂的excel 如:

 
image.png

ps: 该篇文章为代码画excel,不介绍模板填充方式,因为模板填充较为简单。

excel导出Hutool官方教程
excel导出Hutool api 地址
https://apidoc.gitee.com/loolly/hutool/cn/hutool/poi/excel/package-frame.html

版本依赖,项目中直接引入了hutool-all依赖包,其中包括了导出excel所需的所有依赖包

<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.0</version>
</dependency>

api 中已经详细写了方法的说明,再此不多加阐述

1.字体样式常用方法

    /**
* 方法描述: 设置基础字体样式字体 这里保留最基础的样式使用
*
* @param workbook 工作簿
* @param bold 是否粗体
* @param fontName 字体名称
* @param fontSize 字体大小
* @return org.apache.poi.ss.usermodel.Font
* @author wqf
* @date 2021/5/19 15:58
*/
public static Font setBaseFont(Workbook workbook, boolean bold, boolean italic, String fontName, int fontSize) {
Font font = workbook.createFont();
//设置字体名称 宋体 / 微软雅黑 /等
font.setFontName(fontName);
//设置是否斜体
font.setItalic(italic);
//设置字体高度
//font.setFontHeight((short) fontHeight);
//设置字体大小 以磅为单位
font.setFontHeightInPoints((short) fontSize);
//设置是否加粗
font.setBold(bold);
//默认字体颜色
// font.setColor(Font.COLOR_NORMAL);
//红色
//font.setColor(Font.COLOR_RED);
//设置下划线样式
//font.setUnderline(Font.ANSI_CHARSET);
//设定文字删除线
//font.setStrikeout(true);
return font;
}
  1. 全局样式设置
 private static StyleSet GlobalStyleSet(ExcelWriter writer, Workbook workbook,Font font) {
//全局样式设置
StyleSet styleSet = writer.getStyleSet();
CellStyle cellStyle = styleSet.getCellStyle();
//设置全局文本居中
styleSet.setAlign(HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
//设置全局字体样式
styleSet.setFont(font);
//设置背景颜色 第二个参数表示是否将样式应用到头部
styleSet.setBackgroundColor(IndexedColors.WHITE, true);
//设置自动换行 当文本长于单元格宽度是否换行
styleSet.setWrapText();
// 设置全局边框样式
styleSet.setBorder(BorderStyle.THIN, IndexedColors.BLACK);
return styleSet;
}
  1. 头部标题样式
//设置全局样式
StyleSet styleSet = GlobalStyleSet(writer, workbook);
//设置头部标题样式
CellStyle headCellStyle = styleSet.getHeadCellStyle();
//水平居中
headCellStyle.setAlignment(HorizontalAlignment.CENTER);
//垂直居中
headCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//设置字体样式
headCellStyle.setFont(setBaseFont(workbook, true, false, "宋体", 12));
writer.setStyleSet(styleSet);
  1. 数字保留小数
    例:保留两位小数
CellStyle cellStyleForNumber = styleSet.getCellStyleForNumber();
cellStyleForNumber.setDataFormat((short)2);

5.时间格式化
例如格式为:YYYY/MM/dd 格式

CellStyle cellStyleForDate = styleSet.getCellStyleForDate();
//14 代表的时间格式是 yyyy/MM/dd
cellStyleForDate.setDataFormat((short)14);

时间格式占时只看到这一种格式常见些,像yyyy-MM-dd 格式都没找到,就只有在写入数据写先处理下时间格式了。

  1. 行(Row)样式
//获取输出构造器 设置工作簿名称
ExcelWriter writer = ExcelUtil.getWriterWithSheet(sheetName);
Workbook workbook = writer.getWorkbook();
Sheet sheet = writer.getSheet();
Row row = sheet.getRow(rowIndex);
if(sheet.getRow(rowIndex )==null){
//rowIndex 表示的是第几行,例:创建第二行,rowIndex=1
sheet.createRow(rowIndex );
}
//创建样式
CellStyle cellStyle = workbook.createCellStyle();
cellStyle .setVerticalAlignment(VerticalAlignment.CENTER);
cellStyle .setAlignment(HorizontalAlignment.LEFT);
cellStyle .setFont(setBaseFont(workbook, true, false, "宋体", 12));
cellStyle .setBorderBottom(BorderStyle.THIN);
cellStyle .setBorderLeft(BorderStyle.THIN);
cellStyle .setBorderRight(BorderStyle.THIN);
cellStyle .setBorderTop(BorderStyle.THIN);
//应用样式到某一行(
row .setRowStyle(cellStyle );
//应用样式到某一行 (或者这样写) rowIndex 表示的是第几行
//writer.setRowStyle(rowIndex ,cellStyle );
  1. 单元格(Cell)样式
Row row = sheet.getRow(rowIndex);
if(sheet.getRow(rowIndex )==null){
//rowIndex 表示的是第几行,例:创建第二行,rowIndex=1
sheet.createRow(rowIndex );
}
//创建本行的第几个单元格 cellIndex=0 表示第一个
if(row.get(cellIndex)==null){
row .createCell(cellIndex);
} //创建样式
CellStyle cellStyle = workbook.createCellStyle();
cellStyle .setVerticalAlignment(VerticalAlignment.CENTER);
cellStyle .setAlignment(HorizontalAlignment.LEFT);
cellStyle .setFont(setBaseFont(workbook, true, false, "宋体", 12));
cellStyle .setBorderBottom(BorderStyle.THIN);
cellStyle .setBorderLeft(BorderStyle.THIN);
cellStyle .setBorderRight(BorderStyle.THIN);
cellStyle .setBorderTop(BorderStyle.THIN);
//应用样式到某一行(
row .setRowStyle(cellStyle );
//应用样式到某一行 (或者这样写) rowIndex 表示的是第几行
//writer.setRowStyle(rowIndex ,cellStyle );
  1. 合并单元格
    //处理标题行 合并某行的单元格,并写入对象到单元格,如果写到单元格中的内容非null,行号自动+1,否则当前行号不变
//主要有两种方式
1. writer.merge(cellIndex, content, true);
表示当前行 合并从第一个单元到cellIndex+1个单元,并填充内容content,第三个参数表示是否将头部标题样式应用到这里。
或者
2.writer.merge(startRowIndex,endRowIndex, startCellIndex, endCellIndex, content, false);
表示和并第startRowIndex+1行到endRowIndex+1行 ,并合并从第endCellIndex+1个单元到endCellIndex+1个单元格,并填充content内容,最后一个字段表示是否将头部标题样式应用到这里。
  1. 列表别名
//LinkedHashMap 中的数据是根据put先后顺序来的,HashMap数据时无序的。
//使用方法 writer.setHeaderAlias(headerAlias); 时如果使用HashMap 可能展示的数
//据顺序会错乱
Map<String, String> headerAlias = new LinkedHashMap<>();
headerAlias.put(字段名1, 列名1);
headerAlias.put(字段名2, 列名2);
headerAlias.put(字段名3, 列名3);
headerAlias.put(字段名4, 列名4);
headerAlias.put(字段名5, 列名5);
writer.setHeaderAlias(headerAlias);
//或者一项一项设置列的别名 列别名顺序会跟代码中addHeaderAlias顺序一致
writer.addHeaderAlias(字段名1,列名1);
writer.addHeaderAlias(字段名2,列名2);
  1. 列宽问题
    8.1 自动列宽 百度查到一个方法有用 ,但实际好像还是会有点问题,大家可以先试试
    博客链接 :https://blog.csdn.net/kongbai953/article/details/110382544
/**
* 自适应宽度(中文支持)
* @param sheet
* @param size 因为for循环从0开始,size值为 列数-1
*/
public static void setSizeColumn(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() == XSSFCell.CELL_TYPE_STRING) {
int length = currentCell.getStringCellValue().getBytes().length;
if (columnWidth < length) {
columnWidth = length;
}
}
}
}
sheet.setColumnWidth(columnNum, columnWidth * 256);
}
}

8.2 手动列宽设置

//表示 第一列的列宽是15
writer.setColumnWidth(0, 15);
  1. 另外常用方法

//跳过当前行 即当前行不写内容

writer.passCurrentRow();

//定位到最后一行,常用于在末尾追加数据

writer.setCurrentRowToEnd();

10 . 下载excel代码 在数据都填充完成后,调用该方法即可

 /**
* 方法描述: 下载excel文件
*
* @param response 响应
* @param fileName 文件名称
* @param writer writer
* @return void
* @author wqf
* @date 2021/5/24 16:20
*/
private static void downloadExcel(HttpServletResponse response, String fileName, ExcelWriter writer) {
response.setContentType("application/vnd.ms-excel;charset=utf-8");
// test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
ServletOutputStream out = null;
try {
// 设置请求头属性
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) {
log.error(e.getMessage());
e.printStackTrace();
}
}
  1. excel 添加下拉框
CellRangeAddressList addressList = new CellRangeAddressList(2, 2, 5, 5);
DataValidationHelper helper = sheet.getDataValidationHelper();
// 设置下拉框数据
String[] str = new String[]{"男", "女","阴阳人"};
DataValidationConstraint constraint = helper.createExplicitListConstraint(str);
DataValidation dataValidation = helper.createValidation(constraint, addressList);
writer.addValidationData(dataValidation);

12.背景色填充

//示例:将单元格背景填充为黄色
short index = IndexedColors.YELLOW.index;
cellStyle.setFillForegroundColor(index);
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

总结 : 整合了一个工具类,仅作参考

/**
* @Author: wqf
* @Date: 2021/05/28
* @Description: hutool 工具导出excel(非填充模板,手工画)
*/
@Slf4j
public class HutoolExcelUtil {
/**
* YYYY/MM/dd 时间格式
*/
private static final short LOCAL_DATE_FORMAT_SLASH = 14; /**
* 方法描述: 创建excel
*
* @param isXlsx excel文件类型 true-xlsx/false-xls
* @return cn.hutool.poi.excel.ExcelWriter
* @author wqf
* @date 2021/6/1 9:47
*/
public static ExcelWriter createExcel(boolean isXlsx) {
return ExcelUtil.getWriter(isXlsx);
} /**
* 方法描述: 全局基础样式设置
* 默认 全局水平居中+垂直居中
* 默认 自动换行
* 默认单元格边框颜色为黑色,细线条
* 默认背景颜色为白色
*
* @param writer writer
* @param font 字体样式
* @return cn.hutool.poi.excel.StyleSet
* @author wqf
* @date 2021/5/28 10:43
*/
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
* @author wqf
* @date 2021/5/28 10:16
*/
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
* @author wqf
* @date 2021/5/19 15:58
*/
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
* @author wqf
* @date 2021/5/28 10:28
*/
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
* @author wqf
* @date 2021/5/28 10:23
*/
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 导出的字段个数
* @author wqf
* @date 2021/4/29 16:56
*/
public static int setHeaderAlias(ExcelWriter writer, Class<?> clazz) {
//需要导出的字段数
Field[] fields = clazz.getDeclaredFields();
TreeMap<Integer, Map<String, String>> headerAliasMap = new TreeMap<>();
Arrays.stream(fields).forEach(f -> {
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);
}
});
LinkedHashMap<String, String> linkedMap = new LinkedHashMap<>();
for (Map.Entry<Integer, Map<String, String>> entry : headerAliasMap.entrySet()) {
linkedMap.putAll(entry.getValue());
}
writer.setHeaderAlias(linkedMap);
return linkedMap.size();
} /**
* 方法描述: 自适应宽度(中文支持)
*
* @param sheet 页
* @param size 因为for循环从0开始,size值为 列数-1
* @return void
* @author wqf
* @date 2021/5/28 14:06
*/
public static void setSizeColumn(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);
}
} /**
* 方法描述: excel 导出下载
*
* @param response 响应
* @param fileName 文件名
* @param writer writer
* @return void
* @author wqf
* @date 2021/6/1 11:11
*/
public static void downloadExcel(HttpServletResponse response, String fileName, ExcelWriter writer) {
response.setContentType("application/vnd.ms-excel;charset=utf-8");
// test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
ServletOutputStream out = null;
try {
// 设置请求头属性
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) {
log.info("文件下载失败==" + e);
}
} /**
* 方法描述: 最简单的导出,直接将数据放到excel
* 导入的数据最好是List<map>格式数据,主要原因是List<Object> ,
* 对象有字段是LocalDate或者是LocalDateTime类型的数据,
* 时间格式化可能达不到想要的效果
*
* @param data 对象集合 两种
* @param globalFont 全局字体样式
* @param clazz 导出的对应class类型
* @return void
* @author wqf
* @date 2021/5/28 11:22
*/
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);
setSizeColumn(sheet, columnSize);
return writer;
}
}
 
 

Hutool excel导出的更多相关文章

  1. [moka同学笔记]PHPexcel之excel导出和导入

    原案例来自http://www.sucaihuo.com/有修改 1.目录结构(文件不用解释,应该都可以看得懂,直接看代码)

  2. 偷懒小工具 - Excel导出公共类

    说明 最近接了一个任务,就是做一个列表的Excel导出功能.并且有很多页面都会使用这个功能. 导出的Excel大体格式如图 很简单的列表,标题加背景色,然后不同类型,显示方式不一样.对齐方式不一样.不 ...

  3. 转:POI操作Excel导出

    package com.rd.lh.util.excel; import java.beans.PropertyDescriptor; import java.io.FileOutputStream; ...

  4. TP5.0源生Excel导出

    PHPExcel类在TP5里边并不能很好的兼容,使用起来很麻烦. 不像是tp3.2那样直接import()加进来就能new,因为它里边的命名空间找不到.总是说undefined class. 如果是使 ...

  5. java反射学习之二万能EXCEL导出

    一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...

  6. Devexpress EXCEL导出

    #region EXCEL导出 /// <summary> /// EXCEL导出 /// </summary> /// <param name="saveFi ...

  7. 自己写的java excel导出工具类

    最近项目要用到excel导出功能,之前也写过类似的代码.因为这次项目中多次用到excel导出.这次长了记性整理了一下 分享给大伙 欢迎一起讨论 生成excel的主工具类: public class E ...

  8. 发邮件 和 excel导出中文文件名

    /** * 发邮件 * @param email * @param subject * @param body * @throws UnsupportedEncodingException */ pu ...

  9. asp.net(C#) Excel导出类 导出.xls文件

    ---恢复内容开始--- using Microsoft.Office.Interop.Excel; 针对office 2003需添加引用Microsoft   Excel   11.0   Obje ...

  10. Atitit.excel导出 功能解决方案 php java C#.net版总集合.doc

    Atitit.excel导出 功能解决方案 php java C#.net版总集合.docx 1.1. Excel的保存格式office2003 office2007/2010格式1 1.2. 类库选 ...

随机推荐

  1. CRLF the next time Git touches it warning: in the working copy of '', LF will be replaced by CRLF the next time Git touches it warning: in the working copy of

    git config --global core.autocrlf true

  2. v-model 语法糖-在父子组件传值 的简写形式

    props的变量名字 必须是  value ,this.$emit('input',数据值) 的自定义事件必须是 input : v-model 是 vue 中进行数据双向绑定的指令,在内部实际上是通 ...

  3. 一文详述:AI 网关与 API 网关到底有什么区别?

    近年来AI 发展火热,大模型已经成为推动各行各业业务创新和增长的关键力量.随之而来问题是"企业该如何安全管理和部署AI应用的挑战?"AI基础架构的设计不仅要支持现有的业务需求,还要 ...

  4. Nacos2.3.2在ubuntu中的部署

    Nacos2.3.2 在ubuntu下的部署 下载地址 发布历史 | Nacos 官网 https://download.nacos.io/nacos-server/nacos-server-2.3. ...

  5. 混合云下的 Kubernetes 多集群管理与应用部署

    本文是上海站 Meetup 中讲师李宇根据其分享内容梳理成的文章 大家好,很高兴来到今天下午的 Meetup.我先简单做个自我介绍,我叫李宇,目前是 KubeSphere 的一名研发,主要负责多集群方 ...

  6. KubeSphere 网关的设计与实现(解读)

    作者:泓舟子,KubeSphere 后端研发工程师,云原生爱好者,现专注于云原生微服务方向. KubeSphere 中为什么需要网关? 如果需要将 K8s 集群内的服务暴露到外部访问有那些方式呢?可以 ...

  7. Mongo oplog理解

    转载请注明出处: oplog(操作日志)是MongoDB中用于记录所有写操作的日志.它是一个特殊的集合,存储在副本集的主节点中.oplog用于确保副本集中的副节点与主节点的数据保持一致.当主节点执行写 ...

  8. docker常用命令与应用

    docker入门与docker file介绍 原文地址 docker常用命令 https://blog.csdn.net/leilei1366615/article/details/106267225 ...

  9. schedule-执行周期性任务

    模块介绍 该模块主要用于python的任务调度,使用简便友好的python语法定期运行python函数或者一些其他的调用对象,这个模块就类似于windows的任务计划和linux的crontab,都是 ...

  10. 将NC栅格表示时间维度的数据提取出来的方法

      本文介绍基于Python语言,逐一读取大量.nc格式的多时相栅格文件,导出其中所具有的全部时间信息的方法.   .nc是NetCDF(Network Common Data Form)文件的扩展名 ...