EasyExcel导出一个最后一行是合计行的Excel

本文详细介绍了如何使用EasyExcel库在Java中创建Excel文件,包括实体类的注解配置、导出方法中处理合计行的工具类以及设置单元格样式的拦截器,确保最后一行是总计行且样式统一。
摘要由CSDN通过智能技术生成

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

使用EasyExcel导出一个最后一行是合计行的Excel

一、前置操作

这里省略导包等的操作,使用的仍然是3.X以前的EasyExcel版本
在要导出的实体类上使用@ExcelIgnore注解标注不需要导出的属性,使用@ExcelProperty(value = “xxx”,index = 0)注解标注需要导出的属性,其中value是导出的Excel表头显示的内容,index是表头字段的下标,从0开始
这里写了一个工具类,指定哪几列进行合并计算,哪一列写入“合计”汉字

二、使用步骤

1.实体类

这里主要看一下两个注解是怎么使用的:

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class WorkHourPerspectiveCell implements Serializable {
    private static final long serialVersionUID=1L;

    @ApiModelProperty(value = "工艺集工位id")
    @ExcelIgnore
    private String pCellId;

    @ApiModelProperty(value = "工艺集工位")
    @ExcelIgnore
    private String pCellName;

    @ApiModelProperty(value = "工厂结构工位id")
    @ExcelIgnore
    private String cellId;

    @ApiModelProperty(value = "工厂结构工位")
    @ExcelProperty(value = "工位名称",index = 0)
    @ColumnWidth(value = 20)
    private String cellName;

    @ApiModelProperty(value = "总工时")
    @ExcelProperty(value = "总工时",index = 1)
    @ColumnWidth(value = 20)
    private Integer sumHours;

    @ApiModelProperty(value = "机时")
    @ExcelProperty(value = "机时",index = 2)
    @ColumnWidth(value = 15)
    private Integer machineHours;

    @ApiModelProperty(value = "人时")
    @ExcelProperty(value = "人时",index = 3)
    @ColumnWidth(value = 15)
    private Integer personHours;

    @ApiModelProperty(value = "节拍")
    @ExcelProperty(value = "节拍",index = 4)
    @ColumnWidth(value = 15)
    private Integer hourBeat;

}

2.导出方法

public void export(WorkHourPerspectiveCellDto dto,HttpServletResponse response) {
        // 数据准备
        List<WorkHourPerspectiveCell> records = getCellHourList(dto);
        records.stream().forEach(e -> e.setSumHours(e.getMachineHours() + e.getMachineHours()));
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            ServletOutputStream outputStream = response.getOutputStream();
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = null;
            try {
                fileName = URLEncoder.encode("工位标准工时", "UTF-8").replaceAll("\\+", "%20");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            // 这里数据长度+1的原因是在最后加一行合计
            TotalRowHandler totalRowHandler = new TotalRowHandler(records.size()+1);
            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), WorkHourPerspectiveCell.class).registerWriteHandler(totalRowHandler).build();
            // 写入合计行样式;默认表头只有一行
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
			//这里我指定第1、2、3列进行合计
            HashSet<Integer> indexSet = new HashSet<>();
            indexSet.add(1);
            indexSet.add(2);
            indexSet.add(3);
            // 合计行
            WorkHourPerspectiveCell sumCell = ExcelUtils.sumCell(true,0,indexSet,records,WorkHourPerspectiveCell.class);
            records.add(sumCell);
            excelWriter.write(records, writeSheet);
            // 关闭流
            excelWriter.finish();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

3.进行合计的工具类

这里为了更具有通用性使用了反射

public class ExcelUtils {
    /**
     *
     * @param ifSum 是否写入“合计”汉字
     * @param sumIndex 写入“合计”的列下标
     * @param indexSet 需要计算合计的列的下标集合,不能重复
     * @param records 数据集
     * @return
     */
    public static <T> T sumCell(Boolean ifSum, Integer sumIndex, HashSet<Integer> indexSet, List<T> records,Class<T> clazz) throws InstantiationException, IllegalAccessException {
        // 获取类的所有属性
        Field[] declaredFields = clazz.getDeclaredFields();
        T t = clazz.newInstance();
        for (Field field: declaredFields) {
            field.setAccessible(true);
            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
            if (annotation != null) {
                int index = annotation.index();
                if (ifSum) {
                    if (index == sumIndex) {
                        field.set(t,"合计");
                    }
                }
                if (indexSet.contains(index)){
                    String type = field.getType().getName();
                    // 进行合并的列一般为数值型,为更具通用性,判断是否是String类型,统一转成BigDecimal
                    BigDecimal total = BigDecimal.ZERO;
                    for (T temp : records){
                        BigDecimal count = new BigDecimal(String.valueOf(field.get(temp)));
                        total = total.add(count);
                    }
                    if (type.contains("String")){
                        // 转成String类型
                        field.set(t,total.toString());
                    }else if (type.contains("Integer")){
                        field.set(t,total.intValue());
                    }else if (type.contains("Double")){
                        field.set(t,total.doubleValue());
                    }
                }
            }
        }
        return t;
    }
}

4.设置单元格样式的拦截器

@Slf4j
public class TotalRowHandler implements CellWriteHandler {
    /**
     * 开始添加样式的行下标
     */
    private Integer startRow;

    public TotalRowHandler(Integer startRow) {
        this.startRow = startRow;
    }

    @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 relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList,
                                 Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        // 这里根据需要自行选择要设置的样式
        Workbook workbook = writeSheetHolder.getSheet().getWorkbook();
        if (cell != null) {
            // 非表头设置样式
            if (!isHead){
                // 设置内容字体样式
                WriteCellStyle contentStyle = new WriteCellStyle();
                WriteFont contentWriteFont = new WriteFont();
                contentWriteFont.setFontName("宋体");
                contentWriteFont.setFontHeightInPoints((short) 12);
                // 设置水平居中、垂直居中
               contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
                contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
                contentStyle.setWriteFont(contentWriteFont);
                // 样式写入单元格
                CellStyle contentCellStyle = StyleUtil.buildContentCellStyle(workbook, contentStyle);
                cell.setCellStyle(contentCellStyle);
            }else {
                // 设置表头字体样式
                WriteCellStyle headStyle = new WriteCellStyle();
                WriteFont headWriteFont = new WriteFont();
                headWriteFont.setFontName("宋体");
                headWriteFont.setFontHeightInPoints((short) 5);
                headStyle.setWriteFont(headWriteFont);
                // 样式写入单元格
                CellStyle headCellStyle = StyleUtil.buildHeadCellStyle(workbook, headStyle);
                cell.setCellStyle(headCellStyle);
            }
        }
    }
}
  • 15
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您好,可以使用 EasyExcel 中的 SheetWriteHandler 接口来实现导出最后一行合并单元格的功能。具体步骤如下: 1. 创建一个实现了 SheetWriteHandler 接口的类,并重写其 afterSheetCreate 和 afterWrite 方法。 2. 在 afterSheetCreate 方法中获取最后一行号,例如: ``` @Override public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { Sheet sheet = writeSheetHolder.getSheet(); int lastRowIndex = sheet.getLastRowNum(); // TODO: 处理最后一行的合并单元格 } ``` 3. 在 afterWrite 方法中判断当前写入的是否为最后一行,如果是,则执合并单元格的操作,例如: ``` @Override public void afterWrite(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer integer, Integer integer1, Boolean aBoolean) { Sheet sheet = writeSheetHolder.getSheet(); int lastRowIndex = sheet.getLastRowNum(); if (integer == lastRowIndex) { // TODO: 处理最后一行的合并单元格 } } ``` 4. 在处理最后一行的合并单元格时,可以使用 Sheet 的 addMergedRegion 方法来实现,例如: ``` // 合并最后一行的前三列 CellRangeAddress cellRangeAddress = new CellRangeAddress(lastRowIndex, lastRowIndex, 0, 2); sheet.addMergedRegion(cellRangeAddress); ``` 以上是大致的实现思路,具体的实现细节需要根据您的业务需求进调整。希望能对您有所帮助!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值