java处理上传上来的xlsx,和xls是非常常见的操作,批量导入
需要的maven包
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.0.1</version>
</dependency>
比如有一个这样的excel
创建一个注解类
import java.lang.annotation.*;
/**
* @ms 用于标记导入的excel的字段
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcelTitleName {
/**
* excel表中的标题
*
* @return
*/
public String name();
}
注意:注解上的注解不做过多赘述,可网上找描述会很清楚
创建一个实体类并在字段上加上刚才创建的注解
public class User {
@ExcelTitleName(name = "姓名")
private String name;
@ExcelTitleName(name = "年龄")
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
工具类
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
public class ImportExcelTest {
/**
* 读取excel
*
* @param path
*/
public <T> List<T> readXlsx(String path, Class<T> tClass) {
List<T> list = new ArrayList<>();
FileInputStream is = null;
Workbook xwb = null;
try {
// 读取的时候可以使用流,也可以直接使用文件名
is = new FileInputStream(path);
xwb = new XSSFWorkbook(is);
//第一个工作表(可以循环工作表这里就不举例为第一个工作表)
Sheet sheet = xwb.getSheetAt(0);
//标题
Row title = sheet.getRow(0);
// 循环row,如果第一行是标题,则 numRow = 1
for (int numRow = 1; numRow <= sheet.getLastRowNum(); numRow++) {
Row row = sheet.getRow(numRow);
if (row == null) {
continue;
}
//创建实体类
T t = tClass.newInstance();
// 循环cell
for (int numCell = 0; numCell < row.getLastCellNum(); numCell++) {
//标题
Cell titleCell = title.getCell(numCell);
// 打印数据
System.out.println("xlsx标题" + getValue(titleCell));
Cell cell = row.getCell(numCell);
if (cell == null) {
continue;
}
System.out.println("xlsx单元格:" + getValue(cell));
assignmentSave(getValue(titleCell), getValue(cell), t);
}
list.add(t);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
if (xwb != null) {
xwb.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return list;
}
/**
* 解析excel单元格类型
*
* @param cell
* @return
*/
private String getValue(Cell cell) {
String val = null;
if (null != cell) {
switch (cell.getCellType()) {
//布尔类型
case BOOLEAN:
val = String.valueOf(cell.getBooleanCellValue());
break;
// 字符串类型
case STRING:
val = cell.getStringCellValue().trim();
break;
// 数值类型
case NUMERIC:
// 日期格式
if (DateUtil.isCellDateFormatted(cell)) {
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
val = f.format(cell.getDateCellValue());
} else {
// 四舍五入
val = new DecimalFormat("#.####").format(cell.getNumericCellValue());
}
break;
//其它类型
default:
break;
}
}
return val;
}
/**
* 通过注解赋值给变量
*
* @param t
* @param titleName
* @param val
*/
private <T> void assignmentSave(String titleName, String val, T t) {
try {
Field[] at = t.getClass().getDeclaredFields();
for (Field fd : at) {
// 变量是否包含ExcelTitleName注解
if (fd.isAnnotationPresent(ExcelTitleName.class)) {
// 获取注解属性
ExcelTitleName d = fd.getAnnotation(ExcelTitleName.class);
//注解匹配成功给变量赋值
if (d.name().equals(titleName)) {
// 首字母大写
String replace = fd.getName().substring(0, 1).toUpperCase() + fd.getName().substring(1);
Method method = t.getClass().getMethod("set" + replace, String.class);
method.invoke(t, val);
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
List<User> users = new ImportExcelTest().readXlsx("C:\\Users\\Desktop\\ImportExcelTest.xlsx", User.class);
users.forEach(user -> System.out.println(user.toString()));
}
}
工具类原理:根据反射获取实体类参数,判断参数上的注解比对注解,通过反射赋值。
结果: