package cn.exlive.exbooter.excel;
import cn.hutool.core.util.ReflectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.builder.ExcelReaderSheetBuilder;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
*
* Created by zhenqin.
* User: zhenqin
* Date: 2025/2/13
* Time: 09:17
* Vendor: yiidata.com
*
*
*
* @author zhenqin
*/
@Slf4j
public abstract class ExcelImportFactory {
/**
* 返回表头
* @return
*/
public abstract Map getHeaderMap();
/**
* 返回数据
*
* @param processCallback 进度回调. 返回 0-100 之间的进度条
* @return
*/
public abstract List getData(ProcessCallback processCallback);
/**
* 获取 实例
* @param excelFile excel or csv 文件
* @param headerFieldMapping 文件头对应的映射
* @return
*/
public static ExcelImportFactory newInstance(File excelFile,
Map headerFieldMapping,
Class clazz) {
try (InputStream in = new FileInputStream(excelFile);) {
if (excelFile.getName().endsWith(".csv")) {
return new CsvFactory(in, headerFieldMapping);
}
return newInstance(in, headerFieldMapping, clazz);
} catch (IOException e) {
throw new IllegalStateException("文件无法读取", e);
}
}
/**
* 获取 实例
* @param in excel 文件
* @param headerFieldMapping 文件头对应的映射
* @return
*/
public static ExcelImportFactory newInstance(InputStream in,
Map headerFieldMapping,
Class clazz) {
ExcelFactory factory = new ExcelFactory(in, headerFieldMapping, clazz);
return factory;
}
/**
* Excel 数据导入
*/
static class ExcelFactory extends ExcelImportFactory {
/**
* 转换的目标 类型
*/
final Class clazz;
/**
* 表头
*/
final Map headerAndFieldMapping;
/**
* 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
*/
final OnceReadListener readListener;
public ExcelFactory(InputStream in, Map headerFieldMapping, Class clazz) {
this.clazz = clazz;
this.readListener = new OnceReadListener(headerFieldMapping);
// 这里直接赋值,OnceReadListener 中可能会修改字段
this.headerAndFieldMapping = headerFieldMapping;
final ExcelReaderSheetBuilder sheet = EasyExcel.read(in, readListener).sheet();
sheet.doRead();
}
/**
* 返回表头
* @return
*/
@Override
public Map getHeaderMap() {
return readListener.getHeadMap();
}
@Override
public List getData(ProcessCallback processCallback) {
final Map headMap = readListener.getHeadMap();
if(headMap == null) {
throw new IllegalStateException("无法读取 Excel 表头,非法的 Excel 表格。");
}
final Map headFieldMap = new HashMap<>();
for (Map.Entry entry : headMap.entrySet()) {
final String value = headerAndFieldMapping.get(StringUtils.trimToEmpty(entry.getValue()));
if(StringUtils.isBlank(value)) {
continue;
}
headFieldMap.put(entry.getKey(), value);
}
log.info("header: {}", headMap);
// 通过反射,获取 Bean 的字段和字段类型的映射,方便日期类型转换
Map objClassFields = new HashMap<>();
final Field[] fields = ReflectUtil.getFields(clazz);
for (Field field : fields) {
objClassFields.put(field.getName(), field);
}
ObjectMapper mapper = new ObjectMapper();
final List