티스토리 뷰


Apache Poi를 활용한 엑셀(Excel) 이미지 출력


이번에 엑셀 출력 기능을 만들면서, 조금더 Apache Poi에 익숙해졌습니다.


엑셀 출력을 하면서, 엑셀 모양을 잡으면서 출력하는 것은 템플릿 엑셀 파일을 만들어 놓고


부분 별로 로우 및 셀 생성과 위치 설정으로 진행하니 좀 편하더라구요.


오늘은 이미지 출력 부분만 정리하도록 하겠습니다.



시나리오는


DB에서 파일 정보(저장된 파일명) 획득 -> 파일 READ -> 엑셀 출력


입니다.


DB에서 파일을 JSON 형태로 저장을 했습니다.


이 부분은 고정적으로 최대 0~3개 까지 파일을 저장할 수 있는 형태였는데, 따로 테이블을 두기가 귀찮아서..


JSON구조의 스트링을 DB에 저장하는 형태로 하였고, 파일은 따로 Path를 설정하여 저장하였습니다.


- 기본적으로 필요한 라이브러리(Dependency) In pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
<!-- Apache POI -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.12</version>
</dependency>
 
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.12</version>
</dependency>
cs


- 엑셀 이미지 출력 소스

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
56
57
58
59
60
61
62
int rownum = 30;
 
for (int z = 0; z < fileItemList.size(); z++) {
 
    StoreCheckAnswerModel item = fileItemList.get(z);
 
    JSONTokener tokener = new JSONTokener(item.getFileInfo());
    JSONArray fileArray = new JSONArray(tokener);
 
    XSSFRow imgInfoRow = sheet2.createRow(rownum);
    imgInfoRow.setHeight((short2500);
 
    // 사진첨부1
    XSSFCell imgInfoCell5 = imgInfoRow.createCell(9);
    imgInfoCell5.setCellStyle(DataCellStyle);
    // 사진첨부2
    XSSFCell imgInfoCell6 = imgInfoRow.createCell(11);
    imgInfoCell6.setCellStyle(DataCellStyle);
    // 사진첨부3
    XSSFCell imgInfoCell7 = imgInfoRow.createCell(13);
    imgInfoCell7.setCellStyle(DataCellStyle);
 
    for (int j = 0; j < fileArray .length(); j++) {
 
        JSONObject object = fileArray .getJSONObject(j);
        String rFileName = object.getString("saveFileName");
 
        File getFile = new File(SHOPCHECK_FILE_PATH + "/" + rFileName);
 
        if (!getFile.exists()) {
            getFile = new File(SHOPCHECK_TMP_FILE_PATH + "/" + rFileName);
        }
 
        if (getFile.canRead()) {
            BufferedImage img = ImageIO.read(getFile);
 
            img = ImageUtils.resizeImage(img, 200160);
 
            byte[] image = ImageUtils.imageToBytes(img);
 
            int pictureIdx = wb.addPicture(image, Workbook.PICTURE_TYPE_JPEG);
 
            CreationHelper helper = wb.getCreationHelper();
 
            Drawing drawing = sheet2.createDrawingPatriarch();
 
            ClientAnchor anchor = helper.createClientAnchor();
            anchor.setDx1(10 * XSSFShape.EMU_PER_PIXEL);
            anchor.setDx2(10 * XSSFShape.EMU_PER_PIXEL);
            anchor.setDy1(10 * XSSFShape.EMU_PER_PIXEL);
            anchor.setDy2(10 * XSSFShape.EMU_PER_PIXEL);
 
            anchor.setRow1(rownum);
            anchor.setCol1(9 + j*2);
 
            Picture pict = drawing.createPicture(anchor, pictureIdx);
            pict.resize();
        }
    }
 
    rownum++;
}
cs


전체적인 대략 소스는 다음과 같습니다.

먼저 rownum = 30 으로 초기화 하였는데, 엑셀에서는 맨위의 행를 0번으로 인식하니, 실제 엑셀에선 29번 행이 될 것입니다. ( 엑셀에선 왼쪽에 행번호를 ROW라고 합니다.)


항목당 이미지는 최대 3개 까지 저장할 수 있으며, 표 형태로 사진1, 2, 3으로 출력해 줘야 하므로

같은 rownum에 출력이 되고, 9번째, 10번째, 11번째 컬럼에 출력이 되도록 합니다.


저는 템플릿을 활용해서, 해당 컬럼의 WIDTH가 적절하게 조정이 되어있습니다.


item.getFileInfo()를 통해, 해당 항목의 파일 정보를 읽어와서, JSON 객체 API와 반복문을 통해 출력을 진행합니다.


아랫부분에서 크게 설명 드릴 부분은 별로 없는 것 같고,

이미지 유틸로 File 객체를 BufferedImage 로 변경을 해주었고, 

이미지유틸의 resizeImage를 통해 사진의 크기를 적절히 변경하였습니다.


- 비율 유지하며 사진의 크기 변경하기

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
    public static BufferedImage resizeImage(BufferedImage image, int maxWidth, int maxHeight) {
 
        BufferedImage src = image;
        
        try {
 
            int width = src.getWidth();
            int height = src.getHeight();
 
            if (width > maxWidth) {
                float widthRatio = maxWidth / (float) width;
                width = (int) (width * widthRatio);
                height = (int) (height * widthRatio);
            }
            if (height > maxHeight) {
                float heightRatio = maxHeight / (float) height;
                width = (int) (width * heightRatio);
                height = (int) (height * heightRatio);
            }
            return resize(src, width, height);
            
        } catch (Exception e) {
            System.out.println("이 파일은 사이즈를 변경할 수 없습니다. 파일을 확인해주세요.");
            return null;
        }
    }
cs


이미지 파일의 maxWidth, maxHeight을 지정해서, 비율을 유지하면서, 크기를 width 200 또는 height 160에 맞추는 메소드 입니다. 셀 크기를 맞추어 놓았기 때문에 저는 200, 160으로 설정하였습니다.


이 후 아래에서는 POI의 객체와 메소드를 활용하여, 출력을 하는 것이고, 

anchor.setDx() 와 anchor.setDy 등은 셀에 이미지를 넣을 때 셀 왼쪽 상단에 딱 맞게 이미지가 들어가는데 그것의 여백을 줄 수 있습니다.


anchor.setRow1() 와 anchor.setCol1()로 이미지를 출력할 Cell 의 위치를 정할 수 있습니다.


아직 초보 개발자라 많은 시행 착오가 있었던, 엑셀 이미지 출력이었습니다.



많은 질타와 조언은 개발자로서 향상에 도움이 됩니다. 감사합니다 ^^





댓글