Nginx配置 软件测试工程师 金融信贷 windows debugging session gwt seo计费系统 oracle限制查询条数 jq入口函数 centos7安装gcc ubuntu更改文件夹权限 oracle重命名表名 yml文件注释 plsql卸载 linux启动mysql命令 python安装mysql python类和对象 python设置环境变量 python导入文件 javamysql java运算符 java中正则表达式 java函数式接口 java索引 java定义 怎么安装linux linux硬盘 java游戏开发教程 bat脚本 qq免安装版 电脑手机模拟器 苍灵世界 win10wifi c4d挤压怎么用 微信昵称特殊字符保存 微信预约系统 qt5下载 华为手机屏保怎么设置 ae烟雾特效
当前位置: 首页 > 学习教程  > java

Java从零开始实现导出excel(三)

2021/2/23 10:33:05 文章标签:

Java从零开始实现导出excel(三) 新人博主,随笔记录。主要还是通过自己日常工作积累,系统整理一些技术。希望能够节省更多人的时间,走出自己的路。 简述 新的一年,先祝各位小伙伴新的一年,事业…

Java从零开始实现导出excel(三)

新人博主,随笔记录。主要还是通过自己日常工作积累,系统整理一些技术。希望能够节省更多人的时间,走出自己的路。

简述

新的一年,先祝各位小伙伴新的一年,事业有成,身体健康,最重要的暴富发财。

这是年后的第一篇文章,其实篇文章我纠结了很久,excel的导出我的前两篇文章基本都够用了。还有些复杂的场景:复杂表头和复杂数据

同样我去研究了EasyExcel官方文档,个人感觉在这两个方面并没有太多提升。而我看我用的复杂表头技术,和网上的都差不多大家伙都能搜索到。我这里就不再重复写了,给两个链接小伙伴们可以去看看。

poi进行excel复杂表头导出

POI导出复杂表头

这篇文章主要是实现复杂数据,以及excel中颜色的使用。当然这一次我们用的是POI,不再使用EasyExcel。主要的思想就是使用POI在excel表格中一行一行的写入。

环境搭建

这一篇我们用同一个工程。不过我们需要添加新的jar包,这次我们使用的是POI。不知道工程搭建的小伙伴可以去瞟一眼我的第一篇文章Java从零开始实现导出excel(一)

需要使用到的jar包(这里我都是用maven注入的)

 <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-base</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-web</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-annotation</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17-beta1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>

这里我们需要特别注意的一点:
在这里插入图片描述
同时引入EasyExecl的jar包 和 POI jar包时会有 jar包冲突所以jar包的版本得是 3.17-beta1.

下面是使用POI实现excel的导出

这次首先说明我们需要模拟的场景:
在一个sheet页中,有两个不同的表格,给表格中相同的数据标上相同的底色。

这里我用的是:两个不同的学生成绩表,成绩相同的学生底色相同

  1. 添加另外一个学生实体
  2. 编写使用poi导出的方法
  3. 编写ExcelStyle类,控制excel表格的样式
  4. 编写导出的controller

学生实体

/**
 * 学生2
 */
@Data
public class Student2 {
    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private int age;

    /**
     * 性别
     */
    private String sex;


    /**
     * 成绩
     */
    private Integer fraction;
}

导出的controller

 /**
     * 使用poi导出excel
     *
     * 两个不同的学生成绩表,成绩相同的学生底色相同
     * @param response
     * @throws Exception
     */
    @GetMapping(value = "/exportPoiExcel")
    public void exportPoiExcel(HttpServletResponse response) throws Exception {
        String title = "学生成绩对比表";
        String[] headers1 = {"姓名","年龄","性别","学号","家庭地址","成绩"};
        String[] headers2 = {"姓名","性别","性别","成绩"};
        ExcelUtil.fillExcelData(getData(), getData1(), headers1, headers2, title, response);

    }

这里的我们用的字符串数组装两个表得表头;

poi导出的方法

 /**
     * 利用反射机制遍历对象的属性值,并放入单元格中,为excel添加样式
     */
    public static void fillExcelData(List<Student> list, List<Student2> list2, String[] headers, String[] headers2, String title, HttpServletResponse response) throws Exception {
        // 创建工作薄
        HSSFWorkbook wb = new HSSFWorkbook();
        // 生成一个表格
        HSSFSheet sheet = wb.createSheet(title);

        // 设置表格默认宽度为15个字节
        sheet.setDefaultColumnWidth((short) 25);

        //颜色控制器
        Map<String, Integer> colorMap = new HashMap<>();
        int colorIndex = 10;//颜色索引
        int moreColorIndex = 0;//超过索引

        ExcelStyle excelStyle = new ExcelStyle(wb);
        CellStyle style = excelStyle.getTitleStyle(wb);//获取标题样式
        CellStyle style2 = excelStyle.getHeaderStyle(wb);//获取表头样式
        CellStyle style3 = excelStyle.getHeaderExplainStyle(wb);//获取表头说明样式

        // 标题
        int rowIndex = 0;//行数索引
        // 合并单元格0到headers.length -1行
        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 0, headers.length - 1));
        HSSFRow row0 = sheet.createRow(rowIndex++);
        row0.setHeightInPoints(26);
        HSSFCell cell1 = row0.createCell(0);
        cell1.setCellStyle(style);
        cell1.setCellValue(title);
        for (short i = 1; i < headers.length; i++) {
            HSSFCell cell = row0.createCell(i);
            cell.setCellStyle(style);
        }

        // 合并单元格0到headers.length -2行
        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 0, headers.length - 1));
        //添加列表说明
        HSSFRow row1 = sheet.createRow(rowIndex++);
        row1.setHeightInPoints(16);
        HSSFCell cell2 = row1.createCell(0);
        cell2.setCellStyle(style3);
        cell2.setCellValue("1.列表格式一");
        for (short i = 1; i < headers.length; i++) {
            HSSFCell cell = row1.createCell(i);
            cell.setCellStyle(style3);
        }

        // 产生表格表头行
        HSSFRow row = sheet.createRow(rowIndex++);
        row.setHeightInPoints(20);
        for (short i = 0; i < headers.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellStyle(style2);
            cell.setCellValue(headers[i]);
        }

        // 产生表格内容行
        if (list != null && list.size() > 0) {
            for (Student obj : list) {
                // 利用反射得到对象的属性
                Class cls = obj.getClass();
                java.lang.reflect.Field[] flds = cls.getDeclaredFields(); // 得到私有属性
                row = sheet.createRow(rowIndex++);
                row.setHeightInPoints(30);//设置行高
                CellStyle style4 = excelStyle.getListContentStyle(wb);//获取列表内容样式
                //判断是否有相同成绩得学生
                List<Student2> collect2 = list2.stream().filter(data -> data.getFraction().equals(obj.getFraction())).collect(Collectors.toList());
                List<Student> collect1 = list.stream().filter(data -> data.getFraction().equals(obj.getFraction())).collect(Collectors.toList());
                if (collect2.size() + collect1.size() > 1 && colorMap.get(String.valueOf(obj.getFraction())) == null) {
                    colorMap.put(String.valueOf(obj.getFraction()), colorIndex);//加入颜色控制器
                    colorIndex++;
                    if (colorIndex == 27) {//调色板中..27,32-39的索引为空
                        colorIndex++;
                    }
                    if (colorIndex > 31 && colorIndex < 40) {//调色板中.31-39的索引为空
                        colorIndex = 40;
                    }
                    if (colorIndex > 64) {//调色板最大索引64
                        moreColorIndex = 9;
                    }
                }

                if (colorMap.get(String.valueOf(obj.getFraction())) != null || colorIndex > 64) {//超过调色板的项目数据底色都为白色
                    style4.setFillForegroundColor(IndexedColors.fromInt(moreColorIndex == 0 ? colorMap.get(String.valueOf(obj.getFraction())) : moreColorIndex).index);
                    style4.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                }
                for (int j = 0; j < headers.length; j++) {
                    flds[j].setAccessible(true);
                    HSSFCell cell = row.createCell(j);
                    cell.setCellStyle(style4);
                    cell.setCellValue((flds[j].get(obj)).toString());
                }
            }
        }

        //合并单元格
        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 0, headers2.length - 1));
        //添加列表说明
        HSSFRow row2 = sheet.createRow(rowIndex++);
        row2.setHeightInPoints(16);
        HSSFCell cell3 = row2.createCell(0);
        cell3.setCellStyle(style3);
        cell3.setCellValue("1.列表格式二");
        for (short i = 1; i < headers2.length; i++) {
            HSSFCell cell = row2.createCell(i);
            cell.setCellStyle(style3);
        }

        // 产生表头行
        HSSFRow row_cy = sheet.createRow(rowIndex++);
        row_cy.setHeightInPoints(20);
        for (short i = 0; i < headers2.length; i++) {
            HSSFCell cell = row_cy.createCell(i);
            cell.setCellStyle(style2);
            cell.setCellValue(headers2[i]);
        }

        // 产生表格内容行
        if (list2 != null && list2.size() > 0) {
            for (Student2 obj : list2) {
                // 利用反射得到对象的属性
                Class cls = obj.getClass();
                java.lang.reflect.Field[] flds = cls.getDeclaredFields(); // 得到私有属性
                row = sheet.createRow(rowIndex++);
                row.setHeightInPoints(30);//设置行高
                CellStyle style4 = excelStyle.getListContentStyle(wb);//获取列表内容样式
                //判断是否有相同成绩得学生
                List<Student2> collectCy = list2.stream().filter(data -> data.getFraction().equals(obj.getFraction())).collect(Collectors.toList());
                if (collectCy.size() > 1 && colorMap.get(String.valueOf(obj.getFraction())) == null) {
                    colorMap.put(String.valueOf(obj.getFraction()), colorIndex);//加入颜色控制器
                    colorIndex++;
                    if (colorIndex == 27) {//调色板中..27,32-39的索引为空
                        colorIndex++;
                    }
                    if (colorIndex > 31 && colorIndex < 40) {//调色板中.31-39的索引为空
                        colorIndex = 40;
                    }
                    if (colorIndex > 64) {//调色板最大索引64
                        moreColorIndex = 9;
                    }
                }
                if (colorMap.get(String.valueOf(obj.getFraction())) != null || colorIndex > 64) {//超过调色板的项目数据底色都为白色
                    style4.setFillForegroundColor(IndexedColors.fromInt(moreColorIndex == 0 ? colorMap.get(String.valueOf(obj.getFraction())) : moreColorIndex).index);
                    style4.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                }
//
                for (int j = 0; j < headers2.length; j++) {
                    flds[j].setAccessible(true);
                    HSSFCell cell = row.createCell(j);
                    cell.setCellStyle(style4);
                    cell.setCellValue((flds[j].get(obj)).toString());
                }
            }
        }

        response.setContentType("multipart/form-data");
        response.setCharacterEncoding("utf-8");
        String fileName = "学生出成绩对比表" + ".xls";
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("gb2312"), "iso8859-1"));
        response.setContentType("application/ynd.ms-excel;charset=UTF-8");
        OutputStream out = response.getOutputStream();
        wb.write(out);
        out.flush();
        out.close();
    }

这个导出的方法是实现这个功能的关键:

  1. 这里面用到了反射机制获取对象中的属性。在这里插入图片描述

  2. 在对列表内容进行处理的时候,这里用到了JDK1.8新特性 stream流在这里插入图片描述

  3. 就是poi中颜色的注入,这里面有 。颜色索引从9-64其中27,32-39的索引是缺失的,使用的时候我们避开它们,否则会报空指针

颜色索引链接

ExcelStyle类

这个类内容比较多,我贴一点关键的方法,具体大家可以去我的源码中看。这个里面主要是继承两个父类:
ExcelExportStylerDefaultImpl
IExcelExportStyler
在这里插入图片描述

/**
     * 生成标题样式
     * @param workbook
     * @return
     */
    public CellStyle getTitleStyle(Workbook workbook) {
        CellStyle style = getBaseCellStyle(workbook);
        // 前景色
        style.setFillForegroundColor(IndexedColors.LIGHT_YELLOW.index);
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setWrapText(true);
        // 生成标题字体
        Font font = getFont(workbook,(short) 16,true);
        // 把字体应用到当前的样式
        style.setFont(font);
        return style;
    }
    
 /**
     * 基础样式
     *
     * @return
     */
    private CellStyle getBaseCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        //下边框
        style.setBorderBottom(BorderStyle.THIN);
        //左边框
        style.setBorderLeft(BorderStyle.THIN);
        //上边框
        style.setBorderTop(BorderStyle.THIN);
        //右边框
        style.setBorderRight(BorderStyle.THIN);
        //水平居中
        style.setAlignment(HorizontalAlignment.CENTER);
        //上下居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        //设置自动换行
        style.setWrapText(true);
        return style;
    }
    
     /**
     * 生成表头样式
     * @param workbook
     * @return
     */
    public CellStyle getHeaderStyle(Workbook workbook) {

        CellStyle style = getBaseCellStyle(workbook);
        style.setFillForegroundColor(IndexedColors.LIME.index);
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Font font = getFont(workbook, FONT_SIZE_TWELVE, true);
        // 把字体应用到当前的样式
        style.setFont(font);
        return style;
    }
 /**
     * 生成表头说明样式
     * @param workbook
     * @return
     */
    public CellStyle getHeaderExplainStyle(Workbook workbook) {
        CellStyle style = getBaseCellStyle(workbook);
        style.setAlignment(HorizontalAlignment.LEFT);
        Font font = getFont(workbook, FONT_SIZE_TWELVE, false);
        font.setColor(HSSFColor.RED.index);
        // 把字体应用到当前的样式
        style.setFont(font);
        return style;
    }

导出结果

在这里插入图片描述

源码地址


本文链接: http://www.dtmao.cc/news_show_2036697.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?