IT/development

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

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

목차

    화면에서 사용자가 체크한 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


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

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

     

    반응형

    댓글

    💲 추천 글