Excel读取并数据List/Map-POI

简介: 该工具类使用POI解析.xls格式Excel,通过反射将每行数据映射为VO对象,支持日期、数字等类型处理,可全局输出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要保持一致,否则反射时候代码校验不通过

相关文章
|
10月前
|
Arthas 监控 前端开发
arthas精准定位Java应用CPU负载过高问题
通过Arthas的watch命令监控DispatcherServlet的getHandler方法,快速定位Spring MVC中处理请求的Controller;结合反编译功能,实时查看目标代码,提升排查效率。
|
10月前
|
缓存 开发工具 git
QLExpress使用及源码分析
QLExpress是阿里开源的轻量级规则引擎,支持通过注解与YAML配置实现业务逻辑解耦。基于AST语法树解析,提供上下文绑定、动态脚本执行与缓存机制,适用于复杂条件判断与计算场景,如BMI计算、用户规则校验等,具备高扩展性与易维护性。
|
10月前
|
Arthas 监控 Java
arthas 基础指令
Arthas简介:通过dashboard查看线程状态、CPU占用等;jad反编译类文件;thread分析线程堆栈及阻塞情况;watch监控方法执行耗时与参数;支持quit退出连接或stop彻底终止。适用于Java进程诊断,操作便捷,功能强大。(239字)
|
10月前
|
Arthas 监控 Java
arthas 安装
本教程介绍Arthas的安装与基础使用。需提前安装JDK并确保服务器有Java应用运行。下载arthas-boot.jar,上传Java应用(如Arthas-demo.jar),启动后通过`java -jar arthas-boot.jar`接入,选择对应进程即可监控。支持多Java进程管理,为后续深入使用奠定基础。(239字)
|
10月前
|
缓存 Dubbo Java
什么是API网关
API网关是一种架构思想,用于统一管理外部请求,实现请求路由、协议转换、鉴权、限流、熔断降级等功能。通过将多个服务接口聚合到网关,简化调用流程,提升系统安全与性能。常见实现如Soul、Zuul、Kong等,广泛应用于微服务架构中。
|
10月前
|
Java 大数据 Maven
Excel工具-HUTOOL-输出Excel
Hutool封装Excel写出功能,提供ExcelWriter和BigExcelWriter,支持写入List、Map、Bean等数据类型,可自定义样式、标题别名、多Sheet导出,并解决大数据量内存溢出问题,操作简便且高效。
|
10月前
|
Java 数据库连接 调度
xxljob
本文深入分析XXL-JOB执行源码,涵盖架构设计与核心模块实现。包含带中文注释的源码包及流程图,详解国际化初始化、任务触发线程池(快慢池机制)、注册中心心跳检测、失败重试告警、任务结果丢失处理、日志清理及时间轮调度等核心逻辑,助你全面掌握其原理。
|
10月前
|
前端开发 NoSQL Java
jeecgboot 单体版本
JeecgBoot单体版简介:基于Spring Boot 2.7 + Vue3 + TypeScript + Vite5,集成MybatisPlus、Shiro、Redis、Nacos等技术,支持代码生成、权限管理与微服务架构。前端使用Ant-Design-Vue,提供在线表单开发与低代码能力,快速构建企业级应用,适用于农商行笔试题等场景开发。(239字)
|
10月前
|
前端开发 算法 Java
2025最新Java面试题
涵盖Java基础、算法、Web开发、主流框架(Spring/SpringBoot/SpringCloud)、数据库及常用组件,提供前端、人事、Agent等多类面试题,含《中州养老》《云岚到家》等实战项目解析,持续更新面试录音与复盘资料。
|
10月前
|
Java
ACTIVITI
本节带你30分钟快速上手Activiti,涵盖工作流概念、SpringBoot集成、核心代码实现、表模型解析及项目分享,助你高效掌握Activiti7.0基础与应用。视频教程同步配套。

热门文章

最新文章