欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Alibaba easyExcel对Excel操作之复杂标题处理

程序员文章站 2022-03-19 15:58:50
easyExcle对poi进行二次封装优化,对外提供了更加方便的接入方式,如果对导出Excle的标题有比较复杂的业务需求,那么就要用到官方提供的2中方式(模版填充、自定义标题),如果自定义标题也不能满足我们的需求,例如我们需要在标题中切入图片需求,要么采用第一种比较简单的模版填充方式,但是如果你不想使用模版的方式,倾向于使用java代码来实现,那么本文可能对你有所帮助,我们采用自定义标题加上拦截器。业务说明,根据业务需要我们需要生成如下截图的excel文件对导出文件进行分析:1、第一行合并单...

easyExcle对poi进行二次封装优化,对外提供了更加方便的接入方式,如果对导出Excle的标题有比较复杂的业务需求,那么就要用到官方提供的2中方式(模版填充、自定义标题),如果自定义标题也不能满足我们的需求,例如我们需要在标题中切入图片需求,要么采用第一种比较简单的模版填充方式,但是如果你不想使用模版的方式,倾向于使用java代码来实现,那么本文可能对你有所帮助,我们采用自定义标题加上拦截器。

业务说明,根据业务需要我们需要生成如下截图的excel文件

Alibaba easyExcel对Excel操作之复杂标题处理

对导出文件进行分析:

1、第一行合并单元格

2、第一行中间显示图片,图片是根据其中一个字段生成的条形码

3、第二行也是标题

4、从第三行开始才是数据

实现方案:

1、采用模版填充的方式,很好实现,将需要填充的单元格用变量替换,在程序中使用map进行数据封装

2、采用自定义标题,纯java代码,自定义标题加拦截器,第一步在自定义标题中填充除了图片以外的数据,第二步在拦截器中获取该字段将其转成图片,再次写入到excel中且调整格式

这篇文章我们采用第二种方案

controller层类 ExcelExportController

@GetMapping(value = "/exportExcel")
    public void exportExcel(@RequestParam(value = "id") Long id, HttpServletResponse response) throws IOException {
        //封装标题数据 省略
        ExcelTitle title = new ExcelTitle();
        //封装数据 省略
        List<Object> list = new ArrayList();
        
        ExcelUtils.writeExcel(response,new InboundCellWriteHandler(),head(title.getbBillNo(),title), list, "文件名称");
    }

封装复杂标题head方法

private static List<List<String>> head(String inboundNo , Exceltitle title) {
        List<List<String>> listHead = new ArrayList<>();
        List<String> head0 = new ArrayList<>();
        head0.add(inboundNo);
        head0.add("入库单号");
        head0.add("序号");
        listHead.add(head0);
        List<String> head1 = new ArrayList<>();
        head1.add("");
        head1.add(title.getInboundBillNo());
        head1.add("商品编码");
        listHead.add(head1);
        List<String> head2 = new ArrayList<>();
        head2.add("");
        head2.add("入库类型");
        head2.add("商品名称");
        listHead.add(head2);
        List<String> head3 = new ArrayList<>();
        head3.add("");
        head3.add(title.getBillType());
        head3.add("商品条码");
        listHead.add(head3);
        List<String> head4 = new ArrayList<>();
        head4.add("");
        head4.add("预计到仓日期");
        head4.add("预期数量");
        listHead.add(head4);
        List<String> head5 = new ArrayList<>();
        head5.add("");
        head5.add(title.getExpectArriveStoreTime());
        head5.add("清点数量");
        listHead.add(head5);
        //省略其他字段
        return listHead;
    }

咱们先看excle的工具类,比较简单,最后在处理拦截器的逻辑

public static void writeExcel(HttpServletResponse response,CellWriteHandler handler, List<List<String>> header, List list, String fileName) throws IOException {
        response.setContentType("application/vnd.ms-excel; charset=utf-8");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8") + ".xlsx");
        EasyExcel.write(response.getOutputStream()).head(header).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).registerWriteHandler(handler).sheet("sheet1").doWrite(list);
    }

最后咱们看 InboundCellWriteHandler拦截器处理逻辑

public class InboundCellWriteHandler implements CellWriteHandler {
   //省略beforeCellCreate、afterCellCreate、afterCellDataConverted
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                 List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex,
                                 Boolean isHead) {
        if (!isHead) {
            return;
        }
        if (cell.getRowIndex() == 0 && cell.getColumnIndex() == 0) {
            Sheet sheet = writeSheetHolder.getSheet();
            List<String> headNameList = head.getHeadNameList();
            if (CollectionUtils.isEmpty(headNameList)) {
                return;
            }
            String value = null;
            cell.setCellValue(value);
           //先移除合并第一行标题的单元格
            sheet.removeMergedRegion(0);
            sheet.removeMergedRegion(7);
            //再次合并单元格
            CellRangeAddress region = new CellRangeAddress(0,0, 0,11);
            sheet.addMergedRegionUnsafe(region);
            //图片的高
            short i1 = Integer.valueOf(cell.getRow().getHeight() * 4 + cell.getRow().getHeight() / 4).shortValue();
            cell.getRow().setHeight(i1);
            //根据第一行标题数据生成条形码图片
            byte[] generate = BarCodeUtils.generate(headNameList.get(0));
            int i = sheet.getWorkbook().addPicture(generate, 6);
            //生成画板
            Drawing<?> drawingPatriarch = sheet.getDrawingPatriarch();
            if (Objects.isNull(drawingPatriarch)){
                drawingPatriarch = sheet.createDrawingPatriarch();
            }
            CreationHelper creationHelper = sheet.getWorkbook().getCreationHelper();
            //锁定图片所在的位置
            ClientAnchor clientAnchor = creationHelper.createClientAnchor();
            clientAnchor.setCol1(3);
            clientAnchor.setCol2(5);
            clientAnchor.setRow1(0);
            clientAnchor.setRow2(0);
            clientAnchor.setDx1(0);
            clientAnchor.setDy1(0);
            clientAnchor.setDx2(0);
            clientAnchor.setDy2(1);
            clientAnchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_DO_RESIZE);
            Picture picture = drawingPatriarch.createPicture(clientAnchor, i);
            //这个字段必须设置,要不然图片显示不出来
            picture.resize(2d,1d);
        }

    }

总结:对第二种方式的一些思考

1、提高了代码的复杂性,而且要熟悉poi的一些接口

2、无需另外加载远程excle模版,如果是本地,可能会出现找不到文件的情况

3、使用拦截器,提高excel的格式改变的灵活性

4、使用拦截器,能够方便我们在后期excel的格式进行二次修改加工

 

本文地址:https://blog.csdn.net/zanpengfei/article/details/111884782