[JXLS] JAVA SPRING 데이터 엑셀출력 및 셀병합, merge 하는 방법







웹프로젝트를 개발하다보면


테이블이나 어떤 데이터들을 엑셀로 다운받는 기능을 만들어야 하는 경우가 있다.



일단 엑셀로 만드는게 POI만 쓰면 진짜 더럽게 귀찮아진다.


그렇다고 제이쿼리 excel export를 쓰자니


페이징처리된 테이블의 데이터들을 뽑기가 애매하고


1만로우쯤 되었을때 그걸 다 테이블에 append 시키기도 오바같다



그래서 찾다찾다 찾아낸것이


JXLS


일단 jxls는 poi 기반으로 만들어졌다.


사용법은


정말 간단하다.


그냥 마이바티스에서 db데이터 뽑아서


페이지로 날려주는 그 모델


해쉬맵데이터 형식으로뽑은걸 그대로 사용하면 된다


엑셀에 위치 지정이나 반복되는것은 


미리 엑셀 템플릿을 만들어 놓으면


그대로 들어간다.



일단 셋팅 방법부터 알아보도록 하자.


전자정부 기준이로 설명 한다.




1. pom.xml  


pom.xml의 dependency 부분에 아래 코드를 넣어 주도록 하자.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!-- 엑셀 다운로드 -->
        
        <dependency>
              <groupId>net.sf.jxls</groupId>
               <artifactId>jxls-core</artifactId>
             <version>1.0.6</version>
        </dependency>
       <dependency>
            <groupId>org.jxls</groupId>
            <artifactId>jxls-poi</artifactId>
            <version>1.0.13</version>
        </dependency>
        <dependency>
            <groupId>org.jxls</groupId>
            <artifactId>jxls</artifactId>
            <version>2.4.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.14</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.14</version>
        </dependency>
        <dependency>
            <groupId>org.jxls</groupId>
            <artifactId>jxls-jexcel</artifactId>
            <version>1.0.6</version>
        </dependency>
cs




위에서 말했듯 jxls는 poi를 사용하기 때문에 poi도 받아주어야 한다.





2. 엑셀만들고 다운로드 받는 클래스


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package 패키지 경로;
 
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import net.sf.jxls.exception.ParsePropertyException;
import net.sf.jxls.transformer.XLSTransformer;
 
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Workbook;
 
// MakeExcel이라는 클래스를 만들고 그 안에 downliad라는 메소드를 생성한다.
public class MakeExcel {
    public void download(HttpServletRequest request, HttpServletResponse response,
                    Map<String, Object> bean, String fileName, String templateFile, String string)
                    throws ParsePropertyException, InvalidFormatException {
 
        // 받아오는 매개변수 bean는 디비에서 뽑아온 데이터
        // fileName 은 다운로드 받을때 지정되는 파일명
        // templateFile 는 템플릿 엑셀 파일명이다.
        
        // tempPath는 템플릿 엑셀파일이 들어가는 경로를 넣어 준다.
        String tempPath = request.getSession().getServletContext().getRealPath("/WEB-INF/excel");
        
 
        // 별도로 다운로드 만들기 귀찮으까 이런식으로 만들어서 바로 엑셀 생성후 다운 받게 
        try {
 
            InputStream is = new BufferedInputStream(new FileInputStream(tempPath + "\\" + templateFile));
            XLSTransformer xls = new XLSTransformer();
            
            
            Workbook workbook = xls.transformXLS(is, bean);
            
            
            response.setHeader("Content-Disposition""attachment; filename=\"" + fileName + ".xlsx\"");
            
            OutputStream os = response.getOutputStream();
            
            workbook.write(os);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
cs



3. 엑셀 다운로드 요청 및 데이터가져오는 메소드



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 @RequestMapping(value = "/downExcel.do")
        public void listExcel(HttpServletRequest request,
                HttpServletResponse response, VO vo,
                ModelMap modelMap) throws Exception, Exception {
 
            
            // 그냥 평소에 마이바티스에서 데이터 뽑는 방법으로 데이터를 가져온다.
            List<VO> dataList = trs01Service.selectGroupList(groupVO);
            
            
            // 받은 데이터를 맵에 담는다.
            Map<String, Object> beans = new HashMap<String, Object>();
            beans.put("dataList", dataList);
            
            // 엑셀 다운로드 메소드가 담겨 있는 객체
            MakeExcel me = new MakeExcel();
 
            me.download(request, response, beans, "다운받을때지정될 엑셀파일명""엑셀템플릿 파일 명.xlsx""무시해도됨");
        }
cs





이렇게 하면 자바에서 할 건 끝났다.



막 예전에 POI에서 셀위치 지정하고 했던것들은 하지 않아도 된다!!



저 템플릿위치에 아래 4번에서 만든 템플릿 엑셀파일을 넣어놓고


3번에서 만든 메소드를 호출하면 해당 데이터를 담은 엑셀을 다운로드 받게 된다.


정말 너무너무 간단하다.




4. 템플릿 엑셀 예제





위 그림과 같이 JSTL 쓰던것 처럼 적어주면 된다.


저렇게 적으면 콜렉션일 경우 자동으로 반복까지 해준다.


그냥 저렇게만 만들어 두면 저 위치부터 아래로 쭉쭉 엑셀데이터가 입력 되는 것이다.



엄청나다.





5. 셀병합, merge






이런식으로 셀병합을 하고 이름옆에 3줄로 다른 정보를 반복시켜야 하는 경우가 있다.



그냥 4번에 있는식으로 템플릿만들어서 적으면 에러난다.


java.lang.NullPointerException

at net.sf.jxls.util.Util.shiftColumnUp(Util.java:335) ~[jxls-core-1.0.6.jar:?]

at net.sf.jxls.util.Util.shiftUncoupledCellsUp(Util.java:315) ~[jxls-core-1.0.6.jar:?]

at net.sf.jxls.util.Util.duplicateRow(Util.java:246) ~[jxls-core-1.0.6.jar:?]

at net.sf.jxls.controller.SheetTransformationControllerImpl.duplicateRow(SheetTransformationControllerImpl.java:140) ~[jxls-core-1.0.6.jar:?]

at net.sf.jxls.transformer.CollectionRowTransformer.processRowCollections(CollectionRowTransformer.java:106) ~[jxls-core-1.0.6.jar:?]

at net.sf.jxls.transformer.CollectionRowTransformer.transform(CollectionRowTransformer.java:66) ~[jxls-core-1.0.6.jar:?]



이런 에러가 막 뿜어져 나올 것이다.


왜 에러가 나느냐..


템플릿을 잘못 만들었기 때문이다.


이걸 보는 여러분들도 템플릿으로 이것저것 에러뿜어가면서 테스트 하다보면


알수 있을 이유이다


그냥 해결방법만 간단하게 말하면





이런식으로 셀병합한 위치에 들어가는 데이터 옆에 //:숫자  를 넣어 주면 된다.


만약 데이터가 3칸을 병합해서 세줄단위로 넘어가야 하는 경우


0 , 1, 2  로 세서 숫자 2를 넣어주면 된다.



머지를 하지 않더라도


2줄단위로 반복하거나 3줄단위로 반복하게 하는 경우에도 동일하게 적용하면 된다.



JXLS의 가장 좋은 장점은 데이터 넣는곳 템플릿에 스타일 넣어주면 그 스타일도 같이 반복이 된다.


아주 훌륭하다



Cannot find module 'ejs' 에러 해결 방법


드디어 node.js 에 나도 입문을 하게 되었다.


node.js 설치 과정은 다른 블로그에도 많이 나와있고 나중에 시간이 되면 포스팅 하기로 하고


이 포스팅 내용을 검색해 들어온 사람들은 이미 설치를 끝내고 나서 진행하다가 찾아 온 사람들이니 생략


그리고 진짜 오늘 시작해본것 이기 때문에 진정한 야매가이드라는걸 잊지 말고


내 포스팅을 전부 신뢰하진 말길....




nodejs 서버에 jsp 같은 파일을 띄우려면 템플릿? 이라는걸 사용해야 한단다


jade도 있고 ejs도 있는데 html이랑 제일 유사하게 생긴게 ejs라고 하길래 어떻게 하는가 찾아 봤더니


ejs를 설치 하란다


그래서 설치 하고 예제에 있는대로 작성하고 서버를 실행시켰더니


Cannot find module 'ejs' 라는 에러가 나타난다





이런게 뜨길래 구글링해서 찾아봤더니


역시나 스택오버플로우 형님들이 해결책들을 제시해 주었다




package.json 이라는 녀석을 열어 보면 저렇게 mvc2에서 디펜던시 해주는것처럼 종속성에 대한 정보가 들어있는 녀석이 있는데


저기에 아마 ejs 라는 동그라미친 부분이 없어서 나오는 에러이다


저부분을 추가해 주면 해결이 된다고 하는데 난 해결이 안된다...



그래서 스크롤을 좀더 내려보니


npm install ejs --save


이렇게 설치를 해야 한다고 한다


npm 명령어중 --save 는


설치된 node 모듈을 pakage.json 파일 내의 디펜던시 목록에 추가 하게 하는 옵션이다.


나도 아직 nodejs 설치 한지 두시간밖에 안지나서 정확히는 모르겠다.



여하튼 에러나는 사람은 저렇게 다시 설치 해보도록 하자



그리고 만약 프로젝트 폴더에 package.json 이 파일이 없다면


프로젝트 등록? 뭐 그게 안된거다


방법은 해당 프로젝트 폴더로 들어가서


npm init 라는 명령어를 실행시켜


어플리케이션을 보관할 디렉토리를 작업 디렉토리로 설정 하도록 하자


대충 엔터치면 지나가는데


해당 어플리케이션 설명이나 리파지토리 뭐 이런거 적으라고 나오는건


알아서 적도록 하자 그냥 엔터쳐서 넘겨도 된다.


그중에


entry point:(index.js) 라고 나오는데


기본 파일의 이름을 지정 하는것 이라고 한다.



ps: 뒤에 --save 붙이는게 의무적인건 아니라고 한다... 근데 난 저거 붙여서


해결했으니까 ㅠ_ㅠ;;; 


ps2: 에러난 이유가 환경 변수의 문제일 수도 있겠다는 제보를 받았다

노드js는 C에 설치 하고 프로젝트폴더는 D에 있어서 

내가 처음에 설치 할떈 글로벌로 설치 하면 드라이브 상관 없이

다 되는 건줄 알고 npm install ejs -g 라는 -g 옵션을 썻는데

이렇게 설치 하면 C에 경로가 잡히가 되는거 아니냐는 의견을 받았음.

확인 해보진 않았지만 혹시나 다른 사람들은 확인해보시길






켄도 ui 라인차트의 bullet(라인 사이의 동그라미)을 없애는 방법 입니다.


라인을 그려줄때 동그란 마커 없이 깔끔하게 그려주고 싶을때 사용 합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 $("#chart").kendoChart({
                title: {
                    text: "Gross domestic product growth \n /GDP annual %/"
                },
                legend: {
                    position: "bottom"
                },
                chartArea: {
                    background: ""
                },
                seriesDefaults: {
                    type: "line",
                    style: "smooth",
                   markers:{
                                  size:1
                                  }
                },
                series: [{
                    name"India",
                    data: [3.9077.9437.8489.2849.2639.8013.8908.2389.5526.855],
                  
                },{
                    name"World",
                    data: [1.9882.7333.9943.4644.0013.9391.333-2.2454.3392.727]
                },{
                    name"Russian Federation",
                    data: [4.7437.2957.1756.3768.1538.5355.247-7.8324.34.3]
                },{
                    name"Haiti",
                    data: [-0.2530.362-3.5191.7992.2523.3430.8432.877-5.4165.590]
                }],
                valueAxis: {
                    labels: {
                        format: "{0}%"
                    },
                    line: {
                        visible: false
                    },
                    axisCrossingValue: -10
                },
                categoryAxis: {
                    categories: [2002200320042005200620072008200920102011],
                    majorGridLines: {
                        visible: false
                    },
                    labels: {
                        rotation: "auto"
                    }
                },
                tooltip: {
                    visible: true,
                    format: "{0}%",
                    template: "#= series.name #: #= value #"
                }
            });
cs



이전과 같은 켄도 ui 라인차트 데모페이지의 첫번째 소스 입니다.


저기에서 


seriesDefaults 속성에


 markers:{
           size:1
       }


markers 라는 속성을 추가 하였고 사이즈는 1로 지정 하였습니다.


0으로 지정하면 마우스오버 되었을때 엄청 커다란 동그라미가 생기네요


시리즈 디폴트에 마커스 사이즈를 1로 지정해 놓으면 모든 라인에 bullet가 사라지게 됩니다.


혹은 특정 라인에만 bullet를 없애고 싶을땐




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
series: [{
                    name"India",
                    data: [3.9077.9437.8489.2849.2639.8013.8908.2389.5526.855],
                      markers:{
                              size:1
                           }
                },{
                    name"World",
                    data: [1.9882.7333.9943.4644.0013.9391.333-2.2454.3392.727],
                  markers:{
                           size:1
                         }
                },{
                    name"Russian Federation",
                    data: [4.7437.2957.1756.3768.1538.5355.247-7.8324.34.3]
                },{
                    name"Haiti",
                    data: [-0.2530.362-3.5191.7992.2523.3430.8432.877-5.4165.590]
                }],
cs



시리즈에 들어가는 속성에 마커스를 따로 지정해 주면 됩니다.


켄도 ui의 차트를 그릴때 색상을 지정하는 방법 입니다.


차트를 구현하다 보면 임의로 지정된 색상을 사용해야 하는 경우가 있습니다. 그럴 경우 간단하게 


사용 할 수 있는 방법입니다.


코드는 아래와 같습니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 $("#chart").kendoChart({
                title: {
                    text: "Gross domestic product growth \n /GDP annual %/"
                },
                legend: {
                    position: "bottom"
                },
                chartArea: {
                    background: ""
                },
                seriesDefaults: {
                    type: "line",
                    style: "smooth"
                },
                series: [{
                    name"India",
                    data: [3.9077.9437.8489.2849.2639.8013.8908.2389.5526.855]
                },{
                    name"World",
                    data: [1.9882.7333.9943.4644.0013.9391.333-2.2454.3392.727]
                },{
                    name"Russian Federation",
                    data: [4.7437.2957.1756.3768.1538.5355.247-7.8324.34.3]
                },{
                    name"Haiti",
                    data: [-0.2530.362-3.5191.7992.2523.3430.8432.877-5.4165.590]
                }],
                seriesColors: [" #108D25","#48CFAD""#FC6E51",  "#FC6E51""#4FC0E8"
                                 "#009bd7""#26aadd""#4db9e3""#73c8e9""#99d7ef"],
                valueAxis: {
                    labels: {
                        format: "{0}%"
                    },
                    line: {
                        visible: false
                    },
                    axisCrossingValue: -10
                },
                categoryAxis: {
                    categories: [2002200320042005200620072008200920102011],
                    majorGridLines: {
                        visible: false
                    },
                    labels: {
                        rotation: "auto"
                    }
                },
                tooltip: {
                    visible: true,
                    format: "{0}%",
                    template: "#= series.name #: #= value #"
                }
            });
cs



켄도 ui의 라인차트를 그리는 데모페이지의 첫번째 소스에 


seriesColors: [" #108D25","#48CFAD""#FC6E51",  "#FC6E51""#4FC0E8"
                                 "#009bd7""#26aadd""#4db9e3""#73c8e9""#99d7ef"],


이 코드를 추가 하였습니다. seriesColors 라는 속성이 색상을 지정해 주는 속성인데


저 배열 안에 색상코드를 넣으면 차트가 저 순서대로 색상을 넣어주게 됩니다.



두번째 방법은


시리즈에 들어갈 데이터에 직접 색상을 지정해 주는 방법 입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
data: [{
            category: "변속A",
            value: data1Val,
            color: "#9de219"
        },{
            category: "변속C",
            value: data2Val,
            color: "#90cc38"
        },{
            category: "등속B1",
            value: data3Val,
            color: "#006634"
        },{
            category: "등속B2",
            value: data4Val,
            color: "#004d38"
        }]
cs



차트가 그려줄 데이터를 직접 만들어 넣어 줄떄 컬러속성을 함께 넣어 주면 지정된 색상으로 차트를 그려주게 됩니다.

버그 예.


1. 클라이언트(브라우저)에서 jquery ajax 를 수행하여 GET request를 한다.

2. 서버가 GET request를 받고 routing을 수행하여 해당하는 데이터를 response한다.


Chrome, FF, Safari 의 경우 - 서버가 보낸 response를 받고 데이터를 확인한다.

IE 의 경우 - 서버가 보낸 response는 받으나 데이터가 없다.




서버쪽 로그를 확인해보니 특정한 GET 요청을 서버가 받지 못하고 있었다.


헌데 alert(‍), console.log() 등을 이용해서 확인해본 결과


ajax 수행은 error가 나지 않고 제대로 success 를 띄움



재밌는건 익스플로러의 개발자도구를 띄워놓은 상태에선 값을 잘 받아 온다는 점이다.




원인 및 해결 방법



URL이 같으면 IE의 ajax 연결은 cache를 사용하고 갱신하지 않는다는 것이다.


그래서 ajax 연결 시 URL을 매번 바꾸어주어야 한다는 것


간단한 해결 방법은 시간과 같이 매번 변하는 파라메터를 같이 날려 주는 것


http://localhost:8080/session

=> http://localhost:8080/session?1260790889296



제이쿼리에서는 

jQuery.ajaxSetup({cache:false});

와 같이 캐쉬사용을 끄는 옵션도 있지만 간혹 적용이 안되는 경우도 있는 것 같다.


켄도 UI에서 제공하는 차트는 매우 유용합니다.


간단하고 예쁜 차트를 그릴수 있기 때문이죠


제 주변에선 유료 라이센스인 켄도UI를 사용하는 사람이 없기 때문에


혼자서 레퍼런스 뒤지고 삽질 하면서 배우고 있습니다 ㅎㅎ


켄도 UI에서 제공하는 차트의 배경색을 없애는 방법 입니다.


자바 스크립트에서의 코딩은 아래와 같이 작성 합니다.


 $("#kendoChart").kendoChart({

 chartArea: {

   height: 250,

   background: ""

 },

 });


위와 같이 background에 공백문자를 넣으면 배경이 사라집니다.


이것저것 막 해보다가 얻어걸렸는데 저게 정확한 사용법인지는 잘 모르겠습니다만


방법을 정말 모르겠으면 일단 되도록 만들어야겠죠? ㅎㅎ



이것때문에 돌아버리는줄 알았네요


패딩을 0을주고 마진을 0을주고 별것 다 해봤는데도 간격이 그대로 있길래


미치기 직전까지 가던 와중에 다른 방법을 발견 했습니다.


뭐 저도 구글링하면서 발견 한거지만요


<li>

내용

</li><!-- 


 --><li>내용</li> 


이런식으로 li태그 사이에 주석처리로 공백을 없애 주면 됩니다.


<li>

내용

</li><li>내용</li>


이런식으로 공백을 없애도 되지만 가독성이 너무 떨어지기 때문에 위와 같은 방법을 사용하는것이 좋을것 같습니다. 



자바스크립트를 사용하면서 문자열에 데이터를 넣다보면 특수문자 때문에 구글링은 하는 경우가 많다.

이 포스팅을 보는 당신도 바로 그와 같은 경우겠지 

[JAVASCRIPT] JavaScript 특수문자 인코딩

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * 특수문자 인코딩
 * @param str
 * @returnsd
 */
function htmlEntityEnc(str){
    if(str == "" || str == null){
        return str;
    }
    else{
        return str.replace("&""&amp;").replace("#""&#35;").replace("<""&lt;").replace(">""&gt;").replace(/"/g, "&quot;").replace('\\', "&#39;").replace('%', "&#37;").replace('(', "&#40;").replace(')', "&#41;").replace('+', "&#43;").replace('/', "&#47;").replace('.', "&#46;");
    }
}


 

어디서 퍼와서 어딘가에 저장했던 글인데 어디서 퍼온건지 기억이 안나지만 저위에 아이디가 있는걸 보아 저분이 

작성하신 글인거 같다.. 블로그 하기 전에 복사해서 보관하던 건데

혹시나 저분이 이 포스팅을 언짢아 하신다면 바로 내리고 사과하겠습니다.



포스팅이 도움이 되셨다면 마우스를 조금만 움직여서 

공감하기를 눌러주세요 블로거에게 큰 힘이 됩니다~! 

가끔 이클립스를 띄우면 나타나는 에러창이다.


뭐 업데이트 하려는데 삔또가 나갔다 이런말 같은데


Window -> Preferences -> Maven -> Download repository updates index on startup


로 해결하자.


포스팅이 도움이 되셨다면 마우스를 조금만 움직여서 

공감하기를 눌러주세요 블로거에게 큰 힘이 됩니다~! 

an exception has been caught while processing the refactoring delete resource 에러가 나는 경우.


프로젝트를 지우려는데 일부만 지워지고 나머진 안지워지고 에러창이 난다...


이클립스에서 지우려고 하는데 어딘가에서 쓰고 있기 때문이다.


github 에서 검색중 발견한 댓글


This is probably going to be a limitation on windows which locks the files in use. bndtools is using bnd which is using the plugins in cnf. On a sane file system, they can be deleted. I supposed the only thing that could be done is to set the files up for deletion on vm exit.

You can, of course, complete the deletion from the command line after exiting eclipse.



대충... 그냥... 다른데서 쓰고 있으니까 못지운다는 얘기 같은데...


서버 끄고 이클립스 끄고 다시 열어서 지우니까 지워진다.




포스팅이 도움이 되셨다면 마우스를 조금만 움직여서 

공감하기를 눌러주세요 블로거에게 큰 힘이 됩니다~! 


+ Recent posts