<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.4</version></dependency>
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {@ExcelProperty(value = {"年级"}, index = 0)private String grade;@ExcelProperty(value = {"姓名"}, index = 1)private String name;@ExcelProperty(value = {"年龄"}, index = 2)private Integer age;@ExcelProperty(value = {"性别"}, index = 3)private String sex;@ExcelProperty(value = {"综合素质评价"}, index = 4)@ColumnWidth(50)private String evaluate;@ExcelProperty(value = {"综合评分"}, index = 5)@ColumnWidth(20)private String score;}
public class DataReady {public static List<Student> listStudent() {// 综合素质评价List<String> evaluateList = evaluateList();List<Student> students = new ArrayList<>();students.add(new Student("三年一班", "小东", 12, "男", evaluateList.get(0), "优"));students.add(new Student("三年一班", "小南", 12, "男", evaluateList.get(1), "优"));students.add(new Student("三年二班", "小西", 13, "男",evaluateList.get(2), "优"));students.add(new Student("三年二班", "小北", 12, "男",evaluateList.get(3), "优"));students.add(new Student("三年二班", "小红", 12, "女",evaluateList.get(4), "优"));students.add(new Student("三年三班", "小独", 12, "男",evaluateList.get(5), "优"));return students;}private static List<String> evaluateList() {List<String> strings = new ArrayList<>();strings.add("你活泼乐观,自信心强,尊敬老师,是你的最大优点,作业能按时完成,有强烈的好奇心,可惜的是你上课管不住自己,不守纪律,老师提出问题不经过深思熟虑");strings.add("该生在校期间学习态度端正,成绩优良");strings.add("积极参与各项实践活动,全面的锻炼自己。");strings.add("你是个天性好动的男孩。想到你,浮现在老师眼前的是你积极劳动、礼貌待人的身影。");strings.add("热情活泼,全面发展,对于自己喜欢的工作,能投入极大的热情去做,哪怕再苦再累,也不计较。");strings.add("好");return strings;}
}
效果
EasyExcelController
@GetMapping("/download")
public void download(HttpServletResponse response) throws IOException {service.download(response);
}
手机EXCEL?EasyExcelService
/*** 基础下载*/
void download(HttpServletResponse response) throws IOException;
EasyExcelServiceImpl
/*** 基础下载*/
@Override
public void download(HttpServletResponse response) throws IOException {String message = "下载文件失败";String filename = "学生信息.xlsx";try {// 设置响应头response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "utf-8"));response.setContentType("application/octet-stream;charset=UTF-8"); // 类型response.setCharacterEncoding("utf-8");// 获取导出数据List<Student> students = DataReady.listStudent();// 数据导出EasyExcel.write(response.getOutputStream(), Student.class).sheet("Sheet1").doWrite(students);} catch (Exception e) {e.printStackTrace();// 重置responseresponse.reset();response.setContentType("application/json");response.setCharacterEncoding("utf-8");response.getWriter().println(JsonUtil.writeValueAsString(message));}
}
测试
浏览器访问: http://localhost:8060/easyExcel/download 下载Excel
目标
效果
surf下载、自定义样式
public class ExcelUtils {/*** 单元格水平样式策略*/public static HorizontalCellStyleStrategy setHorizontalCellStyleStrategy(){// 头部样式WriteCellStyle headWriteCellStyle = new WriteCellStyle();// 内容样式WriteCellStyle contentWriteCellStyle = new WriteCellStyle();contentWriteCellStyle.setWrapped(true); // 数据超出换行contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); // 水平居中// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);}}
注册自定义样式
目标
效果
统计“指定列“ 的“哪几行”需要进行合并
表格软件电脑版。使用Map集合进行统计
Map<String, List<RowRange>> merStrategyMap
RowRange
/*** 用于记录 Excel某一列, 某一类型的* 合并的开始和结束位置*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class RowRange {/*** 行合并开始位置*/private int start;/*** 行合并结束位置*/private int end;
}
EasyExcelServiceImpl
/*** 添加合并策略*/
private Map<String, List<RowRange>> addMerStrategy(List<Student> students) {// key: 表示需要合并的列 value: 表示该列需要合并的行集合Map<String, List<RowRange>> strategyMap = new HashMap<>();// 前一条数据。 (用于判断是否需要合并)Student preStudent = null;for (int i = 0; i < students.size(); i++) {Student student = students.get(i);if (preStudent != null) {// 年级合并if (student.getGrade().equals(preStudent.getGrade())) {fillStrategyMap(strategyMap, "0", i);}}preStudent = student;}return strategyMap;
}
/*** 计算需要合并的行**/
public static void fillStrategyMap(Map<String, List<RowRange>> strategyMap, String key, int index) {List<RowRange> rowRangeList = strategyMap.get(key) == null ? new ArrayList<>() : strategyMap.get(key);// 判断是否新增分段boolean flag = false;for (RowRange dto : rowRangeList) {//分段list中是否有end索引是上一行索引的,如果有,则索引+1if (dto.getEnd() == index) {dto.setEnd(index + 1);flag = true;}}//如果没有,则新增分段if (!flag) {rowRangeList.add(new RowRange(index, index + 1));}strategyMap.put(key, rowRangeList);
}
在上一步已经统计出了,哪些列的行需要进行合并, 具体的合并工作在这个类完成
/*** 合并类*/
public class MergeStrategy extends AbstractMergeStrategy {// Map<列, 要进行合并的行>private Map<String, List<RowRange>> strategyMap;public MergeStrategy(Map<String, List<RowRange>> strategyMap) {this.strategyMap = strategyMap;}/*** 每一个单元格都会进入到该方法* 第一个单元格进入到该方法时就进行合并操作,其余单元格进入到该方法时不进行合并操作*/@Overrideprotected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {int rowIndex = cell.getRowIndex();int columnIndex1 = cell.getColumnIndex();if (rowIndex == 1 && columnIndex1 == 0) {for (Map.Entry<String, List<RowRange>> entry : strategyMap.entrySet()) {// 哪一列的行需要进行合并int columnIndex = Integer.parseInt(entry.getKey());entry.getValue().forEach(rowRange -> {// 对行进行合并(四个参数: 行开始 行结束 列开始 列结束)sheet.addMergedRegionUnsafe(new CellRangeAddress(rowRange.getStart(), rowRange.getEnd(), columnIndex, columnIndex));});}}}
}
表格软件,关于 if (rowIndex == 1 && columnIndex1 == 0) 的说明
EasyExcelServiceImpl
效果 行高发生了变化
在实体中添加注解即可设置
注意
对超出单元格部分的数据不会自适应高度显示了。这是正常的,因为设置了行高将单元格的高度固定了。
easyExcel如何使用。效果: 行高发生变化且超出单元格部分自适应高度显示
思路: 某一行中,如果某个单元格数据超出了单元格则不设置该行的行高,则该行的行高会根据 “四 单元格样式设置” 中的配置进行自适应高度显示
行高样式策略类
/*** 自定义行高* 注意: 实体类上不可加 @HeadRowHeight(value = 30) 注解,不然此方法失效(会进入到SimpleRowHeightStyleStrategy)*/
public class EvaSysRowHeightStyleStrategy extends AbstractRowHeightStyleStrategy {private Map<Integer, Integer> map = new HashMap<>();// 列数(用于判断当前行是否执行结束了)private Integer cellNum;// 行高private static final Float height = 30f;// 需要设置行高的限制值(如果数据长度 < heightLimit 则需要设置行高,否则不需要)private static final Integer heightLimit = 40;public EvaSysRowHeightStyleStrategy(int cellNum) {this.cellNum = cellNum;}/*** 设置标题的行高*/@Overrideprotected void setHeadColumnHeight(Row row, int i) {row.setHeightInPoints((float)40);}@Overrideprotected void setContentColumnHeight(Row row, int i) {row.forEach(cell -> {// 设置行高和解决数据显示不完整问题// 当前行号int currentNum = cell.getRow().getRowNum();// 当前数据的长度Integer currentLength = getDataLength(cell);// 当前单元格列数int currentCellNum = cell.getColumnIndex()+1;// 如果已经是最后一列,则判断是否需要设置行高if (cellNum == currentCellNum) {// 如果数据最大长度 <= 20 则设置行高Integer max = map.get(currentNum);max = max > currentLength? max: currentLength;if(max <= heightLimit) {cell.getRow().setHeightInPoints(height);}} else {// 获取当前行最大的数据长度。因为可能是新的行,获取数据时可能为null,如果为null,我们就置max为0Integer max = map.get(currentNum) == null? 0: map.get(currentNum);// 比较获取最大的数据长度更新max的值max = max > currentLength? max: currentLength;map.put(currentNum, max);}});}/*** 获取数据长度*/private Integer getDataLength(Cell cell) {CellType type = cell.getCellTypeEnum();String data;switch (type) {case STRING: data = cell.getStringCellValue(); break;case FORMULA: data = cell.getCellFormula(); break;case NUMERIC: data = String.valueOf(cell.getNumericCellValue()); break;default: data = "";}return data.length();}
}
注: 实体类中不可加 @HeadRowHeight, 不然该策略类会失效(会使用 SimpleRowHeightStyleStrategy 进行行高的设置)
注册策略类
EasyExcelServiceImpl
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态