티스토리 뷰

알고리즘 풀이현황을 보여주는 엑셀 파일을 자동으로 생성해주는 프로그램을 개발했다.

자바 코드를 컴파일해서 엑셀파일을 얻는 것이기 때문에 프로그램이라고 말하기에는 좀 그렇지만, 사용자는 오직 나 한명이기 때문에 충분하다고 생각한다.

프로그램을 개발하게된 배경은, 매일 알고리즘을 풀고 풀이현황을 수동으로 엑셀에 정보(문제번호, 문제명, URL, 완료유무, 재풀이 필요유무)를 입력하였다. 

수동으로 입력하기 때문에 가끔 오타가 있었던 적도 있고, 주말에 한번에 입력한 적도 있었고, 매번 귀찮고 번거로웠다. 그래서 개발을 했다!

알고리즘을 풀때 나는 일정한 규칙을 가지고 패키지명과 파일을 구성했다. 


 1. 패키지명은 'Q + 문제번호' 이다. 하지만, 풀이가 완료되지 않는 문제는 'Q + 문제번호 + _Not' 으로 패키지를 만들었다.

   * 풀이유무는 패키지명에 '_Not' 키워드의 유무로 확인할 수 있다.

 2. 백준 알고리즘은 제출할 때, 클래스명은 Main이기 때문에 모든 파일들은 Main.java 이다.

 3. 문제의 상단에는 주석으로 아래와 같이 문제에 대한 정보가 작성되어 있다. 

    /*

     문제명 : 

     url : 

     재풀이 : 

    */


항상 일정한 규칙을 통해 파일을 구성해서 문제를 풀기 때문에 이 규칙을 활용해서 파일 리스트를 얻고, 엑셀 파일로 구성했다.

엑셀 파일은 POI 라이브러리를 이용해서 구현했다. POI 라이브러리는 처음 사용했다. HTML 에서 테이블을 구현하는 것과 비슷해서 어렵지 않았다.

처음 적을 때는 어렵지 않다고 생각했는데, 소스코드를 아래 붙이니까 어려운게 아니라, 복잡해 보인다..

ExcelCreator는 알고리즘 문제현황에 대한 정보를 전달받으면 엑셀을 만들어주는 클래스이다. 인스턴스 변수를 사용하지 않고 상수만 사용하기 때문에 모두 클래스메소드이다.

프로그래머스 현황도 추출할 수 있도록 추가할 예정인데, 그때 같이 리팩토링을 해야겠다. 자세한 코드는 git 에 업로드했다.

 git : https://github.com/lkhlkh23/AlgorithmIndexCreator

[ExcelCreator.java]

package domain;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;

public class ExcelCreator {

    private static final String DIRECTORY_PATH = "/Users/lee_ki_hyun/Desktop";
    private static final int MAXIMUM_DIGIT_WIDTH = 7;
    private static final int PADDING_WIDTH = 10;
    private static final String SHEET_NAME = "BaekJoon Algorithm List";
    private static Sheet sheet;
    private static Workbook xlsWb;
    private static int rowIndex = 0;
    private static Map cellStyleMap = new HashMap<>();

    static {
        // Workbook 생성 //
        xlsWb = new HSSFWorkbook();
        // Sheet 생성 //
        sheet = xlsWb.createSheet(SHEET_NAME);
        // CellStyle 초기화 //
        cellStyleMap.put("sorted_bold_lined_big", createStyleCell(true, true, true, false, true));
        cellStyleMap.put("sorted_bold", createStyleCell(true, true, false, false, false));
        cellStyleMap.put("sorted", createStyleCell(true, false, false, false, false));
        cellStyleMap.put("colored", createStyleCell(false, false, false, true, false));
        cellStyleMap.put("sorted_colored", createStyleCell(true, false, false, true, false));
        cellStyleMap.put("default", createStyleCell(false, false, false, false, false));
    }

    private ExcelCreator() {

    }

    // 컬럼 너비 설정하는 메소드 //
    public static void setSheetInfo() {
        sheet.setColumnWidth(0, calculateColumnWidth(10));
        sheet.setColumnWidth(1, calculateColumnWidth(40));
        sheet.setColumnWidth(2, calculateColumnWidth(40));
        sheet.setColumnWidth(3, calculateColumnWidth(10));
        sheet.setColumnWidth(4, calculateColumnWidth(10));
    }

    // 칼럼 너비 길이 계산하는 메소드 //
    public static int calculateColumnWidth(int numberOfCharacter) {
        // Truncate([{Number of Visible Characters} * {Maximum Digit Width} + {5 pixel padding}]/{Maximum Digit Width}*256) //
        // Maximum Digit : 7px(11pt) //
        return Math.round((numberOfCharacter * MAXIMUM_DIGIT_WIDTH + PADDING_WIDTH) / MAXIMUM_DIGIT_WIDTH * 256);
    }

    public static CellStyle createStyleCell(boolean isSorted, boolean isBold, boolean isLined, boolean isColored, boolean isBig) {
        CellStyle cellStyle = xlsWb.createCellStyle();
        Font font = xlsWb.createFont();
        cellStyle.setWrapText(true);

        if(isSorted) {
            cellStyle.setAlignment(HorizontalAlignment.CENTER); //가운데 정렬
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //높이 가운데 정렬
        }

        if(isLined) {
            font.setUnderline(Font.U_SINGLE);
        }

        if(isColored) {
            //배경색
            cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        }

        if(isBig) {
            font.setFontHeight((short)(14*20));
        }

        font.setBold(isBold);
        cellStyle.setFont(font);

        return cellStyle;
    }

    public static void createExcelFile(List fileComponents) {
        for(FileComponent fileComponent : fileComponents) {
            createRow(fileComponent);
        }
    }

    public static void createSummary() throws IOException {
        // 병합 열시작, 열종료, 행시작, 행종료
        sheet.addMergedRegion(new CellRangeAddress(0,2,0,2));
        Row row = sheet.createRow(rowIndex++);
        createCell(row, 0, "백준 알고리즘 문제풀이 현황", cellStyleMap.get("sorted_bold_lined_big"));

        createCell(row, 3, "총 문제", cellStyleMap.get("sorted_bold"));
        createCell(row, 4, String.valueOf(SourceReader.getQustionCount()), cellStyleMap.get("sorted"));


        row = sheet.createRow(rowIndex++);
        createCell(row, 3, "해결", cellStyleMap.get("sorted_bold"));
        createCell(row, 4, String.valueOf(SourceReader.getQustionCount() - SourceReader.getNotSolvedQuestionCount())
                    , cellStyleMap.get("sorted"));


        row = sheet.createRow(rowIndex++);
        createCell(row, 3, "미해결", cellStyleMap.get("sorted_bold"));
        createCell(row, 4, String.valueOf(SourceReader.getNotSolvedQuestionCount())
                    , cellStyleMap.get("sorted"));
    }


    public static void createHeader() {
        Row row = sheet.createRow(rowIndex++);
        CellStyle cellStyle = cellStyleMap.get("sorted_bold");
        createCell(row, 0, "번호", cellStyle);
        createCell(row, 1, "문제명", cellStyle);
        createCell(row, 2, "URL", cellStyle);
        createCell(row, 3, "완료유무", cellStyle);
        createCell(row, 4, "재풀이필요유무", cellStyle);
    }

    public static void createRow(FileComponent fileComponent) {
        // 줄 생성
        boolean isComplete = fileComponent.isComplete();
        String cellStyleText1 = "colored";
        String cellStyleText2 = "sorted_colored";
        if(isComplete) {
            cellStyleText1 = "default";
            cellStyleText2 = "sorted";
        }
        Row row = sheet.createRow(rowIndex++);
        createCell(row, 0, fileComponent.getQustionNo(), cellStyleMap.get(cellStyleText1));
        createCell(row, 1, fileComponent.getQustionName(), cellStyleMap.get(cellStyleText1));
        createCell(row, 2, fileComponent.getUrl(), cellStyleMap.get(cellStyleText1));
        createCell(row, 3, getCompelteSign(fileComponent.isComplete()), cellStyleMap.get(cellStyleText2));
        createCell(row, 4, fileComponent.getReviewed(), cellStyleMap.get(cellStyleText2));
    }

    public static String getCompelteSign(boolean flag) {
        if(flag) {
            return "O";
        }
        return "X";
    }

    public static void createCell(Row row, int cellIndex, String contents, CellStyle cellStyle) {
        Cell cell = null;
        cell = row.createCell(cellIndex);
        cell.setCellValue(contents);
        cell.setCellStyle(cellStyle); // 셀 스타일 적용
    }

    public static void saveExcel() {
        try {
            File xlsFile = new File(DIRECTORY_PATH + "/baekJoonAlgorithm.xls");
            FileOutputStream fileOut = new FileOutputStream(xlsFile);
            xlsWb.write(fileOut);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


아래는 프로그램을 동작시키고 나서 얻은 결과이다. 사진에서는 보이지 않지만, 완료하지 못한 문제는 셀의 색을 다르게 해서 강조를 했다! (깨알 자랑)



'Java' 카테고리의 다른 글

프로세스와 스레드  (0) 2018.12.28
람다와 스트림의 정의  (2) 2018.11.14
Map Value 정렬 (오름차순, 내림차순)  (2) 2018.11.05
멀티스레드  (0) 2018.10.27
예외처리2 - 사용자 정의 예외 클래스 생성  (0) 2018.10.04
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함