poi导出excel,支持2007和2003,支持javabean,利用反射对poi进行简单封装,支持任意实体和乱序的excel表格
来源:互联网 发布:风水罗盘软件 编辑:程序博客网 时间:2024/06/07 01:47
需要的jar包有poi-3.17.jar
poi-ooxml-3.10-FINAL.jar
poi-ooxml-schemas-3.8.jar
xmlbeans-2.3.0.jar
/** * 将poi进行简单的封装,通过注解和反射,将excel中的集合和实体的set方法对应,形成执行集,再将执行集进行遍历,对bean进行封装,转化为 * 主要支持任意实体, * 支持excel文件中字段的不规则排序
* 单条记录的容错处理
* 支持扩展类型转化 * @author YKD * * @param <T> */package gz.kd.utils.ExcelUtils;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.io.PushbackInputStream;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import java.text.DecimalFormat;import java.util.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.poi.POIXMLDocument;import org.apache.poi.hssf.usermodel.HSSFWorkbook;import org.apache.poi.openxml4j.exceptions.InvalidFormatException;import org.apache.poi.openxml4j.opc.OPCPackage;import org.apache.poi.poifs.filesystem.POIFSFileSystem;import org.apache.poi.ss.usermodel.Cell;import org.apache.poi.ss.usermodel.DateUtil;import org.apache.poi.ss.usermodel.Row;import org.apache.poi.ss.usermodel.Sheet;import org.apache.poi.ss.usermodel.Workbook;import org.apache.poi.ss.usermodel.WorkbookFactory;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import org.hamcrest.core.IsInstanceOf;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * 将poi进行简单的封装,通过注解和反射,将excel中的集合和实体的set方法对应,形成执行集,再将执行集进行遍历,对bean进行封装,转化为 * 主要支持任意实体, * 支持excel文件中字段的不规则排序 * @author 姚楷东 276368974@qq.com * * @param <T> */public class ReadExcelByEntityUtils<T> {private Logger logger = LoggerFactory.getLogger(ReadExcelByEntityUtils.class); private Workbook wb;//每一个Excel文件都将被解析成一个WorkBook对象private Sheet sheet;//Excel的每一页都将被解析成一个Sheet对象;private Row row;//Excel中的每一行都是一个Row对象,每一个单元格都是一个Cell对象。private Map<Integer,T> map; //最终结果集 private Class<T> entity; //泛型类private Field[] fields; //泛型方法集private List<Class> TypeList; //转化类型private Map<String,String> mapByAno=new HashMap<String,String>();//初始化集:<注解,属性名>/** * 构造工具类 * @param filepath * @throws InstantiationException * @throws IllegalAccessException * @throws InvalidFormatException */@SuppressWarnings("unchecked")public ReadExcelByEntityUtils(String filepath) throws InstantiationException, IllegalAccessException, InvalidFormatException{ if(filepath==null){ System.out.println("Excel文件名为空"); return; } String lastName = filepath.substring(filepath.lastIndexOf(".")); try { InputStream is = new FileInputStream(filepath); if(".xls".equals(lastName)){ wb = new HSSFWorkbook(is); }else if(".xlsx".equals(lastName)){ File file = new File(filepath); wb = WorkbookFactory.create(file); }else{ wb=null; } } catch (FileNotFoundException e) { logger.error("文件找不到FileNotFoundException", e); } catch (IOException e) { logger.error("IOException", e); } entity = (Class<T>)((ParameterizedType)this.getClass().getGenericSuperclass()) .getActualTypeArguments()[0]; @SuppressWarnings("unused")T t = entity.newInstance(); if(this.entity!=null){ fields = entity.getDeclaredFields();//获取到属性字段 TypeList = new ArrayList<Class>(); for(Field f:fields){ //设置强制访问 f.setAccessible(true); EntiName e = f.getAnnotation(EntiName.class); if(!e.id()){ //对true的字段进行拦截 mapByAno.put(e.RName(),f.getName()); TypeList.add(e.clazz()); } } } } public Map<Integer,T> getMap() throws Exception{setEntityMap();return map;}/** * * 将excel数据内容填充到map * @throws Exception */private void setEntityMap() throws Exception{this.map = new HashMap<Integer, T>(); T t=null;String methodName=null;List<String> InvokeList = setInvokeList(); sheet = wb.getSheetAt(0); //总行数 int rowNum = sheet.getLastRowNum(); row = sheet.getRow(0); //得到每一行单元格个数,包括其中的空单元格,这里要求表格内容的每一行都是固定的个数 int colNum = row.getLastCellNum(); //每行单元格总数 for (int i = 1; i <= rowNum; i++) { //从第二行开始,遍历每一行 row = sheet.getRow(i); t = exchangeEntity(InvokeList, colNum,i); map.put(i-1, t); //将封装好的实体放入map } }private T exchangeEntity(List<String> InvokeList, int colNum,int rowNum){T t=null;try {DecimalFormat df = new DecimalFormat("#"); // 对长数字段进行string的转化String methodName;int j = 0; t = entity.newInstance(); //每次新建一个Twhile (j < colNum) { Object obj = getCellFormatValue(row.getCell(j)); // Class cs = TypeList.get(j); methodName=InvokeList.get(j); Method method = t.getClass().getMethod(methodName, TypeList.get(j)); if(obj==null||obj.equals("")){ try {method.invoke(t, (Object)null); //Object转化,很关键} catch (Exception e) {// TODO Auto-generated catch blockreturn t;} }else{ Object cast; if(cs.getName().equals("java.lang.String")){ //在这里拦截“excel中读取为double,date,int,boolean”,实际的实体函数形参却是String类型的 if(obj.getClass().getName().equals("java.lang.Double")){ cast = df.format(obj); }else{ cast = String.valueOf(obj); } }else if(cs.getName().equals("java.lang.Integer")){//形参需要的类型 if(obj.getClass().getName().equals("java.lang.Double")){ String intNUm = df.format(obj); cast = Integer.valueOf(intNUm); }else{ cast = cs.cast(obj); //可对类型进行扩展 } }/*else if(obj.getClass().getName().equals("java.util.Date")){ }else if(obj.getClass().getName().equals("set方法中的类型")){ 类型转化处理 } */else{ cast = cs.cast(obj); } //System.out.println(cast);method.invoke(t, cast); } j++; }} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();System.out.println("ExcelDEBUG:第"+rowNum+"行导入出错");return t;//有异常返回一个空t}return t;}/** * 将标题头和实体的属性set方法对应上,形成一个执行函数集list,之后调用这个函数时,每次遍历list,然后invoke即可 * @throws Exception * */private List<String> setInvokeList() throws Exception{if(wb==null){ throw new Exception("Workbook对象为空!"); } List<String> invokeList = new ArrayList<String>();List<String> readExcelTitle = readExcelTitle();StringBuffer sb = new StringBuffer("set");//System.out.println("setInvokeList的判断"+readExcelTitle.size()+"?==?"+mapByAno.size());if(readExcelTitle.size()!=mapByAno.size()){System.out.println("KD:excel表头跟注解数量不对应");return null;}else{for (String obj : readExcelTitle) {if(mapByAno.get(obj)==null){System.out.println("KD:excel表头跟注解名称不对应");return null;}String fieldname = mapByAno.get(obj);mapByAno.remove(obj, fieldname);//每拿一个put掉一个sb = new StringBuffer("set");String method = sb.append(fieldname.substring(0, 1).toUpperCase()).append(fieldname.substring(1)).toString();invokeList.add(method);}if(!mapByAno.isEmpty()){System.out.println("KD:excel表头跟注解名称不对应");return null;}return invokeList;/* */}} /** * 得到标题头,标题头一定要是string类型,否则报错 * @return * @throws Exception */ public List<String> readExcelTitle() throws Exception{ if(wb == null){ throw new Exception("KD:workbook对象为空"); } sheet = wb.getSheetAt(0); row = sheet.getRow(0); //标题总列数int colNum = row.getPhysicalNumberOfCells(); //去掉对空列的计数 //System.out.println("colNum:"+colNum); List<String> list = new ArrayList<String>(); for(int i = 0;i<colNum;i++){ if(row.getCell(i)==null||row.getCell(i).equals("")){ list.add(null); continue; }else { list.add((String) getCellFormatValue(row.getCell(i))); }} return list; } @SuppressWarnings("deprecation") private Object getCellFormatValue(Cell cell) { DecimalFormat df = new DecimalFormat("#"); // 对长数字段进行string的转化 Object cellvalue = null; if (cell != null) { // 判断当前Cell的Type switch (cell.getCellType()) { case Cell.CELL_TYPE_NUMERIC:// 如果当前Cell的Type为NUMERIC case Cell.CELL_TYPE_FORMULA: { // 判断当前的cell是否为Date if (DateUtil.isCellDateFormatted(cell)) { Date date = cell.getDateCellValue(); cellvalue = date; } else {// 如果是纯数字 // 取得当前Cell的数值 cellvalue = cell.getNumericCellValue(); /*if(cellvalue.getClass().getName().equals("java.lang.Double")){ cellvalue = df.format(cellvalue); }如果在此处拦截double就会使得所有的double都变成string,而有的时候我并不需要转成string */ } break; } case Cell.CELL_TYPE_STRING:// 如果当前Cell的Type为STRING // 取得当前的Cell字符串 cellvalue = cell.getRichStringCellValue().getString(); break; default:// 默认的Cell值 cellvalue = ""; } } else { cellvalue = ""; } return cellvalue; } }import static java.lang.annotation.ElementType.FIELD;import static java.lang.annotation.ElementType.TYPE;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 辅助ReadExcelByEntityUtils * @author 姚楷东 276368974@qq.com 做人,要有激情 */@Target({FIELD})@Retention(RetentionPolicy.RUNTIME)//指定注解在运行时有效public @interface EntiName { /** * 是否为序列号 * @return */ boolean id() default false; /** * 字段名称 * @return */String RName()default "";/** * 形参类型 * @return */ Class clazz()default String.class; }应用举例import java.util.Date;import gz.kd.utils.ExcelUtils.EntiName;public class Items {@EntiName(RName="序号",clazz=Integer.class) private Integer id;@EntiName(RName="名称") private String name;@EntiName(RName="价格",clazz=Double.class) private Double price;@EntiName(RName="照片",clazz=String.class) private String pic;@EntiName(RName="创建时间",clazz=Date.class) private Date createtime;@EntiName(RName="细节") private String detail; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name == null ? null : name.trim(); } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public String getPic() { return pic; } public void setPic(String pic) { this.pic = pic; } public Date getCreatetime() { return createtime; } public void setCreatetime(Date createtime) { this.createtime = createtime; } public String getDetail() { return detail; } public void setDetail(String detail) { this.detail = detail == null ? null : detail.trim(); }@Overridepublic String toString() {return "Items [id=" + id + ", name=" + name + ", price=" + price + ", pic=" + pic + ", createtime=" + createtime+ ", detail=" + detail + "]";} }运行结果为封装好的Map实体下面的表格,首行为字段,必需要与实体上的注解对应,顺序不需要对应;第二行开始为表格内容:名称价格照片创建时间 细节台式机1a6f270c-714b-4070-b960-e25015615a19.jpg细节电脑60002017/11/10 15:26 细节背包36002017/11/10 15:30 背包2017/11/10 15:30 细节1如果不懂或者需要源码,留下评论,欢迎加qq 276368974 交流
阅读全文
1 0
- poi导出excel,支持2007和2003,支持javabean,利用反射对poi进行简单封装,支持任意实体和乱序的excel表格
- poi导出excel,支持合并的单元格
- poi/jxls导入/导出Excel工具类(支持2003和2007)
- poi/jxls导入/导出Excel工具类(支持2003和2007)
- Java中利用POI操作Excel(支持2003、2007)
- 使用poi Java封装对Excel内容的读取,支持合并列形式
- 利用Apache POI 实现简单的Excel表格导出
- java操作Excel -- poi支持
- 利用Java反射机制和POI实现导出Excel功能
- 利用Java反射机制和POI实现导出Excel功能
- POI读取excel文件通用代码(增强版--支持返回javaBean集合)---2003,2007
- poi读取excel模板,填充内容并导出,支持导出2007支持公式自动计算
- poi读取excel模板,填充内容并导出,支持导出2007支持公式自动计算
- poi读取excel模板,填充内容并导出,支持导出2007支持公式自动计算
- 简单封装POI导出excel
- 利用POI获取Excel中图片和图片位置(支持excel2003or2007多sheet)
- POI使用公式的问题,POI对excel函数的支持
- 利用poi.jar对excel进行读取、修改和删除
- TR里ABP用配方做选型的补充问题
- AngularJS实现购物车模糊查询,价格区间查找,根据名字删除,点击排序
- 计算一个三位数的各位之和
- The Largest Generation
- 排序算法(一) 冒泡排序
- poi导出excel,支持2007和2003,支持javabean,利用反射对poi进行简单封装,支持任意实体和乱序的excel表格
- Asp.net Core性能对比Asp.net .net Framework和Java Web Servlet
- zabbix-监控磁盘i/o
- 2015新生赛莲花池
- 51单片机实验2017年11月17日
- matlab中size,length,numel函数
- python_中文编码问题
- UGUI中按Tab切换InputField
- Ubuntu中root用户设置