java利用注解实现简单的excel数据读取
程序员文章站
2023-12-15 21:08:52
实现工具类
利用注解实现简单的excel数据读取,利用注解对类的属性和excel中的表头映射,使用apache的poi就不用在业务代码中涉及row,rows这些属性了...
实现工具类
利用注解实现简单的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中有详细复杂的示例,可以研究下。由于我的需求很简单,就不整那么复杂啦。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。