EasyExcel实现 多标题、动态标题、单元格合并【动态合并最后一行数据】,并且实现一个Excel表有多个sheet,一个sheet有多个表;

  • 一、根据文档写了个实体类
  • 二、参照文档写的两个方法,分别是**标题**与**数据**
  • 三、【多个sheet】参照EasyExcel官网导出数据在不同sheet上
  • 四、【同一sheet多个表】
  • 五、【Excel中多个sheet,并且一个sheet多个表】
  • 六、博主根据自己业务写的导出【仅供参考】
  • 七、博主自己重写的合并类【仅供参考】
  • 八、博主导出的excel【图】

)

因工作需要导出数据,导出到excel的格式如下:
需求1:假设有A、B员工,那么就相当于有两张工作表【sheet】
需求2:假设A员工要展示一年的工资,要那么同一工作表【sheet】就得有多个表




再此先奉献上EasyExcel语雀 或者 EasyExcel官网
我最开始看的官网,但是官网又没有语雀写的多。但是耐不住官网的简洁。嗯…我觉得简洁

一、根据文档写了个实体类

package com.admin.ctt.entity.excelPojo;import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import lombok.EqualsAndHashCode;import java.util.Date;/*** 导出员工的合同提成及绩效* @author LunarYouI* @create 2022-06-28 17:05*/@Data
@EqualsAndHashCode
//所有标题的高
@HeadRowHeight(30)
//所有内容的高
@ContentRowHeight(25)
//所有单元格列宽
@ColumnWidth(25)
public class EmployeeSalaryPojo {//    @ColumnWidth(50) //指定某一个单元格列宽
//    @ExcelProperty({"员工工资表", "标题1", "合同提成/绩效", "字符串标题"})
//    private String string;
//
//    @ExcelProperty({"员工工资表", "标题1", "合同提成/绩效", "日期标题"})
//    private Date date;
//
//    @ExcelProperty({"员工工资表", "标题1", "合同提成/绩效", "数字标题"})
//    private Double doubleData;//员工名称private String name;//员工日期private Date date;//员工工资private Double doubleData;
}

二、参照文档写的两个方法,分别是标题数据

  • 标题这里我定义了两个人,分别是王某、李某,分别对应两个sheet
/*** 数据* LunarYouI*/private static List<EmployeeSalaryPojo> data() {List<EmployeeSalaryPojo> list = new ArrayList<>();for (int i = 0; i < 10; i++) {EmployeeSalaryPojo data = new EmployeeSalaryPojo();data.setName("某人" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}return list;}/*** 标题* @return*/private static Map<String, List<List<String>>> head() {String a = "管理员:张某   工资时间:2022.01    职位:员工/执行人   姓名:王某";String b = "管理员:李某   工资时间:2022.01    职位:员工/执行人   姓名:李某";Map<String, List<List<String>>> mp = new HashMap<>();/*** 人1*/List<List<String>> head = new ArrayList<>();List<String> list1 = new ArrayList<>();list1.add("员工工资表");list1.add(a);list1.add("合同提成/绩效");list1.add("员工名称");head.add(list1);List<String> list2 = new ArrayList<>();list2.add("员工工资表");list2.add(a);list2.add("合同提成/绩效");list2.add("员工日期");head.add(list2);List<String> list3 = new ArrayList<>();list3.add("员工工资表");list3.add(a);list3.add("合同提成/绩效");list3.add("员工工资");head.add(list3);mp.put("r1",head);/*** 人2*/List<List<String>> head1 = new ArrayList<>();List<String> list4 = new ArrayList<>();list4.add("员工工资表");list4.add(b);list4.add("合同提成/绩效");list4.add("员工名称");head1.add(list4);List<String> list5 = new ArrayList<>();list5.add("员工工资表");list5.add(b);list5.add("合同提成/绩效");list5.add("员工日期");head1.add(list5);List<String> list6 = new ArrayList<>();list6.add("员工工资表");list6.add(b);list6.add("合同提成/绩效");list6.add("员工工资");head1.add(list6);mp.put("r2",head1);return mp;}

三、【多个sheet】参照EasyExcel官网导出数据在不同sheet上

 public static void simpleWrite() {ExcelWriter excelWriter = null;// 方法2: 如果写到不同的sheet 同一个对象String fileName = "F:\\temporary\\" + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";// 这里 指定文件try {excelWriter = EasyExcel.write(fileName, EmployeeSalaryPojo.class).build();// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面for (int i = 0; i < 5; i++) {// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();//写入到excel和上面空开几行writeSheet.setRelativeHeadRowIndex(1);// 分页去数据库查询数据 这里可以去数据库查询每一页的数据List<EmployeeSalaryPojo> data = data();excelWriter.write(data, writeSheet);}} finally {if(excelWriter!=null){excelWriter.finish();}}}

这里没有标题是因为 EmployeeSalaryPojo实体类中的前字段三个被注释了,解开前三个注释后三个就可以了

四、【同一sheet多个表】

public static void simpleWrite() {ExcelWriter excelWriter = null;// 方法2: 如果写到不同的sheet 同一个对象String fileName = "F:\\temporary\\" + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";// 这里 指定文件try {excelWriter = EasyExcel.write(fileName, EmployeeSalaryPojo.class).build();// 把sheet设置为不需要头 不然会输出sheet的头 这样看起来第一个table 就有2个头了WriteSheet writeSheet = EasyExcel.writerSheet("模板").needHead(Boolean.FALSE).build();//距离上边空一行writeSheet.setRelativeHeadRowIndex(10);// 这里必须指定需要头,table 会继承sheet的配置,sheet配置了不需要,table 默认也是不需要WriteTable writeTable0 = EasyExcel.writerTable(0).needHead(Boolean.TRUE).build();WriteTable writeTable1 = EasyExcel.writerTable(1).needHead(Boolean.TRUE).build();// 第一次写入会创建头excelWriter.write(data(), writeSheet, writeTable0);// 第二次写如也会创建头,然后在第一次的后面写入数据excelWriter.write(data(), writeSheet, writeTable1);} finally {if(excelWriter!=null){excelWriter.finish();}}}

五、【Excel中多个sheet,并且一个sheet多个表】

 public static void simpleWrite() {ExcelWriter excelWriter = null;// 方法2: 如果写到不同的sheet 同一个对象String fileName = "F:\\temporary\\" + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";// 这里 指定文件try {excelWriter = EasyExcel.write(fileName, EmployeeSalaryPojo.class).build();//设置动态标题Map<String, List<List<String>>> head = head();int i = 0;for (String key : head.keySet()) {i++;/*** 1、获取到value; 获取到的List<List<String>>就表示是同一个sheet的数据*/List<List<String>> lists = head.get(key);// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样【这里必须要加.needHead(Boolean.FALSE),否则会多处标题而没数据】WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).needHead(Boolean.FALSE).build();//动态标题writeSheet.setHead(lists);//写入到excel和上面空开几行writeSheet.setRelativeHeadRowIndex(1);/*** 2、相同数据写在同一个sheet里面* 这里的j表示1个sheet会有几个表单数据*/for (int j = 0;j<3;j++) {WriteTable writeTable = EasyExcel.writerTable(j).needHead(Boolean.TRUE).build();excelWriter.write(data(), writeSheet, writeTable);}}} finally {if(excelWriter!=null){excelWriter.finish();}}}





下面就是我根据上面的逻辑和自己的实际业务导出来的表,因为这个项目是二开(前任开发留下的问题,导致很多逻辑业务走不通),所以下面代码是我根据设计图然后屎山堆出来的

六、博主根据自己业务写的导出【仅供参考】

这里主要看点就动态标题(因为码代码的时候发现一个sheet下面的所有子表全部都显示6月份,按理来说应该是6月份-5月份一直推下去)与单元格合并(因为我这里是每个子表最后一行代码进行合并,所以我重写了AbstractMergeStrategy);如果不考虑一些特殊的合并,那么使用这两个都够了OnceAbsoluteMergeStrategyLoopMergeStrategy,可自行百度查看

/*** LunarYouI 导出数据  导出员工的合同与绩效* package com.admin.ctt.entity.excelPojo;* @param params* @param response*/@PostMapping("/export")@RequiresRoles(Role.ADMIN)public R export(@RequestParam Map<String, Object> params, HttpServletResponse response) throws IOException {/*** 思路:*         1、获取到所有的用户(员工),10个员工就是10个sheet*        2、按照月份获取每个员工每月对应的数据,获取到就立即输出。【条件为:每个月份显示的数据不同】*/ExcelWriter excelWriter = null;//文件名与后缀名String fileName = "F:\\temporary\\" + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";try {//指定文件excelWriter = EasyExcel.write(fileName, ExprotEntity.class).build();/*** 导出的具体数据=============================================================================================*///1、获取当前用户的idSysUserEntity user = ShiroUtils.getObject();String id = user.getId();//2、根据id获取到当前管理员下的人有哪些,前提是没有被删除sysClientuserService.byManagerIdRecursion(id);Set<String> set = SysClientuserServiceImpl.set;List<String> list = new ArrayList<String>(set);//3、从list筛选出当前管理员下的所有员工Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {String ex = iterator.next();int count = sysUserRoleService.count(new QueryWrapper<SysUserRoleEntity>().eq("user_id", ex).eq("role_id", "8"));if (count==0) {iterator.remove();}}//3、循环遍历id;这里有多少个员工就表示有多少个sheet(前提是能在employee_attendance_record表中找到当前员工)int iii = 0;for (String userId : list) {int select = 0;iii++;//获取员工的上级(管理员)String sj = employeeAttendanceRecordService.selectByStaffId(userId);if(!(sj.equals("0"))){SysClientuserEntity one = sysClientuserService.getOne(new QueryWrapper<SysClientuserEntity>().eq("account_id", sj).select("true_name"));sj = one.getTrueName();}//员工的姓名SysClientuserEntity clientuser = sysClientuserService.getOne(new QueryWrapper<SysClientuserEntity>().eq("account_id", userId).select("true_name"));String ygName = clientuser.getTrueName();//4、根据员工id获取对应员工的出勤月份(最多12个月); 这里有几个月就表示一个sheet有几个表QueryWrapper<EmployeeAttendanceRecordEntity> queryWrapper = new QueryWrapper<>();queryWrapper.select("DATE_FORMAT(attendance_months,\"%Y-%m\") as attendanceMonths").eq("importor_id",userId).groupBy("attendance_months").orderByDesc("attendance_months").last("limit 12");List<EmployeeAttendanceRecordEntity> yue = employeeAttendanceRecordService.list(queryWrapper);/*** excel 设置不同的sheet*/// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样【这里必须要加.needHead(Boolean.FALSE),否则会多处标题而没数据】WriteSheet writeSheet = EasyExcel.writerSheet(iii, ygName).needHead(Boolean.FALSE).build();//动态标题List<List<String>> lists = new ArrayList<>();//写入到excel和上面空开几行writeSheet.setRelativeHeadRowIndex(1);//5、根据月份获取对应的数据List<List<ExprotEntity>> list1 = new ArrayList<>();//下面有很多个月的数据,每生成一月数据就存储到这里的List<List<ExprotEntity>>,以便后面循环//               int abc = 0;for (EmployeeAttendanceRecordEntity y : yue) {//当前年月(根据这个条件获取对应月份数据)String attendanceMonths = y.getAttendanceMonths();//获取当前用户 管理员的名字、年月、职位、姓名String biaoti = "管理员:"+sj+"   工资时间:"+attendanceMonths+"     姓名:"+ygName;
//                  if(abc == 0){//                      head.clear();
//                      lists.clear();//循环6次,因为有6个字段for(int i = 0;i<6;i++){List<String> head = new ArrayList<>();head.add("员工工资表");head.add(biaoti);head.add("合同提成/绩效");switch (i){case 0:head.add(ExcelText.NUM);break;case 1:head.add(ExcelText.COMPANY_NAME);break;case 2:head.add(ExcelText.NUMBER);break;case 3:head.add(ExcelText.MONEY);break;case 4:head.add(ExcelText.RETURNED_MONEY);break;case 5:head.add(ExcelText.PUSH_MONEY);break;}lists.add(head);}
//                  }
//                  else{//                      lists.set(1,);
//                  }
//                  abc+=1;//【共有字段】获取到了当前用户所有合同的信息【序号、单位名称、合同编号、金额(这里的金额只是合同主产品的金额,服务项目里的是次产品)】List<ExprotEntity> exprotEntity = contractService.exportSelect(userId);for (ExprotEntity data : exprotEntity) {//合同idString contractId = data.getContractId();/*** 获取到当前合同id下的次产品的总金额:金额(次+主)、回款金额、提成金额*///金额(次+主)ServiceItemEntity contractIdDataOne = serviceItemService.getOne(new QueryWrapper<ServiceItemEntity>().eq("contract_id", contractId).select("sum(price) as sumAll"));if (contractIdDataOne != null) {String s = new BigDecimal(contractIdDataOne.getSumAll()).add(new BigDecimal(data.getMoney())).toString();data.setMoney(s);}//回款金额(指定月份 且状态为通过1)PaybackEntity contractIdDataTwo = paybackService.getOne(new QueryWrapper<PaybackEntity>().eq("contract_id", contractId).eq("status", "1").eq("DATE_FORMAT(create_time,\"%Y-%m\")", attendanceMonths).select("sum(money) as sumAll"));if (contractIdDataTwo != null) {data.setReturnedMoney(contractIdDataTwo.getSumAll());}/*** 提成金额(当前合同每一笔回款*对应的产品的比列=一笔提成金额;所有提成金额总和)* 回款-提成类型(0普通百分比提成,1高提成,2单价提成)-提成价格(百分比/具体价格)*/List<Map<String, Object>> push = contractService.push(contractId, attendanceMonths);BigDecimal sumAll = new BigDecimal("0");for (Map<String, Object> je : push) {BigDecimal total = new BigDecimal(je.get("money").toString());String commissionType = je.get("commission_type").toString();BigDecimal commissionPrice = new BigDecimal(je.get("commission_price").toString());//0普通百分比提成,1高提成  都是百分比计算if(commissionType.equals("0") || commissionType.equals("1")){BigDecimal divide = commissionPrice.divide(new BigDecimal("100"), 2, BigDecimal.ROUND_DOWN);BigDecimal multiply = total.multiply(divide);sumAll = sumAll.add(multiply);}//2单价提成 拿实际价格else{sumAll = sumAll.add(commissionPrice);}}data.setPushMoney(sumAll);}//回款为null就删除当前对象BigDecimal pushMoney = new BigDecimal("0");BigDecimal perf = new BigDecimal("0");Iterator<ExprotEntity> it = exprotEntity.iterator();Map<String, String> objectObjectHashMap = new HashMap<>();while (it.hasNext()) {ExprotEntity ex = it.next();if (ex.getReturnedMoney()==null) {it.remove();}else{/*** 每个合同产生的绩效提成*/BigDecimal money = new BigDecimal(ex.getMoney());//获取合同绩效分成比列List<DataInfoEntity> dataInfo = dataInfoService.list();if(dataInfo.size()>0){List<Map<String, Object>> perfItemList = new ArrayList<>();for (DataInfoEntity m : dataInfo) {Map<String, Object> item = new HashMap<>();JSONObject object = JSON.parseObject(m.getItemValue());if (m.getScope().equals(DataInfoItemKey.Perf)) {if (object.containsKey(DataInfoItemKey.Perf_Start)) {item.put(DataInfoItemKey.Perf_Start, new BigDecimal(object.get(DataInfoItemKey.Perf_Start).toString()));}if (object.containsKey(DataInfoItemKey.Perf_End)) {item.put(DataInfoItemKey.Perf_End, new BigDecimal(object.get(DataInfoItemKey.Perf_End).toString()));}if (object.containsKey(DataInfoItemKey.Perf_Percent)) {item.put(DataInfoItemKey.Perf_Percent, new BigDecimal(object.get(DataInfoItemKey.Perf_Percent).toString()));}perfItemList.add(item);}}//对value值进行排序Collections.sort(perfItemList, new Comparator<Map<String, Object>>() {@Overridepublic int compare(Map<String, Object> o1, Map<String, Object> o2) {BigDecimal end1 = new BigDecimal(o1.get("end").toString());BigDecimal end2 = new BigDecimal(o2.get("end").toString());return end2.compareTo(end1);}});//最终绩效金额【如果最大的都小了就取第一个,否则向下走】for (Map<String, Object> mp : perfItemList) {BigDecimal end = new BigDecimal(mp.get("end").toString());BigDecimal start = new BigDecimal(mp.get("start").toString());if(money.compareTo(end) == 1){//1/100 * 金额 = 绩效BigDecimal percent1 = new BigDecimal(mp.get("percent").toString());BigDecimal percent2 = percent1.divide(new BigDecimal("100"),2,BigDecimal.ROUND_DOWN);BigDecimal divide = money.multiply(percent2);ex.setPerf(divide.toString());break;}else if(start.compareTo(money) == -1){BigDecimal percent1 = new BigDecimal(mp.get("percent").toString());BigDecimal percent2 = percent1.divide(new BigDecimal("100"),2,BigDecimal.ROUND_DOWN);BigDecimal divide = money.multiply(percent2);ex.setPerf(divide.toString());break;}}}else{throw new RRException("请检查=》数据管理—数据信息-绩效");}//获取合同金额给到map(重复的合同金额会被顶替)objectObjectHashMap.put(ex.getContractId(),ex.getMoney());//不为null的就累加提成金额pushMoney = pushMoney.add(ex.getPushMoney());}}Iterator<ExprotEntity> itTwo = exprotEntity.iterator();while (itTwo.hasNext()) {ExprotEntity ex = itTwo.next();//不为null的就累加提成金额perf = perf.add(new BigDecimal(ex.getPerf()));}//将objectObjectHashMap的合同金额遍历相加BigDecimal bl = new BigDecimal("0");for (String k : objectObjectHashMap.keySet()) {bl = bl.add(new BigDecimal(objectObjectHashMap.get(k)));}//追加一行空的用于后面合并单元格ExprotEntity exprotEntity1 = new ExprotEntity();exprotEntity1.setNum("绩效合计:"+bl);exprotEntity1.setCompanyName("绩效提成:"+perf);exprotEntity1.setNumber("合同提成合计:");exprotEntity1.setMoney("4");exprotEntity1.setReturnedMoney("5");exprotEntity1.setPushMoney(pushMoney);exprotEntity.add(exprotEntity1);list1.add(exprotEntity);}
//              //添加动态标题
//              writeSheet.setHead(lists);/*** excel 给同一个sheet给数据  .registerWriteHandler(loopMergeStrategy)*/for (int i = 0;i<list1.size();i++) {int size = list1.get(i).size();//因为上面每次显示都只显示一个月份,所以就把头放到这儿了,但是一个表有很多月份表头,所以这里就重新获取了一下表头数据List<List<String>> head2 = new ArrayList<>();for (int abc = 0; abc < 6 ; abc++) {head2.add(lists.get(select));select = select+1;}
//                  OnceAbsoluteMergeStrategy onceAbsoluteMergeStrategy = new OnceAbsoluteMergeStrategy(6,6,2,4);
//                  LoopMergeStrategy loopMergeStrategy = new LoopMergeStrategy(2, 0);MyMergeStrategy my = new MyMergeStrategy(size,size,2,4);WriteTable writeTable = EasyExcel.writerTable(i).needHead(Boolean.TRUE).head(head2).registerWriteHandler(my).build();excelWriter.write(list1.get(i), writeSheet, writeTable);}}}finally {if(excelWriter!=null){excelWriter.finish();}}return R.ok();}

七、博主自己重写的合并类【仅供参考】

根据自己业务重写了AbstractMergeStrategy(每个子表最后一行的指定行列进行单元合并)

package com.admin.slr.responseEntity;import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;import java.util.ArrayList;
import java.util.List;/*** @author LunarYouI* @create 2022-07-06 16:03*/public class MyMergeStrategy extends AbstractMergeStrategy {private int firstRowIndex;private int lastRowIndex;private int firstColumnIndex;private int lastColumnIndex;public MyMergeStrategy(int firstRowIndex, int lastRowIndex, int firstColumnIndex, int lastColumnIndex) {if (firstRowIndex >= 0 && lastRowIndex >= 0 && firstColumnIndex >= 0 && lastColumnIndex >= 0) {this.firstRowIndex = firstRowIndex;this.lastRowIndex = lastRowIndex;this.firstColumnIndex = firstColumnIndex;this.lastColumnIndex = lastColumnIndex;} else {throw new IllegalArgumentException("All parameters must be greater than 0");}}//导出数据需要导入 6 个字段private static int num = 6;private static int i = 1;//同一sheet不同表单的行号private static int trueLine = 0;//保存下一次行的行号private static int line = 0;@Overrideprotected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {//获取当前的行int rowIndex = cell.getRowIndex();//获取当前的列int columnIndex = cell.getColumnIndex();if(line != 0){//如果当前行 等于 上一次记录的行数,那代表还是一个sheet里的第一张表if(rowIndex == line){//是否进入下一行boolean flag = bbbb();if(flag){//                    System.out.println("================================111111");//保存下一次行号line = rowIndex+1;//调用接口aaaaa(sheet,trueLine,rowIndex,columnIndex);//记录当前行号(为真就表示当前行已经结束,开始下一行了)trueLine = trueLine+1;}else{//                    System.out.println("================================222222");//调用接口aaaaa(sheet,trueLine,rowIndex,columnIndex);}}//否则第二张表else{//                System.out.println("================================333333");//1、调用接口bbbb();//2、记录当前行号(不等就表示开始下一行,下一行起始为1)trueLine = 1;//3、保存下一次行号(这里没法判断是否该下一行号,所以这里就定为rowIndex的值)line = rowIndex;//4、调用接口aaaaa(sheet,trueLine,rowIndex,columnIndex);}}else{//            System.out.println("================================444444 ");bbbb();//1、记录当前行号trueLine = 1;//2、保存下一次行号(这里没法判断是否该下一行号,所以这里就定为rowIndex的值)line = rowIndex;//3、调用接口aaaaa(sheet,trueLine,rowIndex,columnIndex);}}/*** 合并数据* @param sheet* @param a 修改行* @param b 原本行* @param c 原本列*/private void aaaaa(Sheet sheet, int a, int b, int c) {//        System.out.println("修改行:"+a);
//        System.out.println("原本行:"+b);if (a == this.firstRowIndex && c == this.firstColumnIndex) {//这里的两个b表示 将第N行~N行的第N列~N列进行合并CellRangeAddress cellRangeAddress = new CellRangeAddress(b, b, this.firstColumnIndex, this.lastColumnIndex);sheet.addMergedRegionUnsafe(cellRangeAddress);}}/*** 表示一行数据有N个字段,每走一次消耗掉一个字段* @return*/private boolean bbbb() {if(i<6){i = i+1;return false;}else{i = 1;return true;}}
}

八、博主导出的excel【图】

EasyExcel 复杂数据导出相关推荐

  1. EasyExcel大批量数据导出OOM,个人案例和解决办法

    1:在我查询大量数据进行导出的时候往往第一次导出是没有问题,但是短时间内连续导出的时候就会出现OOM,导致服务节点重启. 2:我每次导出的数据是100w内,通过分析,首先想到的是创建的对象GC不过来, ...

  2. Springboot 下 EasyExcel 的数据导入导出

    文章目录 1.环境准备 1.0. excel数据 1.1. pom 1.2. excle映射实体 1.3. 自定义日期转换器 1.4.自定义异常 2. 数据导出 3. 数据导入 3.1. excel解 ...

  3. EasyExcel导入和导出excel数据表格用法示例

    说明:平时项目中经常有需要把excel表格中的数据导入库中,或者需要把查询出来的数据导出到excel文件中,今天就来介绍阿里的 easyexcel 的用法 一.SpringBoot集成EasyExce ...

  4. easyexcel 复杂表头、动态表头、复杂数据导出(非注解方式)

    easyexcel 复杂表头.动态表头.复杂数据导出 easyexcel 生成动态复杂表头(非注解)+数据填充(非注解) 实现代码 生成效果图 easyexcel 生成动态复杂表头(非注解)+数据填充 ...

  5. 使用easyExcel批量导入导出数据

    excel在工作中比较常用了,对于需要批量导入的需求,一般都是使用excel.excel导入常用poi,但是POI使用繁琐,而且对内存消耗大,这篇文章就是使用easyexcel来解析数据 场景一:将数 ...

  6. EasyExcel自定义表头导出模板并封装数据下拉选择

    EasyExcel自定义表头导出模板 首先查询可变数据 动态数据Controller 表头封装 定义导出模板时的下拉数据 最终结果 首先查询可变数据 动态数据Controller @ApiOperat ...

  7. easyexcel基于模板的数据导出及自定义表头

    需求背景:需要将数据导出成excel格式,但是表头信息不确定和表头格式复杂,基于代码也可以实现,但是代码实现复杂,且后续需要改动时成本较大,所以选择依赖模板的形式进行数据导出,将提前准备好的模板放置在 ...

  8. EasyExcel通过模板导出数据

    EasyExcel通过模板导出数据 大家好,这两天在做excel导出功能,使用的是easyExcel,不得不说其功能全面,很好入手. 但是在开发的过程中也会遇到一些文档里无法提供解决的问题,这里我分享 ...

  9. EasyExcel使用模板填充数据导出遇到的坑

    EasyExcel使用模板填充数据导出遇到的坑 1.最近需求涉及excel的导出,所以选择用阿里的EasyExcel框架来使用是比较方便的,这个框架封装了许多方法来供我们使用,比传统POI简单许多 2 ...

最新文章

  1. 一文搞懂PointNet全家桶——强势的点云处理神经网络
  2. c语言dp状态转移方程,[总结-动态规划]经典DP状态设定和转移方程
  3. 【模拟】P1424 小鱼的航程(改进版)
  4. Transformer在深度推荐系统中的应用及2019最新进展
  5. 如何做好iOS应用安全?这有一把行之有效的“三板斧”
  6. 安装spark1.3.1单机环境
  7. 他,TypeScript GitHub Star 上海第一,全国第四!GitHub 总标星超两万!
  8. 千万不要这样写代码!9种常见的OOM场景演示
  9. Android代码设置角标,Android上的Badge,快速实现给应用添加角标
  10. 我国.NET域名注册总量超57.3万 6月新增6747个
  11. Axure RP9Team版可用授权
  12. 计算机容量单位换算题,计算机储存容量计算单位换算
  13. 【阿里云生活物联网架构师专题 ④】如何在天猫精灵IOT开放平台二次开发智能设备的 H5控制面板;
  14. [CSS]CSS浮动float详解(三):清除浮动方案
  15. 笔记本连接无线网络后通过有线网口共享网络
  16. 2017/7/11 新开博客
  17. More Effective C++之 Item M6:自增(increment)、自减(decrement)操作符前缀形式与后缀形式的区别
  18. 内核同步机制——蜗窝科技
  19. 怎么做二维码更简单?这款二维码生成器了解一下
  20. 杭州一公司开20万月薪抢AIGC算法工程师;SpaceX「星舰」发射任务失败;华为宣布实现ERP自主可控,突破封锁|极客头条

热门文章

  1. FPGA开发基础之三段式状态机
  2. 修改docker自定义网桥后的默认网卡名称
  3. 【Java】 SpringBoot - 零基础搭建并使用
  4. SEIR模型及多染病仓室再生数的推导
  5. 【单片机项目】平衡小车(一) 控制流程
  6. 【柜子设计】草图大师及插件AFU321安装
  7. painter qt 好恶心_Qt之有关于Painter的理解
  8. docker 配置zabbix时区,本地时区与zabbix时区不相符 ,docker 时区,zabbix页面时区跟,docker 时间不一样
  9. 现成的MP4地址分享
  10. 螺旋天线matlab仿真,螺旋天线矩量法matlab