Skip to content

Commit

Permalink
Merge 7b9dcaf into 8cb5a0d
Browse files Browse the repository at this point in the history
  • Loading branch information
Developer-Matt committed Aug 17, 2018
2 parents 8cb5a0d + 7b9dcaf commit 7f508cd
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 20 deletions.
10 changes: 8 additions & 2 deletions src/main/java/com/poiji/bind/mapping/HSSFUnmarshaller.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ abstract class HSSFUnmarshaller implements Unmarshaller {
@Override
public <T> void unmarshal(Class<T> type, Consumer<? super T> consumer) {
Workbook workbook = workbook();
Sheet sheet = workbook.getSheetAt(options.sheetIndex());
//Sheet sheet = workbook.getSheetAt(options.sheetIndex());

//work out which sheet must process
//ISSUE #55
int processIndex = PoijiOptions.getSheetIndexToProcess(workbook, options);
Sheet sheet = workbook.getSheetAt(processIndex);

int skip = options.skip();
int maxPhysicalNumberOfRows = sheet.getPhysicalNumberOfRows() + 1 - skip;
Expand Down Expand Up @@ -138,8 +143,9 @@ private boolean skip(final Row currentRow, int skip) {
private boolean isRowEmpty(Row row) {
for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
Cell cell = row.getCell(c, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
if (cell != null && cell.getCellTypeEnum() != CellType.BLANK)
if (cell != null && cell.getCellTypeEnum() != CellType.BLANK) {
return false;
}
}
return true;
}
Expand Down
24 changes: 17 additions & 7 deletions src/main/java/com/poiji/bind/mapping/XSSFUnmarshaller.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.function.Consumer;
import org.apache.poi.ss.usermodel.Workbook;

import static org.apache.poi.xssf.eventusermodel.XSSFReader.SheetIterator;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
* Created by hakan on 22/10/2017
Expand All @@ -39,6 +42,12 @@ abstract class XSSFUnmarshaller implements Unmarshaller {

<T> void unmarshal0(Class<T> type, Consumer<? super T> consumer, OPCPackage open) throws IOException, SAXException, OpenXML4JException {

//ISSUE #55
XSSFWorkbook wb = new XSSFWorkbook(open);
Workbook workbook = new SXSSFWorkbook(wb);
//work out which sheet must process
int processIndex = PoijiOptions.getSheetIndexToProcess(workbook, options);

ReadOnlySharedStringsTable readOnlySharedStringsTable = new ReadOnlySharedStringsTable(open);
XSSFReader xssfReader = new XSSFReader(open);
StylesTable styles = xssfReader.getStylesTable();
Expand All @@ -48,7 +57,8 @@ <T> void unmarshal0(Class<T> type, Consumer<? super T> consumer, OPCPackage open

while (iter.hasNext()) {
try (InputStream stream = iter.next()) {
if (index == options.sheetIndex()) {
//if (index == options.sheetIndex()) {
if (index == processIndex) {
processSheet(styles, readOnlySharedStringsTable, type, stream, consumer);
return;
}
Expand All @@ -59,18 +69,18 @@ <T> void unmarshal0(Class<T> type, Consumer<? super T> consumer, OPCPackage open

@SuppressWarnings("unchecked")
private <T> void processSheet(StylesTable styles,
ReadOnlySharedStringsTable readOnlySharedStringsTable,
Class<T> type,
InputStream sheetInputStream,
Consumer<? super T> consumer) {
ReadOnlySharedStringsTable readOnlySharedStringsTable,
Class<T> type,
InputStream sheetInputStream,
Consumer<? super T> consumer) {

DataFormatter formatter = new DataFormatter();
InputSource sheetSource = new InputSource(sheetInputStream);
try {
XMLReader sheetParser = SAXHelper.newXMLReader();
PoijiHandler poijiHandler = new PoijiHandler(type, options, consumer);
ContentHandler contentHandler =
new XSSFSheetXMLHandler(styles, null, readOnlySharedStringsTable, poijiHandler, formatter, false);
ContentHandler contentHandler
= new XSSFSheetXMLHandler(styles, null, readOnlySharedStringsTable, poijiHandler, formatter, false);
sheetParser.setContentHandler(contentHandler);
sheetParser.parse(sheetSource);
} catch (ParserConfigurationException | SAXException | IOException e) {
Expand Down
119 changes: 109 additions & 10 deletions src/main/java/com/poiji/option/PoijiOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,26 @@

import static com.poiji.util.PoijiConstants.DEFAULT_DATE_PATTERN;
import static com.poiji.util.PoijiConstants.DEFAULT_DATE_TIME_FORMATTER;
import org.apache.poi.ss.usermodel.Workbook;

/**
* Created by hakan on 17/01/2017.
*/
public final class PoijiOptions {

private int skip;
private int sheetIndex;
//ISSUE #55 changed form int to integer, in order to check if null when trying to work out which sheet to process in getSheetIndexToProcess below
private Integer sheetIndex;
private String password;
private String datePattern;
private boolean preferNullOverDefault;
private DateTimeFormatter dateTimeFormatter;
//ISSUE #55
//whether or not to ignore any hidden sheets in the work book
//default to false so not to break existing, and so must be explicitly set to true
private boolean ignoreHiddenSheets;
//if set to true will trim(remove leading and trailing) white spaces from cell value
private boolean trimCellValue;

private PoijiOptions() {
super();
Expand All @@ -41,7 +49,7 @@ private PoijiOptions setPreferNullOverDefault(boolean preferNullOverDefault) {
return this;
}

private PoijiOptions setSheetIndex(int sheetIndex) {
private PoijiOptions setSheetIndex(Integer sheetIndex) {
this.sheetIndex = sheetIndex;
return this;
}
Expand All @@ -55,7 +63,7 @@ private PoijiOptions setPassword(String password) {
return this;
}

public int sheetIndex() {
public Integer sheetIndex() {
return sheetIndex;
}

Expand All @@ -80,14 +88,38 @@ public int skip() {
return skip;
}

//ISSUE #55
public boolean ignoreHiddenSheets() {
return ignoreHiddenSheets;
}

//ISSUE #55
public PoijiOptions setIgnoreHiddenSheets(boolean ignoreHiddenSheets) {
this.ignoreHiddenSheets = ignoreHiddenSheets;
return this;
}

//ISSUE #55 : additional
public boolean trimCellValue() {
return trimCellValue;
}

public PoijiOptions setTrimCellValue(boolean trimCellValue) {
this.trimCellValue = trimCellValue;
return this;
}

public static class PoijiOptionsBuilder {

private int skip = 1;
private int sheetIndex;
private Integer sheetIndex;
private String password;
private boolean preferNullOverDefault = false;
private String datePattern = DEFAULT_DATE_PATTERN;
private DateTimeFormatter dateTimeFormatter = DEFAULT_DATE_TIME_FORMATTER;
//ISSUE #55
private boolean ignoreHiddenSheets = false;
private boolean trimCellValue = false;

private PoijiOptionsBuilder() {
}
Expand All @@ -103,15 +135,18 @@ public PoijiOptions build() {
.setPreferNullOverDefault(preferNullOverDefault)
.setDatePattern(datePattern)
.setDateTimeFormatter(dateTimeFormatter)
.setSheetIndex(sheetIndex);
.setSheetIndex(sheetIndex)
.setIgnoreHiddenSheets(ignoreHiddenSheets)
.setTrimCellValue(trimCellValue);
}

public static PoijiOptionsBuilder settings() {
return new PoijiOptionsBuilder();
}

/**
* set a date time formatter, default date time formatter is "dd/M/yyyy" for java.time.LocalDate
* set a date time formatter, default date time formatter is "dd/M/yyyy"
* for java.time.LocalDate
*
* @param dateTimeFormatter date time formatter
* @return this
Expand All @@ -122,7 +157,8 @@ public PoijiOptionsBuilder dateTimeFormatter(DateTimeFormatter dateTimeFormatter
}

/**
* set date pattern, default date format is "dd/M/yyyy" for java.util.Date
* set date pattern, default date format is "dd/M/yyyy" for
* java.util.Date
*
* @param datePattern date time formatter
* @return this
Expand All @@ -133,7 +169,8 @@ public PoijiOptionsBuilder datePattern(String datePattern) {
}

/**
* set whether or not to use null instead of default values for Integer, Double, Float, Long, String and java.util.Date types.
* set whether or not to use null instead of default values for Integer,
* Double, Float, Long, String and java.util.Date types.
*
* @param preferNullOverDefault boolean
* @return this
Expand All @@ -160,7 +197,7 @@ public PoijiOptionsBuilder skip(int skip) {
* @param sheetIndex number
* @return this
*/
public PoijiOptionsBuilder sheetIndex(int sheetIndex) {
public PoijiOptionsBuilder sheetIndex(Integer sheetIndex) {
this.sheetIndex = sheetIndex;
return this;
}
Expand All @@ -175,7 +212,6 @@ public static PoijiOptionsBuilder settings(int skip) {
return new PoijiOptionsBuilder(skip);
}


/**
* set password for encrypted excel file, Default is null
*
Expand All @@ -187,5 +223,68 @@ public PoijiOptionsBuilder password(String password) {
return this;
}

/**
* Ignore hidden sheets
*
* @param ignoreHiddenSheets whether or not to ignore any hidden sheets
* in the work book.
* @return this
*/
public PoijiOptionsBuilder ignoreHiddenSheets(boolean ignoreHiddenSheets) {
this.ignoreHiddenSheets = ignoreHiddenSheets;
return this;
}

/**
* Trim cell value
*
* @param trimCellValue trim the cell value before processing work book.
* @return this
*/
public PoijiOptionsBuilder trimCellValue(boolean trimCellValue) {
this.trimCellValue = trimCellValue;
return this;
}

}

//ISSUE #55
//loop througth all sheets and check if visiable
//if visiable return sheet index, else null so can fall back to default
private static Integer findFirstVisiableSheetIndex(Workbook workbook) {
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
if (!workbook.isSheetHidden(i) && !workbook.isSheetVeryHidden(i)) {
return i;
}
}
return null;
}

//ISSUE #55
//from the given work book, using the oprions set work out which sheet to process
//if given an sheet number, process that
//else if no index set, and ignore hidden is true, find the first visiable
//else get the default first sheet
public static final int getSheetIndexToProcess(Workbook workbook, PoijiOptions options) {
int index;
//if specify whick exact sheet index to get, using the options, then get that sheet regardless
if (options.sheetIndex() != null && options.sheetIndex() > -1) {
index = options.sheetIndex();
} else {
//else if set to only process visiable sheets, get the first visiable one
if (options.ignoreHiddenSheets()) {
Integer visiableSheetIndex = findFirstVisiableSheetIndex(workbook);
if (visiableSheetIndex != null) {
index = visiableSheetIndex;
} else {
//else get default, first (0 based) sheet
index = 0;
}
} else {
//else get default, first (0 based) sheet
index = 0;
}
}
return index;
}
}
7 changes: 7 additions & 0 deletions src/main/java/com/poiji/util/Casting.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ private Object enumValue(String value, Class type) {

public Object castValue(Class<?> fieldType, String value, PoijiOptions options) {
Object o;

//ISSUE #55 : additioanl functionality
//if set in options, will trim any leading and trailing white spaces.
if (options.trimCellValue()) {
value = value.trim();
}

if (fieldType.getName().equals("int")) {
o = primitiveIntegerValue(value);

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

import com.poiji.bind.Poiji;
import com.poiji.deserialize.model.byid.Person;
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 com.poiji.util.Data.unmarshallingPersons;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;

@RunWith(Parameterized.class)
public class DeserializersHiddenSheetTest {

private final String path;
private final List<Person> expectedPersonList;
private final Class<?> expectedException;

public DeserializersHiddenSheetTest(String path, List<Person> expectedPersonList, Class<?> expectedException) {
this.path = path;
this.expectedPersonList = expectedPersonList;
this.expectedException = expectedException;
}

@Parameterized.Parameters(name = "{index}: ({0})={1}")
public static Iterable<Object[]> queries() {
return Arrays.asList(new Object[][]{
{"src/test/resources/hidden.xlsx", unmarshallingPersons(), null},
{"src/test/resources/hidden.xls", unmarshallingPersons(), null}
});
}

@Test
public void testIgnoreHiddenSheets() {
try {
PoijiOptions poijiOptions = PoijiOptions.PoijiOptionsBuilder.settings().ignoreHiddenSheets(true).build();

List<Person> people = Poiji.fromExcel(new File(path), Person.class, poijiOptions);
assertEquals(expectedPersonList.get(0).getRow(), people.get(0).getRow());
assertEquals(expectedPersonList.get(1).getRow(), people.get(1).getRow());
assertEquals(expectedPersonList.get(2).getRow(), people.get(2).getRow());
assertEquals(expectedPersonList.get(3).getRow(), people.get(3).getRow());
assertEquals(expectedPersonList.get(4).getRow(), people.get(4).getRow());
} catch (Exception e) {
if (expectedException == null) {
fail(e.getMessage());
} else {
assertThat(e, instanceOf(expectedException));
}
}
}

@Test
public void testProcessHiddenSheets() {
PoijiOptions poijiOptions = PoijiOptions.PoijiOptionsBuilder.settings().ignoreHiddenSheets(false).build();
List<Person> people = Poiji.fromExcel(new File(path), Person.class, poijiOptions);
assertEquals(people.size(), 0);
}

}
6 changes: 6 additions & 0 deletions src/test/java/com/poiji/deserialize/model/byid/Person.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,10 @@ public String getEmail() {
public void setEmail(String email) {
this.email = email;
}

@Override
public String toString() {
return "Person{" + "row=" + row + ", name=" + name + ", address=" + address + ", mobile=" + mobile + ", email=" + email + '}';
}

}
Loading

0 comments on commit 7f508cd

Please sign in to comment.