最近项目频繁使用到Java对Excel的操作,在项目中使用到POI,下面实现了对Excel读和写,都是通过反射的方式实现,这样就更具有通用的效果了。需要注意的是将一个类的数据写入到Excel中,那么类中的属性要与Excel中的标题一一对应,比如:Excel标题的顺序是姓名、年龄、住址,那么类中的属性名也要是姓名、年龄、住址这个顺序。当然这是要Excel有标题的时候,如果没有标题,那么类中的属性顺序就无所谓了。使用到POI呢,最基本的就是要下载POI,下载链接为:http://poi.apache.org/download.html,接下来进入正题,如下:
写入Excel文件:
/**
* 创建Excel
* @param fileName 文件名称
* @param title Excel工作簿标题
* @param headers 表格头标题
* @param dataList 要写入的数据
*/
public static <T> void createExcel(String fileName,String title,String[] headers,List<T> dataList){
//创建文件输出流
FileOutputStream out=null;
try {
out=new FileOutputStream(getFile(fileName));
//创建HSSFWorkbook
HSSFWorkbook workbook=new HSSFWorkbook();
//创建HSSFSheet
HSSFSheet sheet=workbook.createSheet(title);
//创建标题行
HSSFRow titleRow=sheet.createRow(0);
//设置行高
titleRow.setHeight((short)400);
//根据Workbook创建列样式
HSSFCellStyle cellStyle=workbook.createCellStyle();
//上下居中
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
//遍历标题
for(int i=0;i<headers.length;i++){
//设置列宽
sheet.setColumnWidth(i, 20*150);
//创建列
HSSFCell cell=titleRow.createCell(i);
//设置列值
cell.setCellValue(headers[i]);
//设置样式
cell.setCellStyle(cellStyle);
}
//处理数据行
for(int i=0;i<dataList.size();i++){
//创建数据行
HSSFRow dataRow=sheet.createRow(i+1);
//获取Class对象
Class clazz=dataList.get(i).getClass();
//获取对象中的所有字段
Field[] fields=clazz.getDeclaredFields();
for(int j=0;j<headers.length;j++){
//创建列
HSSFCell cell=dataRow.createCell(j);
//获取属性名称
String fieldName=fields[j+2].getName();
//获取方法名称
String methodName="get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
//获取方法
Method method=clazz.getDeclaredMethod(methodName, new Class[]{});
//获取值
Object value=method.invoke(dataList.get(i), new Object[]{});
//根据值类型设置单元格值
if(null==value||"".equals(value)){
cell.setCellValue("");
}else if(value instanceof Integer){
cell.setCellType(Cell.CELL_TYPE_NUMERIC);//数字单元格
cell.setCellValue(Integer.valueOf(value.toString()));
}else if(value instanceof BigDecimal){
cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00"));
cell.setCellStyle(cellStyle);
cell.setCellValue(value.toString());
}else if(value instanceof Date){
cellStyle.setDataFormat(workbook.createDataFormat().getFormat("yyyy-MM-dd"));
cell.setCellStyle(cellStyle);
cell.setCellValue((Date) value);
}else{
cell.setCellValue(value.toString());
}
}
}
//写入到文件中
workbook.write(out);
} catch (Exception e) {
e.printStackTrace();
}finally{
//关闭流对象
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
读取Excel文件:
/**
* 读取Excel
* @param clazz 将Excel数据读取到对应的Java类
* @param fileName 文件名
* @return
*/
public static <T> List<T> readExcel(Class<T> clazz,String fileName){
//获取文件
File file=getFile(fileName);
//创建数据集合
List<T> list=new ArrayList<T>();
//声明输入流对象
FileInputStream input=null;
try {
//创建输入流对象
input=new FileInputStream(file);
//创建Workbook
HSSFWorkbook workbook=new HSSFWorkbook(input);
//创建Sheet
HSSFSheet sheet=workbook.getSheetAt(0);
for(int i=1;i<=sheet.getLastRowNum();i++){
//获取行
HSSFRow row=sheet.getRow(i);
//实例化对象
T t=clazz.newInstance();
//获取传入对象的所有字段
Field[] fields=clazz.getDeclaredFields();
for(int j=0;j<row.getLastCellNum();j++){
Field field=fields[j+2];//获取Field对象
field.setAccessible(true);//设置属性可访问
//获取字段类型
String type=field.getType().toString();
//根据类型设置值
if(type.endsWith("String")){
field.set(t, row.getCell(j).getStringCellValue());
}else if(type.endsWith("Integer")){
field.set(t, ((Double)row.getCell(j).getNumericCellValue()).intValue());
}else if(type.endsWith("Double")){
field.set(t, (row.getCell(j).getNumericCellValue()));
}else if(type.endsWith("Date")){
field.set(t, row.getCell(j).getDateCellValue());
}
field.setAccessible(false);
}
//添加到集合
list.add(t);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//关闭流对象
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return list;
}
创建文件:
/**
* 获取文件
* @param fileName 文件名称
* @return
*/
private static File getFile(String fileName){
boolean flg1=false;
//文件路径
String filePath=getCurrentPath();
File dir=new File(filePath);
File file=null;
//如果目录不存在,则创建
if(!dir.exists()){
flg1=dir.mkdirs();
//生成目录失败
if(!flg1){
System.out.println("目录生成失败!");
}
}else{
file = new File(dir + File.separator + fileName);
//判断文件是否存在
if (!file.exists()) {
try {
//创建文件
file.createNewFile();
}
catch (IOException e) {
System.out.println("文件创建失败!");
}
}
return file;
}
return file;
}
测试读写Excel文件:
String[] headers={"姓名","年龄","联系电话","居住地址","出生日期"};
//数据准备
List<Student> dataList=new ArrayList<Student>();
dataList.add(new Student(1,"张三", 23, "110", "东风东路", new Date()));
dataList.add(new Student(2,"张三1", 23, "110", "东风东路", new Date()));
dataList.add(new Student(3,"张三2", 23, "110", "东风东路", new Date()));
dataList.add(new Student(4,"张三3", 23, "110", "东风东路", new Date()));
dataList.add(new Student(5,"张三4", 23, "110", "东风东路", new Date()));
//createFile("学生信息表");
String fileName="学生信息表"+System.currentTimeMillis()+".xls";
//写入Excel文件
ExcelHandlerUtil.createExcel(fileName,"学生信息",headers, dataList);
//读取Excel文件
List<Student> list=ExcelHandlerUtil.readExcel(Student.class,"学生信息表1445676251183.xls");
for (Student student : list) {
System.out.println(student.getName()+"\t"+student.getBirthday());
}
需要说明一点,在读写Excel的方法中,在获取属性Field对象时是这样的
Field field=fields[j+2];//获取Field对象
是因为在实体中是要从name开始读取或设置值,因为第一个和第二个属性是serialVersionUID、id,如果没有这两个就不用加2,如果只有一个就加1,下面是实体:
public class Student implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer id;
private String name;//姓名
private Integer age;//年龄
private String telephone;//联系电话
private String address;//居住地址
private Date birthday;//出生日期
public Student() {
super();
}
public Student(Integer id,String name, Integer age, String telephone, String address,
Date birthday) {
super();
this.id=id;
this.name = name;
this.age = age;
this.telephone = telephone;
this.address = address;
this.birthday = birthday;
}
}
省略get和set方法,因为写入和读取都用到的是反射实现,所以就不是针对某一个实体,可以是任何实体,只要对应好关系即可。
源代码下载