一、Excel的写操作
在Excel为我们提供了两种文件类型.XLS和.XLSX文件,这两种文件的读取方式都是一致的.xls文件使用的是HSSF对象,.xlsx使用的是XSSF对象,因为两种方式是一样的,所以我们来看一个HSSF读取的例子
1.导入maven
<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>
2.Excel的写操作
我们先看看我们最终要生成的表格:

import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.ss.usermodel.*;
import org.joda.time.DateTime;
import java.io.FileOutputStream;
public class Demo {
public static void main(String[] args) throws Exception {
showHSSF();
}
/**
* 对HSSF表格文件进行写操作
*
*/
public static void showHSSF() throws Exception {
// 首先创建Excel 工作簿
Workbook workbook=new HSSFWorkbook();
// 在Excel工作簿中建一工作表,即创建sheet,取名为测试表格
Sheet sheet=workbook.createSheet("测试表格");
// 创建行,创建了2行
//值为0表示第一行
Row row1=sheet.createRow(0);
//值为1表示第二行
Row row2=sheet.createRow(1);
//创建单元格样式
CellStyle cellStyle=workbook.createCellStyle();
//设置水平对齐的样式为居中对齐;
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
//设置垂直对齐的样式为居中对齐;
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
//创建单元格
//这个单元格位置:1-1
Cell row1Cell1=row1.createCell(0);
//对单元格赋值
row1Cell1.setCellValue("姓名");
//设置样式
row1Cell1.setCellStyle(cellStyle);
//这个单元格位置:1-2
Cell row1Cell2=row1.createCell(1);
row1Cell2.setCellValue("年龄");
row1Cell2.setCellStyle(cellStyle);
//这个单元格位置:1-3,1-4的合并单元格
Cell row1Cell3to4=row1.createCell(2);
row1Cell3to4.setCellValue("课程");
row1Cell3to4.setCellStyle(cellStyle);
//合并单元格(4个参数,分别为起始行,结束行,起始列,结束列)
//表格的行和列都是从0开始
CellRangeAddress coursRegion = new CellRangeAddress(0, 0, 2, 3);
sheet.addMergedRegion(coursRegion);
//这个单元格位置:2-1
Cell row2Cell1=row2.createCell(0);
row2Cell1.setCellValue("小明");
row2Cell1.setCellStyle(cellStyle);
//这个单元格位置:2-2
Cell row2Cell2=row2.createCell(1);
row2Cell2.setCellValue(16);
row2Cell2.setCellStyle(cellStyle);
//这个单元格位置:2-3
Cell row2Cell3=row2.createCell(2);
row2Cell3.setCellValue("语文");
row2Cell3.setCellStyle(cellStyle);
//这个单元格位置:2-4
Cell row2Cell4=row2.createCell(3);
row2Cell4.setCellValue("数学");
row2Cell4.setCellStyle(cellStyle);
//这个单元格位置:1-5、2-5的合并单元格
//要注意的是如果是行与行的合并,必须对第一行中的单元格赋值
Cell row1to2Cell5=row1.createCell(4);
String dateTime = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
row1to2Cell5.setCellValue(dateTime);
row1to2Cell5.setCellStyle(cellStyle);
//合并单元格
//合并单元格(4个参数,分别为起始行,结束行,起始列,结束列)
//表格的行和列都是从0开始
CellRangeAddress timeRegion=new CellRangeAddress(0,1,4,4);
sheet.addMergedRegion(timeRegion);
// 输出文件
FileOutputStream out = new FileOutputStream("E:\\static\\poi\\写操作测试工作簿.xls");
workbook.write(out);
// 操作结束,关闭文件
out.close();
System.out.println("文件生成成功");
}
}
HSSF文件和XSSF文件两种操作方式是一样的,但是二者又有很大的区别:HSSF写的速度很快,但是最多只能写65536条数据;XSSF能够写大量的数据,但是写的速度很慢,其次XSSF的写操作是直接在内存中写数据,写完后再复制到磁盘,这样就会造成内存溢出的问题,因此为了解决内存溢出问题,poi有为我们提供了一个SXSSF对象进行.XSLX文件的操作。
由于文件是在内存中写的,所以我们需要清理一次内存的操作,关闭文件后添加代码:
((SXSSFWorkbook)workbook).dispose();
二、Excel的读操作
读操作两个文件没有任何区别,但是读操作最重要的是对不同数据类型的读取:
我们要读取的表格内容,需要注意的是H列是F列和G列的求和公式得来的:

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
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 org.joda.time.DateTime;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Date;
public class Demo1 {
public static void main(String[] args) throws Exception {
String fileName = "E:\\static\\poi\\测试工作簿.xls";
readExcel(fileName);
}
public static void readExcel(String fileName) throws Exception {
//读取文件
InputStream inputStream = new FileInputStream(fileName);
//找到工作簿
Workbook workbook = new HSSFWorkbook(inputStream);
//找到对应的表格Sheet,0表示第一sheet
Sheet sheet = workbook.getSheetAt(0);
//得到物理行数
int rowCount = sheet.getPhysicalNumberOfRows();
//根据物理行数,读取每一格的内容
for (int rowNum = 0; rowNum < rowCount; rowNum++) {
// 读取每一行的内容
Row rowData = sheet.getRow(rowNum);
//空指针判断
if (rowData != null) {
// 得到物理列数,总共有多少列
int cellCount = rowData.getPhysicalNumberOfCells();
//读取每个单元格的数据
for (int cellNum = 0; cellNum < cellCount; cellNum++) {
//读取了数据是cell对象
//cell对象有多个数据类型
Cell cell = rowData.getCell(cellNum);
//空指针判断
if (cell != null) {
//获取当前单元格的数据类型
int cellType = cell.getCellType();
//最终读取的值
String cellValue = "";
//根据单元格数据类型来读取数据
switch (cellType) {
//字符串类型
case HSSFCell.CELL_TYPE_STRING:
System.out.print("字符串类型数据:");
//字符串类型数据获取方法
cellValue = cell.getStringCellValue();
break;
//布尔类型,一般不会见到这个类型的值
case HSSFCell.CELL_TYPE_BOOLEAN:
System.out.print("布尔类型的数据:");
//布尔类型数据获取方法
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
//空数据
case HSSFCell.CELL_TYPE_BLANK:
System.out.print("为空的数据:");
break;
//数值类型
//数值类型一共有两种,时间戳和数值
case HSSFCell.CELL_TYPE_NUMERIC:
//判断当前的数值是否是一个时间戳
if (HSSFDateUtil.isCellDateFormatted(cell)) {
System.out.print("日期:");
//时间数据类型转换
Date date = cell.getDateCellValue();
cellValue = new DateTime(date).toString("yyyy-MM-dd HH:mm:ss");
} else {
// 不是日期格式,则防止当数字过长时以科学计数法显示
System.out.print("数值类型的数据:");
//数值类型的数据转换成字符串类型
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cellValue = cell.toString();
}
break;
//公式类型的数据
case HSSFCell.CELL_TYPE_FORMULA:
//得到单元格使用的公式
String formula = cell.getCellFormula();
System.out.print("单元格使用的公式是:" + formula);
//得到计算的数据
double value = cell.getNumericCellValue();
System.out.print("计算的数据为:" + value);
break;
//错误的数据类型
case Cell.CELL_TYPE_ERROR:
System.out.print("数据类型错误");
break;
}
System.out.println(cellValue);
}
}
}
}
inputStream.close();
}
}
测试内容:

来源:https://www.cnblogs.com/daijiting/p/12284417.html