[인실리코젠] Apache POI 라이브러리를 이용한 Exel 데이터 읽기 2

2024. 1. 12. 12:51·인실리코젠
더보기

이번 포스팅은 문제 조건에 따른 문제 풀이 설명입니다.

Type 객체 사용하지 않음

여러 방면을 시도해본 끝에 Type 객체를 사용하지 않고 문제를 해결할 수 있었다. 생각해보면 너무 어렵게 접근한 것 같다.

 


Team 클래스 수정!

먼저 코드부터 살펴보자

package sample;

public class Team{
    private String teamName;
    private int games;
    private int wins;
    private int draws;
    private int losses;
    private double score;
    
    // 기본 생성자
    public Team() {
    }

    // 매개변수를 받는 생성자
    public Team(String teamName, int games, int wins, int draws, int losses,double score) {
        this.teamName = teamName;
        this.games = games;
        this.wins = wins;
        this.draws = draws;
        this.losses = losses;
        this.score = 0.0;
    }

    // Getter 및 Setter 메서드
    public String getTeamName() {
        return teamName;
    }

    public void setTeamName(String teamName) {
        this.teamName = teamName;
    }

    public int getGames() {
        return games;
    }

    public void setGames(int games) {
        this.games = games;
    }

    public int getWins() {
        return wins;
    }

    public void setWins(int wins) {
        this.wins = wins;
    }

    public int getDraws() {
        return draws;
    }

    public void setDraws(int draws) {
        this.draws = draws;
    }

    public int getLosses() {
        return losses;
    }

    public void setLosses(int losses) {
        this.losses = losses;
    }
    
    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }
    
    // toString 메서드 오버라이드
    @Override
    public String toString() {
        return "2018K리그[" +
                "팀명='" + teamName + '\'' +
                ", 경기수=" + games +
                ", 승=" + wins +
                ", 무승부=" + draws +
                ", 패=" + losses +
                ", 승점=" + score +
                ']';
    }
}
팀명, 경기수, 승, 무, 패, 총점 을 클래스 변수로 선언하여 각 셀에 맞는 값을 저장할 수 있도록 하였음

 

이전 포스팅에서 엑셀 데이터를 불러올 때 코드를 보면 Cell의 타입별로 value값을 지정하였다. Cell로 올 수 있었던 타입에는 NUMERIC , STRING, BLANK, ERROR 가 있는데 엑셀에서 불러지는 데이터에는 NUMERIC 과 STRING 뿐이다. 따라서 불러온 값들을 하나의 자료형으로 통일 시키고 변환된 자료형을 재가공 하는게 어떨까 하는 생각을 하였다.

 

  // 셀의 값을 문자열로 변환하는 메서드
    private static String getCellValueAsString(XSSFCell cell) {
        if (cell == null) {
            return "";
        }

        CellType cellType = cell.getCellType();

        switch (cellType) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                return String.valueOf((int) cell.getNumericCellValue());
            default:
                return "";
        }
    }

위 메소드를 통해서 각 셀의 값을 모두 문자열로 반환한다. STRING 과 NUMERIC이 아닌 경우 ""를 반환하여 오류가 발생하지 않도록 처리하였다.

 

엑셀 데이터의 각 셀을 받아 값을 지정하는 코드는 아래와 같이 작성하였다.

  // 팀 리스트 생성
            List<Team> teams = new ArrayList<>();

            // 각 행을 순회
            for (int rowNo = 1; rowNo < rows; rowNo++) {
                XSSFRow row = sheet.getRow(rowNo);

                // 새로운 팀 객체 생성
                Team team = new Team();

                // 각 열을 순회
                for (int colNo = 0; colNo < cols; colNo++) {
                    XSSFCell cell = row.getCell(colNo);

                    // 각 셀의 값을 문자열로 변환
                    String cellValue = getCellValueAsString(cell);

                    // 각 열에 따라 팀 객체에 값을 설정
                    // Type 객체를 사용하고 싶었지만 액셀 열의 값을 아는 경우 아래 코드가 더 깔끔하다고 생각됨.
                    switch (colNo) { // 팀 , 경기수 , 승 , 무 , 패 순서
                        case 0:
                            team.setTeamName(cellValue);
                            break;
                        case 1:
                            team.setGames(Integer.parseInt(cellValue));
                            break;
                        case 2:
                            team.setWins(Integer.parseInt(cellValue));
                            break;
                        case 3:
                            team.setDraws(Integer.parseInt(cellValue));
                            break;
                        case 4:
                            team.setLosses(Integer.parseInt(cellValue));
                            break;
                        default:
                            break;
                    }
                }

                // 팀 객체를 리스트에 추가
                teams.add(team);
            }

 

각 행과 열을 순회하면서 Team 클래스 setter에 맞도록 값을 지정한다. 첫 번째 행을 제외하고 순회를 돌렸다. 첫 행은 "팀명 , 경기수 , 승 , 무 , 패" 로 이루어져있기 때문에 Team 객체에 들어가면 안되는 값들이기 때문이다.

 

전체적인 코드는 아래와 같다.

package sample;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class readFile {
    public static void main(String[] args) {
        try {
            // 엑셀 파일을 읽기 위한 FileInputStream 생성
            FileInputStream file = new FileInputStream("2018K리그.xlsx");

            // XSSFWorkbook 객체 생성하여 엑셀 파일 로드
            XSSFWorkbook workbook = new XSSFWorkbook(file);

            // 첫 번째 시트 가져오기
            XSSFSheet sheet = workbook.getSheetAt(0);

            // 행의 수
            int rows = sheet.getPhysicalNumberOfRows();

            // 열의 수
            int cols = sheet.getRow(0).getPhysicalNumberOfCells();

            // 팀 리스트 생성
            List<Team> teams = new ArrayList<>();

            // 각 행을 순회
            for (int rowNo = 1; rowNo < rows; rowNo++) {
                XSSFRow row = sheet.getRow(rowNo);

                // 새로운 팀 객체 생성
                Team team = new Team();

                // 각 열을 순회
                for (int colNo = 0; colNo < cols; colNo++) {
                    XSSFCell cell = row.getCell(colNo);

                    // 각 셀의 값을 문자열로 변환
                    String cellValue = getCellValueAsString(cell);

                    // 각 열에 따라 팀 객체에 값을 설정
                    // Type 객체를 사용하고 싶었지만 액셀 열의 값을 아는 경우 아래 코드가 더 깔끔하다고 생각됨.
                    switch (colNo) { // 팀 , 경기수 , 승 , 무 , 패 순서
                        case 0:
                            team.setTeamName(cellValue);
                            break;
                        case 1:
                            team.setGames(Integer.parseInt(cellValue));
                            break;
                        case 2:
                            team.setWins(Integer.parseInt(cellValue));
                            break;
                        case 3:
                            team.setDraws(Integer.parseInt(cellValue));
                            break;
                        case 4:
                            team.setLosses(Integer.parseInt(cellValue));
                            break;
                        default:
                            break;
                    }
                }

                // 팀 객체를 리스트에 추가
                teams.add(team);
            }

            // 엑셀 파일 사용 후에는 닫아주어야 함
            workbook.close();
            file.close();

            // 결과 출력
            System.out.println("엑셀 파일 읽은 후 객체 저장 후 출력");
            for (Team team : teams) {
                System.out.println(team);
            }
            
            // 각 팀 승점 계산
            int wins = 0, draws = 0, losses = 0;
            for(int i = 0 ; i < teams.size() ; i++) {         	
            	wins += (teams.get(i).getWins() * 3);
            	draws += (teams.get(i).getDraws() + 1);
            	losses += (teams.get(i).getLosses());
            	
            	int total = wins + draws + losses;
            	
            	double score = (double)(total / teams.get(i).getGames());
            	
            	teams.get(i).setScore(score);
            }
            
            System.out.println("승점 계산 후 출력");
         
            // 계산 후 출력
            for (Team team : teams) {
                System.out.println(team);
            }
            
            System.out.println("내림차순 정렬 후 출력");
            // 내림차순 정렬
            // Comparable 내에 정의된 Collection 클래스 사용
            // 참고 : https://www.daleseo.com/java-comparable-comparator/
            Collections.sort(teams, (a, b) -> (int)b.getScore() - (int)a.getScore());

            // 정렬 후 출력
            for (Team team : teams) {
                System.out.println(team);
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 셀의 값을 문자열로 변환하는 메서드
    private static String getCellValueAsString(XSSFCell cell) {
        if (cell == null) {
            return "";
        }

        CellType cellType = cell.getCellType();

        switch (cellType) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                return String.valueOf((int) cell.getNumericCellValue());
            default:
                return "";
        }
    }
    
    
}

 

글을 작성하다보니 Type 객체를 사용하여서도 충분히 구현할 수 있을 것이라 판단되었다.

위에서 언급했듯이 첫 번째 행을 제외하고 case를 0-4로 나누어 각 열에 맞는 값을 저장하였다.

 

그 뜻은 첫 행은 Type에 해당 된다는 뜻이므로 첫 행에 대한 값들을 Type 리스트로 저장하면 된다.

 

            List<Type> types = new ArrayList<>();
            
            XSSFRow rowZero = sheet.getRow(0);
          
            
            for (int colNo = 0; colNo < cols; colNo++) {
            	Type type = new Type();
                XSSFCell cell = rowZero.getCell(colNo);
                
                // 각 셀의 값을 문자열로 변환
                String cellValue = getCellValueAsString(cell);
                type.setType(cellValue);
                types.add(type);
            }
            System.out.println("타입 출력 ");
            System.out.println(types);

Type 객체에 엑셀의 첫 행의 값을 저장하는 코드이다.  Team 객체에 값을 저장하는 방식과 많이 유사하다.

타입 출력 
[팀 , 경기수 , 승 , 무 , 패 ]

출력 결과 선언한 각 객체에 셀에 맞는 값이 잘 저장되었고 리스트로 표현할 수 있었다.

 

위 데이터를  Team 객체에 저장할 때 각 값에 맞는 데이터를 저장할 수 있도록 가공한다.

            for (int rowNo = 1; rowNo < rows; rowNo++) {
                XSSFRow row = sheet.getRow(rowNo);

                // 새로운 팀 객체 생성
                Team team = new Team();

                // 각 열을 순회
                for (int colNo = 0; colNo < cols; colNo++) {
                    XSSFCell cell = row.getCell(colNo);

                    // 각 셀의 값을 문자열로 변환
                    String cellValue = getCellValueAsString(cell);

                    // 각 열에 따라 팀 객체에 값을 설정
                    switch (types.get(colNo).getType()) { // 팀 , 경기수 , 승 , 무 , 패 
                        case "팀":
                            team.setTeamName(cellValue);
                            break;
                        case "경기수":
                            team.setGames(Integer.parseInt(cellValue));
                            break;
                        case "승":
                            team.setWins(Integer.parseInt(cellValue));
                            break;
                        case "무":
                            team.setDraws(Integer.parseInt(cellValue));
                            break;
                        case "패":
                            team.setLosses(Integer.parseInt(cellValue));
                            break;
                        default:
                            break;
                    }
                }

                // 팀 객체를 리스트에 추가
                teams.add(team);
            }

수정 된 최종 소스 코드


▷readFile.java

package sample;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class readFile {
    public static void main(String[] args) {
        try {
            // 엑셀 파일을 읽기 위한 FileInputStream 생성
            FileInputStream file = new FileInputStream("2018K리그.xlsx");

            // XSSFWorkbook 객체 생성하여 엑셀 파일 로드
            XSSFWorkbook workbook = new XSSFWorkbook(file);

            // 첫 번째 시트 가져오기
            XSSFSheet sheet = workbook.getSheetAt(0);

            // 행의 수
            int rows = sheet.getPhysicalNumberOfRows();

            // 열의 수
            int cols = sheet.getRow(0).getPhysicalNumberOfCells();

            // 팀 리스트 생성
            List<Team> teams = new ArrayList<>();
            List<Type> types = new ArrayList<>();
            
            XSSFRow rowZero = sheet.getRow(0);
          
            
            for (int colNo = 0; colNo < cols; colNo++) {
            	Type type = new Type();
                XSSFCell cell = rowZero.getCell(colNo);
                
                // 각 셀의 값을 문자열로 변환
                String cellValue = getCellValueAsString(cell);
                type.setType(cellValue);
                types.add(type);
            }
            System.out.println("타입 출력 ");
            System.out.println(types);

            // 각 행을 순회
            
            
            
            for (int rowNo = 1; rowNo < rows; rowNo++) {
                XSSFRow row = sheet.getRow(rowNo);

                // 새로운 팀 객체 생성
                Team team = new Team();

                // 각 열을 순회
                for (int colNo = 0; colNo < cols; colNo++) {
                    XSSFCell cell = row.getCell(colNo);

                    // 각 셀의 값을 문자열로 변환
                    String cellValue = getCellValueAsString(cell);

                    // 각 열에 따라 팀 객체에 값을 설정
                    switch (types.get(colNo).getType()) { // 팀 , 경기수 , 승 , 무 , 패 
                        case "팀":
                            team.setTeamName(cellValue);
                            break;
                        case "경기수":
                            team.setGames(Integer.parseInt(cellValue));
                            break;
                        case "승":
                            team.setWins(Integer.parseInt(cellValue));
                            break;
                        case "무":
                            team.setDraws(Integer.parseInt(cellValue));
                            break;
                        case "패":
                            team.setLosses(Integer.parseInt(cellValue));
                            break;
                        default:
                            break;
                    }
                }

                // 팀 객체를 리스트에 추가
                teams.add(team);
            }

            // 엑셀 파일 사용 후에는 닫아주어야 함
            workbook.close();
            file.close();

            // 결과 출력
            System.out.println("엑셀 파일 읽은 후 객체 저장 후 출력");
            for (Team team : teams) {
                System.out.println(team);
            }
            
            // 각 팀 승점 계산
            int wins = 0, draws = 0, losses = 0;
            for(int i = 0 ; i < teams.size() ; i++) {         	
            	wins += (teams.get(i).getWins() * 3);
            	draws += (teams.get(i).getDraws() + 1);
            	losses += (teams.get(i).getLosses());
            	
            	int total = wins + draws + losses;
            	
            	double score = (double)(total / teams.get(i).getGames());
            	
            	teams.get(i).setScore(score);
            }
            
            System.out.println("승점 계산 후 출력");
         
            // 계산 후 출력
            for (Team team : teams) {
                System.out.println(team);
            }
            
            System.out.println("내림차순 정렬 후 출력");
            // 내림차순 정렬
            // Comparable 내에 정의된 Collection 클래스 사용
            // 참고 : https://www.daleseo.com/java-comparable-comparator/
            Collections.sort(teams, (a, b) -> (int)b.getScore() - (int)a.getScore());

            // 정렬 후 출력
            for (Team team : teams) {
                System.out.println(team);
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 셀의 값을 문자열로 변환하는 메서드
    private static String getCellValueAsString(XSSFCell cell) {
        if (cell == null) {
            return "";
        }

        CellType cellType = cell.getCellType();

        switch (cellType) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                return String.valueOf((int) cell.getNumericCellValue());
            default:
                return "";
        }
    }
}

▷Team.java

package sample;

public class Team{
    private String teamName;
    private int games;
    private int wins;
    private int draws;
    private int losses;
    private double score;
    
    // 기본 생성자
    public Team() {
    }

    // 매개변수를 받는 생성자
    public Team(String teamName, int games, int wins, int draws, int losses,double score) {
        this.teamName = teamName;
        this.games = games;
        this.wins = wins;
        this.draws = draws;
        this.losses = losses;
        this.score = 0.0;
    }

    // Getter 및 Setter 메서드
    public String getTeamName() {
        return teamName;
    }

    public void setTeamName(String teamName) {
        this.teamName = teamName;
    }

    public int getGames() {
        return games;
    }

    public void setGames(int games) {
        this.games = games;
    }

    public int getWins() {
        return wins;
    }

    public void setWins(int wins) {
        this.wins = wins;
    }

    public int getDraws() {
        return draws;
    }

    public void setDraws(int draws) {
        this.draws = draws;
    }

    public int getLosses() {
        return losses;
    }

    public void setLosses(int losses) {
        this.losses = losses;
    }
    
    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }
    
    // toString 메서드 오버라이드
    @Override
    public String toString() {
        return "2018K리그[" +
                "팀명='" + teamName + '\'' +
                ", 경기수=" + games +
                ", 승=" + wins +
                ", 무승부=" + draws +
                ", 패=" + losses +
                ", 승점=" + score +
                ']';
    }
}

▷Type.java

package sample;

public class Type {
	private String type;
	
	
	public Type() {
		//
	}
	
	public Type(String type) {
		this.type =type;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}
	
	@Override
	public String toString() {
	    return type + " ";
	}
}

 

최종 실행 화면

 

 

https://github.com/MinWook6457/Insilicogen-Test

 

GitHub - MinWook6457/Insilicogen-Test

Contribute to MinWook6457/Insilicogen-Test development by creating an account on GitHub.

github.com

 

 

'인실리코젠' 카테고리의 다른 글

[인실리코젠] WebCrawling - 1  (0) 2024.01.16
[인실리코젠] Maven에 대하여  (0) 2024.01.12
[인실리코젠] Programmers Lv2.JadenCase 문자열 만들기 리뷰 답변 및 BPM(Business Process Management) 프로세스 모델링  (1) 2024.01.11
[인실리코젠] Apache POI 라이브러리를 이용한 Exel 데이터 읽기  (2) 2024.01.11
[인실리코젠] 배열 vs 리스트  (1) 2024.01.11
'인실리코젠' 카테고리의 다른 글
  • [인실리코젠] WebCrawling - 1
  • [인실리코젠] Maven에 대하여
  • [인실리코젠] Programmers Lv2.JadenCase 문자열 만들기 리뷰 답변 및 BPM(Business Process Management) 프로세스 모델링
  • [인실리코젠] Apache POI 라이브러리를 이용한 Exel 데이터 읽기
min._.uuk_
min._.uuk_
하루 하나 기록하기
  • min._.uuk_
    기록하는 습관
    min._.uuk_
  • 전체
    오늘
    어제
    • 분류 전체보기 (33)
      • 알고리즘 (15)
      • 자바 스크립트 (2)
      • 인실리코젠 (15)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    #BOJ #백준 #10989번 #C언어 #카운팅정렬 #정렬
    JS #테트리스 #HTML #CSS #추억의 게임
    백준 #1407번 #재귀함수
    백준 #후위표기식 #스택 #중위표기식 #우선순위 #1918번
    인실리코젠 #크롤링 #SpringBoot #MVC #jQuery
    백준 #세그먼트 트리 #구간합 #c언어 #골드1 #탐색
    백준 #BOJ #스택 #수열
    Apache #POI #JAVA #maven
    백준 #MST #최소비용신장트리 #크루스칼 #그리디 #알고리즘
    백준 #동적계획법 #dp #백트래킹 #dfs
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
min._.uuk_
[인실리코젠] Apache POI 라이브러리를 이용한 Exel 데이터 읽기 2
상단으로

티스토리툴바