easypoi基于注解的导入导出,修改注解就可以修改Excel
一、注解使用
- @Excel:作用到filed上面,是对Excel一列的一个描述
属性 | 类型 | 默认值 | 功能 |
---|---|---|---|
name | String | null | 列名,支持name_id |
needMerge | boolean | fasle | 是否需要纵向合并单元格(用于含有list中,单个的单元格,合并list创建的多个row) |
orderNum | String | "0" | 列的排序,支持name_id |
replace | String[] | {} | 值得替换 导出是{a_id,b_id} 导入反过来 |
savePath | String | "upload" | 导入文件保存路径,如果是图片可以填写,默认是upload/className/ IconEntity这个类对应的就是upload/Icon/ |
type | int | 1 | 导出类型 1 是文本 2 是图片,3 是函数,10 是数字 默认是文本 |
width | double | 10 | 列宽 |
height | double | 10 | 列高,后期打算统一使用@ExcelTarget的height,这个会被废弃,注意 |
isStatistics | boolean | fasle | 自动统计数据,在追加一行统计,把所有数据都和输出 这个处理会吞没异常,请注意这一点 |
isHyperlink | boolean | false | 超链接,如果是需要实现接口返回对象 |
isImportField | boolean | true | 校验字段,看看这个字段是不是导入的Excel中有,如果没有说明是错误的Excel,读取失败,支持name_id |
exportFormat | String | "" | "yyyy-MM-dd HH:mm:ss" 导出的时间格式,以这个是否为空来判断是否需要格式化日期 |
importFormat | String | "" | 导入的时间格式,以这个是否为空来判断是否需要格式化日期 |
format | String | "" | 时间格式,相当于同时设置了exportFormat 和 importFormat |
databaseFormat | String | "yyyyMMddHHmmss" | 导出时间设置,如果字段是Date类型则不需要设置 数据库如果是string 类型,这个需要设置这个数据库格式,用以转换时间格式输出 |
numFormat | String | "" | 数字格式化,参数是Pattern,使用的对象是DecimalFormat |
imageType | int | 1 | 导出类型 1 从file读取 2 是从数据库中读取 默认是文件 同样导入也是一样的 |
suffix | String | "" | 文字后缀,如% 90 变成90% |
isWrap | boolean | true | 是否换行 即支持\n |
mergeRely | int[] | {} | 合并单元格依赖关系,比如第二列合并是基于第一列 则{0}就可以了 |
mergeVertical | boolean | fasle | 纵向合并内容相同的单元格 |
fixedIndex | int | -1 | 对应excel的列,忽略名字 |
isColumnHidden | boolean | false | 导出隐藏列 |
- @ExcelTarget:限定一个到处实体的注解,以及一些通用设置,作用于最外面的实体
属性 | 类型 | 默认值 | 功能 |
---|---|---|---|
value | String | null | 定义ID |
height | double | 10 | 设置行高 |
fontSize | short | 11 | 设置文字大小 |
- @ExcelEntity:标记是不是导出excel 标记为实体类,一般是一个内部属性类,标记是否继续穿透,可以自定义内部id
属性 | 类型 | 默认值 | 功能 |
---|---|---|---|
id | String | null | 定义ID |
- @ExcelCollection:一对多的集合注解,用以标记集合是否被数据以及集合的整体排序
属性 | 类型 | 默认值 | 功能 |
---|---|---|---|
id | String | null | 定义ID |
name | String | null | 定义集合列名,支持nanm_id |
orderNum | int | 0 | 排序,支持name_id |
type | Class<?> | ArrayList.class | 导入时创建对象使用 |
二、功能实现
1.添加pom依赖
<!--easypoi-->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.0.0</version>
</dependency>
<!-- JSR 303 规范验证包 -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
<!--工具类-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.21</version>
</dependency>
第一种:普通导出
实体类
package com.example.demo.excel;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
@ExcelTarget(value = "商品信息")
@Data
@NoArgsConstructor
public class BatchGoodsImageNameVo implements Serializable{
@Excel(name = "商品名称")
private String name;
@Excel(name = "商品价格", height = 20, width = 30)
private BigDecimal price;
@Excel(name = "商品数量", height = 20, width = 38)
private Integer num;
public BatchGoodsImageNameVo(String name, BigDecimal price, Integer num) {
this.name = name;
this.price = price;
this.num = num;
}
}
浏览器下载excel
package com.example.mybatismysql8demo.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.example.mybatismysql8demo.vo.BatchGoodsImageNameVo;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@RestController
public class EasypoiController {
@GetMapping("/exportExcel")
public void exportExcel(HttpServletResponse response){
//导出数据
List<BatchGoodsImageNameVo> goodInfoList = new ArrayList<>();
goodInfoList.add(new BatchGoodsImageNameVo("草莓",new BigDecimal(20),30));
goodInfoList.add(new BatchGoodsImageNameVo("苹果",new BigDecimal(8),10));
//.xlsx格式
//response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//.xls格式
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setCharacterEncoding("utf-8");
//前端存在跨域不成功,设置可访问
response.setHeader("Access-Control-Allow-Origin","*");
//设置不要缓存
response.setHeader("Pragma", "No-cache");
try {
// 这里URLEncoder.encode可以防止中文乱码
String fileName = URLEncoder.encode("goodsInfo", String.valueOf(StandardCharsets.UTF_8));
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");
//设置sheet名
ExportParams params = new ExportParams();
params.setSheetName("商品信息表");
//设置标题
params.setTitle("商品信息");
// 这里需要设置不关闭流
Workbook workbook = ExcelExportUtil.exportExcel(params, BatchGoodsImageNameVo.class, goodInfoList);
//输出流
OutputStream outStream = response.getOutputStream();
//浏览器下载
workbook.write(outStream);
//关闭流
outStream.flush();
outStream.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
第二种:复杂导出(合并单元格)
实体类
package com.example.mybatismysql8demo.vo;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelCollection;
import cn.afterturn.easypoi.excel.annotation.ExcelEntity;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@ExcelTarget(value = "商品信息")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BatchGoodsImageNameVo{
@Excel(name = "商品型号",needMerge = true,orderNum = "0")
private String model;
@ExcelEntity(name = "公共信息", show = true)
private CommonInfo commonInfo;
/**needMerge = true的属性,就可以完成单元格的合并*/
@Excel(name = "商品分类", needMerge = true, groupName = "分类",orderNum = "2")
private String goodsName;
/**ExcelCollection一对多信息*/
@ExcelCollection(name = "商品信息",orderNum = "3")
private List<GoodInfo> goodsInfo;
public BatchGoodsImageNameVo(String goodsName, String model, List<GoodInfo> goodsInfo,CommonInfo commonInfo) {
this.goodsName = goodsName;
this.model = model;
this.goodsInfo = goodsInfo;
this.commonInfo = commonInfo;
}
@Data
public static class CommonInfo{
@Excel(name = "采摘时间",needMerge = true, exportFormat="yyyy-MM-dd HH:mm:ss")
private Date createTime;
@Excel(name = "是否打药",needMerge = true, replace = {"否_0","是_1"})
private String insecticide;
public CommonInfo(Date createTime, String insecticide) {
this.createTime = createTime;
this.insecticide = insecticide;
}
}
@Data
public static class GoodInfo{
@Excel(name = "商品名称")
private String name;
@Excel(name = "商品价格", height = 20, width = 30)
private BigDecimal price;
@Excel(name = "商品数量", height = 20, width = 38)
private Integer num;
public GoodInfo(String name, BigDecimal price, Integer num) {
this.name = name;
this.price = price;
this.num = num;
}
}
}
本地下载excel文件
package com.example.mybatismysql8demo.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.example.mybatismysql8demo.vo.BatchGoodsImageNameVo;
import org.apache.poi.ss.usermodel.Workbook;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class EasypoiController {
public static void exportExcel(){
List<BatchGoodsImageNameVo.GoodInfo> goodInfoList = new ArrayList<>();
goodInfoList.add(new BatchGoodsImageNameVo.GoodInfo("草莓",new BigDecimal(20),30));
goodInfoList.add(new BatchGoodsImageNameVo.GoodInfo("苹果",new BigDecimal(8),10));
//导出数据
List<BatchGoodsImageNameVo> imageNameVoList = new ArrayList<>();
imageNameVoList.add(new BatchGoodsImageNameVo("水果","m001",goodInfoList,new BatchGoodsImageNameVo.CommonInfo(new Date(),"0")));
//设置sheet名
ExportParams params = new ExportParams();
params.setSheetName("商品信息表");
//设置标题
params.setTitle("商品信息");
// 这里需要设置不关闭流
Workbook workbook = ExcelExportUtil.exportExcel(params, BatchGoodsImageNameVo.class, imageNameVoList);
//本地下载路径
String path = "E:\\新建文件夹\\下载\\goodsInfo.xls";
File file = new File(path);
if(file.exists() && file.isFile()){
file.delete();
}
try {
FileOutputStream outputStream = new FileOutputStream(path);
workbook.write(outputStream);
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
exportExcel();
}
}
浏览器下载excel
package com.example.mybatismysql8demo.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.example.mybatismysql8demo.vo.BatchGoodsImageNameVo;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@RestController
public class EasypoiController {
@GetMapping("/exportExcel")
public void exportExcel(HttpServletResponse response){
List<BatchGoodsImageNameVo.GoodInfo> goodInfoList = new ArrayList<>();
goodInfoList.add(new BatchGoodsImageNameVo.GoodInfo("草莓",new BigDecimal(20),30));
goodInfoList.add(new BatchGoodsImageNameVo.GoodInfo("苹果",new BigDecimal(8),10));
//导出数据
List<BatchGoodsImageNameVo> imageNameVoList = new ArrayList<>();
imageNameVoList.add(new BatchGoodsImageNameVo("水果","m001",goodInfoList,new BatchGoodsImageNameVo.CommonInfo(new Date(),"0")));
//.xlsx格式
//response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//.xls格式
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setCharacterEncoding("utf-8");
//前端存在跨域不成功,设置可访问
response.setHeader("Access-Control-Allow-Origin","*");
//设置不要缓存
response.setHeader("Pragma", "No-cache");
try {
// 这里URLEncoder.encode可以防止中文乱码
String fileName = URLEncoder.encode("goodsInfo", StandardCharsets.UTF_8);
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");
//设置sheet名
ExportParams params = new ExportParams();
params.setSheetName("商品信息表");
//设置标题
params.setTitle("商品信息");
// 这里需要设置不关闭流
Workbook workbook = ExcelExportUtil.exportExcel(params, BatchGoodsImageNameVo.class, imageNameVoList);
//输出流
OutputStream outStream = response.getOutputStream();
//浏览器下载
workbook.write(outStream);
//关闭流
outStream.flush();
outStream.close();
} catch (IOException e) {
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
System.out.println(e.getMessage());
}
}
}
下载结果图
第三种:样式导出
实体类
package com.example.mybatismysql8demo.vo;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class GoodsExportError {
@Excel(name = "商品名称",orderNum = "1",width = 30)
private String goodsName;
@Excel(name = "商品价格",orderNum = "2",width = 30)
private BigDecimal price;
@Excel(name = "商品数量",orderNum = "3",width = 30)
private Integer num;
@Excel(name = "错误描述",orderNum = "4",width = 60)
private String errorMsg;
public GoodsExportError(String goodsName, BigDecimal price, Integer num, String errorMsg) {
this.goodsName = goodsName;
this.price = price;
this.num = num;
this.errorMsg = errorMsg;
}
}
全局样式配置类
package com.example.mybatismysql8demo.config;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.afterturn.easypoi.excel.entity.params.ExcelForEachParams;
import cn.afterturn.easypoi.excel.export.styler.IExcelExportStyler;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.*;
import java.math.BigDecimal;
import java.util.List;
public class ExcelExportStyler implements IExcelExportStyler {
private static final short STRING_FORMAT = (short) BuiltinFormats.getBuiltinFormat("TEXT");
private static final short FONT_SIZE_TEN = 15;
private static final short FONT_SIZE_ELEVEN = 11;
private static final short FONT_SIZE_TWELVE = 12;
/**
* 大标题样式
*/
private CellStyle headerStyle;
/**
* 每列标题样式
*/
private CellStyle titleStyle;
/**
* 数据行样式
*/
private CellStyle styles;
public ExcelExportStyler(Workbook workbook) {
this.init(workbook);
}
/**
* 初始化样式
*
* @param workbook
*/
private void init(Workbook workbook) {
this.headerStyle = initHeaderStyle(workbook);
this.titleStyle = initTitleStyle(workbook);
this.styles = initStyles(workbook);
}
/**
* 大标题样式
*
* @param color
* @return
*/
@Override
public CellStyle getHeaderStyle(short color) {
return headerStyle;
}
/**
* 每列标题样式
*/
@Override
public CellStyle getTitleStyle(short color) {
return titleStyle;
}
/**
* 数据行样式
* @param parity 可以用来表示奇偶行
* @param entity 数据内容
* @return 样式
*/
@Override
public CellStyle getStyles(boolean parity, ExcelExportEntity entity) {
return styles;
}
/**
* 获取样式方法
*
* @param dataRow 数据行
* @param obj 对象
* @param data 数据
*/
@Override
public CellStyle getStyles(Cell cell, int dataRow, ExcelExportEntity entity, Object obj, Object data) {
return getStyles(true, entity);
}
/**
* 模板使用的样式设置
*/
@Override
public CellStyle getTemplateStyles(boolean isSingle, ExcelForEachParams excelForEachParams) {
return null;
}
/**
* 初始化--大标题样式
*
* @param workbook
* @return
*/
private CellStyle initHeaderStyle(Workbook workbook) {
//列样式
CellStyle style = getBaseCellStyle(workbook,BorderStyle.NONE);
style.setFont(getFont(workbook, FONT_SIZE_TEN, true));
// 背景色
style.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
return style;
}
/**
* 初始化--每列标题样式
*
* @param workbook
* @return
*/
private CellStyle initTitleStyle(Workbook workbook) {
CellStyle style = getBaseCellStyle(workbook,BorderStyle.THIN);
style.setFont(getFont(workbook, FONT_SIZE_ELEVEN, false));
// 背景色
style.setFillForegroundColor(IndexedColors.PINK.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
return style;
}
/**
* 行数据样式
*/
private CellStyle initStyles(Workbook workbook) {
CellStyle style = getBaseCellStyle(workbook,BorderStyle.NONE);
style.setFont(getFont(workbook, FONT_SIZE_ELEVEN, false));
return style;
}
/**
* 基础样式
*
* @return
*/
private CellStyle getBaseCellStyle(Workbook workbook,BorderStyle borderStyle) {
CellStyle style = workbook.createCellStyle();
// 下边框
style.setBorderBottom(borderStyle);
// 左边框
style.setBorderLeft(borderStyle);
// 上边框
style.setBorderTop(borderStyle);
// 右边框
style.setBorderRight(borderStyle);
// 水平居中
style.setAlignment(HorizontalAlignment.CENTER);
// 上下居中
style.setVerticalAlignment(VerticalAlignment.CENTER);
// 设置自动换行
style.setWrapText(true);
return style;
}
/**
* 字体样式
*
* @param size 字体大小
* @param isBold 是否加粗
* @return
*/
private Font getFont(Workbook workbook, short size, boolean isBold) {
Font font = workbook.createFont();
// 是否加粗
font.setBold(isBold);
// 字体大小
font.setFontHeightInPoints(size);
return font;
}
/**
*自定义样式
*/
public static void setCellStyle(Workbook workbook){
//获取sheetAt对象,这里一个sheetAt所以角标是0
Sheet sheetAt = workbook.getSheetAt(0);
// 表格行数
int lastRowNum = sheetAt.getLastRowNum();
// 获取列数
int physicalNumberOfCells = sheetAt.getRow(0).getPhysicalNumberOfCells();
//开始遍历单元格并进行判断是否渲染
for (int i = 1; i <= lastRowNum; i++) {
//获取每行对象
Row row = sheetAt.getRow(i);
//获取单元格对象(最后一列设置背景颜色)
Cell cell = row.getCell(physicalNumberOfCells-1);
//获取单元格样式对象
CellStyle cellStyle = workbook.createCellStyle();
//获取单元格内容对象
Font font = workbook.createFont();
//标题行时,设置错误描述列的背景颜色
if (i == 1){
//设置单元格背景颜色
cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
}else {
//设置单元格字体颜色
font.setColor(IndexedColors.RED.getIndex());
}
// 字体大小
font.setFontHeightInPoints(FONT_SIZE_ELEVEN);
//一定要装入 样式中才会生效
cellStyle.setFont(font);
//设置单元格字体居中
cellStyle.setAlignment(HorizontalAlignment.CENTER);
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
cell.setCellStyle(cellStyle);
}
}
public static void setCellStyle(Workbook workbook, List data){
//获取sheetAt对象,这里一个sheetAt所以角标是0
Sheet sheetAt = workbook.getSheetAt(0);
// 表格行数
int lastRowNum = sheetAt.getLastRowNum();
// 获取列数
int physicalNumberOfCells = sheetAt.getRow(0).getPhysicalNumberOfCells();
//开始遍历单元格并进行判断是否渲染
for (int i = 2; i <= lastRowNum; i++) {
//获取每行对象
Row row = sheetAt.getRow(i);
//遍历列数据
for (int j = 0;j < physicalNumberOfCells;j++){
Cell cell = row.getCell(j);
//获取列值
String value = getCellValues(cell);
System.out.println("列值:" + value);
}
}
}
private static String getCellValues(Cell cell) {
if (cell == null) {
return "";
}
//数值类型,整数,小数,日期
if (cell.getCellType() == CellType.NUMERIC) {
//日期与小数和整型类型转换
if (DateUtil.isCellDateFormatted(cell) ) {
//将Date转换为localDate
//LocalDate localDate = LocalDateTime.ofInstant(cell.getDateCellValue().toInstant(), ZoneId.systemDefault()).toLocalDate();
//return dateTimeFormatter.format(localDate);
return HSSFDateUtil.getJavaDate(cell.getNumericCellValue()).toString();
} else {
if (cell.getNumericCellValue() % 1 == 0) {
return new BigDecimal(cell.getNumericCellValue()).toString();
}
return String.valueOf(cell.getNumericCellValue());
}
} else if (cell.getCellType() == CellType.STRING) {
return StringUtils.trimToEmpty(cell.getStringCellValue());
} else if (cell.getCellType() == CellType.FORMULA) {
return StringUtils.trimToEmpty(cell.getCellFormula());
} else if (cell.getCellType() == CellType.BLANK) {
return "";
} else if (cell.getCellType() == CellType.BOOLEAN) {
return String.valueOf(cell.getBooleanCellValue());
} else if (cell.getCellType() == CellType.ERROR) {
return "ERROR";
} else {
return cell.toString().trim();
}
}
}
浏览器下载excel
package com.example.mybatismysql8demo.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.example.mybatismysql8demo.config.ExcelExportStyler;
import com.example.mybatismysql8demo.vo.GoodsExportError;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@RestController
public class EasypoiController {
@RequestMapping(value = "exportExcel",method = RequestMethod.GET)
public void exportExcel(HttpServletResponse response){
try {
List<GoodsExportError> goodsExportErrors = new ArrayList<>();
goodsExportErrors.add(new GoodsExportError("草莓",new BigDecimal(10),10,"商品名称格式错误"));
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setCharacterEncoding("utf-8");
//前端存在跨域不成功,设置可访问
response.setHeader("Access-Control-Allow-Origin","*");
// 这里URLEncoder.encode可以防止中文乱码
String fileName = URLEncoder.encode("goodsInfo", StandardCharsets.UTF_8);
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");
//设置sheet名
ExportParams params = new ExportParams();
params.setSheetName("商品信息表");
//设置表头
params.setTitle("商品信息");
//表头高度
params.setHeaderHeight(30);
//设置标题行高度
params.setTitleHeight((short) 15);
//全局样式
params.setStyle(ExcelExportStyler.class);
// 这里需要设置不关闭流
Workbook workbook = ExcelExportUtil.exportExcel(params, GoodsExportError.class, goodsExportErrors);
//设置错误描述背景颜色
ExcelExportStyler.setCellStyle(workbook);
//输出流
OutputStream outStream = response.getOutputStream();
//浏览器下载
workbook.write(outStream);
//关闭流
outStream.flush();
outStream.close();
} catch (IOException e) {
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
System.out.println(e.getMessage());
}
}
}
导出结果图
第四种:配置excel模板下拉框
实体类
package com.example.mybatismysql8demo.vo;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class GoodsExportError {
@Excel(name = "商品名称",orderNum = "1",width = 30)
private String goodsName;
@Excel(name = "商品价格",orderNum = "2",width = 30)
private BigDecimal price;
@Excel(name = "商品类型",orderNum = "3", height = 20, width = 30)
private String type;
@Excel(name = "商品数量",orderNum = "4",width = 30)
private Integer num;
public GoodsExportError(String goodsName, BigDecimal price, Integer num) {
this.goodsName = goodsName;
this.price = price;
this.num = num;
}
}
下拉框配置类
package com.example.mybatismysql8demo.config;
import org.apache.poi.hssf.usermodel.DVConstraint;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddressList;
public final class ExcelSelectListUtil {
/**
* firstRow 开始行号 根据此项目,默认为2(下标0开始)
* lastRow 根据此项目,默认为最大65535
* firstCol 区域中第一个单元格的列号 (下标0开始)
* lastCol 区域中最后一个单元格的列号
* strings 下拉内容
* */
public static void selectList(Workbook workbook,int firstRow, int firstCol, int lastCol, String[] strings ){
//第一个sheet
Sheet sheet = workbook.getSheetAt(0);
// 生成下拉列表 ,只对(x,x)单元格有效
CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(firstRow, 65535, firstCol, lastCol);
// 生成下拉框内容
DVConstraint dvConstraint = DVConstraint.createExplicitListConstraint(strings);
HSSFDataValidation dataValidation = new HSSFDataValidation(cellRangeAddressList, dvConstraint);
// 对sheet页生效
sheet.addValidationData(dataValidation);
}
}
浏览器下载excel
package com.example.mybatismysql8demo.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.example.mybatismysql8demo.config.ExcelSelectListUtil;
import com.example.mybatismysql8demo.vo.GoodsExportError;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
@RestController
public class EasypoiController {
@RequestMapping(value = "exportExcel",method = RequestMethod.GET)
public void exportExcel(HttpServletResponse response){
try {
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setCharacterEncoding("utf-8");
//前端存在跨域不成功,设置可访问
response.setHeader("Access-Control-Allow-Origin","*");
// 这里URLEncoder.encode可以防止中文乱码
String fileName = URLEncoder.encode("goodsInfo", StandardCharsets.UTF_8);
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");
//设置sheet名
ExportParams params = new ExportParams();
params.setSheetName("商品信息表");
//设置表头
params.setTitle("商品信息");
// 这里需要设置不关闭流
Workbook workbook = ExcelExportUtil.exportExcel(params, GoodsExportError.class, Collections.EMPTY_LIST);
//这里是自己加的带下拉框的代码,列以0开始
ExcelSelectListUtil.selectList(workbook,1, 2, 2, new String[]{"斤","两","个","袋","份"});
//输出流
OutputStream outStream = response.getOutputStream();
//浏览器下载
workbook.write(outStream);
//关闭流
outStream.flush();
outStream.close();
} catch (IOException e) {
e.printStackTrace();
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
System.out.println(e.getMessage());
}
}
}
下载结果图