Java 通过 POI 读取 Excel 文件数据

目录

术语

目的

技术

实现过程

实现的代码

验证程序


术语

术语

说明

工作簿

Excel 文件

工作表

Excel 文件中的 Sheet 表格

xls

xls 格式的Excel 文件,Excel 2003及以前使用的 Excel 文件格式

xlsx

xlsx 格式的 Excel 文件,Excel 2007 及以后使用的 Excel 文件格式

目的

根据 Excel 文件的路径获取到 Excel 文件中的数据。

技术

使用 Apache 组织下 POI 项目对 Excel 文件进行读取操作,本次主要使用到的接口和类如下表所示:

名称

类型

说明

WorkBookFactory

创建合适的工作簿(HSSFWorkBook或XSSFWorkBook),根据文件输入流自动检测。

HSSFWorkBook

创建xls 格式的工作簿,Excel 2003 及其以前使用的格式。

XSSFWorkBook

创建 xlsx 格式的工作簿,Excel 2007 及其以后使用的格式。

WorkBook

接口

工作簿接口

Sheet

接口

工作表接口

Row

接口

行接口

Cell

接口

单元格接口

如需更多关于 POI 项目下的接口和类的详细文档,请参考官方文档:http://poi.apache.org/apidocs/index.html?overview-summary.html

读取 xls 格式文件需要用到的 jar 包:

读取 xls 格式文件时需要的 jar 文件

读取 xlsx 格式文件需要用到的 jar 包:

Java 通过 POI 读取 Excel 文件数据_第1张图片 读取 xlsx 格式文件时需要的 jar 文件

POI 项目使用到的 jar 包官方下载地址:http://poi.apache.org/download.html

实现过程

  1. 如果指定的工作表位置小于1,则默认设置为1;
  2. 判断文件路径是否正确或是不是 Excel 文件(以 .xls 或 .xlsx 结尾的文件),如果判断失败,程序结束;
  3. 如果判断成功,创建工作簿,根据文件输入流自动检测创建工作簿类型;
  4. 判断是否为指定工作表,如果是只读取指定工作表的数据,如果不是读取工作簿中所有工作表数据;
  5. 判断指定工作表位置在工作簿中是否存在,存在读取指定工作表的数据,不存在则读取工作簿最后一张工作表的数据;
  6. 工作表中添加工作表的名称;

如果工作表不止一行数据,工作表的总列数取第一行和第二行中最大的列数,注意:工作表中第一行或第二行的列数必须和工作表的总列数相同

实现的代码

package cn.bc.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.ss.usermodel.Cell;
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;

/**
 * 
 * @ClassName: cn.bc.util.ExcelUtil
 * 
 * @Description: 读取 Excel 工作表数据
 * xls 格式是 Excel 2003及其以前版本使用的格式
 * xlsx 格式是 Excel 2007及其以后版本使用的格式
 * 工作簿表示整个 Excel 文件,工作表表示 Excel 文件中的 Sheet 表
 * 注意:   1、Excel 文件中工作表的第一行不能为空;
 * 		2、如果 Excel 文件中工作表除第一行外还有其它数据时,第二行也不能为空;
 * 		3、Excel 文件中工作表的第一行或第二行的列数必须是整个工作表的总列数
 *
 * @author 17bc8
 * @date: 2019年8月10日
 *
 * @Copyright: 2019 www.17bc8.cn
 */
public class ExcelUtil {

	private static Log log = LogFactory.getLog(ExcelUtil.class);
	
	/**
	 * 
	 * @Title: validExxel
	 * 
	 * @Description: 验证文件是不是 Excel 文件
	 * 
	 * @param path 文件的路径
	 * @return 是:true;不是:false
	 */
	private static Boolean validExxel (String path) {
		String xls = "^.+\\.(?i)(xls)$";	// 正则表达式判断是不是以 .xls 结尾的文件
		String xlsx = "^.+\\.(?i)(xlsx)$";	// 正则表达式判断是不是以 .xlsx 结尾的文件
		if (path == null || !(path.matches(xls) || path.matches(xlsx))) {
			log.error("@!--------------------不是Excel文件!");
			return false;
		}
		return true;
	}
	
	/**
	 * 
	 * @Title: readExcel
	 * 
	 * @Description: 读取 Excel 文件的数据
	 * 
	 * @param path 文件的路径
	 * @param isSheetIndex 是否指定工作表(Sheet)
	 * @param sheetIndex 指定工作表在工作簿中的位置
	 *  1、如果 isSheetIndex 为 true 时,sheetIndex 为大于0的整数
	 *  	1.1、如果 sheetIndex 小于等于 0,默认读取工作簿中的第一张工作表;
	 *  	1.2、如果 sheetIndex 大于工作簿中工作表的总数,默认读取工作簿中最后一张工作表;
	 *  2、如果 isSheetIndex 为 false 时,sheetIndex 可以是任何整数,此时读取工作簿中所有工作表的数据
	 * @return Excel Excel 文件的数据集
	 */
	public static List readExcel (String path, Boolean isSheetIndex, Integer sheetIndex) {
		// 指定工作表位置小于1时,默认读取第一张工作表的数据
		if (sheetIndex < 1) {
			sheetIndex = 1;
		}
		List dataList = new ArrayList<>();
		InputStream is = null;
		// 通过指定的文件路径创建文件对象
		File file = new File (path);
		if (file == null || !file.exists()) {
			log.error("@!--------------------文件不存在!");
			return null;
		}
		if (!validExxel(path)) {
			log.error("@!--------------------此文件不是 Excel 文件!");
			return null;
		}
		try {
			is = new FileInputStream(file);	// 获取文件的输入流
			dataList = readFile (is, isSheetIndex, sheetIndex-1);
		} catch (FileNotFoundException e) {
			log.error("@!--------------------找不到该文件!");
		} finally {
			if (is != null) {
				try {
					is.close();	// 关闭文件输入流
				} catch (IOException e) {
					log.error("@!-----------------------------文件输入流关闭失败!");
				}
			}
		}
		return dataList;
	}
	
	/**
	 * 
	 * @Title: readFile
	 * 
	 * @Description: 读取输入流中的数据
	 * 
	 * @param is 文件输入流
	 * @param isXls 是不是 xls 格式的文件
	 * @param isSheetIndex 是不是指定的工作表
	 * @param sheetIndex 工作表在工作簿中的位置
	 * @return 工作簿的数据
	 */
	private static List readFile (InputStream is, Boolean isSheetIndex, Integer sheetIndex) {
		List dataList = new ArrayList<>();
		Workbook wb = null;
		try {
			// 创建工作簿(HSSFWorkbook或XSSFWorkbook),根据文件输入流自动检测创建对象
			wb = WorkbookFactory.create(is);
			Integer sheetCount = wb.getNumberOfSheets();	// 工作簿中工作表的总数
			List sheetList = new ArrayList<>();
			if (isSheetIndex) {	// 读取指定工作表
				// 判断指定的位置是否在工作簿中有对应的工作表
				if (sheetIndex < sheetCount) {
					sheetList = readWorkBook (wb, sheetIndex);
				} else {
					// 没有找到对应的工作表时,读取工作簿的最后一张工作表
					sheetList = readWorkBook (wb, sheetCount-1);
				}
				dataList.add(sheetList);	// 添加工作表的数据到工作簿数据集中
			} else {
				// 读取工作簿的所有工作表
				for (int i = 0; i < sheetCount; i++) {
					sheetList = readWorkBook (wb, i);
					dataList.add(sheetList);	// 将工作簿中的每一张不为空的工作表添加到工作簿的数据集中
				}
			}
		} catch (IOException e) {
			log.error("@!------------------------------创建工作簿失败!");
		}
		return dataList;
	}
	
	/**
	 * 
	 * @Title: readWorkBook
	 * 
	 * @Description: 读取工作表中的数据
	 * 
	 * @param wb 工作簿
	 * @param index 工作表在工作簿中的位置
	 * @return 工作表的数据
	 */
	private static List readWorkBook (Workbook wb, Integer index) {
		List sheetList = new ArrayList<>();
		Integer totalRows = 0;
		Integer totalCells = 0;
		Sheet sheet = wb.getSheetAt(index);	// 获取工作表对象
		sheetList.add(sheet.getSheetName());	// 添加工作表的名称到工作表中
		totalRows = sheet.getPhysicalNumberOfRows();	// 获取工作表的总行数
		if (totalRows > 0 && sheet.getRow(0) != null) {
			// 获取工作表的总列数,第一行或第二行的列数必须是整张工作表的总列数
			if (sheet.getRow(1) != null && sheet.getRow(0).getPhysicalNumberOfCells() < sheet.getRow(1).getPhysicalNumberOfCells()) {
				totalCells = sheet.getRow(1).getPhysicalNumberOfCells();
			} else {
				totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
			}
		}
		List rowList = new ArrayList<>();
		for (int i = 0; i < totalRows; i++) {
			Row row = sheet.getRow(i);	// 获取行对象
			// 去除空行
			if (row == null) {
				continue;
			}
			List cellList = new ArrayList();
			for (int j = 0; j < totalCells; j++) {
				Cell cell = row.getCell(j);	// 获取单元格对象
				cellList.add(cell);	// 将单元格中的数据添加到单元格数据集中
			}
			rowList.add(cellList);	// 将单元格数据集天津爱到行数据集中
		}
		sheetList.add(rowList);	// 将行数据集添加到工作表中
		return sheetList;
	}
	
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
//		List dataList = readExcel ("D:\\Desktop\\test.xlsx", false, 0);
		List dataList = readExcel ("D:\\Desktop\\test.xlsx", true, 1);
		if (dataList != null) {
			for (int i = 0; i < dataList.size(); i++) {
				// 获取工作表
				List sheetList = (List) dataList.get(i);
				String sheetName =  (String) sheetList.get(0);
				System.out.println("工作表的名称:" + sheetName);
				System.out.println("工作表的数据:");
				for (int j = 1; j < sheetList.size(); j++) {
					// 获取工作表的每一行
					List rowList = (List) sheetList.get(j);
					for (int k = 0; k < rowList.size(); k++) {
						// 获取工作表的每一列
						List cellList = (List) rowList.get(k);
						for (Object object : cellList) {
							// 获取每一个单元格的数据
							System.out.print("  "+object);
						}
						System.out.println();
					}
				}
			}
		}
	}
}
 
  

验证程序

test.xlsx 文件中的数据:

Java 通过 POI 读取 Excel 文件数据_第2张图片 城市邮编工作表的数据
Java 通过 POI 读取 Excel 文件数据_第3张图片 城市区号工作表的数据

不指定工作表程序运行结果:

Java 通过 POI 读取 Excel 文件数据_第4张图片 工作簿中的所有工作表数据

指定工作表程序运行结果:

Java 通过 POI 读取 Excel 文件数据_第5张图片 城市邮编工作表数据

 

 

感谢您的阅读!

你可能感兴趣的:(java工具教程)