POI란
아파치 소프트웨어 재단에서 만든 라이브러리로
마이크로소프트 오피스 파일을 자바 언어로 읽고 쓰는 기능을 제공한다.
마이크로소프트의 excel 파일은 '.xls'와 '.xlsx'이 있다. 이 2개의 차이는
xls : EXCEL2003이전 형식
xlsx : EXCEL2007이전 형식
이다. 이 2개의 excel파일형식에 따라 poi lib도 2개가 존재한다.
이 글에서는 xlsx만 다루도록 하겠다.
pom.xml에 dependency를 추가하자. (나는 xlsx만 할 거기 때문에 poi-ooxml dependency만 추가하면 된다.
<!-- xls -->
<!--<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency> -->
<!-- xlsx-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.7</version>
</dependency>
POI의 주요 메소드 :
// 워크북 생성
XSSFWorkbook wb = new XSSFWorkbook(); //하나의 xlsx파일이다
// 시트 생성
Sheet sheet = wb.createSheet("시트명"); //하나의 excel sheet
// row(행) 순서 변수, cell(셀) 순서 변수
int rowCount = 0;
int cellCount = 0;
// row(행) 생성
Row row = sheet.createRow(rowCount++);
// cell(셀) 생성
Cell cell = row.createCell(cellCount++); //cell이 현재 행(row)의 열이라고 생각하자.
// cell(셀) 값 입력
cell.setCellValue('값');
간단한 excel Download
간단하게 임시데이터를 넣은 excel.xlsx 파일을 다운로드 받아보자.
1.freeList.jsp에 다음과 같이 a태그를 추가해보자.
<!-- 마지막 페이지 -->
<li><a href="freeList.wow?curPage=${paging.totalPageCount}" data-page="${paging.totalPageCount}"><span aria-hidden="true">»</span></a></li>
</ul>
</nav>
<!-- END : 페이지네이션 -->
<!--추가된부분-->
<div class="col-sm-2 col-sm-offset-10 text-right">
<a href="<c:url value='/free/excelDown' />" class="btn btn-sm btn-default" target="_blank" id="excelDown">excelDown</a>
</div>
<!--추가된부분-->
버튼을 누르면 해당 Controller로 요청을 하게 될 것이다.
2. @Controller 작성
Controller에서는 요청 처리하는 과정에서 excel을 처리하고 이 excel을 Response에 담으면 된다.
ExcelController.java
package com.study.excel.web;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class ExcelController {
@RequestMapping("/free/excelDown")
public void excelDownload(HttpServletResponse response) throws IOException{
XSSFWorkbook wb=null;
Sheet sheet=null;
Row row=null;
Cell cell=null;
wb = new XSSFWorkbook();
sheet = wb.createSheet("mysheet이름");
// row(행) 생성
row = sheet.createRow(0); //0번째 행
cell=row.createCell(0);
cell.setCellValue("0");
cell=row.createCell(1);
cell.setCellValue("가가가");
cell=row.createCell(2);
cell.setCellValue("나나나");
row = sheet.createRow(1); //1번째 행
cell=row.createCell(0);
cell.setCellValue("1");
cell=row.createCell(1);
cell.setCellValue("AAA");
cell=row.createCell(2);
cell.setCellValue("BBB");
row = sheet.createRow(2); //2번째 행
cell=row.createCell(0);
cell.setCellValue("2");
cell=row.createCell(1);
cell.setCellValue("aaa");
cell=row.createCell(2);
cell.setCellValue("bbb");
// 컨텐츠 타입과 파일명 지정
response.setContentType("ms-vnd/excel");
response.setHeader("Content-Disposition", "attachment;filename=example.xlsx"); //파일이름지정.
//response OutputStream에 엑셀 작성
wb.write(response.getOutputStream());
}
}
이제 버튼을 누르면 excel파일이 생성된다.
생성된 excel파일 내용.
게시판 List<VO>를 excel로 다운로드 하기
List<VO>를 excel로 다운로드 하는건
List<VO>를 가지고 반복문으로 Row와 Cell을 만들기만 하면 된다.
excel용으로 테이블을 조회할 servie,dao를 만들자.
(기존쿼리는 페이징을 적용해 1데이터를 10개만 가져온다)
나는 검색한 내용에 맞는 데이터만 엑셀로 만들려 하기 때문에 FreeBoardSearchVO를 파라미터로 넣는다.
ExcelServiceImpl.java (interface는 알아서만들자. 안만들어도 된다.)
package com.study.excel.service;
import java.util.List;
import javax.inject.Inject;
@Service
public class ExcelServiceImpl implements IExcelService{
@Inject
IExcelDao excelDao;
public List<FreeBoardVO> getBoardList(SearchVO searchVO, String searchCategory) {
return excelDao.getBoardList(searchVO,searchCategory);
}
}
IExcelDao.java
package com.study.excel.dao;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface IExcelDao {
public List<FreeBoardVO> getBoardList(@Param("search") SearchVO searchVO, @Param("searchCategory") String searchCategory);
}
excel.xml (검색어에 맞는 전체 데이터를 가지고 오도록 했다.)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.study.excel.dao.IExcelDao">
<select id="getBoardList" resultType="com.study.free.vo.FreeBoardVO" >
SELECT
to_char(bo_reg_date,'YYYY-MM-DD') AS bo_reg_date ,
to_char(bo_mod_date,'YYYY-MM-DD') AS bo_mod_date ,
bo_no , bo_title ,
bo_category ,
bo_writer , bo_pass , bo_content ,
bo_hit ,
bo_del_yn ,
b.comm_nm AS bo_category_nm
FROM free_board a
,comm_code b
WHERE a.bo_category=b.comm_cd
<include refid="com.study.free.dao.IFreeBoardDao.search" />
ORDER by bo_no desc
</select>
</mapper>
SearchVO를 파라미터로 넘기기 위해
freeList.jsp의 excelDown버튼( <a>태그)를 눌렀을 때 이벤트등록을 하자.
<script type="text/javascript">
$("#excelDown").click( function(e){
var $form=$("form[name='search']");
$(this).attr("href","<c:url value='/free/excelDown' />"+"?"+$form.serialize() );
}); //excelDown click
</script>
Controller에서는 파라미터로 SearchVO를 등록하고
List<VO>를 반복문으로 돌려서 그때마다 Row와 Cell을 만들어주면 된다.
ExcelController.java
package com.study.excel.web;
@Controller
public class ExcelController {
@Inject
IExcelService excelService;
@RequestMapping("/free/excelDown")
public void excelDownload(HttpServletResponse response, @ModelAttribute("searchVO")SearchVO searchVO) throws IOException{
XSSFWorkbook wb=null;
Sheet sheet=null;
Row row=null;
Cell cell=null;
wb = new XSSFWorkbook();
sheet = wb.createSheet("freeBoard");
List<FreeBoardVO> freeBoardList=excelService.getBoardList(searchVO,searchCategory);
//첫행 열 이름 표기
int cellCount=0;
row = sheet.createRow(0); //0번째 행
cell=row.createCell(cellCount++);
cell.setCellValue("글번호");
cell=row.createCell(cellCount++);
cell.setCellValue("제목");
cell=row.createCell(cellCount++);
cell.setCellValue("분류코드");
cell=row.createCell(cellCount++);
cell.setCellValue("작성자");
cell=row.createCell(cellCount++);
cell.setCellValue("글비밀번호");
cell=row.createCell(cellCount++);
cell.setCellValue("내용");
cell=row.createCell(cellCount++);
cell.setCellValue("조회수");
cell=row.createCell(cellCount++);
cell.setCellValue("등록일");
cell=row.createCell(cellCount++);
cell.setCellValue("수정일");
cell=row.createCell(cellCount++);
cell.setCellValue("분류");
for(int i=0; i < freeBoardList.size() ; i++ ) {
row=sheet.createRow(i+1); // '열 이름 표기'로 0번째 행 만들었으니까 1번째행부터
cellCount=0; //열 번호 초기화
cell=row.createCell(cellCount++);
cell.setCellValue(freeBoardList.get(i).getBoNo());
cell=row.createCell(cellCount++);
cell.setCellValue(freeBoardList.get(i).getBoTitle());
cell=row.createCell(cellCount++);
cell.setCellValue(freeBoardList.get(i).getBoCategory());
cell=row.createCell(cellCount++);
cell.setCellValue(freeBoardList.get(i).getBoWriter());
cell=row.createCell(cellCount++);
cell.setCellValue(freeBoardList.get(i).getBoPass());
cell=row.createCell(cellCount++);
cell.setCellValue(freeBoardList.get(i).getBoContent());
cell=row.createCell(cellCount++);
cell=row.createCell(cellCount++);
cell.setCellValue(freeBoardList.get(i).getBoHit());
cell.setCellValue(freeBoardList.get(i).getBoRegDate());
cell=row.createCell(cellCount++);
cell.setCellValue(freeBoardList.get(i).getBoModDate());
cell=row.createCell(cellCount++);
cell.setCellValue(freeBoardList.get(i).getBoCategoryNm());
}
// 컨텐츠 타입과 파일명 지정
response.setContentType("ms-vnd/excel");
response.setHeader("Content-Disposition", "attachment;filename=freeBoard.xlsx"); //파일이름지정.
//response OutputStream에 엑셀 작성
wb.write(response.getOutputStream());
}
}
freeList화면에서 'excelDown'버튼을 누르면 다음과 같이 excel이 나온다.