前言
在应用程序的开发中,经常要使用Execl文件来进行数据的倒入或导出。所以,在通过java语言实现此类需求的时候,往往会面临着Excel文件的解析(导入)或生成(导出)。在java技术生态圈中,可以进行Excel文件处理的主流技术包括:Apache POI,JXL、Alibaba EasyExcel等。
XSSF解析Excel文件
Workbook(Excel文件)
Workbook接口代表一个Excel文件,用于创建或加载(解析)Excel文件。常见实现类是XSSFWorkbook。
创建Excel文件
public class Workexecise {
public static void main(String[] args) {
try (Workbook workBook = new XSSFWorkbook();
FileOutputStream out = new FileOutputStream("C:\\Users\\admin\\Desktop\\data.xlsx")) {
Sheet sheet = workBook.createSheet();// 创建Sheet工作簿
Row row = sheet.createRow(0);// 创建行
Cell cell = row.createCell(0);// 创建单元格
cell.setCellValue("序号");
workBook.write(out);// 将内容写入Excel文件
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
创建工作簿:
// 按照默认名称创建工作簿
Sheet sheet1 = workbook.createSheet();
// 按照自定义名称创建工作簿
Sheet sheet2 = workbook.createSheet("自定义工作簿2");
创建数据行:
Row row = sheet.createRow(0);
创建单元格:
Cell cell0 = row.createCell(0);
设置单元格:
cell0.setCellValue(UUID.randomUUID().toString());
解析Excel文件:
public class Workexecise {
public static void main(String[] args) {
try (FileInputStream in = new FileInputStream("C:\\Users\\admin\\Desktop\\data.xlsx");
Workbook workBook = new XSSFWorkbook(in)) {
Sheet sheet0 = workBook.getSheetAt(0);// 获取Sheet工作簿
Row row = sheet0.getRow(0);// 获取行
Cell cell = row.getCell(0);
String str = cell.getStringCellValue();// 如果单元格中的数据时字符串
double num = cell.getNumericCellValue();// 如果单元格中的数据时数字
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
获取工作簿:
// 按照工作簿下标获取Sheet
Sheet sheet01 = workbook.getSheetAt(0);
// 按照工作簿名称获取Sheet
Sheet sheet02 = workbook.getSheet("Sheet0");
获取工作簿数量:
int n = workbook.getNumberOfSheets();
获取首行下标:
int first = sheet.getFirstRowNum();
获取尾行下标:
int last = sheet.getLastRowNum();
根据下标获取指定行:
Row row = sheet.getRow(0);
遍历所有行:
for(Row row : sheet) {
System.out.println(row);
}
遍历指定区域:
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
System.out.println(row);
}
根据下标获取单元格:
Cell cell = row.getCell(1);
遍历所有单元格:
for(Cell cell : row) {
}
获取单元格类型:
CellType type = cell.getCellType();
设置单元格对齐:
// 创建单元格样式
CellStyle cellStyle = workbook.createCellStyle();
//设置单元格的水平对齐类型。 此时水平居中
cellStyle.setAlignment(HorizontalAlignment.CENTER);
// 设置单元格的垂直对齐类型。 此时垂直靠底边
cellStyle.setVerticalAlignment(VerticalAlignment.BOTTOM);
超大Excel文件读写
对超大文件的写入,如果使用XSSF会造成内存、cpu等资源占用率过高,甚至会造成内存溢出等问题。因此,有下面方法:
使用POI写入:
List<String> list = Arrays.asList("妲己","貂蝉","后羿","亚瑟","鲁班","庄周","刘禅","南霸天","安琪拉","王昭君");
try (Workbook workBook = new SXSSFWorkbook(100);
FileOutputStream out = new FileOutputStream("C:\\Users\\admin\\Desktop\\data.xlsx")) {
Sheet sheet = workBook.createSheet();
DataFormat dataFormat = workBook.createDataFormat();
short dateFormatCode = dataFormat.getFormat("yyyy年MM月dd日 HH:mm:ss");
short moneyFormatCode = dataFormat.getFormat("¥#,###");
CellStyle dateCellStyle = workBook.createCellStyle();
dateCellStyle.setDataFormat(dateFormatCode);
CellStyle moneyCellStyle = workBook.createCellStyle();
moneyCellStyle.setDataFormat(moneyFormatCode);
for(int i = 0;i<100000;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(dateCellStyle);
cell2.setCellValue(new Date());
Cell cell3 = row.createCell(3);
cell3.setCellStyle(moneyCellStyle);
cell3.setCellValue(Math.random()*100000);
}
workBook.write(out);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
使用SXSSFWorkbook进行写入,通过设置 SXSSFWorkbook的构造参数,可以设置每次在内存中保持的行数,当达到这个值的时候,那么会把这些数据flush到磁盘上。
使用EasyExcel读取100万条数据
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
public class Work713 {
public static void main(String[] args) {
// EasyExcel.write("C:\\Users\\admin\\Desktop\\AAA.xlsx",Order.class)
// .sheet("订单列表")
// .doWrite(data());
List<Order> orderList = new ArrayList<Order>();
EasyExcel.read("C:\\Users\\admin\\Desktop\\AAA.xlsx",Order.class,new AnalysisEventListener<Order>() {
@Override
public void doAfterAllAnalysed(AnalysisContext arg0) {
System.out.println("Game over");
}
@Override
public void invoke(Order order, AnalysisContext arg1) {
orderList.add(order);
}
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
System.out.println(headMap);
super.invokeHeadMap(headMap, context);
}
}).sheet().doRead();
for(Order order:orderList) {
System.out.println(order);
}
}
private static List<Order> data(){
List<Order> list = new ArrayList<Order>();
for(int i = 0;i<1000000;i++) {
list.add(new Order());
}
return list;
}
}
总结
借助第三方库POI对Excel文件进行解析,在解析前要了解到Excel的层层关系,例如:Excel文件包含N张工作簿,工作簿中又包含N行数据,每行又包含N个单元格。数据的读、写都是对单元格进行操作。