poi导出Excel同时动态合并单元格。

poi导出单元格的同时合并相同内容

周一刚写了个poi打出图片的功能,然后看我刚写完这一个模块,就把其他页面导出表格的也交给我了。
在这里插入图片描述
页面需求就是这样
因为刚开始接触poi的我并不熟悉,所以一开始也是百度了很多帖子,最后选了这位大佬的方法。原文链接各位也可以看看这个,比我介绍的更详细。
核心思想就是创建一个工具类,去记录上一行的内容,记录开始合并的行标,列标,插入时和上一行的内容进行比较,不相同则合并,同时更新行标和列标
工具类的代码如下:

import lombok.Data;

@Data
public class PoiModel {
    //内容
    private String content;
    //行标
    private int rowIndex;
    //列标
    private int cellIndex;
    //标记
    public int flog;
}

导出poi方法的代码块如下

public static XSSFWorkbook createExcelCard(List<?> list, List<String> columnName, List<String> columnData,String fileName) {
        /*初始化excel模板*/
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet sheet = workbook.createSheet("123");

       
        //给表头添加行
        XSSFRow row = sheet.createRow(0);
        for (int i = 0, k = 0; i < columnName.size(); i++, k++) {
            sheet.setColumnWidth(k, 4000);
            XSSFCell cell = row.createCell(k);
            cell.setCellValue(columnName.get(i));
            cell.setCellStyle(cellStyle);
        }
        //填入数据
        List<PoiModel> poiModels=new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            XSSFRow nrow = sheet.createRow(i + 1);
            Map map = objectToMap(list.get(i));
            if (map == null) {
                continue;
            }
            //j控制每一行的格子里填入的数据
            for (int j = 0; j < columnData.size(); j++) {
                XSSFCell cell = nrow.createCell(j);
                String column = columnData.get(j);
               //这个if就是做一些数据处理,
                if ("typeName".equals(column)) {
                    cell.setCellValue(getV(map, "typeCode", "typeName"));
                } else if ("departmentName".equals(column)) {
                    String value=getV(map, "departmentCode", "departmentName");
                    if (""==value){
                        value="null无用部门";
                    }
                    cell.setCellValue(value);
                }else if ("agyName".equals(columnData.get(j))){
                    cell.setCellValue(map.get("agyCode").toString()+map.get("agyName").toString());
                } else {
                    Object value = map.get(columnData.get(j));
                    if (value == null) {
                        cell.setCellValue("");
                    } else if (value instanceof BigDecimal) {
                        cell.setCellValue(((BigDecimal) value).doubleValue());
                    } else if (value instanceof String) {
                        cell.setCellValue((String) value);
                    } else if (value instanceof Integer) {
                        cell.setCellValue((Integer) value);
                    }
                }
                //j小于2是因为只有前两列需要合并
                if (j<2){
                	//getV方法只是自己写的一个获取数据的处理,只需要把你往表格填的内容赋值给value就可以
                    String value="";
                    //获取每列填入的内容,有些特殊的列需要进行处理
                    if ("departmentCode".equals(columnData.get(j))){
                        value=getV(map, "departmentCode", "departmentName");
                        if ("".equals(value)){
                            value="null无用部门";
                        }
                    }else if ("agyName".equals(columnData.get(j))){
                        value= map.get("agyCode").toString()+map.get("agyName").toString();
                    }else {
                        value= (String) map.get(columnData.get(j));
                    }
                    //当进行到每列的第一行时,创建辅助类用来记录数据用来判断
                    if (i==0){
                        PoiModel poiModel = new PoiModel();
                        poiModel.setContent(value);
                        poiModel.setRowIndex(i+1);//行数
                        poiModel.setCellIndex(j);//列数
                        poiModels.add(poiModel);

                    }else{
                        //第一列时不需要考虑前一列内容不一样时不进行合并的情况,所以当内容不同直接进行合并
                        if (j==0&& !value.equals(poiModels.get(j).getContent())){
                            //当合并时CellRangeAddress c1 = new CellRangeAddress();的参数不允许为2 2 0 0这种情况,所以进行判断
                            if (poiModels.get(j).getRowIndex()!=i){
                                CellRangeAddress c1 = new CellRangeAddress(poiModels.get(j).getRowIndex() , i,poiModels.get(j).getCellIndex() , poiModels.get(j).getCellIndex());
                                sheet.addMergedRegion(c1);
                            }
                            //每当合并时把第二列的flog修改为1,当进行到第二列时,不管下一行是否相同,直接进行合并。
                            poiModels.get(j+1).setFlog(1);
                            poiModels.get(j).setContent(value);
                            poiModels.get(j).setRowIndex(i+1);
                        }
                        //第二列时,当flog为1时,代表第一列合并过了,所以直接合并,并且把辅助类里面的内容进行修改,并把状态改为0
                        if (j==1&&poiModels.get(j).getFlog()==1){
                            if (poiModels.get(j).getRowIndex()!=i){
                                CellRangeAddress c1 = new CellRangeAddress(poiModels.get(j).getRowIndex() , i,poiModels.get(j).getCellIndex() , poiModels.get(j).getCellIndex());
                                sheet.addMergedRegion(c1);
                            }
                            poiModels.get(j).setRowIndex(i+1);
                            poiModels.get(j).setContent(value);
                            poiModels.get(j).setFlog(0);
                        }else if (j==1&&!value.equals(poiModels.get(j).getContent())){
                            if (poiModels.get(j).getRowIndex()!=i){
                                CellRangeAddress c1 = new CellRangeAddress(poiModels.get(j).getRowIndex() , i,poiModels.get(j).getCellIndex() , poiModels.get(j).getCellIndex());
                                sheet.addMergedRegion(c1);
                            }
                            poiModels.get(j).setContent(value);
                            poiModels.get(j).setRowIndex(i+1);
                        }
                        //当进行到最后一行时,处理最后一行和上面的行合并
                        if (i==list.size()-1){
                            if (poiModels.get(j).getRowIndex()!=i+1){
                                CellRangeAddress c1 = new CellRangeAddress(poiModels.get(j).getRowIndex() , i+1,poiModels.get(j).getCellIndex() , poiModels.get(j).getCellIndex());
                                sheet.addMergedRegion(c1);
                            }
                        }
                    }
                }
            }
        }
        return workbook;
    }

其中list为需要插入的数据集合,columnName为标题行,columnData和标题行对应,为了在map中获取数据,导出方法中用到的一些处理数据的方法

private static Map objectToMap(Object data) {
        Map<String, Object> map = new HashMap();
        try {
            Class obj = data.getClass();
            Field[] fields = obj.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                map.put(field.getName(), field.get(data));
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return map;
    }

controller中的方法调用如下

public void cardSummary(AstCardQO astCard, HttpServletResponse response, HttpServletRequest request,String flag) {
        try {

            String fileName = null;
            List<String> columnName = new ArrayList<>();
            List<String> columnData = new ArrayList<>();
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/octet-stream;charset=UTF-8");
            String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

            //导出卡片表头
     
            fileName = "表名.xlsx";
            PageResult<AstCardListVO> cardSum=null;         
            cardSum = astCardListService.getDepartmentCardSum(astCard);
            columnName.addAll(Arrays.asList("标题1", "标题4", "标题3", "标题5"....));
            columnData.addAll(Arrays.asList("标题1所对应的字段", "标题2所对应的字段", "标题3所对应的字段", "标题4所对应的字段"...));

            list = cardSum.getResult();//需要导入的数据集合
            XSSFWorkbook workbook = ExcelUtil.createExcelCard(list, columnName, columnData,fileName);
            String userAgent = request.getHeader("user-agent");
            Boolean b = userAgent.contains("Edge")
                    && (userAgent.contains("Firefox") || userAgent.contains("Chrome") || userAgent.contains("Safari"));
            if (b) {
                fileName = new String((fileName).getBytes(), "ISO8859-1");
            } else {
                //其他浏览器
                fileName = URLEncoder.encode(fileName, "UTF8");
            }
            response.addHeader("Content-Disposition", "attachment;filename=" + fileName);

            OutputStream os = response.getOutputStream();
            workbook.write(os);
            os.flush();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

因为我这个需求只需要合并前两列,如果有多列合并的话,主要是前一列合并之后修改后一列的flog用来判断。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值