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