Skip to content

Commit 71bc537

Browse files
committed
Merge branch 'v3.x.x'
2 parents 81ba3ed + c094975 commit 71bc537

File tree

14 files changed

+433
-67
lines changed

14 files changed

+433
-67
lines changed

README.md

+41-5
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55

66
# poi-object-mapper
77

8-
**poi-object-mapper** is a wrapper java library for [Apache POI](https://poi.apache.org/) (Apache POI provides java API to read Microsoft Office Formats). POI APIs are very low level giving acess to all the internals of the file formats.
8+
**poi-object-mapper** is a wrapper java library for [Apache POI](https://poi.apache.org/) (Apache POI provides java API to read Microsoft Office Formats). POI APIs are very low level giving access to all the internals of the file formats.
99

10-
The aim of this project is to provide easy to use highlevel APIs to read the Office file formats by wrapping the POI APIs. In simple terms, the wrapper APIs would look similar to the [Jackson Project for XML and JSON](https://github.com/FasterXML/jackson), where the data can be mapped to a JAVA Bean and through the mapper APIs, the file data can directly be read as java objects.
10+
The aim of this project is to provide easy to use high-level APIs to read the Office file formats by wrapping the POI APIs. In simple terms, the wrapper APIs would look similar to the [Jackson Project for XML and JSON](https://github.com/FasterXML/jackson), where the data can be mapped to a JAVA Bean and through the mapper APIs, the file data can directly be read as java objects.
1111

1212
*- Note that the current version of the library supports only **spreadsheets** (Excel files).*
1313

@@ -22,7 +22,7 @@ This library is available in [Maven Central](https://mvnrepository.com/artifact/
2222
<dependency>
2323
<groupId>io.github.millij</groupId>
2424
<artifactId>poi-object-mapper</artifactId>
25-
<version>3.1.0</version>
25+
<version>3.2.0</version>
2626
</dependency>
2727
```
2828

@@ -95,7 +95,7 @@ Reading spreadsheet rows as `Map<String, Object>` Objects ..
9595
```
9696

9797

98-
##### Writing a collection of objects to file
98+
##### Writing a List of objects to file
9999

100100
Similar to `Reader`, the mapped Java Beans can be written to files.
101101

@@ -116,7 +116,43 @@ Use `XlsWriter` for `.xls` files and `XlsxWriter` for `.xlsx` files.
116116
...
117117
```
118118

119-
## Implementation Details
119+
##### Writing a List of objects defined as Map to file
120+
121+
Similar to `Reader`, the `Writer` also supports Row data defined as `Map<String, Object>`.
122+
This is to support the data that is not backed by a concrete bean Class definition
123+
124+
Use `XlsWriter` for `.xls` files and `XlsxWriter` for `.xlsx` files.
125+
126+
```java
127+
...
128+
// Employees
129+
final Map<String, Object> emp1 = new HashMap<>();
130+
emp1.put("Name", "foo");
131+
emp1.put("Age", 12);
132+
emp1.put("Gender", "MALE");
133+
emp1.put("Height (mts)", 1.68);
134+
135+
final Map<String, Object> emp2 = new HashMap<>();
136+
emp1.put("Name", "bar");
137+
emp1.put("Age", null);
138+
emp1.put("Gender", "MALE");
139+
140+
final List<Map<String, Object>> employees = Arrays.asList(emp1, emp2);
141+
142+
// Headers (or Column Names)
143+
final List<String> headers = new ArrayList<>();
144+
headers.add("Name");
145+
headers.add("Age");
146+
headers.add("Gender");
147+
headers.add("Height (mts)");
148+
headers.add("Address");
149+
150+
// Writer
151+
final SpreadsheetWriter writer = new XlsxWriter();
152+
writer.addSheet(employees, headers);
153+
writer.write("<output_file_path>");
154+
155+
```
120156

121157

122158

build.gradle

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ repositories {
1111
}
1212

1313

14-
sourceCompatibility = 1.11
15-
targetCompatibility = 1.11
14+
sourceCompatibility = 1.8
15+
targetCompatibility = 1.8
1616

1717
group = 'io.github.millij'
18-
version = '3.1.0'
18+
version = '3.2.0'
1919

2020

2121
dependencies {

src/main/java/io/github/millij/poi/ss/handler/AbstractSheetContentsHandler.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
import java.util.HashMap;
44
import java.util.Map;
5-
import java.util.Objects;
65

76
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler;
87
import org.apache.poi.xssf.usermodel.XSSFComment;
98
import org.slf4j.Logger;
109
import org.slf4j.LoggerFactory;
1110

1211
import io.github.millij.poi.util.Spreadsheet;
12+
import io.github.millij.poi.util.Strings;
1313

1414

1515
abstract class AbstractSheetContentsHandler implements SheetContentsHandler {
@@ -30,7 +30,6 @@ abstract class AbstractSheetContentsHandler implements SheetContentsHandler {
3030
abstract void afterRowEnd(int rowNum, Map<String, Object> rowObj);
3131

3232

33-
3433
// SheetContentsHandler Implementations
3534
// ------------------------------------------------------------------------
3635

@@ -53,12 +52,12 @@ public void endRow(final int rowNum) {
5352
@Override
5453
public void cell(final String cellRef, final String cellVal, final XSSFComment comment) {
5554
// Sanity Checks
56-
if (Objects.isNull(cellRef) || cellRef.isBlank()) {
55+
if (Strings.isBlank(cellRef)) {
5756
LOGGER.error("Row[#] {} : Cell reference is empty - {}", currentRow, cellRef);
5857
return;
5958
}
6059

61-
if (Objects.isNull(cellVal) || cellVal.isBlank()) {
60+
if (Strings.isBlank(cellVal)) {
6261
LOGGER.warn("Row[#] {} - Cell[ref] formatted value is empty : {} - {}", currentRow, cellRef, cellVal);
6362
return;
6463
}

src/main/java/io/github/millij/poi/ss/model/annotations/SheetColumn.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@
4040

4141

4242
/**
43-
* Data presentation format of the Data cell.
43+
* Data presentation format of the Data Column.
4444
*
4545
* @return Data format String.
4646
*/
4747
String format() default "";
4848

4949
/**
50-
* DateTime Type
50+
* DateTimeType value of the Column
5151
*
52-
* @return
52+
* @return the {@link DateTimeType} value of the Column
5353
*/
5454
DateTimeType datetime() default DateTimeType.NONE;
5555

src/main/java/io/github/millij/poi/ss/reader/XlsReader.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ protected void processSheet(final HSSFSheet sheet, final RowListener<Map<String,
179179
}
180180

181181
final Map<String, Object> rowDataMap = this.extractRowDataAsMap(row);
182-
if (rowDataMap == null || rowDataMap.isEmpty()) {
182+
if (Objects.isNull(rowDataMap) || rowDataMap.isEmpty()) {
183183
continue;
184184
}
185185

@@ -209,7 +209,7 @@ protected <T> void processSheet(final Class<T> beanClz, final HSSFSheet sheet, f
209209
}
210210

211211
final Map<String, Object> rowDataMap = this.extractRowDataAsMap(row);
212-
if (rowDataMap == null || rowDataMap.isEmpty()) {
212+
if (Objects.isNull(rowDataMap) || rowDataMap.isEmpty()) {
213213
continue;
214214
}
215215

src/main/java/io/github/millij/poi/ss/writer/AbstractSpreadsheetWriter.java

+69-7
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import io.github.millij.poi.ss.model.Column;
2323
import io.github.millij.poi.util.Spreadsheet;
24+
import io.github.millij.poi.util.Strings;
2425

2526

2627
/**
@@ -51,14 +52,14 @@ public AbstractSpreadsheetWriter(final Workbook workbook) {
5152
// ------------------------------------------------------------------------
5253

5354

54-
// Sheet :: Add
55+
// Sheet :: Bean
5556

5657
@Override
5758
public <T> void addSheet(final Class<T> beanType, final List<T> rowObjects, final String inSheetName,
5859
final List<String> inHeaders) {
5960
// Sanity checks
6061
if (Objects.isNull(beanType)) {
61-
throw new IllegalArgumentException("AbstractSpreadsheetWriter :: Bean Type is NULL");
62+
throw new IllegalArgumentException("#addSheet :: Bean Type is NULL");
6263
}
6364

6465
// Sheet config
@@ -77,7 +78,7 @@ public <T> void addSheet(final Class<T> beanType, final List<T> rowObjects, fina
7778
}
7879

7980
// Create sheet
80-
final Sheet sheet = Objects.isNull(sheetName) || sheetName.isBlank() //
81+
final Sheet sheet = Strings.isBlank(sheetName) //
8182
? workbook.createSheet() //
8283
: workbook.createSheet(sheetName);
8384
LOGGER.debug("Added new Sheet[name] to the workbook : {}", sheet.getSheetName());
@@ -110,18 +111,79 @@ public <T> void addSheet(final Class<T> beanType, final List<T> rowObjects, fina
110111
}
111112

112113

113-
// Sheet :: Append to existing
114+
// Sheet :: Map<String, Object>
115+
116+
@Override
117+
public void addSheet(final List<Map<String, Object>> rowsData, final String inSheetName,
118+
final List<String> inHeaders) {
119+
// Sanity check
120+
if (Objects.isNull(rowsData)) {
121+
throw new IllegalArgumentException("#addSheet :: Rows data map is NULL");
122+
}
123+
if (Objects.isNull(inHeaders) || inHeaders.isEmpty()) {
124+
throw new IllegalArgumentException("#addSheet :: Headers list is NULL or EMPTY");
125+
}
126+
127+
try {
128+
final Sheet exSheet = workbook.getSheet(inSheetName);
129+
if (Objects.nonNull(exSheet)) {
130+
String errMsg = String.format("A Sheet with the passed name already exists : %s", inSheetName);
131+
throw new IllegalArgumentException(errMsg);
132+
}
133+
134+
// Create sheet
135+
final Sheet sheet = Strings.isBlank(inSheetName) //
136+
? workbook.createSheet() //
137+
: workbook.createSheet(inSheetName);
138+
LOGGER.debug("Added new Sheet[name] to the workbook : {}", sheet.getSheetName());
139+
140+
// Header
141+
final Row headerRow = sheet.createRow(0);
142+
for (int cellNum = 0; cellNum < inHeaders.size(); cellNum++) {
143+
final Cell cell = headerRow.createCell(cellNum);
144+
cell.setCellValue(inHeaders.get(cellNum));
145+
}
146+
147+
// Data Rows
148+
for (int i = 0, rowNum = 1; i < rowsData.size(); i++, rowNum++) {
149+
final Row row = sheet.createRow(rowNum);
150+
final Map<String, Object> rowData = rowsData.get(i);
151+
if (Objects.isNull(rowData) || rowData.isEmpty()) {
152+
continue; // Skip if row is null
153+
}
154+
155+
for (int cellNum = 0; cellNum < inHeaders.size(); cellNum++) {
156+
final String key = inHeaders.get(cellNum);
157+
final Object value = rowData.get(key);
158+
159+
final Cell cell = row.createCell(cellNum);
160+
if (Objects.nonNull(value)) {
161+
cell.setCellValue(String.valueOf(value));
162+
}
163+
}
164+
}
165+
} catch (Exception ex) {
166+
String errMsg = String.format("Error while preparing sheet with passed row objects : %s", ex.getMessage());
167+
LOGGER.error(errMsg, ex);
168+
}
169+
}
114170

115171

116172
// Write
117173

118174
@Override
119-
public void write(final String filepath) throws IOException {
120-
try (final OutputStream outputStrem = new FileOutputStream(new File(filepath))) {
175+
public void write(final File file) throws IOException {
176+
// Sanity checks
177+
if (Objects.isNull(file)) {
178+
throw new IllegalArgumentException("#write :: Input File object is NULL");
179+
}
180+
181+
try (final OutputStream outputStrem = new FileOutputStream(file)) {
121182
workbook.write(outputStrem);
122183
workbook.close();
184+
123185
} catch (Exception ex) {
124-
final String errMsg = String.format("Failed to write workbook data to file : %s", filepath);
186+
final String errMsg = String.format("Failed to write workbook data to file : %s", file.getPath());
125187
LOGGER.error(errMsg);
126188
throw ex;
127189
}

0 commit comments

Comments
 (0)