import cn.com.rydeen.base.utils.data.JsonUtils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class ExcelUtils {
public static <T> List<T> readExcelData(ByteArrayInputStream inputStream, int sheetNo, int headRowNumber, Class<T> clazz) {
List<T> dataList = new ArrayList<>();
EasyExcel.read(inputStream, clazz, new AnalysisEventListener<T>() {
@Override
public void invoke(T data, AnalysisContext context) {
dataList.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
log.info("doAfterAllAnalysed done");
}
}).sheet(sheetNo)
.headRowNumber(headRowNumber)
.doRead();
log.info("dataList: {}", JsonUtils.getInstance().serialize(dataList));
return dataList;
}
public static <T> List<T> readExcelDataWithOutEmptyLine(ByteArrayInputStream inputStream, int sheetNo, int headRowNumber, Class<T> clazz) throws IOException {
List<T> dataList = new ArrayList<>();
Workbook workbook = new XSSFWorkbook(inputStream);
Sheet sheet = workbook.getSheetAt(sheetNo);
Field[] fields = clazz.getDeclaredFields();
for (int i = headRowNumber; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null || isRowEmpty(row)) {
continue;
}
try {
T instance = clazz.getDeclaredConstructor().newInstance();
for (Field field : fields) {
field.setAccessible(true);
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
if (excelProperty != null) {
int columnIndex = excelProperty.index();
Cell cell = row.getCell(columnIndex);
if (cell == null || cell.getCellType() == CellType.BLANK) {
cell = getMergedRegionValue(row.getRowNum(), columnIndex, sheet);
}
setFieldValue(instance, field, cell);
}
}
dataList.add(instance);
} catch (Exception e) {
e.printStackTrace();
}
}
workbook.close();
return dataList;
}
private static boolean isRowEmpty(Row row) {
for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
Cell cell = row.getCell(i);
if (cell != null && cell.getCellType() != CellType.BLANK) {
return false;
}
}
return true;
}
private static Cell getMergedRegionValue(int row, int column, Sheet sheet) {
for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
CellRangeAddress range = sheet.getMergedRegion(i);
if (range.isInRange(row, column)) {
Row firstRow = sheet.getRow(range.getFirstRow());
return firstRow.getCell(range.getFirstColumn());
}
}
return null;
}
private static void setFieldValue(Object instance, Field field, Cell cell) throws IllegalAccessException {
if (cell != null) {
DecimalFormat df = new DecimalFormat("#.##########");
switch (cell.getCellType()) {
case STRING:
field.set(instance, cell.getStringCellValue());
break;
case NUMERIC:
String numericValue = df.format(cell.getNumericCellValue());
field.set(instance, numericValue);
break;
case BOOLEAN:
field.set(instance, String.valueOf(cell.getBooleanCellValue()));
break;
case FORMULA:
switch (cell.getCachedFormulaResultType()) {
case NUMERIC:
String formulaNumericValue = df.format(cell.getNumericCellValue());
field.set(instance, formulaNumericValue);
break;
case STRING:
field.set(instance, cell.getStringCellValue());
break;
default:
break;
}
break;
default:
break;
}
}
}
}
- readExcelData 方法
功能: 读取 Excel 文件中的数据,返回一个列表。
参数:
inputStream: 输入流,通常用于从内存中读取数据。
sheetNo: 要读取的工作表编号。
headRowNumber: 表头所在的行号。
clazz: 泛型参数,代表实体类的类型。
返回值: 包含读取数据的列表。
实现:
使用 EasyExcel 的 read 方法读取数据。
通过 AnalysisEventListener 监听器收集每行数据。
将数据添加到列表中并返回。 - readExcelDataWithOutEmptyLine 方法
功能: 读取 Excel 文件中的数据,处理合并单元格,并过滤掉所有列为空的行。
参数:
同 readExcelData 方法。
返回值: 包含读取数据的列表。
实现:
打开 Excel 文件并获取指定工作表。
遍历每一行数据。
跳过所有列为空的行。
对于每个非空行,创建实体类实例,并设置属性值。
设置属性值时考虑合并单元格的情况。
将有效数据添加到列表中并返回。