diff --git a/src/main/java/io/github/millij/poi/ss/model/annotations/SheetColumn.java b/src/main/java/io/github/millij/poi/ss/model/annotations/SheetColumn.java index e014a65..10d8562 100644 --- a/src/main/java/io/github/millij/poi/ss/model/annotations/SheetColumn.java +++ b/src/main/java/io/github/millij/poi/ss/model/annotations/SheetColumn.java @@ -26,6 +26,8 @@ */ String value() default ""; + String format() default "dd/MM/yyyy"; + /** * Setting this to false will enable the null check on the Column values, to ensure * non-null values for the field. diff --git a/src/main/java/io/github/millij/poi/ss/reader/AbstractSpreadsheetReader.java b/src/main/java/io/github/millij/poi/ss/reader/AbstractSpreadsheetReader.java index 7578272..887c895 100644 --- a/src/main/java/io/github/millij/poi/ss/reader/AbstractSpreadsheetReader.java +++ b/src/main/java/io/github/millij/poi/ss/reader/AbstractSpreadsheetReader.java @@ -2,14 +2,19 @@ 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 org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -130,6 +135,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; + + } } diff --git a/src/main/java/io/github/millij/poi/ss/reader/SpreadsheetReader.java b/src/main/java/io/github/millij/poi/ss/reader/SpreadsheetReader.java index 7761f3f..af60120 100644 --- a/src/main/java/io/github/millij/poi/ss/reader/SpreadsheetReader.java +++ b/src/main/java/io/github/millij/poi/ss/reader/SpreadsheetReader.java @@ -16,6 +16,7 @@ public interface SpreadsheetReader { + public static final String DEFAULT_DATE_FORMAT = "dd/MM/yyyy"; // Read with Custom RowListener /** diff --git a/src/main/java/io/github/millij/poi/ss/reader/XlsReader.java b/src/main/java/io/github/millij/poi/ss/reader/XlsReader.java index 5ed2aa8..207344f 100644 --- a/src/main/java/io/github/millij/poi/ss/reader/XlsReader.java +++ b/src/main/java/io/github/millij/poi/ss/reader/XlsReader.java @@ -1,15 +1,25 @@ 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.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; @@ -69,7 +79,7 @@ public void read(Class beanClz, InputStream is, RowListener listener) LOGGER.error(errMsg, ex); throw new SpreadsheetReadException(errMsg, ex); } - + } @Override @@ -81,7 +91,7 @@ public void read(Class 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 @@ -99,14 +109,14 @@ public void read(Class beanClz, InputStream is, int sheetNo, RowListener< // Sheet Process - + protected void processSheet(Class beanClz, HSSFSheet sheet, int headerRowNo, RowListener eventHandler) { // Header column - name mapping - HSSFRow headerRow = sheet.getRow(headerRowNo); - Map headerMap = this.extractCellHeaderMap(headerRow); - + final HSSFRow headerRow = sheet.getRow(headerRowNo); + final Map headerMap = this.extractCellHeaderMap(headerRow); + // Bean Properties - column name mapping - Map cellPropMapping = Spreadsheet.getColumnToPropertyMap(beanClz); + final Map cellPropMapping = Spreadsheet.getColumnToPropertyMap(beanClz); Iterator rows = sheet.rowIterator(); while (rows.hasNext()) { @@ -117,7 +127,7 @@ protected void processSheet(Class beanClz, HSSFSheet sheet, int headerRow continue; // Skip Header row } - Map rowDataMap = this.extractRowDataAsMap(row, headerMap); + final Map rowDataMap = this.extractRowDataAsMap(beanClz, row, headerMap); if (rowDataMap == null || rowDataMap.isEmpty()) { continue; } @@ -144,7 +154,7 @@ private Map 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()) { @@ -169,7 +179,8 @@ private Map extractCellHeaderMap(HSSFRow headerRow) { return cellHeaderMap; } - private Map extractRowDataAsMap(HSSFRow row, Map columnHeaderMap) { + private Map extractRowDataAsMap(Class beanClz, HSSFRow row, + Map columnHeaderMap) { // Sanity checks if (row == null) { return new HashMap(); @@ -181,8 +192,8 @@ private Map extractRowDataAsMap(HSSFRow row, Map extractRowDataAsMap(HSSFRow row, Map extractRowDataAsMap(HSSFRow row, Map void read(Class beanClz, InputStream is, RowListener listener) - throws SpreadsheetReadException { + public void read(Class beanClz, InputStream is, RowListener listener) throws SpreadsheetReadException { // Sanity checks if (!isInstantiableType(beanClz)) { throw new IllegalArgumentException("XlsxReader :: Invalid bean type passed !"); } try { - final OPCPackage opcPkg = OPCPackage.open(is); + final XSSFWorkbook wb = new XSSFWorkbook(is); + final int sheetCount = wb.getNumberOfSheets(); + LOGGER.debug("Total no. of sheets found in HSSFWorkbook : #{}", sheetCount); - // XSSF Reader - XSSFReader xssfReader = new XSSFReader(opcPkg); - - // Content Handler - StylesTable styles = xssfReader.getStylesTable(); - ReadOnlySharedStringsTable ssTable = new ReadOnlySharedStringsTable(opcPkg); - SheetContentsHandler sheetHandler = new RowContentsHandler(beanClz, listener, 0); - - ContentHandler handler = new XSSFSheetXMLHandler(styles, ssTable, sheetHandler, true); + // Iterate over sheets + for (int i = 0; i < sheetCount; i++) { + final XSSFSheet sheet = wb.getSheetAt(i); + LOGGER.debug("Processing HSSFSheet at No. : {}", i); - // XML Reader - XMLReader xmlParser = SAXHelper.newXMLReader(); - xmlParser.setContentHandler(handler); + // Process Sheet + this.processSheet(beanClz, sheet, 0, listener); + } - // Iterate over sheets - XSSFReader.SheetIterator worksheets = (XSSFReader.SheetIterator) xssfReader.getSheetsData(); - for (int i = 0; worksheets.hasNext(); i++) { - InputStream sheetInpStream = worksheets.next(); + // Close workbook + wb.close(); - String sheetName = worksheets.getSheetName(); - // Parse sheet - xmlParser.parse(new InputSource(sheetInpStream)); - sheetInpStream.close(); - } } catch (Exception ex) { String errMsg = String.format("Error reading sheet data, to Bean %s : %s", beanClz, ex.getMessage()); LOGGER.error(errMsg, ex); @@ -87,7 +81,6 @@ public void read(Class beanClz, InputStream is, RowListener listener) } } - @Override public void read(Class beanClz, InputStream is, int sheetNo, RowListener listener) throws SpreadsheetReadException { @@ -97,36 +90,14 @@ public void read(Class beanClz, InputStream is, int sheetNo, RowListener< } try { - final OPCPackage opcPkg = OPCPackage.open(is); - - // XSSF Reader - XSSFReader xssfReader = new XSSFReader(opcPkg); - - // Content Handler - StylesTable styles = xssfReader.getStylesTable(); - ReadOnlySharedStringsTable ssTable = new ReadOnlySharedStringsTable(opcPkg); - SheetContentsHandler sheetHandler = new RowContentsHandler(beanClz, listener, 0); + final XSSFWorkbook wb = new XSSFWorkbook(is); + final XSSFSheet sheet = wb.getSheetAt(sheetNo); - ContentHandler handler = new XSSFSheetXMLHandler(styles, ssTable, sheetHandler, true); + // Process Sheet + this.processSheet(beanClz, sheet, 0, listener); - // XML Reader - XMLReader xmlParser = SAXHelper.newXMLReader(); - xmlParser.setContentHandler(handler); - - // Iterate over sheets - XSSFReader.SheetIterator worksheets = (XSSFReader.SheetIterator) xssfReader.getSheetsData(); - for (int i = 0; worksheets.hasNext(); i++) { - InputStream sheetInpStream = worksheets.next(); - if (i != sheetNo) { - continue; - } - - String sheetName = worksheets.getSheetName(); - - // Parse Sheet - xmlParser.parse(new InputSource(sheetInpStream)); - sheetInpStream.close(); - } + // Close workbook + wb.close(); } catch (Exception ex) { String errMsg = String.format("Error reading sheet %d, to Bean %s : %s", sheetNo, beanClz, ex.getMessage()); @@ -135,6 +106,138 @@ public void read(Class beanClz, InputStream is, int sheetNo, RowListener< } } + // Process Sheet + protected void processSheet(Class beanClz, XSSFSheet sheet, int headerRowNo, RowListener eventHandler) { + // Header column - name mapping + XSSFRow headerRow = sheet.getRow(headerRowNo); + final Map headerMap = this.extractCellHeaderMap(headerRow); + + // Bean Properties - column name mapping + final Map cellPropMapping = Spreadsheet.getColumnToPropertyMap(beanClz); + + Iterator rows = sheet.rowIterator(); + while (rows.hasNext()) { + // Process Row Data + XSSFRow row = (XSSFRow) rows.next(); + final int rowNum = row.getRowNum(); + if (rowNum == 0) { + continue; // Skip Header row + } + + final Map rowDataMap = this.extractRowDataAsMap(beanClz, row, headerMap); + if (rowDataMap == null || rowDataMap.isEmpty()) { + continue; + } + + // Row data as Bean + T rowBean = Spreadsheet.rowAsBean(beanClz, cellPropMapping, rowDataMap); + eventHandler.row(rowNum, rowBean); + } + } + + + // Private Methods + + private Map extractCellHeaderMap(XSSFRow headerRow) { + // Sanity checks + if (headerRow == null) { + return new HashMap(); + } + + final Map cellHeaderMap = new HashMap(); + + Iterator cells = headerRow.cellIterator(); + while (cells.hasNext()) { + XSSFCell cell = (XSSFCell) cells.next(); + + final int cellCol = cell.getColumnIndex(); + + // Process cell value + switch (cell.getCellTypeEnum()) { + case STRING: + cellHeaderMap.put(cellCol, cell.getStringCellValue()); + break; + case NUMERIC: + + cellHeaderMap.put(cellCol, String.valueOf(cell.getNumericCellValue())); + break; + + case BOOLEAN: + cellHeaderMap.put(cellCol, String.valueOf(cell.getBooleanCellValue())); + break; + case FORMULA: + case BLANK: + case ERROR: + break; + default: + break; + } + } + + return cellHeaderMap; + } + + + private Map extractRowDataAsMap(Class beanClz, XSSFRow row, + Map columnHeaderMap) { + // Sanity checks + if (row == null) { + return new HashMap(); + } + + final Map rowDataMap = new HashMap(); + + Iterator cells = row.cellIterator(); + while (cells.hasNext()) { + XSSFCell cell = (XSSFCell) cells.next(); + + 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; + } + } + case BOOLEAN: + rowDataMap.put(cellColName, cell.getBooleanCellValue()); + break; + case FORMULA: + case BLANK: + case ERROR: + break; + default: + break; + } + } + + return rowDataMap; + } } diff --git a/src/main/java/io/github/millij/poi/ss/writer/SpreadsheetWriter.java b/src/main/java/io/github/millij/poi/ss/writer/SpreadsheetWriter.java index ddbdfa4..538e95e 100644 --- a/src/main/java/io/github/millij/poi/ss/writer/SpreadsheetWriter.java +++ b/src/main/java/io/github/millij/poi/ss/writer/SpreadsheetWriter.java @@ -1,21 +1,28 @@ package io.github.millij.poi.ss.writer; -import io.github.millij.poi.ss.model.annotations.Sheet; -import io.github.millij.poi.util.Spreadsheet; - import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; @@ -23,16 +30,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import io.github.millij.poi.ss.model.annotations.Sheet; +import io.github.millij.poi.ss.model.annotations.SheetColumn; +import io.github.millij.poi.util.Beans; +import io.github.millij.poi.util.Spreadsheet; + @Deprecated public class SpreadsheetWriter { private static final Logger LOGGER = LoggerFactory.getLogger(SpreadsheetWriter.class); + // Default Formats + private static final String DATE_DEFAULT_FORMAT = "EEE MMM dd HH:mm:ss zzz yyyy"; + private static final String LOCAL_DATE_DEFAULT_FORMAT = "yyyy-MM-dd"; + private final XSSFWorkbook workbook; private final OutputStream outputStrem; - // Constructors // ------------------------------------------------------------------------ @@ -51,13 +66,11 @@ public SpreadsheetWriter(OutputStream outputStream) { this.outputStrem = outputStream; } - // Methods // ------------------------------------------------------------------------ - // Sheet :: Add - + public void addSheet(Class beanType, List rowObjects) { // Sheet Headers List headers = Spreadsheet.getColumnNames(beanType); @@ -80,8 +93,7 @@ public void addSheet(Class beanType, List rowObjects, String sheetN this.addSheet(beanType, rowObjects, headers, sheetName); } - public void addSheet(Class beanType, List rowObjects, List headers, - String sheetName) { + public void addSheet(Class beanType, List rowObjects, List headers, String sheetName) { // Sanity checks if (beanType == null) { throw new IllegalArgumentException("GenericExcelWriter :: ExcelBean type should not be null"); @@ -99,6 +111,8 @@ public void addSheet(Class beanType, List rowObjects, List try { XSSFSheet exSheet = workbook.getSheet(sheetName); + final CellStyle cellStyle = workbook.createCellStyle(); + final CreationHelper createHelper = workbook.getCreationHelper(); if (exSheet != null) { String errMsg = String.format("A Sheet with the passed name already exists : %s", sheetName); throw new IllegalArgumentException(errMsg); @@ -108,20 +122,59 @@ public void addSheet(Class beanType, List rowObjects, List LOGGER.debug("Added new Sheet[name] to the workbook : {}", sheet.getSheetName()); // Header - XSSFRow headerRow = sheet.createRow(0); + final XSSFRow headerRow = sheet.createRow(0); for (int i = 0; i < headers.size(); i++) { XSSFCell cell = headerRow.createCell(i); cell.setCellValue(headers.get(i)); } // Data Rows - Map> rowsData = this.prepareSheetRowsData(headers, rowObjects); + final Map> rowsData = prepareSheetRowsData(headers, rowObjects); + + final Map dateFormatsMap = getFormats(beanType); + for (int i = 0, rowNum = 1; i < rowObjects.size(); i++, rowNum++) { final XSSFRow row = sheet.createRow(rowNum); int cellNo = 0; for (String key : rowsData.keySet()) { - Cell cell = row.createCell(cellNo); + final Cell cell = row.createCell(cellNo); + + final String keyFormat = dateFormatsMap.get(key); + if (keyFormat != null) { + + final String value = rowsData.get(key).get(i); + Date date; + + try { + // Date Check + final SimpleDateFormat formatter = new SimpleDateFormat(DATE_DEFAULT_FORMAT); + date = formatter.parse(value); + + } catch (ParseException e) { + + try { + // LocalDate Check + final SimpleDateFormat formatter = new SimpleDateFormat(LOCAL_DATE_DEFAULT_FORMAT); + date = formatter.parse(value); + } catch (ParseException ex) { + cell.setCellValue(value); + cellNo++; + continue; + } + } + + if (Objects.isNull(date)) { + continue; + } + + cellStyle.setDataFormat(createHelper.createDataFormat().getFormat(keyFormat)); + cell.setCellStyle(cellStyle); + + cell.setCellValue(date); + cellNo++; + continue; + } String value = rowsData.get(key).get(i); cell.setCellValue(value); cellNo++; @@ -134,11 +187,8 @@ public void addSheet(Class beanType, List rowObjects, List } } - // Sheet :: Append to existing - - // Write public void write() throws IOException { @@ -146,18 +196,17 @@ public void write() throws IOException { workbook.close(); } - // Private Methods // ------------------------------------------------------------------------ - private Map> prepareSheetRowsData(List headers, - List rowObjects) throws Exception { + private Map> prepareSheetRowsData(List headers, List rowObjects) + throws Exception { final Map> sheetData = new LinkedHashMap>(); // Iterate over Objects for (EB excelBean : rowObjects) { - Map row = Spreadsheet.asRowDataMap(excelBean, headers); + final Map row = Spreadsheet.asRowDataMap(excelBean, headers); for (String header : headers) { List data = sheetData.containsKey(header) ? sheetData.get(header) : new ArrayList(); @@ -171,6 +220,50 @@ private Map> prepareSheetRowsData(List headers return sheetData; } + public static Map getFormats(Class beanType) { + if (beanType == null) { + throw new IllegalArgumentException("getColumnToPropertyMap :: Invalid ExcelBean type - " + beanType); + } + final Map headFormatMap = new HashMap(); + + // Fields + final Field[] fields = beanType.getDeclaredFields(); + + for (Field f : fields) { + if (!f.isAnnotationPresent(SheetColumn.class)) { + continue; + } + + final SheetColumn ec = f.getAnnotation(SheetColumn.class); + + if (ec != null) { + final Class fieldType = f.getType(); + if (fieldType == Date.class || fieldType == LocalDate.class) { + final String value = ec.value(); + headFormatMap.put(StringUtils.isNotBlank(value) ? value : f.getName(), ec.format()); + } + } + } + + // Methods + final Method[] methods = beanType.getDeclaredMethods(); + + for (Method m : methods) { + if (!m.isAnnotationPresent(SheetColumn.class)) { + continue; + } + + final String fieldName = Beans.getFieldName(m); + final Class objType = m.getReturnType(); + + final SheetColumn ec = m.getAnnotation(SheetColumn.class); + if (objType == Date.class || objType == LocalDate.class) { + final String value = StringUtils.isBlank(ec.value()) ? fieldName : ec.value(); + headFormatMap.put(value, ec.format()); + } + } + return headFormatMap; + } } diff --git a/src/main/java/io/github/millij/poi/util/Spreadsheet.java b/src/main/java/io/github/millij/poi/util/Spreadsheet.java index 5412bf5..7a98bb6 100644 --- a/src/main/java/io/github/millij/poi/util/Spreadsheet.java +++ b/src/main/java/io/github/millij/poi/util/Spreadsheet.java @@ -1,21 +1,24 @@ package io.github.millij.poi.util; -import io.github.millij.poi.ss.model.annotations.SheetColumn; - import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import io.github.millij.poi.ss.model.annotations.SheetColumn; + + /** * Spreadsheet related utilites. */ @@ -35,6 +38,7 @@ private Spreadsheet() { * Splits the CellReference and returns only the column reference. * * @param cellRef the cell reference value (ex. D3) + * * @return returns the column index "D" from the cell reference "D3" */ public static String getCellColumnReference(String cellRef) { @@ -56,28 +60,28 @@ public static Map getPropertyToColumnNameMap(Class beanType) final Map mapping = new HashMap(); // Fields - Field[] fields = beanType.getDeclaredFields(); + final Field[] fields = beanType.getDeclaredFields(); for (Field f : fields) { - String fieldName = f.getName(); - mapping.put(fieldName, fieldName); + final String fieldName = f.getName(); SheetColumn ec = f.getAnnotation(SheetColumn.class); - if (ec != null && StringUtils.isNotEmpty(ec.value())) { - mapping.put(fieldName, ec.value()); + + if (ec != null) { + final String value = StringUtils.isNotEmpty(ec.value()) ? ec.value() : fieldName; + mapping.put(fieldName, value); } } // Methods - Method[] methods = beanType.getDeclaredMethods(); + final Method[] methods = beanType.getDeclaredMethods(); for (Method m : methods) { String fieldName = Beans.getFieldName(m); - if (!mapping.containsKey(fieldName)) { - mapping.put(fieldName, fieldName); - } SheetColumn ec = m.getAnnotation(SheetColumn.class); - if (ec != null && StringUtils.isNotEmpty(ec.value())) { - mapping.put(fieldName, ec.value()); + + if (ec != null && !mapping.containsKey(fieldName)) { + String value = StringUtils.isNotEmpty(ec.value()) ? ec.value() : fieldName; + mapping.put(fieldName, value); } } @@ -108,7 +112,6 @@ public static List getColumnNames(Class beanType) { } - // Read from Bean : as Row Data // ------------------------------------------------------------------------ @@ -180,7 +183,7 @@ public static T rowAsBean(Class beanClz, Map cellProperie continue; } - Object propValue = cellValues.get(cellName); + Object propValue = Objects.isNull(cellValues.get(cellName)) ? cellValues.get(propName) : cellValues.get(cellName); try { // Set the property value in the current row object bean BeanUtils.setProperty(rowBean, propName, propValue); diff --git a/src/test/java/io/github/millij/bean/Employee.java b/src/test/java/io/github/millij/bean/Employee.java index 83ba764..33579e2 100644 --- a/src/test/java/io/github/millij/bean/Employee.java +++ b/src/test/java/io/github/millij/bean/Employee.java @@ -23,6 +23,11 @@ public class Employee { @SheetColumn("Address") private String address; + @SheetColumn(value = "Formula") + private String formula; + + @SheetColumn(value = "Date", format = "yyyy/MM/dd") + private String date; // Constructors // ------------------------------------------------------------------------ @@ -31,7 +36,8 @@ public Employee() { // Default } - public Employee(String id, String name, Integer age, String gender, Double height) { + public Employee(String id, String name, Integer age, String gender, Double height, String formula, String date, + String address) { super(); this.id = id; @@ -39,9 +45,11 @@ public Employee(String id, String name, Integer age, String gender, Double heigh this.age = age; this.gender = gender; this.height = height; + this.date = date; + this.address = address; + this.formula = formula; } - // Getters and Setters // ------------------------------------------------------------------------ @@ -95,6 +103,21 @@ public void setAddress(String address) { this.address = address; } + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String getFormula() { + return formula; + } + + public void setFormula(String formula) { + this.formula = formula; + } // Object Methods // ------------------------------------------------------------------------ @@ -102,8 +125,7 @@ public void setAddress(String address) { @Override public String toString() { return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", gender=" + gender + ", height=" + height - + ", address=" + address + "]"; + + ", date=" + date + ", Formula=" + formula + "]"; } - } diff --git a/src/test/java/io/github/millij/bean/Schedule.java b/src/test/java/io/github/millij/bean/Schedule.java new file mode 100644 index 0000000..fb5ebd4 --- /dev/null +++ b/src/test/java/io/github/millij/bean/Schedule.java @@ -0,0 +1,73 @@ +package io.github.millij.bean; + +import java.time.LocalDate; +import java.util.Date; + +// import java.util.Date; + +import io.github.millij.poi.ss.model.annotations.Sheet; +import io.github.millij.poi.ss.model.annotations.SheetColumn; + + +@Sheet("Schedules") +public class Schedule { + + @SheetColumn("Day") + private String day; + + @SheetColumn(value = "Date", format = "dd/MM/yyyy") + private Date date; + + @SheetColumn(value = "LocalDate", format = "dd/MM/yyyy") + private LocalDate localDate; + + // Constructor + // ------------------------------------------------------------------------- + + public Schedule() { + super(); + } + + public Schedule(String day, Date date, LocalDate localDate) { + super(); + this.day = day; + this.date = date; + this.localDate = localDate; + } + + // Getters and Setters + // ------------------------------------------------------------------------- + + + public String getDay() { + return day; + } + + public void setDay(String day) { + this.day = day; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public LocalDate getLocalDate() { + return localDate; + } + + public void setLocalDate(LocalDate localDate) { + this.localDate = localDate; + } + + // Object Methods + // ------------------------------------------------------------------------ + @Override + public String toString() { + return "Schedule [day=" + day + ", date=" + date + ", LocalDate=" + localDate + "]"; + } + +} diff --git a/src/test/java/io/github/millij/dates/DateTest.java b/src/test/java/io/github/millij/dates/DateTest.java new file mode 100644 index 0000000..629f7a3 --- /dev/null +++ b/src/test/java/io/github/millij/dates/DateTest.java @@ -0,0 +1,90 @@ +package io.github.millij.dates; + +import java.io.File; +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.github.millij.bean.Schedule; +import io.github.millij.poi.SpreadsheetReadException; +import io.github.millij.poi.ss.reader.XlsReader; +import io.github.millij.poi.ss.reader.XlsxReader; +import io.github.millij.poi.ss.writer.SpreadsheetWriter; + + +public class DateTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(DateTest.class); + + @Test + public void writeDatesTest() throws IOException, ParseException { + + List schedules = new ArrayList(); + final String filepath_output_file = "src/test/resources/sample-files/write_formatted_date_sample.xls"; + SpreadsheetWriter gew = new SpreadsheetWriter(filepath_output_file); + + SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy"); + DateTimeFormatter format = DateTimeFormatter.ofPattern("dd/MM/yyyy"); + + Date date1 = formatter.parse("02/05/2001"); + Date date2 = formatter.parse("03/06/2001"); + LocalDate ldate1 = LocalDate.parse("02/05/2002", format); + LocalDate ldate2 = LocalDate.parse("03/06/2002", format); + + // Schedules + schedules.add(new Schedule("Friday", date1, ldate1)); + schedules.add(new Schedule("Saturday", date2, ldate2)); + + gew.addSheet(Schedule.class, schedules); + gew.write(); + } + + @Test + public void xlsx_read_dates_test() throws SpreadsheetReadException { + // Excel Reader + LOGGER.info("xlsx_read_dates_test :: Reading file - {}", + "src/test/resources/sample-files/write_formatted_date_sample.xlsx"); + XlsxReader reader = new XlsxReader(); + + // Read + List schedules = reader.read(Schedule.class, + new File("src/test/resources/sample-files/write_formatted_date_sample.xlsx")); + Assert.assertNotNull(schedules); + Assert.assertTrue(schedules.size() > 0); + + for (Schedule emp : schedules) { + LOGGER.info("xlsx_read_dates_test :: Output - {}", emp); + } + + } + + @Test + public void xls_read_dates_test() throws SpreadsheetReadException { + // Excel Reader + LOGGER.info("xlsx_read_dates_test :: Reading file - {}", + "src/test/resources/sample-files/xls_sample_read_dates.xls"); + XlsReader reader = new XlsReader(); + + // Read + List schedules = + reader.read(Schedule.class, new File("src/test/resources/sample-files/xls_sample_read_dates.xls")); + Assert.assertNotNull(schedules); + Assert.assertTrue(schedules.size() > 0); + + for (Schedule emp : schedules) { + LOGGER.info("xlsx_read_dates_test :: Output - {}", emp); + } + + } + +} diff --git a/src/test/java/io/github/millij/poi/ss/reader/XlsReaderTest.java b/src/test/java/io/github/millij/poi/ss/reader/XlsReaderTest.java index dd3e056..f3511eb 100644 --- a/src/test/java/io/github/millij/poi/ss/reader/XlsReaderTest.java +++ b/src/test/java/io/github/millij/poi/ss/reader/XlsReaderTest.java @@ -1,6 +1,7 @@ package io.github.millij.poi.ss.reader; import io.github.millij.bean.Company; + import io.github.millij.bean.Employee; import io.github.millij.poi.SpreadsheetReadException; import io.github.millij.poi.ss.handler.RowListener; diff --git a/src/test/java/io/github/millij/poi/ss/writer/SpreadsheetWriterTest.java b/src/test/java/io/github/millij/poi/ss/writer/SpreadsheetWriterTest.java index dd3b1c6..c52e8ce 100644 --- a/src/test/java/io/github/millij/poi/ss/writer/SpreadsheetWriterTest.java +++ b/src/test/java/io/github/millij/poi/ss/writer/SpreadsheetWriterTest.java @@ -55,9 +55,9 @@ public void test_write_xlsx_single_sheet() throws IOException { // Employees List employees = new ArrayList(); - employees.add(new Employee("1", "foo", 12, "MALE", 1.68)); - employees.add(new Employee("2", "bar", null, "MALE", 1.68)); - employees.add(new Employee("3", "foo bar", null, null, null)); + employees.add(new Employee("1", "foo", 12, "MALE", 1.68, "F2+G2", "02/11/2001", "Chennai")); + employees.add(new Employee("2", "bar", 24, "MALE", 1.98, "F3+G3", "03/11/2001", "Banglore")); + employees.add(new Employee("3", "foo bar", 10, "FEMALE", 2.0, "F4+G4", "04/11/2001", "Kolkata")); // Write gew.addSheet(Employee.class, employees); @@ -74,9 +74,9 @@ public void test_write_xlsx_single_sheet_custom_headers() throws IOException { // Employees List employees = new ArrayList(); - employees.add(new Employee("1", "foo", 12, "MALE", 1.68)); - employees.add(new Employee("2", "bar", null, "MALE", 1.68)); - employees.add(new Employee("3", "foo bar", null, null, null)); + employees.add(new Employee("1", "foo", 12, "MALE", 1.68, "F2+G2", "02/11/2001", "Chennai")); + employees.add(new Employee("2", "bar", 24, "MALE", 1.98, "F3+G3", "03/11/2001", "Banglore")); + employees.add(new Employee("3", "foo bar", 10, "FEMALE", 2.0, "F4+G4", "04/11/2001", "Kolkata")); List headers = Arrays.asList("ID", "Age", "Name", "Address"); @@ -98,9 +98,9 @@ public void test_write_xlsx_multiple_sheets() throws IOException { // Employees List employees = new ArrayList(); - employees.add(new Employee("1", "foo", 12, "MALE", 1.68)); - employees.add(new Employee("2", "bar", null, "MALE", 1.68)); - employees.add(new Employee("3", "foo bar", null, null, null)); + employees.add(new Employee("1", "foo", 12, "MALE", 1.68, "F2+G2", "02/11/2001", "Chennai")); + employees.add(new Employee("2", "bar", 24, "MALE", 1.98, "F3+G3", "03/11/2001", "Banglore")); + employees.add(new Employee("3", "foo bar", 10, "FEMALE", 2.0, "F4+G4", "04/11/2001", "Kolkata")); // Campanies List companies = new ArrayList(); diff --git a/src/test/resources/sample-files/write_formatted_date_sample.xlsx b/src/test/resources/sample-files/write_formatted_date_sample.xlsx new file mode 100644 index 0000000..bb02461 Binary files /dev/null and b/src/test/resources/sample-files/write_formatted_date_sample.xlsx differ diff --git a/src/test/resources/sample-files/xls_sample_read_dates.xls b/src/test/resources/sample-files/xls_sample_read_dates.xls new file mode 100644 index 0000000..2a443ca Binary files /dev/null and b/src/test/resources/sample-files/xls_sample_read_dates.xls differ diff --git a/src/test/resources/sample-files/xls_sample_single_sheet.xls b/src/test/resources/sample-files/xls_sample_single_sheet.xls index 4865c52..7dc20cc 100644 Binary files a/src/test/resources/sample-files/xls_sample_single_sheet.xls and b/src/test/resources/sample-files/xls_sample_single_sheet.xls differ diff --git a/src/test/resources/sample-files/xlsx_sample_multiple_sheets.xlsx b/src/test/resources/sample-files/xlsx_sample_multiple_sheets.xlsx index 9b00f63..f0a14e8 100644 Binary files a/src/test/resources/sample-files/xlsx_sample_multiple_sheets.xlsx and b/src/test/resources/sample-files/xlsx_sample_multiple_sheets.xlsx differ diff --git a/src/test/resources/sample-files/xlsx_sample_single_sheet.xlsx b/src/test/resources/sample-files/xlsx_sample_single_sheet.xlsx index 06f9646..667c579 100644 Binary files a/src/test/resources/sample-files/xlsx_sample_single_sheet.xlsx and b/src/test/resources/sample-files/xlsx_sample_single_sheet.xlsx differ