使用Apache POI生成和读取Excel表数据

使用Apache POI生成和读取Excel表数据

Apache POI是Apache软件基金会的开源项目,提供了Java操作Microsoft Office格式文件的API。本文将介绍如何使用Apache POI生成和读取Excel表数据。

一、导入Maven依赖

在项目的pom.xml文件中添加Apache POI相关依赖:

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.16</version>
</dependency>

说明

  • poi:处理.xls格式的Excel文件
  • poi-ooxml:处理.xlsx格式的Excel文件

二、入门案例

2.1 生成Excel文件并写入数据

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.FileOutputStream;

public class POITest {

/**
* 通过POI创建Excel文件并且写入文件内容
*/
public static void write() throws Exception {
//在内存中创建一个Excel文件
XSSFWorkbook excel = new XSSFWorkbook();
//在Excel文件中创建一个Sheet页
XSSFSheet sheet = excel.createSheet("info");
//在Sheet中创建行对象
XSSFRow row = sheet.createRow(1);
//创建单元格并且写入文件内容
row.createCell(1).setCellValue("姓名");
row.createCell(2).setCellValue("城市");

//创建一个新行
row = sheet.createRow(2);
row.createCell(1).setCellValue("张三");
row.createCell(2).setCellValue("北京");

row = sheet.createRow(3);
row.createCell(1).setCellValue("李四");
row.createCell(2).setCellValue("南京");

//通过输出流将内存中的Excel文件写入到磁盘
FileOutputStream out = new FileOutputStream(new File("F:\\CangQiongWaiMai\\Demo\\ExcelTest\\info.xlsx"));
excel.write(out);

//关闭资源
out.close();
excel.close();
}

2.2 读取Excel文件中的内容

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.FileInputStream;
import java.io.InputStream;

public class POITest {
// ... 上面的write方法 ...

/**
* 通过POI读取Excel文件中的内容
*/
public static void read() throws Exception {
InputStream in = new FileInputStream(new File("F:\\CangQiongWaiMai\\Demo\\ExcelTest\\info.xlsx"));

//读取磁盘上已经存在的Excel文件
XSSFWorkbook excel = new XSSFWorkbook(in);
//读取Excel文件中的第一个Sheet页
XSSFSheet sheet = excel.getSheetAt(0);

//获取Sheet中最后一行的行号
int lastRowNum = sheet.getLastRowNum();

for (int i = 1; i < lastRowNum; i++) {
//获得某一行
XSSFRow row = sheet.getRow(i);
//获得单元格对象
String cellValue1 = row.getCell(1).getStringCellValue();
String cellValue2 = row.getCell(2).getStringCellValue();
System.out.println(cellValue1 + " " + cellValue2);
}

//关闭资源
in.close();
excel.close();
}

public static void main(String[] args) throws Exception {
write();
read();
}
}

三、实际案例 - 导出运营数据报表

3.1 Controller层实现

import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;

@RestController
public class ReportController {

@Autowired
private ReportService reportService;

/**
* 导出运营数据报表
*/
@GetMapping("/export")
@ApiOperation("导出运营数据报表")
public void export(HttpServletResponse response) {
reportService.exportBusinessData(response);
}
}

3.2 Service层接口

import javax.servlet.http.HttpServletResponse;

public interface ReportService {

/**
* 导出运营数据报表
*/
void exportBusinessData(HttpServletResponse response);
}

3.3 Service层实现

import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

@Service
public class ReportServiceImpl implements ReportService {

@Autowired
private WorkspaceService workspaceService;

/**
* 导出运营数据报表
*/
@Override
public void exportBusinessData(HttpServletResponse response) {
//1. 查询数据库,获取营业数据... 查询最近30天的运营数据
LocalDate dateBegin = LocalDate.now().minusDays(30);
LocalDate dateEnd = LocalDate.now().minusDays(1);

//查询概览数据
BusinessDataVO businessDataVO = workspaceService.getBusinessData(
LocalDateTime.of(dateBegin, LocalTime.MIN),
LocalDateTime.of(dateEnd, LocalTime.MAX)
);

//2. 通过POI将数据写入到Excel文件中
InputStream in = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");

try {
//基于模板文件创建一个新的excel文件
XSSFWorkbook excel = new XSSFWorkbook(in);

//获取表格文件的Sheet页
XSSFSheet sheet = excel.getSheet("Sheet1");

//填充数据--时间
sheet.getRow(1).getCell(1).setCellValue("时间:" + dateBegin + "至" + dateEnd);

//获得第4行
XSSFRow row = sheet.getRow(3);
row.getCell(2).setCellValue(businessDataVO.getTurnover());
row.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());
row.getCell(6).setCellValue(businessDataVO.getNewUsers());

//获得第5行
row = sheet.getRow(4);
row.getCell(2).setCellValue(businessDataVO.getValidOrderCount());
row.getCell(3).setCellValue(businessDataVO.getUnitPrice());

//填充明细数据
for (int i = 0; i < 30; i++) {
LocalDate date = dateBegin.plusDays(i);
//查询某一天的营业数据
BusinessDataVO businessData = workspaceService.getBusinessData(
LocalDateTime.of(date, LocalTime.MIN),
LocalDateTime.of(date, LocalTime.MAX)
);

//获得某一行
row = sheet.getRow(7 + i);
row.getCell(1).setCellValue(date.toString());
row.getCell(2).setCellValue(businessData.getTurnover());
row.getCell(3).setCellValue(businessData.getValidOrderCount());
row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
row.getCell(5).setCellValue(businessData.getUnitPrice());
row.getCell(6).setCellValue(businessData.getNewUsers());
}

//3. 通过输出流将Excel文件下载到客户端浏览器
ServletOutputStream out = response.getOutputStream();
excel.write(out);

//关闭资源
out.close();
excel.close();

} catch (IOException e) {
e.printStackTrace();
}
}
}

四、Apache POI主要类说明

类名 描述 备注
XSSFWorkbook Excel工作簿 对应.xlsx文件
HSSFWorkbook Excel工作簿 对应.xls文件(较早版本)
XSSFSheet Excel工作表 工作簿中的一个Sheet页
XSSFRow Excel行 工作表中的一行
XSSFCell Excel单元格 行中的一个单元格
XSSFCellStyle 单元格样式 设置单元格格式、对齐等
XSSFFont 字体设置 设置单元格中字体属性

五、注意事项

  1. 文件格式区分

    • .xlsx格式文件使用XSSF相关类
    • .xls格式文件使用HSSF相关类
  2. 资源关闭

    • 使用完毕后需要关闭WorkbookFileInputStreamFileOutputStream等资源
    • 建议使用try-with-resources语法自动关闭资源
  3. 大文件处理

    • 处理大量数据时,考虑使用SXSSF(流式XSSF)来减少内存占用
    • 设置适当的内存策略和临时文件位置
  4. 单元格类型

    • 在读取单元格时,需要注意单元格的数据类型(字符串、数值、日期等)
    • 使用对应的方法获取值,如getStringCellValue()getNumericCellValue()
  5. 模板使用

    • 使用预设模板可以提高开发效率,保持报表格式一致性
    • 模板文件通常放在resources目录下

通过以上代码示例和说明,可以快速上手使用Apache POI进行Excel文件的生成和读取操作。