package com.example.utils.easyexcel;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
/**
* 描述:
* EasyExcel的基础封装
*
* @author XueGuCheng
* @create 2021-03-19 23:01
*/
@Slf4j
public class EasyExcel {
/**
* 设置响应头
*
* @param response 回应的请求数据
* @param fileName 文件名字
*/
public static void setHead(HttpServletResponse response, String fileName) {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码
try {
fileName = URLEncoder.encode(fileName, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
log.error("编码异常");
}
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
}
/**
* 设置Excel的格式
*
* @return 格式化后的Excel
*/
public static HorizontalCellStyleStrategy formatExcel() {
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
headWriteCellStyle.setFillBackgroundColor(IndexedColors.WHITE.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short) 10);
headWriteCellStyle.setWriteFont(headWriteFont);
// 内容的策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
WriteFont contentWriteFont = new WriteFont();
// 字体大小
contentWriteFont.setFontHeightInPoints((short) 10);
contentWriteCellStyle.setWriteFont(contentWriteFont);
// 设置自动换行
contentWriteCellStyle.setWrapped(true);
// 设置垂直居中
contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 设置水平居中
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
}
/**
* 设置头部单元格宽度
*/
public static class ExcelWidthStyleStrategy extends AbstractColumnWidthStyleStrategy {
@Override
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
// 设置宽度
Sheet sheet = writeSheetHolder.getSheet();
sheet.setColumnWidth(cell.getColumnIndex(), 5000);
}
}
}
package com.example.utils.easyexcel;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
/**
* @ClassName: EasyExcelUtils
* @Description: EasyExcel工具类(替换com.example.utils.easyexcel)
* @Author: jiangbeiping
* @Data: 2021/3/18 16:46
* @Version: 1.0
*/
@Slf4j
public class EasyExcelUtils {
/**
* 每个sheet的容量,即超过60000时就会把数据分sheet
*/
private static final int PAGE_SIZE = 60000;
/**
* 导出报表(使用注解方式设置Excel头数据)
*
* @param response 响应请求
* @param data 报表数据
* @param fileName 文件名字
* @param excelClass 报表实体类的Class(根据该Class的属性来设置Excel的头属性)
*/
public static void exportByExcel(HttpServletResponse response, List<?> data, String fileName, Class<?> excelClass) throws IOException {
@Cleanup ByteArrayOutputStream os = new ByteArrayOutputStream();
// ServletOutputStream os = response.getOutputStream();
long exportStartTime = System.currentTimeMillis();;
log.info("报表导出Size: " + data.size() + "条。");
// 把查询到的数据按设置的sheet的容量进行切割
List<? extends List<?>> lists = SplitList.splitList(data, PAGE_SIZE);
// 设置响应头
com.example.utils.easyexcel.EasyExcel.setHead(response, fileName);
// 格式化Excel数据
// EasyExcelBasic.formatExcel():设置Excel的格式
// EasyExcelBasic.ExcelWidthStyleStrategy():设置头部单元格宽度
ExcelWriter excelWriter = EasyExcel.write(os, excelClass).registerWriteHandler(com.example.utils.easyexcel.EasyExcel.formatExcel()).registerWriteHandler(new com.example.utils.easyexcel.EasyExcel.ExcelWidthStyleStrategy()).build();
// 浏览器访问url直接下载文件的方式
//ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), excelClass).registerWriteHandler(com.example.utils.easyexcel.EasyExcel.formatExcel()).registerWriteHandler(new com.example.utils.easyexcel.EasyExcel.ExcelWidthStyleStrategy()).build();
ExcelWriterSheetBuilder excelWriterSheetBuilder;
WriteSheet writeSheet;
for (int i = 1; i <= lists.size(); ++i) {
excelWriterSheetBuilder = new ExcelWriterSheetBuilder(excelWriter);
excelWriterSheetBuilder.sheetNo(i).sheetName("sheet" + i);
writeSheet = excelWriterSheetBuilder.build();
excelWriter.write(lists.get(i - 1), writeSheet);
}
// 必须要finish才会写入,不finish只会创建empty的文件
excelWriter.finish();
byte[] content = os.toByteArray();
@Cleanup InputStream is = new ByteArrayInputStream(content);
// 文件落地,用来测试文件的格式和数据的完整性
// @Cleanup:lombok关流注解
//FileOutputStream fileOutputStream = new FileOutputStream("/data/logs/" + fileName + ".xlsx");
//@Cleanup BufferedInputStream bis = new BufferedInputStream(is);
//@Cleanup BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream);
//byte[] buff = new byte[2048];
//int bytesRead;
//while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
// bos.write(buff, 0, bytesRead);
// }
//log.info("文件落地磁盘");
// 文件上传到OSS
FileUploadUtil_Test.upLocalFileToOss(is, fileName);
System.out.println("报表导出结束时间:" + new Date() + ";导出耗时: " + (System.currentTimeMillis() - exportStartTime) + "ms");
}
}
package com.example.utils.easyexcel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @ClassName: SplitList
* @Description: EasyExcelUtils类的辅助类(切割查询的数据)
* @Author: jiangbeiping
* @Data: 2021/3/19 17:38
* @Version: 1.0
*/
public class SplitList {
/**
* 切割查询的数据
* @param list 需要切割的数据
* @param len 按照什么长度切割
* @param
* @return
*/
public static <T> List<List<T>> splitList(List<T> list, int len) {
if (list == null || list.size() == 0 || len < 1) {
return null;
}
List<List<T>> result = new ArrayList<List<T>>();
int size = list.size();
int count = (size + len - 1) / len;
for (int i = 0; i < count; i++) {
List<T> subList = list.subList(i * len, (Math.min((i + 1) * len, size)));
result.add(subList);
}
return result;
}
/**
* 集合平均分组
* @param source 源集合
* @param n 分成n个集合
* @param 集合类型
* @return 平均分组后的集合
*/
public static <T> List<List<T>> groupList(List<T> source, int n) {
if (source == null || source.size() == 0 || n < 1) {
return null;
}
if (source.size() < n) {
return Collections.singletonList(source);
}
List<List<T>> result = new ArrayList<List<T>>();
int number = source.size() / n;
int remaider = source.size() % n;
// 偏移量,每有一个余数分配,就要往右偏移一位
int offset = 0;
for (int i = 0; i < n;i++) {
List<T> list1 = null;
if (remaider > 0){
list1 = source.subList(i * number + offset,(i + 1) * number + offset + 1);
remaider--;
offset++;
}else {
list1 = source.subList(i * number + offset, (i+1) * number + offset);
}
result.add(list1);
}
return result;
}
}
package com.example.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import lombok.Data;
@Data
public class User {
@ExcelProperty(value = "ID",index = 2)
private long id;
@ExcelProperty(value = "用户名",index = 3)
private String name;
@ExcelProperty(value = "居住城市",index = 4)
private String city;
@ExcelProperty(value = "性别",index = 5)
private String sex;
@ExcelProperty(value = "序号",index = 1)
private Integer num;
@ExcelProperty(value = "时间",index = 6)
@DateTimeFormat("yyyy-MM-dd hh:mm:ss")
private String time;
}
package com.example.controller;
import com.example.service.UserService;
import com.example.utils.easyexcel.EasyExcel;
import com.example.utils.easyexcel.EasyExcelUtils;
import com.example.vo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* 描述:
* Excel测试
*
* @author XueGuCheng
* @create 2021-03-20 22:27
*/
@RestController
@RequestMapping("Excel")
public class ExcelController {
@Autowired
private UserService userService;
// http://localhost:8081/Excel/EasyExce
@GetMapping("/EasyExce")
public void doExport(HttpServletResponse response) throws IOException {
List<User> users = userService.ListUser();
EasyExcelUtils.exportByExcel(response,users,"EasyExcel测试",User.class);
}
}
第一列是空,因为@ExcelProperty注解的index是从o开始的