使用Apache POI读取Excel文件
jopen
11年前
摘要: 适用于Microsoft Excel xls/xlsx两种类型电子表格的读取操作。
网上关于介绍Apache POI操作Excel的文章已经很多了,但都讲得比较复杂。poi的API 与实际使用中的Excel很类似,可以说是POI把Excel中的workbook、sheet、cell等对象化了,在实际使用中极易理解。但由于Apache POI在存在已有不短时间,至少在excel2007之前就已经出现,造成同样一套Api并不能同时读取(写入)xls和xlsx两种类型的Excel文件。但poi对excel有一个很好的抽象(ss包下的Workbook、Sheet、Cell等类),可以一定程度上忽略xls/xlsx的处理细节,针对其通用部分进行处理,但如果需要对各自有理强的支持,还是建议使用相应的API。
Apache POI 各个包功能描述:
HSSF - 提供读写Microsoft Excel XLS格式档案的功能。XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。
HWPF - 提供读写Microsoft Word DOC格式档案的功能。
HSLF - 提供读写Microsoft PowerPoint格式档案的功能。
HDGF - 提供读Microsoft Visio格式档案的功能。
HPBF - 提供读Microsoft Publisher格式档案的功能。
HSMF - 提供读Microsoft Outlook格式档案的功能。
下面给出一个简单的实现Demo:
[ExcelReader]
package net.yeah.likun_zhang.excel; import static net.yeah.likun_zhang.util.Debug.printf; import java.io.FileInputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import net.yeah.likun_zhang.util.Debug; import org.apache.commons.lang3.StringUtils; import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.hssf.usermodel.HSSFWorkbook; 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.xssf.usermodel.XSSFWorkbook; /** * 读取Excel 97~2003 xls格式 /2007~ xlsx格式 * @author ZhangLiKun * @mail likun_zhang@yeah.net * @date 2013-5-11 */ public class ExcelReader { /** * 创建工作簿对象 * @param filePath * @return * @throws IOException * @date 2013-5-11 */ public static final Workbook createWb(String filePath) throws IOException { if(StringUtils.isBlank(filePath)) { throw new IllegalArgumentException("参数错误!!!") ; } if(filePath.trim().toLowerCase().endsWith("xls")) { return new HSSFWorkbook(new FileInputStream(filePath)) ; } else if(filePath.trim().toLowerCase().endsWith("xlsx")) { return new XSSFWorkbook(new FileInputStream(filePath)) ; } else { throw new IllegalArgumentException("不支持除:xls/xlsx以外的文件格式!!!") ; } } public static final Sheet getSheet(Workbook wb ,String sheetName) { return wb.getSheet(sheetName) ; } public static final Sheet getSheet(Workbook wb ,int index) { return wb.getSheetAt(index) ; } public static final List<Object[]> listFromSheet(Sheet sheet) { int rowTotal = sheet.getPhysicalNumberOfRows() ; Debug.printf("{}共有{}行记录!" ,sheet.getSheetName() ,rowTotal) ; List<Object[]> list = new ArrayList<Object[]>() ; for(int r = sheet.getFirstRowNum() ; r <= sheet.getLastRowNum() ; r ++) { Row row = sheet.getRow(r) ; if(row == null)continue ; // 不能用row.getPhysicalNumberOfCells(),可能会有空cell导致索引溢出 // 使用row.getLastCellNum()至少可以保证索引不溢出,但会有很多Null值,如果使用集合的话,就不说了 Object[] cells = new Object[row.getLastCellNum()] ; for(int c = row.getFirstCellNum() ; c <= row.getLastCellNum() ; c++) { Cell cell = row.getCell(c) ; if(cell == null)continue ; cells[c] = getValueFromCell(cell) ; } list.add(cells) ; } return list ; } /** * 获取单元格内文本信息 * @param cell * @return * @date 2013-5-8 */ public static final String getValueFromCell(Cell cell) { if(cell == null) { printf("Cell is null !!!") ; return null ; } String value = null ; switch(cell.getCellType()) { case Cell.CELL_TYPE_NUMERIC : // 数字 if(HSSFDateUtil.isCellDateFormatted(cell)) { // 如果是日期类型 value = new SimpleDateFormat(DatePattern.LOCALE_ZH_DATE.getValue()).format(cell.getDateCellValue()) ; } else value = String.valueOf(cell.getNumericCellValue()) ; break ; case Cell.CELL_TYPE_STRING: // 字符串 value = cell.getStringCellValue() ; break ; case Cell.CELL_TYPE_FORMULA: // 公式 // 用数字方式获取公式结果,根据值判断是否为日期类型 double numericValue = cell.getNumericCellValue() ; if(HSSFDateUtil.isValidExcelDate(numericValue)) { // 如果是日期类型 value = new SimpleDateFormat(DatePattern.LOCALE_ZH_DATE.getValue()).format(cell.getDateCellValue()) ; } else value = String.valueOf(numericValue) ; break ; case Cell.CELL_TYPE_BLANK: // 空白 value = ExcelConstants.EMPTY_CELL_VALUE ; break ; case Cell.CELL_TYPE_BOOLEAN: // Boolean value = String.valueOf(cell.getBooleanCellValue()) ; break ; case Cell.CELL_TYPE_ERROR: // Error,返回错误码 value = String.valueOf(cell.getErrorCellValue()) ; break ; default:value = StringUtils.EMPTY ;break ; } // 使用[]记录坐标 return value + "["+cell.getRowIndex()+","+cell.getColumnIndex()+"]" ; } }
测试类[ExcelReaderTest]
package net.yeah.likun_zhang.excel; import java.io.FileNotFoundException; import java.io.IOException; import java.util.List; import net.yeah.likun_zhang.BaseTest; import net.yeah.likun_zhang.util.Debug; import net.yeah.likun_zhang.util.ToString; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.junit.Test; /** * 读取 * @author ZhangLiKun * @mail likun_zhang@yeah.net * @date 2013-5-8 */ public class ExcelReaderTest extends BaseTest{ @Test public void testRead() throws FileNotFoundException, IOException { Workbook wb = ExcelReader.createWb("src/main/resources/excels/demo-3.xlsx") ; // 获取Workbook中Sheet个数 int sheetTotal = wb.getNumberOfSheets() ; Debug.printf("工作簿中的工作表个数为:{}" ,sheetTotal); // 获取Sheet Sheet sheet = ExcelReader.getSheet(wb, 0) ; // 遍历Sheet List<Object[]> list = ExcelReader.listFromSheet(sheet) ; Debug.printf(list, new ToString<Object[]>(){ private int index = 1 ; @Override public String toString(Object[] t) { if(t == null || t.length == 0)return StringUtils.EMPTY ; StringBuffer sb = new StringBuffer(index ++ + ":") ; for(int i = 0 ,len = t.length ; i < len ; i++) { sb.append(t[i] + ",") ; } return sb.toString(); } }) ; } }
测试辅助类[Debug]
package net.yeah.likun_zhang.util; import java.util.Collection; import java.util.Iterator; import org.apache.commons.lang3.ArrayUtils; /** * Debug函数库 * @author ZhangLiKun * @mail likun_zhang@yeah.net * @date 2013-5-8 */ public class Debug { /** * 打印函数 * @param objects * @date 2013-5-8 */ public static final void printf(String msg ,Object ...objects) { if(ArrayUtils.isEmpty(objects)) { System.out.println(msg); return ; } for(int i = 0 ,len = objects.length ; i < len ; i ++) { Object obj = objects[i] ; msg = msg.replaceFirst("\\{\\}", obj == null ? "" : obj.toString()) ; } System.out.println(msg); } /** * 打印函数 * @param obj * @date 2013-5-8 */ public static final void printf(Object obj) { if(obj != null){ System.out.println(obj.toString()); } } /** * 打印集合 * @param list * @param ts * @date 2013-5-8 */ public static final <T> void printf(Collection<T> list ,ToString<T> ts) { if(list == null || list.isEmpty()) return ; Iterator<T> iter = list.iterator() ; while(iter.hasNext()) { T t = iter.next() ; // if(t == null)continue ; if(ts == null) { System.out.println(t.toString()); } else { String msg = ts.toString(t) ; // if(msg != null) { System.out.println(msg); // } } } } }