使用Apache POI 读取Excel文件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Apache POI 读取Excel文件相关的知识,希望对你有一定的参考价值。

    生活中用到用到Excel文件的情况很多,什么商品进货单,产品维修单,餐厅的营业额等等。作为程序员,我们该如何读取Excel文件,获取我们想要的资源呢。本篇将讲解如何使用Apache POI读取Excel文件。

    准备工作:

    1)Apache POI 开发jar包

    2)Excel资源文件,包括Excel2003,Excel2007这两种版本分别对应xls、xlsx文件。

    本篇已经为您做好准备工作,请点击此处,下载资源文件,你也可以浏览Apace POI官网了解更多详细信息。

    简要流程:

    获取WorkBook实例- ->获取Sheet实例- ->获取Row实例- ->获取Cell实例- ->取得需要值- ->显示数据;

    因为不愿意写重复的代码,本篇用到了java反射的一些知识,如有读者不认同,请查看本文中给出官方链接进行学习。

    

package com.test.excel.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/*Excel文件读取工具类*/
public class ExcelReadUtil {
	/* 以键值对形式存储数据,这里使用LinkHashMap(可以记录添加顺序),若需要自定义比较器可以使用HashMap、HashTable */
	private LinkedHashMap<String, List<String>> map = new LinkedHashMap<String, List<String>>();
	/* 使用接口Workbook指向HSSFWorkbook子类或者XSSFWorkbook子类 */
	private Workbook workbook;

	/**
	 * 
	 * @param filePath文件路径
	 * @param rowIndex起始行
	 * @param colIndex起始列
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public void readExcel(String filePath, int rowIndex, int colIndex) throws FileNotFoundException, IOException {
		try {
			// 针对与Excel 2007及以上版本
			workbook = new XSSFWorkbook(new FileInputStream(new File(filePath)));
		} catch (Exception e) {
			// 针对Excel 2007一下版本
			workbook = new HSSFWorkbook(new FileInputStream(new File(filePath)));
		} finally {
			// 用于Method无参数的发射调用
			Class<?>[] noC = new Class<?>[] {};
			// 用于Method参数为Int的发射调用
			Class<?>[] intC = new Class<?>[] { int.class };
			// Method反射调用需要的空参数
			Object[] noO = new Object[] {};
			// 获取Sheet(Object是所有类直接或者间接父类,用Object指代反射生成的对象)
			Object sheet = ReflectMethodUtil.getObjectByAll(workbook, "getSheetAt", new Object[] { 0 }, intC);
			// 获取当前sheet的行数
			int rows = (int) ReflectMethodUtil.getObjectByAll(sheet, "getPhysicalNumberOfRows", noO, noC);
			// 用于指向Row对象,Cell对象
			Object row = null, col = null;
			// 获取Row、Cell的反射方法
			Method getRowMethod = null, getCellMethod = null;
			// 用于存储方法名
			String tmn = "";
			// 遍历Rows,获取Row
			for (int i = rowIndex; i < rows; i++) {
				if (getRowMethod == null) {
					// 使用Method.invoke()方法获取Row对象,并设置getRowMethod,以便于二次调用
					row = ReflectMethodUtil.getObjectByAll(sheet, "getRow", new Object[] { i }, intC);
					getRowMethod = ReflectMethodUtil.util.getMethod();
				} else {
					// getRowMethod不为空,直接使用Method.invoke()获取Row对象
					row = ReflectMethodUtil.getObjectWithoutPramTypes(getRowMethod, sheet, new Object[] { i });
				}
				// 若row为空,则跳过本次循环
				if (row == null) {
					continue;
				}
				// row不为空,获取Row的列数
				int cols = (int) ReflectMethodUtil.getObjectByAll(row, "getPhysicalNumberOfCells", noO, noC);
				// 用于存储获取到的值
				List<String> list = new ArrayList<String>();
				// 遍历Cell
				for (int j = colIndex; j < cols; j++) {
					String value = "";
					if (getCellMethod == null) {
						col = ReflectMethodUtil.getObjectByAll(row, "getCell", new Object[] { j }, intC);
						getCellMethod = ReflectMethodUtil.util.getMethod();
					} else {
						col = ReflectMethodUtil.getObjectWithoutPramTypes(getCellMethod, row, new Object[] { j });
					}
					if (col == null) {
						continue;
					}
					CellType type = (CellType) ReflectMethodUtil.getObjectByAll(col, "getCellTypeEnum", noO, noC);
					// 获取Cell的值,并转成String
					switch (type) {
					case FORMULA:
					case NUMERIC:
						tmn = "getNumericCellValue";
						value = (int) ((double) ReflectMethodUtil.getObjectByAll(col, tmn, noO, noC)) + "";
						break;
					case STRING:
						tmn = "getStringCellValue";
						value = (String) ReflectMethodUtil.getObjectByAll(col, tmn, noO, noC);
						break;
					default:
						break;
					}
					// 若value为空,跳过本次循环,不添加进List
					if (value.equals("")) {
						continue;
					}
					// 替换掉字符串中的换行符
					value = value.replaceAll("\n", "");
					list.add(value);
				}
				// 若list的长度为零,则跳过本次循环,不将list添加进LInkHashMap
				if (list.size() < 1) {
					continue;
				}
				map.put(list.get(0), list);
			}
		}

	}

	public static void main(String[] args) throws Exception {
		ExcelReadUtil util = new ExcelReadUtil();
		// util.readExcel("C:\\Users\\linYang\\Desktop\\20161223_095309.xlsx",
		// 3, 1);
		util.readExcel("C:\\Users\\linYang\\Desktop\\Excel练习文档.xls", 0, 0);
		for (Map.Entry<String, List<String>> entry : util.map.entrySet()) {
			List<String> list = entry.getValue();
			for (int i = 0, length = list.size(); i < length; i++) {
				System.out.print(list.get(i) + "\t");
				if (i == length - 1) {
					System.out.println();
				}
			}
		}
	}
}

/* 方法反射工具类 */
class ReflectMethodUtil {
	private Method method;// Method对象
	private Class<?> clazz;// 当前需要进行操作的类类型
	private Object object;// Method.invoke()参数

	public static ReflectMethodUtil util = null;

	public Method getMethod() {
		return method;
	}

	public void setMethod(Method method) {
		this.method = method;
	}

	public Class<?> getClazz() {
		return clazz;
	}

	public void setClazz(Class<?> clazz) {
		this.clazz = clazz;
	}

	public Object getObject() {
		return object;
	}

	public void setObject(Object object) {
		this.object = object;
	}

	/**
	 * @param clazz
	 * @param object
	 */
	public ReflectMethodUtil(Class<?> clazz, Object object) {
		super();
		this.clazz = clazz;
		this.object = object;
	}

	/**
	 * 
	 * @param methodName需要获取的Method的方法名
	 * @param parameterTypesMethod参数的类型数组
	 * @return
	 */
	public Method getMethodByName(String methodName, Class<?>... parameterTypes) {
		try {
			method = clazz.getMethod(methodName, parameterTypes);
		} catch (NoSuchMethodException | SecurityException e) {
			e.printStackTrace();
		}

		return method;
	}

	/**
	 * 
	 * @param paramters通过Object数组获取到Object
	 * @return
	 */
	public Object getObjectByMethodAndParamter(Object... paramters) {
		try {
			return method.invoke(this.object, paramters);
		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取Object
	 * 
	 * @param obj
	 * @param methodName
	 * @param paramters
	 * @param parameterTypes
	 * @return
	 */
	public static Object getObjectByAll(Object obj, String methodName, Object[] paramters, Class<?>... parameterTypes) {
		util = new ReflectMethodUtil(obj.getClass(), obj);
		util.method = util.getMethodByName(methodName, parameterTypes);
		return util.getObjectByMethodAndParamter(paramters);
	}

	/**
	 * 获取Object
	 * 
	 * @param method
	 * @param object
	 * @param paramters
	 * @return
	 */
	public static Object getObjectWithoutPramTypes(Method method, Object object, Object[] paramters) {
		try {
			return method.invoke(object, paramters);
		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

}

 

本文出自 “浅梦薄凉” 博客,请务必保留此出处http://lovexiaoyang.blog.51cto.com/10006124/1886483

以上是关于使用Apache POI 读取Excel文件的主要内容,如果未能解决你的问题,请参考以下文章

使用Apache POI 读取Excel文件

使用Apache POI读取Excel .XLSX时出错

Apache POI将txt文件读取为excel文件

java用poi读取excel文件时怎么获取每个单元格的列宽?

java通过apache poi框架读取2007版Excel文件

Apache POI 4.0.1版本读取普通Excel文件(兼容 xls 和 xlsx)