XSSFWorkbook自由合并单元格并设置单元格样式

我的需求是这样子的:导出下面格式的报表。

(这个格式应该是之前打卡APP的或者是手作的。5月份接入了qiyeweixin打卡,qiyeweixin没有提供导出这样报表的功能。只提供了API给我们开发这样的功能,所以我的任务是自动获取qiyeweixin打卡记录,按照这个格式的报表统计)

这个是主方法体,从new XSSFWorkbook()开始。这个表格创建了....(好像不用说..)。

public void createXlsx(HttpServletResponse response,AttendanceQueryCriteria criteria){
        if(criteria.getMonth()==null || "".equals(criteria.getMonth())){//不传入时间默认取上个月的考勤
            criteria.setMonth(getUpperMonth());//上个月时间yyyy-mm
        }
        String date=criteria.getMonth();//格式2022-04
        String[] dates=date.split("-");
        String staDate=date+"-01";//2022-04-01
        String endDate=date+"-"+getLastDayOfMonth(Integer.parseInt(dates[0]),Integer.parseInt(dates[1]));
        XSSFWorkbook xssfWorkbook = new XSSFWorkbook();//创建工作簿
        String deptName = criteria.getDeptName()==null?"%":criteria.getDeptName();
        List<String> list = attUserRepository.groupByDeptName(deptName);//获取所有部门创建sheet
        XSSFSheet sheet=null;
        for(int i=0;i<list.size();i++){
            sheet = xssfWorkbook.createSheet(list.get(i));//创建工作表
            createHead(sheet,staDate,endDate);     //创建表头
            createTitle(sheet,date,list.get(i));        //创建标题
            criteria.setDeptName(list.get(i));
            List<Map<String,List<String>>> rows=this.getRowsDate(criteria);
            createRow(sheet,rows);//创建行
            createFooter(sheet);//创建底部
        }
        OutputStream osOut=null;
        try {
            response.setHeader("Content-Disposition", "attachment;filename=baobiao.xlsx");
            response.setContentType("application/octet-stream;charset=UTF-8");
            osOut = response.getOutputStream();
            xssfWorkbook.write(osOut);
            osOut.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                osOut.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

再到表头,标题是根据表头的列数合并的,因为表头列数会随着月份的天数有变。

private void createHead(XSSFSheet sheet,String  staDate,String endDate){//创建表头
        String[] heads = {"序号","姓名","部门","应出勤天数","实际出勤天数(包含法定节假日)"
                ,"全勤奖","请假t","请假类型","平时加班h","周日加班h"
                ,"调休h","欠休h","迟到早退m","迟到早退乐捐","缺卡","缺卡乐捐","旷工h"};
        XSSFRow head1 = sheet.createRow(1);//表头
        XSSFRow head2 = sheet.createRow(2);//表头
        head2.setHeight((short)(30*20));
        for(int i = 0;i < heads.length;i++){
            if(i==0){
                sheet.setColumnWidth(i,4*256);
            }else if(i==1){
                sheet.setColumnWidth(i,7*256);
            }else if(i==2){
                sheet.setColumnWidth(i,9*256);
            }else{
                sheet.setColumnWidth(i,5*256);
            }
            XSSFCell cell1 = head1.createCell(i);
            XSSFCell cell2 = head2.createCell(i);
            cell1.setCellValue(heads[i]);
            sheet.addMergedRegion(new CellRangeAddress(1,2,i,i));
            cell1.setCellStyle(setFontBoldStyle(sheet,setBorderStyle(sheet.getWorkbook())));
            cell2.setCellStyle(setFontBoldStyle(sheet,setBorderStyle(sheet.getWorkbook())));
        }
        String[] staDates=staDate.split("-");
        String[] endDates=endDate.split("-");
        LocalDate sta = LocalDate.of(Integer.parseInt(staDates[0]), Integer.parseInt(staDates[1]), Integer.parseInt(staDates[2]));
        LocalDate end = LocalDate.of(Integer.parseInt(endDates[0]), Integer.parseInt(endDates[1]), Integer.parseInt(endDates[2]));
        end = end.plusDays(1);//2022-04-30   2022-05-01
        Map<String,String> map=new HashMap<String,String>();
        map.put("SUNDAY","日");
        map.put("MONDAY","一");
        map.put("TUESDAY","二");
        map.put("WEDNESDAY","三");
        map.put("THURSDAY","四");
        map.put("FRIDAY","五");
        map.put("SATURDAY","六");
        int j=heads.length;
        while(sta.isBefore(end)){
            sheet.setColumnWidth(j,4*280);
            XSSFCell cell1=head1.createCell(j);
            cell1.setCellValue(sta.getDayOfMonth());
            cell1.setCellStyle(setBorderStyle(sheet.getWorkbook()));
            XSSFCell cell2=head2.createCell(j);
            cell2.setCellValue(map.get(sta.getDayOfWeek().name()));
            cell2.setCellStyle(setBorderStyle(sheet.getWorkbook()));
            j++;
            sta = sta.plusDays(1);
        }
        XSSFCell cell = head1.createCell(j);
        XSSFCell cell2=head2.createCell(j);
        cell.setCellValue("本人签字");
        cell.setCellStyle(setBorderStyle(sheet.getWorkbook()));
        cell2.setCellStyle(setBorderStyle(sheet.getWorkbook()));
        sheet.addMergedRegion(new CellRangeAddress(1,2,j,j));
    }
private void createTitle(XSSFSheet sheet,String date,String name){//创建标题
        XSSFRow head = sheet.createRow(0);//标题
        XSSFCell cell=head.createCell(0);
        cell.setCellValue(name+date+"考勤表");
        sheet.addMergedRegion(new CellRangeAddress(0,0,0,sheet.getRow(1).getLastCellNum()-1));
        head.setHeight((short)(40*20));
        XSSFFont f = sheet.getWorkbook().createFont();
        f.setFontHeightInPoints((short) 18);//字号
        f.setUnderline(Font.U_SINGLE);//设置下划线
        f.setBold(true);
        XSSFCellStyle style=setBorderStyle(sheet.getWorkbook());
        style.setFont(f);
        cell.setCellStyle(style);
    }
//设计样式
    private XSSFCellStyle setBorderStyle(XSSFWorkbook wb){
        XSSFCellStyle cellStyle=wb.createCellStyle();
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyle.setWrapText(true);
        return cellStyle;
    }

代码有点多,不全部贴上来了。主要是知道能做成这样,根据自己的需求,去写业务逻辑就ok..

下图是使用XSSFWorkbook做出来的效果

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值