使用poi读取Excel文件数据
Posted thekiterunner
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用poi读取Excel文件数据相关的知识,希望对你有一定的参考价值。
除分数被转换为小数存储外,其他数据经本人测试无问题,如发现问题请留言,方便及时更新
package com.haiyisoft.iecp.util; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.DateUtil; 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.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.XSSFWorkbook; /** * excel读取数据 * * @author * */ public class ReadExceTool { /** * 导出Excel文件的信息 形式为:List<List<Object>> 支持格式为 : xlsx,xls * 第一层list为文件sheet信息 第二层list为一个sheet页面的信息 第三层为sheet内容某一行的信息 * 文件信息由上自下由左自右查找 * 分数数据暂时只能读取成小数保存 * @param File 输入文件 * @param String 文件后缀 * @return List<List<Object>> (最内层object为一个List<Object>数组) */ public List<List<Object>> readExcel(File file, String extension) { List<List<Object>> fileObject = new java.util.ArrayList<List<Object>>(); Workbook wb = null; // 读取文件格式判断,如果是excel文件则返回Workbook实例 wb = readFile(file, extension); if(wb != null){ // 循环sheet页面,添加第一层list for(int numSheet = 0; numSheet < wb.getNumberOfSheets(); numSheet++){ Sheet sheet = wb.getSheetAt(numSheet); /** * column: sheet页面最大列数; * 根据 sheet页最大行,最大列对页面进行循环处理 */ List<Object> sheetObjects = new ArrayList<Object>(); // 获取数据最小列数 int startColumn = getFirstColNum(sheet, sheet.getLastRowNum()); // 获取数据最大列数 int endColumn = getLastColNum(sheet, sheet.getLastRowNum()); // 根据最大行数进行循环,将行数据数据放入第二层list for(int i =0; i <= sheet.getLastRowNum(); i++){ Row row = sheet.getRow(i); List<Object> rowValues = new ArrayList<Object>(); // 空行忽略 if(row == null){ continue; }else { // 每行内根据最大列数循环,将单元数据数据放入第三层list for(int j = startColumn; j < endColumn; j++){ Cell cell = row.getCell(j); // 空单元忽略 String cellValue = null; if(cell == null) continue; // 判断是否为合并单元格 if(isMergedRegion(sheet, i, j)){ // 合并单元格取值(所有单元格取第一个单元格的值,跨列合并单元格 只取第一个数据) cellValue = getMergedValue(sheet, i, j); }else{ // 单元格取值 cellValue = getValue(cell); } // 如果是跨列合并单元格 只取第一个数据 if(cellValue != null && cellValue.equals("ignoredData"))continue; else rowValues.add(cellValue); } sheetObjects.add(rowValues); } } fileObject.add(sheetObjects); } /*//遍历解析出来的list (数据验证) for (List<Object> sheetObjects : fileObject) { for (Object rowObjects : sheetObjects) { List<Object> cellValues = (List<Object>) rowObjects; for (int i = 0; i < cellValues.size(); i++) { System.out.print(cellValues.get(i) + ","); } System.out.println(); } System.out.println(); }*/ } return fileObject; } private static int getFirstColNum(Sheet sheet, int lastRowNum) { if(sheet == null || lastRowNum == 0){ return 0; } // 初始值设置为一个较大的值 int firstCol = 100; Row row = null; // 根据行循环,取第一个非空值的最小下标 for(int i = 0; i <= lastRowNum; i++){ row = sheet.getRow(i); if(row != null){ for(int j = 0; j < row.getLastCellNum(); j++){ if(row.getCell(j) != null){ if(firstCol > j){ firstCol = j; break; } } } } } return firstCol; } /** * 求Excel某一工作簿0~某行内的最大列数 * @param sheet 工作簿 * @param rowNum 行数 * @return */ private static int getLastColNum(Sheet sheet, int rowNum) { if(sheet == null || rowNum == 0){ return 0; } int lastCol = 0; Row row = null; for(int i = 0; i <= rowNum; i++){ row = sheet.getRow(i); if(row != null){ int temp = row.getLastCellNum(); if(temp > lastCol){ lastCol = temp; } } } return lastCol; } /** * 获取合并单元格的值 * @param sheet 工作簿 * @param rowNum 单元行 * @param columnIndex 单元列 * @return Object 单元值 */ private static String getMergedValue(Sheet sheet, int rowNum, int columnIndex) { // 获取合并单元格个数 int mergeNum = sheet.getNumMergedRegions(); String value = null; // 循环判断单元格所在合并单元格,合并单元格内所有单元格赋相同的值 for(int i = 0; i < mergeNum; i++){ CellRangeAddress range = sheet.getMergedRegion(i); // 数据依次为合并单元格的第一列、最后一列、第一行、最后一行 int firstColumn = range.getFirstColumn(); int lastColumn = range.getLastColumn(); int firstRow = range.getFirstRow(); int lastRow = range.getLastRow(); // 判断是否在次单元格区间内 if(rowNum >= firstRow && rowNum <= lastRow){ // 所有单元格取第一个单元格的值,跨列合并单元格 只取第一个数据 if(columnIndex == firstColumn){ value = getValue(sheet.getRow(firstRow).getCell(firstColumn)); }else if(columnIndex > firstColumn && columnIndex <= lastColumn){ value = "ignoredData"; } } } return value; } /** * 判断是不是合并单元格 * @param sheet Excel工作簿 * @param rowNum 单元格行下标 * @param columnIndex 单元格列下标 * @return */ private static boolean isMergedRegion(Sheet sheet, int rowNum, int columnIndex) { // 获取合并单元格个数 int sheetMergedNum = sheet.getNumMergedRegions(); for(int i = 0; i < sheetMergedNum; i++){ CellRangeAddress range = sheet.getMergedRegion(i); // 数据依次为合并单元格的第一列、最后一列、第一行、最后一行 int firstColumn = range.getFirstColumn(); int lastColumn = range.getLastColumn(); int firstRow = range.getFirstRow(); int lastRow = range.getLastRow(); // 判断是否在次单元格区间内,如果是则返回true if(rowNum >= firstRow && rowNum <= lastRow){ if(columnIndex >= firstColumn && columnIndex <= lastColumn){ return true; } } } // 如果不在所有的合并单元格内则返回false return false; } /** * 读取文件类型,如果是excel则返回对象实例, 如果不是则返回null * @param filePath 文件路径 * @return Workbook实例 */ private static Workbook readFile(File file, String extension) { Workbook wb = null; if(file != null){ try { InputStream inputStream = null; inputStream = new FileInputStream(file); if(extension.equals("xls")){ wb = new HSSFWorkbook(inputStream); }else if(extension.equals("xlsx")){ wb = new XSSFWorkbook(inputStream); }else{ wb = null; } } catch (FileNotFoundException e) { System.out.println("未找到文件位置!"); e.printStackTrace(); } catch (IOException e) { System.out.println("文件类型不正确,请重新选择!"); e.printStackTrace(); } } return wb; } /** * 获取单元格的值,并格式化 日期格式不变 其他格式转换为字符串类型 * @param cell 单元格 * @return */ private static String getValue(Cell cell){ String cellValue = null; // 格式化数据对象 DecimalFormat df = new DecimalFormat("0.######"); if(cell != null){ // 获取单元格数据类型 switch (cell.getCellType()) { case Cell.CELL_TYPE_NUMERIC: DateFormat formater = null; Date d = cell.getDateCellValue(); if(cell.getCellStyle().getDataFormat() == 31){ formater = new SimpleDateFormat("yyyy年MM月dd日"); cellValue = formater.format(d); }else if(cell.getCellStyle().getDataFormat() == 58){ formater = new SimpleDateFormat("MM月dd日"); cellValue = formater.format(d); }else if(cell.getCellStyle().getDataFormat() == 14){ formater = new SimpleDateFormat("yyyy-MM-dd"); cellValue = formater.format(d); }else if(cell.getCellStyle().getDataFormat() == 57){ formater = new SimpleDateFormat("yyyy年MM月"); cellValue = formater.format(d); }else if(cell.getCellStyle().getDataFormat() == 20){ formater = new SimpleDateFormat("HH:mm"); cellValue = formater.format(d); }else if(cell.getCellStyle().getDataFormat() == 32){ formater = new SimpleDateFormat("HH时mm分"); cellValue = formater.format(d); }else if(cell.getCellStyle().getDataFormat() == 9){ cellValue = df.format(cell.getNumericCellValue()*100) + "%"; }else if(DateUtil.isCellDateFormatted(cell)){ formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); cellValue = formater.format(d); }else{ cellValue = df.format(cell.getNumericCellValue()); } break; case Cell.CELL_TYPE_FORMULA: try { cellValue = df.format(cell.getNumericCellValue()); } catch (Exception e) { cellValue = cell.getCellFormula(); } break; case Cell.CELL_TYPE_STRING: cellValue = cell.getRichStringCellValue().getString(); break; case Cell.CELL_TYPE_BLANK: break; case Cell.CELL_TYPE_ERROR: break; default: cellValue = ""; break; } } return cellValue; } }
以上是关于使用poi读取Excel文件数据的主要内容,如果未能解决你的问题,请参考以下文章
java使用poi读取excel时,电话号码变成了科学计数法,整数变成double,怎么改过来