excel导出导入(poi+反射+注解)

本文介绍如何通过自定义注解实现Java实体类与Excel文件的自动映射,包括注解定义、实体类设计及Excel读写工具类的实现。
描述:使用注解建立实体与excel之间的映射关系,反射设置实体属性值

一、jar包
二、定义注解
三、定义测试实体
四、封装excel工具类

#一、jar包

poi-3.17.jar
poi-excelant-3.17.jar
poi-ooxml-3.17.jar
poi-ooxml-schemas-3.17.jar

maven导入

<!-- poi-ooxml自动引入操作xlsx文件所用到的其他包 -->
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>3.15-beta2</version>
		</dependency>

#二、定义注解

定义该注解作用:主要用来描述属性存在excel中的第几列,列名是什么。目的是与excel建立关系。


/**
 * 定义excel描述注解
 * @author YZQ
 *
 */

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

	/**
	 * 列索引
	 * @return
	 */
	public int columnIndex() default 0;
	
	/**
	 * 列名
	 * @return
	 */
	public String columnName() default "";
	
}

#三、定义测试实体

public class ExcelEntity {
	
	public ExcelEntity() {
	}
	
	public ExcelEntity(int id, String name) {
		this.id = id;
		this.name = name;
	}
	//描述改属性在excel中第0列,列名为  序号
	@MyAnnotation(columnIndex=0,columnName="序号")
	private int id;
	
	//描述改属性在excel中第1列,列宁为 名字
	@MyAnnotation(columnIndex=1,columnName="名字")
	private String name;
	
	
	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;
	}

	@Override
	public String toString() {
		return "ExcelEntity [id=" + id + ", name=" + name + "]";
	}
}

#四、封装excel工具类
##excel导出(注释很详细,不解释)

/**
	 * 输出excel文件
	 * @param data 数据集合
	 * @param path 输出路径
	 */
	public static void outExcelFile(List<?> data, String path) {

		File file = new File(path);

		// 创建workbook
		HSSFWorkbook wb = new HSSFWorkbook();

		// 创建sheet
		Sheet sheet = wb.createSheet("sheel");

		// 创建表头行
		Row row = sheet.createRow(0);

		// 创建单元格样式
		HSSFCellStyle style = wb.createCellStyle();
		// 居中显示
		style.setAlignment(HorizontalAlignment.CENTER);

		// 获取实体所有属性
		Field[] fields = data.get(0).getClass().getDeclaredFields();
		// 列索引
		int index = 0;
		// 列名称
		String name = "";
		MyAnnotation myAnnotation;
		
		// 创建表头
		for (Field f : fields) {
			// 是否是注解
			if (f.isAnnotationPresent(MyAnnotation.class)) {
				// 获取注解
				myAnnotation = f.getAnnotation(MyAnnotation.class);
				// 获取列索引
				index = myAnnotation.columnIndex();
				// 列名称
				name = myAnnotation.columnName();
				// 创建单元格
				creCell(row, index, name, style);
			}
		}

		// 行索引  因为表头已经设置,索引行索引从1开始
		int rowIndex = 1;
		for (Object obj : data) {
			// 创建新行,索引加1,为创建下一行做准备
			row = sheet.createRow(rowIndex++);
			for (Field f : fields) {
				// 设置属性可访问
				f.setAccessible(true);
				// 判断是否是注解
				if (f.isAnnotationPresent(MyAnnotation.class)) {
					// 获取注解
					myAnnotation = f.getAnnotation(MyAnnotation.class);
					// 获取列索引
					index = myAnnotation.columnIndex();
					try {
						// 创建单元格     f.get(obj)从obj对象中获取值设置到单元格中
						creCell(row, index, String.valueOf(f.get(obj)), style);
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					}
				}
			}
		}

		FileOutputStream outputStream = null;
		try {
			outputStream = new FileOutputStream(file);
			wb.write(outputStream);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			//释放资源
			try {
				if (wb != null) {
					try {
						wb.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if (outputStream != null) {
					outputStream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

#excel导入(注释很详细,不解释)

/**
	 * 读取excel文件,并把读取到的数据封装到clazz中
	 * 
	 * @param path
	 *            文件路径
	 * @param clazz
	 *            实体类
	 * @return 返回clazz集合
	 */
	public static <T extends Object> List<T> readExcelFile(String path, Class<T> clazz) {
		// 存储excel数据
		List<T> list = new ArrayList<>();
		FileInputStream is = null;

		try {
			is = new FileInputStream(new File(path));
		} catch (FileNotFoundException e1) {
			throw new RuntimeException("文件路径异常");
		}

		Workbook wookbook = null;

		// 根据excel文件版本获取工作簿
		if (path.endsWith(".xls")) {
			wookbook = xls(is);
		} else if (path.endsWith(".xlsx")) {
			wookbook = xlsx(is);
		} else {
			throw new RuntimeException("文件出错,非excel文件");
		}

		// 得到一个工作表
		Sheet sheet = wookbook.getSheetAt(0);

		// 获取行总数
		int rows = sheet.getLastRowNum() + 1;

		Row row;

		// 获取类所有属性
		Field[] fields = clazz.getDeclaredFields();

		T obj = null;
		int coumnIndex = 0;
		Cell cell = null;
		MyAnnotation myAnnotation = null;
		for (int i = 1; i < rows; i++) {
			// 获取excel行
			row = sheet.getRow(i);
			try {
				// 创建实体
				obj = clazz.newInstance();
				for (Field f : fields) {
					// 设置属性可访问
					f.setAccessible(true);
					// 判断是否是注解
					if (f.isAnnotationPresent(MyAnnotation.class)) {
						// 获取注解
						myAnnotation = f.getAnnotation(MyAnnotation.class);
						// 获取列索引
						coumnIndex = myAnnotation.columnIndex();
						// 获取单元格
						cell = row.getCell(coumnIndex);
						// 设置属性
						setFieldValue(obj, f, wookbook, cell);
					}
				}
				// 添加到集合中
				list.add(obj);
			} catch (InstantiationException e1) {
				e1.printStackTrace();
			} catch (IllegalAccessException e1) {
				e1.printStackTrace();
			}

		}

		try {
			//释放资源
			wookbook.close();
			is.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return list;
	}

设置属性值
这里只写部分,按自己需要自行添加

	/**
	 * 设置属性值
	 * 
	 * @param obj
	 *            操作对象
	 * @param f
	 *            对象属性
	 * @param cell
	 *            excel单元格
	 */
	private static void setFieldValue(Object obj, Field f, Workbook wookbook, Cell cell) {
		try {
			if (f.getType() == int.class || f.getType() == Integer.class) {
				f.setInt(obj, getInt(cell));
			} else if (f.getType() == Double.class || f.getType() == double.class) {
				f.setDouble(obj, getDouble(null, cell));
			} else {
				f.set(obj, getString(cell));
			}
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
	}

excel版本处理


	/**
	 * 对excel 2003处理
	 */
	private static Workbook xls(InputStream is) {
		try {
			// 得到工作簿
			return new HSSFWorkbook(is);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 对excel 2007处理
	 */
	private static Workbook xlsx(InputStream is) {
		try {
			// 得到工作簿
			return new XSSFWorkbook(is);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

剩下的是一些单元格创建、获取单元格值

/**
	 * 创建单元格
	 * 
	 * @param row
	 * @param c
	 * @param cellValue
	 * @param style
	 */
	private static void creCell(Row row, int c, String cellValue, CellStyle style) {
		Cell cell = row.createCell(c);
		cell.setCellValue(cellValue);
		cell.setCellStyle(style);
	}

测试效果:
这里写图片描述

生成文件
这里写图片描述

这里写图片描述

补充:

注解MyAnnotation的columnIndex其实可以通过ASCII将列序号A,B,C,D转换成对应的0,1,2,3
代码:

	private static int convertToColumnIndex(String columnCode) {
		int begin = 'A';

		int char0Index = columnCode.charAt(0);
		int endIndex = char0Index - begin;

		if (columnCode.length() > 1) {
			// 只考虑A-ZZ之间。超出再扩展 ,按理不会超出,总有26*27=702列
			int char1Index = columnCode.charAt(1);
			return char1Index + (26 * (endIndex + 1)) - begin;
		}
		return endIndex;

	}

源代码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值