Excel读取并数据List/Map-POI

简介: 该工具类基于POI解析.xls格式Excel,通过反射将每行数据映射为Java对象,支持日期、数字等类型处理,可全局输出Map或List,适用于固定模板的数据导入场景,需确保列数与VO字段一致。
  1. 全局输出Map
    import com.test.ExcelVO;
    import org.apache.commons.lang.StringUtils;
    import org.apache.poi.hssf.usermodel.HSSFCell;
    import org.apache.poi.hssf.usermodel.HSSFRow;
    import org.apache.poi.hssf.usermodel.HSSFSheet;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    import org.apache.poi.poifs.filesystem.POIFSFileSystem;
    import org.apache.poi.ss.usermodel.DateUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ParseExcelUtil {

// 解析后存放的全局Map
public static Map<String, DoctorForExcelVO> STATIC_MAP = new HashMap<>();

private static String val = null;

// 这里会对日期格式数据做处理,如不期望更改则删掉
private static SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");

// 这里会对数字格式数据做处理,如不期望更改则删掉
private static DecimalFormat df = new DecimalFormat("0");

private static HSSFWorkbook wb;

// 文件路径
private final static String IMPORT_EXCEL_NAME = "D:Excel_Data.xls";

/**
 * 列数传入,解决列情况: X,X,,X读取列数为3
 **/
private static int colNum = 20;

// 开始行数
private static int startRowNum = 3;

// sheet坐标
private static int index = 1;

/**
 * @return
 */
public static Map<String, DoctorForExcelVO> readExcelData() {

    FileInputStream file = null;
    POIFSFileSystem ts;
    // 读取默认清除上一次数据
    JGPT_DOCTOR_MAP.clear();
    try {
        file = new FileInputStream(DOCTOR_IMPORT_EXCEL_NAME);
        ts = new POIFSFileSystem(file);
        wb = new HSSFWorkbook(ts);
        // 获取表
        HSSFSheet sheet = wb.getSheetAt(index);
        // 获取行数
        int rowNum = sheet.getPhysicalNumberOfRows();
        HSSFRow row;
        for (int i = startRowNum - 1; i < rowNum; i++) {
            List<String> list = new ArrayList<>();
            // 每行
            row = sheet.getRow(i);
            // 每列
            for (int j = 0; j < colNum; j++) {
                HSSFCell cell = row.getCell(j);
                list.add(getXcellVal(cell));
            }
            String key = list.get(3);
            if (StringUtils.isEmpty(key)) {
                continue;
            }
            JGPT_DOCTOR_MAP.put(key, listToModel(list, new DoctorForExcelVO()));
        }
        return JGPT_DOCTOR_MAP;
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != file) {
                file.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return null;
}

/**
 * 类型转换与数据解析
 *
 * @param cell
 * @return
 */
private static String getXcellVal(HSSFCell cell) {

    if (null == cell) {
        return "";
    }
    // 同上,如不希望截取数据,添加下面注释这行
    // 包路径import org.apache.poi.ss.usermodel.Cell;
    // cell.setCellType(Cell.CELL_TYPE_STRING);
    switch (cell.getCellType()) {
        case HSSFCell.CELL_TYPE_NUMERIC:
            if (DateUtil.isCellDateFormatted(cell)) {
                // 日期型
                val = fmt.format(cell.getDateCellValue());
                // 上面如果删掉格式处理,这里统一转成String即可
                // val = String.valueOf(cell.getDateCellValue());
            } else {
                // 数字型
                val = df.format(cell.getNumericCellValue());
                // 上面如果删掉格式处理,这里统一转成String即可
                // val = String.valueOf(cell.getNumericCellValue());
            }
            break;
        // 文本类型
        case HSSFCell.CELL_TYPE_STRING:
            val = cell.getStringCellValue();
            break;
        // 公式特殊处理
        case HSSFCell.CELL_TYPE_FORMULA:
            try {
                val = String.valueOf(cell.getStringCellValue());
            } catch (IllegalStateException e) {
                val = String.valueOf(cell.getNumericCellValue());
            }
            break;
        // 空
        case HSSFCell.CELL_TYPE_BLANK:
            val = cell.getStringCellValue();
            break;
        /** 布尔 **/
        case HSSFCell.CELL_TYPE_BOOLEAN:
            val = String.valueOf(cell.getBooleanCellValue());
            break;
        /** 错误 **/
        case HSSFCell.CELL_TYPE_ERROR:
            val = "ERROR..CHECK DATA";
            break;
        default:
            val = cell.getRichStringCellValue() == null ? null : cell
                    .getRichStringCellValue().toString();
    }

    return val;
}

/**
 * 反射填充属性
 *
 * @param list 数据集
 * @param vo   被反射的对象
 * @return
 * @throws Exception
 */
private static DoctorForExcelVO listToModel(List<String> list, DoctorForExcelVO vo) throws Exception {
    Field[] fields = vo.getClass().getDeclaredFields();
    if (list.size() != fields.length) {
        return null;
    }
    for (int k = 0, len = fields.length; k < len; k++) {
        // 根据属性名称,找寻合适的set方法
        String fieldName = fields[k].getName();
        String setMethodName = "set" + fieldName.substring(0, 1).toUpperCase()
                + fieldName.substring(1);
        Method method = null;
        Class<?> clazz = vo.getClass();
        try {
            method = clazz.getMethod(setMethodName, new Class[]{list.get(k).getClass()});
        } catch (SecurityException e1) {
            e1.printStackTrace();
            return null;
        } catch (NoSuchMethodException e1) {
            String newMethodName = "set" + fieldName.substring(0, 1).toLowerCase()
                    + fieldName.substring(1);
            try {
                method = clazz.getMethod(newMethodName, new Class[]{list.get(k).getClass()});
            } catch (SecurityException e) {
                e.printStackTrace();
                return null;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
                return null;
            }
        }
        if (method == null) {
            return null;
        }
        method.invoke(vo, new Object[]{list.get(k)});
    }
    return vo;
}

反射的VO
@Data
public class DoctorForExcelVO {
private String organ_code;
private String organ_name;
private String remark;
}

  1. 全局输出List
    import org.apache.poi.hssf.usermodel.HSSFCell;
    import org.apache.poi.hssf.usermodel.HSSFRow;
    import org.apache.poi.hssf.usermodel.HSSFSheet;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    import org.apache.poi.poifs.filesystem.POIFSFileSystem;
    import org.apache.poi.ss.usermodel.DateUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

/**

  • @author herb
  • @version 1.0
  • @date 2020/6/9 10:01
  • @Desc 解析Excel模板
    */
    public class ExcelForReturnListUtil {

    // 解析后存放的全局List
    public static List OnlineDataList = new ArrayList<>();

    private static String val = null;

    // 这里的format同上,需要注意,否则会截取数据
    private static SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");

    // 这里的format同上,需要注意,否则会截取数据
    private static DecimalFormat df = new DecimalFormat("0");

    private static HSSFWorkbook wb;

    // 文件路径
    private final static String IMPORT_EXCEL_NAME = "D:/DATA.xls";

    /**

    • 列数传入,解决列情况: X,X,,X读取列数为3
      **/
      private static int colNum = 16;

      // 开始行数
      private static int startRowNum = 3;

      // sheet坐标
      private static int index = 1;

      public static List readExcelData() {
      FileInputStream file = null;
      POIFSFileSystem ts;
      // 读取默认清除上一次数据
      OnlineDataList.clear();
      try {

       file = new FileInputStream(IMPORT_EXCEL_NAME);
       ts = new POIFSFileSystem(file);
       wb = new HSSFWorkbook(ts);
       // 获取表
       HSSFSheet sheet = wb.getSheetAt(index);
       // 获取行数
       int rowNum = sheet.getPhysicalNumberOfRows();
       HSSFRow row;
       for (int i = startRowNum - 1; i < rowNum; i++) {
           List<String> list = new ArrayList<>();
           // 每行
           row = sheet.getRow(i);
           // 每列
           for (int j = 0; j < colNum; j++) {
               HSSFCell cell = row.getCell(j);
               list.add(getXcellVal(cell));
           }
           OnlineDataList.add(listToModel(list, new User()));
       }
       return OnlineDataList;
      

      } catch (Exception e) {

       e.printStackTrace();
      

      } finally {

       try {
           if (null != file) {
               file.close();
           }
       } catch (IOException e) {
           e.printStackTrace();
       }
      

      }
      return null;
      }
      /**

    • 类型转换与数据解析
      *
    • @param cell
    • @return
      */
      private static String getXcellVal(HSSFCell cell) {

      if (null == cell) {

       return "";
      

      }
      // 同上,如不希望截取数据,添加下面注释这行
      // 包路径import org.apache.poi.ss.usermodel.Cell;
      // cell.setCellType(Cell.CELL_TYPE_STRING);
      switch (cell.getCellType()) {

       case HSSFCell.CELL_TYPE_NUMERIC:
           if (DateUtil.isCellDateFormatted(cell)) {
               // 日期型
               val = fmt.format(cell.getDateCellValue());
           } else {
               // 数字型
               val = df.format(cell.getNumericCellValue());
           }
           break;
       // 文本类型
       case HSSFCell.CELL_TYPE_STRING:
           val = cell.getStringCellValue();
           break;
       // 公式特殊处理
       case HSSFCell.CELL_TYPE_FORMULA:
           try {
               val = String.valueOf(cell.getStringCellValue());
           } catch (IllegalStateException e) {
               val = String.valueOf(cell.getNumericCellValue());
           }
           break;
       // 空
       case HSSFCell.CELL_TYPE_BLANK:
           val = cell.getStringCellValue();
           break;
       /** 布尔 **/
       case HSSFCell.CELL_TYPE_BOOLEAN:
           val = String.valueOf(cell.getBooleanCellValue());
           break;
       /** 错误 **/
       case HSSFCell.CELL_TYPE_ERROR:
           val = "ERROR..CHECK DATA";
           break;
       default:
           val = cell.getRichStringCellValue() == null ? null : cell
                   .getRichStringCellValue().toString();
      

      }
      return val;
      }

      /**

    • 反射填充属性
      *
    • @param list 数据集
    • @param vo 被反射的对象
    • @return
    • @throws Exception
      */
      private static ImMedicalOnlineForUploadEntity listToModel(List list, User vo) throws Exception {
      Field[] fields = vo.getClass().getDeclaredFields();
      if (list.size() != fields.length) {
       return null;
      
      }
      for (int k = 0, len = fields.length; k < len; k++) {
       // 根据属性名称,找寻合适的set方法
       String fieldName = fields[k].getName();
       String setMethodName = "set" + fieldName.substring(0, 1).toUpperCase()
               + fieldName.substring(1);
       Method method = null;
       Class<?> clazz = vo.getClass();
       try {
           method = clazz.getMethod(setMethodName, new Class[]{list.get(k).getClass()});
       } catch (SecurityException e1) {
           e1.printStackTrace();
           return null;
       } catch (NoSuchMethodException e1) {
           String newMethodName = "set" + fieldName.substring(0, 1).toLowerCase()
                   + fieldName.substring(1);
           try {
               method = clazz.getMethod(newMethodName, new Class[]{list.get(k).getClass()});
           } catch (SecurityException e) {
               e.printStackTrace();
               return null;
           } catch (NoSuchMethodException e) {
               e.printStackTrace();
               return null;
           }
       }
       if (method == null) {
           return null;
       }
       method.invoke(vo, new Object[]{list.get(k)});
      
      }
      return vo;
      }

注意点:

  1. VO一定要生成set/get方法,我这里借助的@Data注解实现,也可以直接手动生成

  2. 我这里Excel读取行数,列数是写死的,建议作为入参介入【我这里业务场景特殊】

  3. 模板为 *.xls

  4. 模板列数和VO要保持一致,否则反射时候代码校验不通过

目录
相关文章
|
2天前
|
敏捷开发 测试技术 持续交付
微服务技术栈
单元测试是保障代码质量的基石。它快速、稳定,能精准定位问题,提升代码可维护性与团队协作效率。通过“测试金字塔”模型,单元测试作为底层支撑,占比应达80%。相比端到端测试,它显著降低维护成本,助力持续交付。写单测不是踩刹车,而是为软件研发提速。
41 9
|
1天前
|
Java 大数据 Apache
Excel工具-HUTOOL-输出Excel
基于Hutool与Apache POI,封装Excel写入功能,提供ExcelWriter和BigExcelWriter,支持List、Map、Bean等数据类型导出,可自定义样式、多Sheet操作,并避免内存溢出,适用于高效生成Excel文件及Web下载场景。
7 0
|
1天前
HUTOOL-Word生成-Word07Writer
Hutool封装POI实现Word文档生成,提供Word07Writer类便捷创建docx文件。支持自定义字体、段落内容,适用于简单文档导出。需引入hutool-all与poi-ooxml依赖。
2 0
|
1天前
|
缓存 Java 开发工具
QLExpress使用及源码分析
QLExpress是阿里巴巴开源的轻量级规则引擎,支持通过YAML配置规则脚本,结合注解实现Java方法与表达式映射。通过别名机制、AST解析和上下文赋值,实现灵活的动态逻辑执行,适用于复杂业务规则场景。
6 0
|
1天前
Activiti工程分享
本系列包含两个Activiti实战项目:1)ActivitiDemo,快速上手教程与基础示例;2)Activiti,完整审批流程源码,涵盖流程设计、任务审批、监听器等核心功能,助你高效掌握工作流开发。
3 0
|
1天前
|
存储 API 数据库
Activiti框架拓展
Activiti表结构以ACT_开头,分五类:ACT_RE_*存流程定义与资源;ACT_RU_*存运行时实例、任务与变量;ACT_HI_*存历史数据;ACT_ID_*管理用户组及权限;ACT_GE_*存通用二进制与属性数据,支撑流程引擎高效运作。
6 0
|
1天前
|
数据可视化 Java 关系型数据库
认识Activiti
工作流指如请假、报销等需审批的流程,通过引擎实现可视化与自动化。常见技术有BPMN、Activiti、Flowable等,广泛应用于CRM、TMS、WMS等系统,支持单/多节点复杂审批,提升业务效率与管理规范性。(238字)
9 0
|
1天前
|
监控 Java 调度
定时任务概述
定时任务指通过时间表达式调度执行的任务,适用于定时对账、超时取消等场景。实现方式包括单体架构的轮询、Timer、ScheduledExecutorService、Quartz、SpringTask,以及分布式架构下的TBSchedule、Elastic-Job、XXL-JOB等方案,解决集群重复执行、动态调度、故障转移等问题。
14 0
|
1天前
服务暴露总结
本文深入解析服务暴露的核心原理,涵盖本地与远程暴露流程,阐明“Service→Invoker→Exporter”的关键链路,辅以图示帮助理解,为后续学习奠定基础。
4 0
|
1天前
|
消息中间件 算法 网络协议
选举机制理解描述
本文深入解析Zookeeper的Leader选举机制,涵盖服务器启动与运行期间的选举流程,重点介绍FastLeaderElection算法的核心规则:优先比较ZXID(数据最新性),再比较SID(服务器标识)以确保数据一致性。详细阐述投票过程、状态变更及逻辑时钟(electionEpoch)作用,揭示分布式系统中高可用与数据恢复的关键实现。
4 0