先放代码,别人给我的,做个留存,有需要的可以参考一下
public class ImportExcel<T> {
Class<T> clazz;
public ImportExcel(Class<T> clazz) {
this.clazz = clazz;
}
public Collection<T> importExcelInputStream(InputStream inputStream, Integer sheetIndex, String... pattern) {
Collection<T> dist = Lists.newArrayList();
try {
/**
* 类反射得到调用方法
*/
// 得到目标目标类的所有的字段列表
Field filed[] = clazz.getDeclaredFields();
// 将所有标有Annotation的字段,也就是允许导入数据的字段,放入到一个map中
Map fieldmap = new HashMap();
// 循环读取所有字段
for (int i = 0; i < filed.length; i++) {
Field f = filed[i];
// 得到单个字段上的Annotation
ExcelAnnotation exa = f.getAnnotation(ExcelAnnotation.class);
// 如果标识了Annotationd的话
if (exa != null) {
// 构造设置了Annotation的字段的Setter方法
String fieldname = f.getName();
String setMethodName = "set" + fieldname.substring(0, 1).toUpperCase() + fieldname.substring(1);
// 构造调用的method,
Method setMethod = clazz.getMethod(setMethodName, new Class[] { f.getType() });
// 将这个method以Annotaion的名字为key来存入。
fieldmap.put("".equals(exa.exportName())?exa.value():exa.exportName(), setMethod);
}
}
// excel的解析开始
FileInputStream in = (FileInputStream)inputStream;
// 得到工作表
HSSFWorkbook book = new HSSFWorkbook(in);
if (book.getNumberOfSheets() < sheetIndex + 1) {
log.info("总sheet数:{},要获取的index:{}", book.getNumberOfSheets(), sheetIndex);
return null;
}
Sheet sheet = book.getSheetAt(sheetIndex);
Iterator<Row> row = sheet.rowIterator(); // 得到所有行
// 得到第一行,也就是标题行
Row title = row.next();
// 得到第一行的所有列
Iterator<Cell> cellTitle = title.cellIterator();
// 将标题的文字内容放入到一个map中。
Map titlemap = new HashMap();
// 从标题第一列开始
int i = 0;
// 循环标题所有的列
while (cellTitle.hasNext()) {
Cell cell = cellTitle.next();
String value = cell.getStringCellValue();
titlemap.put(i, value);
i = i + 1;
}
while (row.hasNext()) {
// 标题下的第一行
Row rown = row.next();
// 行的所有列
Iterator<Cell> cellbody = rown.cellIterator();
// 得到传入类的实例
T tObject = clazz.newInstance();
// 遍历一行的列
boolean flag = false; // value不为空时才新增行对象值
while (cellbody.hasNext()) {
Cell cell = cellbody.next();
// 这里得到此列的对应的标题
String titleString = (String) titlemap.get(cell.getColumnIndex());
// 如果这一列的标题和类中的某一列的Annotation相同,那么则调用此类的的set方法,进行设值
if (fieldmap.containsKey(titleString)) {
Method setMethod = (Method) fieldmap.get(titleString);
// 判断参数类型
String value = getCellValue(cell);
if (StringUtils.isNotBlank(value)) {
flag = true;
value = value.trim();
String paramType = setMethod.getParameterTypes()[0].getName();
// log.info("paramType == {}, value == {}, titleString == {}", paramType, value, titleString);
if (paramType.equals("java.lang.String")) {
setMethod.invoke(tObject, value);
} else if (paramType.equals("java.lang.Integer")) {
double db = Double.parseDouble(value);
db = Math.round(db);
setMethod.invoke(tObject, new Double(db).intValue());
} else if (paramType.equals("java.math.BigDecimal")) {
setMethod.invoke(tObject, new BigDecimal(value));
}
}
}
}
if (flag) {
dist.add(tObject);
}
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return dist;
}
/**
* 根据excel单元格类型获取excel单元格值
* @param cell
* @return
*/
private String getCellValue(Cell cell) {
String cellvalue = "";
if (cell != null) {
// 判断当前Cell的Type
switch (cell.getCellType()) {
// 如果当前Cell的Type为NUMERIC
case Cell.CELL_TYPE_NUMERIC: {
short format = cell.getCellStyle().getDataFormat();
if(format == 14 || format == 31 || format == 57 || format == 58){ //excel中的时间格式
double value = cell.getNumericCellValue();
Date date = DateUtil.getJavaDate(value);
cellvalue = getDateString2(date);
}
// 判断当前的cell是否为Date
else if (HSSFDateUtil.isCellDateFormatted(cell)) { //先注释日期类型的转换,在实际测试中发现HSSFDateUtil.isCellDateFormatted(cell)只识别2014/02/02这种格式。
// 如果是Date类型则,取得该Cell的Date值 // 对2014-02-02格式识别不出是日期格式
Date date = cell.getDateCellValue();
cellvalue = getDateString(date);
} else { // 如果是纯数字
// 取得当前Cell的数值
cellvalue = NumberToTextConverter.toText(cell.getNumericCellValue());
}
break;
}
// 如果当前Cell的Type为STRIN
case Cell.CELL_TYPE_STRING:
// 取得当前的Cell字符串
cellvalue = cell.getStringCellValue().replaceAll("'", "''");
break;
case Cell.CELL_TYPE_BLANK:
cellvalue = null;
break;
// 默认的Cell值
default:{
cellvalue = " ";
}
}
} else {
cellvalue = "";
}
return cellvalue;
}
private String getDateString2(Date date) {
String cellvalue;Calendar instance = Calendar.getInstance();
instance.setTime(date);
DateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if(1899==instance.get(Calendar.YEAR)){
formater = new SimpleDateFormat("HH:mm:ss");
}else if(0==instance.get(Calendar.HOUR)){
formater = new SimpleDateFormat("yyyy-MM-dd");
}
cellvalue = formater.format(date);
return cellvalue;
}
private String getDateString(Date date) {
String cellvalue;
Calendar instance = Calendar.getInstance();
instance.setTime(date);
DateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if(1899==instance.get(Calendar.YEAR)){
formater = new SimpleDateFormat("HH:mm:ss");
}else if(0==instance.get(Calendar.HOUR)){
formater = new SimpleDateFormat("yyyy-MM-dd");
}
cellvalue= formater.format(date);
return cellvalue;
}
}
这个是主方法,提前根据列名定义对应的实体类,通过反射,将实体类和Excle表格列标题进行绑定(差不多这个意思),例:
遍历excle的值,通过当前列列名,将值set到列名对应的属性值上。这样,当excle表格改变之后,只需改变对应的实体类和sql语句,就可以对代码进行维护,维护起来很方便。如果有其他更好的方法,欢迎大家提出来。PS:此方法非原创!