Java에서 템플릿을 이용해 Excel 파일을 다운로드 하기 위해서는 크게 두 가지 경우를 사용한다. 'JExcel'을 사용하는 방식과 'POI + Jxls'를 사용하는 방식이 그것이다. 이 글에서는 내가 직접 사용해본 'POI + Jxls'을 사용하는 방식에 대해서 간단히 정리할 것이다.
1. POI
우선 POI란 아파치 소프트웨어 재단에서 만든 라이브러리로서 마이크로소프트 오피스 파일 포맷을 순수 자바 언어로서 읽고 쓰는 기능을 제공한다. 주로 워드, 엑셀, 파워포인트와 파일을 지원하며 최근의 오피스 포맷인 Office Open XML File Formats (OOXML, 즉 xml 기반의 *.docx, *.xlsx, *.pptx 등) 이나 아웃룩, 비지오, 퍼블리셔 등으로 지원 파일 포맷을 늘려가고 있다. (위키백과)
2. Jxls
Jxls 공식 홈페이지에서는 다음과 같이 정의하고 있다. 'Jxls는 Excel 문서를 쉽게 생성할 수 있는 작은 규모의 Java 라이브러리로서 Excel 템플릿의 특수 마크업을 사용하여 출력 형식 및 데이터 레이아웃을 정의합니다.' 또한, Java에는 'POI'와 같이 기본적으로 Excel 파일을 생성하는 API들이 존재하지만 이들은 상당히 많은 Java 코드를 작성해야하게 한다며, Jxls을 사용한다면 템플릿을 기반으로 하여 개발자가 Jxls을 사용하기 위한 아주 적은 양의 코드만 작성하면 된다고 말하고 있다.
3. Dependencies
우선 정해진 템플릿을 가지고 엑셀 파일을 다운로드하기 위해서는 아래와 같은 의존성들이 필요하다.
1. POI(poi, poi-ooxml, poi-ooxml-schema)
2. Jxls
3. Jxls-poi
cf. Jxls-poi 2.10.0 버전과의 호환을 위해서 poi 4.1.2 버전을 사용한다. (발생 이슈 참고 - https://u-u002.tistory.com/40)
cf. Jxls-poi가 아닌 Jxls-core를 사용해 'POI, Jxls, Jxls-core'의 조합으로도 템플릿 양식을 갖춘 엑셀 파일 다운로드가 가능하다. 하지만 이는 POI가 최신 버전 업데이트가 되왔던 반면에, Jxls-core가 이를 호환하는 버전을 내놓지 않는 문제 때문에 Jxls-poi를 사용하겠다. - 하위 버전에서는 데이터가 없으면 출력되지 않아야하는데, 이를 오류로 여기고 콘솔에 메세지를 남기는 문제와, Illegal Reflective Access가 발생한다는 오류 메세지가 발생한다. (An illegal reflective access operation has occurred)
(1) Maven 사용 시
<!-- poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<!-- poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<!-- poi-ooxml-schemas -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
<!-- jxls -->
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls</artifactId>
<version>2.10.0</version>
</dependency>
<!-- jxls-poi -->
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-poi</artifactId>
<version>2.10.0</version>
</dependency>
(2) Gradle 사용 시
// poi
implementation group: 'org.apache.poi', name: 'poi', version: '4.1.2'
// poi-ooxml
implementation group: 'org.apache.poi', name: 'poi-ooxml', version: '4.1.2'
// poi-ooxml-schemas
implementation group: 'org.apache.poi', name: 'poi-ooxml-schemas', version: '4.1.2'
// jxls
implementation group: 'org.jxls', name: 'jxls', version: '2.10.0'
// jxls-poi
implementation group: 'org.jxls', name: 'jxls-poi', version: '2.10.0'
4. Template 양식
Jxls는 Apache JEXL 표현식을 이용한다. ${ } 내부에 JEXL 표현식을 넣어 이를 읽어 데이터를 바인딩한다.
1. jx-area(lastCell="")
데이터를 바인딩할 범위를 정한다. ex. 셀 A1에 'jx-area(lastCell="F10")'이 사용됐다면, 데이터 바인딩 영역은 A1부터 F10까지로 간주된다.
2. jx-each(items="", var="", lastCell="")
리스트의 아이템들을 하나씩 반복할 수 있다. ex. 셀 B5에 'jx-each(items="members", var="data", lastCell="E5")'이 사용됐다면, 파일에 전달된 필드 중 'members'라는 값(배열이어야 함)을 반복하되 요소들을 'data'라는 필드로 호출되도록 하고, 이를 E5까지 사용한다는 의미이다.
3. jx-if(condition="", lastCell="", areas=[ : , : ])
조건식(condition)의 값이 참일 때 ' : ' 전자, 거짓일 때 후자가 나타난다. ex. [A1:A1, B1:B1]일 경우, 조건식이 참이면 A1가 해당 셀에 표현된다.
예시
5. 애플리케이션에서의 Template 로드
데이터 전달 : 예시로 잡은 데이터 형태는 다음과 같다.
{
"companyName": "회사명",
"department": "부서명",
"pscDatas": [
{"id": "1", "name": "A", "weight": "56.3kg", "height": "165cm"},
{"id": "2", "name": "B", "weight": "81kg", "height": "180cm"},
{"id": "3", "name": "C", "weight": "75kg", "height": "172com"}
]
}
서버단 : 템플릿 파일 로드 및 템플릿 치환
try(InputStream is = new BufferedInputStream(new FileInputStream(filePath))) {
OutputStream os = new FileOutputStream(destFilePath);
Context context = new Context();
context.putVar(data);
JxlsHelper.getInstance().processTemplate(is, os, context);
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
1. 템플릿으로 사용할 파일의 InputStream 인스턴스 생성 및 저장될 파일의 OutputStream 인스턴스 생성
2. org.jxls.common.Context 인스턴스 생성 후 객체 형태의 데이터 삽입 => Context.putVar(“key”, value);
3. JxlsHelper.getInstance()를 통해 JxlsHelper 인스턴스 생성, processTemplate의 인자로 InputStream 인스턴스, OutputStream 인스턴스, 데이터를 담은 Context 인스턴스 전달
- 내부에서 Excel파일의 셀을 한 줄 씩 조회하며 comment(메모)가 있는 셀을 읽어 데이터를 파싱(메모형태로 표현식을 삽입하는 이유)
'Backend > Spring' 카테고리의 다른 글
Spring) 바이너리 파일을 DB에 저장 후 요청에 의해 바로 다운로드하기 (0) | 2021.12.06 |
---|---|
Spring) Poi와 Jxls를 사용해 Template을 이용한 워드 다운로드 (0) | 2021.12.06 |
Spring) Poi와 Jxls를 사용해 Template을 이용한 파워포인트 다운로드 -2. 테이블 작성 (0) | 2021.11.28 |
Spring) Poi와 Jxls를 사용해 Template을 이용한 파워포인트 다운로드 (0) | 2021.11.21 |
Spring) JXLS, POI 버전 문제 (0) | 2021.10.17 |