web developer

[java] 엑셀 다운로드, 엑셀 읽어오기 [org.apache.poi] 본문

Language/Java

[java] 엑셀 다운로드, 엑셀 읽어오기 [org.apache.poi]

trueman 2022. 1. 18. 17:31
728x90
728x90

아파치 POI(Apache POI)이란?


아파치 소프트웨어 재단에서 만든 라이브러리로 마이크로소프트 오피스 파일을 자바 언어로 읽고 쓰는 기능 제공합니다. 주로 워드, 엑셀, 파워포인트 파일을 지원합니다.


1. pom.xml 설정

<dependency> 
    <groupId>org.apache.poi</groupId> 
    <artifactId>poi</artifactId> 
    <version>3.7</version> 
</dependency> 
<dependency> 
    <groupId>org.apache.poi</groupId> 
    <artifactId>poi-ooxml</artifactId> 
    <version>3.7</version> 
</dependency>

2. apache.poi - HSSF, XSSF 차이

- HSSF - Excel 97(-2007) 파일 포맷을 사용할 때 사용 , ex) HSSFWorkbook, HSSFSheet
- XSSF - Excel 2007 OOXML (.xlsx) 파일 포맷을 사용할 때 사용 , ex) XSSFWorkbook, XSSFSheet


3. 엑셀 다운로드 (TreeMap 활용)

package practice.test;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class PoiMakeExcel {
    public static String filePath = "C:\\poi_temp";
    public static String fileNm = "poi_making_file_test.xlsx";
    public static void main(String[] args) {
        // 빈 Workbook 생성
        XSSFWorkbook workbook = new XSSFWorkbook();
        // 빈 Sheet를 생성
        XSSFSheet sheet = workbook.createSheet("employee data");
        // Sheet를 채우기 위한 데이터들을 Map에 저장
        Map<String, Object[]> data = new TreeMap<>();
        data.put("1", new Object[]{"ID", "NAME", "PHONE_NUMBER"});
        data.put("2", new Object[]{"1", "cookie", "010-1111-1111"});
        data.put("3", new Object[]{"2", "sickBBang", "010-2222-2222"});
        data.put("4", new Object[]{"3", "workingAnt", "010-3333-3333"});
        data.put("5", new Object[]{"4", "wow", "010-4444-4444"});
        // data에서 keySet를 가져온다. 이 Set 값들을 조회하면서 데이터들을 sheet에 입력한다.
        Set<String> keyset = data.keySet();
        int rownum = 0;
        // 알아야할 점, TreeMap을 통해 생성된 keySet는 for를 조회시, 키값이 오름차순으로 조회된다.
        for (String key : keyset) {
            Row row = sheet.createRow(rownum++);
            Object[] objArr = data.get(key);
            int cellnum = 0;
            for (Object obj : objArr) {
                Cell cell = row.createCell(cellnum++);
                if (obj instanceof String) {
                    cell.setCellValue((String)obj);
                } else if (obj instanceof Integer) {
                    cell.setCellValue((Integer)obj);
                }
            }
        }
        try {
            FileOutputStream out = new FileOutputStream(new File(filePath, fileNm));
            workbook.write(out);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4. 엑셀 다운로드 (VO 활용)

/* 230918 poi 라이브러리를 활용하여 DB데이터를 가져와 엑셀 다운로드 */
@RequestMapping(value = "/excelDownload.do", method = RequestMethod.GET)
public void downloadExel(HttpServletResponse response) throws IOException {

    try{
        // 워크북(workboox) 생성
        Workbook workbook = new XSSFWorkbook();

        // 시트(sheet) 생성
        Sheet sheet = workbook.createSheet("명단");

        String fileName = "게시글 작성자 명단";
        int rowNo = 0;

        // 헤더 생성 
        Row headerRow = sheet.createRow(rowNo++);
        headerRow.createCell(0).setCellValue("고유아이디");
        headerRow.createCell(1).setCellValue("제목");
        headerRow.createCell(2).setCellValue("내용");
        headerRow.createCell(3).setCellValue("작성자");
        headerRow.createCell(4).setCellValue("비밀번호");
        headerRow.createCell(5).setCellValue("작성일자");

        List<BoardVO> boardList = boardService.selectBoardListPOi();
        for(BoardVO vo: boardList) {
            // row 추가
            Row row = sheet.createRow(rowNo++);

            // 해당 row에 데이터 넣기 
            row.createCell(0).setCellValue(vo.getId());
            row.createCell(1).setCellValue(vo.getSubject());
            row.createCell(2).setCellValue(vo.getContent());
            row.createCell(3).setCellValue(vo.getWriter());
            row.createCell(4).setCellValue(vo.getPassword());
            row.createCell(5).setCellValue(vo.getRegister_datetime());
        }

        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")+ ".xlsx");
        workbook.write(response.getOutputStream());

    }catch(IOException e){
        e.printStackTrace();
    }catch(Exception e){
        e.printStackTrace();
    }finally {
        try {
            //workbook.close();
        }catch (Exception e) {
            e.printStackTrace();
        }

    }
}

5. 엑셀 읽어오기 

/* xlsx 엑셀파일 읽어오기 */
@RequestMapping(value = "/excelRead.do", method = RequestMethod.GET)
public void downloadExel2(HttpServletResponse response) throws IOException {

    try{
        // FileInputStream 으로 파일 읽기
        String filePath = "C:\\Users\\test\\제목 없는 문서.xlsx";
        FileInputStream inputStream = new FileInputStream(filePath);

        // 워크북 생성
        Workbook workbook = new XSSFWorkbook(inputStream);
        int cellIndex = 0;

        // 첫번째 시트를 가져온다 
        Sheet sheet =  workbook.getSheetAt(0);

        // 여러개 인 경우 for 문을 이용하여 각각의 시트를 가져온다
        int rows = sheet.getPhysicalNumberOfRows(); // 사용자가 입력한 엑셀 Row수를 가져온다

        // 각 Row만큼 반복을 한다.
        for(int i=0; i < rows; i++){ // 엑셀 row수만큼 for문을 돌린다.
            Row row = sheet.getRow(i);

            if(row != null){
                int cells = row.getPhysicalNumberOfCells(); // 해당 Row에 사용자가 입력한 셀의 수를 가져온다

                // cell의 수 만큼 반복한다.
                for(cellIndex = 0; cellIndex <= cells; cellIndex++){  
                    Cell cell = row.getCell(cellIndex); // 셀의 값을 가져온다	        
                    String value = "";	                 

                    if(cell == null){ // 빈 셀 체크 
                        continue;
                    }else{
                        // 타입 별로 내용을 읽는다
                        switch (cell.getCellType()){
                        case Cell.CELL_TYPE_FORMULA:
                            value = cell.getCellFormula();
                            break;
                        case Cell.CELL_TYPE_NUMERIC:
                            value = cell.getNumericCellValue() + "";
                            break;
                        case Cell.CELL_TYPE_STRING:
                            value = cell.getStringCellValue() + "";
                            break;
                        case Cell.CELL_TYPE_BLANK:
                            value = cell.getBooleanCellValue() + "";
                            break;
                        case Cell.CELL_TYPE_ERROR:
                            value = cell.getErrorCellValue() + "";
                            break;
                        }
                    }
                    System.out.println( i + "번 행 : " + cellIndex + "번 열 값은: " + value);
                }
            }
        }
    }catch(Exception e) {
        e.printStackTrace();
    }
}

728x90
728x90
Comments