[Apache POI] Apache POI 사용하기 에서 SXSSF
와 XSSF
의 차이를 설명했습니다. SXSSF
가 XSSF
의 향상된 버전이지만 읽기가 지원이 안되고, XSSF
는 읽기, 쓰기가 모두가능하지만 성능이슈 때문에 사실상 읽기만 가능합니다.
XSSF : 읽기, 쓰기가 가능하지만, 데이터 처리시 Memory Flush가 불가능.
SXSSF : 데이터 처리시 Memory를 flush할 수 있지만, 읽기가 불가능.
Template을 사용하려면 읽기가 가능해야 하기때문에 XSSF
를 사용해야하고, 데이터를 쓰려면 SXSSF
를 사용해야합니다.
위와 같은 Template을 만들어서 webapp/WEB-INF/template/
에 저장하겠습니다.
XSSF
로 Template을 불러오고 SXSSF
로 변환하여 반환해주는 메소드 getSxssfWorkbook()
을 만들어보겠습니다.
public SXSSFWorkbook getSxssfWorkbook(HttpServletRequest request, String templateName) throws IOException {
// 1. 템플릿을 받을 InputStream과, 반환해줄 SXSSFWorkbook을 생성한다.
InputStream inputStream = null;
SXSSFWorkbook sxssfWorkbook = null;
try {
// 2. template file의 경로를 찾아서 inputStream으로 받는다.
String templatePath = request.getSession().getServletContext().getRealPath("/WEB-INF/template/");
inputStream = new BufferedInputStream(new FileInputStream(templatePath + templateName));
// 3. 해당 InputStream(읽어온 Template)으로 XSSFWorkBook을 생성한다.
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(inputStream);
// 4. 생성한 XSSFWorkBook을 SXSSFWorkbook으로 변환한다.
sxssfWorkbook = new SXSSFWorkbook(xssfWorkbook, 10);
} catch(Exception e) {
// Exception 처리하세요.
} finally {
// 5. 사용한 Stream을 닫는다.
if(inputStream != null) inputStream.close();
}
return sxssfWorkbook;
}
- Template을 읽어올
InputStream
과, 반환해줄SXSSFWorkbook
을 생성합니다.XSSF
로 생성하지만 최종반환은SXSSF
를 합니다.
- Template 파일을 가져와서
InputStream
에 넣어줍니다.
- 가져온 Template으로
XSSFWorkbook
을 생성합니다.
XSSFWorkbook
를SXSSFWorkbook
으로 변환합니다.
Stream
을 닫아주고SXSSFWorkbook
를 반환합니다.
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.io.*;
@Controller
public class ExcelController {
@RequestMapping("download")
public void create(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// 1. Excel Workbook(파일)을 생성한다. (Template을 읽어온다)
SXSSFWorkbook workbook = getSxssfWorkbook(request, "sampleTemplate.xlsx");
// 2. Template에는 이미 Sheet가 존재하므로, Sheet Index로 데이터를 적용할 Sheet를 가져온다.
SXSSFSheet sheet = workbook.getSheetAt(0);
// 3. 생성된 Sheet에 Row를 만든다. 해당 Template에는 0번 Row가 있으므로 1번 Row부터 작성한다.
SXSSFRow row = sheet.createRow(1);
// 4. 생성된 Row에 cell을 만든다.
SXSSFCell cell = row.createCell(0);
// 5. 생성된 Cell에 값을 입력한다.
cell.setCellValue("value");
download(workbook, response);
}
public SXSSFWorkbook getSxssfWorkbook(HttpServletRequest request, String templateName) throws IOException {
// 1. 템플릿을 받을 InputStream과, 반환해줄 SXSSFWorkbook을 생성한다.
InputStream inputStream = null;
SXSSFWorkbook sxssfWorkbook = null;
try {
// 2. template file의 경로를 찾아서 inputStream으로 받는다.
String templatePath = request.getSession().getServletContext().getRealPath("/WEB-INF/template/");
inputStream = new BufferedInputStream(new FileInputStream(templatePath + templateName));
// 3. 해당 InputStream(읽어온 Template)으로 XSSFWorkBook을 생성한다.
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(inputStream);
// 4. 생성한 XSSFWorkBook을 SXSSFWorkbook으로 변환한다.
sxssfWorkbook = new SXSSFWorkbook(xssfWorkbook, 10);
} catch(Exception e) {
// Exception 처리하세요.
} finally {
// 5. 사용한 Stream을 닫는다.
if(inputStream != null) inputStream.close();
}
return sxssfWorkbook;
}
public void download(SXSSFWorkbook workbook, HttpServletResponse response) throws IOException {
// 1. OutputStream 생성
OutputStream outputStream = null;
try {
// 2. mime-type을 설정한다.
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
// 3. 파일명을 설정한다.
response.setHeader("Content-Disposition", "Attachment; Filename=sample.xlsx");
// 4. response의 OutputStream에 생성한 workbook을 write한다.
outputStream = new BufferedOutputStream(response.getOutputStream());
workbook.write(outputStream);
outputStream.flush();
} catch (Exception e) {
// Exception 처리하세요.
} finally {
// 5. 사용한 Stream을 닫는다.
if(outputStream != null) outputStream.close();
}
}
}