| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- 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 读取数据,滑动读取表头,读取到表头后,开始读取数据。如果没有读取到表头,就没有数据。
- *
- * <pre>
- *
- * Created by zhenqin.
- * User: zhenqin
- * Date: 2022/10/6
- * Time: 下午5:44
- * Vendor: yiidata.com
- *
- * </pre>
- *
- * @author zhenqin
- */
- public class OnceReadListener extends AnalysisEventListener<Object> {
- /**
- * 预期的标题 Header
- */
- final Map<String, String> headerFieldMapping;
- /**
- * 实际数据
- */
- private List<Object> list = new ArrayList<Object>();
- /**
- * 实际的 Header
- */
- Map<Integer, String> headMap;
- /**
- * 是否有 header
- */
- volatile boolean hasHeader;
- public OnceReadListener(Map<String, String> headerFieldMapping) {
- this.headerFieldMapping = headerFieldMapping;
- }
- /**
- * 滑动读取表头
- * @param headMap Excel 实际表头
- * @param context
- */
- @Override
- public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
- Map<Integer, String> newHeadMap = new HashMap<>(headMap.size());
- // 使用 Stream API 对换 Key 和 Value
- Map<String, Integer> headMapInverse = new HashMap<>(headMap.size());
- for (Map.Entry<Integer, String> 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<Map.Entry<String, String>> entries = new HashSet<>(headerFieldMapping.entrySet());
- for (Map.Entry<String, String> 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<Integer, String>)object, context);
- return;
- }
- //System.out.println(object);
- list.add(object);
- }
- @Override
- public void doAfterAllAnalysed(AnalysisContext context) {
- }
- /**
- * 返回表头,如果没有读取到表头,则返回 null
- * @return
- */
- public Map<Integer, String> getHeadMap() {
- return headMap;
- }
- @Override
- public boolean hasNext(AnalysisContext context) {
- return super.hasNext(context);
- }
- /**
- * 返回数据列表
- * @return
- */
- public List<Object> getList() {
- return list;
- }
- public void setList(List<Object> list) {
- this.list = list;
- }
- }
|