Apache Poi둜 μ—‘μ…€ λ‹€μš΄λ‘œλ“œ κΈ°λŠ₯ κ΅¬ν˜„ν•˜κΈ°

2024. 4. 15. 14:55ㆍSpring/개발 κ΄€λ ¨

728x90

 

μ΅œκ·Όμ— κ°„λ‹¨ν•œ μΆ”κ°€ 개발둜 μ—‘μ…€ λ‹€μš΄λ‘œλ“œ κΈ°λŠ₯ μš”μ²­μ΄ λ“€μ–΄μ™”λ‹€. 

μ—‘μ…€ λ‹€μš΄λ‘œλ“œ κΈ°λŠ₯ κ΅¬ν˜„μ΄μ•Ό 쉽지~ ν•˜κ³  제일 λ§ˆμ§€λ§‰μœΌλ‘œ 미뀄뒀닀가 λ‚˜μ˜ 개발 무지 (?) 둜 μΈν•΄μ„œ 1 ~ 2μ‹œκ°„μ΄λ©΄ μ™„μ„±ν•  것을 쀑간에 λ‹€λ₯Έ 일도 ν•˜λ©΄μ„œ 였λ₯˜ νŒŒμ•…ν•˜λŠλΌ.. 3μΌλ™μ•ˆ λŒμ—ˆλ˜ 것 κ°™λ‹€. 

일단 이걸 λͺ°λΌμ„œ 3일 λ™μ•ˆ λŒμ—ˆλ˜ λ‚΄κ°€ λ„ˆλ¬΄ ν•œμ‹¬ (?) ν•΄μ„œ.. λ‹€μŒμ—” λ˜‘κ°™μ€ μ‹€μˆ˜ ν•˜κ³  싢지 μ•Šμ•„μ„œ κΈ°λ‘ν•œλ‹€. 

( Okky μ—μ„œ 7년전에 μ§ˆλ¬Έν•˜μ‹  λΆ„ 덕뢄에 μ œκ°€ μ‚΄μ•˜μŠ΅λ‹ˆλ‹€.. 감사λ₯Ό.. 😭 )

 

이상 tmi μ˜€κ³ ,

λ°‘μ—μ„œλΆ€ν„°λŠ” 이제 μžλ°”λ‘œ Apache Poiλ₯Ό μ΄μš©ν•΄ κ°„λ‹¨ν•œ μ—‘μ…€ νŒŒμΌμ„ λ§Œλ“€μ–΄ λ‹€μš΄λ‘œλ“œ ν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€. 

 

0️⃣ Apache poi 라이브러리 λ‹€μš΄ 

https://mvnrepository.com/artifact/org.apache.poi/poi/4.1.2

-> 이 μ‚¬μ΄νŠΈμ—μ„œ Apache Poi 라이브러리λ₯Ό λ‹€μš΄λ°›μ„ 수 μžˆλ‹€. λ‚˜λŠ” μ˜ˆμ „ ν”„λ‘œμ νŠΈλΌμ„œ (거의 ~~ 10λ…„μ „ ν”„λ‘œμ νŠΈμΈκ²ƒ κ°™μŒ,, ) Apache Poi 라이브러리 버전은 3.9μ΄μ§€λ§Œ 이 글을 λ³΄μ‹œλŠ” 뢄듀은 비ꡐ적 졜근 + 많이 λ‹€μš΄λ°›μ€ 라이브러리λ₯Ό μ‚¬μš©ν•˜μ‹œκΈ°λ₯Ό ..!

(λ²„μ „λ³„λ‘œ 차이 μžˆλ‹€λŠ” 글을 μ–΄λ””μ„ κ°€ λ³Έ 것 κ°™κΈ°λŠ” ν•©λ‹ˆλ‹€λ§Œ... 이건 μ œν”Όμ…œμž…λ‹ˆλ‹€) ꡳ이 μ˜ˆμ „ 라이브러리 μ‚¬μš©ν•  ν•„μš”λŠ” μ—†μœΌλ‹ˆ... 

 

 

1️⃣ Controller 생성 

@RequestMapping(value = "/downloadExcel")
public void downloadExcel(HttpServletRequest request,  HttpServletResponse response)
{
    xxxService.selectExcelDataList(request, response);
}

-> μ΄λŸ°μ‹μœΌλ‘œ ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ μ—‘μ…€ λ‹€μš΄λ‘œλ“œ GET μš”μ²­μ„ ν•˜λ©΄, μ„œλ²„μ—μ„œ μ—‘μ…€ 데이터λ₯Ό μƒμ„±ν•΄μ„œ μ—‘μ…€ 파일 λ‹€μš΄λ‘œλ“œ ν•  수 μžˆλ„λ‘ ν•œλ‹€! 

μœ„μ— μ½”λ“œλŠ” 예제 μ½”λ“œλ‘œ ν…ŒμŠ€νŠΈμš©μ΄λΌλ©΄ ꡳ이 DB 쑰회λ₯Ό ν•˜μ§€ μ•Šμ•„λ„ λ˜λ‹ˆ, 직접 μ—‘μ…€ 데이터λ₯Ό 쑰금 λ§Œλ“€μ–΄μ„œ κ΅¬ν˜„ν•΄λ„ 될 λ“―ν•˜λ‹€. μ €λŠ” DB 쑰회λ₯Ό ν•΄μ„œ λ§Œλ“€μ–΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— Service도 λ”°λ‘œ λ§Œλ“  κ²ƒμž…λ‹ˆλ‹€ ~_~ 

 

 

2️⃣ Service 생성 

@Override
public void selectExcelDataList(HttpServletRequest request, HttpServletResponse response)
{
    List<xxxVo> resultList = xxxDao.selectExcelDataList(smishingVo);
    ExcelUtil.downloadExcel(resultList, request, response);
}

-> μ΄λŸ°μ‹μœΌλ‘œ μ„œλΉ„μŠ€λ₯Ό λ§Œλ“€μ–΄μ„œ μš°μ„  μ—‘μ…€ νŒŒμΌμ— 넣을 데이터λ₯Ό DBμ—μ„œ μ‘°νšŒν•΄μ„œ resultList에 λ‹΄κ³ , ExcelUtilμ΄λΌλŠ” Util 클래슀λ₯Ό λ§Œλ“€κ³  κ±°κΈ°μ„œ μ—‘μ…€ λ‹€μš΄ λ©”μ„œλ“œμ— resultListλ₯Ό λ„˜κ²¨μ€¬λ‹€. 

 

 

3️⃣ Excel, Sheet, Header 생성 

public static void downloadExcel(List<xxxVo> resultLit,
        HttpServletRequest request, HttpServletResponse response)
{
    String fileName = "Excel_" + DateUtil.getTodayDateTime("yyyyMMddHHmmss") + ".xlsx";
    String sheetName = "데이터 μ‹œνŠΈ";
    
    try
    {
        // WorkBook μ΄ˆκΈ°ν™”
        Workbook workbook = new SXSSFWorkbook();
       
        // Sheet μ΄ˆκΈ°ν™”
        Sheet sheet = workbook.createSheet(sheetName);
        
        // Row 생성
        Row row = sheet.createRow(0);
        
        // Cell 생성
        Cell cell1 = row.createCell(1);
        cell1.setCellValue("Cell1");
        cell1.setCellStyle(titleStyle);
        
        Cell cell2 = row.createCell(2);
        cell2.setCellValue("Cell2");
        cell2.setCellStyle(titleStyle);
        
        Cell cell3 = row.createCell(3);
        cell3.setCellValue("Cell3");
        cell3.setCellStyle(titleStyle);
        
        Cell cell4 = row.createCell(4);
        cell4.setCellValue("Cell4");
        cell4.setCellStyle(titleStyle);
        
        Cell cell5 = row.createCell(5);
        cell5.setCellValue("Cell15");
        cell5.setCellStyle(titleStyle);
        
        int i = 0;
        if (!resultLit.isEmpty()) {
for (xxxVo vo : resultLit)
{
    row = sheet.createRow((i + 1));
    
    cell1 = row.createCell(1);
    cell1.setCellValue();
    cell1.setCellStyle(stringStyle);
    
    cell2 = row.createCell(2);
    cell2.setCellValue();
    cell2.setCellStyle(stringStyle);
    
    cell3 = row.createCell(3);
    cell3.setCellValue();
    cell3.setCellStyle(stringStyle);
    
    cell4 = row.createCell(4);
    cell4.setCellValue();
    cell4.setCellStyle(stringStyle);
    
    cell5 = row.createCell(5);
    cell5.setCellValue();
    cell5.setCellStyle(stringStyle);
    
    i++;
}
        }
        
        //μˆ˜λ™ 컬럼 μ‚¬μ΄μ¦ˆ (λŒ€λž΅ 10κΈ€μž)
        sheet.setColumnWidth(1, 30*256);
        sheet.setColumnWidth(2, 20*256);
        sheet.setColumnWidth(3, 20*256);
        sheet.setColumnWidth(4, 20*256);
        sheet.setColumnWidth(5, 20*256);
        
        response.setContentType("application/x-msdownload");
        String encodedFileName = HttpUtil.getDisposition(fileName, HttpUtil.getBrowser(request));
        response.setHeader("Content-Disposition", encodedFileName);
        workbook.write(response.getOutputStream());
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    
}

 

- λ¨Όμ € λ‹€μš΄λ‘œλ“œ 받을 파일의 이름을 fileName에 μ„€μ •ν•΄μ€€λ‹€. (λ‚˜λŠ” λ‹€μš΄ 받을 λ•Œ λ§ˆλ‹€, 파일λͺ…이 (1), (2)... μ΄λ ‡κ²Œ λ‹€μš΄λ°›λŠ”κ²Œ μ‹«μ–΄μ„œ λ‚ μ§œ + μ‹œκ°„μ„ ν¬ν•¨ν•΄μ„œ 제λͺ©μ— λ„£μ–΄λ’€λ‹€.) 

- 그리고 μ‹œνŠΈ 이름은 κ·Έλƒ₯ μ˜ˆμ‹œλ‘œ '데이터 μ‹œνŠΈ'라고 ν–ˆλŠ”λ° 이건 μ‚¬μš©ν•˜λŠ” μ‚¬λžŒμ΄ μ›ν•˜λŠ” μ‹œνŠΈλͺ…을 λ„£μœΌλ©΄ λœλ‹€. 

 

- WorkBook을 μ΄ˆκΈ°ν™”ν•΄μ€€λ‹€. 

 Workbook workbook = new SXSSFWorkbook();

μ΄λ•Œ SXSSF λŠ” λŒ€μš©λŸ‰ μ—‘μ…€ νŒŒμΌμ„ 좜λ ₯ν•  λ•Œ μ‚¬μš©ν•œλ‹€. 

HSSF : .xls 파일 포맷을 μ‚¬μš©ν•  λ•Œ μ‚¬μš© 
XSSF : .xlsx 파일 포맷을 μ‚¬μš©ν•  λ•Œ μ‚¬μš© 
SXSSF : λŒ€μš©λŸ‰ μ—‘μ…€ νŒŒμΌμ„ 좜λ ₯ν•  λ•Œ μ‚¬μš© 

 

- 그리고 μŠ€νƒ€μΌμ„ 직접 λ³€κ²½ν•  μˆ˜λ„ μžˆλŠ”λ°.. μŠ€νƒ€μΌμ΄ μ§€κΈˆ μ€‘μš”ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— κ·Έλƒ₯ κΈ°λ³Έ μŠ€νƒ€μΌλ‘œ 진행할 μ˜ˆμ •μ΄λ‹€. 

(κ΅¬κΈ€λ§ν•˜λ©΄ μ—‘μ…€ μŠ€νƒ€μΌ λ°”κΎΈλŠ” 방법은 λ§ŽμŠ΅λ‹ˆλ‹€..!) 

 

- WorkBoot μ΄ˆκΈ°ν™”ν›„μ—λŠ” μš°λ¦¬κ°€ λ§Œλ“  μ‹œνŠΈ μ΄λ¦„μœΌλ‘œ μ‹œνŠΈλ₯Ό μƒμ„±ν•œλ‹€. 

        // Sheet μ΄ˆκΈ°ν™”
        Sheet sheet = workbook.createSheet(sheetName);

 

 

- 맨 처음 타이틀 rowλ₯Ό λ§Œλ“€μ–΄μ€˜μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— rowλ₯Ό μƒμ„±ν•˜κ³ , 타이틀 값듀을 μ •μ˜ν•΄μ€€λ‹€. 

        // Row 생성
        Row row = sheet.createRow(0);
        
        // Cell 생성
        Cell cell1 = row.createCell(1);
        cell1.setCellValue("Cell1");
        cell1.setCellStyle(titleStyle);
        
        Cell cell2 = row.createCell(2);
        cell2.setCellValue("Cell2");
        cell2.setCellStyle(titleStyle);
        
        Cell cell3 = row.createCell(3);
        cell3.setCellValue("Cell3");
        cell3.setCellStyle(titleStyle);
        
        Cell cell4 = row.createCell(4);
        cell4.setCellValue("Cell4");
        cell4.setCellStyle(titleStyle);
        
        Cell cell5 = row.createCell(5);
        cell5.setCellValue("Cell15");
        cell5.setCellStyle(titleStyle);

 

 

- 그리고 DBμ—μ„œ μ‘°νšŒν•΄ 온 데이터인 resultListλ₯Ό λ°˜λ³΅λ¬Έμ„ 톡해 row 생성해쀀닀. 

        int i = 0;
        if (!resultLit.isEmpty()) {
for (xxxVo vo : resultLit)
{
    row = sheet.createRow((i + 1));
    
    cell1 = row.createCell(1);
    cell1.setCellValue();
    cell1.setCellStyle(stringStyle);
    
    cell2 = row.createCell(2);
    cell2.setCellValue();
    cell2.setCellStyle(stringStyle);
    
    cell3 = row.createCell(3);
    cell3.setCellValue();
    cell3.setCellStyle(stringStyle);
    
    cell4 = row.createCell(4);
    cell4.setCellValue();
    cell4.setCellStyle(stringStyle);
    
    cell5 = row.createCell(5);
    cell5.setCellValue();
    cell5.setCellStyle(stringStyle);
    
    i++;
}
        }

 

 

- 그리고 데이터 κΈΈμ΄λ•Œλ¬Έμ— μ—‘μ…€ 처음 λ‹€μš΄λ°›κ³  데이터 확인할 λ•Œ 칸이 μ’μœΌλ‹ˆκΉŒ μˆ˜λ™μœΌλ‘œ 컬럼 μ‚¬μ΄μ¦ˆλ₯Ό μ‘°μ ˆν–ˆλ‹€. 

(이것도 찾아보면 μžλ™μœΌλ‘œ 컬럼 μ‚¬μ΄μ¦ˆ μ‘°μ ˆν•˜λŠ” 글듀이 많이 μžˆμ–΄μš” !) 

//μˆ˜λ™ 컬럼 μ‚¬μ΄μ¦ˆ (λŒ€λž΅ 10κΈ€μž)
        sheet.setColumnWidth(1, 30*256);
        sheet.setColumnWidth(2, 20*256);
        sheet.setColumnWidth(3, 20*256);
        sheet.setColumnWidth(4, 20*256);
        sheet.setColumnWidth(5, 20*256);

 

 

- μ΄λ ‡κ²Œ ν•˜λ©΄ μ—‘μ…€ νŒŒμΌμ€ μŠ€νƒ€μΌμ€ λ³„λ‘œκ² μ§€λ§Œ κΈ°λ³Έμ μœΌλ‘œλŠ” 완성이 됐닀..! 

그리고 이제 웹이라고 ν•œλ‹€λ©΄ μ—‘μ…€ λ‹€μš΄λ‘œλ“œ λ²„νŠΌμ΄ μžˆμ„ 것이고 κ·Έ λ²„νŠΌμ„ λˆŒλ €μ„ λ•Œ 엑셀을 파일둜 λ‹€μš΄λ‘œλ“œ ν•  수 μžˆλŠ” 방법이닀. 

        response.setContentType("application/x-msdownload");
        String encodedFileName = HttpUtil.getDisposition(fileName, HttpUtil.getBrowser(request));
        response.setHeader("Content-Disposition", encodedFileName);
        workbook.write(response.getOutputStream());

그리고 ν˜Ήμ‹œ ν•œκΈ€ 파일둜 λ‹€μš΄λ‘œλ“œ ν•˜κ³  μ‹Άλ‹€λ©΄ 인코딩을 ν•΄μ•Ό ν•œλ‹€. 

 

String encodedFileName = new String(filename.getBytes("UTF-8"), "ISO-8859-1");
rtnFileName = String.format("attachment; filename=\"%s\";", encodedFileName);

-> 크둬일 κ²½μš°μ—λŠ” μ΄λ ‡κ²Œ μΈμ½”λ”©ν•œ rtnFileName으둜 response header에 λ‹΄μ•„μ•Ό ν•œλ‹€. 

 

+ 그리고 ν˜Ήμ‹œ μ—‘μ…€ λ‹€μš΄λ‘œλ“œ κΈ°λŠ₯ κ΅¬ν˜„ν–ˆλŠ”λ° '파일 ν˜•μ‹ λ˜λŠ” 파일 ν™•μž₯λͺ…이 잘λͺ»λ˜μ–΄ xlsx νŒŒμΌμ„ μ—΄ 수 μ—†μŠ΅λ‹ˆλ‹€.' 이런 였λ₯˜κ°€ λ°œμƒν•œλ‹€λ©΄  workbook.write(response.getOutputStream()); <= 이 μ½”λ“œ μž‘μ„± ν–ˆλŠ”μ§€ ν™•μΈν•΄λ³΄μ„Έμš”..γ…Žγ…Ž μ €λŠ” λΉΌλ¨Ήκ³  ν–ˆλ‹€κ°€ 계~속 λ‹Ήμ—°νžˆ λ‹€μš΄λ§Œ 되고 μ•ˆμ—΄λ €μ„œ 또 ν•œμ°Έμ„ λ΄€λ„€μš” γ…Žγ…‹γ…‹ ν•˜... 

 

+ 그리고 ν˜Ήμ‹œ λ‹€ ~~ κ΅¬ν˜„ ν–ˆλŠ”λ° λ‹€μš΄λ‘œλ“œ λ²„νŠΌμ„ λˆŒλ €λŠ”λ° λ™μž‘μ„ μ•ˆν•œλ‹€λ©΄... ajax둜 λ™μž‘ν•˜λ„λ‘ ν–ˆλŠ”μ§€ ν™•μΈν•΄λ³΄μ„Έμš”... location.href둜 ν•΄μ•Ό ν•œλ‹€κ³  ν•˜λ”λΌκ³ μš”...? 기본적으둜 ajaxλŠ” 파일 λ‹€μš΄λ‘œλ“œλ₯Ό λͺ»ν•œλ‹€λŠ” 사싀을 μ œλŒ€λ‘œ μ•Œμ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€..... μ§„μ§œ 멍청.... πŸ˜‚πŸ˜‚πŸ˜‚πŸ˜‚ κ΅ν›ˆ μ”¨κ²Œ μ–»κ³  κ°‘λ‹ˆλ‹€ γ…‹γ…‹ γ…  

 

 

μ•”νŠΌ μ΄λ ‡κ²Œ κ°„λ‹¨ν•˜κ²Œ μ—‘μ…€ 파일 λ‹€μš΄λ‘œλ“œ κ΅¬ν˜„ν•˜λŠ” 방법에 λŒ€ν•΄μ„œ 기둝을 λ‚¨κΉλ‹ˆλ‹€. 

제 글이... μ–΄λ–€ ν•œ λΆ„μ—κ²ŒλΌλ„ 도움이 되길 πŸ˜€πŸ˜€πŸ˜€

 

 

 

 

 

 

728x90