Excel通用读取器

在软件开发的过程中经常会需要使用到excel导入的功能,每个excel导入的功能首先都必须先将excel中的数据读取出来然后才能对其进行进一步到操作。读取excel中的数据的工作就成了一个重复性的工作了,且一般都没有比较特别其他操作,只是简单的逐行读取并缓存起来。这样就可以简单设计一个通用的excel读取器,用来方便快捷地读取excel中的数据。详细类如下(读取excel使用的是poi的方式):

定义行读取器接口:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
是的,EasyExcel提供了一种通用的监听器(`AnalysisEventListener`),可以用于读取Excel文件中的多个不同的sheet。以下是一个示例代码段,展示如何使用通用监听器来读取Excel文件中的多个sheet: ```java public class MyListener extends AnalysisEventListener<Object> { private List<Object> dataList = new ArrayList<>(); @Override public void invoke(Object object, AnalysisContext context) { dataList.add(object); // 将读取到的数据添加到列表中 if (dataList.size() >= 1000) { saveData(); // 每读取1000条数据,就调用一次saveData方法 dataList.clear(); // 清空已经处理的数据 } } @Override public void doAfterAllAnalysed(AnalysisContext context) { saveData(); // 处理剩余的数据 } private void saveData() { // 将数据保存到数据库或者其他地方 } } ``` 在上面的代码中,我们创建了一个名为`MyListener`的类作为通用监听器。`MyListener`继承自`AnalysisEventListener`,并重写了`invoke`方法和`doAfterAllAnalysed`方法。在`invoke`方法中,我们将读取到的数据添加到列表中,并在读取到1000条数据时调用`saveData`方法。在`doAfterAllAnalysed`方法中,我们处理剩余的数据。`saveData`方法可以将数据保存到数据库或者其他地方。 接下来,我们可以使用以下代码来读取Excel文件中的多个sheet: ```java // 创建读取Excel的对象 ExcelReader reader = EasyExcel.read("example.xlsx", new MyListener()).build(); // 读取Excel文件中的所有sheet reader.readAll(); // 关闭读取Excel的对象 reader.finish(); ``` 在上面的代码中,我们创建了一个名为`reader`的ExcelReader对象,并将`MyListener`作为参数传递给它。然后,我们使用`readAll`方法来读取Excel文件中的所有sheet。在读取过程中,EasyExcel会自动调用`MyListener`中的`invoke`方法来处理读取到的数据。在读取完成后,EasyExcel会自动调用`MyListener`中的`doAfterAllAnalysed`方法。 使用通用监听器的好处是,您不需要为每个sheet创建一个不同的监听器,而是可以使用一个通用的监听器来处理所有sheet中的数据。这样可以简化代码,并提高代码的可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蜗牛_snail

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值