Added ExcelMapper
This commit is contained in:
@@ -31,3 +31,4 @@ build/
|
|||||||
|
|
||||||
### VS Code ###
|
### VS Code ###
|
||||||
.vscode/
|
.vscode/
|
||||||
|
/target/
|
||||||
|
|||||||
Generated
+2
-1
@@ -1,3 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="MavenProjectsManager">
|
<component name="MavenProjectsManager">
|
||||||
@@ -73,7 +74,7 @@
|
|||||||
</profile-state>
|
</profile-state>
|
||||||
</entry>
|
</entry>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="homebrew-17" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>3.3.4</version>
|
<version>3.5.7</version>
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.example</groupId>
|
<groupId>com.example</groupId>
|
||||||
@@ -27,7 +28,7 @@
|
|||||||
<url/>
|
<url/>
|
||||||
</scm>
|
</scm>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>17</java.version>
|
<java.version>11</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -54,12 +55,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
<artifactId>poi</artifactId>
|
<artifactId>poi</artifactId>
|
||||||
<version>5.2.5</version>
|
<version>5.4.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
<artifactId>poi-ooxml</artifactId>
|
<artifactId>poi-ooxml</artifactId>
|
||||||
<version>5.2.5</version>
|
<version>5.4.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jetbrains</groupId>
|
<groupId>org.jetbrains</groupId>
|
||||||
|
|||||||
@@ -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<LinkedHashMap<String, Object>> rowList = flowableExcelParser.parseExcel(excelPath);
|
||||||
|
ArrayNode arrayNode = objectMapper.createArrayNode();
|
||||||
|
for (LinkedHashMap<String, Object> row : rowList) {
|
||||||
|
JsonNode jsonNode = null;
|
||||||
|
Set<Map.Entry<String, Object>> entries = row.entrySet();
|
||||||
|
for (Map.Entry<String, Object> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,11 +9,11 @@ import java.io.FileInputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class FlowableExcelParser {
|
public class FlowableExcelParser {
|
||||||
public ArrayList<LinkedHashMap<String, Object>> parseExcel(String resourcePath, List<Integer> colNumberList) {
|
|
||||||
|
public ArrayList<LinkedHashMap<String, Object>> parseExcel(String resourcePath) {
|
||||||
ArrayList<LinkedHashMap<String, Object>> rowList = new ArrayList<>();
|
ArrayList<LinkedHashMap<String, Object>> rowList = new ArrayList<>();
|
||||||
try (FileInputStream fileInputStream = new FileInputStream(resourcePath)) {
|
try (FileInputStream fileInputStream = new FileInputStream(resourcePath)) {
|
||||||
Workbook workbook = new XSSFWorkbook(fileInputStream);
|
Workbook workbook = new XSSFWorkbook(fileInputStream);
|
||||||
@@ -22,25 +22,36 @@ public class FlowableExcelParser {
|
|||||||
for (Row row : sheet) {
|
for (Row row : sheet) {
|
||||||
if (row.getRowNum() == 0) {
|
if (row.getRowNum() == 0) {
|
||||||
// Header row
|
// Header row
|
||||||
for (Integer colNumber : colNumberList) {
|
for (int colNum = 0; colNum < row.getLastCellNum(); colNum++) {
|
||||||
colHeaders.add(row.getCell(colNumber).getStringCellValue());
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
boolean allCellsNull = true;
|
||||||
LinkedHashMap<String, Object> rowMap = new LinkedHashMap<>();
|
LinkedHashMap<String, Object> rowMap = new LinkedHashMap<>();
|
||||||
for (int i = 0; i < colNumberList.size(); i++) {
|
for (int colNum = 0; colNum < colHeaders.size(); colNum++) {
|
||||||
Integer colNumber = colNumberList.get(i);
|
|
||||||
Object content = null;
|
Object content = null;
|
||||||
Cell cell = row.getCell(colNumber);
|
Cell cell = row.getCell(colNum);
|
||||||
CellValue cellValue = workbook.getCreationHelper().createFormulaEvaluator().evaluate(cell);
|
CellValue cellValue = workbook.getCreationHelper().createFormulaEvaluator().evaluate(cell);
|
||||||
if (cellValue != null) {
|
if (cellValue != null && cell.getCellType() != CellType.BLANK && cell.getCellType() != CellType._NONE) {
|
||||||
switch (cellValue.getCellType()) {
|
switch (cellValue.getCellType()) {
|
||||||
case STRING : content = cellValue.getStringValue(); break;
|
case STRING : content = cellValue.getStringValue(); break;
|
||||||
case BOOLEAN : content = cellValue.getBooleanValue(); break;
|
case BOOLEAN : content = cellValue.getBooleanValue(); break;
|
||||||
case NUMERIC : content = cellValue.getNumberValue(); 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);
|
rowList.add(rowMap);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@@ -32,6 +31,6 @@ public class ParserApp {
|
|||||||
ClassLoader classLoader = ParserApp.class.getClassLoader();
|
ClassLoader classLoader = ParserApp.class.getClassLoader();
|
||||||
URL resourceUrl = classLoader.getResource("flowableExcelParserExampleData.xlsx");
|
URL resourceUrl = classLoader.getResource("flowableExcelParserExampleData.xlsx");
|
||||||
assert resourceUrl != null;
|
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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,12 +20,12 @@ class FlowableExcelParserTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private FlowableExcelParser flowableExcelParser;
|
private FlowableExcelParser flowableExcelParser;
|
||||||
|
|
||||||
private Stream<Arguments> GetArgumentsFromExcel(String path, List<Integer> colNumberList) {
|
private Stream<Arguments> GetArgumentsFromExcel(String path) {
|
||||||
ArrayList<Arguments> argumentList = new ArrayList<>();
|
ArrayList<Arguments> argumentList = new ArrayList<>();
|
||||||
ClassLoader classLoader = FlowableExcelParserTest.class.getClassLoader();
|
ClassLoader classLoader = FlowableExcelParserTest.class.getClassLoader();
|
||||||
URL resourceUrl = classLoader.getResource(path);
|
URL resourceUrl = classLoader.getResource(path);
|
||||||
Assertions.assertThat(resourceUrl).isNotNull();
|
Assertions.assertThat(resourceUrl).isNotNull();
|
||||||
ArrayList<LinkedHashMap<String, Object>> rowList = flowableExcelParser.parseExcel(resourceUrl.getPath(), colNumberList);
|
ArrayList<LinkedHashMap<String, Object>> rowList = flowableExcelParser.parseExcel(resourceUrl.getPath());
|
||||||
Assertions.assertThat(rowList).isNotNull();
|
Assertions.assertThat(rowList).isNotNull();
|
||||||
for (LinkedHashMap<String, Object> row : rowList) {
|
for (LinkedHashMap<String, Object> row : rowList) {
|
||||||
LinkedHashMap<String, Object> inputMap = new LinkedHashMap<>();
|
LinkedHashMap<String, Object> inputMap = new LinkedHashMap<>();
|
||||||
@@ -46,7 +46,7 @@ class FlowableExcelParserTest {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Stream<Arguments> booleanExcelParserTestDataProvider() {
|
private Stream<Arguments> booleanExcelParserTestDataProvider() {
|
||||||
return GetArgumentsFromExcel("flowableExcelParserTestData1.xlsx", List.of(0,1,2,4,5));
|
return GetArgumentsFromExcel("flowableExcelParserTestData1.xlsx");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@@ -67,7 +67,7 @@ class FlowableExcelParserTest {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Stream<Arguments> stringExcelParserTestDataProvider() {
|
private Stream<Arguments> stringExcelParserTestDataProvider() {
|
||||||
return GetArgumentsFromExcel("flowableExcelParserTestData2.xlsx", List.of(0,1,2,4,5,6));
|
return GetArgumentsFromExcel("flowableExcelParserTestData2.xlsx");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@@ -92,7 +92,7 @@ class FlowableExcelParserTest {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Stream<Arguments> numberExcelParserTestDataProvider() {
|
private Stream<Arguments> numberExcelParserTestDataProvider() {
|
||||||
return GetArgumentsFromExcel("flowableExcelParserTestData3.xlsx", List.of(0,1,2,4,5,6));
|
return GetArgumentsFromExcel("flowableExcelParserTestData3.xlsx");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user