기록/BACKEND

[SpringBoot] DB정보 엑셀로 다운로드하기

5월._. 2022. 8. 5.
728x90

1. pom.xml

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>4.1.2</version>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<scope>runtime</scope>
</dependency>

 

2. Excel Helper

업로드와 동일하게 POI의 Workbook, Sheet, Row, Cell 클래스를 사용한다.

간단한 과정은 다음과 같다.

1.  Workbook 생성

2.  Workbook에서 Sheet 생성

3.  파라미터로 받은 저장할 객체 리스트를 반복하면서 각 cell에 set한다. 

4.  ByteArrayOutputStream을 생성해서 workbook을 저장한다.

5.  ByteArrayOutputStream을 ByteArray로 변환한 뒤 ByteArrayInputStream을 최종 반환한다.

Workbook workbook = new XSSFWorkbook();
Sheet sheet = Workbook.createSheet(SHEET);
for (Tutorial tutorial : tutorials) {
  Row row = sheet.createRow(rowIdx++);
  row.createCell(0).setCellValue(tutorial.getId());
  row.createCell(1).setCellValue(tutorial.getTitle());
  row.createCell(2).setCellValue(tutorial.getDescription());
  row.createCell(3).setCellValue(tutorial.isPublished());
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
workbook.write(out);
return new ByteArrayInputStream(out.toByteArray());

 

활용

1.  서비스에서 이미 header 리스트와 엑셀로 쓸 정보를 순서대로 list에 담았다. 

2.  try with resource를 사용해 Workbook, ByteArrayOutputStream을 생성했다.

3.  row를 하나 생성할때는 sheet.createRow(행번호)를 사용한다. header를 저장하려고 하므로 createRow(0)을 사용해서 헤더를 썼다.

4.  그다음 rowIdx 변수를 이용해서 하나씩 늘려가며 row를 생성했다. cell 역시 cellIdx를 사용했다.

5.  모두 저장한 후 ByteArrayOutputStream에 Workbook 내용을 쓰고 ByteArrayInputStream를 반환했다.

public static ByteArrayInputStream avgScorelistToExcel(String[] HEADERs, List<ExcelApplicant> body) {
   SHEET = "시트이름";
   try (Workbook workbook = new XSSFWorkbook();
       ByteArrayOutputStream out = new ByteArrayOutputStream();) {
      Sheet sheet = workbook.createSheet(SHEET);
      // Header
      Row headerRow = sheet.createRow(0);
      for (int col = 0; col < HEADERs.length; col++) {
         Cell cell = headerRow.createCell(col);
         cell.setCellValue(HEADERs[col]);
      }
      int rowIdx = 1;
      int cellIdx;
      for (ExcelApplicant applicant:body) {
         Row row = sheet.createRow(rowIdx++);
         cellIdx = 0;
         row.createCell(cellIdx++).setCellValue(applicant.getName());
         row.createCell(cellIdx++).setCellValue(applicant.getEmail());
         for(Double score: applicant.getScores()){
            row.createCell(cellIdx++).setCellValue(score);
         }
      }
      workbook.write(out);
      return new ByteArrayInputStream(out.toByteArray());
   } catch (IOException e) {
      throw new RuntimeException("fail to import data to Excel file: " + e.getMessage());
   }
}

 

3. Service

1.  db정보를 포함해서 파일 제목을 따로 만드려고 메서드를 따로 뺐다. 그 내용은 생략했다. 

2.  ByteArrayInputStream을 반환하는 메서드를 만들었다. 헤더 배열을 구성하고 엑셀에 저장될 내용을 따로 list로 구성했다.

3.  ExcelHelper 메서드를 사용해 그 반환값을 Controller로 보낸다.

@Override
public String getExcelTitle() throws Exception {
    return "엑셀파일제목";
}

@Override
public ByteArrayInputStream exportExcel() throws Exception {
    //헤더
    String[] HEADERs = new String[2];
    HEADERs[0] = "이름";
    HEADERs[1] = "이메일";
    //생략
    
    //body
    ArrayList<ExcelApplicant> body = new ArrayList<>();
    //생략

    ByteArrayInputStream in = ExcelHelper.avgScorelistToExcel(HEADERs, body);
    return in;
}

 

4. Controller

1.  RestContoller다.

2.  GetMapping을 사용하고, ResponseEntity<Resource>를 반환한다.

3.  파일이름을 구해서 filename에 저장한다.

4.  서비스에서 반환받은 ByteArrayInputStream을 InputStreamResource로 바꾼다.

5.  밑 코드의 6~9번째 줄처럼 리턴한다.

@ApiOperation(value = "전체 지원자 항목별 상세 평가표 엑셀 다운로드", notes = "전체 지원자의 항목별 평균 점수를 엑셀로 다운로드한다.", response = Map.class)
@GetMapping("/download")
public ResponseEntity<Resource> getAllScoreTable() throws Exception {
    String filename = scoreService.getExcelTitle();
    InputStreamResource file = new InputStreamResource(scoreService.exportExcel());
    return ResponseEntity.ok()
            .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename)
            .contentType(MediaType.parseMediaType("application/vnd.ms-excel"))
            .body(file);
}

 

 

참고 : https://www.bezkoder.com/spring-boot-download-excel-file/

댓글