안녕하세요

 

자바 실무에서 엑셀 다운로드를 할때, 매번 apache poi를 사용한 엑셀 다운로드가 불편하여

 

SheetJS를 사용하기 시작했었는데, 무료버전은 스타일이 적용되지않아

 

스타일이 적용한 fork 된 버전을 찾아 사용 하여 후기 남깁니다

 

파일은 GitHub에 올려두었습니다.

 

https://github.com/wjsskagur/js_excel

 

GitHub - wjsskagur/js_excel: SheetJS를 fork한 xlsx-js-style 사용하여 엑셀 스타일 적용 및 다운로드 업로드

SheetJS를 fork한 xlsx-js-style 사용하여 엑셀 스타일 적용 및 다운로드 업로드 - GitHub - wjsskagur/js_excel: SheetJS를 fork한 xlsx-js-style 사용하여 엑셀 스타일 적용 및 다운로드 업로드

github.com

순수 html파일이 궁금하신분들은 only_html.html 파일 참고하시면 될것같습니다

(이외 파일은 Spring Boot 기반 프로젝트)

 

html 파일 우선 첨부합니다

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<section>
    <div>
        <button type="button" id="btn_excel">엑셀 다운로드</button>
    </div>
    <div>
        <input type="file" id="upload_file" accept=".xls, .xlsx" >
        <label for="upload_file" ></label>
        <!--            <button type="button" id="btn_save">저장</button>-->
    </div>
</section>
</body>
<script lang="javascript" src="/js/xlsx.js"></script>
<script src="/js/excel_js.js"></script>
<script>
    const list = [
        {"name":"홍길동","phone":"010-1234-5678"},
        {"name":"홍길순","phone":"012-1234-1255"},
        {"name":"홍길둔","phone":"010-5678-1234"}
    ];

    document.getElementById("btn_excel").addEventListener("click", () => {
        const header = ["이름","핸드폰"];

        // const response = fetch("/test/", {
        //     method: "POST",
        //     headers: {
        //         "Content-Type": "application/json",
        //     },
        //     body: JSON.stringify(list),
        // })
        //
        // const result = response.json();
        // download_excel(result, header, "시트 이름을 입력하세요", "테스트파일.xlsx")

        download_excel(list, header, "시트 이름을 입력하세요", "테스트파일.xlsx")
    })

    document.getElementById('upload_file').addEventListener('change', async () => {
        const target = document.getElementById('upload_file').files[0];
        await read_excel(target);
    });

</script>
</html>

 

업로드도 같이 샘플링 하기위해 파일을 간단하게 읽을 수 있는 버튼을 추가해두었습니다.

 

이어서 excel_js.js 파일입니다 ( xlsx.js 파일은 https://gitbrent.github.io/xlsx-js-style/ 에 있습니다. )

 

function download_excel(data, headers, sheetName, filename) {
    const wb = XLSX.utils.book_new(); // make Workbook of Excel
    const ws = XLSX.utils.json_to_sheet(data); // make Worksheet of Excel
    const wsCols = []; // for column width

    // ====================== set headers ===========================
    XLSX.utils.sheet_add_aoa(ws, [headers], {origin: "A1"});

    // ====================== set column width ======================
    data.map((item) => {
        Object.keys(item).map((key, index) => {
            let maxWidth;
            if (typeof item[key] === "number") {
                maxWidth = 10;
            } else if (wsCols[index] && item[key]) {
                maxWidth = wsCols[index].width < item[key].length ? (item[key].length+5) : wsCols[index].width;
            } else {
                maxWidth = item[key] !== null ? (item[key].length+5) : 10;
            }
            wsCols[index] = {width: maxWidth}
        })
    })

    ws['!cols'] = wsCols;
    // ==============================================================



    // ====================== set column style ======================
    for (i in ws) {
        if (typeof(ws[i]) != "object") continue;
        let cell = XLSX.utils.decode_cell(i);

        ws[i].s = { // styling for all cells
            font: {
                name: "arial"
            },
            alignment: {
                vertical: "center",
                horizontal: "center",
                wrapText: '1', // any truthy value here
            },
        };

        // if (cell.c === 0) { // first column
        //     ws[i].s.numFmt = "DD/MM/YYYY HH:MM"; // for dates
        //     ws[i].z = "DD/MM/YYYY HH:MM";
        // } else {
        //     ws[i].s.numFmt = "00.00"; // other numbers
        // }

        if (cell.r === 0 ) { // first row
            ws[i].s.fill = { // background color
                patternType: "solid",
                fgColor: { rgb: "b2b2b2" },
                bgColor: { rgb: "b2b2b2" }
            };
        }
    }
    // ==============================================================

    XLSX.utils.book_append_sheet(wb, ws, sheetName);
    XLSX.writeFile(wb, filename);
}

function read_excel(file) {
    const reader = new FileReader();
    reader.onload = function(e) {
        const data = e.target.result;
        const workbook = XLSX.read(data, {type: 'binary'});
        const sheetName = workbook.SheetNames[0];
        const worksheet = workbook.Sheets[sheetName];
        const json = XLSX.utils.sheet_to_json(worksheet, {raw: true});
        console.log(json);
    }
    reader.readAsBinaryString(file);
}

// Java LocalDate to Javascript Date
function convert_date(date, type) {
    let tmpDate;

    try {
        tmpDate = new Date(Date.parse(date));
    } catch (e) {
        return null;
    }
    if (type === "date") {
        return tmpDate.getFullYear() + "-" + ((tmpDate.getMonth() + 1) < 10 ? ("0" + (tmpDate.getMonth() + 1)) : (tmpDate.getMonth() + 1) ) + "-" + tmpDate.getDate();
    } else if(type === "datetime") {
        return tmpDate.getFullYear() + "-" + ((tmpDate.getMonth() + 1) < 10 ? ("0" + (tmpDate.getMonth() + 1)) : (tmpDate.getMonth() + 1) ) + "-" + tmpDate.getDate() + " " + tmpDate.getHours() + ":" + tmpDate.getMinutes() + ":" + tmpDate.getSeconds();
    }
}

 

html 파일에서 넘겨받은 데이터의 각 행의 값마다의 길이를 구하여 cell의 길이를 입력하고,

첫번째 행에 임의 스타일을 적용 해두었습니다.

 

질문이나 피드백은 댓글로 남겨주시면 확인후 답변하겠습니다.

+ Recent posts