欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java EasyExcel實(shí)現(xiàn)動(dòng)態(tài)列解析和存表

 更新時(shí)間:2023年06月15日 17:28:32   作者:我是一顆小虎牙_  
這篇文章主要為大家介紹了java EasyExcel實(shí)現(xiàn)動(dòng)態(tài)列解析和存表示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

背景

一個(gè)表中的數(shù)據(jù)來源于多個(gè)其他系統(tǒng)的導(dǎo)出表,其中的特點(diǎn)就是大多數(shù)的字段都是一樣的(可能導(dǎo)出的表頭不一樣),只有部分少數(shù)字段是每個(gè)系統(tǒng)自己獨(dú)有的。圍繞這個(gè)做一次功能性分析

分析:大多數(shù)字段是一樣的,那么就是實(shí)際的表字段,唯一的區(qū)別就是各系統(tǒng)內(nèi)的名字可能不一樣,少數(shù)每個(gè)系統(tǒng)獨(dú)有的字段,可以歸為動(dòng)態(tài)字段。

總結(jié):

  • 公共字段(翻譯表頭:@ExcelProperty 可以指定多個(gè)表頭( @ExcelProperty(value = {"發(fā)貨數(shù)量", "采購(gòu)數(shù)量(臺(tái))"}) ))
  • 動(dòng)態(tài)字段(需要有每個(gè)系統(tǒng)內(nèi)動(dòng)態(tài)字段的字段名稱和表頭的對(duì)應(yīng)關(guān)系,考慮使用字典,供業(yè)務(wù)員配置,后續(xù)如果新添加其他動(dòng)態(tài)字段直接在字典中配置,無需另行開發(fā))

注意:由于無法控制和預(yù)料固定字段在新接入的系統(tǒng)中的實(shí)際表頭,所以如果新接入系統(tǒng)的公共表頭與表字段不一致,需要在 @ExcelProperty(value = {}) 中添加新的表頭

效果

字典配置:

數(shù)據(jù)表結(jié)果:

公共字段使用常規(guī)的數(shù)據(jù)庫(kù)表字段存儲(chǔ),動(dòng)態(tài)字段使用額外列存 JSON 串。

代碼

引入pom坐標(biāo)

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.1.0</version>
</dependency>

創(chuàng)建實(shí)體類

public class AgentDeliverOrderImportVo {
    @ExcelProperty(value = {"訂單編號(hào)"}, order = 1)
    private String deliverNo;
    @ExcelProperty(value = {"發(fā)貨數(shù)量", "采購(gòu)數(shù)量(臺(tái))"}, order = 14)
    @ColumnName(name = {"發(fā)貨數(shù)量", "采購(gòu)數(shù)量(臺(tái))"})
    private Integer deliverCount;
    /**
     * 動(dòng)態(tài)字段(業(yè)務(wù)線編號(hào)區(qū)分)
     */
    private String dynamicFields;
    private Date createTime;
    private String createBy;
}
  • 因?yàn)榇嬖诓淮_定的列,所以只能使用 EasyExcel 的不創(chuàng)建對(duì)象的寫,那么
public String test(MultipartFile file) throws IOException {
    //假設(shè)從字典中獲取字典值
    Map<String, String> dictMap = new HashMap<>();
    dictMap.put("項(xiàng)目", "xm");
    dictMap.put("嗨一付訂單編號(hào)", "hyfddbh");
    try (InputStream inputStream = file.getInputStream()) {
        EasyExcel.read(inputStream, new ReadListener<Map<String, String>>(){
            private Map<Integer, String> fieldHead;
            //獲取表頭
            @Override
            public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
                Map<Integer, String> integerStringMap = ConverterUtils.convertToStringMap(headMap, context);
                log.info("解析到一條頭數(shù)據(jù):{}", JSON.toJSONString(integerStringMap));
                fieldHead = ExcelParsing.setFieldHead(integerStringMap, AgentDeliverOrderImportVo.class);
                log.info("轉(zhuǎn)化后頭數(shù)據(jù):{}", JSONObject.toJSONString(fieldHead));
            }
            //獲取數(shù)據(jù)
            @Override
            public void invoke(Map<String, String> map, AnalysisContext analysisContext) {
                log.info("解析到一條數(shù)據(jù):{}", JSON.toJSONString(map));
                Map<String, String> valueMap = ExcelParsing.setFieldValue(fieldHead, dictMap, map);
                log.info("轉(zhuǎn)化一條數(shù)據(jù):{}", JSONObject.toJSONString(valueMap));
                log.info("轉(zhuǎn)化一條動(dòng)態(tài)數(shù)據(jù):{}", JSONObject.toJSONString(ExcelParsing.getValueMap(valueMap, AgentDeliverOrderImportVo.class)));
            }
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
            }
        }).sheet().doRead();
    }
    return "完成";
}
/**
 * @author Surpass
 * @Description: excel處理類
 * @date 27/07/2022 15:04
 */
class ExcelParsing {
    /**
     * 將公共字段中的中文轉(zhuǎn)換成數(shù)據(jù)庫(kù)表字段,動(dòng)態(tài)字段(其他字段保留)
     * @param headMap               {1:"姓名", 2:"年齡"}
     * @param obj                   AgentDeliverOrderImportVo(導(dǎo)入實(shí)體類)
     * @return java.util.Map<java.lang.String, java.lang.String>       {1:"name", 2:"年齡"}
     * @author Surpass
     * @date 01/08/2022 17:10
     */
    public static Map<Integer, String> setFieldHead(Map<Integer, String> headMap, Class<?> obj) {
        Field[] fields = obj.getDeclaredFields();
        for (Field field : fields) {
            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
            if (annotation == null) {
                continue;
            }
            //存在翻譯字段的情況,一個(gè)字段對(duì)應(yīng)好幾個(gè)表頭(盡量避免)
            List<String> valueList = Arrays.asList(annotation.value());
            for (Map.Entry<Integer, String> entry : headMap.entrySet()) {
                if (valueList.contains(entry.getValue())) {
                    headMap.put(entry.getKey(), field.getName());
                }
            }
        }
        return headMap;
    }
    /**
     * 獲取數(shù)據(jù)(平鋪),指動(dòng)態(tài)字段kv和公共字段kv在同一級(jí)
     * @param headMap               {1:"name", 2:"年齡"}
     * @param dictMap               {"年齡":"age"}
     * @param valueMap              {1:"廣州****公司", 2:"23"}
     * @return java.util.Map<java.lang.String, java.lang.String>
     * @author Surpass
     * @date 01/08/2022 17:10
     */
    public static Map<String, String> setFieldValue(Map<Integer, String> headMap,
                                                    Map<String, String> dictMap,
                                                    Map<String, String> valueMap) {
        Map<Integer, String> valueIntegerMap = valueMap.entrySet().stream().collect(
                Collectors.toMap(item -> Integer.valueOf(String.valueOf(item.getKey())),
                        item -> StrUtil.nullToEmpty(item.getValue()))
        );
        Map<String, String> valueResultMap = new HashMap<>(valueMap.size());
        Iterator<Map.Entry<Integer, String>> iterator = valueIntegerMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, String> entry = iterator.next();
            //動(dòng)態(tài)字段
            if (dictMap != null && dictMap.containsKey(headMap.get(entry.getKey()))) {
                valueResultMap.put(dictMap.get(headMap.get(entry.getKey())), entry.getValue());
                continue;
            }
            //公共字段
            valueResultMap.put(headMap.get(entry.getKey()), entry.getValue());
            iterator.remove();
        }
        return valueResultMap;
    }
    /**
     * 獲取數(shù)據(jù)(表結(jié)構(gòu)),指動(dòng)態(tài)字段kv已經(jīng)加入到數(shù)據(jù)庫(kù)表字段 dynamicFields 中
     * @param obj                   AgentDeliverOrderImportVo(導(dǎo)入實(shí)體類)
     * @param valueMap              {"name":"廣州****公司", "age":"23"}
     * @return java.util.Map<java.lang.String, java.lang.String>  
     * 返回結(jié)果: {"name":"廣州****公司","dynamicFields":{"age":"23"}}
     * @author Surpass
     * @date 01/08/2022 17:10
     */
    public static Map<String, Object> getValueMap(Map<String, String> valueMap,
                                                  Class<?> obj) {
        Map<String, Object> resultMap = new HashMap<>(valueMap);
        List<String> commonFieldList = new ArrayList<>();
        Field[] fields = obj.getDeclaredFields();
        for (Field field : fields) {
            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
            if (annotation == null) {
                continue;
            }
            commonFieldList.add(field.getName());
        }
        //過濾掉實(shí)體中的公共字段
        Map<String, String> dynamicMap = valueMap.entrySet().stream()
                .filter(item -> !commonFieldList.contains(item.getKey()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        resultMap.put("dynamicFields", dynamicMap);;
        return resultMap;
    }
}

經(jīng)過解析以后這個(gè)文檔的數(shù)據(jù)已經(jīng)和數(shù)據(jù)庫(kù)表一致了,那么我們后續(xù)的操作就是常規(guī)的校驗(yàn)和插入邏輯了。

目前有一個(gè)缺點(diǎn)就是這樣存的動(dòng)態(tài)字段不好做條件查詢,影響不是很大。

總結(jié)

本文介紹了使用 EasyExcel 組件來進(jìn)行導(dǎo)入,實(shí)現(xiàn)公共列和動(dòng)態(tài)列組合類型的導(dǎo)入,以及如何存儲(chǔ)的功能,主要利用反射和字典分別來維護(hù)公共列和動(dòng)態(tài)列的表頭和字段的對(duì)應(yīng)關(guān)系,利用此關(guān)系對(duì)數(shù)據(jù)進(jìn)行解析。

以上就是java EasyExcel實(shí)現(xiàn)動(dòng)態(tài)列解析和存表的詳細(xì)內(nèi)容,更多關(guān)于java EasyExcel動(dòng)態(tài)列存表的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論