Java实现集合和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":"女"}]}]
相关推荐
激流丶15 分钟前
【Kafka 实战】如何解决Kafka Topic数量过多带来的性能问题?
java·大数据·kafka·topic
神奇夜光杯17 分钟前
Python酷库之旅-第三方库Pandas(202)
开发语言·人工智能·python·excel·pandas·标准库及第三方库·学习与成长
Themberfue19 分钟前
Java多线程详解⑤(全程干货!!!)线程安全问题 || 锁 || synchronized
java·开发语言·线程·多线程·synchronized·
让学习成为一种生活方式36 分钟前
R包下载太慢安装中止的解决策略-R语言003
java·数据库·r语言
晨曦_子画41 分钟前
编程语言之战:AI 之后的 Kotlin 与 Java
android·java·开发语言·人工智能·kotlin
南宫生1 小时前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
小c君tt1 小时前
MFC中Excel的导入以及使用步骤
c++·excel·mfc
Heavydrink1 小时前
HTTP动词与状态码
java
ktkiko111 小时前
Java中的远程方法调用——RPC详解
java·开发语言·rpc
计算机-秋大田2 小时前
基于Spring Boot的船舶监造系统的设计与实现,LW+源码+讲解
java·论文阅读·spring boot·后端·vue