Java实际项目中怎么利用POI解析Excel,实现数据的批量导入批量导出~
程序员文章站
2022-04-30 16:33:34
...
前言:
在真实的互联网项目中,很多项目都需要批量的导入导出数据,那么是如何实现的呢?
引入的依赖
<!--利用poi 读取excel-->
<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>
简单说明
主要有四个属性,Workbook(工作表),Sheet(表单),Row(行), Cell(单元格)
需要读取的文件
读取的Excel文件
读取Excel
思路是按照Workbook,Sheet,Row,Cell一层一层往下读取。
首先是初始化Workbook
private Workbook getReadWorkBookType(String filePath) throws BusinessException {
//xls-2003, xlsx-2007
FileInputStream is = null;
try {
is = new FileInputStream(filePath);
if (filePath.toLowerCase().endsWith("xlsx")) {
return new XSSFWorkbook(is);
} else if (filePath.toLowerCase().endsWith("xls")) {
return new HSSFWorkbook(is);
} else {
// 抛出自定义的业务异常
throw OnlinePayErrorCode.EXCEL_ANALYZE_ERROR.convertToException("excel格式文件错误");
}
} catch (IOException e) {
// 抛出自定义的业务异常
throw OnlinePayErrorCode.EXCEL_ANALYZE_ERROR.convertToException(e.getMessage());
} finally {
IOUtils.closeQuietly(is);
}
}
关于版本不同的Excel如何初始化Workbook
点击阅读
解析Excel文件
因为我的excel只有一页sheet,所以直接读取第0页sheet(workbook.getSheetAt(0)),如果有多个可以自行顺序循环读取;
并且我只有一列数据,所以每次只读取第0列的数据(row.getCell(0)),如果有多个可以依次循环读取。
把excel文件里的数据读取放入一个List中
public List readExcel(String sourceFilePath) throws BusinessException {
Workbook workbook = null;
try {
workbook = getReadWorkBookType(sourceFilePath);
List<String> contents = Lists.newArrayList();
//获取第一个sheet
Sheet sheet = workbook.getSheetAt(0);
//第0行是表名,忽略,从第二行开始读取
for (int rowNum = 1; rowNum <= sheet.getLastRowNum(); rowNum++) {
Row row = sheet.getRow(rowNum);
Cell cell = row.getCell(0);
contents.add(getCellStringVal(cell).trim());
}
return contents;
} finally {
IOUtils.closeQuietly(workbook);
}
}
如果excel中的数据是数字,会发现java中对应的变成了科学计数法的,
所以在获取值的时候就要做一些特殊处理,这样就能保证获取的值是我想要的值。
private String getCellStringVal(Cell cell) {
CellType cellType = cell.getCellTypeEnum();
switch (cellType) {
case NUMERIC:
return cell.getStringCellValue();
case STRING:
return cell.getStringCellValue();
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case FORMULA:
return cell.getCellFormula();
case BLANK:
return "";
case ERROR:
return String.valueOf(cell.getErrorCellValue());
default:
return StringUtils.EMPTY;
}
}
然后写入Excel
我需要实现的写入格式是
写入的Excel格式
三列分别是租户id, 门店id和入件状态,前两列是数值类型,最后一个列是字符串类型。
按照Workbook,Sheet, Row, Cell依次创建,并将数据写入cell中
同理先初始化Workbook
private Workbook getWriteWorkBoolType(String filePath) throws BusinessException{
if (filePath.toLowerCase().endsWith("xlsx")) {
return new XSSFWorkbook();
} else if (filePath.toLowerCase().endsWith("xls")) {
return new HSSFWorkbook();
} else {
//抛出自定的业务异常
throw OnlinePayErrorCode.EXCEL_ANALYZE_ERROR.convertToException("excel格式文件错误");
}
}
将数据写入到Excel中
public void writeExcel(String targetFilePath, List<? extends GetPoiAccountSettingsFromExcelVO> contents) throws BusinessException {
Workbook workbook = null;
FileOutputStream fos = null;
workbook = getWriteWorkBoolType(targetFilePath);
//创建sheet
Sheet sheet = workbook.createSheet("门店入件状态");
//在sheet第一行写出表单的各个字段名
Row titleRow = sheet.createRow(0);
titleRow.createCell(0).setCellValue("租户id");
titleRow.createCell(1).setCellValue("门店id");
titleRow.createCell(2).setCellValue("入件状态");
//每行的单元格一次写入
Integer rowIndex = contents.size();
for (int i = 0; i < rowIndex; i++) {
//第1行作为表格列名,所以从第2行开始读取
Row row = sheet.createRow(i + 1);
Cell cellTenantId = row.createCell(0);
cellTenantId.setCellValue(contents.get(i).getTenantId());
Cell cellPoiId = row.createCell(1);
cellPoiId.setCellValue(contents.get(i).getMerchantId());
Cell cellStatus = row.createCell(2);
cellStatus.setCellValue(contents.get(i).getMerchantStatus());
}
//写入到文件流中
try {
fos = new FileOutputStream(targetFilePath);
workbook.write(fos);
} catch (IOException e) {
throw OnlinePayErrorCode.EXCEL_ANALYZE_ERROR.convertToException(e.getMessage());
} finally {
IOUtils.closeQuietly(workbook);
}
}
读取测试
@Test
public void testReadXls() {
String path = "../crm-onlinepay-web/tenantId.xls";
try {
List<String> tenantIds = excelUtils.readExcel(path);
LOGGER.info("tenantIds:{}", tenantIds);
} catch (Exception e) {
LOGGER.info("exception:", e);
}
}
测试结果:
2017-09-12 11:01:41,124 INFO (AccountSettingRemoteServiceTest.java:138) - tenantIds:[10193, 8902, 10191, 10129, 10107, 10105, 10041]
写入测试
@Test
public void writeXls() {
String path = "../crm-onlinepay-web/PoiStatus.xls";
GetPoiAccountSettingsFromExcelVO excelVO = new GetPoiAccountSettingsFromExcelVO(1, 2, "WAIT");
GetPoiAccountSettingsFromExcelVO excelVO1 = new GetPoiAccountSettingsFromExcelVO(3, 4, "WAIT");
GetPoiAccountSettingsFromExcelVO excelVO2 = new GetPoiAccountSettingsFromExcelVO(5, 6, "WAIT");
GetPoiAccountSettingsFromExcelVO excelVO3 = new GetPoiAccountSettingsFromExcelVO(7, 8, "WAIT");
List<GetPoiAccountSettingsFromExcelVO> excelVOS = Lists.newArrayList(excelVO, excelVO1, excelVO2, excelVO3);
try {
excelUtils.writeExcel(path, excelVOS);
} catch (Exception e) {
LOGGER.info("exception:", e);
}
}
测试结果: