React(리액트)에서 Excel(엑셀) 파일을 읽고 이를 웹 화면에 보여주고, 편집하고 다시 저장 또는 다운로드는 기능을 만들고 싶은데... 생각보다 쉽지 않습니다.


막상 ReactJS 기반의 Excel API 라이브러리를 찾아봐도 마땅한 것들이 없습니다.
아주 단순하게 정형화된 Excel 파일에 있는 단순 데이터를 JSON 형태로 코드 단에 읽어오는 것만 가능하지만, 우리가 원하는 Excel(엑셀) 그 자채를 리액트JS 웹 애플리케이션으로 가져올 수는 없어 많은 좌절을 격으셨을 꺼에요 ㅜㅜ.


이번 스터디에서는 React(리액트JS)의 JavaScript 코드 만으로 웹 상에서 여러 수식과 양식(스타일, 테두리, 색상, 이미지 등)이 적용되어 있는 엑셀(Excel) 파일(xlsx)을 그대로 읽고, 이를 Excel 형태로 웹 화면에 보여주고 사용자가 쉽게 편집할 수 있는 방법을 설명합니다.


서버측 기술없이도 클라이언트 기술로만 로컬에 저장된 엑셀(Excel) 파일의 수식부터 차트, 셀 서식, 이미지 등을 그대로 읽고 수정 및 저장할 수 있는, React(리액트) 전용 Execl UI & API Module(모듈)인 SpreadJS를 사용하여 엑셀 파일을 자유롭게 다루는 방법을 JS코드로 정리해 봅니다.

"ReactJS(리액트JS)에서 Excel 화면(UI/UX) 부터 Excel 모든 기능을 웹으로 가져오고 싶을때 SpreadJS 하나로 모두 해결 가능합니다." 😲




샘플 프로젝트 실행

아래 링크를 통해서 React(리액트) 코드로 개발한 Excel 가져오기/내보내기 실제 동작하는 샘플과 코드를 볼 수 있습니다.

- React에서 Excel(엑셀) 파일 가져오기/내보내기 (바로가기)




1. React 프로젝트 만들기

빈 React 프로젝트를 만들어 봅니다!!

npm init react-app sjs-react-app 

//(옵션) yarn을 사용한다면 
yarn create react-app sjs-react-app

//이후 폴더 이동
cd sjs-react-app

2. SpreadJS npm 패키지 설치

필요한 SpreadJS의 모듈을 모두 설치합니다.


npm을 사용한다면,

npm install @mescius/spread-sheets-react @mescius/spread-sheets @mescius/spread-sheets-charts  @mescius/spread-sheets-io @mescius/spread-sheets-pivot-addon @mescius/spread-sheets-resources-ko @mescius/spread-sheets-shapes @mescius/spread-sheets-slicers file-saver

(옵션) yarn을 사용한다면,

yarn add @mescius/spread-sheets-react @mescius/spread-sheets @mescius/spread-sheets-charts  @mescius/spread-sheets-io @mescius/spread-sheets-pivot-addon @mescius/spread-sheets-resources-ko @mescius/spread-sheets-shapes @mescius/spread-sheets-slicers

3. 프로젝트에 SpreadJS React 컴포넌트 추가/초기화

src 폴더 내의 App.js 파일을 연 후 , App.js 내부의 내용을 아래 코드로 대체합니다.

import './App.css';
import React, { useRef } from 'react';
import ReactDOM from 'react-dom/client';
import * as GC from '@mescius/spread-sheets';
import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react';
import '@mescius/spread-sheets-shapes';
import '@mescius/spread-sheets-charts';
import '@mescius/spread-sheets-slicers';
import '@mescius/spread-sheets-pivot-addon';
import '@mescius/spread-sheets-io';
import '@mescius/spread-sheets-resources-ko';
import '@mescius/spread-sheets/styles/gc.spread.sheets.excel2016colorful.css';
import { saveAs } from 'file-saver';

GC.Spread.Common.CultureManager.culture('ko-kr');

function App() {
  let hostStyle = {
    width: '100%',
    height: '600px'
  }

  // SpreadJS 초기화
  let initSpread = function (spread) {
    let sheet = spread.getActiveSheet();
    sheet.getCell(0, 0).vAlign(GC.Spread.Sheets.VerticalAlign.center).value('Hello SpreadJS!');
  }

  return (
    <div className="App">
      <SpreadSheets workbookInitialized={spread => initSpread(spread)}  hostStyle={hostStyle}>
        <Worksheet> </Worksheet>
      </SpreadSheets>
    </div>
  );
}

export default App;

4. Excel 불러오기/저장을 위한, HTML 요소 만들기

파일을 불러오고 내보내는 버튼들과 SpreadJS 컴포넌트를 띄울 div를 추가합니다.

  return (
    <div>
      <div className="row">
        <div className="left">
          <SpreadSheets
            workbookInitialized={(spread) => initSpread(spread)}
            hostStyle={hostStyle}
          >
            <Worksheet></Worksheet>
          </SpreadSheets>
        </div>

        <div className="right">
          <div>
            <h4> Excel 가져오기 </h4>
            <input type="file" name="files[]" id="fileDemo" accept=".xlsx" />
            <button onClick={ImportFile}>불러오기</button>
          </div>
          <div>
            <h4> Excel 내보내기 </h4>
            파일명:
            <input
              type="text"
              id="exportFileName"
              placeholder="Export file name"
              value={minutes}
              onChange={(e) => setMinutes(e.target.value)}
            />
            <button onClick={Export_Excel}>저장하기</button>
          </div>
          <div>
            <h4> 특정 셀(Cell) 데이터 가져오기 </h4>
            <button onClick={getCellData}>콘솔로 A1 & B2:D4 값 가져오기</button>
          </div>
        </div>
      </div>
    </div>
  );

5. css 설정

App.css 파일 내에 아래 코드를 추가합니다.

div.row {
  width: 100%;
  display: flex;
  gap: 15px;
}

div.left {
  width: 70%;
  float: left;
  box-sizing: border-box;
}

div.right {
  width: 30%;
  float: left;
  box-sizing: border-box;
}

이제 화면 구성을 끝났습니다!!!
위의 코드를 실행하면 아래 이미지와 같은 화면을 볼 수 있습니다.

이제 각 버튼들의 엑셀 저장/불러오기 등의 동작들을 구현해 보도록 하겠습니다.


6. SpreadJS로 Excel 파일 가져오기

  const ImportFile = () => {
    let file = document.getElementById('fileDemo').files[0];
    let fileType = file.name.split('.');
    if (fileType[fileType.length - 1] == 'xlsx') {
      spread.import(
        file,
        function () {},
        function (e) {
          console.log(e); // error callback
        },
        {
          // 참고: https://demo.mescius.co.kr/spreadjs/learn-spreadjs/features/spreadjs-file-format/overview/react
          fileType: GC.Spread.Sheets.FileType.excel,
        }
      );
    }
  };

7. SpreadJS로 Excel 파일 내보내기

  const Export_Excel = () => {
    let fileName = document.getElementById('exportFileName').value;
    if (fileName.substr(-5, 5) !== '.xlsx') {
      fileName += '.xlsx';
    }
    spread.export(
      function (blob) {
        saveAs(blob, fileName);
      },
      function (e) {
        console.log(e);
      },
      {
        // ExportXlsxOptions - https://developer.mescius.com/spreadjs/api/modules/GC.Spread.Sheets#exportxlsxoptions
        fileType: GC.Spread.Sheets.FileType.excel,
      }
    );
  };

8. SpreadJS 특정 셀 데이터 가져오기

SpreadJS에서는 Excel 시트에 있는 데이터들을 JavaScirpt 코드로 가져올 수 있는 함수들을 제공합니다.

특정 셀의 데이터 읽기

아래와 같은 코드로 특정 셀에 있는 데이터 값을 가져올 수 있습니다.

    //현재 시트 가져오기
    let sheet = spread.getActiveSheet();
    
    // A1 데이터 가져오기
    let val = sheet.getValue(0, 0);
    console.log('A1-', val);      

특정 셀 영역의 데이터 읽기

getArray 함수를 이용하여 특정 셀 영역에 있는 데이터 값을 배열(Array)형태로 가져올 수 있습니다.

  const getCellData = () => {
    //현재 시트 가져오기
    let sheet = spread.getActiveSheet();
    
    // B2:D4 데이터 가져오기
    let arr = sheet.getArray(1, 1, 3, 3);
    console.log('B2:D4-', arr);
  };

아래는 HTML 버튼을 눌렀을때, SpreadJS 위에 있는 Excel 시트 상의 데이터를 읽어 Console로 보여주는 샘플 코드 입니다.

  const getCellData = () => {
    let sheet = spread.getActiveSheet();
    // A1 데이터 가져오기
    let val = sheet.getValue(0, 0);
    console.log('A1-', val);
    // B2:D4 데이터 가져오기
    let arr = sheet.getArray(1, 1, 3, 3);
    console.log('B2:D4-', arr);
  };



전체 코드

import './App.css';
import React, { useRef } from 'react';
import ReactDOM from 'react-dom/client';
import * as GC from '@mescius/spread-sheets';
import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react';
import '@mescius/spread-sheets-shapes';
import '@mescius/spread-sheets-charts';
import '@mescius/spread-sheets-slicers';
import '@mescius/spread-sheets-pivot-addon';
import '@mescius/spread-sheets-io';
import '@mescius/spread-sheets-resources-ko';
import '@mescius/spread-sheets/styles/gc.spread.sheets.excel2016colorful.css';
import { saveAs } from 'file-saver';

GC.Spread.Common.CultureManager.culture('ko-kr');

function App() {
  const [minutes, setMinutes] = React.useState('export');
  const [spread, setSpread] = React.useState(null);

  let hostStyle = {
    width: '100%',
    height: '380px',
  };

  let initSpread = function (spread) {
    setSpread(spread);

    // let sheet = spread.getActiveSheet();
    // sheet
    //   .getCell(0, 0)
    //   .vAlign(GC.Spread.Sheets.VerticalAlign.center)
    //   .value('Hello SpreadJS!');
  };

  const ImportFile = () => {
    let file = document.getElementById('fileDemo').files[0];
    let fileType = file.name.split('.');
    if (fileType[fileType.length - 1] == 'xlsx') {
      spread.import(
        file,
        function () {},
        function (e) {
          console.log(e); // error callback
        },
        {
          // importxlsxoptions - https://developer.mescius.com/spreadjs/api/modules/GC.Spread.Sheets#importxlsxoptions
          fileType: GC.Spread.Sheets.FileType.excel,
        }
      );
    }
  };

  const Export_Excel = () => {
    let fileName = document.getElementById('exportFileName').value;
    if (fileName.substr(-5, 5) !== '.xlsx') {
      fileName += '.xlsx';
    }
    spread.export(
      function (blob) {
        saveAs(blob, fileName);
      },
      function (e) {
        console.log(e);
      },
      {
        // ExportXlsxOptions - https://developer.mescius.com/spreadjs/api/modules/GC.Spread.Sheets#exportxlsxoptions
        fileType: GC.Spread.Sheets.FileType.excel,
      }
    );
  };

  const getCellData = () => {
    let sheet = spread.getActiveSheet();
    // A1 데이터 가져오기
    let val = sheet.getValue(0, 0);
    console.log('A1-', val);
    // B2:D4 데이터 가져오기
    let arr = sheet.getArray(1, 1, 3, 3);
    console.log('B2:D4-', arr);
  };

  return (
    <div>
      <div className="row">
        <div className="left">
          <SpreadSheets
            workbookInitialized={(spread) => initSpread(spread)}
            hostStyle={hostStyle}
          >
            <Worksheet></Worksheet>
          </SpreadSheets>
        </div>

        <div className="right">
          <div>
            <h4> Excel 가져오기 </h4>
            <input type="file" name="files[]" id="fileDemo" accept=".xlsx" />
            <button onClick={ImportFile}>불러오기</button>
          </div>
          <div>
            <h4> Excel 내보내기 </h4>
            파일명:
            <input
              type="text"
              id="exportFileName"
              placeholder="Export file name"
              value={minutes}
              onChange={(e) => setMinutes(e.target.value)}
            />
            <button onClick={Export_Excel}>저장하기</button>
          </div>
          <div>
            <h4> 특정 (Cell) 데이터 가져오기 </h4>
            <button onClick={getCellData}>콘솔로 A1 & B2:D4 값 가져오기</button>
          </div>
        </div>
      </div>
    </div>
  );
}

export default App;

SpreadJS를 사용해 여러분들만의 React(리액트) Excel 뷰어를 만들어 보았습니다!

위의 코드를 실행하면, React(리액트) 웹 페이지 상에서 Excel의 화면과 Excel 파일 읽기/쓰기 기능을 개발할 수 있습니다.
이 뷰어를 사용하면 몇 가지 간단한 단계만으로 Excel 파일을 열고, 보호하고, 암호를 추가한 다음 내보낼 수도 있습니다.




지금 SpreadJS를 무료로 사용해보세요!!

더욱 상세한 기능이 포함되어 있는 Excel 가져오기/내보내기 데모를 소스 코드와 함께 확인해 볼 수 있어요!!! PureJS, React, Vue, Angular 코드도 확인할 수 있어요 !!

profile
메시어스는 개발자분들을 응원합니다.

4개의 댓글

comment-user-thumbnail
2024년 6월 12일

웹에서 동작하는 엑셀 기능 찾아보다가 여기까지 왔네요.
좋은 정보 감사합니다.
한번 사용해보고 궁금한 거 있으면 질문 드리겠습니다

답글 달기
comment-user-thumbnail
2024년 6월 12일

안녕하세요, 포스팅 잘 봤습니다.

특정 셀의 데이터를 읽어오는 기능이 예시로 나와있는데, 반대로 특정 셀의 데이터만 변경하는 기능도 지원하나요?

월마다 생성하던 Excel 형식 보고 자료가 있는데, 거기서 년/월/일이나 작성자 정보 외 몇몇 필드 등의 값을 코드 단에서 변경하여, 자동으로 보고 자료가 생성되도록 하는 것이 목표입니다.

1개의 답글