[Spring] Apache POI library로 엑셀 다운로드 API 만들기 for 온리 백엔드 (기초편)

Walter Mitty·2023년 6월 19일
0

엑셀 다운로드 기능은 쉽다면 쉽고, 어렵다면 어려운데
나는 조회한 값에 회원의 이름과 지역, 전화번호, 신청 교육 리스트가 있다면
엑셀 표 안에는 아래와 같은 식으로 들어가야 했다.

이름지역전화번호신청교육 제목1신청교육 제목2신청교육 제목3
임씨서울01012341234수강률(%)수강률(%)수강률(%)
장씨부산01056785678수강률(%)수강률(%)수강률(%)
이씨서울01012345678수강률(%)수강률(%)수강률(%)

이름과 지역, 전화번호까지 해주는건 그럭저럭 괜찮았는데....신청 교육 리스트 부분이 꽤나 까다로웠다.

일단 POI 라이브러리를 사용해보자.

build.gradle 에서 선언하고 코끼리 한번 클릭해서 build를 해주자.

// excel download : poi
implementation 'org.apache.poi:poi:5.2.2'                // .xls 확장자
implementation 'org.apache.poi:poi-ooxml:5.2.2'          // .xlsx 확장자

참고한 글이다.

내가 구현한 코드는 거의 알고리즘 코딩테스트 느낌으로 엄청난 for문이 존재하므로,
참고한 글처럼 Controller 단에서 구현했다면 테스트를 하러갈 수 있다.

단, 포스트맨에선 불가능!

오히려 더 간단한 버전일수가 있는데, 해당 API에 직접 접근하면 된다.

Controller 단

@GetMapping(value = "/edu/excel-download")
    public void eduExcelDownload(HttpServletResponse response) throws IOException {
        Workbook wb = new XSSFWorkbook();
        Sheet sheet = wb.createSheet("교육 진행률");
        Row row = null;
        Cell cell = null;
        int rowNum = 0;

        List<String> excelHeaderList = userAdminService.getHeaderName(EduReaderListDTO.class);
        List<EduReaderListDTO> excelBodyList = userReaderCustomRepository.findEduPercentageList();
        List<EduContents> excelEduContents = eduContentsRepository.findAll();

        // 콘텐츠 id들을 담는 배열
        int[] contentsIds = new int[excelEduContents.size()];

        for(int i=0; i<contentsIds.length; i++) {
            contentsIds[i] = excelEduContents.get(i).getId();
            System.out.println("contentsId: " + contentsIds[i]);
        }

        // Header
        row = sheet.createRow(rowNum++);
        for(int i=0; i<excelHeaderList.size(); i++) {
            cell = row.createCell(i);
            cell.setCellValue(excelHeaderList.get(i));
        }

        for(int i=0; i<excelEduContents.size(); i++) {
            cell = row.createCell(excelHeaderList.size() + i);
            cell.setCellValue(excelEduContents.get(i).getTitle());
        }

        // Body
        for (int i=0; i<excelBodyList.size(); i++) {
            row = sheet.createRow(rowNum++);
            cell = row.createCell(0);
            cell.setCellValue(excelBodyList.get(i).getId());
            cell = row.createCell(1);
            cell.setCellValue(excelBodyList.get(i).getUserRegion());
            cell = row.createCell(2);
            cell.setCellValue(excelBodyList.get(i).getUserName());
            cell = row.createCell(3);
            cell.setCellValue(excelBodyList.get(i).getUserBirth());
            cell = row.createCell(4);
            cell.setCellValue(excelBodyList.get(i).getUserGender());
            cell = row.createCell(5);
            cell.setCellValue(excelBodyList.get(i).getUserTel());
            cell = row.createCell(6);
            if(excelBodyList.get(i).getEduPercentage() == null) {
                cell.setCellValue(0);
            } else {
               cell.setCellValue(excelBodyList.get(i).getEduPercentage());
            }

            int[] userContentIds = new int[excelBodyList.get(i).getEduInfos().size()];
            for(int n=0; n<userContentIds.length; n++) {
                if(excelBodyList.get(i).getEduInfos().get(n).getEduContentId() == null) {
                    userContentIds[n] = 0;
                } else {
                    userContentIds[n] = excelBodyList.get(i).getEduInfos().get(n).getEduContentId();
                }
            }

            // 각 교육 콘텐츠당 퍼센테이지를 담을 배열 [0,0,0,0...,0]
            int[] percentages = new int[excelEduContents.size()];

            // 대상자가 가지고 있는 교육 콘텐츠 id와 교육 콘텐츠 배열의 값이 일치하면 해당 퍼센테이지 배열의 idx값에 대상자 percentage로 변경
            for(int j=0; j<userContentIds.length; j++) {
                for(int m=0; m<contentsIds.length; m++) {
                    if(userContentIds[j] == contentsIds[m]) {
                        percentages[m] = excelBodyList.get(i).getEduInfos().get(j).getEduEachPercentage();
                    }
                }
            }

            for(int p=0; p<percentages.length; p++){
                cell = row.createCell(7+p);
                cell.setCellValue(percentages[p]);
            }
        }

        // 컨텐츠 타입과 파일명 지정
        response.setContentType("ms-vnd/excel");
        String fileName = "엑셀 파일 이름";
        String outputFileName = new String(fileName.getBytes("KSC5601"), "8859_1"); // 엑셀 파일 이름이 한글이라면 넣어주자~
        response.setHeader("Content-Disposition", "attachment;filename=" + outputFileName + ".xlsx");

        // Excel File Output
        wb.write(response.getOutputStream());
        wb.close();
    }

이런식으로 코드를 짜줬다면, http://localhost:8080/edu/excel-download 포스트맨에서 쓰는 것처럼 바로 그 API를 브라우저에 넣어주면 다운로드가 된다.

잘 다운로드 된다!

0개의 댓글