diff --git a/.gitignore b/.gitignore
index 549e00a..e92c632 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,4 @@ build/
### VS Code ###
.vscode/
+/target/
diff --git a/.idea/misc.xml b/.idea/misc.xml
index b268cf8..b169464 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,3 +1,4 @@
+
@@ -73,7 +74,7 @@
-
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index c85fa9d..2a38a9a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,11 +1,12 @@
-
4.0.0
org.springframework.boot
spring-boot-starter-parent
- 3.3.4
+ 3.5.7
com.example
@@ -27,7 +28,7 @@
- 17
+ 11
@@ -54,12 +55,12 @@
org.apache.poi
poi
- 5.2.5
+ 5.4.1
org.apache.poi
poi-ooxml
- 5.2.5
+ 5.4.1
org.jetbrains
diff --git a/src/main/java/com/example/parser/FlowableExcelMapper.java b/src/main/java/com/example/parser/FlowableExcelMapper.java
new file mode 100644
index 0000000..16c0dd0
--- /dev/null
+++ b/src/main/java/com/example/parser/FlowableExcelMapper.java
@@ -0,0 +1,100 @@
+package com.example.parser;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+
+@Component
+public class FlowableExcelMapper {
+
+ protected static ObjectMapper objectMapper = new ObjectMapper();
+ protected static FlowableExcelParser flowableExcelParser = new FlowableExcelParser();
+
+ public ArrayNode excelToJsonNode(String excelPath) {
+ ArrayList> rowList = flowableExcelParser.parseExcel(excelPath);
+ ArrayNode arrayNode = objectMapper.createArrayNode();
+ for (LinkedHashMap row : rowList) {
+ JsonNode jsonNode = null;
+ Set> entries = row.entrySet();
+ for (Map.Entry entry : entries) {
+ jsonNode = addNode(jsonNode, entry.getKey(), entry.getValue());
+ }
+ arrayNode.add(jsonNode);
+ }
+ return arrayNode;
+ }
+
+ public JsonNode addNode(JsonNode parent, String path, Object value) {
+ objectMapper = new ObjectMapper();
+
+ if (parent == null) {
+ parent = objectMapper.createObjectNode();
+ }
+
+ int delimiterPosition = indexOfFirstDelimiter(path, ".*");
+ if (delimiterPosition <= 0) {
+ if (parent instanceof ObjectNode) {
+ // Key of a value in an ObjectNode
+ ((ObjectNode) parent).set(path, objectMapper.valueToTree(value));
+ } else {
+ // Index of a value in an ArrayNode
+ int index = Integer.parseInt(path);
+ for (int i = 0; parent.size() <= index; i++) {
+ ((ArrayNode) parent).add(objectMapper.createObjectNode());
+ }
+ ((ArrayNode) parent).set(index, objectMapper.valueToTree(value));
+ }
+ return parent;
+ }
+
+ String key = path.substring(0, delimiterPosition);
+ String newPath = path.substring(delimiterPosition + 1);
+ String delimiter = path.substring(delimiterPosition, delimiterPosition + 1);
+ JsonNode child = null;
+ if (delimiter.equals(".")) {
+ child = objectMapper.createObjectNode();
+ } else if (delimiter.equals("*")) {
+ child = objectMapper.createArrayNode();
+ }
+
+ JsonNode node;
+ if (parent instanceof ObjectNode) {
+ // Key of a JsonNode in an ObjectNode
+ node = parent.get(key);
+ if (node != null) {
+ // Take the existing ObjectNode as child
+ child = node;
+ }
+ ((ObjectNode) parent).set(key, addNode(child, newPath, value));
+ } else {
+ // Index of a JsonNode in an ArrayNode
+ int index = Integer.parseInt(key);
+ node = parent.get(index);
+ if (node != null) {
+ // Take the existing ArrayNode as child
+ child = node;
+ }
+ // Create empty entries to parent ArrayNode
+ for (int i = 0; parent.size() <= index; i++) {
+ ((ArrayNode) parent).add(objectMapper.createObjectNode());
+ }
+ ((ArrayNode) parent).set(index, addNode(child, newPath, value));
+ }
+ return parent;
+ }
+
+ public static int indexOfFirstDelimiter(String str, String delimiters) {
+ for (int i = 0; i < str.length(); i++) {
+ for (char c : delimiters.toCharArray()) {
+ if (str.charAt(i) == c) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+}
diff --git a/src/main/java/com/example/parser/FlowableExcelParser.java b/src/main/java/com/example/parser/FlowableExcelParser.java
index 1efdc27..8ff5a7a 100644
--- a/src/main/java/com/example/parser/FlowableExcelParser.java
+++ b/src/main/java/com/example/parser/FlowableExcelParser.java
@@ -9,11 +9,11 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
-import java.util.List;
@Component
public class FlowableExcelParser {
- public ArrayList> parseExcel(String resourcePath, List colNumberList) {
+
+ public ArrayList> parseExcel(String resourcePath) {
ArrayList> rowList = new ArrayList<>();
try (FileInputStream fileInputStream = new FileInputStream(resourcePath)) {
Workbook workbook = new XSSFWorkbook(fileInputStream);
@@ -22,25 +22,36 @@ public class FlowableExcelParser {
for (Row row : sheet) {
if (row.getRowNum() == 0) {
// Header row
- for (Integer colNumber : colNumberList) {
- colHeaders.add(row.getCell(colNumber).getStringCellValue());
+ for (int colNum = 0; colNum < row.getLastCellNum(); colNum++) {
+ Cell cell = row.getCell(colNum);
+ if (cell == null || cell.getCellType() == CellType.BLANK || cell.getCellType() == CellType._NONE) {
+ // Take all columns until the first empty header cell
+ break;
+ } else {
+ colHeaders.add(cell.getStringCellValue());
+ }
}
continue;
}
+ boolean allCellsNull = true;
LinkedHashMap rowMap = new LinkedHashMap<>();
- for (int i = 0; i < colNumberList.size(); i++) {
- Integer colNumber = colNumberList.get(i);
+ for (int colNum = 0; colNum < colHeaders.size(); colNum++) {
Object content = null;
- Cell cell = row.getCell(colNumber);
+ Cell cell = row.getCell(colNum);
CellValue cellValue = workbook.getCreationHelper().createFormulaEvaluator().evaluate(cell);
- if (cellValue != null) {
+ if (cellValue != null && cell.getCellType() != CellType.BLANK && cell.getCellType() != CellType._NONE) {
switch (cellValue.getCellType()) {
case STRING : content = cellValue.getStringValue(); break;
case BOOLEAN : content = cellValue.getBooleanValue(); break;
case NUMERIC : content = cellValue.getNumberValue(); break;
}
+ allCellsNull = false;
}
- rowMap.put(colHeaders.get(i), content);
+ rowMap.put(colHeaders.get(colNum), content);
+ }
+ if (allCellsNull) {
+ // Take all rows until the first empty row
+ return rowList;
}
rowList.add(rowMap);
}
diff --git a/src/main/java/com/example/parser/ParserApp.java b/src/main/java/com/example/parser/ParserApp.java
index 2dc04e3..74ed2aa 100644
--- a/src/main/java/com/example/parser/ParserApp.java
+++ b/src/main/java/com/example/parser/ParserApp.java
@@ -9,7 +9,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
-import java.util.List;
import java.util.Map;
@SpringBootApplication
@@ -32,6 +31,6 @@ public class ParserApp {
ClassLoader classLoader = ParserApp.class.getClassLoader();
URL resourceUrl = classLoader.getResource("flowableExcelParserExampleData.xlsx");
assert resourceUrl != null;
- logger.info("parsed excel={}", flowableExcelParser.parseExcel(resourceUrl.getPath(), List.of(0,1,2,4,5,6)));
+ logger.info("parsed excel={}", flowableExcelParser.parseExcel(resourceUrl.getPath()));
}
}
diff --git a/src/test/java/com/example/parser/FlowableExcelMapperTest.java b/src/test/java/com/example/parser/FlowableExcelMapperTest.java
new file mode 100644
index 0000000..e25becc
--- /dev/null
+++ b/src/test/java/com/example/parser/FlowableExcelMapperTest.java
@@ -0,0 +1,50 @@
+package com.example.parser;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.net.URL;
+
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+@SpringBootTest
+class FlowableExcelMapperTest {
+
+ @Autowired
+ private FlowableExcelMapper flowableExcelMapper;
+
+ private static final Logger logger = LoggerFactory.getLogger(ParserApp.class);
+
+
+ @Test
+ public void addNodeTest() {
+ JsonNode node = null;
+ node = flowableExcelMapper.addNode(node, "3*0*2", "String1");
+ node = flowableExcelMapper.addNode(node, "3*0*3", "String1");
+ node = flowableExcelMapper.addNode(node, "3*1.1", 234);
+ node = flowableExcelMapper.addNode(node, "3*1.2", 234);
+ node = flowableExcelMapper.addNode(node, "3*2", false);
+ node = flowableExcelMapper.addNode(node, "4.5", "String1");
+ node = flowableExcelMapper.addNode(node, "4.6", 234);
+ node = flowableExcelMapper.addNode(node, "4.7", false);
+ logger.info("node2={}{}", System.lineSeparator(), node.toPrettyString());
+ }
+
+ protected String getResourcePath(String path) {
+ ClassLoader classLoader = FlowableExcelMapperTest.class.getClassLoader();
+ URL resourceUrl = classLoader.getResource(path);
+ Assertions.assertThat(resourceUrl).isNotNull();
+ return resourceUrl.getPath();
+ }
+
+ @Test
+ public void excelToJsonNodeTest() {
+ JsonNode node = flowableExcelMapper.excelToJsonNode(getResourcePath("flowableExcelMapperTestData1.xlsx"));
+ logger.info("node2={}{}", System.lineSeparator(), node.toPrettyString());
+ }
+}
diff --git a/src/test/java/com/example/parser/FlowableExcelParserTest.java b/src/test/java/com/example/parser/FlowableExcelParserTest.java
index d16e72c..ed4f4de 100644
--- a/src/test/java/com/example/parser/FlowableExcelParserTest.java
+++ b/src/test/java/com/example/parser/FlowableExcelParserTest.java
@@ -20,12 +20,12 @@ class FlowableExcelParserTest {
@Autowired
private FlowableExcelParser flowableExcelParser;
- private Stream GetArgumentsFromExcel(String path, List colNumberList) {
+ private Stream GetArgumentsFromExcel(String path) {
ArrayList argumentList = new ArrayList<>();
ClassLoader classLoader = FlowableExcelParserTest.class.getClassLoader();
URL resourceUrl = classLoader.getResource(path);
Assertions.assertThat(resourceUrl).isNotNull();
- ArrayList> rowList = flowableExcelParser.parseExcel(resourceUrl.getPath(), colNumberList);
+ ArrayList> rowList = flowableExcelParser.parseExcel(resourceUrl.getPath());
Assertions.assertThat(rowList).isNotNull();
for (LinkedHashMap row : rowList) {
LinkedHashMap inputMap = new LinkedHashMap<>();
@@ -46,7 +46,7 @@ class FlowableExcelParserTest {
@NotNull
private Stream booleanExcelParserTestDataProvider() {
- return GetArgumentsFromExcel("flowableExcelParserTestData1.xlsx", List.of(0,1,2,4,5));
+ return GetArgumentsFromExcel("flowableExcelParserTestData1.xlsx");
}
@ParameterizedTest
@@ -67,7 +67,7 @@ class FlowableExcelParserTest {
@NotNull
private Stream stringExcelParserTestDataProvider() {
- return GetArgumentsFromExcel("flowableExcelParserTestData2.xlsx", List.of(0,1,2,4,5,6));
+ return GetArgumentsFromExcel("flowableExcelParserTestData2.xlsx");
}
@ParameterizedTest
@@ -92,7 +92,7 @@ class FlowableExcelParserTest {
@NotNull
private Stream numberExcelParserTestDataProvider() {
- return GetArgumentsFromExcel("flowableExcelParserTestData3.xlsx", List.of(0,1,2,4,5,6));
+ return GetArgumentsFromExcel("flowableExcelParserTestData3.xlsx");
}
@ParameterizedTest
diff --git a/src/test/resources/flowableExcelMapperTestData1.xlsx b/src/test/resources/flowableExcelMapperTestData1.xlsx
new file mode 100644
index 0000000..60d1406
Binary files /dev/null and b/src/test/resources/flowableExcelMapperTestData1.xlsx differ