IT/development

[spring] spring excel download (feat. 체크박스)

알 수 없는 사용자 2024. 1. 13. 04:08
반응형

목차

    화면에서 사용자가 체크한 row의 데이터들만 서버로 보내서 엑셀 다운로드 창을 브라우저에게 띄우게 하고 엑셀 다운로드 하는 로직

    체크박스 엑셀 다운로드

    springBoot 2.7.7, jdk 11 version

    view

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    
      <div class="contents">
          <h2>엑셀 다운로드 예제</h2>
    
          <div class="tbl scroll-x">
                <table>
                  <caption>목록</caption>
                  <colgroup>
                    <col width="60px">
                    <col width="60px">
                    <col width="100px">
                    <col width="150px">
                  </colgroup>
                  <thead>
                  <tr>
                    <th scope="row">체크박스</th>
                    <th scope="row">순번</th>
                    <th scope="row">사원명</th>
                    <th scope="row">직업</th>
                  </tr>
                  </thead>
                  <tbody class="center">
                    <tr>
                      <td><input type="checkbox" class="checkbox"></td>
                      <td>kkh</td>
                      <td>김경호</td>
                      <td>가수</td>
                    </tr>
                    <tr>
                      <td><input type="checkbox" class="checkbox"></td>
                      <td>ljb</td>
                      <td>박완규</td>
                      <td>가수</td>
                    </tr>
                    <tr>
                      <td><input type="checkbox" class="checkbox"></td>
                      <td>jkh</td>
                      <td>정경화</td>
                      <td>가수</td>
                    </tr>
                  </tbody>
                </table>
    
                <button id="btn">엑셀 다운로드</button>
              </div>
      </div>
    
        <script>
            function downloadExcel() {
    			//데이터 담을 배열				
                var selectedData = [];
    			//class명이 checkbox인 친구들 루프 돌며 td 엘리먼트에서 텍스트를 가져온다.
                $('.checkbox:checked').each(function() {
                    var rowData = $(this).closest('tr');
                    var fields = rowData.find('td');
    				//td에 표시된 데이터들을 JSON형식으로 세팅
                    var dataObject = {
                        id: fields.eq(1).text(),
                        name: fields.eq(2).text(),
                        job: fields.eq(3).text(),
                    };
    				//배열에 JSON 데이터 저장
                    selectedData.push(dataObject);
                });
    			//엑셀다운로드 url + 데이터 인코딩한 값을 쿼리스트링으로 붙인 값으로 주소 변경
                var downloadUrl = '/user/downloadExcel?selectedData=' + encodeURIComponent(JSON.stringify(selectedData));
                window.location.href = downloadUrl;
            }
    
            $("#btn").on("click", function () {
                downloadExcel();
            });
        </script>
    </html>

    의존성(gradle)

    // poi
    implementation 'org.apache.poi:poi:5.1.0'	// xls
    implementation 'org.apache.poi:poi-ooxml:5.1.0'	//xlsx

    Controller(VO버전)

    본래 컨트롤러에는 비즈니스 로직이 없어야 하지만 여기선 예시니까 비즈니스 로직 서비스로 빼지 않았다.(귀찮아서)

    @GetMapping("/downloadExcel")
    //JSON타입의 문자열을 받는다.
    public void downloadExcel(@RequestParam(name = "selectedData") String selectedData, HttpServletResponse response) throws IOException {
    	//ExcelVO타입의 list를 받는다.(ExcelVO는 id, name, job만 있는 VO다.)				
        List<ExcelVO> dataList = convertJsonToList(selectedData);
    	//엑셀파일 하나 생성				
        Workbook wb = new XSSFWorkbook();
        //시트 하나 생성
        Sheet sheet = wb.createSheet("test");
    
        // header(상단 제목)
        Row headerRow = sheet.createRow(0);	//row 삽입
        //row의 셀(열) 세팅
        headerRow.createCell(0).setCellValue("아이디");
        headerRow.createCell(1).setCellValue("이름");
        headerRow.createCell(2).setCellValue("직업");
    
        // body(헤더 아래 본문)
        int rowNum = 1;
        //리스트 루프 돌며 vo의 값으로 셀의 값 세팅
        for (ExcelVO vo : dataList) {
            Row row = sheet.createRow(rowNum++);
            row.createCell(0).setCellValue(vo.getId());
            row.createCell(1).setCellValue(vo.getName());
            row.createCell(2).setCellValue(vo.getJob());
        }
    		
        String fileName = "엑셀다운로드.xlsx";
        //파일명이 한글이기에 인코딩
        fileName = URLEncoder.encode(fileName, "UTF-8");
    
        // HTTP 응답 설정(브라우저에게 파일다운로드 표시 요청)
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
    
        // 엑셀 파일을 HTTP 응답 스트림에 쓰기
        wb.write(response.getOutputStream());
        wb.close();
    }
    
    //JSON 타입의 데이터를 ExcelVO타입의 List로 변환 후 반환
    private List<ExcelVO> convertJsonToList(String jsonData) throws IOException {
    
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readValue(jsonData, new TypeReference<List<ExcelVO>>() {});
    }

    Controller(map 버전 + 키값 한글 매핑)

    @GetMapping("/downloadExcel")
    public void downloadExcel(@RequestParam(name = "selectedData") String selectedData, HttpServletResponse response) throws IOException {
    		//map 버전
        List<Map<String, String>> dataList = convertJsonToList(selectedData);
    
        Workbook wb = new XSSFWorkbook();
        Sheet sheet = wb.createSheet("test");
    
        // header
        Row headerRow = sheet.createRow(0);
    
        int cellNum = 0;
        for (String key : dataList.get(0).keySet()) {
    				//헤더값 한글 세팅(맵의 키값과 매핑되는 한글)
            String headerName = convertToKorean(key);
            headerRow.createCell(cellNum++).setCellValue(headerName);
        }
        // body
        int rowNum = 1;
        for (Map<String, String> data : dataList) {
           Row row = sheet.createRow(rowNum++);
    
           cellNum = 0;
           //맵의 value로 셀 세팅
           for (String key : data.keySet()) {
               row.createCell(cellNum++).setCellValue(data.get(key));
           }
        }
    
        String fileName = "엑셀다운로드.xlsx";
        fileName = URLEncoder.encode(fileName, "UTF-8");
    
        // HTTP 응답 설정
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
    
        // 엑셀 파일을 HTTP 응답 스트림에 쓰기
        wb.write(response.getOutputStream());
        wb.close();
    }
    
    //JSON데이터를 String, String타입의 Map형식의 리스트로 변환 후 반환
    private List<Map<String, String>> convertJsonToList(String jsonData) throws IOException {
    
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readValue(jsonData, new TypeReference<List<Map<String, String>>>() {});
    }
    
    // 키값을 한글로 변환하는 메서드
    private String convertToKorean(String key) {
    
        switch (key) {
                case "rowNum":
                    return "순번";
                case "id":
                    return "아이디";
                case "name":
                    return "이름";
                case "job":
                    return "직업";
                // 추가 필드가 있을 경우 계속해서 매핑
                default:
                    return key;
            }
    }

    아래는 이 부분을 나름 모듈화 한 내용이다.

     

    [spring] spring excel download (feat. 공통으로 분리)

    목차 아래 포스팅에서 이어진 내용입니다. [spring] spring excel download (feat. 체크박스) 목차 화면에서 사용자가 체크한 row의 데이터들만 서버로 보내서 엑셀 다운로드 창을 브라우저에게 띄우게 하

    yaga.tistory.com


    개인 스터디 기록을 메모하는 공간이라 틀린점이 있을 수 있습니다.

    틀린 점 있을 경우 댓글 부탁드립니다.

     

    반응형