1、添加依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
2、xls和xlsx的区别介绍
- xls是Excel03版本,最大支持65536行、256列,poi 操作xls,使用HSSFWorkbook
- xlsx是Excel007版本,最大支持1048576行、16384列,poi-ooml操作xlsx,使用XSSFWorkbook
3、代码示例,读取Excel
/**
* 读.xlsx文件
*/
private static List<List<String>> readXlsx(String path) throws Exception {
InputStream is = Files.newInputStream(Paths.get(path));
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(is);
List<List<String>> result = new ArrayList<List<String>>();
// 循环每一页,并处理当前循环页 (sheet 页)
int numberOfSheets = xssfWorkbook.getNumberOfSheets();
for (int i = 0; i < numberOfSheets; i++) {
XSSFSheet sheetAt = xssfWorkbook.getSheetAt(i);
if (sheetAt == null) {
continue;
}
// 从第一行一直循环到当前sheet的最后一行
for (int rowNum = 1; rowNum <= sheetAt.getLastRowNum(); rowNum++) {
// 获取行数据,然后在获取列数据
XSSFRow xssfRow = sheetAt.getRow(rowNum);
int minColIx = xssfRow.getFirstCellNum();
int maxColIx = xssfRow.getLastCellNum();
List<String> rowList = new ArrayList<String>();
for (int colIx = minColIx; colIx < maxColIx; colIx++) {
XSSFCell cell = xssfRow.getCell(colIx);
if (cell == null) {
continue;
}
rowList.add(cell.toString());
}
result.add(rowList);
}
}
return result;
}
/**
* 读.xls文件
*/
private static List<List<String>> readXls(String path) throws IOException {
InputStream is = Files.newInputStream(Paths.get(path));
HSSFWorkbook hssfWorkbook = new HSSFWorkbook(is);
List<List<String>> result = new ArrayList<List<String>>();
int numberOfSheets = hssfWorkbook.getNumberOfSheets();
for (int i = 0; i < numberOfSheets; i++) {
HSSFSheet hssfSheet = hssfWorkbook.getSheetAt(i);
if (hssfSheet == null) {
continue;
}
int firstRowNum = hssfSheet.getFirstRowNum();
int lastRowNum = hssfSheet.getLastRowNum();
for (int rowIx = firstRowNum; rowIx < lastRowNum; rowIx++) {
HSSFRow row = hssfSheet.getRow(rowIx);
int minColIx = row.getFirstCellNum();
int maxColIx = row.getLastCellNum();
List<String> rowList = new ArrayList<String>();
for (int colIx = minColIx; colIx < maxColIx; colIx++) {
HSSFCell cell = row.getCell(colIx);
if (cell == null) {
continue;
}
rowList.add(cell.toString());
}
result.add(rowList);
}
}
return result;
}
4、代码示例,写Excel (HSSFWorkBook类似)
// 将上面读取的数据,在重新写到一个新的文件中
private static void writeXlsx(List<List<String>> dataList, String destPath) throws IOException {
// 创建一个工作簿
XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
Sheet sheet001 = xssfWorkbook.createSheet("sheet001");
for (int i = 0; i < dataList.size(); i++) {
Row row = sheet001.createRow(i);
List<String> rowData = dataList.get(i);
for (int j = 0; j < rowData.size(); j++) {
Cell cell = row.createCell(j);
cell.setCellValue(rowData.get(j));
}
}
FileOutputStream fileOutputStream = new FileOutputStream(destPath);
xssfWorkbook.write(fileOutputStream);
fileOutputStream.close();
}
5、合并单元格 --- addMergedRegion
private static void mergeWithXSSF(String destPath) throws IOException {
XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
XSSFSheet sheet = xssfWorkbook.createSheet("new Sheet");
XSSFRow row = sheet.createRow(1);
XSSFCell cell = row.createCell(1);
cell.setCellValue("测试合并单元格");
// 按照范围合并单元格
sheet.addMergedRegion(new CellRangeAddress(1, 1, 1, 2));
FileOutputStream fileOutputStream = new FileOutputStream(destPath);
xssfWorkbook.write(fileOutputStream);
fileOutputStream.close();
}
合并效果:
6.合并单元格的优化 ----- addMergedRegionUnsafe
当我们还使用addMergedRegion方法的时候,比如循环10000次合并操作,可以计算一下耗时
private static void mergeWithXSSF1(String destPath) throws IOException {
XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
XSSFSheet sheet = xssfWorkbook.createSheet("new Sheet");
long startTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
XSSFRow row = sheet.createRow(i);
XSSFCell cell = row.createCell(1);
cell.setCellValue("测试合并单元格");
sheet.addMergedRegion(new CellRangeAddress(i, i, 1, 2));
}
long endTime = System.currentTimeMillis();
System.out.println("耗费时间: " + (endTime - startTime));
FileOutputStream fileOutputStream = new FileOutputStream(destPath);
xssfWorkbook.write(fileOutputStream);
fileOutputStream.close();
}
耗费时间: 22918
如果换成addMergedRegionUnsafe方法,同样循环10000次合并操作,计算了一下耗时
private static void mergeWithXSSF1(String destPath) throws IOException {
XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
XSSFSheet sheet = xssfWorkbook.createSheet("new Sheet");
long startTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
XSSFRow row = sheet.createRow(i);
XSSFCell cell = row.createCell(1);
cell.setCellValue("测试合并单元格");
// 改成不校验
sheet.addMergedRegionUnsafe(new CellRangeAddress(i, i, 1, 2));
}
long endTime = System.currentTimeMillis();
System.out.println("耗费时间: " + (endTime - startTime));
FileOutputStream fileOutputStream = new FileOutputStream(destPath);
xssfWorkbook.write(fileOutputStream);
fileOutputStream.close();
}
耗费时间: 926
可以看到,消耗的时间是大大减少的。