Skip to content

Commit 484837b

Browse files
Merge pull request #18950 from programenth/swagger-tag
BAEL-7214 | Adding Apache POI HSSFWorkbook code
2 parents 18e0d75 + 41a027c commit 484837b

File tree

7 files changed

+347
-1
lines changed

7 files changed

+347
-1
lines changed

apache-poi-3/pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
</parent>
1515

1616
<dependencies>
17+
<dependency>
18+
<groupId>org.springframework.boot</groupId>
19+
<artifactId>spring-boot-starter-web</artifactId>
20+
<version>${spring.web.version}</version>
21+
</dependency>
1722
<dependency>
1823
<groupId>org.apache.poi</groupId>
1924
<artifactId>poi-ooxml</artifactId>
@@ -108,6 +113,7 @@
108113
<logback-core.version>1.5.6</logback-core.version>
109114
<jmh.version>1.37</jmh.version>
110115
<log4j.version>2.23.1</log4j.version>
116+
<spring.web.version>3.5.7</spring.web.version>
111117
</properties>
112118

113-
</project>
119+
</project>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.baeldung.hssfworkbook;
2+
3+
import java.io.IOException;
4+
5+
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
6+
import org.springframework.boot.SpringApplication;
7+
import org.springframework.boot.autoconfigure.SpringBootApplication;
8+
9+
@SpringBootApplication
10+
public class DemoApplication {
11+
12+
public static void main(String[] args) throws IOException {
13+
SpringApplication.run(DemoApplication.class, args);
14+
}
15+
16+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.baeldung.hssfworkbook;
2+
3+
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
4+
import org.apache.poi.ss.usermodel.Sheet;
5+
import org.springframework.http.HttpHeaders;
6+
import org.springframework.http.MediaType;
7+
import org.springframework.http.ResponseEntity;
8+
import org.springframework.web.bind.annotation.GetMapping;
9+
import org.springframework.web.bind.annotation.PostMapping;
10+
import org.springframework.web.bind.annotation.RequestParam;
11+
import org.springframework.web.bind.annotation.RestController;
12+
import org.springframework.web.multipart.MultipartFile;
13+
14+
import java.io.ByteArrayOutputStream;
15+
import java.io.IOException;
16+
17+
@RestController
18+
public class ExcelController {
19+
20+
@GetMapping("/download-excel")
21+
public ResponseEntity<byte[]> downloadExcel() {
22+
try {
23+
HSSFWorkbook workbook = ExcelCreator.createSampleWorkbook();
24+
25+
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
26+
workbook.write(baos);
27+
byte[] bytes = baos.toByteArray();
28+
29+
return ResponseEntity.ok()
30+
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=employee_data.xls")
31+
.contentType(MediaType.parseMediaType("application/vnd.ms-excel")) // More specific MIME type
32+
.body(bytes);
33+
}
34+
} catch (IOException e) {
35+
System.err.println("Error generating or writing Excel workbook: " + e.getMessage());
36+
return ResponseEntity.internalServerError()
37+
.build();
38+
}
39+
}
40+
41+
@PostMapping("/upload-excel")
42+
public ResponseEntity<String> uploadExcel(@RequestParam("file") MultipartFile file) {
43+
if (file.isEmpty()) {
44+
return ResponseEntity.badRequest()
45+
.body("File is empty. Please upload a file.");
46+
}
47+
48+
try {
49+
try (HSSFWorkbook workbook = new HSSFWorkbook(file.getInputStream())) {
50+
Sheet sheet = workbook.getSheetAt(0);
51+
52+
return ResponseEntity.ok("Sheet '" + sheet.getSheetName() + "' uploaded successfully!");
53+
}
54+
} catch (IOException e) {
55+
System.err.println("Error processing uploaded Excel file: " + e.getMessage());
56+
return ResponseEntity.internalServerError()
57+
.body("Failed to process the Excel file.");
58+
} catch (Exception e) {
59+
System.err.println("An unexpected error occurred during file upload: " + e.getMessage());
60+
return ResponseEntity.internalServerError()
61+
.body("An unexpected error occurred.");
62+
}
63+
}
64+
65+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.baeldung.hssfworkbook;
2+
3+
import java.io.ByteArrayInputStream;
4+
import java.io.ByteArrayOutputStream;
5+
import java.io.IOException;
6+
7+
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
8+
9+
public class ExcelConverter {
10+
11+
public static byte[] convertWorkbookToBytes(HSSFWorkbook workbook) throws IOException {
12+
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
13+
workbook.write(baos);
14+
return baos.toByteArray();
15+
}
16+
}
17+
18+
public static HSSFWorkbook convertBytesToWorkbook(byte[] excelBytes) throws IOException {
19+
try (ByteArrayInputStream bais = new ByteArrayInputStream(excelBytes)) {
20+
return new HSSFWorkbook(bais);
21+
}
22+
}
23+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.baeldung.hssfworkbook;
2+
3+
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
4+
import org.apache.poi.hssf.usermodel.HSSFFont;
5+
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
6+
import org.apache.poi.ss.usermodel.Cell;
7+
import org.apache.poi.ss.usermodel.Row;
8+
import org.apache.poi.ss.usermodel.Sheet;
9+
10+
public class ExcelCreator {
11+
12+
public static HSSFWorkbook createSampleWorkbook() {
13+
HSSFWorkbook workbook = new HSSFWorkbook();
14+
15+
final String SHEET_NAME = "Employees";
16+
final String[] COLUMN_HEADERS = { "ID", "Name", "Department" };
17+
Object[][] data = { { 101, "John Doe", "Finance" }, { 102, "Jane Smith", "HR" }, { 103, "Michael Clark", "IT" } };
18+
19+
Sheet sheet = workbook.createSheet(SHEET_NAME);
20+
21+
HSSFFont font = workbook.createFont();
22+
font.setBold(true);
23+
HSSFCellStyle headerStyle = workbook.createCellStyle();
24+
headerStyle.setFont(font);
25+
26+
Row header = sheet.createRow(0);
27+
for (int i = 0; i < COLUMN_HEADERS.length; i++) {
28+
Cell cell = header.createCell(i);
29+
cell.setCellValue(COLUMN_HEADERS[i]);
30+
cell.setCellStyle(headerStyle);
31+
}
32+
33+
int rowNum = 1;
34+
for (Object[] rowData : data) {
35+
Row row = sheet.createRow(rowNum++);
36+
for (int i = 0; i < rowData.length; i++) {
37+
Cell cell = row.createCell(i);
38+
Object value = rowData[i];
39+
40+
if (value instanceof Integer) {
41+
cell.setCellValue(((Integer) value).doubleValue());
42+
} else if (value instanceof Double) {
43+
cell.setCellValue((Double) value);
44+
} else if (value != null) {
45+
cell.setCellValue(value.toString());
46+
}
47+
}
48+
}
49+
50+
for (int i = 0; i < COLUMN_HEADERS.length; i++) {
51+
sheet.autoSizeColumn(i);
52+
}
53+
54+
return workbook;
55+
}
56+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.baeldung.hssfworkbook;
2+
3+
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
4+
import org.apache.poi.ss.usermodel.Sheet;
5+
import org.junit.jupiter.api.DisplayName;
6+
import org.junit.jupiter.api.Test;
7+
8+
import java.io.ByteArrayOutputStream;
9+
import java.io.IOException;
10+
import java.io.UncheckedIOException;
11+
12+
import com.baeldung.hssfworkbook.ExcelConverter;
13+
14+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
15+
import static org.junit.jupiter.api.Assertions.assertNotNull;
16+
import static org.junit.jupiter.api.Assertions.assertThrows;
17+
import static org.junit.jupiter.api.Assertions.assertTrue;
18+
import static org.junit.jupiter.api.Assertions.assertEquals;
19+
20+
class ExcelConverterTest {
21+
22+
private HSSFWorkbook createMinimalWorkbook() {
23+
HSSFWorkbook workbook = new HSSFWorkbook();
24+
Sheet sheet = workbook.createSheet("TestSheet");
25+
sheet.createRow(0)
26+
.createCell(0)
27+
.setCellValue("Test Data");
28+
return workbook;
29+
}
30+
31+
private byte[] convertWorkbookToBytesSafely(HSSFWorkbook workbook) {
32+
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
33+
workbook.write(baos);
34+
return baos.toByteArray();
35+
} catch (IOException e) {
36+
throw new UncheckedIOException("Failed to create test bytes.", e);
37+
}
38+
}
39+
40+
@Test
41+
@DisplayName("GivenAValidHSSFWorkbook_whenConvertingToBytes_thenByteArrayIsNonEmptyAndValid")
42+
void givenAValidHSSFWorkbook_whenConvertingToBytes_thenByteArrayIsNonEmptyAndValid() throws IOException {
43+
HSSFWorkbook workbook = createMinimalWorkbook();
44+
45+
byte[] resultBytes = ExcelConverter.convertWorkbookToBytes(workbook);
46+
47+
assertNotNull(resultBytes, "The byte array should not be null.");
48+
assertTrue(resultBytes.length > 0, "The byte array should not be empty.");
49+
50+
HSSFWorkbook convertedWorkbook = ExcelConverter.convertBytesToWorkbook(resultBytes);
51+
assertEquals("TestSheet", convertedWorkbook.getSheetName(0));
52+
}
53+
54+
@Test
55+
@DisplayName("GivenAValidExcelByteArray_whenConvertingToWorkbook_thenHSSFWorkbookIsReturned")
56+
void givenAValidExcelByteArray_whenConvertingToWorkbook_thenHSSFWorkbookIsReturned() throws IOException {
57+
HSSFWorkbook originalWorkbook = createMinimalWorkbook();
58+
byte[] validExcelBytes = convertWorkbookToBytesSafely(originalWorkbook);
59+
60+
HSSFWorkbook resultWorkbook = ExcelConverter.convertBytesToWorkbook(validExcelBytes);
61+
62+
assertNotNull(resultWorkbook, "The resulting workbook should not be null.");
63+
assertEquals(1, resultWorkbook.getNumberOfSheets(), "The resulting workbook should have 1 sheet.");
64+
assertEquals("TestSheet", resultWorkbook.getSheetName(0), "Sheet name should match the original.");
65+
assertEquals("Test Data", resultWorkbook.getSheetAt(0)
66+
.getRow(0)
67+
.getCell(0)
68+
.getStringCellValue());
69+
}
70+
71+
@Test
72+
@DisplayName("GivenAnEmptyByteArray_whenConvertingToWorkbook_thenIOExceptionIsThrown")
73+
void givenAnEmptyByteArray_whenConvertingToWorkbook_thenIOExceptionIsThrown() {
74+
byte[] emptyBytes = new byte[0];
75+
76+
assertThrows(IOException.class, () -> ExcelConverter.convertBytesToWorkbook(emptyBytes), "Expected IOException for empty byte array.");
77+
}
78+
79+
@Test
80+
@DisplayName("GivenAnInvalidByteArray_whenConvertingToWorkbook_thenIOExceptionIsThrown")
81+
void givenAnInvalidByteArray_whenConvertingToWorkbook_thenIOExceptionIsThrown() {
82+
byte[] invalidBytes = { 0x01, 0x02, 0x03, 0x04, 0x05 };
83+
84+
assertThrows(IOException.class, () -> ExcelConverter.convertBytesToWorkbook(invalidBytes), "Expected IOException for invalid byte array format.");
85+
}
86+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package com.baeldung.hssfworkbook;
2+
3+
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
4+
import org.apache.poi.ss.usermodel.Cell;
5+
import org.apache.poi.ss.usermodel.CellStyle;
6+
import org.apache.poi.ss.usermodel.CellType;
7+
import org.apache.poi.ss.usermodel.Font;
8+
import org.apache.poi.ss.usermodel.Row;
9+
import org.apache.poi.ss.usermodel.Sheet;
10+
import org.junit.jupiter.api.DisplayName;
11+
import org.junit.jupiter.api.Test;
12+
13+
import com.baeldung.hssfworkbook.ExcelCreator;
14+
15+
import static org.junit.jupiter.api.Assertions.assertEquals;
16+
import static org.junit.jupiter.api.Assertions.assertNotNull;
17+
import static org.junit.jupiter.api.Assertions.assertTrue;
18+
19+
class ExcelCreatorTest {
20+
21+
private static final String SHEET_NAME = "Employees";
22+
private static final String[] COLUMN_HEADERS = { "ID", "Name", "Department" };
23+
private static final Object[][] DATA = { { 101, "John Doe", "Finance" }, { 102, "Jane Smith", "HR" }, { 103, "Michael Clark", "IT" } };
24+
25+
@Test
26+
@DisplayName("Workbook should be created and contain one sheet named 'Employees'")
27+
void givenExcelCreator_whenCreateSampleWorkbookCalled_thenWorkbookContainsOneSheetNamedEmployees() {
28+
HSSFWorkbook workbook = ExcelCreator.createSampleWorkbook();
29+
30+
assertNotNull(workbook, "The workbook should not be null.");
31+
assertEquals(1, workbook.getNumberOfSheets(), "The workbook should contain exactly one sheet.");
32+
33+
Sheet sheet = workbook.getSheet(SHEET_NAME);
34+
assertNotNull(sheet, "The sheet named '" + SHEET_NAME + "' must exist.");
35+
}
36+
37+
@Test
38+
@DisplayName("Header row should have correct content and bold style")
39+
void givenExcelCreator_whenCreateSampleWorkbookCalled_thenHeaderRowContainsCorrectTextAndBoldStyle() {
40+
HSSFWorkbook workbook = ExcelCreator.createSampleWorkbook();
41+
Sheet sheet = workbook.getSheet(SHEET_NAME);
42+
43+
Row headerRow = sheet.getRow(0);
44+
assertNotNull(headerRow, "Header row (row 0) should exist.");
45+
46+
Font expectedFont = workbook.getFontAt(headerRow.getCell(0)
47+
.getCellStyle()
48+
.getFontIndex());
49+
assertTrue(expectedFont.getBold(), "Header font should be bold.");
50+
51+
for (int i = 0; i < COLUMN_HEADERS.length; i++) {
52+
Cell cell = headerRow.getCell(i);
53+
assertNotNull(cell, "Header cell at index " + i + " should exist.");
54+
assertEquals(COLUMN_HEADERS[i], cell.getStringCellValue(), "Header text mismatch at column " + i + ".");
55+
56+
CellStyle cellStyle = cell.getCellStyle();
57+
assertNotNull(cellStyle, "Header cell should have a style applied.");
58+
59+
Font actualFont = workbook.getFontAt(cellStyle.getFontIndex());
60+
assertTrue(actualFont.getBold(), "Header cell at index " + i + " style must be bold.");
61+
}
62+
}
63+
64+
@Test
65+
@DisplayName("Data rows should have correct content and data type handling")
66+
void givenExcelCreator_whenCreateSampleWorkbookCalled_thenDataRowsContainCorrectContentAndTypes() {
67+
HSSFWorkbook workbook = ExcelCreator.createSampleWorkbook();
68+
Sheet sheet = workbook.getSheet(SHEET_NAME);
69+
70+
assertEquals(DATA.length + 1, sheet.getLastRowNum() + 1, "The sheet should contain header row + data rows.");
71+
72+
for (int i = 0; i < DATA.length; i++) {
73+
Row dataRow = sheet.getRow(i + 1);
74+
Object[] expectedRowData = DATA[i];
75+
76+
assertNotNull(dataRow, "Data row at index " + (i + 1) + " should exist.");
77+
78+
for (int j = 0; j < expectedRowData.length; j++) {
79+
Cell cell = dataRow.getCell(j);
80+
Object expectedValue = expectedRowData[j];
81+
82+
assertNotNull(cell, "Cell [" + (i + 1) + ", " + j + "] should exist.");
83+
84+
if (expectedValue instanceof Integer) {
85+
assertEquals(CellType.NUMERIC, cell.getCellType(), "Cell " + j + " type should be NUMERIC for Integer.");
86+
assertEquals(((Integer) expectedValue).doubleValue(), cell.getNumericCellValue(), 0.001, "Numeric value mismatch.");
87+
} else {
88+
assertEquals(CellType.STRING, cell.getCellType(), "Cell " + j + " type should be STRING.");
89+
assertEquals(expectedValue.toString(), cell.getStringCellValue(), "String value mismatch.");
90+
}
91+
}
92+
}
93+
}
94+
}

0 commit comments

Comments
 (0)