Skip to content

Commit 102fab6

Browse files
committed
Added new methods to convert Excel to POJOs
1 parent 4607bbd commit 102fab6

File tree

8 files changed

+232
-20
lines changed

8 files changed

+232
-20
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.github.mbenincasa.javaexcelutils.model.converter;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
import lombok.Setter;
6+
7+
@AllArgsConstructor
8+
@Getter
9+
@Setter
10+
public class ExcelToObject<T> {
11+
12+
private String sheetName;
13+
private Class<T> clazz;
14+
}

src/main/java/io/github/mbenincasa/javaexcelutils/model/excel/ExcelCell.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,18 @@ public ExcelRow getRow() {
5151
public Object readValue(Class<?> type) throws ReadValueException {
5252
Object val;
5353
switch (this.cell.getCellType()) {
54-
case BOOLEAN -> val = this.cell.getBooleanCellValue();
55-
case STRING -> val = this.cell.getStringCellValue();
54+
case BOOLEAN -> {
55+
if (!Boolean.class.equals(type)) {
56+
throw new ReadValueException("This type '" + type + "' is either incompatible with the CellType '" + this.cell.getCellType() + "'");
57+
}
58+
val = this.cell.getBooleanCellValue();
59+
}
60+
case STRING -> {
61+
if (!String.class.equals(type)) {
62+
throw new ReadValueException("This type '" + type + "' is either incompatible with the CellType '" + this.cell.getCellType() + "'");
63+
}
64+
val = this.cell.getStringCellValue();
65+
}
5666
case NUMERIC -> {
5767
if (Integer.class.equals(type)) {
5868
val = (int) this.cell.getNumericCellValue();
@@ -67,7 +77,7 @@ public Object readValue(Class<?> type) throws ReadValueException {
6777
} else if (LocalDate.class.equals(type)) {
6878
val = this.cell.getLocalDateTimeCellValue().toLocalDate();
6979
} else {
70-
throw new ReadValueException("This numeric type is not supported: " + type);
80+
throw new ReadValueException("This type '" + type + "' is either incompatible with the CellType '" + this.cell.getCellType() + "' or not yet supported");
7181
}
7282
}
7383
case FORMULA -> {
Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
import io.github.mbenincasa.javaexcelutils.annotations.ExcelBodyStyle;
44
import io.github.mbenincasa.javaexcelutils.annotations.ExcelField;
55
import io.github.mbenincasa.javaexcelutils.annotations.ExcelHeaderStyle;
6-
import lombok.*;
6+
import lombok.AllArgsConstructor;
7+
import lombok.NoArgsConstructor;
8+
import lombok.Setter;
9+
import lombok.ToString;
710
import org.apache.poi.ss.usermodel.HorizontalAlignment;
811
import org.apache.poi.ss.usermodel.IndexedColors;
912
import org.apache.poi.ss.usermodel.VerticalAlignment;
@@ -18,18 +21,22 @@
1821
@ToString
1922
@ExcelHeaderStyle(cellColor = IndexedColors.ORANGE, horizontal = HorizontalAlignment.RIGHT, vertical = VerticalAlignment.BOTTOM, autoSize = true)
2023
@ExcelBodyStyle(cellColor = IndexedColors.LIGHT_ORANGE, horizontal = HorizontalAlignment.RIGHT, vertical = VerticalAlignment.BOTTOM)
21-
public class Car {
24+
public class Employee {
2225

23-
@ExcelField(name = "BRAND")
24-
private String brand;
25-
@ExcelField(name = "MODEL")
26-
private String model;
27-
@ExcelField(name = "YEAR")
28-
private Integer year;
29-
@ExcelField(name = "RELEASE DATE")
30-
private LocalDate releaseDate;
31-
@ExcelField(name = "FIRST SALE")
32-
private Date firstSale;
33-
@ExcelField(name = "LAST SALE")
34-
private LocalDateTime lastSale;
26+
@ExcelField(name = "LAST NAME")
27+
private String lastName;
28+
@ExcelField(name = "NAME")
29+
private String name;
30+
@ExcelField(name = "AGE")
31+
private Integer age;
32+
@ExcelField(name = "BIRTHDAY")
33+
private LocalDate birthday;
34+
@ExcelField(name = "HIRE DATE")
35+
private Date hireDate;
36+
@ExcelField(name = "SALARY (€)")
37+
private Double salary;
38+
@ExcelField(name = "LAST SIGN IN")
39+
private LocalDateTime lastSignIn;
40+
@ExcelField(name = "IS IN OFFICE")
41+
private Boolean isInOffice;
3542
}

src/main/java/io/github/mbenincasa/javaexcelutils/samples/convertExcelFileToObjectsSample/Main.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,33 @@
11
package io.github.mbenincasa.javaexcelutils.samples.convertExcelFileToObjectsSample;
22

3+
import io.github.mbenincasa.javaexcelutils.model.converter.ExcelToObject;
34
import io.github.mbenincasa.javaexcelutils.tools.Converter;
45

56
import java.io.File;
7+
import java.util.ArrayList;
68
import java.util.List;
9+
import java.util.Map;
10+
import java.util.stream.Stream;
711

812
public class Main {
913

1014
public static void main(String[] args) {
1115

12-
File file = new File("./src/main/resources/car.xlsx");
16+
File file = new File("./src/main/resources/result.xlsx");
17+
ExcelToObject<Employee> employeeExcelToObject = new ExcelToObject<>("Employee", Employee.class);
18+
ExcelToObject<Office> officeExcelToObject = new ExcelToObject<>("Office", Office.class);
19+
List<ExcelToObject<?>> excelToObjects = new ArrayList<>();
20+
excelToObjects.add(employeeExcelToObject);
21+
excelToObjects.add(officeExcelToObject);
1322

1423
try {
1524
System.out.println("Start the conversion...");
16-
List<Car> cars = (List<Car>) Converter.excelToObjects(file, Car.class);
17-
System.out.println("The list is ready. List: " + cars);
25+
Map<String, Stream<?>> map = Converter.excelFileToObjects(file, excelToObjects);
26+
System.out.println("...completed");
27+
for (Map.Entry<String, Stream<?>> entry : map.entrySet()) {
28+
System.out.println("Sheet: " + entry.getKey());
29+
System.out.println("Data: " + entry.getValue().toList());
30+
}
1831
} catch (Exception e) {
1932
System.err.println("There was an error. Check the console");
2033
throw new RuntimeException(e);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.github.mbenincasa.javaexcelutils.samples.convertExcelFileToObjectsSample;
2+
3+
import io.github.mbenincasa.javaexcelutils.annotations.ExcelBodyStyle;
4+
import io.github.mbenincasa.javaexcelutils.annotations.ExcelField;
5+
import io.github.mbenincasa.javaexcelutils.annotations.ExcelHeaderStyle;
6+
import lombok.AllArgsConstructor;
7+
import lombok.NoArgsConstructor;
8+
import lombok.Setter;
9+
import lombok.ToString;
10+
11+
@AllArgsConstructor
12+
@NoArgsConstructor
13+
@Setter
14+
@ToString
15+
@ExcelHeaderStyle(autoSize = true)
16+
@ExcelBodyStyle
17+
public class Office {
18+
19+
@ExcelField(name = "CITY")
20+
private String city;
21+
@ExcelField(name = "PROVINCE")
22+
private String province;
23+
@ExcelField(name = "NUMBER OF STATIONS")
24+
private Integer numStations;
25+
}

src/main/java/io/github/mbenincasa/javaexcelutils/samples/convertObjectsToExcelFileSample/Office.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
@ExcelHeaderStyle(autoSize = true)
1414
@ExcelBodyStyle
1515
public class Office {
16+
1617
@ExcelField(name = "CITY")
1718
private String city;
1819
@ExcelField(name = "PROVINCE")

src/main/java/io/github/mbenincasa/javaexcelutils/tools/Converter.java

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.opencsv.exceptions.CsvValidationException;
99
import io.github.mbenincasa.javaexcelutils.enums.Extension;
1010
import io.github.mbenincasa.javaexcelutils.exceptions.*;
11+
import io.github.mbenincasa.javaexcelutils.model.converter.ExcelToObject;
1112
import io.github.mbenincasa.javaexcelutils.model.converter.ObjectToExcel;
1213
import io.github.mbenincasa.javaexcelutils.model.excel.ExcelCell;
1314
import io.github.mbenincasa.javaexcelutils.model.excel.ExcelRow;
@@ -26,6 +27,7 @@
2627
import java.time.LocalDateTime;
2728
import java.util.*;
2829
import java.util.concurrent.atomic.AtomicInteger;
30+
import java.util.stream.Stream;
2931

3032
/**
3133
* {@code Converter} is the static class with implementations of conversion methods
@@ -373,6 +375,7 @@ public static OutputStream objectsToExcelStream(List<ObjectToExcel<?>> objectToE
373375
/**
374376
* This method allows you to convert objects into a Sheet of a File that already exists.<p>
375377
* By default, the header is added if not specified
378+
* @deprecated since version 0.4.0
376379
* @param file The {@code File} to update
377380
* @param objects The list of objects that will be converted into an Excel file
378381
* @param clazz The class of the list elements
@@ -382,12 +385,14 @@ public static OutputStream objectsToExcelStream(List<ObjectToExcel<?>> objectToE
382385
* @throws IllegalAccessException If a field or fields of the {@code clazz} could not be accessed
383386
* @since 0.2.1
384387
*/
388+
@Deprecated
385389
public static void objectsToExistingExcel(File file, List<?> objects, Class<?> clazz) throws OpenWorkbookException, ExtensionNotValidException, IOException, IllegalAccessException {
386390
objectsToExistingExcel(file, objects, clazz, true);
387391
}
388392

389393
/**
390394
* This method allows you to convert objects into a Sheet of a File that already exists.
395+
* @deprecated since version 0.4.0
391396
* @param file The {@code File} to update
392397
* @param objects The list of objects that will be converted into an Excel file
393398
* @param clazz The class of the list elements
@@ -398,6 +403,7 @@ public static void objectsToExistingExcel(File file, List<?> objects, Class<?> c
398403
* @throws IllegalAccessException If a field or fields of the {@code clazz} could not be accessed
399404
* @since 0.2.1
400405
*/
406+
@Deprecated
401407
public static void objectsToExistingExcel(File file, List<?> objects, Class<?> clazz, Boolean writeHeader) throws OpenWorkbookException, ExtensionNotValidException, IOException, IllegalAccessException {
402408
/* Open workbook */
403409
ExcelWorkbook excelWorkbook = ExcelWorkbook.open(file);
@@ -416,24 +422,28 @@ public static void objectsToExistingExcel(File file, List<?> objects, Class<?> c
416422
* This method allows you to convert objects into a Sheet of a Workbook that already exists.<p>
417423
* Note: This method does not call the "write" method of the workbook.<p>
418424
* By default, the header is added if not specified
425+
* @deprecated since version 0.4.0
419426
* @param workbook The {@code Workbook} to update
420427
* @param objects The list of objects that will be converted into an Excel file
421428
* @param clazz The class of the list elements
422429
* @throws IllegalAccessException If a field or fields of the {@code clazz} could not be accessed
423430
*/
431+
@Deprecated
424432
public static void objectsToExistingExcel(Workbook workbook, List<?> objects, Class<?> clazz) throws IllegalAccessException {
425433
objectsToExistingExcel(workbook, objects, clazz, true);
426434
}
427435

428436
/**
429437
* This method allows you to convert objects into a Sheet of a Workbook that already exists.<p>
430438
* Note: This method does not call the "write" method of the workbook.
439+
* @deprecated since version 0.4.0
431440
* @param workbook The {@code Workbook} to update
432441
* @param objects The list of objects that will be converted into an Excel file
433442
* @param clazz The class of the list elements
434443
* @param writeHeader If {@code true} it will write the header to the first line
435444
* @throws IllegalAccessException If a field or fields of the {@code clazz} could not be accessed
436445
*/
446+
@Deprecated
437447
public static void objectsToExistingExcel(Workbook workbook, List<?> objects, Class<?> clazz, Boolean writeHeader) throws IllegalAccessException {
438448
/* Create sheet */
439449
ExcelWorkbook excelWorkbook = new ExcelWorkbook(workbook);
@@ -460,6 +470,7 @@ public static void objectsToExistingExcel(Workbook workbook, List<?> objects, Cl
460470
* Convert an Excel file into a list of objects<p>
461471
* Note: The type of the elements of the return objects must coincide with the type of {@code clazz}<p>
462472
* By default, the first sheet is chosen
473+
* @deprecated since version 0.4.0
463474
* @param file The input Excel file that will be converted into a list of objects
464475
* @param clazz The class of the list elements
465476
* @return A list of objects that contains as many objects as there are lines in the input file
@@ -473,13 +484,15 @@ public static void objectsToExistingExcel(Workbook workbook, List<?> objects, Cl
473484
* @throws SheetNotFoundException If the sheet to open is not found
474485
* @throws HeaderNotPresentException If the first row is empty and does not contain the header
475486
*/
487+
@Deprecated
476488
public static List<?> excelToObjects(File file, Class<?> clazz) throws ExtensionNotValidException, IOException, OpenWorkbookException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SheetNotFoundException, HeaderNotPresentException {
477489
return excelToObjects(file, clazz, null);
478490
}
479491

480492
/**
481493
* Convert an Excel file into a list of objects<p>
482494
* Note: The type of the elements of the return objects must coincide with the type of {@code clazz}
495+
* @deprecated since version 0.4.0
483496
* @param file The input Excel file that will be converted into a list of objects
484497
* @param clazz The class of the list elements
485498
* @param sheetName The name of the sheet to open
@@ -494,6 +507,7 @@ public static List<?> excelToObjects(File file, Class<?> clazz) throws Extension
494507
* @throws SheetNotFoundException If the sheet to open is not found
495508
* @throws HeaderNotPresentException If the first row is empty and does not contain the header
496509
*/
510+
@Deprecated
497511
public static List<?> excelToObjects(File file, Class<?> clazz, String sheetName) throws ExtensionNotValidException, IOException, OpenWorkbookException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException, SheetNotFoundException, HeaderNotPresentException {
498512
/* Open file excel */
499513
ExcelWorkbook excelWorkbook = ExcelWorkbook.open(file);
@@ -523,6 +537,71 @@ public static List<?> excelToObjects(File file, Class<?> clazz, String sheetName
523537
return resultList;
524538
}
525539

540+
public static Map<String, Stream<?>> excelByteToObjects(byte[] bytes, List<ExcelToObject<?>> excelToObjects) throws OpenWorkbookException, SheetNotFoundException, ReadValueException, HeaderNotPresentException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
541+
ByteArrayInputStream byteStream = new ByteArrayInputStream(bytes);
542+
return excelStreamToObjects(byteStream, excelToObjects);
543+
}
544+
545+
public static Map<String, Stream<?>> excelFileToObjects(File file, List<ExcelToObject<?>> excelToObjects) throws IOException, OpenWorkbookException, SheetNotFoundException, ReadValueException, HeaderNotPresentException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
546+
FileInputStream fileInputStream = new FileInputStream(file);
547+
Map<String, Stream<?>> map = excelStreamToObjects(fileInputStream, excelToObjects);
548+
fileInputStream.close();
549+
return map;
550+
}
551+
552+
public static Map<String, Stream<?>> excelStreamToObjects(InputStream inputStream, List<ExcelToObject<?>> excelToObjects) throws OpenWorkbookException, SheetNotFoundException, HeaderNotPresentException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ReadValueException {
553+
/* Open Workbook */
554+
ExcelWorkbook excelWorkbook = new ExcelWorkbook(inputStream);
555+
Map<String, Stream<?>> map = new HashMap<>();
556+
557+
/* Iterate all the sheets to convert */
558+
for (ExcelToObject<?> excelToObject : excelToObjects) {
559+
Class<?> clazz = excelToObject.getClazz();
560+
ExcelSheet excelSheet = excelWorkbook.getSheet(excelToObject.getSheetName());
561+
562+
/* Retrieving header names */
563+
Field[] fields = clazz.getDeclaredFields();
564+
setFieldsAccessible(fields);
565+
Map<Integer, String> headerMap = getHeaderNames(excelSheet, fields);
566+
567+
Stream.Builder<Object> streamBuilder = Stream.builder();
568+
569+
/* Iterate all rows */
570+
for (ExcelRow excelRow : excelSheet.getRows()) {
571+
if (excelRow.getRow() == null || excelRow.getIndex() == 0) {
572+
continue;
573+
}
574+
575+
Object obj = clazz.getDeclaredConstructor().newInstance();
576+
/* Iterate all cells */
577+
for (ExcelCell excelCell : excelRow.getCells()) {
578+
if (excelCell.getCell() == null) {
579+
continue;
580+
}
581+
582+
String headerName = headerMap.get(excelCell.getIndex());
583+
if (headerName == null || headerMap.isEmpty()) {
584+
continue;
585+
}
586+
587+
/* Read the value in the cell */
588+
Optional<Field> fieldOptional = Arrays.stream(fields).filter(f -> f.getName().equalsIgnoreCase(headerName)).findFirst();
589+
if (fieldOptional.isEmpty()) {
590+
throw new RuntimeException();
591+
}
592+
Field field = fieldOptional.get();
593+
PropertyUtils.setSimpleProperty(obj, headerName, excelCell.readValue(field.getType()));
594+
}
595+
/* Adds the object to the Stream after it has finished cycling through all cells */
596+
streamBuilder.add(obj);
597+
}
598+
/* inserts the Stream of all Sheet objects into the Map */
599+
map.put(excelSheet.getName(), streamBuilder.build());
600+
}
601+
602+
return map;
603+
}
604+
526605
/**
527606
* Convert an Excel file into a CSV file<p>
528607
* The default path is that of the temporary folder. By default, the first sheet is chosen and the filename will be the same as the input file if not specified
@@ -831,6 +910,27 @@ private static Map<Integer, String> getHeaderNames(Sheet sheet, Field[] fields)
831910
return headerMap;
832911
}
833912

913+
private static Map<Integer, String> getHeaderNames(ExcelSheet excelSheet, Field[] fields) throws HeaderNotPresentException {
914+
Map<String, String> fieldNames = new HashMap<>();
915+
for (Field field : fields) {
916+
ExcelField excelField = field.getAnnotation(ExcelField.class);
917+
fieldNames.put(excelField == null ? field.getName() : excelField.name(), field.getName());
918+
}
919+
920+
Row headerRow = excelSheet.getSheet().getRow(0);
921+
if (headerRow == null)
922+
throw new HeaderNotPresentException("There is no header in the first row of the sheet.");
923+
924+
Map<Integer, String> headerMap = new TreeMap<>();
925+
for (Cell cell : headerRow) {
926+
if (fieldNames.containsKey(cell.getStringCellValue())) {
927+
headerMap.put(cell.getColumnIndex(), fieldNames.get(cell.getStringCellValue()));
928+
}
929+
}
930+
931+
return headerMap;
932+
}
933+
834934
private static Object convertCellValuesToObject(Class<?> clazz, Row row, Field[] fields, Map<Integer, String> headerMap) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
835935
Object obj = clazz.getDeclaredConstructor().newInstance();
836936
for (Cell cell : row) {

0 commit comments

Comments
 (0)