Skip to content

Commit

Permalink
feat(core): support regular expression for column name
Browse files Browse the repository at this point in the history
Feature request

Refs: 304
  • Loading branch information
aerfus committed Feb 18, 2024
1 parent d659fbb commit 6578e53
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/main/java/com/poiji/annotation/ExcelCellName.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

/**
* Specifies the column name where the corresponding value is mapped from the
* excel data
* Excel data
*
* @return column name
*/
Expand All @@ -35,4 +35,12 @@
* @return mandatory cell signal. Default is false.
*/
boolean mandatoryCell() default false;

/**
* Specifies the column regular expression where the corresponding value is mapped from the
* Excel data
*
* @return column regular expression
*/
String expression() default "";
}
11 changes: 11 additions & 0 deletions src/main/java/com/poiji/bind/mapping/HSSFUnmarshaller.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

Expand Down Expand Up @@ -279,6 +280,16 @@ private Integer findTitleColumn(ExcelCellName excelCellName) {
return titleToIndex.get(titleName);
}

if (!StringUtil.isBlank(excelCellName.expression())) {
final String titleName = formatting.transform(options, excelCellName.expression());
Pattern pattern = Pattern.compile(titleName);
return titleToIndex.entrySet().stream()
.filter(entry -> pattern.matcher(entry.getKey()).matches())
.findFirst()
.map(Map.Entry::getValue)
.orElse(null);
}

return null;
}

Expand Down
11 changes: 11 additions & 0 deletions src/main/java/com/poiji/bind/mapping/PoijiHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import static java.lang.String.valueOf;
Expand Down Expand Up @@ -190,6 +191,16 @@ private Integer findTitleColumn(ExcelCellName excelCellName) {
return titleToIndex.get(titleName);
}

if (!StringUtil.isBlank(excelCellName.expression())) {
final String titleName = formatting.transform(options, excelCellName.expression());
Pattern pattern = Pattern.compile(titleName);
return titleToIndex.entrySet().stream()
.filter(entry -> pattern.matcher(entry.getKey()).matches())
.findFirst()
.map(Map.Entry::getValue)
.orElse(null);
}

return null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.poiji.deserialize;

import com.poiji.bind.Poiji;
import com.poiji.deserialize.model.InventoryData;
import com.poiji.option.PoijiOptions;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.io.File;
import java.util.List;

import static com.poiji.option.PoijiOptions.PoijiOptionsBuilder.settings;
import static com.poiji.util.Data.unmarshallingInventoryData;
import static org.junit.Assert.assertEquals;

/**
* Test for Reading Excel columns with Regular expression (Regex)
*/
@RunWith(Parameterized.class)
public class ReadExcelWithRegexInColumnNameTest {
private final String path;
private final List<InventoryData> expectedData;
private final PoijiOptions options;

public ReadExcelWithRegexInColumnNameTest(String path, List<InventoryData> expectedData, PoijiOptions options) {
this.path = path;
this.expectedData = expectedData;
this.options = options;
}

@Parameterized.Parameters(name = "{index}: ({0})={1}")
public static Iterable<Object[]> queries() {
return List.of(new Object[][]{
{
"src/test/resources/regex/inventory.xlsx",
unmarshallingInventoryData(),
settings().sheetName("Books").build()
},
{
"src/test/resources/regex/inventory.xlsx",
unmarshallingInventoryData(),
settings().sheetName("Songs").build()
},
{
"src/test/resources/regex/inventory.xls",
unmarshallingInventoryData(),
settings().sheetName("Books").build()
},
{
"src/test/resources/regex/inventory.xls",
unmarshallingInventoryData(),
settings().sheetName("Songs").build()
},
});
}

@Test
public void shouldReadInventoryData() {
List<InventoryData> actualData = Poiji.fromExcel(new File(path), InventoryData.class, options);

assertEquals(expectedData, actualData);
}

}
45 changes: 45 additions & 0 deletions src/test/java/com/poiji/deserialize/model/InventoryData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.poiji.deserialize.model;

import com.poiji.annotation.ExcelCellName;

import java.util.Objects;

/**
* An InventoryData POJO.
*/
public class InventoryData {
@ExcelCellName(value = "Id")
private Integer id;

@ExcelCellName(value = "", expression = "Author|Composer")
private String author;

public void setId(Integer id) {
this.id = id;
}

public void setAuthor(String author) {
this.author = author;
}

@Override
public String toString() {
return "InventoryData{" +
"id='" + id + '\'' +
", author='" + author + '\'' +
'}';
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
InventoryData that = (InventoryData) o;
return Objects.equals(id, that.id) && Objects.equals(author, that.author);
}

@Override
public int hashCode() {
return Objects.hash(id, author);
}
}
14 changes: 14 additions & 0 deletions src/test/java/com/poiji/util/Data.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.poiji.util;

import com.poiji.deserialize.model.InventoryData;
import com.poiji.deserialize.model.Student;
import com.poiji.deserialize.model.byid.Employee;
import com.poiji.deserialize.model.byid.Person;
Expand Down Expand Up @@ -126,4 +127,17 @@ public static List<Student> unmarshallingStudents() {
students.add(student);
return students;
}


public static List<InventoryData> unmarshallingInventoryData() {
InventoryData record1 = new InventoryData();
record1.setId(1);
record1.setAuthor("Peter");

InventoryData record2 = new InventoryData();
record2.setId(2);
record2.setAuthor("Maria");

return List.of(record1, record2);
}
}
Binary file added src/test/resources/regex/inventory.xls
Binary file not shown.
Binary file added src/test/resources/regex/inventory.xlsx
Binary file not shown.

0 comments on commit 6578e53

Please sign in to comment.