Java 从Excel文件读取数据的更好方法
我必须从一个Excel文件中读取数据,该文件大约有40列,我正在使用列索引逐个读取数据。i、 e:Java 从Excel文件读取数据的更好方法,java,excel,apache-poi,Java,Excel,Apache Poi,我必须从一个Excel文件中读取数据,该文件大约有40列,我正在使用列索引逐个读取数据。i、 e: Cell cell = row.getCell(0); if (!(cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK)) { cell.setCellType(Cell.CELL_TYPE_STRING); // set in setter } 但这种方法和Exce
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对象字段的绑定。我建议添加带有列信息(即名称)的标题行和处理列(即将它们映射到Java对象)因此。也许您甚至可以使用反射API来反序列化对象。类似的东西是用来将java对象保存到数据库的,我在这里不擅长,但你可以用谷歌搜索并检查 该标题行可以隐藏在XL中 或者,您可以将映射信息放在java代码中(不修改原始XL文件)-只需为此定义一个数据结构,而不是像在
row.getCell(0)
中那样硬编码常量-它应该更改为解释有关XL文件中列的元数据
换句话说,每个正在处理的XL文件都有数据定义,并且每个定义都有一个处理XL文件的通用代码。您应该有一个以XL文件名和定义文件为参数的例程。有两个选项:
- 第一/最后
- 迭代器
for(Row row : sheet) {
for(Cell cell : row) {
...
它允许遍历所有可用的行/单元格,而不会遇到任何空项。创建了一个实用程序,该实用程序将从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;
}
}
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;
}
}
导入java.io.File;
导入java.io.FileInputStream;
导入java.lang.reflect.Constructor;
导入java.util.HashMap;
导入java.util.Iterator;
导入java.util.LinkedList;
导入java.util.List;
导入java.util.Map;
导入org.apache.poi.ss.usermodel.Cell;
导入org.apache.poi.ss.usermodel.Row;
导入org.apache.poi.xssf.usermodel.xssfheet;
导入org.apache.poi.xssf.usermodel.xssf工作簿;
公开课的优异成绩{
公共静态列表读取(字符串文件路径、类objClass、映射头TopPropertyMap){
试一试{
FileInputStream file=newfileinputstream(新文件(filePath));
//创建包含对.xlsx文件引用的工作簿实例
XSSF工作簿=新XSSF工作簿(文件);
XSSFSheet sheet=workbook.getSheetAt(0);
迭代器rowIterator=sheet.Iterator();
List retList=新建LinkedList();
Constructor=objClass.getConstructor();
Map columnIndexToProperty=null;
if(roweiterator.hasNext()){
行=行迭代器。下一步();
ColumnIndexTopProperty=getCorrespondingColumnIndex(标题属性映射,行);
}
while(roweiterator.hasNext())
{
T obj=constructor.newInstance();
行=行迭代器。下一步();
setObjectFromRow(对象、行、列索引属性);
retList.add(obj);
}
file.close();
返回列表;
}捕获(例外e){
e、 printStackTrace();
}
返回新的LinkedList();
}
私有静态void setObjectFromRow(T obj,Row Row,Map columnIndexToProperty){
int numColumns=row.getPhysicalNumberOfCells();
对于(int i=0;i您使用哪个excel库?如果使用APACHE POI,则可以使用getPhysicalNumberOfRows()
检查列和行的边界,对于行的列getPhysicalNumberOfCells()
BTW,getPhysicalNumberOfCells()不会告诉您列在一行中的实际位置,它只是计算填充了多少单元格,但其间可能存在间隙。
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);