`
紫_色
  • 浏览: 144300 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

java 使用POI操作Excel(3)----基于对象操作Excel

    博客分类:
  • J2EE
阅读更多

        前两章介绍了POI对Excel的使用,对于java程序员来说,使用对象来操作Excel更符合要求.

        下面是一个用于测试的实体对象:

package gd.hz.poi.model;

import gd.hz.poi.annotation.ExcelSign;

import java.io.Serializable;
import java.util.Date;

/**
 * 用户Model
 * @author lfd 
 * 2013-12-09
 */
public class User implements Serializable {
	private static final long serialVersionUID = 1L;
	private int id ;
	private String name ;
	private int age ;
	private String sex ;
	private Date createDate ;
	private boolean hasVisible ;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	
	public Date getCreateDate() {
		return createDate;
	}
	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}
	
	public boolean isHasVisible() {
		return hasVisible;
	}
	public void setHasVisible(boolean hasVisible) {
		this.hasVisible = hasVisible;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		User other = (User) obj;
		if (id != other.id)
			return false;
		return true;
	}
	
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", age=" + age + ", sex="
				+ sex + ", createDate=" + createDate + ", hasVisible="
				+ hasVisible + "]";
	}
}

 

 一个对象就是Excel表中的一行,为了确定实体属性与Excel每一列之间的对应关系,写一个注解来标识:ExcelSign

package gd.hz.poi.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExcelSign {
	String title() ;  //记录每个字段在Excel中的标题
	int order() default 0 ;  //记录每个字段在Excel的排序
}

 将实体加上注解:

package gd.hz.poi.model;

import gd.hz.poi.annotation.ExcelSign;

import java.io.Serializable;
import java.util.Date;

/**
 * 用户Model
 * @author lfd 
 * 2013-12-09
 */
public class User implements Serializable {
	private static final long serialVersionUID = 1L;
	private int id ;
	private String name ;
	private int age ;
	private String sex ;
	private Date createDate ;
	private boolean hasVisible ;
	
	@ExcelSign(title="用户标记", order=10)
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	@ExcelSign(title="用户名称", order=9)
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	@ExcelSign(title="年龄", order=7)
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	@ExcelSign(title="性别", order=8)
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	
	@ExcelSign(title="日期")
	public Date getCreateDate() {
		return createDate;
	}
	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}
	
	@ExcelSign(title="是否在职")
	public boolean isHasVisible() {
		return hasVisible;
	}
	public void setHasVisible(boolean hasVisible) {
		this.hasVisible = hasVisible;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		User other = (User) obj;
		if (id != other.id)
			return false;
		return true;
	}
	
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", age=" + age + ", sex="
				+ sex + ", createDate=" + createDate + ", hasVisible="
				+ hasVisible + "]";
	}
}

 

以字符串的形式保存每个字段的名称,类型,在Excel中先后顺序和对应的标题.

package gd.hz.poi.util;

import java.lang.reflect.Type;

/**
 * Excel用户标题
 * @author lfd
 * 2013-12-10
 */
public class ExcelHeader implements Comparable<ExcelHeader> {
	private String methodName ;  //字段的方法名称(字符串形式,保存字段的getXXX方法)
	private String title ;      //字段在Excel中对应的标题
	private int order ;         //记录每个字段的先后顺序(越大越靠前)
	private Type type ;         //字段的类型
	
	public ExcelHeader() {}
	
	public ExcelHeader(String methodName, String title, int order, Type type) {
		this.methodName = methodName;
		this.title = title;
		this.order = order;
		this.type = type;
	}
	
	public String getMethodName() {
		return methodName;
	}
	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}

	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	
	public int getOrder() {
		return order;
	}
	public void setOrder(int order) {
		this.order = order;
	}

	public Type getType() {
		return type;
	}
	public void setType(Type type) {
		this.type = type;
	}

	/**
	 * 根据order进行排序
	 */
	@Override
	public int compareTo(ExcelHeader o) {
		return this.order > o.order ? -1 : (this.order < o.order ? 1 : 0) ;
	}
}

 

保存实体每个字段的基本信息:

/**
	 * 输出对象标题
	 * @param clazz Class
	 * @return List<ExcelHeader>
	 */
	private List<ExcelHeader> getHeader(Class<?> clazz) {
		Method[] methods = clazz.getDeclaredMethods() ;  //反射获取实体上的所有方法
		String name = null ;
		List<ExcelHeader> headers = new ArrayList<ExcelHeader>() ;
		for(Method method : methods) {
			name = method.getName() ; //实体对象的方法名称
			//过滤只剩下getXXX和isXXX
			if(name != null && (name.startsWith("get") || name.startsWith("is"))) {
				//getXXX和isXXX上是否有ExcelSign这个annotation
				if(method.isAnnotationPresent(ExcelSign.class)) {
					ExcelSign sign = method.getAnnotation(ExcelSign.class) ;  //获取方法上的ExcelSign注解
					//method.getGenericReturnType():获取getxxx获取isxxx上的返回类型
					ExcelHeader header = new ExcelHeader(name, sign.title(), sign.order(), method.getGenericReturnType()) ;
					headers.add(header) ; //保存到List中
				}
			}
		}
		Collections.sort(headers) ; //对List进行排序
		return headers ;
	}

  

 

将实体对象导出到Excel中:

 

/**
	 * 根据路径将数据填充到Excel表中. 
	 * @param path 路径
	 * @param clazz Class
	 * @param entitys 实体集合
	 * @param hasXLS true:为Excel 2003版本 false:为Excel 2007以上版本
	 * @return ExcelUtil
	 */
	public void export2Obj(String path, Class<?> clazz, List<?> entitys, boolean hasXLS) {
		Workbook workbook = export(clazz, entitys, hasXLS) ;
		OutputStream stream = null ;
		try {
			stream = new FileOutputStream(path) ;
			workbook.write(stream) ;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(stream != null) {
					stream.close() ;
					stream = null ;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	private Workbook export(Class<?> clazz, List<?> entitys, boolean hasXLS) {
		Workbook workbook = null ;
		if(hasXLS) {
			workbook = new HSSFWorkbook() ;
		} else {
			workbook = new XSSFWorkbook() ;
		}
		try {
			Sheet sheet = workbook.createSheet() ;
			
			//输出标题
			List<ExcelHeader> headers = getHeader(clazz) ;
			Row row = sheet.createRow(0) ;
			int count = headers.size() ;
			for(int i=0; i<count; i++) {
				Cell cell = row.createCell(i) ;
				cell.setCellValue(headers.get(i).getTitle()) ;
			}
			
			//输出数据
			int number = entitys.size() ;
			Method method = null ;
			for(int i=0; i<number; i++) {
				row = sheet.createRow(i+1) ;
				Object obj = entitys.get(i) ;
				for(int j=0; j<count; j++) {
					method = clazz.getDeclaredMethod(headers.get(j).getMethodName()) ; //反射获取实体上的指定方法(根据方法的字符串名称)
					Cell cell = row.createCell(j) ;
					String type = headers.get(j).getType().toString() ; //字符串的形式输出实体每个字段的类型.
					//method.invoke(obj):获取调用方法(根据方法的getxxx)
					if(type.equals("class java.util.Date")) {
						cell.setCellValue((Date)method.invoke(obj)) ;
					} else if(type.equals("class java.lang.Boolean") || type.equals("boolean")) {
						cell.setCellValue((Boolean)method.invoke(obj)) ;
					} else if(type.equals("class java.lang.Integer") || type.equals("int")) {
						cell.setCellValue((Integer)method.invoke(obj)) ;
					} else if(type.equals("class java.lang.Double") || type.equals("double")) {
						cell.setCellValue((Double)method.invoke(obj)) ;
					} else if(type.equals("class java.util.Calendar")) {
						cell.setCellValue((Calendar)method.invoke(obj)) ;
					} else {
						cell.setCellValue((String)method.invoke(obj)) ;
					}
				}
			}
			
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} 
		return workbook ;
	}

 测试:

@Test
	public void testExport2Obj() {
		List<User> users = new ArrayList<User>() ;
		User user = null ;
		for(int i=0; i<20; i++) {
			user = new User() ;
			user.setId(i) ;
			user.setAge(i) ;
			user.setCreateDate(new Date()) ;
			user.setHasVisible(true) ;
			user.setName("lfdlfdlfkdlfklfkdlfdsk" + i) ;
			user.setSex("男") ;
			users.add(user) ;
		}
		
		//数据输出到D:/Download目录下.
		export2Obj("D:/Download/lfd.xls", User.class, users, false) ;
 	}

 

将Excel的数据转换成实体对象:
首先要获取Excel每一列与实体属性的对应关系:
/**
	 * 读取模板头信息(标题信息)
	 */
	private Map<Integer, ExcelHeader> readHeader(Row row, Class<?> clazz) {
		List<ExcelHeader> headers = getHeader(clazz) ;
		Map<Integer, ExcelHeader> headerMap = new LinkedHashMap<Integer, ExcelHeader>() ;
		String value = null ;
		for(Cell cell : row) {
			if(cell.getCellType() != Cell.CELL_TYPE_STRING) continue ;
			value = cell.getStringCellValue().trim() ;
			for(ExcelHeader header : headers) {
				if(header.getTitle().equals(value)) {
					headerMap.put(cell.getColumnIndex(), header) ;
					break ;
				}
			}
		}
		return headerMap ;
	}
 
转换成实体对象:
/**
	 * 数据所在的位置
	 * @param path Excel所在的位置
	 * @param clazz Class
	 * @param startLine 标题所在行(从1开始,startLine-1为标题行,startLine为数据开始行)
	 * @param tailLine 不是数据所占的行数
	 * @param hasClasspath true:路径为classpath false:path为绝对路径
	 * @return 数据
	 */
	public <T> List<T> readExcel2Obj(String path, Class<T> clazz, int startLine, int tailLine, boolean hasClasspath) {
		Workbook workbook = null ;
		InputStream stream = null ;
		List<T> entitys = null ;
		try {
			if(hasClasspath) {
				if(path != null && !path.startsWith("/")) {
					path = new StringBuffer(path).insert(0, "/").toString() ;
				}
				stream = ExcelTemplate.class.getResourceAsStream(path) ;
				workbook = WorkbookFactory.create(stream) ;
			} else {
				workbook = WorkbookFactory.create(new File(path)) ;
			}
			entitys = getEntitys(workbook, clazz, startLine, tailLine) ;
		} catch (InvalidFormatException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} finally {
			try {
				if(stream != null) {
					stream.close() ;
					stream = null ;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return entitys ;
	}
	
	/**
	 * 将数据转换成实体
	 * @param workbook Workbook
	 * @param clazz Class
	 * @param startLine 标题所在行(从1开始,startLine-1为标题行,startLine为数据开始行)
	 * @param tailLine 不是数据所占的行数
	 * @return
	 */
	private <T> List<T> getEntitys(Workbook workbook, Class<T> clazz, int startLine, int tailLine) {
		List<T> entitys = null ;
		Sheet sheet = workbook.getSheetAt(0) ;
		//读取标题,这里输入标题行是从1开始不是从0开始所以startLine - 1
		Map<Integer, ExcelHeader> headers = readHeader(sheet.getRow(startLine - 1), clazz) ;
		int end = sheet.getLastRowNum() - tailLine ; 
		entitys = new ArrayList<T>() ;
		String type = null ;
		try {
			for(int i=startLine; i<end; i++) {
				Row row = sheet.getRow(i) ;
				T entity = clazz.newInstance() ; //反射new对象(要有空的构造方法)
				for(Cell cell : row) {
					ExcelHeader header = headers.get(cell.getColumnIndex()) ; //根据readHeader方法的映射关系获取对应的实体属性关系
					if(header != null) {
						String methodName = header.getMethodName() ;  //实体对象的字段属性名称
						//替换成setxxx方法
						if(methodName.startsWith("is")) {
							methodName = methodName.replaceFirst("is", "set") ;
						} else {
							methodName = methodName.replaceFirst("get", "set") ;
						}
						type = header.getType().toString() ;
						Method method = clazz.getDeclaredMethod(methodName, getFieldType(type)) ;
						if(type.equals("class java.util.Date")) {
							method.invoke(entity, cell.getDateCellValue()) ;
						} else if(type.equals("class java.lang.Boolean") || type.equals("boolean")) {
							method.invoke(entity, cell.getBooleanCellValue()) ;
						} else if(type.equals("class java.lang.Integer") || type.equals("int")) {
							method.invoke(entity, (int)cell.getNumericCellValue()) ;
						} else if(type.equals("class java.lang.Double") || type.equals("double")) {
							method.invoke(entity, cell.getNumericCellValue()) ;
						} else if(type.equals("class java.util.Calendar")) {
							Calendar calendar =  Calendar.getInstance() ;
							calendar.setTime(cell.getDateCellValue()) ;
							method.invoke(entity, calendar) ;
						} else {
							method.invoke(entity, cell.getStringCellValue()) ;
						}
					}
				}
				entitys.add(entity) ;
			}
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return entitys ;
	}
	
	/**
	 * 获取对象字段的类型Class
	 * @param type
	 * @return
	 */
	private Class<?> getFieldType(String type) {
		if(type.equals("class java.util.Date")) {
			return Date.class ;
		} else if(type.equals("class java.lang.Boolean")) {
			return Boolean.class ;
		} else if(type.equals("boolean")) {
			return Boolean.TYPE ;
		} else if(type.equals("class java.lang.Integer")) {
			return Integer.class ;
		} else if(type.equals("int")) {
			return Integer.TYPE ;
		} else if(type.equals("class java.lang.Double")) {
			return Double.class ;
		} else if(type.equals("double")) {
			return Double.TYPE ;
		} else if(type.equals("class java.util.Calendar")) {
			return Calendar.class ;
		}
		return String.class ;
	}
 测试:
@Test
	public void testReadExcel2Obj() {
		List<User> users = readExcel2Obj("D:/Download/lfd.xls", User.class, 1, 2, false) ;
		for(User user : users) {
			System.out.println(user);
		}
	}
 
下面是上述例子的封装例子,包括使用模板输出数据(基于Maven项目):
分享到:
评论
1 楼 pengshuangbao520 2014-02-24  
写的真的不错 ,各种模式,各种思想,通俗的语言,精炼的代码,佩服!

相关推荐

    java使用poi操作excel需要的所有jar包(poi3.8版本)

    java使用poi操作excel需要的所有jar包(poi3.8版本),里面有poi-3.8-20120326.jar、poi-ooxml-3.8-20120326.jar、poi-ooxml-schemas-3.8-20120326.jar、dom4j-1.6.1.jar、xmlbeans-2.3.0.jar

    Java开发案例-springboot-52-POI导出Excel-源代码+文档.rar

    Java开发案例-springboot-52-POI导出Excel-源代码+文档.rar Java开发案例-springboot-52-POI导出Excel-源代码+文档.rar Java开发案例-springboot-52-POI导出Excel-源代码+文档.rar Java开发案例-springboot-52-POI...

    java使用POI导出 Excel工具类

    java使用POI导出 Excel+图片工具类 ,里面含有poi jar包,只调用接口即可直接保存Excel。使用的时候需先把数据封装,具体包装需根据实际导出数据进行处理。文件demo中只提供包装格式。

    poi全家桶ooxml-schemas/poi/poi-examples/poi-ooxml/poi-ooxml-schemas/poi-scratchpad

    3. **poi-examples**: 这个目录包含了一系列的示例代码,展示了如何使用Apache POI库进行实际操作。开发者可以通过这些例子学习如何创建、读取和修改Excel、Word和PowerPoint文档。 4. **poi-ooxml**: 这个模块专注...

    java_poi实现excel导入导出

    要使用 Java POI 实现 Excel 导出,需要首先创建一个 HSSFWorkbook 或 XSSFWorkbook 对象,然后使用该对象创建一个工作表。下面是一个简单的示例: ```java import org.apache.poi.hssf.usermodel.HSSFWorkbook; ...

    java excel操作 poi-3.17 可用于jdk1.70

    附件是java poi 3.17的lib库及其依赖库,全部下载引用后,可以进行excel的读写操作,无需引用其他lib库。poi-3.17适用于jdk1.7。 Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft ...

    POI操作Excel----------(转人家的)

    POI的实现基于MVC(Model-View-Controller)设计模式,其中Record对象对应于Excel文件中的低级别记录,而上述的HSSF类则代表模型和视图。HSSFWorkbook和HSSFSheet等类通过log机制(如Apache Log4J的POILogger)提供...

    Java 使用poi导入excel 并使用xml做数据验证

    Apache POI是一个流行的库,它允许开发者使用Java来读取、写入和修改Microsoft Office格式的文件,包括Excel(.xlsx, .xls)。在本项目中,我们结合了POI库和XML技术来实现Excel数据的验证与导入数据库。 首先,...

    java-poi-excel-导出20万条记录

    java-poi-excel-导出20万条记录

    poi-3.9、poi-ooxml-3.9、poi-ooxml-schemas-3.9

    总结来说,Apache POI 是Java开发中处理Excel文件的强大工具,它提供了全面的API来操作Excel的各种特性。结合 poi-3.9.jar、poi-ooxml-3.9.jar 和 poi-ooxml-schemas-3.9.jar 这三个库,开发者可以构建出功能丰富的...

    java 通过poi操作excel jar包

    标题中的"java通过poi操作excel jar包"指的是使用Apache POI库来处理Excel文件的Java程序,通常需要引入特定版本的POI JAR包。在这个案例中,我们有两个版本的JAR包可供使用:poi_3.17.jar和poi_3.15.jar。这些版本...

    java使用POI操作excel (支持excel2007)

    Java 使用Apache POI库操作Excel 2007文件详解 在Java开发中,处理Excel文件是一项常见的任务,特别是对于数据分析、数据导入导出或报表生成等场景。Apache POI是一个流行的开源库,它允许开发者读写Microsoft ...

    java导出内容为excel poi-3.0.2-FINAL-20080204.jar

    3. **行(Row)**:工作表中每一行数据由`Row`对象表示,使用`createRow(int rowIndex)`方法创建。 4. **单元格(Cell)**:行中的每一个单元格由`Cell`对象表示,通过`createCell(int columnIndex)`方法创建。...

    java的poi生成excel图表demo

    Java的Apache POI库是一个强大的工具,用于读取、创建和修改Microsoft Office格式的文件,尤其是Excel(.xlsx)文档。在本示例中,我们将深入探讨如何利用POI库来生成Excel中的图表曲线,这对于数据可视化和报告生成...

    poi-3.12-android-a.jar和poi-ooxml-schemas-3.12-20150511-a.jar

    Apache POI是一个流行的Java库,允许程序员创建、修改和显示MS Office文件,包括Excel工作簿。这个特定的.jar文件包含了基本的功能以支持.xls格式的Excel文件操作。 poi-ooxml-schemas-3.12-20150511-a.jar: 这个库...

    java使用poi操作excel

    Java 使用 Apache POI 操作 Excel 是一种常见的数据处理方式,特别是在大数据分析、报表生成和数据导入导出等场景中。Apache POI 是一个开源库,它允许 Java 开发者读写 Microsoft Office 格式,包括 Excel(.xlsx ...

    java poi 操作Excel

    下面将详细介绍如何使用Java POI来操作Excel以及相关的知识点。 1. **基本概念** - HSSF(Horrible Spreadsheet Format):这是POI库处理Excel 97-2003(.xls)格式的部分。HSSF提供了一套API,可以创建、修改和...

    Java Poi 操作excel的API 好用

    二、Java POI操作Excel的核心功能 1. 创建新的Excel工作簿 使用`WorkbookFactory.create()`方法可以创建一个新的Excel工作簿对象,然后通过工作簿对象创建工作表。 2. 读取Excel工作簿 同样,使用`WorkbookFactory....

    java+poi+excel读取写入等操作所有jar(最新支持excel2013)+poi-bin-3.10-beta2-20130904源代码学习

    在Java中,使用POI库可以实现对Excel文件的读取、写入以及修改等操作,这对于数据分析、报表生成、自动化测试等场景非常实用。在你提到的资源中,"javaYdmxx80.zip"很可能包含了进行这些操作所需的jar文件,这些文件...

    java-poi-excel-导出20万条记录【源代码】

    本示例“java-poi-excel-导出20万条记录【源代码】”展示了如何使用Apache POI库来高效地处理大数据量的Excel导出,避免内存溢出的问题。Apache POI是一个流行的开源Java API,用于读写Microsoft Office格式的文件,...

Global site tag (gtag.js) - Google Analytics