/**
* 前端下载Excel
*
* @param response
* @param activityQueryVo
*/
@Override
public void export(HttpServletResponse response, ActivityQueryVo activityQueryVo) {
try {
Map<String, Object> data = getData(activityQueryVo);
Workbook workbook = export(templateUrl, data);
String fileName = "返回给前端的文件名";
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + ".xlsx", "UTF-8"));
workbook.write(response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
工具类
/**
* 模板数据替换
*
* @param templateUtl 模板路径
* @param map 数据集合
* @return
* @throws IOException
*/
private Workbook export(String templateUtl, Map<String, Object> map) throws IOException {
File file = new File(templateUtl);
String canonicalPath = file.getCanonicalPath();
// 默认为false, 设置sheetName为true, 开启多sheet,
TemplateExportParams params = new TemplateExportParams(canonicalPath, true);
Workbook workbook = ExcelExportUtil.exportExcel(params, map);
return workbook;
}
数据准备
Map<String, Object> allMap = new HashMap<String, Object>();
List<Map<String, Object>> list0 = Lists.newArrayList();
Map<String, Object> map = new HashMap<String, Object>();
// 添加多个map
map.put("peopleNumber", 100);
// 如果有多处需要循环输出的数据, 就添加多个list
list0.add(map);
allMap.put("list", list0);
数据样式
{
"msg": "操作成功",
"code": 200,
"data": {
"list": [
{
"venueCategory": "",
"peopleNumber": 100,
"num": 1,
"activityName": "非常",
"organizers": "道济四等奖",
"activityType": "",
"holdTime": "2022-02-06"
},
{
"venueCategory": "",
"peopleNumber": 15,
"num": 2,
"activityName": "测试2",
"organizers": "啊啊啊啊",
"activityType": "",
"holdTime": "2022-03-24"
},
{
"venueCategory": "",
"peopleNumber": 250,
"num": 3,
"activityName": "测试A",
"organizers": "维众",
"activityType": "",
"holdTime": "2022-09-07"
}
]
}
}
模板说明:
循环数据用{{KaTeX parse error: Expected 'EOF', got '}' at position 18: …: 集合名称 t.字段名 }̲} 包裹起来 其中 {{fe: }} 是不变的, t是easypoi默认的循环标识
为实体添加注解
@Excel(name = "场馆类别", needMerge = true)
private String venueCategory;
工具类
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import com.vxdata.activity.entity.CulturalActivity;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
/**
*
*/
@Slf4j
@Component
public class EasyPoiUtil {
public void exportExcel(List<CulturalActivity> list) throws IOException {
String outUrl = "D:\\Excel\\527.xls";
List<CulturalActivity> newList = list;
//获取导出参数
ExportParams exportParams = new ExportParams("人均接受文化场馆服务次数专项活动汇总表(1-12月)", "报送单位:", ExcelType.XSSF);
//设置导出样式
exportParams.setStyle(ExcelStyleUtil.class);
//设置行高
exportParams.setHeight((short) 6);
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, CulturalActivity.class, list);
// 获取到workbook对象之后设置每列列宽
Sheet sheet = workbook.getSheetAt(0);
// sheet.setColumnWidth(3, 30 * 256);
// sheet.setColumnWidth(5, 30 * 256);
// 动态设置行高
for(int i = 0; i <= sheet.getLastRowNum(); i ++) {
Row row = sheet.getRow(i);
setRowHeight(row);
}
FileOutputStream outputStream = new FileOutputStream(new File(outUrl));
workbook.write(outputStream);
outputStream.close();
}
private static void setRowHeight(Row row){
//根据内容长度设置行高
int enterCnt = 0;
for(int j = 0; j < row.getPhysicalNumberOfCells(); j ++) {
int rwsTemp = row.getCell(j).toString().length();
//这里取每一行中的每一列字符长度最大的那一列的字符
if (rwsTemp > enterCnt) {
enterCnt = rwsTemp;
}
}
//设置默认行高为35
row.setHeightInPoints(35);
//如果字符长度大于35,判断大了多少倍,根据倍数来设置相应的行高
if (enterCnt>35){
float d = enterCnt/35;
float f = 35*d;
if (d>2 && d<4){
f = 35*2;
}else if(d>=4 && d<6){
f = 35*3;
}else if (d>=6 && d<8){
f = 35*4;
}
row.setHeightInPoints(f);
}
}
}
工具类:
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import com.vxdata.common.config.VxdataConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
/**
* @Auther: HeJD
* @Date: 2018/10/9 13:54
* @Description:
*/
@Slf4j
public class EasyPoiUtil {
/**
* 功能描述:复杂导出Excel,包括文件名以及表名。创建表头
*
* @author HeJD
* @date 2018/10/9 13:54
* @param list 导出的实体类
* @param title 表头名称
* @param sheetName sheet表名
* @param pojoClass 映射的实体类
* @param isCreateHeader 是否创建表头
* @param fileName
* @param response
* @return
*/
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, boolean isCreateHeader, HttpServletResponse response) {
ExportParams exportParams = new ExportParams(title, sheetName);
exportParams.setCreateHeadRows(isCreateHeader);
defaultExport(list, pojoClass, fileName, response, exportParams);
}
/**
* 功能描述:复杂导出Excel,包括文件名以及表名,不创建表头
*
* @author HeJD
* @date 2018/10/9 13:54
* @param list 导出的实体类
* @param title 表头名称
* @param sheetName sheet表名
* @param pojoClass 映射的实体类
* @param fileName
* @param response
* @return
*/
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response) {
defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName));
}
/**
* 功能描述:Map 集合导出
*
* @author HeJD
* @date 2018/10/9 13:54
* @param list 实体集合
* @param fileName 导出的文件名称
* @param response
* @return
*/
public static void exportExcel(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
defaultExport(list, fileName, response);
}
/**
* 功能描述:默认导出方法
*
* @author HeJD
* @date 2018/10/9 13:54
* @param list 导出的实体集合
* @param fileName 导出的文件名
* @param pojoClass pojo实体
* @param exportParams ExportParams封装实体
* @param response
* @return
*/
private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) {
exportParams.setStyle(ExcelStyleUtil.class);
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
if (workbook != null) {
downLoadExcel(fileName, response, workbook);
}
}
/**
* 功能描述:Excel导出
*
* @author HeJD
* @date 2018/10/9 15:35
* @param fileName 文件名称
* @param response
* @param workbook Excel对象
* @return
*/
private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {
ServletOutputStream outputStream = null;
try {
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" +URLEncoder.encode(fileName, "UTF-8") );
outputStream = response.getOutputStream();
workbook.write(outputStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 导出到若依的本地目录
* @param list 实体集合
* @param title 表头名称
* @param sheetName sheet表名
* @param pojoClass 映射的实体类
* @param fileName 文件名
*/
public static void exportExcelToLocal(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName) {
ExportParams exportParams = new ExportParams(title, sheetName);
exportParams.setStyle(ExcelStyleUtil.class);
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
if (workbook != null) {
// 本地资源路径
String localPath = VxdataConfig.getDownloadPath();
File savefile = new File(localPath);
if (!savefile.exists()) {
savefile.mkdirs();
}
FileOutputStream fos = null;
try {
String excelName = localPath + fileName;
fos = new FileOutputStream(excelName);
workbook.write(fos);
fos.close();
log.debug("export Excel Success: {}", fileName);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 功能描述:默认导出方法
*
* @author HeJD
* @date 2018/7/23 15:33
* @param list 导出的实体集合
* @param fileName 导出的文件名
* @param response
* @return
*/
private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);
if (workbook != null) ;
downLoadExcel(fileName, response, workbook);
}
/**
* 功能描述:根据文件路径来导入Excel
*
* @author HeJD
* @date 2018/10/9 14:17
* @param filePath 文件路径
* @param titleRows 表标题的行数
* @param headerRows 表头行数
* @param pojoClass Excel实体类
* @return
*/
public static <T> List<T> importExcel(String filePath, Integer titleRows, Integer headerRows, Class<T> pojoClass) {
//判断文件是否存在
if (StringUtils.isBlank(filePath)) {
return null;
}
ImportParams params = new ImportParams();
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
try {
list = ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
} catch (NoSuchElementException e) {
throw new RuntimeException("模板不能为空");
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
/**
* 功能描述:根据接收的Excel文件来导入Excel,并封装成实体类
*
* @author HeJD
* @date 2018/10/9 14:17
* @param file 上传的文件
* @param titleRows 表标题的行数
* @param headerRows 表头行数
* @param pojoClass Excel实体类
* @return
*/
public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class<T> pojoClass) {
if (file == null) {
return null;
}
ImportParams params = new ImportParams();
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
try {
list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params);
} catch (NoSuchElementException e) {
throw new RuntimeException("excel文件不能为空");
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return list;
}
}
样式配置:
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.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
public class ExcelStyleUtil implements IExcelExportStyler {
// 数据行类型
private static final String DATA_STYLES = "dataStyles";
// 标题类型
private static final String TITLE_STYLES = "titleStyles";
//数据行样式
private CellStyle styles;
// 标题样式
private CellStyle titleStyle;
public ExcelStyleUtil(Workbook workbook) {
this.init(workbook);
}
private void init(Workbook workbook) {
this.styles = initStyles(workbook);
this.titleStyle = initTitleStyle(workbook);
}
@Override
public CellStyle getHeaderStyle(short i) {
return null;
}
/**
* 标题样式
*/
@Override
public CellStyle getTitleStyle(short i) {
return titleStyle;
}
@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 initTitleStyle(Workbook workbook) {
return buildCellStyle(workbook,TITLE_STYLES);
}
/**
* 初始化--数据行样式
* @param workbook
* @return
*/
private CellStyle initStyles(Workbook workbook) {
return buildCellStyle(workbook,DATA_STYLES);
}
/**
* 设置单元格样式
* @param workbook
* @param type 类型 用来区分是数据行样式还是标题样式
* @return
*/
private CellStyle buildCellStyle(Workbook workbook,String type) {
CellStyle style = workbook.createCellStyle();
// // 字体样式
// Font font = workbook.createFont();
// if(TITLE_STYLES.equals(type)){
// font.setFontHeightInPoints((short)12);
// font.setBold(true);
// }
// if(DATA_STYLES.equals(type)){
// font.setFontHeightInPoints((short)10);
// }
// font.setFontName("Courier New");
// style.setFont(font);
// 设置底边框
// style.setBorderBottom(BorderStyle.THIN);
// // 设置左边框
// style.setBorderLeft(BorderStyle.THIN);
// // 设置右边框;
// style.setBorderRight(BorderStyle.THIN);
// // 设置顶边框;
// style.setBorderTop(BorderStyle.THIN);
// // 设置底边颜色
// style.setBottomBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
// // 设置左边框颜色;
// style.setLeftBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
// // 设置右边框颜色;
// style.setRightBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
// // 设置顶边框颜色;
// style.setTopBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
// 设置自动换行;
style.setWrapText(false);
// 设置水平对齐的样式为居中对齐;
style.setAlignment(HorizontalAlignment.CENTER);
// 设置垂直对齐的样式为居中对齐;
style.setVerticalAlignment(VerticalAlignment.CENTER);
return style;
}
}
使用:
EasyPoiUtil.exportExcelToLocal(数据集合list, 表头名称,sheet表名, 实体.class, 输出文件全路径);
正确版本对应关系:
一开始的业务是生成word文件, 使用 poi-tl 生成 , 我的poi-tl 版本是1.5.0
<dependency>
<groupId>com.deepoovegroupId>
<artifactId>poi-tlartifactId>
<version>1.5.0version>
dependency>
对应的 org.apache.poi 版本是3.16
但是后来需要生成Excel , 我使用的是 easypoi 版本是4.1.0
<dependency>
<groupId>cn.afterturngroupId>
<artifactId>easypoi-spring-boot-starterartifactId>
<version>4.1.0version>
dependency>
这个时候我在实行生成Excel的时候就报错误了
org.apache.poi.ss.usermodel.Cell.getCellType()Lorg/apache/poi/ss/usermodel/CellType
java.lang.ClassNotFoundException: org.apache.poi.poifs.filesystem.FileMagic
查询了一下是org.apache.poi 版本太低, 需要换成3.8以上版本, 于是我就把org.apache.poi 换成 4.1.0版本, 但是这个时候poi-tl又报错说版本不匹配
解决方案: 将poi-tl升级到1.6.0版本, 将org.apache.poi 升级到4.1.0版本
<dependency>
<groupId>com.deepoovegroupId>
<artifactId>poi-tlartifactId>
<version>1.6.0version>
dependency>
poi-tl 的1.5.0版本使用的org.apache.poi 是3.16 , 而1.6.0版本的poi-tl 对应的就是 4.1.0 版本的org.apache.poi