java基于poi操作Excel

一、环境配置

我们通过学习知道,java操作Excel时需要在maven工程中的pom.xml文件添加poi-ooxml的依赖包,眼下我们选择的版本是3.17,因为相对稳定且使用率较高。配置路径以及结果如下:


二、poi-ooxml源码类学习

我们安装好依赖后按照业务需要,即操作Excel表格(当前不涉及Excel的写入,只有读取操作),会学习到四个源码类,分别是XSSFWorkbook源码类、XSSFSheet源码类、XSSFRow源码类和XSSFCell源码类。学习源码的一个大体节奏是通过源码类先学习类的构造方法,然后是普通方法最后汇总源码方法,进行流水线开发。现在我先把四个源码类的常用方法总结下来,具体如下。

2.1 XSSFWorkbook源码类[public class XSSFWorkbook extends POIXMLDocument implements Workbook]。(路径:poi-ooxml-3.17.jar-->org.apache.poi.xssf.usermodel-->XSSFWorkbook.clss):

//构造方法

public XSSFWorkbook();

public XSSFWorkbook(XSSFWorkbookType workbookType);

// public XSSFWorkbook(OPCPackage pkg) throws IOException;

// public XSSFWorkbook(InputStream is) throws IOException;

public XSSFWorkbook(File file) throws IOException, InvalidFormatException;

---上面构造方法引出File源码类,通过实例话File类拿到File类的对象,传参,获取XSSFWorkbook的对象。

public XSSFWorkbook(String path) throws IOException;

//普通方法

public XSSFSheet cloneSheet(int sheetNum);

public XSSFSheet cloneSheet(int sheetNum, String newName);

public XSSFSheet createSheet();

public XSSFSheet createSheet(String sheetname);

public XSSFSheet getSheet(String name);

public XSSFSheet getSheetAt(int index);

public int getSheetIndex(String name);

public int getSheetIndex(Sheet sheet);

public String getSheetName(int sheetIx);

public void removeSheetAt(int index);

public void setSheetName(int sheetIndex, String sheetname);

2.2 XSSFSheet源码类[public class XSSFSheet extends POIXMLDocumentPart implements Sheet]。上面我们观察到普通方法内创建Sheet、获取Sheet等方法最终都会得到一个sheet对象,那么XSSFSheet源码类又有哪些方法提供给我们使用呢?

// 构造方法

protected XSSFSheet();

protected XSSFSheet(PackagePart part);

注意:XSSFSheet源码类的构造方法都是被保护类型的,不能直接调用,我们可以通过XSSFWorkbook源码类拿到sheet对象,操作XSSFSheet源码类中的方法。

// 普通方法

public XSSFWorkbook getWorkbook();

public String getSheetName();

public int getColumnWidth(int columnIndex);

public int getDefaultColumnWidth();

public boolean isColumnHidden(int columnIndex);

public void setColumnHidden(int columnIndex, boolean hidden);

public void setColumnWidth(int columnIndex, int width);

public void setDefaultColumnWidth(int width)

public int getFirstRowNum();

public int getLastRowNum();

public short getDefaultRowHeight();

public void setDefaultRowHeight(short height);

public XSSFRow createRow(int rownum);

public XSSFRow getRow(int rownum);

public void removeRow(Row row)

2.3 XSSFRow源码类[public class XSSFRow implements Row, Comparable]。上面我们可以看到由XSSFWorkbook类对象操作XSSFSheet类中的方法可以得到XSSFRow类的对象。得到行对象后就可以操作XSSFRow源码类中的方法。

// 构造方法

protected XSSFRow(CTRow row, XSSFSheet sheet);

同XSSFSheet源码类,XSSFRow源码类的构造方法也是被保护的,解决方法类似。

// 普通方法

public XSSFSheet getSheet();

public XSSFCell createCell(int columnIndex);

public XSSFCell createCell(int columnIndex, CellType type);

public XSSFCell getCell(int cellnum);

public short getFirstCellNum();

public short getLastCellNum();  // 特殊点:从1开始计数。

public int getRowNum();

public void setRowNum(int rowIndex);

public void removeCell(Cell cell);

2.4 XSSFCell源码类[public final class XSSFCell implements Cell ]。同样的道理,我们来看一下XSSFCell源码类中都有哪些构造方法和普通方法。

// 构造方法

protected XSSFCell(XSSFRow row, CTCell cell);

// 普通方法

public XSSFSheet getSheet();

public XSSFRow getRow();

public boolean getBooleanCellValue();

public void setCellValue(boolean value);

public double getNumericCellValue();

public void setCellValue(double value);

public String getStringCellValue();

public void setCellValue(String str);

public XSSFRichTextString getRichStringCellValue();

public void setCellValue(RichTextString str);

public String getCellFormula();

public void setCellFormula(String formula);

public Date getDateCellValue();

public void setCellValue(Date value);

public String getErrorCellString() throws IllegalStateException;

public void setCellErrorValue(byte errorCode);

public int getColumnIndex();

public int getRowIndex();

public CellType getCellTypeEnum();

三、现在我们已经总结了以上四个源码类中的方法,下面我们就可以写流水线代码了。

import java.io.IOException;

import java.util.Date;

import org.apache.poi.ss.usermodel.CellType;

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;

//流水线代码

public class TestUtil {

public static void main(String[] args) throws Exception {

XSSFWorkbook wb = new XSSFWorkbook("/Users/xxxxxxxxx/testdata/app_testcase.xlsx");

XSSFSheet getSheet = wb.getSheetAt(3);

XSSFRow getRow = getSheet.getRow(1);

XSSFCell getCell = getRow.getCell(2);

CellType cellType = getCell.getCellTypeEnum();

System.out.println(getSheet.getLastRowNum());

System.out.println(getRow.getFirstCellNum());

System.out.println(getRow.getLastCellNum());

switch(cellType) {

case _NONE:

System.out.println("_NONEvalue为空。");

break;

case NUMERIC:

double numValue = getCell.getNumericCellValue();

System.out.println("numValue = " + numValue);

break;

case STRING:

String strValue = getCell.getStringCellValue();

System.out.println("strValue = " + strValue);

break;

case FORMULA:

String formulaValue = getCell.getCellFormula();

System.out.println("formulaValue = " + formulaValue);

case BLANK:

System.out.println("BLANKvalue为空。");

break;

case BOOLEAN:

boolean booleanValue = getCell.getBooleanCellValue();

System.out.println("booleanValue = " + booleanValue);

break;

case ERROR:

System.out.println("没见过这种格式的单元格。");

break;

default:

Date dateValue = getCell.getDateCellValue();

System.out.println("dateValue = " + dateValue);

break;

}

}

}

四、第一次封装代码。原则上一个源码类我们封装成一个方法,不同的源码类封装成不同的方法。此次封装得到3个方法,分别是:获取workbook、获取sheet、获取单元格的值。

import java.io.IOException;

import java.util.Date;

import org.apache.poi.ss.usermodel.CellType;

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;

//第一次封装流水线代码

public class TestUtil2 {

//私有属性

private String filePath;

//构造方法

public TestUtil2(String filePath) {

this.filePath = filePath;

}

//普通方法,获取workbook

public XSSFWorkbook getWb() throws Exception {

XSSFWorkbook wb = new XSSFWorkbook(this.filePath);

return wb;

}

//普通方法,获取sheet。通过workbook,根据下标拿到excel表格,即sheet。

public XSSFSheet getSheet(int sheetIndex) throws Exception {

XSSFWorkbook wb = getWb();

XSSFSheet sheet = wb.getSheetAt(sheetIndex);

return sheet;

}

//普通方法,获取某一个单元格的值。通过拿到的sheet表格,拿到某一行;通过这一行拿到这一行的某一列的单元格;通过该单元格属性,使用不同方法获取该单元格的值。

public Object getCellValue(int sheetIndex, int rowIndex, int cellIndex) throws Exception {

Object value = null;

XSSFSheet sheet = getSheet(sheetIndex);

XSSFRow row = sheet.getRow(rowIndex);

XSSFCell cell = row.getCell(cellIndex);

CellType cellType = cell.getCellTypeEnum();

switch(cellType) {

case _NONE:

value = "";

break;

case NUMERIC:

value = cell.getNumericCellValue();

break;

case STRING:

value = cell.getStringCellValue();

break;

case FORMULA:

value = cell.getCellFormula();

case BLANK:

value = "";

break;

case BOOLEAN:

value = cell.getBooleanCellValue();

break;

case ERROR:

System.out.println("没见过这种格式的单元格。");

break;

default:

value = cell.getDateCellValue();

break;

}

return value;

}

public static void main(String[] args) throws Exception {

TestUtil2 tu2 = new TestUtil2("/Users/xxxxxxx/testdata/app_testcase.xlsx");

Object value = tu2.getCellValue(1, 1, 3);

System.out.println("第2个表格的第二行第四列的值是:" + value);

}

}

五、第二次封装代码。此次封装主要针对上面获取单元格的值做了拆解。由一个方法拆分成两个方法,抽离出直接通过cell对象就能直接返回单元格的值的方法。

import java.io.IOException;

import java.util.Date;

import org.apache.poi.ss.usermodel.CellType;

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;

//第二次封装流水线代码

public class TestUtil3 {

//私有属性

private String filePath;

//构造方法

public TestUtil3(String filePath) {

this.filePath = filePath;

}

//普通方法,获取workbook

public XSSFWorkbook getWb() throws Exception {

XSSFWorkbook wb = new XSSFWorkbook(this.filePath);

return wb;

}

//普通方法,获取sheet。通过workbook,根据下标拿到excel表格,即sheet。

public XSSFSheet getSheet(int sheetIndex) throws Exception {

XSSFWorkbook wb = getWb();

XSSFSheet sheet = wb.getSheetAt(sheetIndex);

return sheet;

}

//普通方法,获取某一个单元格的值。通过拿到的sheet表格,拿到某一行;通过这一行拿到这一行的某一列的单元格;通过该单元格属性,使用不同方法获取该单元格的值。

public Object getCellValue(int sheetIndex, int rowIndex, int cellIndex) throws Exception {

XSSFSheet sheet = getSheet(sheetIndex);

XSSFRow row = sheet.getRow(rowIndex);

XSSFCell cell = row.getCell(cellIndex);

Object value = fromCellGetCellValue(cell);

return value;

}

//普通方法,获取单元格的值。通过只传一个cell单元格对象就能返回单元格的值

public Object fromCellGetCellValue(XSSFCell cell) {

Object value = null;

CellType cellType = cell.getCellTypeEnum();

switch(cellType) {

case _NONE:

value = "";

break;

case NUMERIC:

value = cell.getNumericCellValue();

break;

case STRING:

value = cell.getStringCellValue();

break;

case FORMULA:

value = cell.getCellFormula();

case BLANK:

value = "";

break;

case BOOLEAN:

value = cell.getBooleanCellValue();

break;

case ERROR:

System.out.println("没见过这种格式的单元格。");

break;

default:

value = cell.getDateCellValue();

break;

}

return value;

}

public static void main(String[] args) throws Exception {

TestUtil3 tu2 = new TestUtil3("/Users/xxxxxxx/testdata/app_testcase.xlsx");

Object value = tu2.getCellValue(1, 1, 3);

System.out.println("第2个表格的第二行第四列的值是:" + value);

}

}

六、第三次封装代码。第三次封装主要是根据二维数组和Excel表格的相似性(都是通过两个坐标来定位一个元素)来把Excel表格的数据存储到二维数组内,再通过二维数组坐标取值,或者通过两层for循环拿到二维数组的全部值。

import org.apache.poi.ss.usermodel.CellType;

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;

//第三次封装流水线代码

public class TestUtil4 {

//私有属性

private String filePath;

//构造方法

public TestUtil4(String filePath) {

this.filePath = filePath;

}

//普通方法,获取workbook

public XSSFWorkbook getWb() throws Exception {

XSSFWorkbook wb = new XSSFWorkbook(this.filePath);

return wb;

}

//普通方法,获取sheet。通过workbook,根据下标拿到excel表格,即sheet。

public XSSFSheet getSheet(int sheetIndex) throws Exception {

XSSFWorkbook wb = getWb();

XSSFSheet sheet = wb.getSheetAt(sheetIndex);

return sheet;

}

//普通方法,获取某一个单元格的值。通过拿到的sheet表格,拿到某一行;通过这一行拿到这一行的某一列的单元格;通过该单元格属性,使用不同方法获取该单元格的值。

public Object getCellValue(int sheetIndex, int rowIndex, int cellIndex) throws Exception {

XSSFSheet sheet = getSheet(sheetIndex);

XSSFRow row = sheet.getRow(rowIndex);

XSSFCell cell = row.getCell(cellIndex);

Object value = fromCellGetCellValue(cell);

return value;

}

//普通方法,获取单元格的值。通过只传一个cell单元格对象就能返回单元格的值

public Object fromCellGetCellValue(XSSFCell cell) {

Object value = null;

CellType cellType = cell.getCellTypeEnum();

switch(cellType) {

case _NONE:

value = "";

break;

case NUMERIC:

value = cell.getNumericCellValue();

break;

case STRING:

value = cell.getStringCellValue();

break;

case FORMULA:

value = cell.getCellFormula();

case BLANK:

value = "";

break;

case BOOLEAN:

value = cell.getBooleanCellValue();

break;

case ERROR:

System.out.println("没见过这种格式的单元格。");

break;

default:

value = cell.getDateCellValue();

break;

}

return value;

}

//普通方法,获取整个Excel的数据。通过Excel的坐标定位到cell单元格对象,由上面的fromCellGetCellValue方法得到该单元格的值;再定义一个二维数组接收所有单元格的值。

//注意:二位数组的下表要和excel中想要获取的值的下表对应。

public Object[][] getArrayExcelValue(int sheetIndex) throws Exception{

XSSFSheet sheet =getSheet(sheetIndex);

int lastRowNum = sheet.getLastRowNum();

// int lastCellnum = sheet.getl

Object[][] testData = new Object[lastRowNum][11];

for(int i=1;i

XSSFRow row = sheet.getRow(i);

if(row==null) {continue;}

for(int j=row.getFirstCellNum();j

XSSFCell cell = row.getCell(j);

if(cell==null) {continue;}

testData[i-1][j] = fromCellGetCellValue(cell);

// testData[i-1][j] = getCellValue(sheetIndex, i, j);

}

}

return testData;

}

//普通方法,输出二维数组

public static void outPutArray(Object[][] data){

for(int i=0;i

for(int j=0;j

Object value = data[i][j];

System.out.print(value + " ");

}

System.out.print("\n");

}

}

public static void main(String[] args) throws Exception {

// TestUtil4 tu2 = new TestUtil4("/Users/zhaoxiaodong/testdata/app_testcase.xlsx");

// Object value = tu2.getCellValue(1, 1, 3);

// System.out.println("第2个表格的第二行第四列的值是:" + value);

TestUtil4 tu4 = new TestUtil4("/Users/zhaoxiaodong/testdata/app_testcase.xlsx");

Object[][] testData = tu4.getArrayExcelValue(3);

// System.out.println(testData);

System.out.println(testData[1][1]);

outPutArray(testData);

}

}

完美,完毕!

你可能感兴趣的:(java基于poi操作Excel)