EasyExcel 复杂数据导出

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

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

)

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




再此先奉献上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实体类中的前字段三个被注释了,解开前三个注释后三个就可以了
EasyExcel 复杂数据导出_第2张图片

四、【同一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();
			}
		}
	}

EasyExcel 复杂数据导出_第3张图片

五、【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>就表示是同一个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();
			}
		}
	}

EasyExcel 复杂数据导出_第4张图片





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

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

这里主要看点就动态标题(因为码代码的时候发现一个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、获取当前用户的id
			SysUserEntity 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>,以便后面循环

//				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) {
						//合同id
						String 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>>() {
									@Override
									public 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(每个子表最后一行的指定行列进行单元合并)
EasyExcel 复杂数据导出_第5张图片

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;

    @Override
    protected 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 复杂数据导出_第6张图片

你可能感兴趣的:(java,java,开发语言)