参考:https://blog.csdn.net/weixin_48052161/article/details/117303899?spm=1001.2014.3001.5501
官网:https://poi.apache.org/components/spreadsheet/quick-guide.html#NewWorkbook
1.1什么是poi
Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java对Microsoft Office格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写,意为“简洁版的模糊实现”。
1.2poi常用的包
HSSF - 提供读写Microsoft Excel XLS格式档案的功能。
XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。
HWPF - 提供读写Microsoft Word DOC格式档案的功能。
HSLF - 提供读写Microsoft PowerPoint格式档案的功能。
HDGF - 提供读Microsoft Visio格式档案的功能。
HPBF - 提供读Microsoft Publisher格式档案的功能。
HSMF - 提供读Microsoft Outlook格式档案的功能。
缺点:Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc。
解决方案:使用easyExcel下一个讲;
1、了解excel的文档结构,有助于理解代码;
大体结构分为:
工作簿 Workbook接口
工作表 Sheet
行 Row
列 Cell
Workbook接口
HSSFWorkbook(03版本)
XSSFWorkbook(07版本)
SXSSFWorkbook(07版本加强版本)
引入pom
```powershell
org.apache.poi
poi
4.1.2
org.apache.poi
poi-ooxml
4.1.2
一、写操作
03Excel 写操作.xls
1.HSSFWorkbook ==> 03 Excel
2. .文件名结尾.xls
package com.example.dtest.excel.poiTest.write;
import cn.hutool.core.date.DateTime;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import java.io.FileOutputStream;
import java.io.IOException;
```java
public class XlsExcelWriteTest {
public void testWrite03() throws IOException {
// 在windows系统下,这是绝对路径,若是要跨系统,则需要用类加载器获取当前目录路径的相对路径;
String path = "D:\my\";
// 创建新的Excel 工作簿
Workbook workbook = new HSSFWorkbook();
// 在Excel工作簿中建一工作表,其名为缺省值 Sheet0
//Sheet sheet = workbook.createSheet();
// 如要新建一名为"会员登录统计"的工作表,其语句为:
Sheet sheet = workbook.createSheet("狂神观众统计表");
// 创建行(row 1)
Row row1 = sheet.createRow(0);
// 创建单元格(col 1-1)
Cell cell11 = row1.createCell(0);
cell11.setCellValue("今日新增关注");
// 创建单元格(col 1-2)
Cell cell12 = row1.createCell(1);
cell12.setCellValue("999");
// 创建行(row 2)
Row row2 = sheet.createRow(1);
// 创建单元格(col 2-1)
Cell cell21 = row2.createCell(0);
cell21.setCellValue("统计时间");
//创建单元格(第三列)
Cell cell22 = row2.createCell(1);
String dateTime = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
cell22.setCellValue(dateTime);
// 新建一输出文件流(注意:要先创建文件夹)
FileOutputStream out = new FileOutputStream(path+"狂神观众统计表03.xls");
// 把相应的Excel 工作簿存盘
workbook.write(out);
// 操作结束,关闭文件
out.close();
System.out.println("文件生成成功");
}
public static void main(String[] args) {
XlsExcelWriteTest xlsExcelWriteTest = new XlsExcelWriteTest();
try {
xlsExcelWriteTest.testWrite03();
} catch (IOException e) {
e.printStackTrace();
}
}
}
b、03 大批量导入.xls
package com.example.dtest.excel.poiTest.write;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class XlsExcelMoreWriteTest {
public static void testWrite03BigData() throws IOException {
// 在windows系统下,这是绝对路径,若是要跨系统,则需要用类加载器获取当前目录路径的相对路径;
String path = "D:\my\";
//记录开始时间
long begin = System.currentTimeMillis();
//创建一个SXSSFWorkbook
Workbook workbook = new HSSFWorkbook();
//创建一个sheet
Sheet sheet = workbook.createSheet();
//xls文件最大支持65536行
for (int rowNum = 0; rowNum < 65536; rowNum++) {
//创建一个行
Row row = sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10; cellNum++) {//创建单元格
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("done");
FileOutputStream out = new FileOutputStream(path+"bigdata03.xls");
workbook.write(out);
// 操作结束,关闭文件
out.close();
//记录结束时间
long end = System.currentTimeMillis();
System.out.println((double)(end - begin)/1000);
}
public static void main(String[] args) {
try {
testWrite03BigData();
} catch (IOException e) {
e.printStackTrace();
}
}
}
07 Excel 写操作.xlsx
1.XSSFWorkbook ==> 07 Excel
2. .文件名结尾.xlsx
package com.example.dtest.excel.poiTest.write;
import cn.hutool.core.date.DateTime;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class XlsxExcelWriteTest {
public static void testWrite07() throws IOException {
// 在windows系统下,这是绝对路径,若是要跨系统,则需要用类加载器获取当前目录路径的相对路径;
String path = "D:\my\";
// 创建新的Excel 工作簿, 只有对象变了
Workbook workbook = new XSSFWorkbook();
// 如要新建一名为"会员登录统计"的工作表,其语句为:
Sheet sheet = workbook.createSheet("狂神观众统计表");
// 创建行(row 1)
Row row1 = sheet.createRow(0);
// 创建单元格(col 1-1)
Cell cell11 = row1.createCell(0);
cell11.setCellValue("今日新增关注");
// 创建单元格(col 1-2)
Cell cell12 = row1.createCell(1);
cell12.setCellValue(666);
// 创建行(row 2)
Row row2 = sheet.createRow(1);
// 创建单元格(col 2-1)
Cell cell21 = row2.createCell(0);
cell21.setCellValue("统计时间");
//创建单元格(第三列)
Cell cell22 = row2.createCell(1);
String dateTime = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
cell22.setCellValue(dateTime);
// 新建一输出文件流(注意:要先创建文件夹)
FileOutputStream out = new FileOutputStream(path+"狂神观众统计表07.xlsx");
// 把相应的Excel 工作簿存盘
workbook.write(out);
// 操作结束,关闭文件
out.close();
System.out.println("文件生成成功");
}
public static void main(String[] args) {
try {
testWrite07();
} catch (IOException e) {
e.printStackTrace();
}
}
}
b、大批量07写操作 .xlsx
package com.example.dtest.excel.poiTest.write;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class XlsxExcelMoreWriteTest {
public static void testWrite07BigDataFast() throws IOException {
// 在windows系统下,这是绝对路径,若是要跨系统,则需要用类加载器获取当前目录路径的相对路径;
String path = "D:\my\";
//记录开始时间
long begin = System.currentTimeMillis();
//创建一个SXSSFWorkbook
Workbook workbook = new SXSSFWorkbook();
//创建一个sheet
Sheet sheet = workbook.createSheet();
//xls文件最大支持65536行
for (int rowNum = 0; rowNum < 65536; rowNum++) {
//创建一个行
Row row = sheet.createRow(rowNum);
for (int cellNum = 0; cellNum < 10; cellNum++) {//创建单元格
Cell cell = row.createCell(cellNum);
cell.setCellValue(cellNum);
}
}
System.out.println("done");
FileOutputStream out = new FileOutputStream(path+"bigdata07-fast.xlsx");
workbook.write(out);
// 操作结束,关闭文件
out.close();
//清除临时文件
((SXSSFWorkbook)workbook).dispose();
//记录结束时间
long end = System.currentTimeMillis();
System.out.println("写65536条数据耗时: "+(double)(end - begin)/1000);
}
public static void main(String[] args) {
try {
testWrite07BigDataFast();
} catch (IOException e) {
e.printStackTrace();
}
}
}
二、读操作
HSSFWorkbook 读03Excel
package com.example.dtest.excel.poiTest.read;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import java.io.FileInputStream;
import java.io.InputStream;
public class XlsExcelReadTest {
public static void testRead03() throws Exception{
// 在windows系统下,这是绝对路径,若是要跨系统,则需要用类加载器获取当前目录路径的相对路径;
String path = "D:\my\";
InputStream is = new FileInputStream(path+"狂神观众统计表03.xls");
Workbook workbook = new HSSFWorkbook(is);
Sheet sheet = workbook.getSheetAt(0);
// 读取第一行第一列
Row row = sheet.getRow(0);
Cell cell11 = row.getCell(0);
Cell cell12 = row.getCell(1);
String cellValue1 = cell11.getStringCellValue();
double cellValue2 = cell12.getNumericCellValue();
// 输出单元内容
System.out.println(cellValue1+" "+cellValue2);
// 操作结束,关闭文件
is.close();
}
public static void main(String[] args) {
try {
testRead03();
} catch (Exception e) {
e.printStackTrace();
}
}
}
XSSFWorkbook 读07Excel
package com.example.dtest.excel.poiTest.read;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.InputStream;
public class XlsxExcelReadTest {
public static void testRead07() throws Exception{
// 在windows系统下,这是绝对路径,若是要跨系统,则需要用类加载器获取当前目录路径的相对路径;
String path = "D:\my\";
InputStream is = new FileInputStream(path+"/狂神观众统计表07.xlsx");
Workbook workbook = new XSSFWorkbook(is);
Sheet sheet = workbook.getSheetAt(0);
// 读取第一行第一列
Row row = sheet.getRow(0);
Cell cell11 = row.getCell(0);
Cell cell12 = row.getCell(1);
String cellValue1 = cell11.getStringCellValue();
double cellValue2 = cell12.getNumericCellValue();
// 输出单元内容
System.out.println(cellValue1+" "+cellValue2);
// 操作结束,关闭文件
is.close();
}
public static void main(String[] args) {
try {
testRead07();
} catch (Exception e) {
e.printStackTrace();
}
}
}
读取复杂明细表
package com.example.dtest.excel.poiTest.read;
import cn.hutool.core.date.DateTime;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Date;
public class XlsExcelMoreReadTest {
public static void testCellType() throws Exception {
// 在windows系统下,这是绝对路径,若是要跨系统,则需要用类加载器获取当前目录路径的相对路径;
String path = "D:\my\";
InputStream is = new FileInputStream(path+"/狂神观众统计表03.xls");
Workbook workbook = new HSSFWorkbook(is);
Sheet sheet = workbook.getSheetAt(0);
// 读取标题所有内容
Row rowTitle = sheet.getRow(0);
if (rowTitle != null) {// 行不为空
// 读取cell
int cellCount = rowTitle.getPhysicalNumberOfCells();
for (int cellNum = 0; cellNum < cellCount; cellNum++) {
Cell cell = rowTitle.getCell(cellNum);
if (cell != null) {
// int cellType = cell.getCellType();
CellType cellType = cell.getCellType();
String cellValue = cell.getStringCellValue();
System.out.print(cellValue + "|");
}
}
System.out.println();
}
// 读取商品列表数据
int rowCount = sheet.getPhysicalNumberOfRows();
for (int rowNum = 1; rowNum < rowCount; rowNum++) {
Row rowData = sheet.getRow(rowNum);
if (rowData != null) {// 行不为空
// 读取cell
int cellCount = rowTitle.getPhysicalNumberOfCells();
for (int cellNum = 0; cellNum < cellCount; cellNum++) {
System.out.print("【" + (rowNum + 1) + "-" + (cellNum + 1) + "】");
Cell cell = rowData.getCell(cellNum);
if (cell != null) {
// int cellType = cell.getCellType();
CellType cellType = cell.getCellType();
//判断单元格数据类型
String cellValue = "";
switch (cellType) {
case STRING://字符串
System.out.print("【STRING】");
cellValue = cell.getStringCellValue();
break;
case BOOLEAN://布尔
System.out.print("【BOOLEAN】");
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case BLANK://空
System.out.print("【BLANK】");
break;
case NUMERIC:
System.out.print("【NUMERIC】");
//cellValue = String.valueOf(cell.getNumericCellValue());
if (HSSFDateUtil.isCellDateFormatted(cell)) {//日期
System.out.print("【日期】");
Date date = cell.getDateCellValue();
cellValue = new DateTime(date).toString("yyyy-MM-dd");
} else {
// 不是日期格式,则防止当数字过长时以科学计数法显示
System.out.print("【转换成字符串】");
cell.setCellType(CellType.STRING);
cellValue = cell.toString();
}
break;
case ERROR:
System.out.print("【数据类型错误】");
break;
}
System.out.println(cellValue);
}
}
}
}
is.close();
}
public static void main(String[] args) {
try {
testCellType();
} catch (Exception e) {
e.printStackTrace();
}
}
}



