From 988a420d8dcd1089fb76c351e33a681256cd946d Mon Sep 17 00:00:00 2001 From: pipinet Date: Wed, 3 Jan 2024 22:19:03 +0800 Subject: [PATCH] feat: add excel --- .../java/com/qwlabs/excel/DataReader.java | 2 +- .../java/com/qwlabs/excel/ExcelHeaders.java | 29 ------------ .../java/com/qwlabs/excel/ExcelHelper.java | 43 ++++++++++++++++++ .../com/qwlabs/excel/SingleRowReader.java | 5 +- .../com/qwlabs/excel/SingleRowReaderTest.java | 14 +++--- .../src/test/resources/single-row-reader.xlsx | Bin 14654 -> 10204 bytes 6 files changed, 53 insertions(+), 40 deletions(-) delete mode 100644 excel/src/main/java/com/qwlabs/excel/ExcelHeaders.java create mode 100644 excel/src/main/java/com/qwlabs/excel/ExcelHelper.java diff --git a/excel/src/main/java/com/qwlabs/excel/DataReader.java b/excel/src/main/java/com/qwlabs/excel/DataReader.java index b38f1d7..2870fb7 100644 --- a/excel/src/main/java/com/qwlabs/excel/DataReader.java +++ b/excel/src/main/java/com/qwlabs/excel/DataReader.java @@ -43,7 +43,7 @@ public Listener(Map headMapping) { @Override public void invokeHeadMap(Map headMap, AnalysisContext context) { - this.indexFields.putAll(ExcelHeaders.lookupHeaders(headMap, headMapping)); + this.indexFields.putAll(ExcelHelper.lookupHeaders(headMap, headMapping)); } @Override diff --git a/excel/src/main/java/com/qwlabs/excel/ExcelHeaders.java b/excel/src/main/java/com/qwlabs/excel/ExcelHeaders.java deleted file mode 100644 index 0b856c8..0000000 --- a/excel/src/main/java/com/qwlabs/excel/ExcelHeaders.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.qwlabs.excel; - -import com.google.common.collect.Maps; -import jakarta.validation.constraints.NotNull; - -import java.util.Map; -import java.util.Objects; - -public class ExcelHeaders { - public static Map lookupHeaders(@NotNull Map headerData, - @NotNull Map lookups) { - Map headers = Maps.newHashMapWithExpectedSize(headerData.size()); - headerData.forEach((index, title) -> { - if (Objects.isNull(title)) { - return; - } - var newTitle = lookups.get(title); - if (Objects.nonNull(newTitle)) { - headers.put(index, newTitle); - } - }); - headerData.forEach((index, title) -> { - if (!headers.containsKey(index) && Objects.nonNull(title)) { - headers.put(index, title); - } - }); - return headers; - } -} diff --git a/excel/src/main/java/com/qwlabs/excel/ExcelHelper.java b/excel/src/main/java/com/qwlabs/excel/ExcelHelper.java new file mode 100644 index 0000000..fd6fb07 --- /dev/null +++ b/excel/src/main/java/com/qwlabs/excel/ExcelHelper.java @@ -0,0 +1,43 @@ +package com.qwlabs.excel; + +import com.google.common.collect.Maps; +import jakarta.validation.constraints.NotNull; + +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.function.BiPredicate; + +public final class ExcelHelper { + private ExcelHelper() { + } + + public static Map cleanup(Map data) { + return cleanup(data, (index, value) -> Objects.nonNull(value)); + } + + public static Map cleanup(Map data, + BiPredicate predicate) { + Map cleanup = Maps.newHashMap(); + Optional.ofNullable(data).orElseGet(Map::of) + .forEach((index, value) -> { + if (predicate.test(index, value)) { + cleanup.put(index, value); + } + }); + return cleanup; + } + + public static Map lookupHeaders(@NotNull Map headerData, + @NotNull Map lookups) { + Map headers = Maps.newHashMapWithExpectedSize(headerData.size()); + cleanup(headerData).forEach((index, title) -> { + var newTitle = lookups.get(title); + if (Objects.nonNull(newTitle)) { + headers.put(index, newTitle); + } + }); + headerData.forEach(headers::putIfAbsent); + return headers; + } +} diff --git a/excel/src/main/java/com/qwlabs/excel/SingleRowReader.java b/excel/src/main/java/com/qwlabs/excel/SingleRowReader.java index d4745c9..422a835 100644 --- a/excel/src/main/java/com/qwlabs/excel/SingleRowReader.java +++ b/excel/src/main/java/com/qwlabs/excel/SingleRowReader.java @@ -7,7 +7,6 @@ import java.io.InputStream; import java.util.Map; -import java.util.Optional; public class SingleRowReader { private final InputStream inputStream; @@ -22,11 +21,12 @@ public Map read(SheetReadOptions options, int rowIndex) { options.config(EasyExcel.read(inputStream, listener)) .headRowNumber(rowIndex + 1) .doRead(); - return listener.getData(); + return ExcelHelper.cleanup(listener.getData()); } private static final class Listener extends AnalysisEventListener> { private Map data; + @Override public boolean hasNext(AnalysisContext context) { return false; @@ -44,7 +44,6 @@ public void invoke(Map data, AnalysisContext context) { @Override public void doAfterAllAnalysed(AnalysisContext context) { - this.data = Optional.ofNullable(this.data).orElseGet(Map::of); } public Map getData() { diff --git a/excel/src/test/java/com/qwlabs/excel/SingleRowReaderTest.java b/excel/src/test/java/com/qwlabs/excel/SingleRowReaderTest.java index dbe8ec3..2e960e2 100644 --- a/excel/src/test/java/com/qwlabs/excel/SingleRowReaderTest.java +++ b/excel/src/test/java/com/qwlabs/excel/SingleRowReaderTest.java @@ -32,7 +32,7 @@ void should_read_twice() { SheetReadOptions.builder().sheetNo(0).build(), 1 ); - + valid(data1); valid(data2); } @@ -46,12 +46,12 @@ private void valid(Map data) { assertThat(data.get(4), is("发动机型号")); assertThat(data.get(5), is("发动机序列号")); assertThat(data.get(6), is("航站")); - assertThat(data.get(7), is("ATA章节")); - assertThat(data.get(8), is("故障描述")); - assertThat(data.get(9), is("处置措施")); - assertThat(data.get(10), is("故障发生时间")); - assertThat(data.get(11), is("故障记录时间")); - assertThat(data.get(12), is("故障关闭时间")); + assertThat(data.get(8), is("ATA章节")); + assertThat(data.get(9), is("故障描述")); + assertThat(data.get(10), is("处置措施")); + assertThat(data.get(11), is("故障发生时间")); + assertThat(data.get(12), is("故障记录时间")); + assertThat(data.get(13), is("故障关闭时间")); } private InputStream read(String path) { diff --git a/excel/src/test/resources/single-row-reader.xlsx b/excel/src/test/resources/single-row-reader.xlsx index e6c25d0bfd3d69b190a403097a29734e0b94d691..3248cb95a9e59e2726dae901e266f1b266d9e3e5 100644 GIT binary patch literal 10204 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 TYtjLP{PK~0@#aeO`s@DzX?m%B literal 14654 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