리액트 엑셀 업로드

2023. 4. 28. 11:02Library/React

728x90
반응형

일을 하다보면 값을 일일히 쳐서 데이터를 밀어넣는 경우보다 엑셀을 이용해 일괄로 데이터를 등록해야하는 경우가 있다.

이번 포스트는 리액트에서 엑셀을 업로드해 엑셀 내 데이터를 간단하게 다뤄보는 글을 써보려고 한다.

 

ReactJS | SheetJS Community Edition

 

ReactJS | SheetJS Community Edition

ReactJS is a JS library for building user interfaces.

docs.sheetjs.com

npm i --save https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz

 

 


0. 전체 코드

import React, { useState } from 'react';
import * as XLSX from 'xlsx'

const Excel = () => {
    const [result, setResult] = useState([]);
    const excelHandle = (e) => {

        const reader = new FileReader();
        reader.onload = (e) => {
            console.log(e)
            let data = e.target.result;
            console.log(data);

            const sheets = XLSX?.read(data,{type:"binary"});
            console.log(sheets)
            console.log(sheets.Sheets)
            console.log(sheets.SheetNames)

            const sheet = sheets.Sheets[sheets.SheetNames[0]]
            console.log(sheet)

            const sheet1_json = XLSX.utils.sheet_to_json(sheets.Sheets[sheets.SheetNames[0]]);
            console.log(sheet1_json)

            const sheet2_html = XLSX.utils.sheet_to_html(sheets.Sheets[sheets.SheetNames[1]])
            console.log(sheet2_html)


            let mutResult = [];
            let sheet2 = sheets.Sheets[sheets.SheetNames[0]]
            let row, rowNum, colNum;
            let range = XLSX.utils.decode_range(sheet2["!ref"]);

            for(rowNum = range.s.r; rowNum <= range.e.r; rowNum++){
                row = [];
                for (colNum = range.s.c; colNum <= range.e.c; colNum++){
                    var nextCell = sheet2[XLSX.utils.encode_cell({r:rowNum, c:colNum})]
                    if(typeof nextCell ==='undefined'){
                        row.push(<td>{}</td>)
                    }else{
                        row.push(<td>{nextCell.w}</td>);
                    }
                }
                mutResult.push(<tr>{row}</tr>)
            }

            setResult(mutResult)

        }

        reader.readAsBinaryString(e.target.files[0])
    }

    return (
        <>
        <div class="contents">
            <input
                type='file'
                onChange={(e)=>{
                    console.log(e)
                    console.log(e.target)
                    console.log(e.target.files)
                    excelHandle(e)
                }}
            />
            
            <table>
                <tbody>
                    {result}
                </tbody>
            </table>
        </div>
        </>
    );
};

export default Excel;

1. input 태그 내 엑셀파일

import React from 'react';
import * as XLSX from 'xlsx'

const Excel = () => {

    return (
        <div>
            <input
                type='file'
                onChange={(e)=>{
                    console.log(e)
                    console.log(e.target)
                    console.log(e.target.files)
                }}
            />
        </div>
    );
};

export default Excel;

먼저 input 태그를 만들어 파일을 업로드하고 로그를 찍어보면

 

  • e : 이벤트 객체
  • e.target : 이벤트가 발생한 타겟
  • e.target.files : 해당 태그 내 파일이 들어있는 배열

이 콘솔에 찍힌 것을 확인할 수 있다.

그렇다면 우리는 e.target.files 배열에 들어있는 엑셀 파일을 다루면 되겠고

보통은 e.target.files[0] 을 통해 꺼내오거나

다중파일업로드를 이용하는 사람이라면 원하는 배열 인덱스 혹은 반복문을 통해 해당 파일을 다루면 되겠다.

 

 


2. 엑셀파일 읽기

import React from 'react';
import * as XLSX from 'xlsx'

const Excel = () => {
    
    const excelHandle = (e) => {

        const reader = new FileReader();
        reader.onload = (e) => {

        }

        reader.readAsBinaryString(e.target.files[0])
    }

    return (
        <div>
            <input
                type='file'
                onChange={(e)=>{
                    console.log(e)
                    console.log(e.target)
                    console.log(e.target.files)
                    excelHandle(e)
                }}
            />
        </div>
    );
};

export default Excel;

인풋 태그에 파일이 올라가면 excelHandle 함수가 실행된다.

해당 함수 내에서는 먼저 FileReader를 생성해준 후 onload 함수를 정의해준다.

이후 FileReader의 readAsBinaryString함수를 실행해주면 onload 함수가 돌기때문에

우리는 onload함수 내에서 원하는 작업을 처리할 것이다.

readAsBinaryString 함수의 파라미터로 엑셀파일을 넘겨준다.

 

 


3. 엑셀 내 데이터 다루기

먼저 다뤄볼 엑셀은 과일과 자동차 시트를 가지고 있다.

 

 

reader.onload = (e) => {
    console.log(e)
    let data = e.target.result;
    console.log(data);

    const sheets = XLSX.read(data,{type:"binary"});
    console.log(sheets)
    console.log(sheets.Sheets)
    console.log(sheets.SheetNames)

}

로그를 찍어보면

파라미터로 넘어온 데이터중 우리가 필요한 엑셀 내부 데이터는 e.target.result 안에 들어있는 것을 확인할 수 있다.

이를 sheet.js에서 제공하는 함수를 이용해 읽어보면 (XLSX.read(data,{type:"binary"}))

 

sheets 변수에 엑셀파일에 대한 정보가 담겨있는 것을 확인할 수 있으며

sheets의 키값 중 Sheets에 현재 가지고있는 시트들이 객체로,

SheetNames에 시트들의 이름이 배열로 담겨있는 것을 확인할 수 있다.

 

우리가 필요한 각 셀들의 데이터는

Sheets 객체에 시트이름이 키, 시트 내용이 값으로 들어있으며,

시트내용은 또한번 셀번호가 키, 데이터가 값으로 들어있다.

우리는 시트이름을 이용해 전체 시트중 원하는 시트의 데이터를 가져오면 된다.

 

 

reader.onload = (e) => {
    console.log(e)
    let data = e.target.result;
    console.log(data);

    const sheets = XLSX?.read(data,{type:"binary"});
    console.log(sheets)
    console.log(sheets.Sheets)
    console.log(sheets.SheetNames)

    const sheet = sheets.Sheets[sheets.SheetNames[0]]


    const sheet1_json = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
    console.log(web)

    const sheet2_html = XLSX.utils.sheet_to_html(wb.Sheets[wb.SheetNames[1]])
    console.log(html)

}

 

sheet.js에서 제공하는 함수를 이용해 시트내용을 json객체 혹은 html로 변환할 수 있다.

sheet_to_json : 시트 정보를 파라미터로 받아 json 객체를 리턴한다.

sheet_to_html : 시트 정보를 파라미터로 받아 html을 반환한다.

시트정보는 전체 시트내용 중 시트이름을 키값으로 꺼내와 사용했다. 

위는 sheet_to_json, 아래는 sheet_to_html의 결과로

원하는 데이터를 갖다 쓰면 된다.

 

 

현재 엑셀은 가장 위에 속성명이 적혀있기 때문에 json으로 변환할 때 자동으로 키값이 설정되지만

엑셀 내 데이터 형태에 따라 json으로 변환하기 애매할 때가 있다.

그럴 경우 각 셀을 가져와 배열을 돌려 원하는대로 만들 수 있다.

 

reader.onload = (e) => {
            console.log(e)
            let data = e.target.result;
            console.log(data);

            const sheets = XLSX?.read(data,{type:"binary"});
            console.log(sheets)
            console.log(sheets.Sheets)
            console.log(sheets.SheetNames)

            const sheet = sheets.Sheets[sheets.SheetNames[0]]
            console.log(sheet)

            const sheet1_json = XLSX.utils.sheet_to_json(sheets.Sheets[sheets.SheetNames[0]]);
            console.log(sheet1_json)

            const sheet2_html = XLSX.utils.sheet_to_html(sheets.Sheets[sheets.SheetNames[1]])
            console.log(sheet2_html)


            let mutResult = [];
            let sheet2 = sheets.Sheets[sheets.SheetNames[0]]
            let row, rowNum, colNum;
            let range = XLSX.utils.decode_range(sheet2["!ref"]);

            for(rowNum = range.s.r; rowNum <= range.e.r; rowNum++){
                row = [];
                for (colNum = range.s.c; colNum <= range.e.c; colNum++){
                    var nextCell = sheet2[XLSX.utils.encode_cell({r:rowNum, c:colNum})]
                    if(typeof nextCell ==='undefined'){
                        row.push(<td>{}</td>)
                    }else{
                        row.push(<td>{nextCell.w}</td>);
                    }
                }
                mutResult.push(<tr>{row}</tr>)
            }

            setResult(mutResult)

        }

 

 

728x90
반응형

'Library > React' 카테고리의 다른 글

리액트 엑셀 다운로드  (0) 2023.04.28
fetch 페치란  (0) 2023.03.29
axios 액시오스란  (0) 2023.03.29
리액트 DB데이터로 메뉴 트리뷰 만들기  (0) 2023.03.29
리액트 페이징 처리  (0) 2023.03.29