Игнорировать пустые ячейки, но не строки, используя Java - PullRequest
0 голосов
/ 21 января 2020

Я создаю java программу для загрузки файла Excel и чтения его как 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());
}

Util class

    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();
}

Исключение составляет:

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] 

1 Ответ

0 голосов
/ 22 января 2020

IndexOutOfBoundsException означает несоответствие между headerCells.size() и количеством ячеек содержимого в строке. В конкретном случае у вас есть 38 столбцов заголовков, но по крайней мере одна из ваших строк контента имеет только 37 ячеек контента. Действительно пустые ячейки не повторяются в Iterable row, потому что их нет в XML. Это приводит к headerCells.size() и colCount 38 (от 0 до 37), но к cellList.size() только 37 (от 0 до 36). Так что cellList::get завершается ошибкой, когда IntStream на 37.

Так что, если лист Excel может содержать действительно пустые ячейки, вы не можете использовать Iterable row. Вместо этого вам нужно использовать Row.getCell для каждого индекса столбца, который имеет представление в строке заголовка.

Используя Stream s, этого можно достичь, используя IntStream в диапазоне от 0 до colCount так же, как вы уже делаем это, чтобы собрать ячейки от Map headerCells до cellList. Затем вы получаете ячейку от 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();
 }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...