💻 it/development

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

꼬비랩 2025. 11. 15.

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


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

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

 

[springBoot + mybatis] 개발환경 세팅(테스트 영상 & 소스코드 포함)

스프링부트로 개발 시 mybatis를 정말 간편하게 세팅할 수 있다. 😄역시나 시간이 지나면 기억을 못하기 때문에 미래의 내가 보기 위해 이곳에 기록한다.예시를 위해서 테이블을 하나 생성하고

yaga.tistory.com

 

 

[springBoot] 프로젝트 세팅(IntelliJ 사용)

목차 springBoot 프로젝트 세팅(IntelliJ 사용) https://start.spring.io 접속 후 프로젝트 세팅 후 다운로드(IntelliJ에서 spring initializr해도 같은 결과) 프로젝트 빌드도구 선택 -> 요즘 Gradle로 넘어가는 추세라

yaga.tistory.com

 

 

[AWS] EC2 + Docker + RDS로 쉽게 배우는 서버 및 DB 구축 가이드 🚀💻📦

이 포스팅은 AWS 회원가입부터 EC2/RDS 인스턴스 생성 및 웹서버와 연동한 기본 가이드입니다.빠른 시일내에 AWS 회원가입부터 아키텍처 3까지 구축하는 라이브 영상 포스팅 예정입니다.2025년 2월15

yaga.tistory.com

댓글