1、引入依赖
org.apache.poi
poi
4.0.1
org.apache.poi
poi-ooxml
4.0.1
com.monitorjbl
xlsx-streamer
2.1.0
2、编写ExcelDataDO类
@Data
public class ExcelDataDO {
public Class clazz;
public ExcelData(Class clazz) {
this.clazz = clazz;
}
public String sheetName;
public List data;
}
3、编写自动封装@ExcelField注解类
@Retention(RetentionPolicy.RUNTIME)
@Target({java.lang.annotation.ElementType.FIELD})
public @interface ExcelField {
/**
* 导出到Excel中的名字.
*/
public abstract String name();
/**
* 配置列的名称,对应A,B,C,D....
*/
public abstract String column();
/**
* 必填项
*/
public abstract boolean required() default false;
/**
* 校验规则(正则)
*/
public abstract String regex() default "";
/**
* 是否导出数据
*/
public abstract boolean isExport() default true;
}
4、编写自动封装ExcelBridge实体类
@Data
public class ExcelBridgeDO{
/**
* 项目序号
*/
@ExcelField(name = "序号", column = "A", required = true)
private String projectNumber;
/**
* 地市名称
*/
@ExcelField(name = "地市名称", column = "B", required = true)
private String cityName;
/**
* 路线名称
*/
@ExcelField(name = "路线名称", column = "C", required = true)
private String roadName;
/**
* 项目类型
*/
@ExcelField(name = "工程项目", column = "D", required = true)
private String projectType;
/**
* 工程所在地区间桩号
*/
@ExcelField(name = "工程所在地区间桩号", column = "E", required = true)
private String sectionNo;
/**
* 建设性质
*/
@ExcelField(name = "建设性质", column = "F", required = true)
private String buildNature;
/**
* 技术标准结构
*/
@ExcelField(name = "技术标准结构", column = "G", required = true)
private String buildStructure;
/**
* 单位
*/
@ExcelField(name = "单位", column = "H", required = true)
private String projectUnit;
/**
* 数量
*/
@ExcelField(name = "数量", column = "I", required = true)
private String projectNum;
/**
* 座
*/
@ExcelField(name = "座", column = "J", required = true)
private String zuo;
/**
* 总投资金额
*/
@ExcelField(name = "总投资金额", column = "K", required = true)
private BigDecimal projectTotalMoney;
/**
* 部投资金额
*/
@ExcelField(name = "部投资金额", column = "L", required = true)
private BigDecimal countyOutMoney;
/**
* 省投资金额
*/
@ExcelField(name = "省投资金额", column = "M", required = true)
private BigDecimal provinceOutMoney;
/**
* 备注
*/
@ExcelField(name = "备注", column = "R", required = true)
private String remark;
}
5、编写ExcelUtil类
/**
* Excel 工具类.
*/
@SuppressWarnings("all")
public class ExcelUtil {
public Class clazz;
boolean v2007 = true;
public ExcelUtil(Class clazz) {
this.clazz = clazz;
}
public Workbook getWorkbook(InputStream in, boolean v2007) throws Exception {
Workbook workbook = null;
this.v2007 = v2007;
if (v2007) {
workbook = StreamingReader.builder().rowCacheSize(100).bufferSize(4096).open(in);
} else {
workbook = new HSSFWorkbook(in);
}
return workbook;
}
public boolean validity(Workbook workbook) throws Exception {
Sheet sheet = workbook.getSheetAt(0);
List allFields = getMappedFiled(clazz, null);
if (sheet.getLastRowNum() <= 0) {
return false;
}
Row topRow = null;
boolean flag = false;
for (Row row : sheet) {
if (flag) {
break;
}
topRow = row;
flag = true;
}
int colNum = 0;
for (Field field : allFields) {
if (field.isAnnotationPresent(ExcelField.class)) {
ExcelField attr = field.getAnnotation(ExcelField.class);
if (topRow.getCell(colNum) == null) {
return false;
} else {
String headName = topRow.getCell(colNum).getStringCellValue();
if (!headName.equals(attr.name())) {
return false;
}
}
colNum++;
}
}
return true;
}
public List> getList(Workbook workbook, int headRow) throws Exception {
List> result = new ArrayList>();
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
Sheet sheet = workbook.getSheetAt(i);
ExcelDataDO exceData = new ExcelDataDO(clazz);
List list = getList(sheet, headRow);
exceData.setSheetName(sheet.getSheetName());
exceData.setData(list);
result.add(exceData);
}
return result;
}
public List> getList(Workbook workbook, int sheetIndex, int headRow) throws Exception {
List> result = new ArrayList>();
Sheet sheet = workbook.getSheetAt(sheetIndex);
ExcelDataDO exceData = new ExcelDataDO(clazz);
List list = getList(sheet, headRow);
exceData.setSheetName(sheet.getSheetName());
exceData.setData(list);
result.add(exceData);
return result;
}
public List getList(Sheet sheet, int headRow) throws Exception {
List list = new ArrayList<>();
int maxCol = 0;
List allFields = getMappedFiled(clazz, null);
Map fieldsMap = new HashMap<>();
for (Field field : allFields) {
if (field.isAnnotationPresent(ExcelField.class)) {
ExcelField attr = field.getAnnotation(ExcelField.class);
int col = getExcelCol(attr.column());
maxCol = Math.max(col, maxCol);
field.setAccessible(true);
fieldsMap.put(col, field);
}
}
int index = 0;
boolean flag = false;
for (Row row : sheet) {
int cellNum = maxCol;
index = index + 1;
if (index <= headRow) {
continue;
}
if (row.getCell(0).getStringCellValue().equals("1") || flag) {
flag = true;
} else {
continue;
}
T entity = null;
for (int j = 0; j <= cellNum; j++) {
Cell cell = row.getCell(j);
if (cell == null) {
continue;
}
if (!v2007) {
cell.setCellType(CellType.STRING);
}
String c = cell.getStringCellValue();
if (c == null || c.equals("")) {
continue;
}
entity = (entity == null ? clazz.newInstance() : entity);
Field field = fieldsMap.get(j);
if (field == null) {
continue;
}
Class fieldType = field.getType();
if (String.class == fieldType) {
field.set(entity, String.valueOf(c));
} else if ((Integer.TYPE == fieldType)
|| (Integer.class == fieldType)) {
field.set(entity, Integer.parseInt(c));
} else if ((Long.TYPE == fieldType)
|| (Long.class == fieldType)) {
field.set(entity, Long.valueOf(c));
} else if ((Float.TYPE == fieldType)
|| (Float.class == fieldType)) {
field.set(entity, Float.valueOf(c));
} else if ((Short.TYPE == fieldType)
|| (Short.class == fieldType)) {
field.set(entity, Short.valueOf(c));
} else if ((Double.TYPE == fieldType)
|| (Double.class == fieldType)) {
field.set(entity, Double.valueOf(c));
} else if ((BigDecimal.class == fieldType)
|| (BigDecimal.class == fieldType)) {
c = c.replaceAll("\\\\(.*?\\\\)", "");
field.set(entity, new BigDecimal(c));
} else if (Character.TYPE == fieldType) {
if ((c != null) && (c.length() > 0)) {
field.set(entity, Character.valueOf(c.charAt(0)));
}
}
}
if (entity != null) {
list.add(entity);
}
if (!flag) {
throw new Exception("未找到有效数据.");
}
}
return list;
}
public int getExcelCol(String col) {
col = col.toUpperCase();
int count = -1;
char[] cs = col.toCharArray();
for (int i = 0; i < cs.length; i++) {
count += (cs[i] - 64) * Math.pow(26, cs.length - 1 - i);
}
return count;
}
private List getMappedFiled(Class clazz, List fields) {
if (fields == null) {
fields = new ArrayList<>();
}
Field[] allFields = clazz.getDeclaredFields();
for (Field field : allFields) {
if (field.isAnnotationPresent(ExcelField.class)) {
fields.add(field);
}
}
if (clazz.getSuperclass() != null && !clazz.getSuperclass().equals(Object.class)) {
getMappedFiled(clazz.getSuperclass(), fields);
}
return fields;
}
private boolean notEmpty(Object object) {
if (object == null || String.valueOf(object).trim().equals("")) {
return false;
}
return true;
}
private boolean match(String regex, String str) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
return matcher.matches();
}
}
6、测试代码
本地测试
public static void main(String agrs[]) throws Exception {
ExcelUtil excelUtil = new ExcelUtil(ExcelBridgeDO.class);
File file = new File("D:\\traffic-project-new\\开发文档\\2020-危桥改造计划-录入表总.xlsx");
FileInputStream inv = new FileInputStream(file);
Workbook workbook = excelUtil.getWorkbook(inv, "XLSX".equals("XLSX"));
List> list = excelUtil.getList(workbook, 1, 8);
}
接口测试
@RequestMapping(value = "/upload")
public R upload(@RequestParam("file") MultipartFile file) {
ExcelUtil excelUtil = new ExcelUtil(ExcelBridgeDO.class);
InputStream inputStream = file.getInputStream();
Workbook workbook = excelUtil.getWorkbook(inputStream, suffix.toUpperCase().equals("XLSX"));
List> excelDataList = excelUtil.getList(workbook, 1, 8);
return R.ok();
}