poi导出多级表头

//社保导出表头名
//{字段名称,排序号,level(1.2.3...代表从高到低),父级序号}
public static final String[][] empInsuredHeader = {
        {"公司名称", "0", "1", "-1"},
        {"养老保险", "1", "1", "-1"}, //养老
        {"社保基数", "2", "2", "1"},
        {"参保月份", "3", "2", "1"},
        {"单位比例", "4", "2", "1"},
        {"单位缴纳金额", "5", "2", "1"},
        {"个人比例", "6", "2", "1"},
        {"个人缴纳金额", "7", "2", "1"},
        {"医疗保险", "8", "1", "-1"},   //医疗
        {"社保基数", "9", "2", "8"},
        {"参保月份", "10", "2", "8"},
        {"单位比例", "11", "2", "8"},
        {"单位缴纳金额", "12", "2", "8"},
        {"个人比例", "13", "2", "8"},
        {"个人缴纳金额", "14", "2", "8"},
        {"失业保险", "15", "1", "-1"},   //失业
        {"社保基数", "16", "2", "15"},
        {"参保月份", "17", "2", "15"},
        {"单位比例", "18", "2", "15"},
        {"单位缴纳金额", "19", "2", "15"},
        {"个人比例", "20", "2", "15"},
        {"个人缴纳金额", "21", "2", "15"},
        {"生育保险", "22", "1", "-1"},   //生育
        {"社保基数", "23", "2", "22"},
        {"参保月份", "24", "2", "22"},
        {"单位比例", "25", "2", "22"},
        {"单位缴纳金额", "26", "2", "22"},
        {"个人比例", "27", "2", "22"},
        {"个人缴纳金额", "28", "2", "22"},
        {"工伤保险", "29", "1", "-1"},   //工伤
        {"社保基数", "30", "2", "29"},
        {"参保月份", "31", "2", "29"},
        {"单位比例", "32", "2", "29"},
        {"单位缴纳金额", "33", "2", "29"},
        {"个人比例", "34", "2", "29"},
        {"个人缴纳金额", "35", "2", "29"},
        {"大病保险", "36", "1", "-1"},   //大病
        {"社保基数", "37", "2", "36"},
        {"参保月份", "38", "2", "36"},
        {"单位比例", "39", "2", "36"},
        {"单位缴纳金额", "40", "2", "36"},
        {"个人比例", "41", "2", "36"},
        {"个人缴纳金额", "42", "2", "36"},
        {"缴纳金额", "43", "1", "-1"},
        {"单位缴纳总金额", "44", "2", "43"},
        {"个人缴纳总金额", "45", "2", "43"},
        {"合计", "46", "2", "43"}
};



//各有效名称的字段值   对应Hearder的最低一级的值
public static final String[] empInsuredProperties = {
        "companyName",
        "endowmentBase",
        "endowmentDate", "endowmentPublicRatio", "endowmentPublicAmount", "endowmentPersonalRatio", "endowmentPersonalAmount",
        "medicalBase",
        "medicalDate", "medicalPublicRatio", "medicalPublicAmount", "medicalPersonalRatio", "medicalPersonalAmount",
        "unemploymentBase",
        "unemploymentDate", "unemploymentPublicRatio", "unemploymentPublicAmount", "unemploymentPersonalRatio", "unemploymentPersonalAmount",
        "maternityBase",
        "maternityDate", "maternityPublicRatio", "maternityPublicAmount", "maternityPersonalRatio", "maternityPersonalAmount",
        "injuryBase",
        "injuryDate", "injuryPublicRatio", "injuryPublicAmount", "injuryPersonalRatio", "injuryPersonalAmount",
        "illnessBase",
        "illnessDate", "illnessPublicRatio", "illnessPublicAmount", "illnessPersonalRatio", "illnessPersonalAmount",
        "publicPaymentTotal", "personalPaymentTotal", "paymentTotal"
};

 

protected void exportExcelMultipleHeader(HttpServletResponse response, String[] properties, String sheetName, List list,String[][] headers) {
    OutputStream outputStream = null;
    XSSFWorkbook workbook = null;
    List dataList;
    if (list != null) {
        dataList = new ArrayList(list.size());
        for (Object object : list) {
            String[] row = ExcelUtils.bean2Array(object, properties);
            dataList.add(row);
        }
    } else {
        dataList = Collections.emptyList();
    }
    try {
        outputStream = response.getOutputStream();
        workbook = ExcelUtils.exportExcelMultipleHeader(headers, dataList, sheetName);
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/octet-stream");
        response.addHeader("Content-Disposition",
                "attachment;fileName=" + URLEncoder.encode(sheetName, "utf-8") + ".xlsx");
        workbook.write(outputStream);
        outputStream.flush();
        IOUtils.closeQuietly(outputStream);
    } catch (IOException e) {
        LogUtil.error(e, "导出数据表格异常", "导出excel表格异常");
    } finally {
        IOUtils.closeQuietly(outputStream);
    }
}
/**
 * @Author zhangsj
 * @Description 针对社保方面的数据导出
 */
public static XSSFWorkbook exportExcelMultipleHeader(String[][] headers, List data,
                                                     String sheetName) {
    XSSFWorkbook wb = new XSSFWorkbook();
    XSSFSheet sheet = wb.createSheet(sheetName);
    XSSFCellStyle bodyStyle = getBodyStyle(wb);
    XSSFCellStyle headStyle = getHeadStyle(wb);

    //获取树深度
    int deep = getDeep(headers);

    //冻结表头
    sheet.createFreezePane(0, deep);

    //根据树的深度创建行
    List headerRows = new ArrayList();
    for (int i = 0; i < deep; i++) {
        XSSFRow headerRow = sheet.createRow((short) i);
        headerRow.setHeight((short) 500);
        headerRows.add(headerRow);
    }

    List nodeList = arrayToList(headers);

    CellRangeAddress region = null;
    for (HeaderNode node : nodeList) {
        int level = Integer.parseInt(node.getLevel());
        if (node.isOverNode()) {
            //为叶子节点
            //向下合并单元格
            region = new CellRangeAddress(level - 1, deep - 1, node.getFrontCount(), node.getFrontCount());
            sheet.addMergedRegion(region);
        } else {
            //为非叶子节点
            //向右合并单元格
            region = new CellRangeAddress(level - 1, level - 1, node.getFrontCount(), node.getFrontCount() + node.getAllOverNodeCount() - 1);
            sheet.addMergedRegion(region);
        }

        //解决合并单元格 边框不全问题
        if(region != null){
            for (int i = region.getFirstRow(); i <= region.getLastRow(); i++) {
                XSSFRow row = sheet.getRow(i);
                if (row == null)
                    row = sheet.createRow(i);
                for (int j = region.getFirstColumn(); j <= region.getLastColumn(); j++) {
                    XSSFCell cell = row.getCell(j);
                    if (cell == null) {
                        cell = row.createCell(j);
                        cell.setCellValue(node.getHeaderName());
                    }
                    cell.setCellStyle(headStyle);
                }
            }
        }
    }

    XSSFCell cell = null;
    int j = deep - 1;
    for (String[] row : data) {
        XSSFRow dataRow = sheet.createRow(++j);
        int k = 0;
        if (row.length > 0) {
            for (String v : row) {
                if (!StringUtil.isEmpty(v)) {
                    cell = dataRow.createCell(k++);
                    cell.setCellStyle(bodyStyle);
                    cell.setCellValue(v);
                }else{
                    cell = dataRow.createCell(k++);
                    cell.setCellStyle(bodyStyle);
                    cell.setCellValue("-");
                }
            }
        }
    }

    return wb;
}

private static int getDeep(String[][] header) {
    int deep = 0;
    for (int i = 0; i < header.length; i++) {
        if (Integer.parseInt(header[i][2]) > deep) {
            deep = Integer.parseInt(header[i][2]);
        }
    }
    return deep;
}

/**
 * 数组转化list集合
 *
 * @param header
 * @return
 */
private static List arrayToList(String[][] header) {
    List headerNodes = new ArrayList();
    for (String[] headerNode : header) {
        //获取此节点下的所有叶子节点数量
        int count = getOverNodeCount(headerNode, header);
        int frontCount = getFrontOverNodeCount(headerNode, header);
        headerNodes.add(new HeaderNode(headerNode[0], headerNode[1], headerNode[2], headerNode[3], count, isOverNode(headerNode, header), frontCount));
    }
    return headerNodes;
}


/**
 * 获取当前节点下的所有叶子节点数量
 *
 * @param headerNode
 * @param header
 * @return
 */
private static int getOverNodeCount(String[] headerNode, String[][] header) {
    int count = 0;
    for (int i = 0; i < header.length; i++) {
        if (header[i][3].equals(headerNode[1])) {
            if (isOverNode(header[i], header)) {
                count++;
            } else {
                count += getOverNodeCount(header[i], header);
            }
        }
    }
    return count;
}


/**
 * 判断是否为叶子节点
 *
 * @param headerNode
 * @param header
 * @return
 */
private static boolean isOverNode(String[] headerNode, String[][] header) {
    for (int i = 0; i < header.length; i++) {
        if (header[i][3].equals(headerNode[1])) {
            return false;
        }
    }
    return true;
}


/**
 * 获取当前节点空间顺序之前的所有叶子节点数量
 *
 * @param headerNode
 * @param header
 * @return
 */
private static int getFrontOverNodeCount(String[] headerNode, String[][] header) {
    int count = 0;
    for (int i = 0; i < header.length; i++) {
        if (header[i].equals(headerNode)) {
            break;
        }
        if (isOverNode(header[i], header)) {
            count++;
        }
    }
    return count;
}

 

你可能感兴趣的:(java)