Java 解析 Excel

sweetmain發表於2018-01-05

解析 Excel 工具類

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;


public class ExcelTool {

	public static final String XLSX = ".xlsx";
	public static final String XLS=".xls";

	/**
	 * 獲取Excel檔案(.xls和.xlsx都支援)
	 * @param file
	 * @return  解析excle後的Json資料
	 * @throws IOException
	 * @throws FileNotFoundException
	 * @throws InvalidFormatException
	 */
	public static JSONArray readExcel(File file) throws IOException, InvalidFormatException{
		int res = checkFile(file);
		if (res == 0) {
			throw new NullPointerException("the file is null.");
		}else if (res == 1) {
			return readXLSX(file);
		}else if (res == 2) {
			return readXLS(file);
		}
		throw new IllegalAccessError("the file["+file.getName()+"] is not excel file.");
	}

	/**
	 * 判斷File檔案的型別
	 * @param file 傳入的檔案
	 * @return 0-檔案為空,1-XLSX檔案,2-XLS檔案,3-其他檔案
	 */
	public static int checkFile(File file){
		if (file==null) {
			return 0;
		}
		String flieName = file.getName();
		if (flieName.endsWith(XLSX)) {
			return 1;
		}
		if (flieName.endsWith(XLS)) {
			return 2;
		}
		return 3;
	}

	/**
	 * 讀取XLSX檔案
	 * @param file
	 * @return
	 * @throws IOException
	 * @throws InvalidFormatException
	 */
	public static JSONArray readXLSX(File file) throws InvalidFormatException, IOException{
		Workbook book = new XSSFWorkbook(file);
		Sheet sheet = book.getSheetAt(0);
		return read(sheet, book);
	}

	/**
	 * 讀取XLS檔案
	 * @param file
	 * @return
	 * @throws IOException
	 * @throws FileNotFoundException
	 */
	public static JSONArray readXLS(File file) throws FileNotFoundException, IOException{
		POIFSFileSystem poifsFileSystem = new POIFSFileSystem(new FileInputStream(file));
		Workbook book = new HSSFWorkbook(poifsFileSystem);
		Sheet sheet = book.getSheetAt(0);
		return read(sheet, book);
	}

	/**
	 * 解析資料
	 * @param sheet 表格sheet物件
	 * @param book 用於流關閉
	 * @return
	 * @throws IOException
	 */
	public static JSONArray read(Sheet sheet,Workbook book) throws IOException{
		int rowStart = sheet.getFirstRowNum();	// 首行下標
		int rowEnd = sheet.getLastRowNum();	// 尾行下標
		// 如果首行與尾行相同,表明只有一行,直接返回空陣列
		if (rowStart == rowEnd) {
			book.close();
			return new JSONArray();
		}
		// 獲取第一行JSON物件鍵
		Row firstRow = sheet.getRow(rowStart);
		int cellStart = firstRow.getFirstCellNum();
		int cellEnd = firstRow.getLastCellNum();
		Map<Integer, String> keyMap = new HashMap<Integer, String>();
		for (int j = cellStart; j < cellEnd; j++) {
			keyMap.put(j,getValue(firstRow.getCell(j), rowStart, j, book, true));
		}
		// 獲取每行JSON物件的值
		JSONArray array = new JSONArray();
		for(int i = rowStart+1; i <= rowEnd ; i++) {
			Row eachRow = sheet.getRow(i);
			JSONObject obj = new JSONObject();
			StringBuffer sb = new StringBuffer();
			for (int k = cellStart; k < cellEnd; k++) {
				if (eachRow != null) {
					String val = getValue(eachRow.getCell(k), i, k, book, false);
					sb.append(val);		// 所有資料新增到裡面,用於判斷該行是否為空
					obj.put(keyMap.get(k),val);
                }
			}
			if (sb.toString().length() > 0) {
				array.add(obj);
            }
		}
		book.close();
		return array;
	}

	/**
	 * 獲取每個單元格的資料
	 * @param cell 單元格物件
	 * @param rowNum 第幾行
	 * @param index 該行第幾個
	 * @param book 主要用於關閉流
	 * @param isKey 是否為鍵:true-是,false-不是。 如果解析Json鍵,值為空時報錯;如果不是Json鍵,值為空不報錯
	 * @return
	 * @throws IOException
	 */
	public static String getValue(Cell cell,int rowNum,int index,Workbook book,boolean isKey) throws IOException{

		// 空白或空 CELL_TYPE_BLANK

		if (cell == null || cell.getCellTypeEnum() == CellType.BLANK) {
			if (isKey) {
				book.close();
				throw new NullPointerException(String.format("the key on row %s index %s is null ", ++rowNum,++index));
            }else{
            	return "";
            }
		}

		// 0. 數字 型別
		if (cell.getCellTypeEnum() == CellType.NUMERIC) {
			if (HSSFDateUtil.isCellDateFormatted(cell)) {
				Date date = cell.getDateCellValue();
				DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				return df.format(date);
			}
			String val = cell.getNumericCellValue()+"";
			val = val.toUpperCase();
			if (val.contains("E")) {
				val = val.split("E")[0].replace(".", "");
            }
			return val;
		}

		// 1. String型別
		if (cell.getCellTypeEnum() == CellType.STRING) {
			String val = cell.getStringCellValue();
			if (val == null || val.trim().length()==0) {
				if (book != null) {
					book.close();
				}
				return "";
			}
			return val.trim();
		}

		// 2. 公式 CELL_TYPE_FORMULA
		if (cell.getCellTypeEnum() == CellType.FORMULA) {
			return cell.getStringCellValue();
		}

		// 4. 布林值 CELL_TYPE_BOOLEAN
		if (cell.getCellTypeEnum() == CellType.BOOLEAN) {
			return cell.getBooleanCellValue()+"";
		}

		// 5.	錯誤 CELL_TYPE_ERROR
		return "";
	}
}
複製程式碼

很尷尬的是我找不到原文出處了,如果作者看到,請聯絡我,我會註明出處的。

測試

public static void main(String[] args) throws Exception {
    JSONArray jsonArray = ExcelTool.readExcel(new File("user.xls"));
    jsonArray.forEach(System.out::println);

    System.out.println("-------xlsx-------");
    
    JSONArray jsonArray1 = ExcelTool.readExcel(new File("user.xlsx"));
    jsonArray1.forEach(System.out::println);
}
複製程式碼

依賴

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.39</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.17</version>
</dependency>
複製程式碼

相關文章