一.概述
在程序的开发过程中,通常会使用Excel文件来进行数据的导入和导出,在使用Java实现此类需求时也要经理Excel文件的解析或生成
在Java技术中,能实现此类需求的技术主要有:Apache POI, Alibaba EasyExcel 和 JXL。
其中,JXL只支持Excel2003以下版本,所以现在不太常见,那简单学习一下另外两种技术吧
二.Apache POI
Apache POI是基于DOM方式进行解析,将文件直接加载内存,速度较快,适合文件数据量不大的应用场景,它提供Java编写的免费开源跨平台的Java API,Apache POI提供给Java程序对Microsoft Office格式档案进行读写功能的API开源类库。
它分别对不同格式的文件提供不同的文件解析:
HSSF -提供读写Microsoft Excel格式档案的功能。
XSSF-提供读写Microsoft Excel OOXML格式档案的功能。
HWPF-提供读写Microsoft Word格式档案的功能。
HSLF-提供读写Microsoft PowerPoint格式档案的功能。
HDGF-提供读写Microsoft Visio格式档案的功能。
最常用的是HSSF和XSSF,其中HSSF主要用于解析.xls格式的Excel文件,而XSSF主要用于解析.xlsx格式的Excel文件。前一种格式的Excel文件所能存储的数据较小。我们重点要了解的是XSSF解析和生成文件的方法
1.XSSF解析文件
首先我们要知道每个对象所代表的是什么:
1. Workbook对象:Excel文件
2. Sheet对象:电子工作簿
3. Row对象:数据行
4. Cell对象:单元格
1. 我们首先要创建一个输入流,用于传入所要解析的Excel文件,还要创建一个Workbook对象,用于解析所传入的文件:(传入的地址是所需要解析的Excel文件地址)(ps:输入流用完是需要关闭的,参考下文生成excel方法)
- 使用getNumberOfSheets()方法获取工作部的数量:
- 根据传入的下标或工作簿的名称获取工作簿:
以上实现代码如下:
public class Demo01 {
public static void main(String[] args) throws IOException {
//通过输入流传入excel文件
FileInputStream in = new FileInputStream("C:\\text Java\\1627356552686.xlsx");
//将输入流传入Workbook对象并完成解析
Workbook workbook = new XSSFWorkbook(in);
//获取工作簿数量
int sheetNumber = workbook.getNumberOfSheets();
System.out.println("工作簿数量:" + sheetNumber);
//按照名称或下标获取工作簿
Sheet sheet0 = workbook.getSheet("sheet0");
Sheet sheet1 = workbook.getSheetAt(1);
System.out.println("工作簿1:" + sheet0.getLastRowNum());
System.out.println("工作簿2:" + sheet1.getLastRowNum());
}
}
4.此外我们还需要获取单元格信息,或许其信息的方式有两种,一种是使用遍历下标的方法遍历所有行,来获取单元格信息
另外一种是使用foreach遍历,能使用这种方法,是因为在Sheet接口中实现了iterator迭代器
实现代码如下:
import java.io.FileInputStream;
import java.io.IOException;
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;
public class Demo02 {
public static void main(String[] args) {
try (Workbook workbook = new XSSFWorkbook(new FileInputStream("C:\\text Java\\1627356552686.xlsx"))) {
// 获取工作簿对象
Sheet sheet = workbook.getSheetAt(0);
// 遍历工作簿中的所有行
// 方法一:
for (int i = 0; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
// 按照下标获取单元格
Cell cell0 = row.getCell(0);
Cell cell1 = row.getCell(1);
Cell cell2 = row.getCell(2);
Cell cell3 = row.getCell(3);
Cell cell4 = row.getCell(4);
System.out.println("序号:" + cell0.getNumericCellValue());
System.out.println("部门:" + cell1.getStringCellValue());
System.out.println("姓名:" + cell2.getStringCellValue());
System.out.println("职位:" + cell3.getStringCellValue());
System.out.println("身份证号:" + cell4.getStringCellValue());
System.out.println();
}
// 方法二:(sheet接口中实现了iterater迭代器)
for (Row row : sheet) {
Cell cell0 = row.getCell(0);
Cell cell1 = row.getCell(1);
Cell cell2 = row.getCell(2);
Cell cell3 = row.getCell(3);
Cell cell4 = row.getCell(4);
System.out.println("序号:" + cell0.getNumericCellValue());
System.out.println("部门:" + cell1.getStringCellValue());
System.out.println("姓名:" + cell2.getStringCellValue());
System.out.println("职位:" + cell3.getStringCellValue());
System.out.println("身份证号:" + cell4.getStringCellValue());
System.out.println();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.XSSF生成文件
既有解析文件,那也就有生成文件,下面说说生成文件的方法
1.创建输出流用于导出所要生成的Excel文件,同时也要创建Workbook对象用于写入文件
2.创建工作簿:
3.创建行
4.创建单元格,即填充内容
5.别忘了调用write方法进行写入:
实现代码如下:
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.UUID;
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;
public class Demo03 {
public static void main(String[] args) {
try (Workbook workbook = new XSSFWorkbook();
FileOutputStream file = new FileOutputStream("C:\\text Java\\test.xlsx")) {
//创建sheet工作簿
Sheet sheet0 = workbook.createSheet("表1");
Sheet sheet1 = workbook.createSheet("表2");
Sheet sheet2 = workbook.createSheet("表3");
//创建row行
Row row0 = sheet0.createRow(0);
//创建cell单元格并写进内容
Cell cell0 = row0.createCell(0);
cell0.setCellValue(UUID.randomUUID().toString());
Cell cell1 = row0.createCell(1);
cell1.setCellValue(Math.random() * 10);
Cell cell2 = row0.createCell(2);
cell2.setCellValue(LocalDateTime.now());
//写入
workbook.write(file);
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上是关于Apache POI中XSSF解析和生成文件的方法,下来说说Alibaba EasyExcel
三.Alibaba EasyExcel
采用逐行读取的解析模式,将每一行解析结果以观察者的模式通知处理,所以比较适合数据体量较大的Excel文件解析,用这种方法生成Excel文件时需要有对应的实现类辅助完成:
1.主函数和返回值为list<>的方法:(doWrtie()方法中需要传入的参数类型为list<>)
在这里,我们实现了100w条数据的写入,也测试了写入数据所需要的时间,运行结果如下所示
import java.util.ArrayList;
import java.util.List;
import com.alibaba.excel.EasyExcel;
public class Demo01 {
public static void main(String[] args) {
long begin = System.currentTimeMillis(); //获取当前时间(毫秒)
// 写入100w
EasyExcel.write("C:\\text Java\\easyexcelTest\\easy.xlsx", Order.class)
.sheet("订单列表") //创建工作簿并设置工作簿名称
.doWrite(data());
long end = System.currentTimeMillis();
System.out.println("用时" + (end-begin) + "毫秒"); //计算时间差
}
// 创建100w条订单数据
private static List<Order> data() {
List<Order> list = new ArrayList<Order>();
for (int i = 0; i < 1000000; i++) {
list.add(new Order());
}
return list;
}
}
写入数据所需要的时间与电脑本身的性能也有关系。
2.Order订单实现类:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.NumberFormat;
public class Order {
@ExcelProperty("订单编号")
private String orderId; // 订单编号
@ExcelProperty("支付金额")
@NumberFormat("¥#,###")
private Double payment; // 支付金额
@ExcelProperty(value = "创建日期",converter = LocalDateTimeConverter.class)
private LocalDateTime creationTime; // 创建时间
public Order() {
this.orderId = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddhhmmss"))
+ UUID.randomUUID().toString().substring(0, 5);
this.payment = Math.random() * 10000;
this.creationTime = LocalDateTime.now();
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public Double getPayment() {
return payment;
}
public void setPayment(Double payment) {
this.payment = payment;
}
public LocalDateTime getCreationTime() {
return creationTime;
}
public void setCreationTime(LocalDateTime creationTime) {
this.creationTime = creationTime;
}
@Override
public String toString() {
return "Order [orderId=" + orderId + ", payment=" + payment + ", creationTime=" + creationTime + "]";
}
}
四.SXSSF写入文件
SXSSF也是POI写入文件的方法,只不过更适用于超大文件的写入,在这种方法中通过设置SXSSFWorkbook()对象的参数可以防止出现内存不够用的情况
1.下面是写入1万条数据的实现代码及所需时间
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
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;
public class Demo03 {
public static void main(String[] args) {
long begin = System.currentTimeMillis(); //获取当前时间(毫秒)
//超大excel文件写入使用SXSSFWorkbook对象
try (Workbook workbook = new SXSSFWorkbook();
FileOutputStream out = new FileOutputStream("C:\\text Java\\Test-10W.xlsx")) {
// 创建新的工作簿
Sheet sheet = workbook.createSheet();
// 获取格式编码值
DataFormat format = workbook.createDataFormat();
short dateFormat = format.getFormat("yyyy年MM月dd日 HH:mm:ss");
short monyFormat = format.getFormat("¥#,###");
// 创建日期格式对象
CellStyle dateCellType = workbook.createCellStyle();
dateCellType.setDataFormat(dateFormat);
// 创建红包格式对象
CellStyle moneyCellType = workbook.createCellStyle();
moneyCellType.setDataFormat(monyFormat);
for (int i = 0; i < 10000; i++) {
String name = "a" + i;
Row row = sheet.createRow(i + 1);
Cell cell0 = row.createCell(0); // 序号
cell0.setCellValue(String.valueOf(i + 1));
Cell cell1 = row.createCell(1); // 姓名
cell1.setCellValue(name);
Cell cell2 = row.createCell(2); // 日期
cell2.setCellStyle(dateCellType);
cell2.setCellValue(new Date());
Cell cell3 = row.createCell(3); // 红包
cell3.setCellStyle(moneyCellType);
cell3.setCellValue((int) (Math.random() * 10000));
}
workbook.write(out);
long end = System.currentTimeMillis();
System.out.println("耗时" + (end-begin) + "毫秒"); //计算时间差
} catch (IOException e) {
e.printStackTrace();
}
}
}
相比起来SXSSF和EasyExcel虽然都是用于对大数据量文件的写入,但是EasyExcel更适用于此类情况
版权归原作者 x.y.r 所有, 如有侵权,请联系我们删除。