一、POI
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能,简单来说就是能在Java程序中导入导出Word,Excel,PPT,Visio等文件内容。
二、使用POI
运行环境:
IDEA 2019.3.3 x64
JDK 1.8.0_241
Maven 3.6.3
我将以Excel表格的导入导出为例,演示如何使用POI。
1.创建Maven项目
新建Maven项目,通过模板创建可以更快捷。
配置电脑中已安装的Maven
2.pom.xml文件添加依赖
在下图位置添加POI依赖:
导入依赖如下:
<!-- POI依赖 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
pom.xml文件完整代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>poi_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>poi_demo Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- POI依赖 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
</dependencies>
<build>
<finalName>poi_demo</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
3.导出
代码如下:
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class POIdemo {
// Excel数据导出
public static void main(String[] args) {
// Excel2003版本(包含2003)以前使用HSSFWorkbook类,扩展名为.xls
// Excel2007版本(包含2007)以后使用XSSFWorkbook类,扩展名为.xlsx
// 创建工作簿类
XSSFWorkbook workbook = new XSSFWorkbook();
// 创建工作表并设置表名
XSSFSheet sheet = workbook.createSheet("学生信息");
// 创建行,下标从0开始
XSSFRow row = sheet.createRow(0);
// 在行中创建列并赋值,下标从0开始
row.createCell(0).setCellValue("学号");
row.createCell(1).setCellValue("姓名");
row.createCell(2).setCellValue("专业");
row.createCell(3).setCellValue("班级");
row = sheet.createRow(1);
row.createCell(0).setCellValue("2018010627");
row.createCell(1).setCellValue("赵国庆");
row.createCell(2).setCellValue("软件工程");
row.createCell(3).setCellValue("软件1806");
// 设置Excel文件路径
File file = new File("C:\\Users\\lenovo\\Desktop\\poi_demo.xlsx");
try {
// 创建指向该路径的输出流
FileOutputStream stream = new FileOutputStream(file);
// 将数据导出到Excel表格
workbook.write(stream);
// 关闭输出流
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行效果图:
4.导入
代码如下:
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.*;
public class POIdemo {
// Excel数据导出
public static void main(String[] args) {
// 创建文件并指定文件路径
File file = new File("C:\\Users\\lenovo\\Desktop\\poi_demo.xlsx");
try {
// 创建改文件的输入流
FileInputStream stream = new FileInputStream(file);
// 创建工作簿
XSSFWorkbook workbook = new XSSFWorkbook(stream);
// 获取一个工作表,下标从0开始
XSSFSheet sheet = workbook.getSheetAt(0);
// 通过循环,逐行取出表中每行数据
for(int i=0;i<=sheet.getLastRowNum();i++){
// 获取行
XSSFRow row = sheet.getRow(i);
// 获取行中列的数据
String[] value = new String[4];
value[0] = row.getCell(0).getStringCellValue();
value[1] = row.getCell(1).getStringCellValue();
value[2] = row.getCell(2).getStringCellValue();
value[3] = row.getCell(3).getStringCellValue();
for (String data:value) {
System.out.println(data);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行效果图:
三、自定义工具类
/**
* author:赵国庆
* date:2023/1/14
* name:Excel导入/导出工具类
*/
public class ExcelTool {
/**
* message:Excel导出功能
* @param excelName Excel文件名
* @param excelOutPath Excel文件保存路径
* @param rowList Excel的内容
* @return
*/
public String excelOut(String excelName, String excelOutPath, ArrayList<ArrayList> rowList) {
String status = "0"; // 设置导出方法执行结果,0失败,1成功,2成功但文件名已存在
String message = ""; // 设置提示信息
JSONObject obj = new JSONObject(); // 存放执行信息status和message
// 创建工作簿类
// Excel2003版本(包含2003)以前使用HSSFWorkbook类,扩展名为.xls
// Excel2007版本(包含2007)以后使用XSSFWorkbook类,扩展名为.xlsx
XSSFWorkbook workbook = new XSSFWorkbook();
// 创建工作表并设置表名,表名为 传入的表名参数,请注意工作表名不是Excel文件名
XSSFSheet sheet = workbook.createSheet(excelName);
// 工作表中的行
XSSFRow row = null;
// rowList为预导出的数据集,结构为ArrayList套ArraList,外层为行,里层为列,如下图所示
// [ excel内容
// [第一列, 第二列, 第三列 ...], excel第一行
// [第一列, 第二列, ...], excel第二行
// [第一列, ...], excel第三行
// ... 以此类推
// ]
int rowNum = 0; // 行下标
// 创建excel行
for (ArrayList<String> colList: rowList) {
row = sheet.createRow(rowNum);
int colNum = 0; // 列下标
// 对每行逐列插入值
for (String colValue: colList) {
row.createCell(colNum).setCellValue(colValue);
colNum++;
}
rowNum++;
}
// 设置Excel文件路径,例如:E:\ + 学生表 + 20230114(这是我自己写的时间获取方法,别人用不了,删了就行) + .xlsx
String excelFileName = excelOutPath + excelName + CalendarTool.getTodayNum() + ".xlsx";
File outExcleFile = new File(excelFileName);
int fileVersion = 0;
// 判断路径下是否存在同名文件,如果不进行判断,会覆盖同名文件内容,造成同名信息丢失
// 所以,若存在同名文件,给文件名加(1)、(2)这样的标识
while (outExcleFile.exists()) {
fileVersion++;
excelFileName = excelOutPath + excelName + CalendarTool.getTodayNum() + "(" + fileVersion + ").xlsx";
outExcleFile = new File(excelFileName);
}
try {
// 创建指向该路径的输出流
FileOutputStream stream = new FileOutputStream(outExcleFile);
// 将数据导出到Excel表格
workbook.write(stream);
// 关闭输出流
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("excel导出失败。");
obj.put("status", status);
obj.put("message", "excel导出失败。");
return obj.toJSONString();
} catch (IOException e) {
e.printStackTrace();
}
if (fileVersion == 0) {
System.out.println("导出成功,保存路径为:" + excelFileName);
obj.put("status", "1");
obj.put("message", "导出成功,保存路径为:" + excelFileName);
return obj.toJSONString();
} else {
System.out.println("导出成功,保存路径为:" + excelFileName);
obj.put("status", "2");
obj.put("message", "导出成功,保存路径为:" + excelFileName);
return obj.toJSONString();
}
}
/**
* message:Excel导出功能,浏览器下载
* @param excelName Excel文件名
* @param rowList Excel的内容
* @return
*/
public String excelOutOnBrowser(HttpServletResponse resp, String excelName, ArrayList<ArrayList> rowList) {
String status = "0"; // 设置导出方法执行结果,0失败,1成功,2成功但文件名已存在
String message = ""; // 设置提示信息
JSONObject obj = new JSONObject(); // 存放执行信息status和message
// 创建工作簿类
// Excel2003版本(包含2003)以前使用HSSFWorkbook类,扩展名为.xls
// Excel2007版本(包含2007)以后使用XSSFWorkbook类,扩展名为.xlsx
XSSFWorkbook workbook = new XSSFWorkbook();
// 创建工作表并设置表名,表名为 传入的表名参数,请注意工作表名不是Excel文件名
XSSFSheet sheet = workbook.createSheet(excelName);
// 工作表中的行
XSSFRow row = null;
// rowList为预导出的数据集,结构为ArrayList套ArraList,外层为行,里层为列,如下图所示
// [ excel内容
// [第一列, 第二列, 第三列 ...], excel第一行
// [第一列, 第二列, ...], excel第二行
// [第一列, ...], excel第三行
// ... 以此类推
// ]
int rowNum = 0; // 行下标
// 创建excel行
for (ArrayList<String> colList: rowList) {
row = sheet.createRow(rowNum);
int colNum = 0; // 列下标
// 对每行逐列插入值
for (String colValue: colList) {
row.createCell(colNum).setCellValue(colValue);
colNum++;
}
rowNum++;
}
// 设置Excel文件名,例如:学生表 + 20230114(这是我自己写的时间获取方法,别人用不了,删了就行) + .xlsx
String excelFileName = excelName + CalendarTool.getTodayNum() + ".xlsx";
try {
// 设置响应格式,让浏览器知道是下载操作
resp.setContentType("applicaton/x-mdownload");
// 设置下载后的文件名
resp.setHeader("Content-Disposition", "atachment;filename=" + new String(excelFileName.getBytes("utf-8"),"ISO8859-1"));
// 设置响应编码
resp.setContentType("text/html;charcet=UTF-8");
// 建立输出流的连接
OutputStream outputStream = resp.getOutputStream();
// 将数据导出到Excel表格
workbook.write(outputStream);
// 关闭输出流
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("excel导出失败。");
obj.put("status", status);
obj.put("message", "excel导出失败。");
return obj.toJSONString();
} catch (IOException e) {
e.printStackTrace();
}
status = "1";
obj.put("status", status);
obj.put("message", "excel导出成功。");
return obj.toJSONString();
}
/**
* name:Excel导入功能
* remark:该Excel导入功能,是一张表对应一个实体类,一行对应一条实体对象信息,一列对应一项实体对象属性
* 所以针对不同实体类,需要进行微调
* @param excelFile 预导入的Excel文件
* @return
*/
public List<Student> excelInput(MultipartFile excelFile) {
String excelFileName = excelFile.getOriginalFilename(); // 获取excel文件名
int excelVersion = getExcelVersion(excelFileName); // 获取excel文件的版本
Workbook workbook = null;
List<Student> studentList = null;
// 2003版本xls
if (excelVersion == 1) {
try {
workbook = new HSSFWorkbook(excelFile.getInputStream());
studentList = readExcelValue(workbook);
return studentList;
} catch (IOException e) {
e.printStackTrace();
}
}
// 2007版本xlsx
if (excelVersion == 2) {
try {
workbook = new XSSFWorkbook(excelFile.getInputStream());
studentList = readExcelValue(workbook);
return studentList;
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
// 判断要导入的excel信息,0代表未接收到,1代表2003版,2代表2007版
public int getExcelVersion(String excelFileName) {
int flag = 0;
if (excelFileName.matches("^.+\\.(?i)(xls)$")) {
flag = 1;
}
if (excelFileName.matches("^.+\\.(?i)(xlsx)$")) {
flag = 2;
}
return flag;
}
// 读取Excel内容,将其放入对应的实体对象中
private List<Student> readExcelValue(Workbook workbook) {
int totalRows = 0;
int totalCells = 0;
// 获取第一张表
Sheet sheet = workbook.getSheetAt(0);
// 得到表的总行数
totalRows = sheet.getPhysicalNumberOfRows();
// 根据第一行(标题行)获得总列数,获得总列数得根据某行确定
if (totalRows >= 1 && sheet.getRow(0) != null) {
totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
}
List<Student> studentList = new ArrayList<>();
// 逐行取数据,每行对应一条实体对象信息
for (int rowNum = 1; rowNum < totalRows; rowNum++) {
// 跳过标题行
Row row = sheet.getRow(rowNum);
if (row == null){
continue;
}
Student student = new Student();
// 逐列取数据,每列对应一个实体对象属性
for (int colNum = 0; colNum < totalCells; colNum++) {
System.out.println("第" + (rowNum + 1) + "行,第" + (colNum + 1) + "列");
Cell cell = row.getCell(colNum);
if (null != cell) {
if (colNum == 0) { //第一列
// 如果是纯数字,将单元格类型转为String
if(cell.getCellTypeEnum() != CellType.STRING){
cell.setCellType(CellType.STRING);
}
student.setId(Long.valueOf(cell.getStringCellValue()));
}
else if (colNum == 1){
if(cell.getCellTypeEnum() != CellType.STRING){
cell.setCellType(CellType.STRING);
}
student.setName(cell.getStringCellValue());
}
else if (colNum == 2){
if(cell.getCellTypeEnum() != CellType.STRING){
cell.setCellType(CellType.STRING);
}
student.setAge(Integer.valueOf(cell.getStringCellValue()));
}
else if (colNum == 3){
if(cell.getCellTypeEnum() != CellType.STRING){
cell.setCellType(CellType.STRING);
}
student.setSex(cell.getStringCellValue());
}
}
}
// 添加到studentList
studentList.add(student);
}
return studentList;
}
}