在软件开发的过程中经常会需要使用到excel导入的功能,每个excel导入的功能首先都必须先将excel中的数据读取出来然后才能对其进行进一步到操作。读取excel中的数据的工作就成了一个重复性的工作了,且一般都没有比较特别其他操作,只是简单的逐行读取并缓存起来。这样就可以简单设计一个通用的excel读取器,用来方便快捷地读取excel中的数据。详细类如下(读取excel使用的是poi的方式):
定义行读取器接口:
默认实现是将excel中的数据逐行读取并放入到Map<String,Object>。(需要将列对应的key传给读取器)
import org.apache.poi.ss.usermodel.Sheet;
/**
* excel行数据读取器.
* @param <T>
*/
public interface ExcelRowDataReader<T> {
/**
* 读取指定行的数据
* @param sheet
* @param rowIndex
* @param startCellIndex
* @param endCellIndex
* @return
*/
public T getRowData(Sheet sheet, int rowIndex, int startCellIndex, int endCellIndex);
}
定义读取excel的基类
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
/**
* @Description:excel读取器.
* @param <T>
*/
public class ExcelReader<T> {
private Sheet sheet;
private ExcelRowDataReader<T> reader;
private int startRowIndex = 0;
private int startCellIndex = 0;
private int endRowIndex = -1;
private int endCellIndex = -1;
public ExcelReader() {
}
public ExcelReader(Sheet sheet, ExcelRowDataReader<T> reader) {
this();
this.setSheet(sheet);
this.setReader(reader);
}
public ExcelReader(HSSFWorkbook wb, ExcelRowDataReader<T> reader) {
this(wb.getSheetAt(0), reader);
}
public ExcelReader(InputStream inStream, ExcelRowDataReader<T> reader)
throws IOException {
this(new HSSFWorkbook(inStream), reader);
}
/**
* 逐行读取Excel中的数据缓存到List中.
* @return excel中的数据集合
*/
public List<T> getExcelData() {
List<T> returnDatas = new ArrayList<T>();
if (getSheet() == null || getReader() == null) {
return returnDatas;
}
int lastRowNum = getSheet().getLastRowNum();
if (getEndRowIndex() >= 0 && lastRowNum > getEndRowIndex()) {
lastRowNum = getEndRowIndex();
}
if (getStartRowIndex() > lastRowNum) {
return returnDatas;
}
Row row = getSheet().getRow(getStartRowIndex());
int lastCellNum = row.getLastCellNum();
if (getEndCellIndex() >= 0 && lastCellNum > getEndCellIndex()) {
lastCellNum = getEndCellIndex();
}
if (getStartCellIndex() > lastCellNum) {
return returnDatas;
}
T data = null;
for (int rowIndex = getStartRowIndex(); rowIndex <= lastRowNum; rowIndex++) {
data = getReader().getRowData(getSheet(), rowIndex, getStartCellIndex(),
lastCellNum);
if (data != null) {
returnDatas.add(data);
}
}
return returnDatas;
}
//setter/getter方法
}
如上,行读取的接口提供读取一行数据的具体实现,并范围一个泛型,并由ExcelReader中的getExcelData方法中逐行调用此接口的方法以得到各行的数据,当返回的结果不为null是添加到集合中。如此就完成了一个整个excel的读取工作。
以下提供了一个默认的实现。
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
/**
* @Description:默认Excel读取器.将Excel数据读取到Map中.
*/
public class DefualtExcelReader extends ExcelReader<Map<String, Object>> {
public DefualtExcelReader(Sheet sheet, String mapKeys) {
super(sheet, new DefualtExcelRowDataReader(mapKeys));
}
public DefualtExcelReader(HSSFWorkbook wb, String mapKeys) {
this(wb.getSheetAt(0), mapKeys);
}
public DefualtExcelReader(InputStream inStream, String mapKeys) throws IOException {
this(new HSSFWorkbook(inStream), mapKeys);
}
}
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
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;
/**
* 默认Excel行读取器.将一行中的数据保存到Map中,map的key由mapKeys指定,其顺序对应于Excel中的列顺序.
*/
public class DefualtExcelRowDataReader implements ExcelRowDataReader<Map<String, Object>> {
private static final SimpleDateFormat DATE_TIME_DF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final SimpleDateFormat DATE_DF = new SimpleDateFormat("yyyy-MM-dd");
private List<String> mapKeys;
public DefualtExcelRowDataReader(List<String> mapKeys) {
this.setMapKeys(mapKeys);
}
public DefualtExcelRowDataReader(String mapKeys) {
this.setMapKeys(changeToList(mapKeys));
}
public DefualtExcelRowDataReader(String mapKeys, String splitStr) {
this.setMapKeys(changeToList(mapKeys, splitStr));
}
@Override
public Map<String, Object> getRowData(Sheet sheet, int rowIndex, int startCellIndex, int endCellIndex) {
Map<String, Object> data = new HashMap<String, Object>();
if (getMapKeys() == null || getMapKeys().isEmpty()) {
return data;
}
Row row = sheet.getRow(rowIndex);
if (row == null) {
return data;
}
int i = 0;
int size = getMapKeys().size();
endCellIndex = Math.min(endCellIndex - 1, startCellIndex + size - 1);
for (int cellIndex = startCellIndex; cellIndex <= endCellIndex; cellIndex++) {
Cell cell = row.getCell(cellIndex);
String key = getMapKeys().get(i++);
if (cell == null) {
data.put(key, "");
} else {
data.put(key, getCellValueToString(cell));
}
}
return data;
}
//其他辅助方法
}
默认实现是将excel中的数据逐行读取并放入到Map<String,Object>。(需要将列对应的key传给读取器)
默认实现的使用如下:
public static void main(String[] args) throws Exception {
FileItemStream fis = null; //Excel文件流
String mapKeys = "select,beforeValue,afterValue,afterDes,operation"; //Excel从左到右的列在map中对应的key值.
DefualtExcelReader excelReader = new DefualtExcelReader(fis.openStream(), mapKeys);
excelReader = new DefualtExcelReader(fis.openStream(), mapKeys); //读取Excel中的第一个sheet中的数据.
// DefualtExcelReader(Sheet sheet, String mapKeys) //读取指定的sheet中的数据.
// DefualtExcelReader(HSSFWorkbook wb, String mapKeys) //读取Excel中的第一个sheet中的数据.
excelReader.setStartRowIndex(1); //设置读取数据的开始行号(从0开始)
List<Map<String, Object>> dataList = excelReader.getExcelData();
}
若是excel没有什么特别的话,则直接使用上述代码就可以方便地将excel中的数据读取到List<Map<Stirng,Object>>中,直接使用此集合就可以进行其他的处理了。
当然若是excel比较特殊的话,也可以使此读取器,只需重新实现ExcelRowDataReader类中的getRowData方法即可。实现的方式可以参照default的实现类。
全部代码参见http://download.csdn.net/detail/shui878412/8385487