package cn.exlive.exbooter.excel; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; /** * Excel 读取数据,滑动读取表头,读取到表头后,开始读取数据。如果没有读取到表头,就没有数据。 * *
 *
 * Created by zhenqin.
 * User: zhenqin
 * Date: 2022/10/6
 * Time: 下午5:44
 * Vendor: yiidata.com
 *
 * 
* * @author zhenqin */ public class OnceReadListener extends AnalysisEventListener { /** * 预期的标题 Header */ final Map headerFieldMapping; /** * 实际数据 */ private List list = new ArrayList(); /** * 实际的 Header */ Map headMap; /** * 是否有 header */ volatile boolean hasHeader; public OnceReadListener(Map headerFieldMapping) { this.headerFieldMapping = headerFieldMapping; } /** * 滑动读取表头 * @param headMap Excel 实际表头 * @param context */ @Override public void invokeHeadMap(Map headMap, AnalysisContext context) { Map newHeadMap = new HashMap<>(headMap.size()); // 使用 Stream API 对换 Key 和 Value Map headMapInverse = new HashMap<>(headMap.size()); for (Map.Entry entry : headMap.entrySet()) { final String oriHead = entry.getValue(); headMapInverse.put(oriHead, entry.getKey()); String head = oriHead; // head 可能包含特殊字符 if(head.contains("*")) { head = head.replaceAll("\\*", ""); } else if(head.contains("(")) { head = head.startsWith("(") ? head.substring(head.indexOf(")") + 1) : head.substring(0, head.indexOf("(")); } else if(head.contains("(")) { head = head.startsWith("(") ? head.substring(head.indexOf(")") + 1) : head.substring(0, head.indexOf("(")); } else if(head.contains("【")) { head = head.startsWith("【") ? head.substring(head.indexOf("】") + 1) : head.substring(0, head.indexOf("【")); } else if(head.contains("[")) { head = head.startsWith("[") ? head.substring(head.indexOf("]") + 1) : head.substring(0, head.indexOf("[")); } // oriHead 中 包含特殊字符 if(!StringUtils.equals(oriHead, head)) { headMapInverse.put(head, entry.getKey()); } } int matchCount = 0; final HashSet> entries = new HashSet<>(headerFieldMapping.entrySet()); for (Map.Entry entry : entries) { String key = entry.getKey(); if(key.contains("*")) { key = key.replaceAll("\\*", ""); } else if(key.contains("(")) { key = key.startsWith("(") ? key.substring(key.indexOf(")") + 1) : key.substring(0, key.indexOf("(")); } else if(key.contains("(")) { key = key.startsWith("(") ? key.substring(key.indexOf(")") + 1) : key.substring(0, key.indexOf("(")); } else if(key.contains("【")) { key = key.startsWith("【") ? key.substring(key.indexOf("】") + 1) : key.substring(0, key.indexOf("【")); } else if(key.contains("[")) { key = key.startsWith("[") ? key.substring(key.indexOf("]") + 1) : key.substring(0, key.indexOf("[")); } final Integer index = headMapInverse.get(key); if(index != null) { matchCount++; newHeadMap.put(index, key); } // 检测是否发生了变化,如果变化,则重新放入 if(!StringUtils.equals(entry.getKey(), key)) { // 重新放入新的字段 headerFieldMapping.put(key, entry.getValue()); } } // 如果 10个 header,满足了 6 个,则成功 if((matchCount * 1.0f / headerFieldMapping.size()) >= 0.5f) { this.headMap = newHeadMap; this.hasHeader = true; } } /** * 处理数据,需要判断 header 是否读取到,读取不到则往下继续读,直到结束 * @param object one row value. It is same as {@link AnalysisContext#readRowHolder()} * @param context analysis context */ @Override public void invoke(Object object, AnalysisContext context) { // 先找到表头,有时候表头不在第一行 if(!hasHeader) { this.invokeHeadMap((Map)object, context); return; } //System.out.println(object); list.add(object); } @Override public void doAfterAllAnalysed(AnalysisContext context) { } /** * 返回表头,如果没有读取到表头,则返回 null * @return */ public Map getHeadMap() { return headMap; } @Override public boolean hasNext(AnalysisContext context) { return super.hasNext(context); } /** * 返回数据列表 * @return */ public List getList() { return list; } public void setList(List list) { this.list = list; } }