package org.fanlychie.excel;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
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.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.fanlychie.util.DynaBean;
* 可进行读操作的 EXCEL 工具类
*
* @author fanlychie
*/
public class ReadableExcel {
private Sheet sheet;
private int sheetIndex;
private Map<Integer, String> mapper;
private DynaBean dynaBean;
private int maxColumnIndex;
* 构造可读的 Excel 实例
*
* @param file
* Excel 文件
*/
public ReadableExcel(File file) {
try {
init(new FileInputStream(file));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
* 构造可读的 Excel 实例
*
* @param in
* Excel 文件输入流
*/
public ReadableExcel(InputStream in) {
init(in);
}
* 解析 Excel 文档到一个 List 列表, 约定第一行为标题行, 标题行不被解析
*
* @param beanClass
* 简单的 JavaBean 类型, Excel 文档的每一行解析成该类的一个实例
* @param mapper
* Excel 文档的列映射到 JavaBean 对象的属性列表<br>
* 格式串 A:["prop_name1", "prop_name2", ...]<br>
* 格式串 B:["1:prop_name1", "2:prop_name2", ...]
* @return 返回解析 Excel 文档的 List 结果列表
*/
public <T> List<T> asList(Class<T> beanClass, String... mapper) {
this.mapper = parseMapper(mapper);
this.dynaBean = new DynaBean(beanClass);
List<T> beanList = new ArrayList<T>();
Iterator<Row> rows = sheet.iterator();
Row rowOfTitle = rows.next();
this.maxColumnIndex = rowOfTitle.getPhysicalNumberOfCells();
while (rows.hasNext()) {
@SuppressWarnings("unchecked")
T bean = (T) parseRow(rows.next());
beanList.add(bean);
}
return beanList;
}
* 设置读取的工作表的索引
*
* @param sheetIndex
* 工作表的索引
*/
public void setSheetIndex(int sheetIndex) {
this.sheetIndex = sheetIndex;
}
* 初始化工作表
*
* @param in
* Excel 输入流
*/
private void init(InputStream in) {
try {
Workbook workbook = WorkbookFactory.create(in);
sheet = workbook.getSheetAt(sheetIndex);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
* 解析 Excel 文档的一行到一个 Bean 的对象里
*
* @param row
* Excel 文档中的行对象
* @return 返回解析行的 Bean 对象
*/
private Object parseRow(Row row) {
dynaBean.newBeanInstance();
Iterator<Cell> cells = row.cellIterator();
while (cells.hasNext()) {
Cell cell = cells.next();
int columnIndex = cell.getColumnIndex();
if (columnIndex >= maxColumnIndex) {
break;
}
String name = mapper.get(columnIndex);
if (name == null) {
continue ;
}
Class<?> type = dynaBean.getFieldType(name);
Object value;
if (type == Date.class) {
value = cell.getDateCellValue();
} else {
cell.setCellType(Cell.CELL_TYPE_STRING);
String stringCellValue = cell.getStringCellValue();
value = commonTypeConvert(stringCellValue, type);
}
dynaBean.setFieldValue(name, value);
}
return dynaBean.getBean();
}
* 解析映射的字符串
*
* @param mapper
* 格式串 A:["prop_name1", "prop_name2", ...]
* 格式串 B:["1:prop_name1", "2:prop_name2", ...]
* @return 返回解析后的对照表
*/
private Map<Integer, String> parseMapper(String... mapper) {
Map<Integer, String> map = new HashMap<Integer, String>();
String item;
int length = mapper.length;
for (int i = 0; i < length; i++) {
item = mapper[i];
if (item.contains(":")) {
String[] items = item.split(":");
map.put(Integer.valueOf(items[0]), items[1]);
} else {
map.put(i, item);
}
}
return map;
}
* 常用的数据类型转换
*
* @param value
* 被转换的对象
* @param type
* 期望得到的类型
* @return 返回转换后的数据类型对象
*/
private Object commonTypeConvert(String value, Class<?> type) {
if (type == String.class) {
return value;
}
if (type == Character.TYPE || type == Character.class) {
return value.charAt(0);
}
if (type == Boolean.TYPE || type == Boolean.class) {
if (value == "1" || value.equals("是")
|| value.equalsIgnoreCase("Y")
|| value.equalsIgnoreCase("YES")
|| value.equalsIgnoreCase("T")
|| value.equalsIgnoreCase("TRUE")) {
return true;
}
if (value == "0" || value.equals("否")
|| value.equalsIgnoreCase("N")
|| value.equalsIgnoreCase("NO")
|| value.equalsIgnoreCase("F")
|| value.equalsIgnoreCase("FALSE")) {
return false;
}
}
Double objVal = Double.valueOf(value);
if (type == Byte.TYPE || type == Byte.class) {
return objVal.byteValue();
}
if (type == Short.TYPE || type == Short.class) {
return objVal.shortValue();
}
if (type == Integer.TYPE || type == Integer.class) {
return objVal.intValue();
}
if (type == Long.TYPE || type == Long.class) {
return objVal.longValue();
}
if (type == Float.TYPE || type == Float.class) {
return objVal.floatValue();
}
if (type == Double.TYPE || type == Double.class) {
return objVal;
}
throw new ClassCastException("Cannot cast java.lang.String to " + type.getName());
}
}