Java基於POI讀取Excel工具類

爲什麼爲封裝此工具類?

由於公司供應鏈部門業務需要,對Excel處理這塊有較爲嚴苛的要求。爲了提高開發效率,從實際項目出發封裝了通用自定義讀取Excel工具類。  

功能概述

  1. 支持讀取全部excel數據
  2. 支持自定義讀取(自定義讀取行、列)數據
  3.  支持讀取以title爲基準的數據(只讀取title下的行)
  4. 支持讀取圖片(返回圖片的位置和流)
  5.  支持設置sheet index讀取
  6.  支持讀取函數值
  7.  支持annation讀取列表值
使用注意點
由於操作Excel文件一般較大,建議對JVM調優,調大堆內存空間,將大對象直接放在老年代,具體調優方式,網上資料很多。

核心代碼
/**
 * 讀取excel文件內容 
 * 僅支持xlsx格式
 * @author Vachel.Wang
 * @date 2016年6月16日 下午5:10:18  
 * @version V1.2
 */
public class ReadExcel {
	
	private XSSFWorkbook workbook = null;
	private XSSFSheet sheet;
    private XSSFRow row;
    private int sheetIndex = 0 ;
    private int rowIndex = 0 ;
    private int cellIndex = 0 ;
   
    
	public static ReadExcel me(InputStream s) throws IOException{
		return new ReadExcel(s);
	}
	
	public ReadExcel(InputStream s) throws IOException{
			workbook = new XSSFWorkbook(s);
			setSheetIndex(0);
	}
	
	public <T> List<T> readCoustomTemplet(Class<T> clazz) throws InstantiationException, IllegalAccessException {
	    List<T> list = new ArrayList<T>();
	    
	    XSSFRow titleRow = sheet.getRow(rowIndex-1);
	    ArrayList<String> rowArr = new ArrayList<String>();
	    int cells = titleRow.getPhysicalNumberOfCells();
	    for (int j = cellIndex; j < cells; j++) {
            rowArr.add(getStringCellValue(titleRow.getCell(j)));
        }
	    
	    List<Field> allFields = getMappedFiled(clazz, null);
        Map<String, Field> fieldsMap = new HashMap<String, Field>();//定義一個map用於存放列的序號和field.
        for (Field field : allFields) {
            if (field.isAnnotationPresent(ExcelField.class)) {
                ExcelField attr = field.getAnnotation(ExcelField.class);
                field.setAccessible(true);
                fieldsMap.put(attr.title(), field);
            }
        }
        
        //row = sheet.getRow(rowIndex);
        for (int i = rowIndex ; i < sheet.getPhysicalNumberOfRows(); i++) {
            row = sheet.getRow(i);
            T entity = null;
            for (int j = cellIndex; j < cells; j++) {
                String c = getStringCellValue(row.getCell(j));
                entity = (entity == null ? clazz.newInstance() : entity);// 如果不存在實例則新建.
                Field field = fieldsMap.get(rowArr.get(j));// 從map中得到對應列的field.
               
                if (field==null) {
                    continue;
                }
                
                Class<?> fieldType = field.getType();
                if (String.class == fieldType) {
                    field.set(entity, String.valueOf(c));
                } else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {
                    field.set(entity, Integer.parseInt(c));
                } else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {
                    field.set(entity, Long.valueOf(c));
                } else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {
                    field.set(entity, Float.valueOf(c));
                } else if ((Short.TYPE == fieldType) || (Short.class == fieldType)) {
                    field.set(entity, Short.valueOf(c));
                } else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {
                    field.set(entity, Double.valueOf(c));
                } else if (Character.TYPE == fieldType) {
                    if ((c != null) && (c.length() > 0)) {
                        field.set(entity, Character.valueOf(c.charAt(0)));
                    }
                }
            }
            if (entity != null) {
                list.add(entity);
            }
        }
	    
	    return list;
    }
	
	private List<Field> getMappedFiled(Class clazz, List<Field> fields) {
        if (fields == null) {
            fields = new ArrayList<Field>();
        }

        Field[] allFields = clazz.getDeclaredFields();// 得到所有定義字段
        // 得到所有field並存放到一個list中.
        for (Field field : allFields) {
            if (field.isAnnotationPresent(ExcelField.class)) {
                fields.add(field);
            }
        }
        if (clazz.getSuperclass() != null && !clazz.getSuperclass().equals(Object.class)) {
            getMappedFiled(clazz.getSuperclass(), fields);
        }

        return fields;
    }
	
	/**
	 * 讀取自定義讀取方式數據
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public List<ArrayList<String>> readCoustom() throws FileNotFoundException, IOException{
		List<ArrayList<String>> excelData = new ArrayList<ArrayList<String>>();
		for (int i = rowIndex ; i < sheet.getPhysicalNumberOfRows(); i++) {
			ArrayList<String> rowArr = new ArrayList<String>();
			row = sheet.getRow(i);
			for (int j = cellIndex; j < row.getPhysicalNumberOfCells(); j++) {
				rowArr.add(getStringCellValue(row.getCell(j)));
			}
			excelData.add(rowArr);
		}
		return excelData;
	}
	/**
	 * 以title列爲標準讀取自定義數據
	 * @param titleIndex
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public List<ArrayList<String>> readCoustomByTitle(int titleIndex) throws FileNotFoundException, IOException{
		XSSFRow titleRow = sheet.getRow(titleIndex);
		List<ArrayList<String>> excelData = new ArrayList<ArrayList<String>>();
		for (int i = rowIndex ; i < sheet.getPhysicalNumberOfRows(); i++) {
			ArrayList<String> rowArr = new ArrayList<String>();
			row = sheet.getRow(i);
			for (int j = cellIndex; j < titleRow.getPhysicalNumberOfCells(); j++) {
				rowArr.add(getStringCellValue(row.getCell(j)));
			}
			excelData.add(rowArr);
		}
		return excelData;
	}
	
	/**
	 * 讀取自定義讀取非空數據
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public List<ArrayList<String>> readCoustomExcludeNull() throws FileNotFoundException, IOException{
		List<ArrayList<String>> excelData = new ArrayList<ArrayList<String>>();
		for (int i = rowIndex ; i < sheet.getPhysicalNumberOfRows(); i++) {
			ArrayList<String> rowArr = new ArrayList<String>();
			row = sheet.getRow(i);
			for (int j = cellIndex; j < row.getPhysicalNumberOfCells(); j++) {
				String cellValue = getStringCellValue(row.getCell(j)); 
				if(!cellValue.equals(""))
					rowArr.add(cellValue);
			}
			excelData.add(rowArr);
		}
		return excelData;
	}
	
	/**
	 * 讀取所有
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public List<ArrayList<String>> readAll() throws FileNotFoundException, IOException{
		List<ArrayList<String>> excelData = new ArrayList<ArrayList<String>>();
		for (int i = 0 ; i < sheet.getPhysicalNumberOfRows(); i++) {
			ArrayList<String> rowArr = new ArrayList<String>();
			row = sheet.getRow(i);
			for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {
				rowArr.add(getStringCellValue(row.getCell(j)));
			}
			excelData.add(rowArr);
		}
		return excelData;
	}
	
	/**
	 * 以title行爲標準來讀其它所有取列值
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public List<ArrayList<String>> readAllByTitle(int titleIndex) throws FileNotFoundException, IOException{
		XSSFRow titleRow = sheet.getRow(titleIndex);
		List<ArrayList<String>> excelData = new ArrayList<ArrayList<String>>();
		for (int i = 0 ; i < sheet.getPhysicalNumberOfRows(); i++) {
			ArrayList<String> rowArr = new ArrayList<String>();
			row = sheet.getRow(i);
			if(row==null)
				continue;
			for (int j = 0; j < titleRow.getPhysicalNumberOfCells(); j++) {
				rowArr.add(getStringCellValue(row.getCell(j)));
			}
			excelData.add(rowArr);
		}
		return excelData;
	}

	/**
	 * 讀取title行下的所有數據
	 * @param titleIndex
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
     */
	public List<ArrayList<String>> readNextByTitle(int titleIndex) throws FileNotFoundException, IOException{
		XSSFRow titleRow = sheet.getRow(titleIndex);
		List<ArrayList<String>> excelData = new ArrayList<ArrayList<String>>();
		for (int i = titleIndex+1 ; i < sheet.getPhysicalNumberOfRows(); i++) {
			ArrayList<String> rowArr = new ArrayList<String>();
			row = sheet.getRow(i);
			if(row==null){
			    continue;
			}
			for (int j = 0; j < titleRow.getPhysicalNumberOfCells(); j++) {
				rowArr.add(getStringCellValue(row.getCell(j)));
			}
			excelData.add(rowArr);
		}
		return excelData;
	}
	
	/**
	 * 讀取非空數據
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public List<ArrayList<String>> readAllExcludeNull() throws FileNotFoundException, IOException{
		List<ArrayList<String>> excelData = new ArrayList<ArrayList<String>>();
		for (int i = 0 ; i < sheet.getPhysicalNumberOfRows(); i++) {
			ArrayList<String> rowArr = new ArrayList<String>();
			row = sheet.getRow(i);
			for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {
				String cellValue = getStringCellValue(row.getCell(j)); 
				if(!cellValue.equals(""))
					rowArr.add(cellValue);
			}
			excelData.add(rowArr);
		}
		return excelData;
	}
	
	/**
	 * 讀取行的所有列的數據
	 * @param rowIndex
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public ArrayList<String> readRowData(int rowIndex) throws FileNotFoundException, IOException{
		ArrayList<String> rowDataArr = new ArrayList<String>();
		row = sheet.getRow(rowIndex);
		for (int i = 0 ; i < row.getPhysicalNumberOfCells(); i++) {
			String cellStr = getStringCellValue(row.getCell(i));
			rowDataArr.add(cellStr);
		}
		return rowDataArr;
	}
	
	/**
	 * 讀取行的所有列的非空數據
	 * @param rowIndex
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public ArrayList<String> readRowExcludeNullData(int rowIndex) throws FileNotFoundException, IOException{
		ArrayList<String> rowDataArr = new ArrayList<String>();
		row = sheet.getRow(rowIndex);
		for (int i = 0 ; i < row.getPhysicalNumberOfCells(); i++) {
			String cellValue = getStringCellValue(row.getCell(i));
			if(!cellValue.equals(""))
				rowDataArr.add(cellValue);
		}
		return rowDataArr;
	}
	
	/**
	 * 讀取讀列的數據 
	 * 空爲 ""
	 * @param rowIndex
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public String readCellData(int rowIndex , int cellIndex) throws FileNotFoundException, IOException{
		row = sheet.getRow(rowIndex);
		return getStringCellValue(row.getCell(cellIndex));
	}
	
	/**
	 * 獲取所有圖片 
	 * @return
	 */
	public List<XSSFPictureData> readPictures() {
		return workbook.getAllPictures();
	}
	
	/**
	 * 讀取單元格內容,支持獲取函數內容
	 * @param cell
	 * @return
	 */
	public static String getStringCellValue(Cell cell) {
        String strCell = "";
        if(cell==null) return strCell;
        switch (cell.getCellType()) {
	        case Cell.CELL_TYPE_STRING:	// get String data 
	        	strCell = cell.getRichStringCellValue().getString().trim();
	            break;
	        case Cell.CELL_TYPE_NUMERIC:	// get date or number data 
	            if (DateUtil.isCellDateFormatted(cell)) {
	                strCell = com.gjw.utils.DateUtil.formatYYYYMMDDHHMMSS(cell.getDateCellValue());
	            } else {
	            	BigDecimal numberic=new BigDecimal(cell.getNumericCellValue());
	            	strCell = numberic.toPlainString();
	            }
	            break;
	        case Cell.CELL_TYPE_BOOLEAN:	// get boolean data 
	        	strCell = String.valueOf(cell.getBooleanCellValue());
	            break;
	        case Cell.CELL_TYPE_FORMULA:	// get expression data 
	        	FormulaEvaluator evaluator = cell.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
	            evaluator.evaluateFormulaCell(cell);
	            CellValue cellValue = evaluator.evaluate(cell);
				if(StringUtil.isNotBlank(cellValue.getStringValue())){
					strCell = String.valueOf(cellValue.getStringValue()) ;
				}else{
					strCell = String.valueOf(cellValue.getNumberValue()) ;
				}
	            break;
	        default:
	        	strCell = "";
	    }
        return strCell;
    }
	
	/**
	 * 設置讀取sheet下標,默認爲0
	 * @param sheetIndex
	 * @return
	 */
	public ReadExcel setSheetIndex(int sheetIndex){
		this.sheetIndex = sheetIndex ;
		sheet = workbook.getSheetAt(sheetIndex);
		return this;
	}
	/**
	 * 設置讀取sheet下標,默認爲0
	 * @param rowIndex
	 * @return
	 */
	public ReadExcel setRowIndex(int rowIndex){
		this.rowIndex = rowIndex ;
		return this;
	}
    /**
	 * 設置讀取cell下標,默認爲0
	 * @param rowIndex
	 * @return
	 */
	public ReadExcel setCellIndex(int cellIndex){
		this.cellIndex = cellIndex ;
		return this;
	}
	/**
	 * 獲取sheet總數
	 * @return
	 */
	public int getSheetCount(){
		return this.workbook.getNumberOfSheets();
	}
	/**
	 * 根據sheet下標獲取sheet名稱
	 * @param index
	 * @return
	 */
	public String getSheetNameByIndex(int index){
		return this.workbook.getSheetAt(index).getSheetName();
	}
	public String getCurrentSheetName(){
		return this.workbook.getSheetAt(sheetIndex).getSheetName();
	}
	/**
	 * 獲取Excel2007圖片
	 * @param sheetNum 當前sheet編號
	 * @param sheet 當前sheet對象
	 * @param workbook 工作簿對象
	 * @return Map key:圖片單元格索引(0_1_1)String,value:圖片流PictureData
	 */
	public static Map<String, PictureData> getSheetPictrues(int sheetNum,
															  XSSFSheet sheet, XSSFWorkbook workbook) {
		Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();

		for (POIXMLDocumentPart dr : sheet.getRelations()) {
			if (dr instanceof XSSFDrawing) {
				XSSFDrawing drawing = (XSSFDrawing) dr;
				List<XSSFShape> shapes = drawing.getShapes();
				for (XSSFShape shape : shapes) {
					XSSFPicture pic = (XSSFPicture) shape;
					XSSFClientAnchor anchor = pic.getPreferredSize();
					CTMarker ctMarker = anchor.getFrom();
					String picIndex = String.valueOf(sheetNum) + "_"
							+ ctMarker.getRow() + "_" + ctMarker.getCol();
					sheetIndexPicMap.put(picIndex, pic.getPictureData());
				}
			}
		}

		return sheetIndexPicMap;
	}

	public static void printImg(List<Map<String, XSSFPictureData>> sheetList) throws IOException {

		for (Map<String, XSSFPictureData> map : sheetList) {
			Object key[] = map.keySet().toArray();
			for (int i = 0; i < map.size(); i++) {
				// 獲取圖片流
				XSSFPictureData pic = map.get(key[i]);
				// 獲取圖片索引
				String picName = key[i].toString();
				// 獲取圖片格式
				String ext = pic.suggestFileExtension();

				byte[] data = pic.getData();

				FileOutputStream out = new FileOutputStream("D:\\pic" + picName + "." + ext);
				out.write(data);
				out.close();
			}
		}

	}

	public XSSFWorkbook getWorkbook() {
		return workbook;
	}

	public XSSFSheet getSheet() {
		return sheet;
	}

	public int getSheetIndex() {
		return sheetIndex;
	}

	public static void main(String[] args) throws IOException {
		/*InputStream inputStream = new FileInputStream("d:\\success3.xlsx");
		try {
            List<ScmInvoiceImportLog> list = ReadExcel.me(inputStream).setSheetIndex(0).setRowIndex(1).readCoustomTemplet(ScmInvoiceImportLog.class);
            System.out.println(list);
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }*/

		// list all demo
		/*List<ArrayList<String>> list = ReadExcel.me(inputStream).setSheetIndex(0).readAllByTitle(4);
		for(ArrayList<String> rowArray : list){
			for(String string : rowArray){
				System.out.print(string+"\t");
			}
			System.out.println();
		}*/
		// read picture demo
		/*List<XSSFPictureData> readPictures = ReadExcel.me(inputStream).readPictures();
		for(XSSFPictureData pictureData:readPictures){
			int type = pictureData.getPictureType();
			if(type == Workbook.PICTURE_TYPE_JPEG){
				File file = new File("d:\\"+System.currentTimeMillis()+".jpg");
				OutputStream outputStream = new FileOutputStream(file);
				outputStream.write(pictureData.getData());
				outputStream.flush();
				outputStream.close();
			}
		}*/
		/*ReadExcel readExcel = ReadExcel.me(inputStream).setSheetIndex(0);
		Map<String, PictureData> dataMap =  readExcel.getSheetPictrues(readExcel.getSheetIndex(),readExcel.getSheet(),readExcel.getWorkbook());
		for(Map.Entry<String,PictureData> entry : dataMap.entrySet()){
			System.out.println("key = "+entry.getKey()+" , value = "+entry.getValue());
		}*/
	}
}

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelField {

	/**
	 * 導出字段名(默認調用當前字段的“get”方法,如指定導出字段爲對象,請填寫“對象名.對象屬性”,例:“area.name”、“office.name”)
	 */
	String value() default "";
	
	/**
	 * 導出字段標題(需要添加批註請用“**”分隔,標題**批註,僅對導出模板有效)
	 */
	String title();
	
	/**
	 * 字段類型(0:導出導入;1:僅導出;2:僅導入)
	 */
	int type() default 0;

	/**
	 * 導出字段對齊方式(0:自動;1:靠左;2:居中;3:靠右)
	 */
	int align() default 0;
	
	/**
	 * 導出字段字段排序(升序)
	 */
	int sort() default 0;

	/**
	 * 如果是字典類型,請設置字典的type值
	 */
	String dictType() default "";
	
	/**
	 * 反射類型
	 */
	Class<?> fieldType() default Class.class;
	
	/**
	 * 字段歸屬組(根據分組導出導入)
	 */
	int[] groups() default {};
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章