POI导入,兼容xlsx 和 xls

气死了,之前遇到一个感觉比较好用的poi导入,谁知道现在用起来,各种bug,干脆使用最新的api模仿实现了一个,使用模版方法模式回调,只需要实现接口,处理每一行数据,就ok了。此实现只支持单页sheetIndex
多页实现请参考:http://git.oschina.net/zhuqiang/utils

使用到的jar包pom

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.12</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.12</version>
</dependency>

核心PoiAbstract抽象类

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
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;
/**
 * 读取xlsx 和 xls,只支持单页sheetIndex
 * @author zq
 *
 */
public abstract class PoiAbstract {
    Workbook wb = null;

    public PoiAbstract(String path) {
        try {
            InputStream inp = new FileInputStream(path);
            wb = WorkbookFactory.create(inp);  //使用工厂创建,兼容xlsx 和 xls
        } catch (Exception e) {
            new RuntimeException(e.getMessage());
        }

    }

    /**
     * 遍历Excel所有数据,包含header
     * 
     * @param sheetIndex
     */
    public void process(int sheetIndex) {
        int columnNum = 0; // 获取列
        Sheet sheet = wb.getSheetAt(sheetIndex);
        if (sheet.getRow(0) != null) {
            columnNum = sheet.getRow(0).getLastCellNum() - sheet.getRow(0).getFirstCellNum();
        }
        if (columnNum > 0) {
            for (Row row : sheet) {
                List<String> rowlist = new ArrayList<String>(columnNum);
                int n = 0;
                for (int i = 0; i < columnNum; i++) {
                    Cell cell = row.getCell(i, Row.CREATE_NULL_AS_BLANK);
                    switch (cell.getCellType()) {
                    case Cell.CELL_TYPE_BLANK:
                        rowlist.add(n, "");
                        break;
                    case Cell.CELL_TYPE_BOOLEAN:
                        rowlist.add(Boolean.toString(cell.getBooleanCellValue()));
                        break;
                    // 数值
                    case Cell.CELL_TYPE_NUMERIC:
                        if (DateUtil.isCellDateFormatted(cell)) {
                            rowlist.add(String.valueOf(cell.getDateCellValue()));
                        } else {
                            cell.setCellType(Cell.CELL_TYPE_STRING);
                            String temp = cell.getStringCellValue();
                            // 判断是否包含小数点,如果不含小数点,则以字符串读取,如果含小数点,则转换为Double类型的字符串
                            if (temp.indexOf(".") > -1) {
                                rowlist.add(String.valueOf(new Double(temp)).trim());
                            } else {
                                rowlist.add(temp.trim());
                            }
                        }
                        break;
                    case Cell.CELL_TYPE_STRING:
                        rowlist.add(cell.getStringCellValue().trim());
                        break;
                    case Cell.CELL_TYPE_ERROR:
                        rowlist.add("");
                        break;
                    case Cell.CELL_TYPE_FORMULA:
                        cell.setCellType(Cell.CELL_TYPE_STRING);
                        rowlist.add(cell.getStringCellValue());
                        if (rowlist.get(n) != null) {
                            rowlist.set(n, rowlist.get(n).replaceAll("#N/A", "").trim());
                        }
                        break;
                    default:
                        rowlist.add("");
                        break;
                    }
                    n++;
                }
                try {
                    this.optRows(sheetIndex, row.getRowNum(), rowlist); // 行结束,调用行,每行的数据
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public abstract void optRows(int sheetIndex, int curRow, List<String> rowlist) throws Exception;
}

PoiRead 简易处理方式

import java.util.ArrayList;
import java.util.List;
/**
 * 一种感觉比较好的处理方式。信息量比较全。
 * @author zq
 *
 */
public class PoiRead extends PoiAbstract {
    // 数据处理解析数据的接口
    private PoiOptRowsInterface poiOptRowsInterface;
    // 处理数据总数 (如果有总数包含总数)
    private int optRows_sum = 0;
    // 处理数据成功数量
    private int optRows_success = 0;
    // 处理数据失败数量
    private int optRows_failure = 0;
    // excel表格每列标题
    private List<String> rowtitle;
    // 失败数据
    private List<List<String>> failrows;
    // 失败原因
    private List<String> failmsgs;

    // 要处理数据所在的sheet索引,sheet索引从0开始
    private int sheetIndex;

    /**
     * @param path
     *            导入文件的物理路径
     * @param sheetIndex
     *            要读取数据所在sheet序号,从0开始
     * @param poiOptRowsInterface
     *            处理读取每一行数据的接口
     */
    PoiRead(String path, int sheetIndex, PoiOptRowsInterface poiOptRowsInterface) {
        super(path);
        this.sheetIndex = sheetIndex;
        this.poiOptRowsInterface = poiOptRowsInterface;
        this.rowtitle = new ArrayList<String>();
        this.failrows = new ArrayList<List<String>>();
        this.failmsgs = new ArrayList<String>();
    }

    @Override
    public void optRows(int sheetIndex, int curRow, List<String> rowlist) throws Exception {
        // 将rowlist的长度补齐和标题一致
        int k = rowtitle.size() - rowlist.size();
        for (int i = 0; i < k; i++) {
            rowlist.add(null);
        }
        if (sheetIndex == this.sheetIndex) {
            optRows_sum++;

            if (curRow == 0) {// 记录标题
                rowtitle.addAll(rowlist);
            } else {
                // 接口返回的结果是导入数据的结果,有成功,有失败
                String result = poiOptRowsInterface.optRows(sheetIndex, curRow, rowlist);
                if (result != null && !result.equals(PoiOptRowsInterface.SUCCESS)) {
                    optRows_failure++;// 失败统计数加1
                    // 失败数据列表
                    failrows.add(new ArrayList<String>(rowlist));
                    failmsgs.add(result);
                } else {
                    optRows_success++;
                }
            }

        }
    }

    public int getOptRows_sum() {
        return optRows_sum;
    }

    public void setOptRows_sum(int optRows_sum) {
        this.optRows_sum = optRows_sum;
    }

    public int getOptRows_success() {
        return optRows_success;
    }

    public void setOptRows_success(int optRows_success) {
        this.optRows_success = optRows_success;
    }

    public int getOptRows_failure() {
        return optRows_failure;
    }

    public void setOptRows_failure(int optRows_failure) {
        this.optRows_failure = optRows_failure;
    }

    public List<String> getRowtitle() {
        return rowtitle;
    }

    public void setRowtitle(List<String> rowtitle) {
        this.rowtitle = rowtitle;
    }

    public List<List<String>> getFailrows() {
        return failrows;
    }

    public void setFailrows(List<List<String>> failrows) {
        this.failrows = failrows;
    }

    public List<String> getFailmsgs() {
        return failmsgs;
    }

    public void setFailmsgs(List<String> failmsgs) {
        this.failmsgs = failmsgs;
    }


    //测试读取
    public static void main(String[] args) {
        PoiRead poiRead = new PoiRead("C:/Users/99299/Desktop/读取测试.xlsx", 0, new Impl());
        poiRead.process(0);
        System.out.println("处理数据总数:" + poiRead.getOptRows_sum());
        System.out.println("处理数据成功数量:" + poiRead.getOptRows_success());
        System.out.println("处理数据失败数量:" + poiRead.getOptRows_failure());
        System.out.println("excel表格每列标题:" + poiRead.getRowtitle());
        System.out.println("失败数据:" + poiRead.getFailrows());
        System.out.println("失败原因:" + poiRead.getFailmsgs());
    }

}

PoiRead的回调接口PoiOptRowsInterface

import java.util.List;

/**
 * 与 简易实现 PoiRead.java类配合使用的回调接口
 * @author zq
 *
 */
public interface PoiOptRowsInterface {
    public static final String SUCCESS = "success";

    /**
     * 处理excel文件每行数据方法
     * 
     * @param sheetIndex
     *            为sheet的序号
     * @param curRow
     *            为行号
     * @param rowlist
     *            行数据
     * @return success:返回 SUCCESS 或则 null 表示成功,否则为失败原因
     * @throws Exception
     */
    public String optRows(int sheetIndex, int curRow, List<String> rowlist) throws Exception;
}

使用示例

编写一个回调接口的实现类

编写该类的一些思路:这里回调给你的是,当前页数,当前处理的行,当前行的所有列数据
在构建该实现类的时候,可以加入各种与数据库的服务,和各种验证方法,比如:可以定义一些变量,把所要保留下来的数据存起来;在返回的字符串中,按照一定的格式记录错误的行和列,在前台jsp页面中就能做到把错误的列都飘红显示。等等。 这里就简单的打印下

import java.util.List;

public class Impl implements PoiOptRowsInterface {

    public String optRows(int sheetIndex, int curRow, List<String> rowlist) throws Exception {
        System.out.println( curRow + "行------------");
        for (String st : rowlist) {
            System.out.print(st + "\t");
        }
        System.out.println("");
        return "xxxxxxxxxx";
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值