之前工作中需要接触到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();
}
}
}
如果有什么不理解的地方,欢迎私信,多相互交流,学习促进