2015-10-06 66 views
0

我必須從Excel文件中讀取大約40列的數據,並且使用列索引逐個讀取它。即:從Excel文件中讀取數據的更好方法

Cell cell = row.getCell(0); 
if (!(cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK)) { 
      cell.setCellType(Cell.CELL_TYPE_STRING); 
      // set in setter 
     } 

但是,這種方法是緊密結合的Excel文件結構,因爲如果任何新的列被添加在之間然後將需要主代碼(列的索引值)。

請建議我從Excel文件中讀取數據的任何有效方法,應該與Excel的結構鬆散耦合,或者如果有任何其他方式可以提供與Java對象字段的列綁定。

+0

你使用哪個excel庫?如果是APACHE POI,那麼你可以用'getPhysicalNumberOfRows()'和列的行'getPhysicalNumberOfCells()' –

+0

檢查行和列的邊界,getPhysicalNumberOfCells()不會告訴你列在哪裏實際上是一個行,它只是計數有多少個單元格被填充,但是它們之間可能存在空隙。 – centic

回答

1

我會建議添加一個標題行列信息(即名稱)和處理列(即映射到Java對象)。可能你甚至可以使用反射API來反序列化對象。類似的東西是用來保存java對象到數據庫,我不是很好,但你可以谷歌和檢查。

該標題行可以隱藏在XL中。

或者你可以在你的java代碼中放置映射信息(不要修改原始XL文件) - 只需定義一個數據結構而不是像row.getCell(0)那樣的硬編碼常量 - 它應該被修改爲解釋你的有關列的元數據在XL文件中。

換句話說,您將對每個您正在處理的XL文件進行數據定義,併爲每個定義處理XL文件創建一個通用代碼。您應該有一個以XL文件名和定義文件爲參數的例程。

0

有兩種選擇:

  • 首先/最後
  • 迭代

首先/最後

POI提供Sheet.getFirstRowNum()/ getLastRowNum()能夠從第一行到最後一行,以及單元格的Row.getFirstCellNum()/ getLastCellNum()。

請注意,如果某些未填充,您仍然可能遇到空行/單元格。

迭代

兩個表和行實現Iterable接口,這樣你就可以這樣做

for(Row row : sheet) { 
    for(Cell cell : row) { 
      ... 

它允許步行所有可用的行/細胞沒有遇到任何空項。

0

創建該實用程序將讀取Excel中的每一行,併爲每行創建一個自定義Java對象。請確保您在使用前閱讀底部的限制。

ExcelUtils.java:

import java.io.File; 
import java.io.FileInputStream; 
import java.lang.reflect.Constructor; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.LinkedList; 
import java.util.List; 
import java.util.Map; 

import org.apache.poi.ss.usermodel.Cell; 
import org.apache.poi.ss.usermodel.Row; 
import org.apache.poi.xssf.usermodel.XSSFSheet; 
import org.apache.poi.xssf.usermodel.XSSFWorkbook; 

public class ExcelUtils { 

    public static <T> List<T> read(String filePath,Class<T> objClass, Map<String,String> headersToPropertyMap){ 
     try { 
       FileInputStream file = new FileInputStream(new File(filePath)); 

       //Create Workbook instance holding reference to .xlsx file 
       XSSFWorkbook workbook = new XSSFWorkbook(file); 
       XSSFSheet sheet = workbook.getSheetAt(0); 
       Iterator<Row> rowIterator = sheet.iterator(); 
       List<T> retList = new LinkedList<T>(); 
       Constructor<T> constructor =objClass.getConstructor(); 
       Map<Integer,String> columnIndexToProperty = null; 
       if(rowIterator.hasNext()){ 
        Row row = rowIterator.next(); 
        columnIndexToProperty = getCorrespondingColumnIndex(headersToPropertyMap,row); 
       } 

       while (rowIterator.hasNext()) 
       { 
        T obj = constructor.newInstance(); 
        Row row = rowIterator.next(); 
        setObjectFromRow(obj,row,columnIndexToProperty); 
        retList.add(obj); 
       } 
       file.close(); 
       return retList; 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     return new LinkedList<T>(); 
    } 
    private static <T> void setObjectFromRow(T obj, Row row, Map<Integer,String> columnIndexToProperty){ 
     int numColumns = row.getPhysicalNumberOfCells(); 
     for(int i=0;i<numColumns;i++){ 
      Object value = getCellValue(row.getCell(i)); 
      ReflectUtils.set(obj, columnIndexToProperty.get(i), value); 
     } 
    } 
    private static Map<Integer,String> getCorrespondingColumnIndex(Map<String,String> headersToPropertyMap,Row row){ 
     int numColumns = row.getPhysicalNumberOfCells(); 
     Map<Integer,String> columnIndexToProperty = new HashMap<Integer,String>(); 
     for(int i=0;i<numColumns;i++){ 
      Cell cell =row.getCell(i); 
      String header = cell.getStringCellValue(); 
      String property = headersToPropertyMap.get(header); 
      if(property==null) 
       System.out.println("Warning: not able to find property with header: "+header); 
      columnIndexToProperty.put(i, property); 
     } 
     return columnIndexToProperty; 
    } 

    private static Object getCellValue(Cell cell){ 
     switch (cell.getCellType()) 
     { 
      case Cell.CELL_TYPE_NUMERIC: 
       return cell.getNumericCellValue(); 
      case Cell.CELL_TYPE_STRING: 
       return cell.getStringCellValue(); 
      case Cell.CELL_TYPE_BOOLEAN: 
       return cell.getBooleanCellValue(); 
     } 
     return null; 
    } 
} 

ReflectUtils。Java的:

import java.lang.reflect.Field; 
import java.lang.reflect.ParameterizedType; 
import java.lang.reflect.Type; 

import com.google.common.base.Optional; 

public class ReflectUtils { 

    public static boolean set(Object object, String fieldName, Object fieldValue) { 
     if(fieldName==null) 
      return false; 
     Class<?> clazz = object.getClass(); 
     while (clazz != null) { 
      try { 
       Field field = clazz.getDeclaredField(fieldName); 
       field.setAccessible(true); 
       Type pt=null; 
       try{ 
        pt = field.getGenericType(); 
       }catch(Exception e){ 
        e.printStackTrace(); 
       } 
       if(pt!=null && pt.getTypeName().equals("com.google.common.base.Optional<java.lang.String>")) 
        field.set(object, Optional.fromNullable(fieldValue)); 
       else if(pt!=null && pt.getTypeName().equals("java.lang.String")) 
        if(fieldValue instanceof Double) 
         field.set(object, String.valueOf(((Double)fieldValue).intValue())); 
        else 
         field.set(object, String.valueOf(fieldValue)); 
       else if(pt!=null && (pt.getTypeName().equals("java.lang.Integer") || pt.getTypeName().equals("int"))) 
        if(fieldValue instanceof Double) 
         field.set(object, ((Double) fieldValue).intValue()); 
        else 
         field.set(object, Integer.parseInt(String.valueOf(fieldValue))); 
       else 
        field.set(object, fieldValue); 
       return true; 
      } catch (NoSuchFieldException e) { 
       clazz = clazz.getSuperclass(); 
      } catch (Exception e) { 
       throw new IllegalStateException(e); 
      } 
     } 
     return false; 
    } 
} 

用法:

 Map<String,String> headersToPropertyMap = new HashMap<String,String>(); 
     //The header column name in excel-First, the property you wish to assign the value-firstName 
     headersToPropertyMap.put("First", "firstName"); 
     headersToPropertyMap.put("Last", "lastName"); 
     headersToPropertyMap.put("Email", "email"); 
     headersToPropertyMap.put("orgNodeId", "companyname"); 
     headersToPropertyMap.put("Company Name", "companynameString"); 
     headersToPropertyMap.put("EULA", "eula"); 
     headersToPropertyMap.put("Email Notification", "emailNotification"); 
     return ExcelUtils.read("path to excel file",CUSTOM.class,headersToPropertyMap); 

限制:

  • 僅支持字符串,整數和布爾的Java性能。
  • 只支持來自excel的String,Double和boolean。
  • 必須修改ReflectUtils以添加您自己的自定義對象。例如,我添加到ReflectUtils中的可選對象。