Apache POI 是基于 Office Open XML 标准(OOXML)和 Microsoft 的 OLE 2 复合文档格式(OLE2)处理各种文件格式的开源项目。 可以使用 Java 读写 MS Excel 文件,可以使用 Java 读写 MS Word 和 MS PowerPoint 文件。
模块
-
HSSF - 提供读写 Microsoft Excel XLS 格式 (Microsoft Excel 97 (-2003)) 档案的功能。
-
XSSF - 提供读写 Microsoft Excel OOXML XLSX 格式 (Microsoft Excel XML (2007+)) 档案的功能。
-
SXSSF - 提供低内存占用量读写 Microsoft Excel OOXML XLSX 格式档案的功能。
-
HWPF - 提供读写 Microsoft Word DOC97 格式 (Microsoft Word 97 (-2003)) 档案的功能。
-
XWPF - 提供读写 Microsoft Word DOC2003 格式 (WordprocessingML (2007+)) 档案的功能。
-
HSLF/XSLF - 提供读写 Microsoft PowerPoint 格式档案的功能。
-
HDGF/XDGF - 提供读 Microsoft Visio 格式档案的功能。
-
HPBF - 提供读 Microsoft Publisher 格式档案的功能。
-
HSMF - 提供读 Microsoft Outlook 格式档案的功能。
首先导入依赖
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
03版本xls比07版本xlsx的容量大,对应的工作类也不同
分别有:工作簿,工作表,行,列
生成03版本
String PATH="D:\\";
@Test
public void testWrite03() throws Exception {
//1.创建一个工作簿
Workbook workbook=new HSSFWorkbook();
//2.创建一个工作表
Sheet sheet=workbook.createSheet("sheet1");
//3.创建一个行
Row row1=sheet.createRow(0);
//4.创建一个单元格
Cell cell11=row1.createCell(0);
cell11.setCellValue("11");
Cell cell12=row1.createCell(1);
cell12.setCellValue("12");
//第二行
Row row2=sheet.createRow(1);
Cell cell21=row2.createCell(0);
cell21.setCellValue("21");
Cell cell22=row2.createCell(1);
cell22.setCellValue("22");
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "xxx.xls");
workbook.write(fileOutputStream);
fileOutputStream.close();
System.out.println("生成完毕");
}
生成07版本
@Test
public void testWrite07() throws Exception {
//1.创建一个工作簿
Workbook workbook=new XSSFWorkbook();
//2.创建一个工作表
Sheet sheet=workbook.createSheet("sheet1");
//3.创建一个行
Row row1=sheet.createRow(0);
//4.创建一个单元格
Cell cell11=row1.createCell(0);
cell11.setCellValue("11");
Cell cell12=row1.createCell(1);
cell12.setCellValue("12");
//第二行
Row row2=sheet.createRow(1);
Cell cell21=row2.createCell(0);
cell21.setCellValue("21");
Cell cell22=row2.createCell(1);
cell22.setCellValue("22");
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "xxx.xlsx");
workbook.write(fileOutputStream);
fileOutputStream.close();
System.out.println("生成完毕");
}
两个版本的区别
更快地写入大文件
public void test07BigDataS() throws Exception
{
long begin=System.currentTimeMillis();
Workbook workbook=new SXSSFWorkbook();
Sheet sheet=workbook.createSheet();
for(int i=0;i<10000;i++)
{
Row row=sheet.createRow(i);
for(int j=0;j<10;j++)
{
Cell cell=row.createCell(j);
cell.setCellValue(j);
}
}
System.out.println("over");
FileOutputStream fileOutputStream = new FileOutputStream(PATH + "xxxS.xlsx");
workbook.write(fileOutputStream);
fileOutputStream.close();
//清除临时文件
((SXSSFWorkbook)workbook).dispose();
long end=System.currentTimeMillis();
System.out.println((double)(end-begin)/1000);
}
记得清除临时数据
读excel03版
String PATH="D:\\";
@Test
public void testRead03() throws Exception {
//获取文件流
FileInputStream fileInputStream = new FileInputStream(PATH + "xxx.xls");
//1.创建一个工作簿
Workbook workbook=new HSSFWorkbook(fileInputStream);
//2.得到表
Sheet sheet = workbook.getSheetAt(0);
//3.得到行
Row row=sheet.getRow(0);
//4.得到列
Cell cell=row.getCell(0);
System.out.println(cell.getStringCellValue());
fileInputStream.close();
}
读取值的时候,记得注意类型
读excel07版
@Test
public void testRead07() throws Exception {
//获取文件流
FileInputStream fileInputStream = new FileInputStream(PATH + "xxx.xlsx");
//1.创建一个工作簿
Workbook workbook=new XSSFWorkbook(fileInputStream);
//2.得到表
Sheet sheet = workbook.getSheetAt(0);
//3.得到行
Row row=sheet.getRow(0);
//4.得到列
Cell cell=row.getCell(1);
System.out.println(cell.getNumericCellValue());
fileInputStream.close();
}
较为完整的程序
@Test
public void testCellType() throws Exception {
//获取文件流
FileInputStream fileInputStream = new FileInputStream(PATH + "xxx.xlsx");
//1.创建一个工作簿
Workbook workbook=new XSSFWorkbook(fileInputStream);
//2.得到表
Sheet sheet = workbook.getSheetAt(0);
//3.得到行
Row row=sheet.getRow(0);
if(row!=null)
{
int physicalNumberOfCells = row.getPhysicalNumberOfCells();
for(int i=0;i<physicalNumberOfCells;i++)
{
Cell cell=row.getCell(i);
if(cell!=null)
{
int cellType = cell.getCellType();
String numericCellValue = cell.getStringCellValue();
System.out.println("类型值为"+cellType);
System.out.println(numericCellValue);
}
System.out.println();
}
}
int rowCount=sheet.getPhysicalNumberOfRows();
for(int i=1;i<rowCount;i++)//从第一行开始
{
Row rowData=sheet.getRow(i);
if(rowData!=null)
{
int cellCount=row.getPhysicalNumberOfCells();
for(int j=0;j<cellCount;j++)
{
Cell cell = rowData.getCell(j);
if(cell!=null)
{
int cellType=cell.getCellType();
String cellValue="";
switch (cellType)
{
case XSSFCell.CELL_TYPE_STRING: //字符串
cellValue= cell.getStringCellValue();
break;
case XSSFCell.CELL_TYPE_BOOLEAN: //布尔
cellValue=String.valueOf(cell.getBooleanCellValue());
break;
case XSSFCell.CELL_TYPE_BLANK://空
break;
case XSSFCell.CELL_TYPE_NUMERIC://日期,普通数字
if(HSSFDateUtil.isCellDateFormatted(cell)) //日期
{
Date dateCellValue = cell.getDateCellValue();
cellValue= new DateTime(dateCellValue).toString("yyyy-MM-dd");
}
else
//不是日期格式,防止数字过长
{
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cellValue=cell.toString();
}
break;
case XSSFCell.CELL_TYPE_ERROR:
break;
}
System.out.println(cellValue);
}
}
}
}
fileInputStream.close();
}
计算公式相关
@Test
public void testFormula() throws Exception
{
FileInputStream inputStream=new FileInputStream(PATH+"公式.xls");
Workbook workbook=new HSSFWorkbook(inputStream);
Sheet sheet=workbook.getSheetAt(0);
Row row = sheet.getRow(4);
Cell cell = row.getCell(0);
//拿到计算公式
FormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workbook);
//输出单元格的内容
int cellType = cell.getCellType();
switch (cellType){
case Cell.CELL_TYPE_FORMULA://公式
String cellFormula = cell.getCellFormula();
System.out.println(cellFormula);
//计算
CellValue evaluate = formulaEvaluator.evaluate(cell);
String s = evaluate.formatAsString();//将结果转为字符串
System.out.println(s);
break;
}
inputStream.close();
}
EasyExcel:
加入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.0-beta2</version>
</dependency>
快速开始:
写入:
package com.excel.easy;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
@Data
public class DemoData {
@ExcelProperty("字符串标题")
private String string;
@ExcelProperty("日期标题")
private Date date;
@ExcelProperty("数字标题")
private Double doubleData;
/**
* 忽略这个字段
*/
@ExcelIgnore
private String ignore;
}
package com.excel.easy;
import com.alibaba.excel.EasyExcel;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class EasyTest {
String PATH="D:\\";
private List<DemoData> data() {
List<DemoData> list = new ArrayList<DemoData>();
for (int i = 0; i < 10; i++) {
DemoData data = new DemoData();
data.setString("字符串" + i);
data.setDate(new Date());
data.setDoubleData(0.56);
list.add(data);
}
return list;
}
/**
* 最简单的写
* <p>
* 1. 创建excel对应的实体对象 参照{@link DemoData}
* <p>
* 2. 直接写即可
*/
@Test
public void simpleWrite() {
// 注意 simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大参照 重复多次写入
// 写法1 JDK8+
// since: 3.0.0-beta1
String fileName = PATH+"Easy.xlsx";
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
//write(fileName,格式类)
//sheet(表名)
//doWrite(数据)
EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
}
}
效果:
读取:
package com.excel.easy;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
@Data
public class DemoData {
@ExcelProperty("字符串标题")
private String string;
@ExcelProperty("日期标题")
private Date date;
@ExcelProperty("数字标题")
private Double doubleData;
/**
* 忽略这个字段
*/
@ExcelIgnore
private String ignore;
}
package com.excel.easy;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class DemoDataListener extends AnalysisEventListener<DemoData> {
private static final Logger LOGGER= LoggerFactory.getLogger(DemoDataListener.class);
private static final int BATCH_COUNT=5;
List<DemoData> list=new ArrayList<DemoData>();
private DemoDAO demoDAO;
public DemoDataListener() {
demoDAO=new DemoDAO();
}
public DemoDataListener(DemoDAO demoDAO) {
this.demoDAO=demoDAO;
}
//读取数据会执行invoke方法
//DemoData 类型
//AnalysisContext 分析上下文
@Override
public void invoke(DemoData data, AnalysisContext context) {
System.out.println(JSON.toJSONString(data));
list.add(data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
list.clear();
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
saveData();
LOGGER.info("所有数据解析完成");
}
private void saveData() {
LOGGER.info("{}条数据,开始存储数据库!",list.size());
demoDAO.save(list);
LOGGER.info("存储数据成功!");
}
}
package com.excel.easy;
import java.util.List;
/**
* 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。
**/
public class DemoDAO {
public void save(List<DemoData> list) {
// 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入
}
}
在saveData中调用了DemoDAO的save方法,在此时可编辑数据库操作文章来源:https://www.toymoban.com/news/detail-513036.html
测试类:文章来源地址https://www.toymoban.com/news/detail-513036.html
@Test
public void simpleRead() {
// 写法1:JDK8+ ,不用额外写一个DemoDataListener
// since: 3.0.0-beta1
String fileName = PATH+"Easy.xlsx";
//这里 需要指定读用哪个class去读,然后读取第一个sheet,文件流会自动关闭
EasyExcel.read(fileName,DemoData.class,new DemoDataListener()).sheet().doRead();
}
到了这里,关于POI及EasyExcel操作xls,xlsx文件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!