Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

For issue#35 - Read sheet by name #55

Open
wants to merge 23 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
92a2ea6
Enhanced to read and write formatted dates and formulas.
Harsha0211 Oct 2, 2023
9327ba4
Issue-27 fix
Harsha0211 Oct 3, 2023
bfdb650
minor variable name change
Harsha0211 Oct 3, 2023
1a44805
Enhanced to read and write formatted dates and formulas-modified acc.…
Harsha0211 Oct 3, 2023
41ff52e
minor code refactor
Harsha0211 Oct 4, 2023
00efbc6
executed DateTest.java->sample-files changed
Harsha0211 Oct 4, 2023
78995e4
Enhanced to write new sheet to existing file without clearing prev. s…
Harsha0211 Oct 6, 2023
8944d87
Revert "Enhanced to write new sheet to existing file without clearing…
Harsha0211 Oct 6, 2023
ee9b2bf
[TestCase Update] updated test cases with Date format checks
Harsha0211 Oct 10, 2023
114501c
[SheetColumn] removed 'isFormated' field from sheet column
Harsha0211 Oct 10, 2023
1d48dce
[DateFormat] added support for localDate and Date
Harsha0211 Oct 10, 2023
6cd9cbb
[RMVD-Formula part] Removed all the formula related code
Harsha0211 Oct 10, 2023
b45ad03
[Final keyword] Added final keyword at necessary lines
Harsha0211 Oct 10, 2023
fdfb8a5
[LocalDate read] Modified code to support LocalDate
Harsha0211 Oct 11, 2023
0819f0b
[Test Cases] Added and modified files for Dates TestCases
Harsha0211 Oct 11, 2023
6037107
[Finla keyword]Added final keyword at necessary lines
Harsha0211 Oct 11, 2023
fba7611
[Unused imports] Removed unused imports
Harsha0211 Oct 11, 2023
851936e
[Revert] reverted sheet and rowListeners file from develop branch
Harsha0211 Oct 11, 2023
2e44848
[Code refactor] Replaced SheetColumn,SSReader,Beans,XlsxReader files …
Harsha0211 Oct 11, 2023
5f44494
[Code Refactor] Added minor changes to replaced files in prev commit
Harsha0211 Oct 11, 2023
d59ac27
[Final] Added final keyword
Harsha0211 Oct 11, 2023
e2cb59c
[Primary code commit] Added to read sheet by sheet name
Harsha0211 Oct 12, 2023
f451011
[test cases] Added Test cases to read sheet by name
Harsha0211 Oct 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
*/
String value() default "";

String format() default "dd/MM/yyyy";

/**
* Setting this to <code>false</code> will enable the null check on the Column values, to ensure
* non-null values for the field.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@

import io.github.millij.poi.SpreadsheetReadException;
import io.github.millij.poi.ss.handler.RowListener;
import io.github.millij.poi.ss.model.annotations.SheetColumn;
import io.github.millij.poi.util.Beans;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -96,6 +102,17 @@ public void row(int rowNum, T rowObj) {
return sheetBeans;
}

@Override
public <T> List<T> read(Class<T> beanClz, File file, String sheetName) throws SpreadsheetReadException {
// Sanity Checks
if (Objects.isNull(sheetName)) {
String errMsg = "Failed to read the file with SheetName : NULL";
throw new SpreadsheetReadException(errMsg);
}
final int sheetNo = this.getSheetNo(beanClz, file, sheetName);
return this.read(beanClz, file, sheetNo);
}


@Override
public <T> List<T> read(Class<T> beanClz, File file, int sheetNo) throws SpreadsheetReadException {
Expand Down Expand Up @@ -130,6 +147,44 @@ public void row(int rowNum, T rowObj) {

return sheetBeans;
}

public static String getReturnType(Class<?> beanClz, String header) {


String headerType = null;
// Fields
Field[] fields = beanClz.getDeclaredFields();
for (Field f : fields) {
if (!f.isAnnotationPresent(SheetColumn.class)) {
continue;
}
String fieldName = f.getName();
SheetColumn ec = f.getDeclaredAnnotation(SheetColumn.class);
if (header.equals(fieldName) || header.equals(ec.value())) {
headerType = f.getType().getName();
}
continue;
}

// Methods
Method[] methods = beanClz.getDeclaredMethods();
for (Method m : methods) {
if (!m.isAnnotationPresent(SheetColumn.class)) {
continue;
}
String fieldName = Beans.getFieldName(m);
SheetColumn ec = m.getDeclaredAnnotation(SheetColumn.class);
if (header.equals(fieldName) || header.equals(ec.value())) {
headerType = m.getReturnType().getName();
}
continue;
}
if (StringUtils.isBlank(headerType)) {
LOGGER.info("Failed to get the return type of the given Header '{}'", header);
}
return headerType;

}


}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
public interface SpreadsheetReader {


public static final String DEFAULT_DATE_FORMAT = "dd/MM/yyyy";
// Read with Custom RowListener

/**
Expand Down Expand Up @@ -169,6 +170,34 @@ <T> void read(Class<T> beanClz, InputStream is, int sheetNo, RowListener<T> list
*/
<T> List<T> read(Class<T> beanClz, InputStream is, int sheetNo) throws SpreadsheetReadException;

/**
*
* @param <T> The Parameterized bean Class.
* @param beanClz beanClz The Class type to deserialize the rows data
* @param file file {@link File} object of the spreadsheet file
* @param sheetName name of the Sheet to be read
*
* @return a {@link List} of objects of the parameterized type
*
* @throws SpreadsheetReadException SpreadsheetReadException an exception is thrown in cases where the file data is
* not readable or row data to bean mapping failed.
*/
<T> List<T> read(Class<T> beanClz, File file, String sheetName) throws SpreadsheetReadException;

/**
*
* @param <T> The Parameterized bean Class.
* @param beanClz beanClz The Class type to deserialize the rows data
* @param file file {@link File} object of the spreadsheet file
* @param sheetName name of the Sheet to be read
*
* @return a Integer value stating the Sheet Number
*
* @throws SpreadsheetReadException SpreadsheetReadException an exception is thrown in cases where the file data is
* not readable or row data to bean mapping failed.
*/
<T> Integer getSheetNo(Class<T> beanClz, File file, String sheetName) throws SpreadsheetReadException;



}
84 changes: 71 additions & 13 deletions src/main/java/io/github/millij/poi/ss/reader/XlsReader.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
package io.github.millij.poi.ss.reader;

import static io.github.millij.poi.util.Beans.isInstantiableType;

import io.github.millij.poi.SpreadsheetReadException;
import io.github.millij.poi.ss.handler.RowListener;
import io.github.millij.poi.ss.writer.SpreadsheetWriter;
import io.github.millij.poi.util.Spreadsheet;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
Expand Down Expand Up @@ -38,6 +50,29 @@ public XlsReader() {
}


public <T> Integer getSheetNo(Class<T> beanClz, File file, String sheetName) throws SpreadsheetReadException {
// Sanity Checks
if (!isInstantiableType(beanClz)) {
throw new IllegalArgumentException("XlsReader :: Invalid bean type passed !");
}

try {
FileInputStream fis = new FileInputStream(file);
final HSSFWorkbook wb = new HSSFWorkbook(fis);
final int sheetNo = wb.getSheetIndex(sheetName);
if (sheetNo == -1) {
LOGGER.error("No sheet is available with name :" + sheetName);
return null;
}
return sheetNo;
} catch (Exception ex) {
String errMsg = String.format("Error getting HSSFSheet number, to %s : %s", beanClz, ex.getMessage());
LOGGER.error(errMsg, ex);
throw new SpreadsheetReadException(errMsg, ex);
}
}


// WorkbookReader Impl
// ------------------------------------------------------------------------

Expand Down Expand Up @@ -69,7 +104,7 @@ public <T> void read(Class<T> beanClz, InputStream is, RowListener<T> listener)
LOGGER.error(errMsg, ex);
throw new SpreadsheetReadException(errMsg, ex);
}

}

@Override
Expand All @@ -81,7 +116,7 @@ public <T> void read(Class<T> beanClz, InputStream is, int sheetNo, RowListener<
}

try {
HSSFWorkbook wb = new HSSFWorkbook(is);
final HSSFWorkbook wb = new HSSFWorkbook(is);
final HSSFSheet sheet = wb.getSheetAt(sheetNo);

// Process Sheet
Expand All @@ -99,14 +134,14 @@ public <T> void read(Class<T> beanClz, InputStream is, int sheetNo, RowListener<


// Sheet Process

protected <T> void processSheet(Class<T> beanClz, HSSFSheet sheet, int headerRowNo, RowListener<T> eventHandler) {
// Header column - name mapping
HSSFRow headerRow = sheet.getRow(headerRowNo);
Map<Integer, String> headerMap = this.extractCellHeaderMap(headerRow);
final HSSFRow headerRow = sheet.getRow(headerRowNo);
final Map<Integer, String> headerMap = this.extractCellHeaderMap(headerRow);

// Bean Properties - column name mapping
Map<String, String> cellPropMapping = Spreadsheet.getColumnToPropertyMap(beanClz);
final Map<String, String> cellPropMapping = Spreadsheet.getColumnToPropertyMap(beanClz);

Iterator<Row> rows = sheet.rowIterator();
while (rows.hasNext()) {
Expand All @@ -117,7 +152,7 @@ protected <T> void processSheet(Class<T> beanClz, HSSFSheet sheet, int headerRow
continue; // Skip Header row
}

Map<String, Object> rowDataMap = this.extractRowDataAsMap(row, headerMap);
final Map<String, Object> rowDataMap = this.extractRowDataAsMap(beanClz, row, headerMap);
if (rowDataMap == null || rowDataMap.isEmpty()) {
continue;
}
Expand All @@ -144,7 +179,7 @@ private Map<Integer, String> extractCellHeaderMap(HSSFRow headerRow) {
while (cells.hasNext()) {
HSSFCell cell = (HSSFCell) cells.next();

int cellCol = cell.getColumnIndex();
final int cellCol = cell.getColumnIndex();

// Process cell value
switch (cell.getCellTypeEnum()) {
Expand All @@ -169,7 +204,8 @@ private Map<Integer, String> extractCellHeaderMap(HSSFRow headerRow) {
return cellHeaderMap;
}

private Map<String, Object> extractRowDataAsMap(HSSFRow row, Map<Integer, String> columnHeaderMap) {
private <T> Map<String, Object> extractRowDataAsMap(Class<T> beanClz, HSSFRow row,
Map<Integer, String> columnHeaderMap) {
// Sanity checks
if (row == null) {
return new HashMap<String, Object>();
Expand All @@ -181,15 +217,38 @@ private Map<String, Object> extractRowDataAsMap(HSSFRow row, Map<Integer, String
while (cells.hasNext()) {
HSSFCell cell = (HSSFCell) cells.next();

int cellCol = cell.getColumnIndex();
String cellColName = columnHeaderMap.get(cellCol);
final int cellCol = cell.getColumnIndex();
final String cellColName = columnHeaderMap.get(cellCol);

// Process cell value
switch (cell.getCellTypeEnum()) {
case STRING:
rowDataMap.put(cellColName, cell.getStringCellValue());
break;
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {

// Checking Date or LocalDate
String headerType = AbstractSpreadsheetReader.getReturnType(beanClz, cellColName);
if (headerType.equals(Date.class.getName())) {
final Date date = cell.getDateCellValue();
rowDataMap.put(cellColName, date);
break;
}
if (headerType.equals(LocalDate.class.getName())) {

final Date ldate = cell.getDateCellValue();

// Convert Date to LocalDate
final Instant instant = ldate.toInstant();
final ZoneId zoneId = ZoneId.systemDefault();
final ZonedDateTime zonedDateTime = instant.atZone(zoneId);
final LocalDate localDate = zonedDateTime.toLocalDate();

rowDataMap.put(cellColName, localDate);
break;
}
}
rowDataMap.put(cellColName, cell.getNumericCellValue());
break;
case BOOLEAN:
Expand All @@ -209,5 +268,4 @@ private Map<String, Object> extractRowDataAsMap(HSSFRow row, Map<Integer, String




}
Loading