java利用注解实现简单的excel数据读取

实现工具类

利用注解实现简单的excel数据读取,利用注解对类的属性和excel中的表头映射,使用Apache的poi就不用在业务代码中涉及row,rows这些属性了。

定义注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel {

 String name();

}

由于本例中只涉及根据Excel表头部分对Excel进行解析,只定义了一个name作为和Excel表头的隐射。

工具类完整代码如下:

public class ExcelUtil<T> {

 Class<T> clazz;

 public ExcelUtil(Class<T> clazz) {
  this.clazz = clazz;
 }

 public List<T> importExcel(String sheetName, InputStream input) {
  int maxCol = 0;
  List<T> list = new ArrayList<T>();
  try {
   Workbook workbook = WorkbookFactory.create(input);
   Sheet sheet = workbook.getSheet(sheetName);
   // 如果指定sheet名,则取指定sheet中的内容.
   if (!sheetName.trim().equals("")) {
    sheet = workbook.getSheet(sheetName);
   }
   // 如果传入的sheet名不存在则默认指向第1个sheet.
   if (sheet == null) {
    sheet = workbook.getSheetAt(0);
   }
   int rows = sheet.getPhysicalNumberOfRows();
   // 有数据时才处理
   if (rows > 0) {
    List<Field> allFields = getMappedFiled(clazz, null);
    // 定义一个map用于存放列的序号和field.
    Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>();
    // 第一行为表头
    Row rowHead = sheet.getRow(0);
    Map<String, Integer> cellMap = new HashMap<>();
    int cellNum = rowHead.getPhysicalNumberOfCells();
    for (int i = 0; i < cellNum; i++){
     cellMap.put(rowHead.getCell(i).getStringCellValue().toLowerCase(), i);
    }
    for (Field field : allFields) {
     // 将有注解的field存放到map中.
     if (field.isAnnotationPresent(Excel.class)) {
      Excel attr = field.getAnnotation(Excel.class);
      // 根据Name来获取相应的failed
      int col = cellMap.get(attr.name().toLowerCase());
      field.setAccessible(true);
      fieldsMap.put(col, field);
     }
    }
    // 从第2行开始取数据
    for (int i = 1; i < rows; i++) {
     Row row = sheet.getRow(i);
     T entity = null;
     for (int j = 0; j < cellNum; j++) {
      Cell cell = row.getCell(j);
      if (cell == null) {
       continue;
      }
      int cellType = cell.getCellType();
      String c = "";
      if (cellType == HSSFCell.CELL_TYPE_NUMERIC) {
       DecimalFormat df = new DecimalFormat("0");
       c = df.format(cell.getNumericCellValue());
      } else if (cellType == HSSFCell.CELL_TYPE_BOOLEAN) {
       c = String.valueOf(cell.getBooleanCellValue());
      } else {
       c = cell.getStringCellValue();
      }
      if (c == null || c.equals("")) {
       continue;
      }
      entity = (entity == null ? clazz.newInstance() : entity);
      // 从map中得到对应列的field.
      Field field = fieldsMap.get(j);
      if (field == null) {
       continue;
      }
      // 取得类型,并根据对象类型设置值.
      Class<?> fieldType = field.getType();
      if (String.class == fieldType) {
       field.set(entity, String.valueOf(c));
      } else if ((Integer.TYPE == fieldType)
        || (Integer.class == fieldType)) {
       field.set(entity, Integer.valueOf(c));
      } else if ((Long.TYPE == fieldType)
        || (Long.class == fieldType)) {
       field.set(entity, Long.valueOf(c));
      } else if ((Float.TYPE == fieldType)
        || (Float.class == fieldType)) {
       field.set(entity, Float.valueOf(c));
      } else if ((Short.TYPE == fieldType)
        || (Short.class == fieldType)) {
       field.set(entity, Short.valueOf(c));
      } else if ((Double.TYPE == fieldType)
        || (Double.class == fieldType)) {
       field.set(entity, Double.valueOf(c));
      } else if (Character.TYPE == fieldType) {
       if (c.length() > 0) {
        field.set(entity, c.charAt(0));
       }
      }
     }
     if (entity != null) {
      list.add(entity);
     }
    }
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
  return list;
 }

 /**
  * 得到实体类所有通过注解映射了数据表的字段
  *
  * @param clazz
  * @param fields
  * @return
  */
 private List<Field> getMappedFiled(Class clazz, List<Field> fields) {
  if (fields == null) {
   fields = new ArrayList<Field>();
  }
  // 得到所有定义字段
  Field[] allFields = clazz.getDeclaredFields();
  // 得到所有field并存放到一个list中.
  for (Field field : allFields) {
   if (field.isAnnotationPresent(Excel.class)) {
    fields.add(field);
   }
  }
  if (clazz.getSuperclass() != null
    && !clazz.getSuperclass().equals(Object.class)) {
   getMappedFiled(clazz.getSuperclass(), fields);
  }

  return fields;
 }

}

代码很简单,获取sheet,解析第一行,并和实体类标有注解的字段一一对应,用hashMap记录下来,然后循环取得Excel中剩下所有的数据,根据map的对应关系将值set到对应字段。

基本使用

待解析表格如下:

定义实体类:

public class User {

 @Excel(name = "filed1")
 private String name;
 @Excel(name = "filed2")
 private String nameEn;
 @Excel(name = "filed3")
 private Integer age;
 @Excel(name = "filed4")
 private String six;
 @Excel(name = "filed5")
 private String weight;

 // ...getter setter
}

使用工具类:

public static void main (String[] args) {
 FileInputStream fileInputStream = null;
 try {
  fileInputStream = new FileInputStream("D://data.xlsx");
 } catch (FileNotFoundException e) {
  e.printStackTrace();
 }
 ExcelUtil<User> util = new ExcelUtil<>(User.class);
 List<User> jalanHotelList = util.importExcel("user", fileInputStream);
 // do something
}

利用这个思路可以扩展出导出excel功能,利用注解指定导出的excel表头,甚至可以轻松控制excel表头的颜色,合并属性等等,在xdemo中有详细复杂的示例,可以研究下。由于我的需求很简单,就不整那么复杂啦。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java注解实现动态数据源切换的实例代码

    当一个项目中有多个数据源(也可以是主从库)的时候,我们可以利用注解在mapper接口上标注数据源,从而来实现多个数据源在运行时的动态切换. 实现原理 在Spring 2.0.1中引入了AbstractRoutingDataSource, 该类充当了DataSource的路由中介, 能有在运行时, 根据某种key值来动态切换到真正的DataSource上. 看下AbstractRoutingDataSource: 复制代码 代码如下: public abstract class AbstractR

  • java 注解的基础详细介绍

    java 注解的基础详细介绍 前言 注解是Java引入的一项非常受欢迎的补充,它提供了一种结构化的,并且具有类型检查能力的新途径,从而使得程序员能够为代码加入元数据,而不会导致代码杂乱且难以阅读.使用注解能够帮助我们避免编写累赘的部署描述文件,以及其他生成的文件. 注解的语法比较简单,除了@符号的使用之外,它基本与java固有的语法一致.但由于java源码中提供的内置注解很少,所以大部分同学对注解都不是很了解,虽然我们都接触过,比如java内置的几种注解: @Override,表示当前的方法定义

  • java 中MyBatis注解映射的实例详解

    java  中MyBatis注解映射的实例详解 1.普通映射 @Select("select * from mybatis_Student where id=#{id}") public Student getStudent(int id); @Insert("insert into mybatis_Student (name, age, remark, pic,grade_id,address_id) values (#{name},#{age},#{remark}, #{

  • 深入理解 Java注解及实例

     Java注解 什么是注解? Java中的注解就是Java源代码的元数据,也就是说注解是用来描述Java源代码的. 基本语法就是:@后面跟注解的名称. ①Override:标识某一个方法是否正确覆盖了它的父类的方法. ②Deprecated:表示已经不建议使用这个类成员了. 它是一个标记注解. ③SuppressWarnings:用来抑制警告信息 等等. 要更好的理解注解,我们可以自己写一个注解 @Target : 用来限制注解可以用到那几个地方.比方可以用到类上,可以用到方法胜都可以用@Tar

  • Kotlin 基础教程之注解与java中的注解比较

    Kotlin 的注解完全兼容 Java 的注解. 声明注解 @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION) @Retention(AnnotationRetention.SOURCE) @MustBeDocumented annotation class Fancy 可以通过向注解类添加元注解(meta

  • java 中@Deprecated 注解的实例详解

    java 中@Deprecated 注解的实例详解 1 简介 Deprecated 同 SuppressWarnings 一样,都是 J2SE 5.0 中定义在Java.lang包中的标准 Annotation 之一,其可以标注在类.字段和方法上,其作用为:不鼓励程序员使用被 @Deprecated 注释的程序元素,因为被 @Deprecated 注释的元素很危险(例如,现阶段 JDK 提供的带有 @Deprecated 注释的元素在以后的 JDK 版本中可能被删除)或存在更好的选择.在使用不被

  • 详解Java注解的实现与使用方法

    详解Java注解的实现与使用方法 Java注解是java5版本发布的,其作用就是节省配置文件,增强代码可读性.在如今各种框架及开发中非常常见,特此说明一下. 如何创建一个注解 每一个自定义的注解都由四个元注解组成,这四个元注解由java本身提供: @Target(ElementType.**) 这是一个枚举,它置顶是该自定义的注解使用的地方,像类.变量.方法等 @Retention(RetentionPolicy.**)作用是标明注解保存在什么级别,像在编译时.class文件中,vm运行中 @D

  • java利用注解实现简单的excel数据读取

    实现工具类 利用注解实现简单的excel数据读取,利用注解对类的属性和excel中的表头映射,使用Apache的poi就不用在业务代码中涉及row,rows这些属性了. 定义注解: @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Excel { String name(); } 由于本例中只涉及根据Excel表头部分对Excel进行解析,只定义了一个name作为和Excel表头的隐射

  • 利用Python实现简单的Excel统计函数

    目录 需求分析 解决步骤 最终结果 技术总结 需求分析 根据原始数据,计算出累计和.回撤.连续正确.连续错误.连续正确值与连续错误值6项数据,其中原始数据大于等于0认定为正确,原始数据小于0为错误.明白了要求,那我们就开始撸代码吧~ 解决步骤 import pandas as pd #创建一个计算数据的函数 def calculate(df): pass #读取原始数据,将索引列去除 df = pd.read_excel('需求0621.xlsx',index_col=0) #调用计算数据的函数

  • Java利用POI实现导入导出Excel表格

    本文实例为大家分享了Java利用POI实现导入导出Excel表格的具体代码,供大家参考,具体内容如下 一.Java利用POI实现导入导出Excel表格demo 1.引入依赖 <dependency>       <groupId>org.apache.poi</groupId>       <artifactId>poi-ooxml</artifactId>        <version>4.1.2</version>

  • Java利用正则取标签之间的数据

    我就废话不多说了,大家还是直接看代码吧~ String str = "哈哈<font color='red'>1111</font>还是你牛<font color='red'>11111</font> "; String regStr = "<font color='red'>(.*?)</font>"; Pattern pattern = Pattern.compile(regStr); if

  • java利用pdfbox+poi往pdf插入数据

    目录 指定页码插入/替换 思路1(插入): 思路2(替换): 啰嗦几句 总结 指定页码插入/替换 pdfbox好像没有专门提供这个方法,但是现有的方法多重组合起来也能实现这个功能, 需求:一个pdf文件A有10页,现在想在第6页插入一页新的pdf文件B,插入完成后整个pdf文件A变成11页. 思路1(插入): 先将这个10的pdf拆分成10个1页的pdf,按顺序放好,文件名分别是:1.pdf.2.pdf....10.pdf.再拆分到第6页的时候将文件B放进来,重命名问6.pdf,原本pdf文件A

  • 详解Python如何实现Excel数据读取和写入

    目录 1. 功能分析 2.系统开发环境 3.安装依赖库 4. 主函数设计 5.模块设计 1. 功能分析 1.加载文件夹内所有的Excel数据: 2.生产贡献度分析图表(以柱状图显示表格数据): 3.提起Excel表格中指定列数据: 4.定向筛选所需数据: 5.多表数据统计排行: 6.多表数据合并新excel文件. 2.系统开发环境 Anaconda3,在conda 中,window和ubuntu中的python功能一样 . pycharm. 3.安装依赖库 这些依赖包   都要装好 import

  • Java利用POI实现导入导出Excel表格示例代码

    介绍 Jakarta POI 是一套用于访问微软格式文档的Java API.Jakarta POI有很多组件组成,其中有用于操作Excel格式文件的HSSF和用于操作Word的HWPF,在各种组件中目前只有用于操作Excel的HSSF相对成熟.官方主页http://poi.apache.org/index.html,API文档http://poi.apache.org/apidocs/index.html 实现 已经在代码中加入了完整的注释. import java.io.FileInputSt

  • Java利用剪贴板实现交换程序间数据的方法

    本文实例讲述了Java利用剪贴板交换程序间数据的实现方法.在图形化系统中,系统剪贴板非常重要,很难想象一个没有剪贴板功能的图形化操作系统使用起来会是怎样.本例就实现了Java 程序与所在系统的剪贴板的数据交流,当单击"Paste"按钮后,Java 程序从系统剪贴板中取得数据并显示在一个JTextArea 组件中:当单击"Copy"按钮后,文本区中的选中文本将被传送到系统剪贴板上. 首先必须得到系统剪贴板的实例引用,java.awt.Toolkit 类中提供了getS

  • 使用Python对EXCEL数据的预处理

    一.熟悉数据 我们将EXCEL中的数据导入之后,需要对数据进行大致性的了解,当对数据充分地了解之后,才便于后期的分析工作. 该部分涉及到四个基本方法,分别为“shape”“info”“head”“describe”.下面会具体介绍四者的用法与功能. 以下是我准备好的一组简单的excel数据: 其中:“编号”“姓名”“识别码”“时间”称为索引列:左边的“1”“2”···“6”称为索引行. 通过第一篇的方法,将数据导入python中.代码与输出结果如下所示: import pandas as pd

  • Java利用自定义注解、反射实现简单BaseDao实例

    在常见的ORM框架中,大都提供了使用注解方式来实现entity与数据库的映射,这里简单地使用自定义注解与反射来生成可执行的sql语句. 这是整体的目录结构,本来是为复习注解建立的项目^.^ 好的,首先我们来确定思路. 1. 自定义@Table @Column注解, 我们稍微模仿hibernate,让@Table作用于类上,来表明实体类与数据表的映射关系,且让@Table中的属性value映射为数据表的名称tableName:让@Column作用于属性上(这里没实现作用于set方法上),表明属性与

随机推荐