Skip to content

Commit 1117f75

Browse files
authored
Merge pull request #57 from millij/writer-xlsx
Spreadsheet Writer API and Implementation
2 parents 728277d + ab300c0 commit 1117f75

File tree

11 files changed

+508
-253
lines changed

11 files changed

+508
-253
lines changed

src/main/java/io/github/millij/poi/ss/model/Column.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ public class Column implements Comparable<Column> {
2626

2727
public Column() {
2828
super();
29-
// init
3029
}
3130

3231
public Column(String name) {
@@ -43,8 +42,12 @@ public Column(String name) {
4342
// Comparable
4443

4544
@Override
46-
public int compareTo(Column o) {
47-
return Objects.isNull(o) ? 1 : Integer.compare(this.order, o.order);
45+
public int compareTo(final Column o) {
46+
if (Objects.isNull(o) || Objects.isNull(o.getOrder())) {
47+
return 1;
48+
}
49+
50+
return Objects.isNull(this.getOrder()) ? -1 : Integer.compare(this.getOrder(), o.getOrder());
4851
}
4952

5053

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ private Map<String, String> asHeaderNameToCellRefMap(final HSSFRow headerRow) {
155155

156156
final Map<String, String> headerCellRefs = new HashMap<>();
157157

158-
Iterator<Cell> cells = headerRow.cellIterator();
158+
final Iterator<Cell> cells = headerRow.cellIterator();
159159
while (cells.hasNext()) {
160160
final HSSFCell cell = (HSSFCell) cells.next();
161161
final int cellColIdx = cell.getColumnIndex();
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package io.github.millij.poi.ss.writer;
2+
3+
import java.io.File;
4+
import java.io.FileOutputStream;
5+
import java.io.IOException;
6+
import java.io.OutputStream;
7+
import java.util.ArrayList;
8+
import java.util.Collections;
9+
import java.util.LinkedHashMap;
10+
import java.util.List;
11+
import java.util.Map;
12+
import java.util.Objects;
13+
import java.util.stream.Collectors;
14+
15+
import org.apache.poi.ss.usermodel.Cell;
16+
import org.apache.poi.ss.usermodel.Row;
17+
import org.apache.poi.ss.usermodel.Sheet;
18+
import org.apache.poi.ss.usermodel.Workbook;
19+
import org.slf4j.Logger;
20+
import org.slf4j.LoggerFactory;
21+
22+
import io.github.millij.poi.ss.model.Column;
23+
import io.github.millij.poi.util.Spreadsheet;
24+
25+
26+
/**
27+
* Abstract Implementation of {@link SpreadsheetWriter}
28+
*
29+
* @since 3.0
30+
*/
31+
abstract class AbstractSpreadsheetWriter implements SpreadsheetWriter {
32+
33+
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSpreadsheetWriter.class);
34+
35+
36+
protected final Workbook workbook;
37+
38+
39+
// Constructors
40+
// ------------------------------------------------------------------------
41+
42+
public AbstractSpreadsheetWriter(final Workbook workbook) {
43+
super();
44+
45+
// init
46+
this.workbook = workbook;
47+
}
48+
49+
50+
// Methods
51+
// ------------------------------------------------------------------------
52+
53+
54+
// Sheet :: Add
55+
56+
@Override
57+
public <T> void addSheet(final Class<T> beanType, final List<T> rowObjects, final String inSheetName,
58+
final List<String> inHeaders) {
59+
// Sanity checks
60+
if (Objects.isNull(beanType)) {
61+
throw new IllegalArgumentException("AbstractSpreadsheetWriter :: Bean Type is NULL");
62+
}
63+
64+
// Sheet config
65+
final String defaultSheetName = Spreadsheet.getSheetName(beanType);
66+
final List<String> defaultHeaders = this.getColumnNames(beanType);
67+
68+
// output config
69+
final String sheetName = Objects.isNull(inSheetName) ? defaultSheetName : inSheetName;
70+
final List<String> headers = Objects.isNull(inHeaders) || inHeaders.isEmpty() ? defaultHeaders : inHeaders;
71+
72+
try {
73+
final Sheet exSheet = workbook.getSheet(sheetName);
74+
if (Objects.nonNull(exSheet)) {
75+
String errMsg = String.format("A Sheet with the passed name already exists : %s", sheetName);
76+
throw new IllegalArgumentException(errMsg);
77+
}
78+
79+
// Create sheet
80+
final Sheet sheet = Objects.isNull(sheetName) || sheetName.isBlank() //
81+
? workbook.createSheet() //
82+
: workbook.createSheet(sheetName);
83+
LOGGER.debug("Added new Sheet[name] to the workbook : {}", sheet.getSheetName());
84+
85+
// Header
86+
final Row headerRow = sheet.createRow(0);
87+
for (int i = 0; i < headers.size(); i++) {
88+
Cell cell = headerRow.createCell(i);
89+
cell.setCellValue(headers.get(i));
90+
}
91+
92+
// Data Rows
93+
final Map<String, List<String>> rowsData = this.prepareSheetRowsData(headers, rowObjects);
94+
for (int i = 0, rowNum = 1; i < rowObjects.size(); i++, rowNum++) {
95+
final Row row = sheet.createRow(rowNum);
96+
97+
int cellNo = 0;
98+
for (String key : rowsData.keySet()) {
99+
Cell cell = row.createCell(cellNo);
100+
String value = rowsData.get(key).get(i);
101+
cell.setCellValue(value);
102+
cellNo++;
103+
}
104+
}
105+
106+
} catch (Exception ex) {
107+
String errMsg = String.format("Error while preparing sheet with passed row objects : %s", ex.getMessage());
108+
LOGGER.error(errMsg, ex);
109+
}
110+
}
111+
112+
113+
// Sheet :: Append to existing
114+
115+
116+
// Write
117+
118+
@Override
119+
public void write(final String filepath) throws IOException {
120+
try (final OutputStream outputStrem = new FileOutputStream(new File(filepath))) {
121+
workbook.write(outputStrem);
122+
workbook.close();
123+
} catch (Exception ex) {
124+
final String errMsg = String.format("Failed to write workbook data to file : %s", filepath);
125+
LOGGER.error(errMsg);
126+
throw ex;
127+
}
128+
}
129+
130+
131+
// Private Methods
132+
// ------------------------------------------------------------------------
133+
134+
private <T> Map<String, List<String>> prepareSheetRowsData(List<String> headers, List<T> rowObjects)
135+
throws Exception {
136+
// Sheet data
137+
final Map<String, List<String>> sheetData = new LinkedHashMap<>();
138+
139+
// Iterate over Objects
140+
for (final T rowObj : rowObjects) {
141+
final Map<String, String> row = Spreadsheet.asRowDataMap(rowObj, headers);
142+
for (final String header : headers) {
143+
final List<String> data = sheetData.getOrDefault(header, new ArrayList<>());
144+
final String value = row.getOrDefault(header, "");
145+
146+
data.add(value);
147+
sheetData.put(header, data);
148+
}
149+
}
150+
151+
return sheetData;
152+
}
153+
154+
private List<String> getColumnNames(Class<?> beanType) {
155+
// Bean Property to Column Mapping
156+
final Map<String, Column> propToColumnMap = Spreadsheet.getPropertyToColumnDefMap(beanType);
157+
final List<Column> colums = new ArrayList<>(propToColumnMap.values());
158+
Collections.sort(colums);
159+
160+
final List<String> columnNames = colums.stream().map(Column::getName).collect(Collectors.toList());
161+
return columnNames;
162+
}
163+
164+
165+
}

0 commit comments

Comments
 (0)