Skip to content

Commit ecec69a

Browse files
authored
Release 0.1.0 (#72)
* chore: remove unused imports * refactor: Rename Exporter classes 변경된 클래스 목록: - SXSSFExporter to AbstractExcelExporter - DefaultExcelExporter to SXSSFExporter - DefaultExcelExporterBuilder to SXSSFExporterBuilder * chore: release 0.1.0으로 수정
1 parent b12ced9 commit ecec69a

File tree

9 files changed

+352
-353
lines changed

9 files changed

+352
-353
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ List<Product> products = Arrays.asList(
105105
);
106106

107107
// 3. Export to Excel
108-
DefaultExcelExporter<Product> exporter = DefaultExcelExporter.builder(Product.class, products)
108+
SXSSFExporter<Product> exporter = SXSSFExporter.builder(Product.class, products)
109109
.sheetStrategy(SheetStrategy.MULTI_SHEET) // Optional, MULTI_SHEET is default
110110
.maxRows(100) // Optional, Max row of SpreadsheetVersion.EXCEL2007 is default
111111
.sheetName("Products") // Optional, if not specified sheets will be named Sheet0, Sheet1, etc.

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ plugins {
1111
}
1212

1313
group = 'io.github.hee9841.excel'
14-
version = '0.0.4'
14+
version = '0.1.0'
1515

1616
repositories {
1717
mavenCentral()

src/main/java/io/github/hee9841/excel/annotation/Excel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
*
4242
* // Usage example:
4343
* List{@literal <}UserData{@literal >} users = getUserData();
44-
* DefaultExcelExporter{@literal <}UserData{@literal >} exporter = DefaultExcelExporter.builder(UserData.class, users)
44+
* SXSSFExporter{@literal <}UserData{@literal >} exporter = SXSSFExporter.builder(UserData.class, users)
4545
* .sheetName("Users")
4646
* .build();
4747
* exporter.write(new FileOutputStream("users.xlsx"));
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package io.github.hee9841.excel.core.exporter;
2+
3+
import io.github.hee9841.excel.core.meta.ColumnInfo;
4+
import io.github.hee9841.excel.core.meta.ColumnInfoMapper;
5+
import io.github.hee9841.excel.exception.ExcelException;
6+
import java.io.IOException;
7+
import java.io.OutputStream;
8+
import java.lang.reflect.Field;
9+
import java.util.List;
10+
import java.util.Map;
11+
import org.apache.commons.lang3.reflect.FieldUtils;
12+
import org.apache.poi.ss.SpreadsheetVersion;
13+
import org.apache.poi.ss.usermodel.Cell;
14+
import org.apache.poi.ss.usermodel.Row;
15+
import org.apache.poi.ss.usermodel.Sheet;
16+
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
17+
import org.slf4j.Logger;
18+
import org.slf4j.LoggerFactory;
19+
20+
/**
21+
* Abstract base class for Excel file operations using Apache POI's SXSSF (Streaming XML Spreadsheet
22+
* Format).
23+
* This class provides the core functionality for handling Excel files with streaming support for
24+
* large datasets.
25+
*
26+
* <p>Key features:</p>
27+
* <ul>
28+
* <li>Uses SXSSFWorkbook for memory-efficient handling of large Excel files</li>
29+
* <li>Supports Excel 2007+ format (XLSX)</li>
30+
* <li>Provides column mapping and header generation</li>
31+
* <li>Handles cell styling and data type conversion</li>
32+
* </ul>
33+
*
34+
* <p>This class implements the core functionality while leaving sheet management strategies
35+
* to be implemented by concrete subclasses.</p>
36+
*
37+
* @param <T> The type of data to be handled in the Excel file
38+
*/
39+
public abstract class AbstractExcelExporter<T> implements ExcelExporter<T> {
40+
41+
protected static final Logger logger = LoggerFactory.getLogger(AbstractExcelExporter.class);
42+
43+
protected static final SpreadsheetVersion supplyExcelVersion = SpreadsheetVersion.EXCEL2007;
44+
45+
protected SXSSFWorkbook workbook;
46+
protected Map<Integer, ColumnInfo> columnsMappingInfo;
47+
48+
protected String dtoTypeName;
49+
50+
/**
51+
* Constructs a new AbstractExcelExporter with a new SXSSFWorkbook instance.
52+
*/
53+
protected AbstractExcelExporter() {
54+
this.workbook = new SXSSFWorkbook();
55+
}
56+
57+
/**
58+
* Initializes the Excel file with the specified type and data.
59+
* This method performs validation and sets up column mapping information.
60+
*
61+
* @param type The class type of the data to be exported
62+
* @param data The list of data objects to be exported
63+
*/
64+
protected void initialize(Class<?> type, List<T> data) {
65+
this.dtoTypeName = type.getName();
66+
logger.info("Initializing Excel file for DTO: {}.java.", dtoTypeName);
67+
68+
validate(type, data);
69+
70+
logger.debug("Mapping DTO to Excel data - DTO class({}).", dtoTypeName);
71+
//Map DTO to Excel data
72+
this.columnsMappingInfo = ColumnInfoMapper.of(type, workbook).map();
73+
}
74+
75+
76+
/**
77+
* Creates headers using the column mapping information.
78+
*
79+
* @param sheet The sheet to add headers to
80+
* @param headerRowIndex The headers row index
81+
*/
82+
protected void createHeader(Sheet sheet, Integer headerRowIndex) {
83+
Row row = sheet.createRow(headerRowIndex);
84+
for (Integer colIndex : columnsMappingInfo.keySet()) {
85+
ColumnInfo columnMappingInfo = columnsMappingInfo.get(colIndex);
86+
Cell cell = row.createCell(colIndex);
87+
cell.setCellValue(columnMappingInfo.getHeaderName());
88+
cell.setCellStyle(columnMappingInfo.getHeaderStyle());
89+
}
90+
}
91+
92+
/**
93+
* Creates a new sheet with headers.
94+
*
95+
* <p>This method resets the current row index, creates a new sheet, and adds headers to it.
96+
* If a sheet name is provided, it will be used as a base name with an index(index starts from
97+
* 0) suffix.</p>
98+
*/
99+
protected Sheet createNewSheet(String sheetName, int sheetIndex) {
100+
//If sheet name is provided, create sheet with sheet name + idx
101+
final String finalSheetName = (sheetName != null)
102+
? String.format("%s(%d)", sheetName, sheetIndex)
103+
: null;
104+
105+
106+
Sheet sheet = (finalSheetName != null)
107+
? workbook.createSheet(finalSheetName)
108+
: workbook.createSheet();
109+
110+
logger.debug("Create new Sheet : {}.", sheet.getSheetName());
111+
112+
return sheet;
113+
}
114+
115+
/**
116+
* Creates a row in the Excel sheet for the given data object.
117+
* This method handles field access and cell value setting based on column mapping information.
118+
*
119+
* @param sheet The Sheet object to create a row.
120+
* @param data The data object for rendering data to cell
121+
* @param rowIndex The index of the row to create
122+
* @throws ExcelException if field access fails
123+
*/
124+
protected void createBody(Sheet sheet, Object data, int rowIndex) {
125+
logger.debug("Add rows data - row:{}.", rowIndex);
126+
Row row = sheet.createRow(rowIndex);
127+
for (Integer colIndex : columnsMappingInfo.keySet()) {
128+
ColumnInfo columnInfo = columnsMappingInfo.get(colIndex);
129+
try {
130+
Field field = FieldUtils.getField(data.getClass(), columnInfo.getFieldName(), true);
131+
Cell cell = row.createCell(colIndex);
132+
//Set cell value by cell type
133+
columnInfo.getColumnType().setCellValueByCellType(cell, field.get(data));
134+
//Set cell style
135+
cell.setCellStyle(columnInfo.getBodyStyle());
136+
} catch (IllegalAccessException e) {
137+
throw new ExcelException(
138+
String.format("Failed to create body(column:%d, row:%d) : "
139+
+ "Access to field %s failed.",
140+
colIndex, rowIndex, columnInfo.getFieldName()), e);
141+
}
142+
}
143+
}
144+
145+
/**
146+
* Writes the Excel file content to the specified output stream.
147+
* This method ensures proper resource cleanup using try-with-resources.
148+
*
149+
* @param stream The output stream to write the Excel file to
150+
* @throws IOException if an I/O error occurs during writing
151+
*/
152+
@Override
153+
public final void write(OutputStream stream) throws IOException {
154+
if (stream == null) {
155+
throw new ExcelException("Output stream is null.");
156+
}
157+
logger.info("Start to write Excel file for DTO class({}.java).", dtoTypeName);
158+
159+
try (SXSSFWorkbook autoCloseableWb = this.workbook) {
160+
autoCloseableWb.write(stream);
161+
logger.info("Successfully wrote Excel file for DTO class({}.java).", dtoTypeName);
162+
}
163+
}
164+
165+
/**
166+
* Validates the provided data and type.
167+
* This method can be overridden by subclasses to add custom validation logic.
168+
*
169+
* @param type The class of the data type
170+
* @param data The list of data objects to be exported
171+
*/
172+
protected abstract void validate(Class<?> type, List<T> data);
173+
174+
/**
175+
* Creates the Excel file with the provided data.
176+
* This method must be implemented by subclasses to define their specific sheet management
177+
* strategy.
178+
*
179+
* @param data The list of data objects to be exported
180+
*/
181+
protected abstract void createExcel(List<T> data);
182+
183+
}

0 commit comments

Comments
 (0)