본문 바로가기

개발/React.js

Xlsx parsing + react-table

분석 계기

https://bizinsight.atlassian.net/wiki/pages/createpage.action?spaceKey=Software&title=1.%20Excel%20%ED%8C%8C%EC%8B%B1

B2B 여행자 보험 가입 서비스 프로젝트에서 가장 중요한 기능인 Excel 파싱 기능 관련하여 어떤 라이브러리를 사용할지 기술 검토를 했었다. 그 결과, xlsx 라이브러리(SheetJS)를 사용하는 것이 가장 적절하다고 판단하여 개발팀에 공유를 하였다.

 

그렇다면, 이 xlsx 라이브러리로 어떤 기능들을 구현해야 할지 보다 디테일하게 분석을 해보려고 한다.

필요한 기능

  1. 정해진 양식의 엑셀 파일에 원하는 정보를 리스트업하고, 해당 엑셀 파일을 정확하게 읽어오는 것
  2. 정확하게 읽어온 데이터를 UI 상에서 수정할 수 있도록 테이블 형식으로 구현하는 것
    1. 이 때, 데이터를 이중 배열로 만든다.
  3. 추후 가입자 내역을 export하기 위해 기존 json 형식의 데이터를 엑셀로 바꾸는 것

(참고) 물론 디자인이 어떻게 바뀔지는 모른다. 해당 테이블을 사용하게 될지도 모르는 상태.

 

상기 작성한 필요한 기능들을 토대로 핵심 코드는 어떻게 되는지 살펴보자.


1. 정해진 양식의 엑셀 파일에 원하는 정보를 리스트업하고, 해당 엑셀 파일을 정확하게 읽어오는 것

// (1) 첨부된 엑셀 파일을 읽어오고
const handleChangeUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files) {
        const filesArray = Array.from(e.target.files) as File[];
        ParseExcelSheetToJson(acceptedFiles).then(r => console.log("성공"));
    }
}
// (2) 엑셀 파일을 파싱한다.
const ParseExcelSheetToJson = async (files: File[]): Promise<void> => {
    const file = files[0];
    const arrayBuffer = await file.arrayBuffer();
    const wb = read(arrayBuffer); // ArrayBuffer를 파싱한다.
    const ws = wb.Sheets[wb.SheetNames[0]]; // 첫 번째 시트를 가져온다.
    const data: any[] = utils.sheet_to_json(ws);
    console.log("[data] ", data, " / [data:Stringify] ", JSON.stringify(data));
    setPres(data);
}
  • JSON 파일 Prettier
[
  {
    "성명(한글)": "장혜승",
    "주민등록번호": "9405052342321"
  },
  {
    "성명(한글)": "김길동",
    "주민등록번호": "9210211231122"
  },
  {
    "성명(한글)": "이탐사",
    "주민등록번호": "8705122346744"
  }
]
  • 배열로 바꾼다? 어떻게? 이중 배열?

→ 필요 없어짐 ㅎ

 

 

2. 정확하게 읽어온 데이터를 UI 상에서 수정할 수 있도록 테이블 형식으로 구현하는 것

tailAdmin에서 사용하는 react-table에서 editable table 옵션이 있어서 이것을 활용하면 좋을 것 같다는 생각이다.

https://tanstack.com/table/v8/docs/framework/react/examples/editable-data

import한 엑셀 데이터를 다시 테이블로 옮겨서 CUD가 가능하게 하는 방법을 따로 풀어보았다.

https://bizinsight.atlassian.net/wiki/spaces/~7120203874d6268a0e43069751a782e0c3b31b/pages/162365450

3. 추후 가입자 내역을 export하기 위해 기존 json 형식의 데이터를 엑셀로 바꾸는 것

const exportFile = useCallback(() => {
    const ws = utils.json_to_sheet(pres);
    const wb = utils.book_new();
    utils.book_append_sheet(wb, ws, "Data");
    writeFileXLSX(wb, "export.xlsx");
}, [pres]);

고려해야할 사항

  1. XLS 파일, XLSX 파일, CSV 파일 구분하기

→ XLS, XLSX, CSV 파일은 모두 똑같이 라이브러리에서 잘 작동한다.

  • XLS 파일
    • Excel 2003 이전 형식으로 만든 문서
  • XLSX 파일
    • Excel 2007 이후 형식으로 만든 문서

컴포넌트 구성

→ 컴포넌트들은 어떤 것들을 만들고, 어떤 조건을 만족해야할까?

1. [완료]

<XlsxFileDragInput export={true} output={output} onChange={onChangeFile} limitedSize={} />

→ 역할 : 엑셀 파일을 Drag & Drop 하면 fileData와 jsonData를 한 객체에서 동시에 보내준다. 그리고 onChangeFile 이벤트 함수를 타고 컴포넌트를 사용하는 페이지에서 테이블 내용 상태관리를 한다.

엑셀 하나만 첨부 (복수개 고려 X)
validation 체크 필요
엑셀 하나 첨부하면 File 타입 상태로 빼준다.
props의 output 옵션 (boolean)
json 파싱된 값 console에 출력
내부적으로 jsonOutput과 fileOutput key로 구성된 객체가 포함될 예정
props의 export 옵션 (boolean)
엑셀로 export하는 버튼 추가
파일별 용량에 대한 정보를 컴포넌트 내부에서 제한해줘야 한다. (나중에)
{
  jsonOutput: sheetToJsons,
  fileOutput: files
}
 

그런데 고려해야할 점이 하나 더 있다. Dropzone 컴포넌트를 사용할 것인지, useDropzone을 사용할 것인지.

  • Dropzone 컴포넌트를 쓴다면?
    • <Dropzone onDrop={onDropFiles}> </Dropzone>형태로 간결하게 쓸 수 있다.
    • 확장자 제한을 두려면 useDropzone 커스텀훅을 추가로 써야한다.
  • useDropzone 커스텀훅을 쓴다면?
    • 확장자 제한을 쉽게 둘 수 있다.
    • 로직과 UI 분리를 두기 쉬워진다.

2. <EditableTable data={data} onChange={onChangeTable} />

→ 역할 : {key : value} data를 보내면 table에서 보여주고, 테이블 내용이 바뀌면, 바뀐 data를 보내준다.

  1. data로 React-table에 맞는 데이터 타입으로 보내준다.
  2. Table 내에 데이터가 바뀔 경우, data에 있는 데이터를 수정해준다.
  3. 데이터 내용에 따른 계산이 필요할 경우 컴포넌트를 사용하는 페이지에서 컨트롤

'개발 > React.js' 카테고리의 다른 글

React 주민등록번호 컴포넌트  (0) 2024.09.13
Dynamic Route - Slug  (0) 2024.09.13
OAuth 인증 - 인가에 대하여  (0) 2024.09.13
전역 상태 관리 라이브러리 - Zustand vs Recoil  (0) 2024.09.13
파일 Drag & Drop  (0) 2024.09.13