Skip to content

Commit

Permalink
Merge fbcfdd5 into d69fc6f
Browse files Browse the repository at this point in the history
  • Loading branch information
thuydx55 committed Nov 6, 2020
2 parents d69fc6f + fbcfdd5 commit 1e51b8b
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 16 deletions.
18 changes: 11 additions & 7 deletions src/main/java/com/poiji/bind/mapping/HSSFUnmarshaller.java
Expand Up @@ -128,15 +128,19 @@ private Sheet getSheetToProcess(Workbook workbook, PoijiOptions options, String
private void loadColumnTitles(Sheet sheet, int maxPhysicalNumberOfRows) {
if (maxPhysicalNumberOfRows > 0) {
int row = options.getHeaderStart();
if (row == -1) {
int headerCount = options.getHeaderCount();
if (headerCount == 0) {
return;
}
Row firstRow = sheet.getRow(row);
for (Cell cell : firstRow) {
final int columnIndex = cell.getColumnIndex();
final String titleName = formatting.transform(options, cell.getStringCellValue());
indexToTitle.put(columnIndex, getTitleNameForMap(titleName, columnIndex));
titleToIndex.put(titleName, columnIndex);

for (short i = 0; i < headerCount; i++) {
Row firstRow = sheet.getRow(row + i);
for (Cell cell : firstRow) {
final int columnIndex = cell.getColumnIndex();
final String titleName = formatting.transform(options, cell.getStringCellValue());
indexToTitle.put(columnIndex, getTitleNameForMap(titleName, columnIndex));
titleToIndex.put(titleName, columnIndex);
}
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/com/poiji/bind/mapping/PoijiHandler.java
Expand Up @@ -201,9 +201,10 @@ public void endRow(int rowNum) {
public void cell(String cellReference, String formattedValue, XSSFComment comment) {
final CellAddress cellAddress = new CellAddress(cellReference);
int row = cellAddress.getRow();
int header = options.getHeaderStart();
int headerStart = options.getHeaderStart();
int headerCount = options.getHeaderCount();
int column = cellAddress.getColumn();
if (row == header) {
if (row >= headerStart && row < headerStart + headerCount) {
String transformedValue = formatting.transform(options, formattedValue);
titleToIndex.put(transformedValue, column);
indexToTitle.put(column, getTitleNameForMap(transformedValue, column));
Expand Down
37 changes: 32 additions & 5 deletions src/main/java/com/poiji/option/PoijiOptions.java
Expand Up @@ -36,6 +36,7 @@ public final class PoijiOptions {
private DateTimeFormatter dateTimeFormatter;
private Casting casting;
private int headerStart;
private int headerCount;
private String sheetName;
private boolean caseInsensitive;
private boolean ignoreWhitespaces;
Expand Down Expand Up @@ -203,11 +204,20 @@ public int getHeaderStart() {
return headerStart;
}

public int getHeaderCount() {
return headerCount;
}

private PoijiOptions setHeaderStart(int headerStart) {
this.headerStart = headerStart;
return this;
}

private PoijiOptions setHeaderCount(int headerCount) {
this.headerCount = headerCount;
return this;
}

private PoijiOptions setSheetName(String sheetName) {
this.sheetName = sheetName;
return this;
Expand Down Expand Up @@ -289,6 +299,7 @@ public static class PoijiOptionsBuilder {
private PoijiLogCellFormat cellFormat;
private PoijiNumberFormat numberFormat;
private int headerStart = 0;
private int headerCount = 1;
private int skip = 1;
private int limit = 0;
private String sheetName;
Expand Down Expand Up @@ -372,7 +383,7 @@ public PoijiOptionsBuilder preferNullOverDefault(boolean preferNullOverDefault)

public PoijiOptions build() {
return new PoijiOptions()
.setSkip(skip + headerStart)
.setSkip(skip + headerStart + headerCount - 1)
.setPassword(password)
.setPreferNullOverDefault(preferNullOverDefault)
.setDatePattern(datePattern)
Expand All @@ -386,6 +397,7 @@ public PoijiOptions build() {
.setDateTimeRegex(dateTimeRegex)
.setDateLenient(dateLenient)
.setHeaderStart(headerStart)
.setHeaderCount(headerCount)
.setCasting(casting)
.setLimit(limit)
.setPoijiLogCellFormat(cellFormat)
Expand Down Expand Up @@ -540,20 +552,35 @@ public PoijiOptionsBuilder withCasting(Casting casting) {
* This is to set the row which the unmarshall will
* use to start reading header titles, incase the
* header is not in row 0.
* <br/>
* Set -1 to indicate that no header in the excel file.
*
* @param headerStart an index number of the excel header to start reading header
* @return this
*/
public PoijiOptionsBuilder headerStart(int headerStart) {
if (headerStart < -1) {
throw new PoijiException("Header index must be greater than -1");
if (headerStart < 0) {
throw new PoijiException("Header index must be greater than 0");
}
this.headerStart = headerStart;
return this;
}

/**
* This is to set the number of row contains headers
* <br/>
* Set 0 to indicate that no header in the excel file.
* Default - 1.
*
* @param headerCount an index number of the excel header to start reading header
* @return this
*/
public PoijiOptionsBuilder headerCount(int headerCount) {
if (headerCount < 0) {
throw new PoijiException("Number of header row must be greater than 0");
}
this.headerCount = headerCount;
return this;
}

/**
* Permits case insensitive column names mapping for annotation {@link ExcelCellName}.
* Default - false.
Expand Down
@@ -0,0 +1,73 @@
package com.poiji.deserialize;

import com.poiji.bind.Poiji;
import com.poiji.deserialize.model.byid.PersonATest;
import com.poiji.deserialize.model.byid.PersonBTest;
import com.poiji.deserialize.model.byid.PersonCreditInfo;
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.Arrays;
import java.util.List;

import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.fail;

@RunWith(Parameterized.class)
public class MultiHeadersExcelSheetTest {

private String path;

public MultiHeadersExcelSheetTest(String path) {
this.path = path;
}

@Parameterized.Parameters
public static Iterable<Object[]> queries() {
return Arrays.asList(new Object[][]{
{"src/test/resources/test-multi-headers.xlsx"},
{"src/test/resources/test-multi-headers.xls"}
});
}

@Test
public void shouldRetrieveDataWith2LevelHeaders() {
try {
PoijiOptions options = PoijiOptions.PoijiOptionsBuilder.settings()
.headerCount(2)
.trimCellValue(true)
.build();
List<PersonCreditInfo> actualPersonalCredits =
Poiji.fromExcel(new File(path), PersonCreditInfo.class, options);

assertThat(actualPersonalCredits, notNullValue());
assertThat(actualPersonalCredits.size(), not(0));
assertThat(actualPersonalCredits.size(), is(3));

PersonCreditInfo personCreditInfo1 = actualPersonalCredits.get(0);
PersonCreditInfo personCreditInfo2 = actualPersonalCredits.get(1);

PersonCreditInfo.PersonInfo expectedPerson1 = personCreditInfo1.getPersonInfo();
PersonCreditInfo.CardInfo expectedCard1 = personCreditInfo1.getCardInfo();
PersonCreditInfo.PersonInfo expectedPerson2 = personCreditInfo2.getPersonInfo();
PersonCreditInfo.CardInfo expectedCard2 = personCreditInfo2.getCardInfo();

assertThat(expectedPerson1.getAge(), is(21));
assertThat(expectedPerson2.getCity(), is("Greenbelt"));
assertThat(expectedPerson1.getName(), is("John Doe"));
assertThat(expectedPerson2.getState(), is("Maryland"));
assertThat(expectedPerson1.getZipCode(), is("22349"));

assertThat(expectedCard1.getType(), is("VISA"));
assertThat(expectedCard2.getLast4Digits(), is("2345"));
assertThat(expectedCard1.getExpirationDate(), is("Jan-21"));
} catch (Exception e) {
fail(e.getMessage());
}
}

}
Expand Up @@ -38,7 +38,8 @@ public static Iterable<Object[]> excel() {
@Test
public void shouldRetrieveDataWithNoHeaderLimit1Row() {
PoijiOptions options = PoijiOptions.PoijiOptionsBuilder.settings()
.headerStart(-1)
.headerStart(0)
.headerCount(0)
.limit(1)
.trimCellValue(true)
.build();
Expand All @@ -56,7 +57,8 @@ public void shouldRetrieveDataWithNoHeaderLimit1Row() {
@Test
public void shouldRetrieveDataWithNoHeaderLimit1RowAndSkip1Row() {
PoijiOptions options = PoijiOptions.PoijiOptionsBuilder.settings()
.headerStart(-1)
.headerStart(0)
.headerCount(0)
.skip(1)
.limit(1)
.trimCellValue(true)
Expand Down
@@ -0,0 +1,82 @@
package com.poiji.deserialize.model.byid;

import com.poiji.annotation.ExcelCellName;
import com.poiji.annotation.ExcelCellRange;

public class PersonCreditInfo {

@ExcelCellName("No.")
private Integer no;

@ExcelCellRange
private PersonInfo personInfo;

@ExcelCellRange
private CardInfo cardInfo;

public Integer getNo() {
return no;
}

public PersonInfo getPersonInfo() {
return personInfo;
}

public CardInfo getCardInfo() {
return cardInfo;
}

public static class PersonInfo {
@ExcelCellName("Name")
private String name;
@ExcelCellName("Age")
private Integer age;
@ExcelCellName("City")
private String city;
@ExcelCellName("State")
private String state;
@ExcelCellName("Zip Code")
private String zipCode;

public String getName() {
return name;
}

public Integer getAge() {
return age;
}

public String getCity() {
return city;
}

public String getState() {
return state;
}

public String getZipCode() {
return zipCode;
}
}

public static class CardInfo {
@ExcelCellName("Card Type")
private String type;
@ExcelCellName("Last 4 Digits")
private String last4Digits;
@ExcelCellName("Expiration Date")
private String expirationDate;

public String getType() {
return type;
}

public String getLast4Digits() {
return last4Digits;
}

public String getExpirationDate() {
return expirationDate;
}
}
}
Binary file added src/test/resources/test-multi-headers.xls
Binary file not shown.
Binary file added src/test/resources/test-multi-headers.xlsx
Binary file not shown.

0 comments on commit 1e51b8b

Please sign in to comment.