使用自定义注解和反射操作apache POI实现多表头和动态导出

之前工作中需要接触到apache POI进行导入导出,在网上找了一圈没有详细的,对于poi的动态导出,这样就无需创建多个实体类,动态控制需要导出导入的字段。后面自己业余时间写了一点,但因为自己本身技术不大够,没有完整写完。如果有大佬可以完整写完,还请私信我相互讨论交流。这篇文章对于使用到apache POI的朋友应该会有所帮助。

注解

写自定义注解,首先要了解到元注解:
 

@Target注解

描述注解的使用范围(被修饰的注解可以用在什么地方) 。

它的取值范围定义在ElementType 枚举中:

public enum ElementType {
 
    TYPE, // 类、接口、枚举类
 
    FIELD, // 成员变量(包括:枚举常量)
 
    METHOD, // 成员方法
 
    PARAMETER, // 方法参数
 
    CONSTRUCTOR, // 构造方法
 
    LOCAL_VARIABLE, // 局部变量
 
    ANNOTATION_TYPE, // 注解类
 
    PACKAGE, // 可用于修饰:包
 
    TYPE_PARAMETER, // 类型参数,JDK 1.8 新增
 
    TYPE_USE // 使用类型的任何地方,JDK 1.8 新增
 
}

@Retention注解

描述注解保留的时间范围(被描述的注解在它所修饰的类中可以被保留到何时) 。

它的取值范围定义在RetentionPolicy枚举中:

public enum RetentionPolicy {
 
    SOURCE,    // 源文件保留
    CLASS,       // 编译期保留,默认值
    RUNTIME   // 运行期保留,可通过反射去获取注解信息
}

@Documented注解

描述在使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息。

@Inherited注解

使被它修饰的注解具有继承性(如果某个类使用了被@Inherited修饰的注解,则其子类将自动具有该注解)。

Lombok:

  • @Setter 注解在类或字段,注解在类时为所有字段生成setter方法,注解在字段上时只为该字段生成setter方法。
  • @Getter 使用方法同上,区别在于生成的是getter方法。
  • @ToString 注解在类,添加toString方法。
  • @EqualsAndHashCode 注解在类,生成hashCode和equals方法。
  • @NoArgsConstructor 注解在类,生成无参的构造方法。
  • @RequiredArgsConstructor 注解在类,为类中需要特殊处理的字段生成构造方法,比如final和被@NonNull注解的字段。
  • @AllArgsConstructor 注解在类,生成包含类中所有字段的构造方法。
  • @Data 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。
  • @SneakyThrows 用于简化在方法中抛出受检异常(checked exception)的处理
  • @Slf4j 注解在类,生成log变量,严格意义来说是常量。private static final Logger log = LoggerFactory.getLogger(UserController.class);用于简化在方法中抛出受检异常(checked exception)的处理

首先进行依赖导入(大体上我会引入到这些依赖,可能有些冗余):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>ApachePoiExportStu</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>provided</scope>
        </dependency>

        <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>

        <!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
            <version>2.0.41</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>

    </dependencies>
</project>

写入自定义注解:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Excel注解集
 *
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Excels
{
    Excel[] value();
}
import java.lang.annotation.*;

/**
 * 自定义导出Excel数据注解
 *
 * @author luotai
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel {

    /**
     * 日期格式, 如: yyyy-MM-dd
     */
    String dateFormat() default "";

    /**
     * 数值映射处理 (如: 0-男,1-女)
     */
    String convertValue() default "";

    /**
     * BigDecimal、double保留小数位,默认2位
     */
    int scale() default 2;

    /**
     * 设置导出数据的次序,下标从0开始
     */
    int order() default -1;

    /**
     * 对导出的数据追加后缀文本
     */
    String suffix() default "";

    /**
     * 导出字段对齐方式(0:默认;1:靠左;2:居中;3:靠右)
     */
    int align() default 0;

    /**
     * 导出表头名字.
     */
    String value() default "";

    /**
     * 另一个类中的属性名称,支持多级获取,以小数点隔开
     */
    String targetAttr() default "";

    /**
     * 字段类型(0:导出导入;1:仅导出;2:仅导入)
     */
    Type type() default Type.ALL;

    /**
     * 是否包含子集
     */
    boolean isSubsets() default false;

    /**
     * 父集字段名
     */
    String supersetName() default "";

    enum Type {
        ALL(0), EXPORT(1), IMPORT(2), CONDITION(3);
        private final int value;

        Type(int value) {
            this.value = value;
        }

        public int value() {
            return this.value;
        }
    }
}

实体类(差不多数据类型我都用到了):

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;

/**
 * 学生实体类
 * @date 2024-07-08 22:11
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {


    /**
     * 序号
     */
    @Excel(order = 0, value = "序号")
    private Long id;

    /**
     * 所属模块
     */
    @Excel(order = 1, value = "所属模块")
    private String model;

    /**
     * 单位名称
     */
    @Excel(order = 2, value = "单位名称")
    private String unitName;

    /**
     * 情况统计
     */
    @Excel(order = 3, value = "情况统计")
    private String situationStatistics;

    /**
     * 合计
     */
    @Excels({
            @Excel(value = "餐费", targetAttr = "tableMoney", order = 4),
            @Excel(value = "学费", targetAttr = "tuitionFee", order = 5),
            @Excel(value = "学杂费", targetAttr = "miscellaneousFees", order = 6)
    })
    @Excel(order = 4, value = "合计")
    private Cost total;

    /**
     * 学校
     */
    @Excel(value = "学校")
    private Map<Integer, String> school;

    /**
     * 班级
     */
    @Excel(value = "班级", isSubsets = true, order = 7)
    private String classes;

    /**
     * 学号
     */
    @Excel(value = "学号", order = 0, supersetName = "classes")
    private Long pkId;

    /**
     * 姓名
     */
    @Excel(value = "姓名", order = 3, supersetName = "classes")
    private String name;

    /**
     * 入学时间
     */
    @Excel(value = "入学时间", dateFormat = "yyyy-MM-dd HH:mm:ss", order = 2, supersetName = "classes")
    private Date joinTime;

    /**
     * 入学日期
     */
    @Excel(value = "入学日期", dateFormat = "yyyy-MM-dd", order = 1, supersetName = "classes")
    private LocalDateTime joinDate;

    /**
     * 是否
     */
    @Excel(value = "是否", type = Excel.Type.IMPORT)
    private Boolean tag;

    @SneakyThrows
    public String get(Integer order) {
        Field[] declaredFields = Student.class.getDeclaredFields();
        Class<Excels> excelsClass = Excels.class;
        Class<Excel> excelClass = Excel.class;

        //遍历Student实体类中所有字段
        for (Field declaredField : declaredFields) {
            //检查字段是否有@Excels注解      多注解字段
            if (declaredField.isAnnotationPresent(excelsClass)) {
                Excels annotation = declaredField.getAnnotation(excelsClass);
                Excel[] excels = annotation.value();
                for (Excel excel : excels) {
                    // 检查注解中的order是否与传入的order匹配
                    if (excel.order() == order) {
                        // 这里o是Cost对象,我们需要获取Cost对象中相应字段的值
                        Object value = declaredField.get(this);
                        if (value != null) {
                            // 通过反射获取嵌套字段的值
                            try {
                                // 获取字段名
                                String targetAttr = excel.targetAttr();
                                //  通过字段名获取到该字段
                                Field targetField = value.getClass().getDeclaredField(targetAttr);
                                // 设置字段访问权限,使得可以访问私有字段
                                targetField.setAccessible(true);
                                // 格式化日期类型的字段
                                if (value instanceof Date && !excel.dateFormat().isEmpty()) {
                                    SimpleDateFormat sdf = new SimpleDateFormat(excel.dateFormat());
                                    return sdf.format(value);
                                }
                                // 格式化BigDecimal类型的字段
                                if (value instanceof BigDecimal && excel.scale() > 0) {
                                    return ((BigDecimal) value).setScale(excel.scale(), RoundingMode.HALF_UP).toString();
                                }
                                // 返回字段的值
                                return String.valueOf(targetField.get(value));
                            } catch (NoSuchFieldException | IllegalAccessException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                //单注解字段
            } else {
                //检查字段是否有@Excel注解
                if (declaredField.isAnnotationPresent(excelClass)) {
                    Excel excel = declaredField.getAnnotation(excelClass);
                    // 检查注解中的order是否与传入的order匹配
                    if (excel.order() == order) {
                        // 设置字段访问权限,使得可以访问私有字段
                        declaredField.setAccessible(true);
                        Object value = declaredField.get(this);
                        // 格式化日期类型的字段
                        if (value instanceof Date && !excel.dateFormat().isEmpty()) {
                            SimpleDateFormat sdf = new SimpleDateFormat(excel.dateFormat());
                            return sdf.format(value);
                        }
                        // 格式化BigDecimal类型的字段
                        if (value instanceof BigDecimal && excel.scale() > 0) {
                            return ((BigDecimal) value).setScale(excel.scale(), RoundingMode.HALF_UP).toString();
                        }
                        // 返回字段的值
                        return String.valueOf(value);
                    }
                }
            }
        }
        return null;
    }
}

合计实体类:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;

/**
 * 合计实体类
 * @Date: 2024/07/10 14:18
 */

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Cost {
    public Long id;

    /**
     *  餐费
     */
    public BigDecimal tableMoney;

    /**
     *  学费
     */
    public BigDecimal tuitionFee;

    /**
     *  学杂费
     */
    public BigDecimal miscellaneousFees;

}

导出功能实现,也可以自己封装成工具类来用,反正是自己平时学习,写的有点乱,看看得了:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

public class POIExportdemo {

    private static final String EMPTY = "";
    /**
     * 实体对象
     */
    public static Class<Student> clazz;
    /**
     * 导出类型(EXPORT:导出数据;IMPORT:导入模板)
     */
    private static Excel.Type type;

    // Excel数据导出
    public static void main(String[] args) throws NoSuchFieldException {
        // Excel2003版本(包含2003)以前使用HSSFWorkbook类,扩展名为.xls
        String suffixXls = ".xls";
        // Excel2007版本(包含2007)以后使用XSSFWorkbook类,扩展名为.xlsx
        String suffixXlsx = ".xlsx";

        // 数据源
        List<Student> shujuku = shujuku();

        // 创建工作簿类
        XSSFWorkbook workbook = new XSSFWorkbook();
        // 创建工作表并设置表名
        XSSFSheet sheet = workbook.createSheet("学生信息");
        //  合并单元格
        extracted(sheet);
        //  设置样式以及字体样式
        XSSFCellStyle headCellStyle = createHeadCellStyle(workbook);

        int rowNum = 0;

        //创建第一页的第一行,索引从0开始
        XSSFRow row0 = sheet.createRow(rowNum++);
        //设置行高
        row0.setHeight((short) 600);
        sheet.setColumnWidth(2, 8000);
        sheet.setColumnWidth(3, 8000);

        //第二行
        XSSFRow row2 = sheet.createRow(rowNum++);
        row2.setHeight((short) 700);

        //第三行
        XSSFRow row3 = sheet.createRow(rowNum);
        row3.setHeight((short) 700);

        //通过反射获取 id 的字段,再获取 Excel 的注解中方法value的值: 序号
        String id = Student.class.getDeclaredField("id").getAnnotation(Excel.class).value();

        String[] rowOne = new String[]{id, "所属模块", "单位名称", "情况统计", "合计", "", "",
                "毛坦厂中学", "", "", "", "", "", "", "", "", "", "", "",
                "黄冈中学", "", "", "", "", "", "", "", "", "", "", "",};

        Map<String, String> fields = new HashMap<>();
        List<Field> tempFields = new ArrayList<>();

        //添加当前类的父类的所有声明字段
        tempFields.addAll(Arrays.asList(Student.class.getSuperclass().getDeclaredFields()));
        //添加当前类中声明的所有字段
        tempFields.addAll(Arrays.asList(Student.class.getDeclaredFields()));

        for (Field field : tempFields) {
            if (field.isAnnotationPresent(Excels.class)) {
                Excels attrs = field.getAnnotation(Excels.class);
                Excel[] excels = attrs.value();
                for (Excel attr : excels) {
                    //非空校验  且不为 CONDITION   类型
                    if (attr != null && (attr.type() == Excel.Type.ALL || attr.type() == type)) {
                        //通过反射绕过访问权限检查,从而访问和修改私有字段的值
                        field.setAccessible(true);
                        fields.put(attr.targetAttr(), attr.value());
                    }
                }
            }
        }

        List<String> rowTwoList = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            rowTwoList.add(EMPTY);
        }
        rowTwoList.add(fields.get("tableMoney"));
        rowTwoList.add(fields.get("tuitionFee"));
        rowTwoList.add(fields.get("miscellaneousFees"));

        //  获取所有的班级 并进行去重
        List<String> classList = shujuku.stream().map(Student::getClasses).distinct().collect(Collectors.toList());
        // 每个班级元素后添加三个空字符串
        List<String> modifiedList = classList.stream()
                .flatMap(className -> Arrays.asList(className, "", "", "").stream())
                .collect(Collectors.toList());
        rowTwoList.addAll(modifiedList);
        String[] rowTwo = rowTwoList.toArray(new String[0]);

//        String[] rowTwo = new String[]{"", "", "", "", "餐费", "学费", "学杂费",
//                "班级A1", "", "", "",
//                "班级A2", "", "", "",
//                "班级A3", "", "", "",
//                "班级B1", "", "", "",
//                "班级B2", "", "", "",
//                "班级B3", "", "", ""};


        String[] rowThree = new String[]{"", "", "", "", "", "", "",
                "学号", "入学日期", "入学时间", "姓名",
                "学号", "入学日期", "入学时间", "姓名",
                "学号", "入学日期", "入学时间", "姓名",

                "学号", "入学日期", "入学时间", "姓名",
                "学号", "入学日期", "入学时间", "姓名",
                "学号", "入学日期", "入学时间", "姓名",};


        // 创建第一行单元格
        for (int i = 0; i < rowOne.length; i++) {
            XSSFCell c00 = row0.createCell(i);
            c00.setCellValue(rowOne[i]);
            c00.setCellStyle(headCellStyle);
        }
        // 创建第二行单元格
        for (int i = 0; i < rowTwo.length; i++) {
            XSSFCell tempCell = row2.createCell(i);
            tempCell.setCellValue(rowTwo[i]);
            tempCell.setCellStyle(headCellStyle);
        }
        // 创建第三行单元格
        for (int i = 0; i < rowThree.length; i++) {
            XSSFCell tempCell = row3.createCell(i);
            tempCell.setCellValue(rowThree[i]);
            tempCell.setCellStyle(headCellStyle);
        }
        Field[] fields1 = Student.class.getDeclaredFields();

        //标题和表头占用了前两行
        int i = 3;
        for (Student student : shujuku) {
            XSSFRow row = sheet.createRow(i++);






            for (int j = 0; j < 10; j++) {
                for (Field field : fields1) {
                    //判断字段上是否没有 @Excels 注解  单注解字段
                    if (!field.isAnnotationPresent(Excels.class)) {
                        //判断字段上是否有 @Excel 注解
                        if (field.isAnnotationPresent(Excel.class)) {

                            //判断字段上的@Excel注解是否不是IMPORT类型和CONDITION类型
                            if (field.getAnnotation(Excel.class).type() != Excel.Type.IMPORT && field.getAnnotation(Excel.class).type() != Excel.Type.CONDITION) {
                                if (field.getAnnotation(Excel.class).order() == j) {
                                    row.createCell(j).setCellValue(student.get(j));
                                }
                            }

                        }
                        //多注解字段
                    } else {
                        Excel[] value = field.getAnnotation(Excels.class).value();
                        for (Excel excel : value) {
                            if (excel.type() != Excel.Type.IMPORT && excel.type() != Excel.Type.CONDITION) {
                                if (excel.order() == j) {
                                    row.createCell(j).setCellValue( student.get(j));
                                }
                            }
                        }
                    }
                }
            }
        }

        // 设置表头单元格的宽度
        tableTitleStyleColumnwidth(sheet);

        // 设置Excel文件路径
        File file = new File("D:\\poi_demo" + UUID.randomUUID() + suffixXlsx);

        try {
            // 创建指向该路径的输出流
            FileOutputStream stream = new FileOutputStream(file);

            // 将数据导出到Excel表格
            workbook.write(stream);

            // 关闭输出流
            stream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取字段注解信息
     */
    public static List<Object[]> getFields() {
        List<Object[]> fields = new ArrayList<Object[]>();
        List<Field> tempFields = new ArrayList<>();
        //添加当前类的父类的所有声明字段
        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
        //添加当前类中声明的所有字段
        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        for (Field field : tempFields) {
            // 单注解  检查是否有 @Excel 注解
            if (field.isAnnotationPresent(Excel.class)) {
                Excel attr = field.getAnnotation(Excel.class);
                if (attr != null && (attr.type() == Excel.Type.ALL || attr.type() == type)) {
                    //通过反射绕过访问权限检查,从而访问和修改私有字段的值
                    field.setAccessible(true);
                    fields.add(new Object[]{field, attr});
                }
            }

            // 多注解  检查是否有 @Excels 注解
            if (field.isAnnotationPresent(Excels.class)) {
                Excels attrs = field.getAnnotation(Excels.class);
                Excel[] excels = attrs.value();
                for (Excel attr : excels) {
                    if (attr != null && (attr.type() == Excel.Type.ALL || attr.type() == type)) {
                        field.setAccessible(true);
                        fields.add(new Object[]{field, attr});
                    }
                }
            }
        }
        return fields;
    }


    /**
     * 设置表头单元格的宽度
     *
     * @Param @see XSSFSheet
     * @return:
     * @throws:
     * @Author: PZM
     * @Date: 2024/07/09
     **/
    private static void tableTitleStyleColumnwidth(XSSFSheet sheet) {

        sheet.setColumnWidth(2, 8000);
        sheet.setColumnWidth(3, 8000);
        for (int i = 7; i <= 30; i++) {
            sheet.setColumnWidth(i, 3000);
        }
    }

    /**
     * 合并单元格
     *
     * @Param @see XSSFSheet
     * @return:
     * @throws:
     * @Author: PZM
     * @Date: 2024/07/09
     **/
    private static void extracted(XSSFSheet sheet) {
        /*
          合并参数分别为: 起始行,结束行,起始列,结束列
         */
        // 将第一列 的 第一行到第三行合并
        sheet.addMergedRegion(new CellRangeAddress(0, 2, 0, 0));
        // 将第二列的 第一行到第三行合并
        sheet.addMergedRegion(new CellRangeAddress(0, 2, 1, 1));
        //  将第三列的 第一行到第三行合并
        sheet.addMergedRegion(new CellRangeAddress(0, 2, 2, 2));
        sheet.addMergedRegion(new CellRangeAddress(0, 2, 3, 3));

        // 合计
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 4, 6));
        // 合计下的单元格
        sheet.addMergedRegion(new CellRangeAddress(1, 2, 4, 4));
        sheet.addMergedRegion(new CellRangeAddress(1, 2, 5, 5));
        sheet.addMergedRegion(new CellRangeAddress(1, 2, 6, 6));


        sheet.addMergedRegion(new CellRangeAddress(0, 0, 7, 18));

        sheet.addMergedRegion(new CellRangeAddress(0, 0, 19, 30));


        sheet.addMergedRegion(new CellRangeAddress(1, 1, 7, 10));
        sheet.addMergedRegion(new CellRangeAddress(1, 1, 11, 14));
        sheet.addMergedRegion(new CellRangeAddress(1, 1, 15, 18));


        sheet.addMergedRegion(new CellRangeAddress(1, 1, 19, 22));
        sheet.addMergedRegion(new CellRangeAddress(1, 1, 23, 26));
        sheet.addMergedRegion(new CellRangeAddress(1, 1, 27, 30));
    }

    /**
     * 创建表头样式
     *
     * @param wb
     * @return XSSFCellStyle
     */
    private static XSSFCellStyle createHeadCellStyle(XSSFWorkbook wb) {
        XSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setWrapText(true);// 设置自动换行
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());//背景颜色:25%的灰色占比
        cellStyle.setAlignment(HorizontalAlignment.CENTER); //水平居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //垂直对齐
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);//将单元格的填充模式设置为实心填充

        //单元格边框设置
        cellStyle.setBottomBorderColor(IndexedColors.BLACK.index);//单元格底部边框的颜色
        cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
        cellStyle.setBorderLeft(BorderStyle.THIN); //左边框
        cellStyle.setBorderRight(BorderStyle.THIN); //右边框
        cellStyle.setBorderTop(BorderStyle.THIN); //上边框

        XSSFFont headerFont = wb.createFont(); // 创建字体样式
        headerFont.setBold(true); //字体加粗
        headerFont.setFontName("黑体"); // 设置字体类型
        headerFont.setFontHeightInPoints((short) 12); // 设置字体大小
        cellStyle.setFont(headerFont); // 为标题样式设置字体样式

        return cellStyle;
    }

    /**
     * 懒得建数据库,这方法就先加点数据
     *
     * @Param @see List<Student>
     * @return: @return {@link List }<{@link Student }>
     **/
    public static List<Student> shujuku() {
        Cost cost1 = new Cost();
        cost1.setId(1L);
        cost1.setTableMoney(BigDecimal.TEN);
        cost1.setTuitionFee(new BigDecimal("10"));
        cost1.setMiscellaneousFees(BigDecimal.ZERO);

        Cost cost2 = new Cost();
        cost2.setId(8L);
        cost2.setTableMoney(new BigDecimal("99.99"));
        cost2.setTuitionFee(new BigDecimal("35.96"));
        cost2.setMiscellaneousFees(new BigDecimal("556"));

        List<Student> studentList = new ArrayList<>();

        Student s1 = new Student();
        s1.setId(1L);
        s1.setModel("测试模块1");
        s1.setUnitName("测试单位1");
        s1.setSituationStatistics(null);
        s1.setSchool((Map<Integer, String>) new HashMap<>().put(1, "毛坦厂中学"));
        s1.setTotal(cost1);
        s1.setClasses("班级A1");
        s1.setPkId(10001L);
        s1.setJoinTime(new Date());
        s1.setJoinDate(LocalDateTime.now());
        s1.setTag(Boolean.TRUE);
        studentList.add(s1);

        Student s2 = new Student();
        s2.setId(2L);
        s2.setModel("测试模块2");
        s2.setUnitName("测试单位2");
        s2.setSituationStatistics(null);
        s2.setSchool((Map<Integer, String>) new HashMap<>().put(1, "毛坦厂中学"));
        s2.setTotal(cost2);
        s2.setClasses("班级A1");
        s2.setPkId(10002L);
        s2.setJoinTime(new Date());
        s2.setJoinDate(LocalDateTime.now());
        s2.setTag(true);
        studentList.add(s2);

        Student s3 = new Student();
        s3.setId(3L);
        s3.setModel("测试模块3");
        s3.setUnitName("测试单位3");
        s3.setSituationStatistics(null);
        s3.setSchool((Map<Integer, String>) new HashMap<>().put(1, "毛坦厂中学"));
        s3.setTotal(cost1);
        s3.setClasses("班级A2");
        s3.setPkId(10003L);
        s3.setJoinTime(new Date());
        s3.setJoinDate(LocalDateTime.now());
        s3.setTag(true);
        studentList.add(s3);

        Student s4 = new Student();
        s4.setId(4L);
        s4.setModel("测试模块4");
        s4.setUnitName("测试单位1");
        s4.setSituationStatistics(null);
        s4.setSchool((Map<Integer, String>) new HashMap<>().put(1, "毛坦厂中学"));
        s4.setTotal(cost2);
        s4.setClasses("班级A3");
        s4.setPkId(10004L);
        s4.setJoinTime(new Date());
        s4.setJoinDate(LocalDateTime.now());
        s4.setTag(true);
        studentList.add(s4);

        Student s5 = new Student();
        s5.setId(5L);
        s5.setModel("测试模块5");
        s5.setUnitName("测试单位5");
        s5.setSituationStatistics(null);
        s5.setSchool((Map<Integer, String>) new HashMap<>().put(1, "毛坦厂中学"));
        s5.setTotal(cost1);
        s5.setClasses("班级B1");
        s5.setPkId(10005L);
        s5.setJoinTime(new Date());
        s5.setJoinDate(LocalDateTime.now());
        s5.setTag(true);
        studentList.add(s5);

        Student s6 = new Student();
        s6.setId(6L);
        s6.setModel("测试模块6");
        s6.setUnitName("测试单位6");
        s6.setSituationStatistics(null);
        s6.setSchool((Map<Integer, String>) new HashMap<>().put(1, "黄冈中学"));
        s6.setTotal(cost1);
        s6.setClasses("班级B2");
        s6.setPkId(10006L);
        s6.setJoinTime(new Date());
        s6.setJoinDate(LocalDateTime.now());
        s6.setTag(true);
        studentList.add(s6);

        Student s7 = new Student();
        s7.setId(7L);
        s7.setModel("测试模块2");
        s7.setUnitName("测试单位5");
        s7.setSituationStatistics(null);
        s7.setSchool((Map<Integer, String>) new HashMap<>().put(1, "黄冈中学"));
        s7.setTotal(cost1);
        s7.setClasses("班级B2");
        s7.setPkId(10007L);
        s7.setJoinTime(new Date());
        s7.setJoinDate(LocalDateTime.now());
        s7.setTag(true);
        studentList.add(s7);

        Student s8 = new Student();
        s8.setId(8L);
        s8.setModel("测试模块6");
        s8.setUnitName("测试单位9");
        s8.setSituationStatistics(null);
        s8.setSchool((Map<Integer, String>) new HashMap<>().put(1, "黄冈中学"));
        s8.setTotal(cost2);
        s8.setClasses("班级B3");
        s8.setPkId(10008L);
        s8.setJoinTime(new Date());
        s8.setJoinDate(LocalDateTime.now());
        s8.setTag(true);
        studentList.add(s8);

        return studentList;
    }
}

 导出后的结果如下:

导入:

import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;

public class POIImportdemo {
    // Excel数据导出
    public static void main(String[] args) {
        // 创建文件并指定文件路径
        File file = new File("D:\\poi_demo.xlsx");

        try {
            // 创建改文件的输入流
            FileInputStream stream = new FileInputStream(file);

            // 创建工作簿
            XSSFWorkbook workbook = new XSSFWorkbook(stream);

            // 获取一个工作表,下标从0开始
            XSSFSheet sheet = workbook.getSheetAt(0);

            // 通过循环,逐行取出表中每行数据
            for (int i = 0; i <= sheet.getLastRowNum(); i++) {
                // 获取行
                XSSFRow row = sheet.getRow(i);

                // 获取行中列的数据
                String[] value = new String[4];

                value[0] = row.getCell(0).getStringCellValue();
                value[1] = row.getCell(1).getStringCellValue();
                value[2] = row.getCell(2).getStringCellValue();
                value[3] = row.getCell(3).getStringCellValue();

                for (String data : value) {
                    System.out.println(data);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

如果有什么不理解的地方,欢迎私信,多相互交流,学习促进

  • 19
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值