gpt4 book ai didi

java - 使用 Java 忽略空白单元格但不忽略行

转载 作者:行者123 更新时间:2023-12-01 18:45:58 25 4
gpt4 key购买 nike

我正在创建一个java程序来上传一个excel文件并使用spring boot将其读取为Json,但是每当我尝试上传我的文件时,它都会显示错误,并且还可以执行哪些操作来忽略任何空白单元格而不是行。

{
"timestamp": 1579604789613,
"status": 500,
"error": "Internal Server Error",
"exception": "java.lang.IndexOutOfBoundsException",
"message": "Index: 1, Size: 1",
"path": "/applications/upload"
}

服务等级如下

   Workbook workbook = WorkbookFactory.create(file.getInputStream());

Sheet sheet = workbook.getSheetAt(0);

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

Row headerRow = rowStreamSupplier.get().findFirst().get();

List<String> headerCells = uploadUtil.getStream(headerRow)
.map(Cell::getStringCellValue)
.collect(Collectors.toList());

int colCount = headerCells.size();

return rowStreamSupplier.get()
.skip(1)
.map(row -> {

List<String> cellList = uploadUtil.getStream(row)
.map(Cell::getStringCellValue)
.collect(Collectors.toList());

return uploadUtil.cellIteratorSupplier(colCount)
.get()
.collect(toMap(headerCells::get, cellList::get));

})
.collect(Collectors.toList());
}

实用程序类

    public Supplier<Stream<Row>> getRowStreamSupplier(Iterable<Row> rows) {
return () -> getStream(rows);
}

public <T> Stream<T> getStream(Iterable<T> rows) {
return StreamSupport.stream(rows.spliterator(), false);
}

public Supplier<Stream<Integer>> cellIteratorSupplier(int end) {
return () -> numberStream(end);
}

public Stream<Integer> numberStream(int end) {
return IntStream.range(0, end).boxed();
}

异常(exception)是:

java.lang.IndexOutOfBoundsException: Index: 37, Size: 37 at java.util.ArrayList.rangeCheck(ArrayList.java:653) ~[?:1.8.0_111]
at java.util.ArrayList.get(ArrayList.java:429) ~[?:1.8.0_111]
at com.application.lms.application.service.UploadService.lambda$upload$2(UploadService.java:57) ~[classes/:?]
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[?:1.8.0_111]

最佳答案

IndexOutOfBoundsException 是关于 headerCells.size() 和一行内容单元格计数之间的差异。在具体情况下,您有 38 个标题列,但至少其中一个内容行只有 37 个内容单元格。真正的空单元格不会被 Iterable row 迭代,因为它们不存在于 XML 中。这会导致 headerCells.size()colCount 为 38(0 到 37),但 cellList.size() 仅37(0 到 36)。因此,当 IntStream 为 37 时,cellList::get 会失败。

因此,如果 Excel 工作表可能包含真正的空单元格,则您不能使用 Iterable row。相反,您需要对标题行中具有表示形式的每个列索引使用 Row.getCell

使用 Stream 可以使用范围为 0 到 colCountIntStream 来实现,就像您已经收集的数据一样Map headerCellscellList 单元格。然后,您从 row::getCell 获取单元格,并从 formatter.formatCellValue(cell, evaluator) 获取单元格值,这会为不存在的空单元格返回一个空字符串。

示例:

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

import java.io.FileInputStream;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

public class ReadExcelUsingStreams {

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

DataFormatter formatter = new DataFormatter();

FileInputStream fileIn = new FileInputStream ("Excel.xlsx");
Workbook workbook = WorkbookFactory.create(fileIn);

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 -> formatter.formatCellValue(cell, evaluator))
.collect(Collectors.toList());

int colCount = headerCells.size();

List<Map<String, String>> content = rowStreamSupplier.get()
.skip(1)
.map(row -> {
List<String> cellList = UploadUtils.cellIteratorSupplier(colCount)
.get()
.map(row::getCell)
.map(cell -> formatter.formatCellValue(cell, evaluator))
.collect(Collectors.toList());
return UploadUtils.cellIteratorSupplier(colCount)
.get()
.collect(Collectors.toMap(headerCells::get, cellList::get));
})
.collect(Collectors.toList());

System.out.println(content);

workbook.close();
}
}

class UploadUtils {

static Supplier<Stream<Row>> getRowStreamSupplier(Iterable<Row> rows) {
return () -> getStream(rows);
}

static <T> Stream<T> getStream(Iterable<T> iterable) {
return StreamSupport.stream(iterable.spliterator(), false);
}

static Supplier<Stream<Integer>> cellIteratorSupplier(int end) {
return () -> numberStream(end);
}

static Stream<Integer> numberStream(int end) {
return IntStream.range(0, end).boxed();
}
}

关于java - 使用 Java 忽略空白单元格但不忽略行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59840220/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com