해당 글은 (주)인실리코젠 이수호 주임님께서 주신 문제에 대한 풀이입니다.
문제 : 2017-2018 K리그팀들의 규칙에 따른 승점과 순위를 구하시오. ※ 규칙에 따르면 경기에서 이긴 팀은 3점을 얻고 비기면 1을 지면 0점을 받는다. ※ (첨부된 2018K리그 엑셀 파일 리스트를 불러와서 구현)->API 활용(POI) 결과 예) 팀 = 대구 ,승점 = 101 순위= 1 팀 = 울산 ,승점 =94 순위= 2 팀 = 서울 ,승점 =68 순위= 3 팀 = 수원 ,승점 =48 순위= 4 팀 = 전북 ,승점 =41 순위= 5 ...
조건
- 정렬 알고리즘 구현할 필요 없음(원하면 해도 됨)
- 출력은 console에 찍히는 정도로
- 엑셀 파일 관련 라이브러리 : Apache POI
2018K리그.xlsx
팀 | 경기수 | 승 | 무 | 패 |
전남 | 38 | 8 | 8 | 22 |
경남 | 38 | 18 | 11 | 9 |
울산 | 38 | 17 | 12 | 9 |
전북 | 38 | 26 | 8 | 4 |
수원 | 38 | 13 | 11 | 14 |
대구 | 38 | 14 | 8 | 16 |
제주 | 38 | 14 | 12 | 12 |
강원 | 38 | 12 | 10 | 16 |
인천 | 38 | 10 | 12 | 16 |
상주 | 38 | 10 | 10 | 18 |
서울 | 38 | 9 | 13 | 16 |
포항 | 38 | 15 | 9 | 14 |
Apache POI란?
아파치 소프트웨어 재단에서 만든 라이브러리로 마이크로소프트 오피스 파일 포맷을 순수 자바언어로 읽고 쓰는 기능을 제공
사용 버전
- 표준프레임워크 eGovFrame
- Apache POI 4.1.2
- Apache tomcat 9.0
기본적인 버전 다운로드는 구글링을 통해 여러 게시글을 참고 하였으며 해당 과정은 생략하겠음
Apache POI 라이브러리를 사용하려면 Maven 프로젝트를 생성하여 pom.xml 파일에 dependency(의존성)을 추가해주어야 한다.

Maven Dependencies 파일을 확인해보자.

알맞게 추가된 것을 확인할 수 있다.
이제 엑셀에서 파일을 불러오는 코드를 작성해보자.
오픈 소스를 사용하여 내 입맛에 맞게 수정하였다.
readFile.java
package sample;
//-*- coding: utf-8 -*-
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
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) throws Exception{
try {
// 경로에 있는 파일을 읽기
FileInputStream file = new FileInputStream("2018K리그.xlsx");
XSSFWorkbook workbook = new XSSFWorkbook(file);
int rowNo = 0;
int cellIndex = 0;
XSSFSheet sheet = workbook.getSheetAt(0); // 0 번째 시트를 가져온다
// 만약 시트가 여러개 인 경우 for 문을 이용하여 각각의 시트를 가져온다
int rows = sheet.getPhysicalNumberOfRows(); // 사용자가 입력한 엑셀 Row수를 가져온다
List<Team> teams = new ArrayList<>();
List<Type> types = new ArrayList<>();
for(rowNo = 0; rowNo < rows; rowNo++){
XSSFRow row = sheet.getRow(rowNo);
if(row != null){
int cells = row.getPhysicalNumberOfCells(); // 해당 Row에 사용자가 입력한 셀의 수를 가져온다
for(cellIndex = 0; cellIndex <= cells; cellIndex++){
XSSFCell cell = row.getCell(cellIndex); // 셀의 값을 가져온다
String value = "";
if(cell == null){ // 빈 셀 체크
continue;
}else{
// 타입 별로 내용을 읽는다
switch (cell.getCellType()){
case FORMULA :
value = cell.getCellFormula();
break;
case NUMERIC:
double cellValue = cell.getNumericCellValue();
if (cellValue == Math.rint(cellValue)) { // Math.rint를 이용
value = String.valueOf((int) cellValue); // Math.rint는 가장 가까운 int 값을 찾아 double 형태로 변환
} else {
value = String.valueOf(cellValue);
}
break;
case STRING:
value = cell.getStringCellValue() + "";
if(value.equals("팀")||value.equals("경기수")||value.equals("승")||value.equals("무")||value.equals("패"))
((Type) types).setType(value);
else
((Team) teams).setTeamName(value);
break;
case BLANK:
value = cell.getBooleanCellValue() + "";
break;
case ERROR:
value = cell.getErrorCellValue() + "";
break;
default:
break;
}
}
System.out.print(value + " ");
}
System.out.println("");
}
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
해당 소스코드에서 중요한 핵심 키워드는 아래와 같다.
Workbook, Sheet, Row, Cell
- Workbook은 하나의 엑셀 파일을 의미
- Sheet는 엑셀파일(= Workbook)의 시트를 의미
- Row, Cell 은 Sheet 안에 있는 행과 열을 의미
순서는 다음과 같다.
1. workbook 객체 생성
2. workbook 내에 sheet를 생성
3. sheet 내에 row를 생성
4. 하나의 row에 여러개의 cell을 생성 (= 하나의 행에 여러 열을 생성)
5. 3과 4의 과정을 계속해서 반복
값이 NUMBERIC인 경우 double로 반환?!
- 제목으로 알 수 있듯이 NUMERIC인 경우 double로 반환한다.
- 이를 해결하기 위해 아래 코드를 추가하였다.
case NUMERIC:
double cellValue = cell.getNumericCellValue();
if (cellValue == Math.rint(cellValue)) { // Math.rint를 이용
value = String.valueOf((int) cellValue); // Math.rint는 가장 가까운 int 값을 찾아 double 형태로 변환
} else {
value = String.valueOf(cellValue);
}
break;
Team 클래스 (Team.java)
package sample;
class Team {
private String name;
private int points;
public Team(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int getPoints() {
return points;
}
public void setTeamName(String name) {
this.name = name;
}
public void setPoints(int points) {
this.points = points;
}
}
Type 클래스 (Type.java)
package sample;
public class Type {
private String type;
public Type(String type) {
this.type =type;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
코드를 먼저 확인하고 나서 설명을 하는 것이 좋을거라 판단되어 먼저 코드를 올려두었습니다. 아직 완성되지 않은 단계이며 풀이를 진행중에 있다는 점을 기억해주시면 감사하겠습니다.
Team 객체는 각 팀의 정보를 저장한다. 팀명과 승점이 필요하여 name과 points를 선언하였다. 경기수 , 승, 무, 패 각각 저장하는 방식보다 조건절로 승,무,패를 나눠 해당 팀의 승점을 구하는 로직이 더 낫다고 판단하였기 때문이다.
Type 객체는 액셀 시트 맨 첫 줄에 해당한다. Type 객체에 경기수, 승, 무, 패 를 저장하고 Exel 요소를 순회하면서 각 타입에 맞는 점수를 Team 객체 points에 저장하여 승점을 계산한다.
아직 완벽한 구현은 되지 않았으며 Exel에서 값을 읽어오는 것 까지만 성공하였다.

'인실리코젠' 카테고리의 다른 글
[인실리코젠] WebCrawling - 1 (0) | 2024.01.16 |
---|---|
[인실리코젠] Maven에 대하여 (0) | 2024.01.12 |
[인실리코젠] Apache POI 라이브러리를 이용한 Exel 데이터 읽기 2 (0) | 2024.01.12 |
[인실리코젠] Programmers Lv2.JadenCase 문자열 만들기 리뷰 답변 및 BPM(Business Process Management) 프로세스 모델링 (1) | 2024.01.11 |
[인실리코젠] 배열 vs 리스트 (1) | 2024.01.11 |