POI實現一個通用的Excel讀取模板
阿新 • • 發佈:2019-01-06
POI是Apache基金會的提供的java實現的一套用於讀取Excel、Word、PPT等文件的庫,在實際專案中可能 很多地方都會用到Excel的讀取,比如Excel的匯入,我們不可能每個地方都單獨實現一套Excel的讀取方法,這時候就需要封裝一個通用的類,只要有讀取Excel的地方就呼叫該方法就可以了,下面我們就來實現它。
首先,為了提高可擴充套件性,也為了方便擴充套件到譬如Word、PPT這類文件,我們需要抽象出一個Template類,通過工廠方法來構建不同的Template。
然後,實現每個不同的Template,在實現過程中,我們還可以設定Listener,這樣只要實現了該監聽器,就能得到當前讀取到的值,方便擴充套件。
OK,下面請看具體的程式碼:
import java.io.InputStream; import java.io.Serializable; import java.util.List; import cn.sunsharp.poi.bean.Filter; /** * The template of POI. * All template must inherit this class. * @author lynn * */ public abstract class Template { protected List<Filter> filters; protected boolean ignore = false; public void setFilters(List<Filter> filters) { this.filters = filters; } public List<Filter> getFilters() { return filters; } public boolean isIgnore() { return ignore; } public void setIgnore(boolean ignore) { this.ignore = ignore; } /** * parse the excel、ppt、word etc. * it is a abstract method. * you can implement it. * @param inputStream * @return * @throws Exception */ public abstract List<Serializable> parse(InputStream inputStream)throws Exception; public abstract void parse(InputStream inputStream,TemplateListener listener)throws Exception; }
import java.io.InputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import cn.sunsharp.poi.bean.Excel; import cn.sunsharp.poi.bean.ExcelFilter; import cn.sunsharp.poi.bean.Filter; class ExcelTemplate extends Template { @Override public List<Serializable> parse(InputStream inputStream) throws Exception { OPCPackage pkg = null; List<Serializable> list = new ArrayList<Serializable>(); try{ pkg = OPCPackage.open(inputStream); XSSFWorkbook workbook = new XSSFWorkbook(pkg); int sheetNum = workbook.getNumberOfSheets(); XSSFSheet sheet = null; XSSFRow row = null; XSSFCell cell = null; Excel excel = null; for (int i = 0; i < sheetNum; i++) { sheet = workbook.getSheetAt(i); if(null == sheet){ continue; } for (int j = 0,rowNum = sheet.getLastRowNum(); j <= rowNum; j++) { row = sheet.getRow(j); if(null == row){ continue; } for (int k = 0,cellNum = row.getLastCellNum(); k <= cellNum; k++) { cell = row.getCell(k); if(null == cell){ continue; } excel = new Excel(); excel.setSheetName(sheet.getSheetName()); excel.setSheetIndex(i); excel.setCell(k); excel.setRow(j); excel.setValue(cell.toString()); list.add(excel); } } } }finally{ if(null != pkg){ pkg.close(); } } return filterData(list); } @Override public void parse(InputStream inputStream, TemplateListener listener) throws Exception { if(null == listener){ throw new NullPointerException("listener must not be null."); } List<Serializable> data = parse(inputStream); int size = 0; if(null != data && (size = data.size()) > 0){ Excel excel = null; for (int i = 0; i < size; i++) { excel = (Excel)data.get(i); listener.callback(excel); } } } /** * ignore為true,則不讀取filter指定的資料,為false則讀取filter指定的資料 * filter為空,則ignore引數失效,即讀取所有資料 * filter引數中,sheetIndex為空,則讀取所有sheet,row為空,則讀取所有row,cell為空,則讀取所有cell */ private List<Serializable> filterData(List<Serializable> list){ List<Serializable> data = new ArrayList<Serializable>(); int size = 0; if(null != list && (size = list.size()) > 0){ Excel excel = null; if(null != filters && filters.size() > 0){ for (int i = 0; i < size; i++) { excel = (Excel)list.get(i); for (Filter item : filters) { ExcelFilter filter = (ExcelFilter)item; Integer sheetIndex = filter.getSheetIndex(); Integer row = filter.getRow(); Integer cell = filter.getCell(); if(ignore){ if(null != sheetIndex && sheetIndex.intValue() == excel.getSheetIndex()){ continue; } if(null != row && row.intValue() == excel.getRow()){ continue; } if(null != cell && cell.intValue() == excel.getCell()){ continue; } data.add(excel); }else{ //如果三個都有值 if(null != sheetIndex && null != row && null != cell){ if(sheetIndex.intValue() == excel.getSheetIndex() && row.intValue() == excel.getRow() && cell.intValue() == excel.getCell()){ data.add(excel); } } //如果sheetIndex沒有值,row和cell有值 if(null == sheetIndex && null != row && null != cell){ if(row.intValue() == excel.getRow() && cell.intValue() == excel.getCell()){ data.add(excel); } } //如果row沒有值,sheetIndex和cell有值 if(null == row && null != sheetIndex && null != cell){ if(sheetIndex.intValue() == excel.getSheetIndex() && cell.intValue() == excel.getCell()){ data.add(excel); } } //如果cell沒有值,sheetIndex和row有值 if(null == cell && null != sheetIndex && null != row){ if(sheetIndex.intValue() == excel.getSheetIndex() && row.intValue() == excel.getRow()){ data.add(excel); } } //如果只有sheetIndex有值 if(null == row && null == cell && null != sheetIndex){ if(sheetIndex.intValue() == excel.getSheetIndex()){ data.add(excel); } } //如果只有row有值 if(null == cell && null == sheetIndex && null != row){ if(row.intValue() == excel.getRow()){ data.add(excel); } } //如果只有cell有值 if(null == sheetIndex && null == row && null != cell){ if(cell.intValue() == excel.getCell()){ data.add(excel); } } } } } }else{ data.addAll(list); } } return data; } }
import java.io.Serializable;
/**
* template listener
* you can implement this interface to push to your custom class.
* @author lynn
*
*/
public interface TemplateListener {
public void callback(Serializable entity);
}
import cn.sunsharp.poi.enumeration.POI;
public class TemplateFactory {
/**
* via the factory to create template
* @param poi
* @return
*/
public static Template create(POI poi){
switch(poi){
case Excel:
return new ExcelTemplate();
case PPT:
break;
case Word:
break;
case PDF:
break;
}
return null;
}
}
public enum POI {
Excel,PPT,Word,PDF
}
import java.io.Serializable;
/**
* the excel bean.
* @author administrator
*
*/
public class Excel implements Serializable {
private static final long serialVersionUID = -7606795591653370811L;
private String sheetName;
private int sheetIndex;
private int row;
private int cell;
private String value;
public String getSheetName() {
return sheetName;
}
public void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
public int getSheetIndex() {
return sheetIndex;
}
public void setSheetIndex(int sheetIndex) {
this.sheetIndex = sheetIndex;
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getCell() {
return cell;
}
public void setCell(int cell) {
this.cell = cell;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "Excel [sheetName=" + sheetName + ", sheetIndex=" + sheetIndex
+ ", row=" + row + ", cell=" + cell + ", value=" + value + "]";
}
}
public class Filter {
}
public class ExcelFilter extends Filter {
private Integer sheetIndex;
private Integer row;
private Integer cell;
public static Builder options(){
return new Builder();
}
public static class Builder{
private Integer sheetIndex;
private Integer row;
private Integer cell;
public Builder setSheetIndex(Integer sheetIndex){
this.sheetIndex = sheetIndex;
return this;
}
public Builder setRow(Integer row){
this.row = row;
return this;
}
public Builder setCell(Integer cell){
this.cell = cell;
return this;
}
public ExcelFilter build(){
return new ExcelFilter(this);
}
}
private ExcelFilter(Builder builder){
this.sheetIndex = builder.sheetIndex;
this.row = builder.row;
this.cell = builder.cell;
}
public Integer getSheetIndex() {
return sheetIndex;
}
public Integer getRow() {
return row;
}
public Integer getCell() {
return cell;
}
@Override
public String toString() {
return "ExcelFilter [sheetIndex=" + sheetIndex + ", row=" + row
+ ", cell=" + cell + "]";
}
}
通過以上程式碼,我們發現,在Template有Filter和ignore兩個屬性,Filter是過濾器,ignore如果為true,則不讀取filter指定的資料,ignore為false,則只讀取filter指定的資料,
這樣就完成了比較優雅的可擴充套件的Excel讀取,我們如果要讀取PPT,就構建一個PPTTemplate來實現Template抽象類即可。下面請看測試類:
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import cn.sunsharp.poi.bean.Excel;
import cn.sunsharp.poi.bean.ExcelFilter;
import cn.sunsharp.poi.bean.Filter;
import cn.sunsharp.poi.enumeration.POI;
import cn.sunsharp.poi.template.Template;
import cn.sunsharp.poi.template.TemplateFactory;
import cn.sunsharp.poi.template.TemplateListener;
public class Test implements TemplateListener{
public static void main(String[] args) throws Exception{
new Test().testExcel();
}
private List<String> headers = new ArrayList<String>();
private void testExcel()throws Exception{
String path = "C:\\Users\\administrator.YCSPC017\\Desktop\\農產品行業體系新舊編碼對比.xlsx";
Template template = TemplateFactory.create(POI.Excel);
List<Filter> filters = new ArrayList<Filter>();
ExcelFilter filter = ExcelFilter.options()
.setRow(0)
.setSheetIndex(2)
.build();
filters.add(filter);
// filter = ExcelFilter.options()
// .setRow(1)
// .setSheetIndex(1)
// .setCell(1)
// .build();
// filters.add(filter);
template.setFilters(filters);
template.setIgnore(false);
InputStream inputStream = new FileInputStream(path);
template.parse(inputStream,this);
System.out.println(headers);
}
@Override
public void callback(Serializable entity){
Excel excel = (Excel)entity;
headers.add(excel.getValue());
}
}
import java.io.Serializable;
public class Category implements Serializable{
private static final long serialVersionUID = 2348166129263260641L;
private String name;
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Category [name=" + name + ", id=" + id + "]";
}
}
如果有問題,可以給我留言哦!