HTML 테이블을 CSV 파일로 다운로드 하기

현업에서 테이블 형태로 정리된 데이터를 엑셀 파일로 다운로드 받는 것은 생각보다 빈번하며 중요합니다.

웹으로 모든 걸 구현해 온라인에서 해결할 수 있지만, 원시데이터를 다운로드 받아 엑셀에서 재가공하는 방식은 여전히 현실에서는 강력한 위력을 가지고 있습니다.

다만, 엑셀 파일로 테이블 데이터를 다운로드 하는 방식은 코스트가 많이 듭니다.

서버에서 네이티브 엑셀 파일을 생성하는 기능을 추가로 구현하거나, 자바스크립트를 사용해 클라이언트 PC의 웹브라우저 표시 화면에 여러개의 모듈을 부착해 네이티브 엑셀 파일을 생성하는 무거운 작업을 실행해야 합니다.

CSV(Comma Separated Values)는 단순 텍스트 데이터이고 콤마로 구분해 데이터를 단순하게 표현하기 때문에 최종 데이터 생성이 쉽고, 서버와 클라이언트에 부담이 적습니다.

비록 네이티브 엑셀 파일이 좀 더 세련되고, 데이터 타입의 명확한 표현이 가능하지만, 원시 데이터를 얻는 목적에 부합한다면 CSV는 엑셀보다 가볍고 빠른 대안이 될 수 있습니다.

먼저 화면에 표시되는 HTML 문서에 테이블이 하나 있다고 치고, 이 테이블 데이터를 CSV로 다운로드 받는 기능을 하는 버튼이 있는 걸로 합니다.

<!DOCTYPE html><html><head>    <meta charset="utf-8"></head><body><!-- "다운로드 버튼" -->    <a href="" id="download">다운로드</a>    <table id="csvtable">    <tr>        <th>열1</th>        <th>열2</th>        <th>열3</th>        <th>열4</th>        <th>열5</th>        <th>열6</th>        <th>열7</th>        <th>열8</th>        <th>열9</th>    </tr>    <tr>        <td>item1</td>        <td>item2</td>        <td>item3</td>        <td>item4</td>        <td>item5</td>        <td>item6</td>        <td>item7</td>        <td>item8</td>        <td>item9</td>    </tr><!-- "행데이터 추가" -->    ...    </table></body></html>

함수 이름은 saveCSV() 로 하고, 다운로드 버튼에 클릭 이벤트를 이 함수로 연결해주면 됩니다.

saveCSV() 함수만 구현하면 됩니다.

CSV 파일 생성은 Blob(Binary Large Object) 을 이용합니다.

블롭(Blob)은 바이트, 또는 바이너리 형태의 데이터를 담는 자바스크립트의 객체로 이미지 파일 등의 파일에서 읽은 데이터를 객체에 담아 HTML 요소에 적용할 때 주로 사용하는 객체입니다.

//다운로드 하이퍼링크에 클릭 이벤트 발생시 saveCSV 함수를 호출하도록 이벤트 리스너를 추가document.addEventListener('DOMContentLoaded', function(){  document.getElementById('download').addEventListener('click', function(){    saveCSV('data.csv'); // CSV파일 다운로드 함수 호출    return false;  })});
//CSV 생성 함수function saveCSV(fileName){    //CSV 문자열 생성    let downLink = document.getElementById('download');    let csv = ''; //CSV최종 문자열을 저장하는 변수    let rows = document.querySelectorAll("#csvtable tr"); // 테이블에서 행 요소들을 모두 선택
    //행단위 루핑    for (var i = 0; i < rows.length; i++) {        let cells = rows[i].querySelectorAll("td, th");        let row = [];        //행의 셀 값을 배열로 얻기        cells.forEach(function(cell){          row.push(cell.innerHTML);        });
        csv += row.join(',') + (i != rows.length-1 ? '\n':''); // 배열을 문자열+줄바꿈으로 변환    }
    //CSV 파일 저장    csvFile = new Blob([csv], {type: "text/csv"}); // 생성한 CSV 문자열을 Blob 데이터로 생성    downLink.href = window.URL.createObjectURL(csvFile); // Blob 데이터를 URL 객체로 감싸 다운로드 하이퍼링크에 붙임.    downLink.download = fileName; // 인자로 받은 다운로드 파일명을 지정}