Java实现集合和Excel文件相互转换

news/2024/7/21 6:06:15 标签: java, excel

目录

    • 一、集合转化为Excel文件
    • 二、Excel文件转化为集合

一、集合转化为Excel文件

效果如下,是将集合转化为Excel文件,Excel包含合并单元格。
在这里插入图片描述
实体类:

java">@Data
public class ClassGrade {
    /** 年级 */
    private String grade;
    /** 班主任 */
    private String leader;
    /** 学生列表 */
    private List<Student> students;

    @Data
    public static class Student {
        /** 姓名 */
        private String name;
        /** 年龄 */
        private Integer age;
        /** 性别 */
        private String sex;
        /** 成绩 */
        private Integer gradeResult;
    }
}

需求就是将ClassGrade的集合转化为Excel表格对外输出。没有针对当前类去逐个取值处理,用到了反射来处理,达到了简化代码通用的目的。这个只针对有一个合并单元格的情形,如果是合并单元格中包含合并单元格的话,还需要加代码去处理。
实现代码如下:
1.初始化表头类,参数为表头集合

java">    public static SXSSFWorkbook makeExcelHead(String[] titles) {
        SXSSFWorkbook workbook = new SXSSFWorkbook();
        CellStyle styleTitle = getTitleStyle(workbook, (short) 16);
        SXSSFSheet sheet = workbook.createSheet();
        SXSSFRow rowTitle = sheet.createRow(0);
        for (int i = 0; i < titles.length; i++) {
            sheet.setDefaultColumnWidth(25);
            SXSSFCell cellTitle = rowTitle.createCell(i);
            // 为标题设置背景颜色
            styleTitle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            styleTitle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.GREY_25_PERCENT.getIndex());
            cellTitle.setCellValue(titles[i]);
            cellTitle.setCellStyle(styleTitle);
        }
        return workbook;
    }

2.反射获取实体的值

java">    public static <T> Object getProperty(T t, String propertyName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IndexOutOfBoundsException {
        Class<?> aClass = t.getClass();
        propertyName = propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
        Method method = aClass.getMethod("get" + propertyName);
        Object invoke = method.invoke(t);
        return invoke;
    }

2.将集合转化为Excel

java">    @Test
    public void exportExcel() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        //初始化数据
        List<ClassGrade> fileList = new ArrayList<>();
        for (int m = 1; m <= 1; m++) {
            fileList.addAll(getGrades());
        }

        //表头名称
        String[] title = {"班主任", "学生姓名", "学生年龄", "学生性别", "学生成绩", "班级"};
        SXSSFWorkbook workbook = SXSSFWorkbookUtil.makeExcelHead(title);

        //每一列表头属性,如果子类里面的,则提取子类里面对应的属性名
        String[] properties = {"leader", "name", "age", "sex", "gradeResult", "grade"};

        //获取当前sheet
        SXSSFSheet sheet = workbook.getSheetAt(0);
        int initRowNum = 0;
        //遍历数据,需要根据业务逻辑去处理是否合并单元格
        for (int i = 0; i < fileList.size(); i++) {
            ClassGrade file = fileList.get(i);
            int size = file.getStudents().size();

			//创建行,以子类的集合数为准
            int startRowNum = initRowNum + 1;
            int lastRowNum = startRowNum + size - 1;
            SXSSFRow row = sheet.getRow(startRowNum);
            if (row == null) {
                row = sheet.createRow(startRowNum);
            }

            //班主任一列,处理合并单元格
            for (int m = 0; m < 1; m++) {
                if (lastRowNum - startRowNum > 0) {
                    sheet.addMergedRegion(new CellRangeAddress(startRowNum, lastRowNum, m, m));
                }
                createCell(row, m, SXSSFWorkbookUtil.getProperty(file, properties[m]));
            }

            //处理学生姓名~学生成绩四列,非合并单元格信息
            int xRowNum = startRowNum;
            List<ClassGrade.Student> receiptItems = file.getStudents();
            for (ClassGrade.Student student : receiptItems) {
                SXSSFRow row1 = sheet.getRow(xRowNum);
                if (row1 == null) {
                    row1 = sheet.createRow(xRowNum);
                }
                for (int q = 1; q <= 4; q++) {
                	//利用反射获取到值,并且设置到cell里面
                    createCell(row1, q, SXSSFWorkbookUtil.getProperty(student, properties[q]));
                }
                xRowNum++;
            }

            //处理班级信息合并单元格
            for (int n = 5; n <= 5; n++) {
                if (lastRowNum - startRowNum >= 1) {
                    sheet.addMergedRegion(new CellRangeAddress(startRowNum, lastRowNum, n, n));
                }
                createCell(row, n, SXSSFWorkbookUtil.getProperty(file, properties[n]));
            }
            initRowNum = lastRowNum;

        }

        //导出
        try (
                FileOutputStream excel = new FileOutputStream("excel.xls");
                BufferedOutputStream bos = new BufferedOutputStream(excel)) {
            workbook.write(bos);
            System.out.println("导出完成");
        } catch (
                IOException e) {
            System.out.println("导出失败:" + e.getMessage());
        }

    }

    private void createCell(SXSSFRow row, int column, Object value) {
        SXSSFCell cell = row.createCell(column);
        if (value != null) {
            cell.setCellValue(String.valueOf(value));
        }
    }

效果
在这里插入图片描述

二、Excel文件转化为集合

如题,将获取到的excel文件流转化为集合进行处理。挺简单的。思路就是将一个文件流转化为一个备用类,再将备用类转化为想要的集合。
excel
在这里插入图片描述
备用类代码:

java">@Data
public class ClassGrade2 {
    /** 年级 */
    private String grade;
    /** 班主任 */
    private String leader;
    /** 姓名 */
    private String name;
    /** 年龄 */
    private Integer age;
    /** 性别 */
    private String sex;
    /** 成绩 */
    private Integer gradeResult;
}

转化代码:

java">    @Test
    public void test1() {
        ExcelReader reader = ExcelUtil.getReader("excelToList.xls");
        List<List<Object>> rows = reader.read();
        //根据excel的结构,需要准备一个备用类接收数据
        List<ClassGrade2> listBaks = new ArrayList<>();

        //初始化属性,属性是备用类的属性名
        String[] properties = {"leader", "name", "age", "sex", "gradeResult", "grade"};
        for (int j = 1; j < rows.size(); j++) {
            List<Object> cells = rows.get(j);
            try {
                //反射获取值,组装成备用类
                ClassGrade2 file = new ClassGrade2();
                Class<?> clz = file.getClass();
                Method[] methods = clz.getDeclaredMethods();
                for (int i = 0; i < cells.size(); i++) {
                    String propertyName = properties[i].substring(0, 1).toUpperCase() + properties[i].substring(1);
                    Method method = Arrays.stream(methods).filter(m -> Objects.equal(m.getName(), "set" + propertyName)).findFirst().orElse(null);
                    Object cell = cells.get(i);
                    if (cell == null) {
                        continue;
                    }
                    Field field = clz.getDeclaredField(properties[i]);
                    String fieldType = field.getType().getName();
                    if (fieldType.equals("java.lang.String")) {
                        method.invoke(file, String.valueOf(cell));
                    } else if (fieldType.equals("java.math.BigDecimal")) {
                        method.invoke(file, new BigDecimal(String.valueOf(cell)));
                    }
                }
                listBaks.add(file);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } finally {

            }
        }
        //备用类转化为想要的集合类
        int i = 0;
        List<ClassGrade> files = new ArrayList<>();
        for (int m = 0; m < listBaks.size(); m++) {
            ClassGrade2 fileBak = listBaks.get(m);
            if (Strings.isNotEmpty(fileBak.getGrade())) {
                ClassGrade file = BeanUtil.copyProperties(fileBak, ClassGrade.class);
                files.add(file);

                ClassGrade.Student item = BeanUtil.copyProperties(fileBak, ClassGrade.Student.class);
                List<ClassGrade.Student> items = new ArrayList<>();
                items.add(item);
                file.setStudents(items);
                i++;
            } else {
                ClassGrade.Student item = BeanUtil.copyProperties(fileBak, ClassGrade.Student.class);
                ClassGrade file = files.get(i - 1);
                List<ClassGrade.Student> items = CollectionUtils.isEmpty(file.getStudents()) ? new ArrayList<>() : file.getStudents();
                items.add(item);
                file.setStudents(items);
            }
        }
        log.info("{}", JSONArray.toJSONString(listBaks));
        log.info("{}", JSONArray.toJSONString(files));
    }

实现效果:

java">11:47:03.635 [main] INFO Excel3Test - [{"grade":"八年级1班","leader":"赵老师","name":"张三","sex":"女"},{"grade":"八年级1班","leader":"赵老师","name":"李四","sex":"女"},{"grade":"八年级1班","leader":"赵老师","name":"王五","sex":"女"}]
11:47:03.647 [main] INFO Excel3Test - [{"grade":"八年级1班","leader":"赵老师","students":[{"name":"张三","sex":"女"}]},{"grade":"八年级1班","leader":"赵老师","students":[{"name":"李四","sex":"女"}]},{"grade":"八年级1班","leader":"赵老师","students":[{"name":"王五","sex":"女"}]}]


http://www.niftyadmin.cn/n/5218571.html

相关文章

删除巨大文本文件的最后一行

用truncate去年最后的字节数。 export file"abc.json"tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}mac上面truncate需要安装一下。 参考&#xff1a; Remove the last line from a file in Bash - Stack Overflow

介绍比特币上的 sCrypt 开发平台

最强大的基础设施和工具套件&#xff0c;可轻松构建和扩展您的 dApp 杀手级应用在哪里&#xff1f; 尽管比特币在小额支付、国际汇款和供应链管理等广泛用例中具有颠覆性潜力&#xff0c;但在推出 14 年后&#xff0c;我们还没有看到一款非常受欢迎并被主流采用的杀手级应用。 …

2023.11.25电商项目平台建设2 -四大业务之核销主题建模

1.数仓建模步骤 自下而上 ADS-DWS-DWM-DWD 2.DWD方案(清洗转换,降维拉宽) DWD层的表 dwd_sale_store_sale_dtl_i 门店销售明细宽表 维度dim 销售sale合成成的宽表 dwd_dim_date_f 日期表 store_sale_dtl 门店销售明细表 dwd_sale_store_sale_dtl_i 门店销售明细表 …

网关知识总结

网关&#xff08;Gateway&#xff09;是一种网络设备或软件&#xff0c;用于连接两个不同的网络或协议&#xff0c;并能够在这两个网络或协议之间进行数据交换。网关是网络体系结构中的重要组成部分&#xff0c;它可以使不同的网络或协议相互通信&#xff0c;实现数据的传输和处…

谈谈中间件设计的思路

前言 想要设计和真正理解中间件的架构理论和思想。对于开发来说需要具备三个关键的能力 1&#xff1a;基础通用技术的深入理解和运用2&#xff1a;了解和熟悉常见中间件的设计思想&#xff0c;且有自己的感悟,并且能按照自己的理解模仿写一写3&#xff1a;业务的高度理解能力…

二叉树进阶OJ题

目录 一、前序遍历非递归 二、中序遍历非递归 三、后序遍历非递归 四、二叉树转链表 五、二叉树的最近公共祖先 六、二叉树的层序遍历1 七、二叉树的层序遍历2 一、前序遍历非递归 题目描述&#xff1a;写出二叉树前序遍历的非递归形式。 链接&#xff1a;前序遍历 思…

CF 1900A Cover in Water 学习笔记

原题链接 传送门 题意 给定多个细胞&#xff0c;细胞有两种情况&#xff0c;一种情况是空的&#xff0c;另一种情况是阻塞的&#xff0c;可以往空的细胞里面装水&#xff0c;可以把装水细胞里面的水转移到另一个细胞里面&#xff0c;阻塞的细胞不能进行任何操作&#xff0c;…

AI和人工智能与机器学习全景报告

今天分享的是AI系列深度研究报告&#xff1a;《AI和人工智能与机器学习全景报告》。 &#xff08;报告出品方&#xff1a;appen&#xff09; 报告共计&#xff1a;30页 获取 数据获取仍是AI应用构建团队的主要瓶颈。 原因各不相同。例如&#xff0c;特定用例的数据可能不足…