1.依赖

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.15</version>
</dependency>

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>

2.模板例子

这是我在实际工作中需要导入的模板


springboot  excel 导入到数据 功能实现_xml image.png

3.导入原理

我们需要解析excel的数据,而每个单元格都是有格式的,比如数值类型的,你就无法解析成字符串,所以格式这块要弄好,然后解析的时候是按照 sheet页,行,格子 这样的顺序解析的,比如图中就是首先拿到第一个sheet页,然后遍历第一行,然后遍历格子这样取数据的。

图中的数据,我需要首先拿到导入数据的所有日期,然后呢,每一个物料,每一天的数据作为一条数据,然后都收集好之后再统一插入到数据库中,下面是我的实际代码:

步骤1.获取所有日期 2.删除掉数据库中的旧数据 3.解析数据 4.插入数据

可以看到在excel中的数据其实从第三行开始,所以下标我从2开始读,然后每一行我获取前两个格子作为基础数据,从第三个格子开始生成每一条数据。

最后我使用批量插入的操作,这种jdbc的插入速度非常快,所以使用这种方式,我感觉也好用的。

@Transactional
@PostMapping(path = "importOrderPlan")
@ApiOperation(value = "导入装机计划")
public Response importOrderPlan(@RequestParam("file") MultipartFile file) {
if (OrderPlanImportHelper.hasExcelFormat(file)) {
try {
Workbook workbook = new XSSFWorkbook(file.getInputStream());
Sheet sheet = workbook.getSheetAt(0);
//获取所有的物料数据
String sql = "select plant_id,item_id,item_code from mdas.t06_item";
List<ItemDto> itemList = jdbcTemplate.query(sql, new BeanPropertyRowMapper(ItemDto.class));
Map<String, ItemDto> itemMap = itemList.stream().collect(Collectors.toMap(ItemDto::getItem_code, Function.identity(), (a, b) -> a));

//获取日期数组
int year = LocalDate.now().getYear();
List<String> days = new ArrayList<>();
int countFirstRowCellNumber = sheet.getRow(0).getPhysicalNumberOfCells();
for (int cellIndex = 2; cellIndex < countFirstRowCellNumber - 1; cellIndex++) {
days.add(year + "-" + sheet.getRow(0).getCell(cellIndex).getStringCellValue());
}

//清除掉旧数据
String delSql = "delete from mdas.t06_day_loading_plan where zday >= '" + days.get(0) + "' and zday<='"+days.get(days.size()-1)+"'";
jdbcTemplate.update(delSql);

List<OrderPlanInsertDto> orderPlanInsertList = new ArrayList<>();
OrderPlanInsertDto orderPlanInsertDto;
Cell cell;
String itemCode, itemName, ItemId, plantId;
int countRowCellNumber;
for (int row = 2; row < sheet.getPhysicalNumberOfRows(); row++) {
countRowCellNumber = sheet.getRow(row).getPhysicalNumberOfCells();
//判断是否含有物料id
if (!itemMap.containsKey(sheet.getRow(row).getCell(0).getStringCellValue())) continue;
if (StringUtils.isBlank(sheet.getRow(row).getCell(0).getStringCellValue())) continue;
if (StringUtils.isBlank(sheet.getRow(row).getCell(1).getStringCellValue())) continue;

itemCode = sheet.getRow(row).getCell(0).getStringCellValue();
itemName = sheet.getRow(row).getCell(0).getStringCellValue();
ItemId = itemMap.get(itemCode).getItem_id();
plantId = itemMap.get(itemCode).getPlant_id();

for (int cellIndex = 2; cellIndex < countRowCellNumber - 1; cellIndex++) {
cell = sheet.getRow(row).getCell(cellIndex);
orderPlanInsertDto = new OrderPlanInsertDto();
orderPlanInsertDto.setPlant_id(plantId);
orderPlanInsertDto.setItem_id(ItemId);
orderPlanInsertDto.setItem_code(itemCode);
orderPlanInsertDto.setItem_descriptions(itemName);
orderPlanInsertDto.setQty((long) (cell.getNumericCellValue()));
orderPlanInsertDto.setZday(days.get(cellIndex - 2));
orderPlanInsertList.add(orderPlanInsertDto);
}
}
//保存数据
saveOrderPlan(orderPlanInsertList);
return Response.OK;
} catch (Exception e) {
return Response.fail(e.getMessage());
}
}
return Response.OK;
}

//保存数据
private void saveOrderPlan(List<OrderPlanInsertDto> orderPlanInsertList) {
Timestamp nowDate = new Timestamp(System.currentTimeMillis());
jdbcTemplate.batchUpdate("INSERT INTO mdas.t06_day_loading_plan (plant_id, item_code, item_descriptions, qty, zday, input_time, item_id,prod_line_code)" +
" VALUES (?,?,?,?,?,?,?,?)",
new BatchPreparedStatementSetter() {
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setString(1, orderPlanInsertList.get(i).getPlant_id());//随机id
ps.setString(2, orderPlanInsertList.get(i).getItem_code());
ps.setString(3, orderPlanInsertList.get(i).getItem_descriptions());
ps.setLong(4, orderPlanInsertList.get(i).getQty());
ps.setString(5, orderPlanInsertList.get(i).getZday());
ps.setTimestamp(6, nowDate);
ps.setString(7, orderPlanInsertList.get(i).getItem_id());
ps.setString(8, null);
}
public int getBatchSize() {
return orderPlanInsertList.size();
}
});
}

下面是OrderPlanImportHelper代码,其实就是个判断,也可以拿出来,这都无所谓:

public static String TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
static String[] HEADERs = { "Id", "Title", "Description", "Published" };
static String SHEET = "Tutorials";

public static boolean hasExcelFormat(MultipartFile file) {
if (!TYPE.equals(file.getContentType())) {
return false;
}
return true;
}