POI的名字来源于Poor Obfuscation Implementation (蹩脚的模糊实现),是说虽然特意对文件格式进行了模糊处理,但是仍然可以成功使用反向工程。
使用POI前,添加POI的MAVEN依赖,
< dependency > < groupId >org.apache.poi</ groupId > < artifactId >poi</ artifactId > < version >3.8</ version > </ dependency > |
也可以直接下载JAR包放入CLASSPATH.
读取 Excel 文件
如下列,从EXCEL的单元中读取内容:
import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; //.. FileInputStream
file = new FileInputStream( new File( "C:\\test.xls" )); //获取XLS文件的工作簿实例 HSSFWorkbook
workbook = new HSSFWorkbook(file); //获取工作簿的第一张工作表 HSSFSheet
sheet = workbook.getSheetAt( 0 ); //获取当前工作表的行迭代器 Iterator<Row>
rowIterator = sheet.iterator(); //获取当前行所有单元的迭代器 Iterator<Cell>
cellIterator = row.cellIterator(); |
注意,必须使用HSSF开头的POI类库。
POI 处理文件的类库分为以下几类:
- HSSF– XLS文件
- XSSF– XLSX文件
- HWPF - Microsoft Word 97 (DOC) 文件
-
XWPF - DOCX文件
- HSLF– Microsoft PowerPoint 文件.
- HDGF– Microsoft Visio 二进制文件.
- HPBF – Microsoft Publisher 文件.
- HSMF– Microsoft Outlook MSG 文件
读写 .xlsx 文件
上面代码中的
HSSFWorkbook
和 HSSFSheet
用于 .xls 格式。对于.xlsx格式的文件,你需要使用更新的
POI 类:
import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.xssf.usermodel.XSSFSheet; //.. FileInputStream
file = new FileInputStream( new File( "C:\\test.xlsx" )); //获取XLS文件的工作簿实例 XSSFWorkbook
workbook = new XSSFWorkbook
(file); //获取工作簿的第一张工作表 XSSFSheet
sheet = workbook.getSheetAt( 0 ); //获取当前工作表的行迭代器 Iterator<Row>
rowIterator = sheet.iterator(); //获取当前行所有单元的迭代器 Iterator<Cell>
cellIterator = row.cellIterator(); |
使用 XSSFWorkbook
和 XSSFSheet
类读写
.xlsx 文件。
例如:
test.xls
现在,我们使用Apache POI 读取该XLS文件并打印数据。
try { FileInputStream
file = new FileInputStream( new File( "C:\\test.xls" )); //获取XLS文件的工作簿实例 HSSFWorkbook
workbook = new HSSFWorkbook(file); //获取工作簿的第一张工作表 HSSFSheet
sheet = workbook.getSheetAt( 0 ); //从第一张工作表开始迭代每一行 Iterator<Row>
rowIterator = sheet.iterator(); while (rowIterator.hasNext())
{ Row
row = rowIterator.next(); //迭代每一行的每一列 Iterator<Cell>
cellIterator = row.cellIterator(); while (cellIterator.hasNext())
{ Cell
cell = cellIterator.next(); switch (cell.getCellType())
{ case Cell.CELL_TYPE_BOOLEAN: System.out.print(cell.getBooleanCellValue()
+ "\t\t" ); break ; case Cell.CELL_TYPE_NUMERIC: System.out.print(cell.getNumericCellValue()
+ "\t\t" ); break ; case Cell.CELL_TYPE_STRING: System.out.print(cell.getStringCellValue()
+ "\t\t" ); break ; } } System.out.println( "" ); } file.close(); FileOutputStream
out = new FileOutputStream( new File( "C:\\test.xls" )); workbook.write(out); out.close(); } catch (FileNotFoundException
e) { e.printStackTrace(); } catch (IOException
e) { e.printStackTrace(); } |
在读单元的内容前,我们需要使用方法 cell.getCellType()
获取单元的类型,然后调用合适的方法读取内容。
输出:
Emp
Id Name Salary 1.0
John 2000000.0 2.0
Dean 420000.0 3.0
Sam 280000.0 4.0
Cass 6000000.0 |
3. 创建新的 Excel 文件
代码如下:
import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; //.. HSSFWorkbook
workbook = new HSSFWorkbook(); HSSFSheet
sheet = workbook.createSheet( "Sample
sheet" ); //在当前工作表中创建新行 Row
row = sheet.createRow( 0 ); //在当前行中创建一个单元 Cell
cell = row.createCell( 0 ); //设置单元格的值 cell.setCellValue( "Blahblah" ); |
下面的代码把虚构的数据写入一个新的EXCEL文件中。
HSSFWorkbook
workbook = new HSSFWorkbook(); HSSFSheet
sheet = workbook.createSheet( "Sample
sheet" ); Map<String,
Object[]> data = new HashMap<String,
Object[]>(); data.put( "1" , new Object[]
{ "Emp
No." , "Name" , "Salary" }); data.put( "2" , new Object[]
{1d, "John" ,
1500000d}); data.put( "3" , new Object[]
{2d, "Sam" ,
800000d}); data.put( "4" , new Object[]
{3d, "Dean" ,
700000d}); Set<String>
keyset = data.keySet(); int rownum
= 0 ; for (String
key : keyset) { Row
row = sheet.createRow(rownum++); Object
[] objArr = data.get(key); int cellnum
= 0 ; for (Object
obj : objArr) { Cell
cell = row.createCell(cellnum++); if (obj instanceof Date) cell.setCellValue((Date)obj); else if (obj instanceof Boolean) cell.setCellValue((Boolean)obj); else if (obj instanceof String) cell.setCellValue((String)obj); else if (obj instanceof Double) cell.setCellValue((Double)obj); } } try { FileOutputStream
out = new FileOutputStream( new File( "C:\\new.xls" )); workbook.write(out); out.close(); System.out.println( "Excel
written successfully.." ); } catch (FileNotFoundException
e) { e.printStackTrace(); } catch (IOException
e) { e.printStackTrace(); } |
输出: new.xls
4. 修改Excel 文件的内容
修改EXCEL文件的内容简单直接。用前面讨论的API打开EXCEL,然后设置单元的值。请注意,只有在关闭EXCEL文件后,我们才能更新EXCEL的文件。
update.xls
下列代码读取单元里面的工资,然后把工资乘2
try { FileInputStream
file = new FileInputStream( new File( "C:\\update.xls" )); HSSFWorkbook
workbook = new HSSFWorkbook(file); HSSFSheet
sheet = workbook.getSheetAt( 0 ); Cell
cell = null ; //更新单元的值 cell
= sheet.getRow( 1 ).getCell( 2 ); cell.setCellValue(cell.getNumericCellValue()
* 2 ); cell
= sheet.getRow( 2 ).getCell( 2 ); cell.setCellValue(cell.getNumericCellValue()
* 2 ); cell
= sheet.getRow( 3 ).getCell( 2 ); cell.setCellValue(cell.getNumericCellValue()
* 2 ); //关闭文件
(很重要,别忘记) file.close(); FileOutputStream
outFile = new FileOutputStream( new File( "C:\\update.xls" )); workbook.write(outFile); outFile.close(); } catch (FileNotFoundException
e) { e.printStackTrace(); } catch (IOException
e) { e.printStackTrace(); } |
修改EXCEL文件的步骤是:
- 用读取(输入流)模式打开EXCEL文件 (inputstream)
- 使用POI API 读取excel 的内容
-
使用不同的
setCellValue
方法设置单元的值. - 关闭EXCEL的输入文件(inputstream)
- 用写模式(输入流)打开相同的 excel 文件 (outputstream)
- 把修改后的工作簿内容写出输出文件
- 关闭excel 输出文件流
输出: update.xls