상세 컨텐츠

본문 제목

대용량 데이터 엑셀파일 생성

Programming

by otamot 2011. 2. 11. 14:58

본문

 엑셀 다운로드는 지원하는 라이브러리가 여럿 존재하기 때문에 어디서든 예제를 참고할 수 있다. 하지만 데이터량이 많을 경우 엑셀 파일 자체가 커지므로 메모리 문제가 발생하게 된다. 대용량의 엑셀을 생성하는 예제는 찾아보기 힘들었다. 그리고 여담이지만 대용량의 데이터를 엑셀로 생성하는 것은 하지 않는 것이 좋을 듯 싶다. 
 이번 요구사항에서 db 내용을 엑셀파일로 다운로드 할 수 있게 해 달라는 요구 사항이 있었다. 물로 우려한 대로 대용량이다. 그래서 찾은 예제가 다음 사이트에서 소개 되고 있다.
대용량 엑셀은 'xlsx'.

 라이브러리는 일단 apache의 POI를 사용하게 된다. 대용량 엑셀은 MS 엑셀 2007부터 지원하는 'xlsx'확장명으로 한다. 대략 설명하면 xlsx는 xml파일들을 압축형태로 구성된 파일이다. 이 참고 예제에서는 data를 xml 파일로 작성하고 이후에 파일 압축을 통해 처리한다. 

Row단위로 fetch마다 파일 작성.

 또한 고려해야 할 부분이 현재 ibatis를 db framework으로 사용하는데 모든 data를 조회해서 fetch후 메모리에 올린 다음에 엑셀 파일을 쓰는 형태로 한다면 당연히 메모리 문제가 발생할 것이다. 그래서 각 row를 fetch할 때 마다 엑셀파일을 써 내려가는 형태가 되어야 한다. 이 때 사용할 수 있는 것이 ibatis에서 지원하는 RowHandler를 이용한다. RowHandler을 구현하면 각 row단위로 fetch하면서 처리할 수 있게 할 수 있다.

참고 예제

 적용된 공통 소스를 첨부한다. 정리가 되지 않은 상태로 급하게 작성하느라 좀 부끄러운 소스다.


DAO내에서 다음과 같이 사용한다.
public class ExclDAOImpl extends BaseBigExcelDownDAO implements ExclDAO {

...
    @Override
    public void getDiaryExcelData(StatisticsVO pVo, String targetSheetFilePath,
            String templeteSheetFilePath) throws RuntimeException {
        LinkedHashMap<String, String> sheetMap  = new LinkedHashMap<String, String>();
        sheetMap.put("buzYy"            , "년도"        );
        sheetMap.put("buzYNo"           , "기수"        );
        sheetMap.put("centNm"           , "센터명"        );
        sheetMap.put("mngrNm"           , "사례관리자"        );
        sheetMap.put("userNm"           , "참여자"        );
        sheetMap.put("cnslMakeStatDesc" , "초기상담지"        );
        sheetMap.put("cnslDt"           , "상담일자"        );
        sheetMap.put("cnslDueDt"        , "상담예정일"        );
        sheetMap.put("cnslTypeDesc"     , "상담유형"        );
        sheetMap.put("cnslWayDesc"      , "상담방법"        );
        sheetMap.put("cnslPlace"        , "상담장소"        );
        sheetMap.put("cnslTime"         , "상담시간"        );
        sheetMap.put("cnslTopic"        , "상담주제"        );
        sheetMap.put("cnslCentNm"       , "상담센터명"        );
        sheetMap.put("cnslMngrNm"       , "상담사례관리자"        );
        
        createSheetFile("Excl.getDiaryExcelData", pVo, sheetMap, targetSheetFilePath, templeteSheetFilePath);
    }

...
}

"Excl.getDiaryExcelData" : ibatis에 명시한 query id
pVo: 조회조건을 갖고 있는 vo
sheetMap : 상단에 정의 했듯이 excel의 첫 라인에 작성될 header명과 query의 컬럼명
targetSheetFilePath : 실제 작성될 결과물 xlsx 파일 path
templeteSheetFilePath : 현재 예제를 통해서 xlsx파일을 작성할 때는 temp파일이 필요한데 바로 그 파일의 path정보.

마무리...

 공통소스라고 첨부한 파일의 소스는 이번 글에서 명시 하지 않는다. POI라이브러리 사용과 RowHandler를 사용하는 등의 내용이 주이다. 다음에 상황이 될 때 공통 소스를 설명할 기회가 있을지 모르겠지만 아무튼 일단 좀더 상세 내용은 다음으로 미룬다.

관련글 더보기