1. 程式人生 > >Excel匯入匯出工具類 POI

Excel匯入匯出工具類 POI

/**
 * Copyright (C), 2015-2018, XXX有限公司
* FileName: ExcelUtils
 * Author:   luohui
 * Date:     2018/9/12 15:31
 * Description: Excel工具類
* History:
 * <author>          <time>          <version>          <desc>
* 作者姓名           修改時間           版本號              描述
*/
package com.test.util.sys.excel;

import com.test.util.sys.Tools;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 〈一句話功能簡述〉<br> 
* 〈Excel工具類〉
*
 * @author luohui
 * @create 2018/9/12
 * @since 1.0.0
 */
public class ExcelUtils {
    /**
    * @方法概述 匯入excel資料並對映到類
    * @param path 檔案路徑
    * @param sheetNumber 第幾張表,預設從0開始為第一張表
    * @param mappingClass 要對映的類
    */
    public static <T> List<T> inputExcel(String path, int sheetNumber, Class<T> mappingClass) throws Exception{
        //儲存讀取的資料
        List<T>      result   = new ArrayList<>();
        HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(path));
        HSSFSheet sheet       = workbook.getSheetAt(sheetNumber);

        // 獲取資料總行數,編號是從0開始的
        int rowcount = sheet.getLastRowNum() + 1;
        if (rowcount < 1) {
            return result;
        }

        //獲取類屬性
        Field[] property = mappingClass.getDeclaredFields();
        Field.setAccessible(property, true);
        //逐行讀取資料
        for (int i = 0; i < rowcount; i++) {
            //建立物件
            T bean = mappingClass.newInstance();
            // 獲取行物件
            HSSFRow row = sheet.getRow(i + 1);
            if (row != null) {
                // 獲取本行中單元格個數
                int column = row.getLastCellNum();
                // 獲取本行中各單元格的資料
                for (int cindex = 0; cindex < column; cindex++) {
                    HSSFCell cell  = row.getCell(cindex);
                    // 獲得指定單元格中的資料
                    Object cellstr = getCellString(cell);
                    if(i > property.length) {
                        break;
                    }
                    //獲取屬性型別
                    String attType = property[cindex].getGenericType().toString();
                    //判斷屬性型別
                    if("class java.lang.String".equals(attType)) {
                        property[cindex].set(bean, cellstr);
                    }
                    else if("int".equals(attType)) {
                        property[cindex].setInt(bean, Integer.parseInt(cellstr.toString()));
                    }
                    else if("double".equals(attType)) {
                        property[cindex].setDouble(bean, Double.parseDouble(cellstr.toString()));
                    }
                    else if("float".equals(attType)) {
                        property[cindex].setFloat(bean, Float.parseFloat(cellstr.toString()));
                    }
                    else if("long".equals(attType)) {
                        property[cindex].setLong(bean, Long.parseLong(cellstr.toString()));
                    }
                    else if("boolean".equals(attType)) {
                        property[cindex].setBoolean(bean, Boolean.parseBoolean(cellstr.toString()));
                    }
                    else if("class java.lang.Integer".equals(attType)) {
                        String method = alephUppercase( property[cindex].getName() );
                        Method set    = bean.getClass().getMethod(method,Integer.class );
                        int tempNum   = Integer.parseInt(cellstr.toString());
                        set.invoke(bean, tempNum);
                    }
                    else if("class java.lang.Double".equals(attType)) {
                        String method  = alephUppercase( property[cindex].getName() );
                        Method set     = bean.getClass().getMethod(method,Double.class );
                        double tempNum = Double.parseDouble(cellstr.toString());
                        set.invoke(bean, tempNum);
                    }
                    else if("class java.lang.Long".equals(attType)) {
                        String method = alephUppercase( property[cindex].getName() );
                        Method set    = bean.getClass().getMethod(method,Long.class );
                        long tempNum  = Long.parseLong(cellstr.toString());
                        set.invoke(bean, tempNum);
                    }
                }
                result.add(bean);
            }
        }
        return result;
    }

    /**
    * 匯出Excel
    * @param <T>
    * @param sourceData 源資料
    * @param sheetName  表格別名
    * @param title      表格標題,如果為空預設為類屬性
    * @param fieldList  欄位集合
    * @param file       儲存路徑,包括檔名,如:F:/test.xls
    * @param isCover    false 追加工作表,true 覆蓋工作表
    */
    public static File outputExcel(List sourceData, String sheetName, String[] titles, String[] fieldList, File file, boolean isCover) {
        if(file == null || Tools.isEmpty(sourceData) || titles == null || titles.length == 0 || fieldList == null || fieldList.length == 0) {
            return null;
        }

        FileOutputStream fos = null;
        FileInputStream  fis = null;
        HSSFWorkbook book;
        HSSFSheet sheet;
        HSSFRow hssfrow;
        HSSFCell hssfcell;

        try {
            if(file.exists()) {
                //是否覆蓋原有資料,還是在原基礎上建立一張新的工作表
                if(isCover) {
                    book = new HSSFWorkbook();// 所有execl的父節點
                } else {
                    fis  = new FileInputStream(file);
                    POIFSFileSystem poiFile = new POIFSFileSystem(fis);
                    book = new HSSFWorkbook(poiFile);
                }
            } else{
                //如果檔案不存在,直接建立一個新的檔案,而不去讀取
                book = new HSSFWorkbook();// 所有execl的父節點
            }

            //-----------------------------------------------------------
            sheet   = book.createSheet( sheetName == null ? "sheet1" : sheetName);// 此處可以隨意設定
            hssfrow = sheet.createRow(0); // 建立首行標題

            //-----------------------------------------------------------
            //獲取引數中集合物件的欄位
            Field[] fields = sourceData.get(0).getClass().getDeclaredFields();
            Field.setAccessible(fields, true);

            //欄位轉成Map集合
            Map<String, Field> fieldMap = new HashMap<>();
            for (int i = 0; i < fields. length; i++) {
                fieldMap.put(fields[i].getName(), fields[i]);
            }

            //-----------------------------------------------------------
            for (int i = 0; i < titles. length; i++) { // 建立標題欄目,也就是表格第一行
                hssfcell = hssfrow.createCell(i);
                hssfcell.setCellType (HSSFCell.ENCODING_UTF_16);
                hssfcell.setCellValue(titles[i]);
            }

            //-----------------------------------------------------------
            for (int i = 0; i < sourceData.size(); i++) { // 新增表格中的內容
                hssfrow = sheet.createRow(i + 1); // 建立表格第二行,由於標記為0,這裡設定為一,主要為了區別標題和內容
                Object bean = sourceData.get(i);
                for(int f = 0; f < fieldList.length; f++) {
                    Field field = fieldMap.get(fieldList[f]);
                    if(field == null) {
                        continue;
                    }
                    hssfcell = hssfrow.createCell(f);
                    hssfcell.setCellType (HSSFCell.ENCODING_UTF_16); // 關於資料編碼的問題
                    //獲取物件屬性值
                    Object value = field.get(bean);
                    if(value == null) {
                        value = "";
                    }
                    hssfcell.setCellValue(value + ""); // 轉換為字串的方式
                }
            }

            fos = new FileOutputStream(file);
            book.write(fos);
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fos != null) {
                try {
                    fos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return file;
    }

    /**
    * @方法概述 獲取單元格中的內容 ,該犯法用於解析各種形式的資料
    * @param cell
    */
    private static Object getCellString( HSSFCell cell) {
        Object result = null;
        if (cell != null) {
            int cellType = cell.getCellType();
            switch (cellType) {
                case HSSFCell.CELL_TYPE_STRING:
                    result = cell.getRichStringCellValue().getString();
                    break;
                case HSSFCell.CELL_TYPE_NUMERIC:
                    result = cell.getNumericCellValue();
                    break;
                case HSSFCell.CELL_TYPE_FORMULA:
                    result = cell.getNumericCellValue();
                    break;
                case HSSFCell.CELL_TYPE_ERROR:
                    result = null;
                    break;
                case HSSFCell.CELL_TYPE_BOOLEAN:
                    result = cell.getBooleanCellValue();
                    break;
                case HSSFCell.CELL_TYPE_BLANK:
                    result = null;
                    break;
                default:
                    break;
            }
        }
        return result;
    }

    private static String alephUppercase(String name) {
        String tmp = name.trim().intern();
        if (Tools.isEmpty(tmp))
            return "";
        if (tmp.length() < 2) {
            return "set" + name.toUpperCase();
        } else {
            return "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
        }
    }
}