HSSFWorkbook——导出excel,动态合并单元格

一 前言

开发中,对于导出一个excel表格这样的功能很常见,这里谈谈我所知道的相关知识

二 需求 

导出某个套餐所关联的所有项目的一个Excel表格

三 HSSFWorkbook

        //创建一个Excel文件

        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet();

        //设置列宽 参数一:第几列,参数二:列宽(列宽有限制,会出现空指针)
        sheet.setColumnWidth(0, 1000);
        sheet.setColumnWidth(1, 1000);
        sheet.setColumnWidth(2, 1000);
        sheet.setColumnWidth(3, 1000);

        //样式
        //两个最基本的样式
        HSSFCellWork sheetStyle = workbook.createCellStyle();
        sheetStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 左右居中
        sheetStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 上下居中
        //其他比如颜色,边框样式就不例举了

        try{
            int rowNum = 0;
            HSSFRow row  = sheet.getRow(rowNum);
            if(row == null) {
                HSSFRow row = sheet.createRow(rowNum);
            }
            //第一行高度 相当于标题
            row.setHeight((short)500);
            //设置标题
            row.setCellValue("套餐ID");
            row.setCellValue("套餐名称");
            row.setCellValue("。。。。");


            //获取数据集 list
            List<Object> list = XXXService.get(xxx);

            //动态生成表格数据
            if(list != null && list.size() > 0) {
                for(Object item : list) {
                    row.setCellValue(item.getId);
                    row.setCellValue(item.getName);
                    row.setCellValue(item.getXXX);
                    rowNum++;
                }
            }

            //接下来就是文件处理了 可能用到阿里云的东西,看你公司用的技术

        }catch (Exception e) {
            e.printStackTrace();
            //返回给上层 用来判断是否成功
            return "500";
        }finally {

        }

        return "";

    合并单元格
        老版本
            sheet.addMergedRegion(new Region((short)0,(short)i,(short)1,(short)i));
        现在用
            addMergedRegion(new CellRangeAddress(row,row,col,col);
            参数一 第一个单元格所在行
            参数二 第二个单元格所在行
            参数三 第一个单元格所在列
            参数死 第二个单元格所在列
            
    其实对于固定行和列的合并很简单,复杂的是动态合并,行和宽都是不确定的,我以前没有好好想过这个问题,今天仔细想了想,功能还是实现了,很开心,我这里给个思路:
    分析:首先你要将数据分组!!!!你要知道四个参数中,在同一个列下,有两个参数我们是知道的,就是两个col是知道的,问题关键是,前两个行数不确定,因为,第一个单元格行数,你不知道前面已有多少行,即使知道,你也不知道这组数据长度(我简称是跨度)。
    好的问题已找到!说下我今天实现的思路!
    首先,两个for循环找出重复的name(数据结构简单算法),对于重复数据,我们只放一个到map中,key是name,value是list,先放一个0进去,数据结构是Map<String,List<Integer>>
    然后遍历list的时候,先判断,是否在map中,如果是,就记下每次出现的行数存到list中(好处后面你就知道),当然这里有一些细节。
    遍历完后,数据都写到文件中了,这个时候单独进行合并。这个时候就知道map中list存的行数的重要性了!他们分别记录了,该组数据第一次出现的行数一直到最有一次出现的行数,写到这里,聪明的你可能已经想到明天接下来的代码了:list中第一个数据就是第一个单元格所在行数,list最后一个数据就是第二个单元格所在行数。。
 

     代码:
     
     //记录重复数据
     for(int i = 0; i< itemList.size() - 1; i++) {
        for(int j = itemList.size() - 1 ; j > i ; j--) {
                    
          if(itemList.get(i).getSummaryName().equals(itemList.get(j).getSummaryName())) {
                List<Integer> innerList = map.get(itemList.get(i).getSummaryName());
                        if(innerList == null) {
                            List<Integer> list = new ArrayList<Integer>();
                            list.add(0);
                            map.put(itemList.get(i).getSummaryName(),list);
                        }
                    }
                }
            }

     }


    //记录所有有共同点数据的行数
    for(String title : titleSet) {
                    
		 row.createCell(0).setCellValue(title);
					  
			if(map.get(title) != null) {
				List<Integer> listInner = map.get(title);
				listInner.add(i);
				map.put(title,listInner);
			}
			i++;
					
		 }
	 rowNum ++;




    //根据map合并
    for(Map.Entry<String, List<Integer>> entry : map.entrySet()) {
                                                                   List<Integer> list = entry.getValue();
    
        int firstRow = list.get(0);
    
        int secondRow = list.get(list.size() - 1);
    
        CellRangeAddress range = new CellRangeAddress(firstRow,secondRow,0,0);
                                            sheet.addMergedRegion(range);

    }

    其实,我以前也是很怕遇到复杂的问题,后来慢慢觉得,怕也是解决不了问题的,躲掉这次,下次你怎么办?只有直面困难,勇往直前,才能使自己变强!
        

 

 

 

 

 

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值