java - 将数据保存到表中并将其保存到数据库中,即使 EXCEL 中为空行 java POI Apache

标签 java excel spring spring-boot apache-poi

我不知道如何将内容保存在数据库中,我尝试导入 Excel,它可以工作,但如果 Excel 的其中一行为空,则会出现 java.lang.IndexOutOfBoundsException

--这是我的代码--

-- BranchEntity.java --

公开课分支{

private static final long serialVersionUID = 1L;

@Column(name = "branch_code", nullable = false, length = 10)
private String branchCode;

@Column(name = "branch_desc", nullable = false, length = 100)
private String branchDescription;

@OneToMany(mappedBy = "branch", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JsonIgnore
private List<User> user;

public Branch(String branchCode, String branchDescription, List<User> user) {
    super();
    this.branchCode = branchCode;
    this.branchDescription = branchDescription;
    this.user = user;
}

public Branch() {
    super();
}

public String getBranchCode() {
    return branchCode;
}

public void setBranchCode(String branchCode) {
    this.branchCode = branchCode;
}

public String getBranchDescription() {
    return branchDescription;
}

public void setBranchDescription(String branchDescription) {
    this.branchDescription = branchDescription;
}

public List<User> getUser() {
    return user;
}

public void setUser(List<User> user) {
    this.user = user;
}

}

-- BranchService.java ---

@Autowired 私有(private) BranchRepository 分支存储库;

公共(public)列表> uploadEmployee(MultipartFile multip) 抛出异常 {

    DataFormatter formatter = new DataFormatter();

    String fileNames = multip.getOriginalFilename();

    File file = new File("./reports/" + fileNames);
    Workbook workbook = WorkbookFactory.create(file);

    FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();

    Sheet sheet = workbook.getSheetAt(0);

    Supplier<Stream<Row>> rowStreamSupplier = uploadUtils.getRowStreamSupplier(sheet);

    Row headerRow = rowStreamSupplier.get().findFirst().get();
    List<String> headerCells = uploadUtils.getStream(headerRow)
    .map(Cell::getStringCellValue) 
    .collect(Collectors.toList());

    int colCount = headerCells.size();

    List<Map<String, String>> content = rowStreamSupplier.get()
    .skip(1)
    .map(row -> {

    List<String> cellList = uploadUtils.getStream(row)
    .map((cell) -> formatter.formatCellValue(cell, evaluator))
    .collect(Collectors.toList());  
        return uploadUtils.cellIteratorSupplier(colCount)
    .get()
    .collect(Collectors.toMap(headerCells::get, cellList::get));
    }).collect(Collectors.toList());

    branchRepository.save(content);

    workbook.close();

    return content;

}

-- BranchController.java --

@RequestMapping(value = "/uploadEmployee", method = RequestMethod.POST)
public List<Map<String, String>> uploadEmployee(MultipartFile file) throws Exception {
    return employeeService.uploadEmployee(file);
}

最佳答案

要避免 java.lang.IndexOutOfBoundsException,您需要避免 java.util.stream.* 方法,因为这完全取决于使用 Iterators。但是 apache poi 的繁忙开发者指南 -> Iterate over rows and cells告诉:

Note that a rowIterator and cellIterator iterate over rows or cells that have been created, skipping empty rows and cells.

因此空行和单元格不会被迭代。这就是为什么从 cellIterator 获取空单元格是不可能的并且会失败。

为了避免这种情况,我们应该执行以下操作:

首先收集列标题作为标题名称到列索引的Map。这可以使用第一行上的单元迭代器来完成。如果单元格为空,则将跳过此列。

然后将内容收集到所需的 MapList 中,其中单元格值映射到标题名称。必须使用从第一个标题列索引到最后一个标题列索引的 for 循环对每一行执行此操作。如果单元格为空,则可以将单元格创建为空单元格。因此,DataFormatter 将其值获取为空字符串。

完整的工作示例:

import org.apache.poi.ss.usermodel.*;

import java.io.File;
import java.util.*;

public class ReadExcelToCollection {

 public static void main(String[] args) throws Exception {

  DataFormatter formatter = new DataFormatter();

  File file = new File("Excel.xlsx");
  Workbook workbook = WorkbookFactory.create(file);

  FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();

  Sheet sheet = workbook.getSheetAt(0);

  int headerRowNum = sheet.getFirstRowNum();

  // collecting the column headers as a Map of header names to column indexes
  Map<Integer, String> colHeaders = new HashMap<Integer, String>();
  Row row = sheet.getRow(headerRowNum);
  for (Cell cell : row) {
   int colIdx = cell.getColumnIndex();
   String value = formatter.formatCellValue(cell, evaluator);
   colHeaders.put(colIdx, value);
  }

  System.out.println(colHeaders);

  // collecting the content into List of Maps where cell values are mapped to header names.
  List<Map<String, String>> content = new ArrayList<Map<String, String>>();
  for (int r = headerRowNum + 1; r <= sheet.getLastRowNum(); r++) {
   row = sheet.getRow(r); if (row == null) row = sheet.createRow(r);
   Map<String, String> valuesToHeaders = new HashMap<String, String>();
   for (Map.Entry<Integer, String> entry : colHeaders.entrySet()) {
    int colIdx = entry.getKey();
    Cell cell = row.getCell(colIdx); if (cell == null) cell = row.createCell(colIdx);
    String cellValue = formatter.formatCellValue(cell, evaluator);
    valuesToHeaders.put(entry.getValue(), cellValue);
   }
   content.add(valuesToHeaders);
  }

  System.out.println(content);

  workbook.close();
 }
}

关于java - 将数据保存到表中并将其保存到数据库中,即使 EXCEL 中为空行 java POI Apache,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58974646/

相关文章:

java - 使用 AsyncTask 作为内部类

java - 如何在Struts 2中显示图像?

vb.net - 如何在使用 Visual Studio 2010 创建的 Excel 加载项中执行 .Onkey 事件?

vba - 如何将 excel VBA UI 放在前面

java - 如何使用 Gradle 在 Spring Boot 中覆盖来自 Thymeleaf 1.5.8.RELEASE 的传递依赖 Groovy 版本

java - 如何根据日期和时间自动运行特定的代码块?

java - Spring集成TCP服务器: Get the Ip address & the payload

java - Storm Bolt 中跨任务的变量

java - Libgdx 1.2.0 Controller 扩展崩溃

excel - 如果单元格包含 .com 或 .co.uk - excel/google 电子表格中的 if 语句