java中的复杂表头导出excel(使用poi附完整代码)

目录

需求背景:

预期效果:

分析需求,提取思路:

1、表头

2、数据

3、合计行

4、表尾

重难点(需要考虑到的知识点):

1、跨列合并

2、字体样式

3、行列宽高

4、单元格水平居中、垂直居中

5、表格中格子的边框

6、文字自动换行

7、表尾的行数是表头行数加数据体行数加合计行行数

完整代码:


需求背景:

之前的导出都是单行表头+数据,所以使用easyexcel框架自带的方法两行代码就搞定了,需求变动之后要导出复杂的表格,更贴合实际运用点,针对客户需求,我们需要重新写导出方法

预期效果:

分析需求,提取思路:

针对复杂的表格还是选取最原始的方法,使用poi创建表格,

java 复制代码
// 创建一个新的 Excel 工作簿
XSSFWorkbook workbook = new XSSFWorkbook();
// 创建一个工作表
XSSFSheet sheet = workbook.createSheet("sheet1");

需要导出的excel分为以下几部分:

1、表头

①附件行(附件1)

创建行使用:

java 复制代码
XSSFRow fileRow = sheet.createRow(0);

在该行创建单元格(列):

java 复制代码
XSSFCell fileCell = fileRow.createCell(0);

②标题行(xx市稻谷生产者补贴分户登记清册)

③表格样式行

④盖章行

⑤数据表头行(序号、姓名、身份证、银行账户等)

2、数据

这块数据直接从数据库中查出来填充就好了

3、合计行

4、表尾

重难点(需要考虑到的知识点):

1、跨列合并

java 复制代码
// 合并单元格
// 合并第一行的前八列
// 起始行、截至行、起始列、截至列
sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(1, 1, 0, 8)); 

2、字体样式

上面讲了创建行、在行上创建单元格(列),样式是设置在单元格上的:

java 复制代码
// 创建大标题单元格样式
XSSFCellStyle cellStyle = workbook.createCellStyle();
XSSFFont font = workbook.createFont();
font.setBold(true); // 加粗字体
font.setFontName("仿宋_GB2312");
font.setFontHeightInPoints((short) 18); // 设置字体大小为三号(16pt)
cellStyle.setFont(font);
// 设置为单元格样式
cell.setCellStyle(cellStyle);

3、行列宽高

设置行高:

java 复制代码
XSSFRow blankRow = sheet.createRow(3);
blankRow.setHeightInPoints(25.5f);

设置列宽:

java 复制代码
sheet.setColumnWidth(0, 6 * 256); // 第1列宽度

4、单元格水平居中、垂直居中

居中是在cellstyle上设置的:

java 复制代码
// 设置单元格居中对齐
cellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中

5、表格中格子的边框

java 复制代码
// 设置边框
cellStyle.setBorderTop(BorderStyle.THIN);
cellStyle.setBorderBottom(BorderStyle.THIN);
cellStyle.setBorderLeft(BorderStyle.THIN);
cellStyle.setBorderRight(BorderStyle.THIN);

6、文字自动换行

java 复制代码
cellStyle.setWrapText(true);

7、表尾的行数是表头行数加数据体行数加合计行行数

完整代码:

java 复制代码
@Override
    public void export(HttpServletResponse response, ApplyQueryVO query) {
        // 创建一个新的 Excel 工作簿
        XSSFWorkbook workbook = new XSSFWorkbook();
        // 创建一个工作表
        XSSFSheet sheet = workbook.createSheet("sheet1");
        // 设置列宽
        sheet.setColumnWidth(0, 6 * 256); // 第1列宽度
        sheet.setColumnWidth(1, 20 * 256); // 第1列宽度
        sheet.setColumnWidth(2, 20 * 256); // 第1列宽度
        sheet.setColumnWidth(3, 22 * 256); // 第1列宽度
        sheet.setColumnWidth(4, 10 * 256); // 第1列宽度
        sheet.setColumnWidth(5, 10 * 256); // 第1列宽度
        sheet.setColumnWidth(6, 12 * 256); // 第1列宽度
        sheet.setColumnWidth(7, 13 * 256); // 第1列宽度
        sheet.setColumnWidth(8, 14 * 256); // 第1列宽度
        // 附件1
        // 创建字体
        Font font = workbook.createFont();
        font.setFontName("黑体"); // 设置字体为黑体
        font.setFontHeightInPoints((short) 12); // 设置字体大小
        // 创建单元格样式并设置字体
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setFont(font);

        XSSFRow fileRow = sheet.createRow(0);
        XSSFCell fileCell = fileRow.createCell(0);
        fileCell.setCellValue("附件1");
        fileCell.setCellStyle(cellStyle);
        // 设置大表头标题
        XSSFRow bigTitleRow = sheet.createRow(1);
        bigTitleRow.setHeightInPoints(33.75f); // 增加行高以便容纳大标题
        // 创建大标题单元格样式
        XSSFCellStyle bigTitleCellStyle = workbook.createCellStyle();
        XSSFFont bigTitleFont = workbook.createFont();
        bigTitleFont.setBold(true); // 加粗字体
        bigTitleFont.setFontName("仿宋_GB2312");
        bigTitleFont.setFontHeightInPoints((short) 18); // 设置字体大小为三号(16pt)
        bigTitleCellStyle.setFont(bigTitleFont);
        // 设置单元格居中对齐
        bigTitleCellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
        bigTitleCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
        // 合并单元格以使大标题横跨所有列
        sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(1, 1, 0, 8)); // 合并第一行的前三列
        // 大标题单元格内容
        XSSFCell bigTitleCell = bigTitleRow.createCell(0);
        bigTitleCell.setCellValue("xxx市稻谷生产者补贴分户登记清册");
        if (Func.isNotBlank(query.getYear())) {
            bigTitleCell.setCellValue("xxx市稻谷生产者补贴分户登记清册" + "(" + query.getYear() + "年)");
        }
        bigTitleCell.setCellStyle(bigTitleCellStyle);
        // 样表格式
        XSSFRow styleRow = sheet.createRow(2);
        XSSFCell styleCell = styleRow.createCell(0);
        styleCell.setCellValue("(样表格式)");
        XSSFCellStyle styleCellStyle = workbook.createCellStyle();
        styleCellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
        styleCell.setCellStyle(styleCellStyle);
        sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(2, 2, 0, 8)); // 合并第一行的前三列
        // 设置普通文字行
        XSSFRow blankRow = sheet.createRow(3);
        blankRow.setHeightInPoints(25.5f);
        XSSFCell blankCell = blankRow.createCell(0);
        // 设置普通文字行
        XSSFRow textRow = sheet.createRow(4);
        XSSFCell textCell = textRow.createCell(0);
        textCell.setCellValue("____镇(街道)   ____村(社区)(盖章)                                                        镇人民政府(街道办事处)(盖章)");
        // 合并单元格以使大标题横跨所有列
        sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(4, 4, 0, 8)); // 合并第一行的前三列

        // 创建数据表头
        XSSFRow headerRow = sheet.createRow(5);
        // 设置行高为42.75磅
        headerRow.setHeightInPoints(42.75f);
        XSSFCellStyle titleCellStyle = workbook.createCellStyle();
        titleCellStyle.setWrapText(true);
        // 设置单元格居中对齐
        titleCellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
        titleCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
        // 设置边框
        titleCellStyle.setBorderTop(BorderStyle.THIN);
        titleCellStyle.setBorderBottom(BorderStyle.THIN);
        titleCellStyle.setBorderLeft(BorderStyle.THIN);
        titleCellStyle.setBorderRight(BorderStyle.THIN);
        XSSFFont titleFont = workbook.createFont();
        titleFont.setBold(true); // 加粗字体
        titleFont.setFontHeightInPoints((short) 12); // 设置字体大小为三号(16pt)
        titleCellStyle.setFont(titleFont);
        XSSFCell cell0 = headerRow.createCell(0);
        cell0.setCellStyle(titleCellStyle);
        XSSFCell cell1 = headerRow.createCell(1);
        cell1.setCellStyle(titleCellStyle);
        XSSFCell cell2 = headerRow.createCell(2);
        cell2.setCellStyle(titleCellStyle);
        XSSFCell cell3 = headerRow.createCell(3);
        cell3.setCellStyle(titleCellStyle);
        XSSFCell cell4 = headerRow.createCell(4);
        cell4.setCellStyle(titleCellStyle);
        XSSFCell cell5 = headerRow.createCell(5);
        cell5.setCellStyle(titleCellStyle);
        XSSFCell cell6 = headerRow.createCell(6);
        cell6.setCellStyle(titleCellStyle);
        XSSFCell cell7 = headerRow.createCell(7);
        cell7.setCellStyle(titleCellStyle);
        XSSFCell cell8 = headerRow.createCell(8);
        cell8.setCellStyle(titleCellStyle);
        // 创建样式并启用换行

        cell0.setCellValue("序号");
        cell1.setCellValue("姓名(单位)");
        cell2.setCellValue("身份证号码");
        cell3.setCellValue("银行账号\n" +
                "(一折通号、三代社保卡号、对公账号)");
        cell4.setCellValue("补贴面积(亩)");
        cell5.setCellValue("补贴标准(元/亩)");
        cell6.setCellValue("补贴金额(元)");
        cell7.setCellValue("联系电话");
        cell8.setCellValue("户主签名");
        // 一折通号(对公账号)
        //补贴面积(亩)
        // 补贴标准(元/亩)
        // 补贴金额(元)
        // 联系电话
        // 添加一些示例数据
        List<RiceSubsidyApplyExcel> listvo = this.listExcel(query);
        XSSFCellStyle bodyCellStyle = workbook.createCellStyle();
        bodyCellStyle.setWrapText(true);
        XSSFFont bodyFont = workbook.createFont();
        bodyFont.setFontName("宋体");
        bodyFont.setFontHeightInPoints((short) 10); // 设置字体大小为三号(16pt)
        bodyCellStyle.setFont(bodyFont);
        // 设置边框
        bodyCellStyle.setBorderTop(BorderStyle.THIN);
        bodyCellStyle.setBorderBottom(BorderStyle.THIN);
        bodyCellStyle.setBorderLeft(BorderStyle.THIN);
        bodyCellStyle.setBorderRight(BorderStyle.THIN);
        bodyCellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
        bodyCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
        for (int i = 0; i < listvo.size(); i++) {
            XSSFRow dataRow = sheet.createRow(6 + i);
            // 设置行高为33.75磅
            dataRow.setHeightInPoints(33.75f); // 行高
//            dataRow.setRowStyle(bodyCellStyle);
            XSSFCell cell00 = dataRow.createCell(0);
            cell00.setCellStyle(bodyCellStyle);
            cell00.setCellValue(listvo.get(i).getRowNum());
            XSSFCell cell01 = dataRow.createCell(1);
            cell01.setCellStyle(bodyCellStyle);
            cell01.setCellValue(listvo.get(i).getFarmerName());
            XSSFCell cell02 = dataRow.createCell(2);
            cell02.setCellStyle(bodyCellStyle);
            cell02.setCellValue(listvo.get(i).getIdCardNo());
            XSSFCell cell03 = dataRow.createCell(3);
            cell03.setCellStyle(bodyCellStyle);
            cell03.setCellValue(listvo.get(i).getSubsidyAccount());
            XSSFCell cell04 = dataRow.createCell(4);
            cell04.setCellStyle(bodyCellStyle);
            cell04.setCellValue(listvo.get(i).getSubsidyArea().toString());
            XSSFCell cell05 = dataRow.createCell(5);
            cell05.setCellStyle(bodyCellStyle);
            String standard = listvo.get(i).getSubsidyStandard();
            standard = getRealStandard(standard);
            cell05.setCellValue(standard);
            XSSFCell cell06 = dataRow.createCell(6);
            cell06.setCellStyle(bodyCellStyle);
            cell06.setCellValue(listvo.get(i).getSubsidyPrice().toString());
            XSSFCell cell07 = dataRow.createCell(7);
            cell07.setCellStyle(bodyCellStyle);
            cell07.setCellValue(listvo.get(i).getContactPhone());
            XSSFCell cell08 = dataRow.createCell(8);
            cell08.setCellStyle(bodyCellStyle);
            cell08.setCellValue("");
        }
        // 调整列宽以适应内容
        /*for (int i = 0; i < 8; i++) {
            sheet.autoSizeColumn(i);
        }*/
        // 设置表尾
        // 合计
        XSSFRow countRow = sheet.createRow(6 + listvo.size());
        countRow.setHeightInPoints(30);
        XSSFCell countCell = countRow.createCell(0);
        countCell.setCellValue("合计");
        sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(6 + listvo.size(), 6 + listvo.size(), 0, 3)); // 合并第一行的前三列
        countCell.setCellStyle(bodyCellStyle);

        XSSFCell countCell1 = countRow.createCell(1);
        countCell1.setCellStyle(bodyCellStyle);

        XSSFCell countCell2 = countRow.createCell(2);
        countCell2.setCellStyle(bodyCellStyle);

        XSSFCell countCell3 = countRow.createCell(3);
        countCell3.setCellStyle(bodyCellStyle);

        // 补贴面积合计
        XSSFCell areaCell = countRow.createCell(4);
        areaCell.setCellValue(listvo.stream().map(RiceSubsidyApplyExcel::getSubsidyArea).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        areaCell.setCellStyle(bodyCellStyle);

        XSSFCell countCell5 = countRow.createCell(5);
        countCell5.setCellStyle(bodyCellStyle);
        // 补贴金额合计
        XSSFCell priceCell = countRow.createCell(6);
        priceCell.setCellValue(listvo.stream().map(RiceSubsidyApplyExcel::getSubsidyPrice).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        priceCell.setCellStyle(bodyCellStyle);

        XSSFCell countCell7 = countRow.createCell(7);
        countCell7.setCellStyle(bodyCellStyle);

        XSSFCell countCell8 = countRow.createCell(8);
        countCell8.setCellStyle(bodyCellStyle);

        XSSFRow tailRow = sheet.createRow(8 + listvo.size());
        tailRow.setHeightInPoints(30f);
        XSSFCell tailCell = tailRow.createCell(0);
        tailCell.setCellValue("村民委员会(社区)主任(签名):                                         数据采集人:(签名):");
        // 合并单元格以使大标题横跨所有列
        sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(8 + listvo.size(), 8 + listvo.size(), 0, 8)); // 合并第一行的前三列
        // 设置表尾
        XSSFRow tailRow2 = sheet.createRow(8 + listvo.size() + 1);
        XSSFCell tailCell2 = tailRow2.createCell(0);
        tailCell2.setCellValue("市级举报电话:市财政xxx            农业农村局xx            镇(街道)举报电话:xxx");
        // 合并单元格以使大标题横跨所有列
        sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(8 + listvo.size() + 1, 8 + listvo.size() + 1, 0, 8)); // 合并第一行的前三列
        // 设置表尾
        XSSFRow tailRow3 = sheet.createRow(8 + listvo.size() + 2);
        XSSFCell tailCell3 = tailRow3.createCell(0);
        tailCell3.setCellValue("注:1.此表由村民委员会(社区)填报,镇人民政府(街道办事处)加盖公章后在村(社区)公示。公示无异议后镇(街道)填报附件2,连同此表一并上报市财政、市农业农村局,并由村民委员会(社区)、镇人民政府(街道办事处)、镇(街道)财政所分别留档。");
        // 合并单元格以使大标题横跨所有列
        sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(8 + listvo.size() + 2, 8 + listvo.size() + 2, 0, 8)); // 合并第一行的前三列
        //  2.补贴面积保留2位小数。
        // 设置表尾
        XSSFRow tailRow4 = sheet.createRow(8 + listvo.size() + 3);
        XSSFCell tailCell4 = tailRow4.createCell(0);
        tailCell4.setCellValue("2.补贴面积保留2位小数。");
        // 合并单元格以使大标题横跨所有列
        sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(8 + listvo.size() + 3, 8 + listvo.size() + 3, 0, 8)); // 合并第一行的前三列
        // 设置响应类型和头部
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=稻谷补贴.xlsx");

        // 将工作簿写入响应输出流
        try (OutputStream out = response.getOutputStream()) {
            workbook.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭工作簿
            try {
                workbook.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
相关推荐
cuiyaonan20004 小时前
SpringBoot 下的Excel文件损坏与内容乱码问题
spring boot·后端·excel
cuisidong19975 小时前
excel IF函数用法
excel
云空5 小时前
《基于 Excel 和 CSV 文件数据的迁移学习应用》
人工智能·excel·迁移学习
BLOB_1010018 小时前
【折腾一上午】Java POI 导出 Excel 自适应列宽行高
java·excel
云表平台10 小时前
微软苹果强强联合,Word、Excel、PowerPoint支持苹果设备跨端接力
微软·word·excel
丿似锦1 天前
Excel-多表数据查找匹配(VLOOKUP)
excel
_oP_i1 天前
Excel 单元格小数点精确位数机制
excel
taller_20001 天前
如何使用VBA识别Excel中的“单元格中的图片”(1/2)
excel·图片·插入图片·单元格中的图片·picture in cell
winfredzhang2 天前
使用 python中 pandas 将 Excel 转换为 CSV 文件
python·excel·pandas·csv文件
Eiceblue2 天前
用Python设置、更新和获取Excel单元格的值
开发语言·python·excel·visual studio