EasyExcel复杂报表导出

需要导出的报表的模板

在这里插入图片描述

处理数据及格式(行列合并、sheet页重命名)

public class ExportDailyReportService {
	@Autowired
	private Environment env;
	
	public String exportDailyReport(List<DailyReportExportVo> dataList, String dateStr){
		File savePath = new File(env.getProperty("excel.path"));

		String number = DateUtils.formatDate(new Date(), "HHmmss");

		String fileName = new StringBuilder("xxx数据日报月报").append(dateStr).append("-"+number).append(ExcelTypeEnum.XLSX.getValue()).toString();

		long startTime = System.currentTimeMillis();

		ExcelWriter excelWriter = null;
		try {
            if(!savePath.exists()){
            	savePath.mkdir();
            }
            File file = new File(savePath,fileName);

			excelWriter = EasyExcel.write(file)
					.registerWriteHandler(new MergeSameRowsStrategy(2,new int[]{2}))
					.registerWriteHandler(new TotalMergeStrategy(dataList.size()))
					.registerWriteHandler(new UpdateSheetNameStrategy())
					.withTemplate(Thread.currentThread().getContextClassLoader().getResourceAsStream("templates/excel/export/DailyReportExport.xlsx")).build();

			WriteSheet writeSheet = EasyExcel.writerSheet(0, dateStr.concat("日报数据")).build();


			FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();


			//最后一行数据需要从第二列进行合并
			DailyReportExportVo dailyReportExportVo = dataList.get(dataList.size()-1);
			dailyReportExportVo.setArea(dailyReportExportVo.getYqMerchantName());

			Map<String, Object> map =new HashMap<>();
			map.put("exportDate",dateStr);

			excelWriter.fill(dataList,fillConfig,writeSheet);

			excelWriter.fill(map,writeSheet);


    		return env.getProperty("excel.url") + fileName;
        }finally{
			excelWriter.finish();
			log.info("export {} excel use {}ms",fileName,System.currentTimeMillis() - startTime);
        }
	}



	class UpdateSheetNameStrategy extends AbstractSheetWriteHandler {

		public UpdateSheetNameStrategy() {

		}

		@Override
		public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
			super.afterSheetCreate(writeWorkbookHolder, writeSheetHolder);
			writeWorkbookHolder.getWorkbook().setSheetName(writeSheetHolder.getSheetNo(), writeSheetHolder.getSheetName());
		}


	}



	class MergeSameRowsStrategy implements CellWriteHandler {
		private int[] mergeColumnIndex;
		private int mergeRowIndex;

		public MergeSameRowsStrategy() {
		}

		public MergeSameRowsStrategy(int mergeRowIndex, int[] mergeColumnIndex) {
			this.mergeRowIndex = mergeRowIndex;
			this.mergeColumnIndex = mergeColumnIndex;
		}

		@Override
		public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {

		}

		@Override
		public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

		}

		@Override
		public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {

		}

		@Override
		public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
			// 当前行
			int curRowIndex = cell.getRowIndex();
			// 当前列
			int curColIndex = cell.getColumnIndex();

			if (curRowIndex > mergeRowIndex) {
				for (int i = 0; i < mergeColumnIndex.length; i++) {
					if (curColIndex == mergeColumnIndex[i]) {
						mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
						break;
					}
				}
			}
		}

		/**
		 * 当前单元格向上合并
		 *
		 * @param writeSheetHolder sheet保持对象
		 * @param cell             当前单元格
		 * @param curRowIndex      当前行
		 * @param curColIndex      当前列
		 */
		private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
			// 获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并
			Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
			Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
			Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();

			// 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行
			if (curData.equals(preData)) {
				Sheet sheet = writeSheetHolder.getSheet();
				List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
				boolean isMerged = false;
				for (int i = 0; i < mergedRegions.size() && !isMerged; i++) {
					CellRangeAddress cellRangeAddr = mergedRegions.get(i);
					// 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
					if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
						sheet.removeMergedRegion(i);
						cellRangeAddr.setLastRow(curRowIndex);
						sheet.addMergedRegion(cellRangeAddr);
						isMerged = true;
					}
				}
				// 若上一个单元格未被合并,则新增合并单元
				if (!isMerged) {
					CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex);
					sheet.addMergedRegion(cellRangeAddress);
				}
			}
		}
	}


	class TotalMergeStrategy extends AbstractMergeStrategy {

		private final int size;


		public TotalMergeStrategy(int size) {
			this.size = size;
		}

		@Override
		protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
			// 由于每个单元格 都会调用该方法,为了避免重复合并异常,只在应合并的行、列执行即可
			// 最后一行 需要开始合并的列开始合并
		 	if (cell.getRowIndex()==size+1 && cell.getColumnIndex() == 1) {
		 		sheet.addMergedRegionUnsafe(new CellRangeAddress(cell.getRowIndex(), cell.getRowIndex(), cell.getColumnIndex(), cell.getColumnIndex() + 4));

			}
		}

	}
}

导出结果

在这里插入图片描述

例2:

package cn.com.glsx.dj.smartcarlife.service.smartcarlife;

import cn.com.glsx.dj.smartcarlife.dto.PurchaseOrderExportPageDTO;
import cn.com.glsx.dj.smartcarlife.model.PurchaseOrderGoods;
import cn.com.glsx.dj.smartcarlife.vo.excel.PurchaseOrderExportVo;
import cn.com.glsx.framework.core.util.DateUtils;
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.support.ExcelTypeEnum;
import com.alibaba.excel.write.handler.AbstractSheetWriteHandler;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.*;

@Service
@Slf4j
public class ExportPurchaseOrderService {
    @Autowired
    private Environment env;

    public String exportPurchaseOrder(List<PurchaseOrderExportPageDTO> dataList) {
        File savePath = new File(env.getProperty("gop.excel.tem.path"));

        String number = DateUtils.formatDate(new Date(), "yyyyMMddHHmmss");

        String fileName = new StringBuilder("采购订单").append("-" + number).append(ExcelTypeEnum.XLSX.getValue()).toString();

        long startTime = System.currentTimeMillis();

        ExcelWriter excelWriter = null;

        try {
            if (!savePath.exists()) {
                savePath.mkdir();
            }
            File file = new File(savePath, fileName);

            List<CellRangeAddress> addressList = new ArrayList<>();
            List<PurchaseOrderExportVo> exportVoList = new ArrayList<>();

            for (int i = 0; i < dataList.size(); i++) {
                PurchaseOrderExportPageDTO dto = dataList.get(i);
                if (i < 1) {
                    addressList.add(new CellRangeAddress(1, dto.getGoodsList().size(), 0, 0));
                } else {
                    int firstRow = addressList.get(i - 1).getLastRow() + 1;
                    int lastRow = addressList.get(i - 1).getLastRow() + dto.getGoodsList().size();
                    addressList.add(new CellRangeAddress(firstRow, lastRow, 0, 0));
                }
                for (PurchaseOrderGoods goods : dto.getGoodsList()) {
                    PurchaseOrderExportVo vo = new PurchaseOrderExportVo();
                    BeanUtils.copyProperties(dto, vo);
                    BeanUtils.copyProperties(goods, vo);

                    exportVoList.add(vo);
                }
            }

            excelWriter = EasyExcel.write(file)
                    .registerWriteHandler(new UpdateSheetNameStrategy())
                    .registerWriteHandler(new MergeRowsAndConvertedStrategy(1, new int[]{8, 11}, addressList))
                    .withTemplate(Thread.currentThread().getContextClassLoader().getResourceAsStream("templates/excel/export/采购订单导出.xlsx")).build();

            WriteSheet writeSheet = EasyExcel.writerSheet(0, "采购订单").build();

            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();

            excelWriter.fill(exportVoList, fillConfig, writeSheet);

            return env.getProperty("gop.excel.tem.url") + fileName;
        } finally {
            excelWriter.finish();
            log.info("export {} excel use {}ms", fileName, System.currentTimeMillis() - startTime);
        }
    }


    class UpdateSheetNameStrategy extends AbstractSheetWriteHandler {

        public UpdateSheetNameStrategy() {

        }

        @Override
        public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
            super.afterSheetCreate(writeWorkbookHolder, writeSheetHolder);
            writeWorkbookHolder.getWorkbook().setSheetName(writeSheetHolder.getSheetNo(), writeSheetHolder.getSheetName());
        }


    }

//    class MergeStrategy extends AbstractMergeStrategy {
//
//     //合并开始行
//
//        private Integer startRow = 0;
//
//
//    //list表格所有的合并列集合
//
//        private List<CellRangeAddress> addressList = null;
//
//        public MergeStrategy() {
//        }
//
//        public MergeStrategy(int startRow, List<CellRangeAddress> addressList) {
//            this.startRow = startRow;
//            this.addressList = addressList;
//        }
//
//        @Override
//        protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
//            //由于每个单元格 都会调用该方法,为了避免重复合并异常,只在应合并的行、列执行即可
//            //在这里判断从哪一行开始调用合并的方法
//            int colIndex = cell.getColumnIndex();
//            if (cell.getRowIndex() > this.startRow && colIndex >= 0 && colIndex < 12) {
				if (relativeRowIndex == null || relativeRowIndex == 0) {
					return;
				}
//                mergeRow(sheet, cell);
//            }
//
//        }
//
//        protected void mergeRow(Sheet sheet, Cell cell) {
//            int rowIndex = cell.getRowIndex();
			sheet = cell.getSheet();
//            int colIndex = cell.getColumnIndex();
//            List<CellRangeAddress> list = this.addressList;
//            for (int i = 0; i < list.size(); i++) {
//                CellRangeAddress cellRangeAddress = list.get(i);
//                if (cellRangeAddress.containsRow(rowIndex)) {
//                    //合并单元格区域只有一个单元格时,不合并
//                    if (cellRangeAddress.getLastRow() == cellRangeAddress.getFirstRow()) {
//                        return;
//                    }
//                    CellRangeAddress cra = new CellRangeAddress(cellRangeAddress.getFirstRow(), cellRangeAddress.getLastRow(), colIndex, colIndex);
					log.info("{},{},{},{}",cellRangeAddress.getFirstRow(),cellRangeAddress.getLastRow(),colIndex,colIndex);
//                    List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
//                    if (mergedRegions.contains(cra)) {
//                        return;
//                    }
//                    sheet.addMergedRegion(cra);
//                    return;
//                }
//            }
//
//        }
//
//    }


    class MergeRowsAndConvertedStrategy implements CellWriteHandler {

        private int[] mergeColumnIndex;
        private int startRow;
        private List<CellRangeAddress> addressList;

        public MergeRowsAndConvertedStrategy() {
        }

        public MergeRowsAndConvertedStrategy(int startRow, int[] mergeColumnIndex, List<CellRangeAddress> addressList) {
            this.startRow = startRow;
            this.mergeColumnIndex = mergeColumnIndex;
            this.addressList = addressList;
        }

        @Override
        public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {

        }

        @Override
        public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {

        }

        @Override
        public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {

        }

        @Override
        public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
            // 当前行
            int curRowIndex = cell.getRowIndex();
            // 当前列
            int curColIndex = cell.getColumnIndex();

            //状态值转换
            if (curRowIndex >= startRow) {
                for (int i = 0; i < mergeColumnIndex.length; i++) {
                    if (curColIndex == mergeColumnIndex[i]) {
                        dataConverted(cell, curColIndex);
                        break;
                    }
                }
            }
            //行合并
            if (curRowIndex > this.startRow && curColIndex >= 0 && curColIndex < 12) {
//				if (relativeRowIndex == null || relativeRowIndex == 0) {
//					return;
//				}
                Sheet sheet = writeSheetHolder.getSheet();
                mergeRow(sheet, cell, curRowIndex, curColIndex);
            }
        }

        private void mergeRow(Sheet sheet, Cell cell, int curRowIndex, int curColIndex) {
            List<CellRangeAddress> list = this.addressList;
            for (int i = 0; i < list.size(); i++) {
                CellRangeAddress cellRangeAddress = list.get(i);
                if (cellRangeAddress.containsRow(curRowIndex)) {
                    //合并单元格区域只有一个单元格时,不合并
                    if (cellRangeAddress.getLastRow() == cellRangeAddress.getFirstRow()) {
                        return;
                    }
                    CellRangeAddress cra = new CellRangeAddress(cellRangeAddress.getFirstRow(), cellRangeAddress.getLastRow(), curColIndex, curColIndex);
//					log.info("{},{},{},{}",cellRangeAddress.getFirstRow(),cellRangeAddress.getLastRow(),colIndex,colIndex);
                    List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
                    if (mergedRegions.contains(cra)) {
                        return;
                    }
                    sheet.addMergedRegion(cra);
                    return;
                }
            }

        }

        private void dataConverted(Cell cell, int curColIndex) {
            if (curColIndex == 8) {
                double numericCellValue = cell.getNumericCellValue();
                switch ((int) numericCellValue) {
                    case 1:
                        cell.setCellValue("未发货");
                        break;
                    case 2:
                        cell.setCellValue("已发货");
                        break;
                }
            } else if (curColIndex == 11) {
                double numericCellValue = cell.getNumericCellValue();
                switch ((int) numericCellValue) {
                    case 1:
                        cell.setCellValue("待审核");
                        break;
                    case 2:
                        cell.setCellValue("已审核");
                        break;
                    case 3:
                        cell.setCellValue("已取消");
                        break;
                }
            }

        }
    }

}

结果

在这里插入图片描述

例二的另一种做法

一对多的场景:一条订单对应多个商品
模板
在这里插入图片描述
导出类

package cn.com.glsx.dj.smartcarlife.vo.excel;

import cn.com.glsx.dj.smartcarlife.dto.purchase.PurchaseOrderGoodsExportDTO;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import lombok.Data;
import org.oreframework.commons.office.easyexcel.annotation.ExcelMergeRow;
import org.oreframework.commons.office.easyexcel.annotation.ExcelValueReplace;
import org.oreframework.commons.office.easyexcel.converter.ReplaceByteToStringConvert;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Data
public class PurchaseOrderExportVo implements Serializable{
    private static final long serialVersionUID = 4223969010443009963L;

    @ExcelMergeRow(columIndex = 0)
    private Integer index;
    /**
     * 订单编号
     */
    @ExcelMergeRow(columIndex = 1)
    private String orderCode;

    /**
     * 订单总价
     */
    @ExcelMergeRow(columIndex = 2)
    private BigDecimal totalPrice;

    /**
     * 下单时间
     */
    @ExcelMergeRow(columIndex = 3)
    @DateTimeFormat(value="yyyy-MM-dd HH:mm:ss")
    private Date orderTime;

    /**
     * 下单门店商户名称
     */
    @ExcelMergeRow(columIndex = 4)
    private String merchantName;

    /**
     * 收件人
     */
    @ExcelMergeRow(columIndex = 5)
    private String contactName;

    /**
     * 收件人电话
     */
    @ExcelMergeRow(columIndex = 6)
    private String contactPhone;

    /**
     * 收件人地址
     */
    @ExcelMergeRow(columIndex = 7)
    private String contactAddress;


    /**
     * 发货状态(1:未发货,2全部发货,3部分发货)
     */
    @ExcelMergeRow(columIndex = 8)
    @ExcelProperty(converter = ReplaceByteToStringConvert.class)
    @ExcelValueReplace(replace={"未发货_1","已发货_2","部分发货_3"})
    private Byte deliveryStatus;

    /**
     * 采购类型
     */
    @ExcelMergeRow(columIndex = 9)
    @ExcelProperty(converter = ReplaceByteToStringConvert.class)
    @ExcelValueReplace(replace={"商城采购_1","自采入库_2"})
    private Byte purchaseType;

    /**
     * 入库状态(1.未入库,2.全部入库,3部分入库)
     */
    @ExcelMergeRow(columIndex = 10)
    @ExcelProperty(converter = ReplaceByteToStringConvert.class)
    @ExcelValueReplace(replace={"未入库_1","全部入库_2","部分入库_3"})
    private Byte putStatus;

    /**
     * 订单状态(1.待审核,2.已审核,3.已取消,4.已驳回)
     */
    @ExcelMergeRow(columIndex = 11)
    @ExcelProperty(converter = ReplaceByteToStringConvert.class)
    @ExcelValueReplace(replace={"运营审核_1","商务审核_2","已取消_3","已驳回_4","已审核_5"})
    private Byte status;

    private List<PurchaseOrderGoodsExportDTO> goodsList;

}
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值