프로젝트

#4 [REACT.JS] 사진 불러오기, 엑셀 읽어오기

user-anonymous 2021. 11. 22. 00:37
728x90

 

 

#3 기본 레이아웃 구성 및 팝업 생성

#2 기본 버튼 컴포넌트 만들기 #1 기획단계 및 UI 작업 드디어 1인 토이 프로젝트를 진행하려 마음을 먹었다. 토이 프로젝트의 큰 토픽은 이름표다. (..오잉) 회사마다 다를 수 있지만 현재 본인이

potential-coding.tistory.com


깃허브 일일커밋 4일차 개발 사항은 

- 이미지 첨부

    - 이미지 앞면, 뒷면 보여주기 

- 엑셀파일 첨부

    - 엑셀 파싱 작업 진행 완료

---  

현재 css는 아직 완전히 구현되지 않은 상태이다. 이렇게 앞면과 뒷면 이미지를 불러오고,  엑셀에서 매일 첫번째 로우인 header 컬럼을 받아와 변수 지정에 설정했다.

 

그리하여 앞으로는 header에 있는 이름, 직급, 부서명 등을 드래그앤 드랍할 수 있는 객체로 만들어 명함 앞면과 뒷면에 위치를 지정해주고 싶다. 또한 더 나아가 X축과 Y축을 로컬에 저장해놓아 나중에 사용자가 사용할 때도 기본 값을 지정해줬으면 좋을 것 같다. 

 

 

리액트 이미지 로딩 과정


1. 버튼 클릭 

        <FileUpload
          text={"앞면 업로드"}
          extension={".png,.jpeg,.jpg"}
          id={"front"}
          handleFile={(e) => handleUploadFile(e)}
        />

2. FileUpload에서 해당 사항을 props로 받음 

styled-components에서 input type file 커스텀하는 방법(참고) 

 

How to customize the file upload button in React

The default file upload button is ugly. Customizing its style is hard. I’ve surveyed the solutions available across the web. Here’s what I…

medium.com

import React, { useRef } from "react";
import Button from "./Button";

const FileUpload = (props) => {
  const fileInputInfo = useRef(null);
  const handleClick = (e) => {
    fileInputInfo.current.click();
  };

  const handleChangeUpload = (e) => {
    props.handleFile(e);
  };

  return (
    <>
      <Button text={props.text} onClick={(e) => handleClick(e)} />
      <input
        type="file"
        id={props.id}
        accept={props.extension}
        ref={fileInputInfo}
        style={{ display: "none" }}
        onChange={(e) => handleChangeUpload(e)}
      />
    </>
  );
};

FileUpload.defaultProps = {
  extension: ".xls,.xlsx",
  text: "파일 업로드",
  id: "",
};

export default FileUpload;

나는 props를 확장자, 버튼 텍스트, id를 받도록 설정했다. 그리고 handleClick이라는 props를 넘겨줬을 경우 해당 file의 정보들을 넘겨줬다. 

 

3. 호출한 곳에서 파일의 정보 받기 

  const handleUploadFile = (e) => {  
    setFilesInfo({
      ...filesInfo,
      [e.target.id]: e.target.files[0],
    }); 
  };

해당 handleUploadFile에서 2번에서 준 파일의 정보를 받아 filesInfo에 e.target.files[0] 파일의 정보를 넣어줬다.

 

4.  이미지 보여주기

   <ThumbNail>
          {filesInfo.hasOwnProperty("front") ? (
            <Image src={URL.createObjectURL(filesInfo["front"])} />
          ) : (
            <React.Fragment />
          )}
        </ThumbNail>

setFilesInfo를 하여 front 키가 있을 경우 URL.createObjectURL(filesInfo["front"]) 파일 정보를 불러와 로드해줬다.

이때, URL.createObjectURL(filesInfo["front"]) 은 BLOB을 나타내는 URL을 생성하여 참조할 수 있게 해준다.

 

 

리액트 엑셀 로딩 과정 

엑셀 업로드 경우에는 SHEETJS 라이브러리를 사용했다. 

더보기

npm install xlsx

내가 엑셀에서 파싱하고 싶은 JSON 형태는 각 로우마다 배열이 생기고 그 로우안에는 각 컬럼들의 배열이 있는 형태이다.

 

(참고)  

 

Looping through rows and columns · Issue #270 · SheetJS/sheetjs

How do I loop through rows and columns without converting the worksheet to csv or json before doing so? Is it not possible to do something like var worksheet = workbook.Sheets['Sheet1']; fo...

github.com

파일을 가져오는 과정은  위의 이미지 불러오는 3번까지 동일하다. 

 

1. 업로드 버튼 생성 

        {filesInfo.hasOwnProperty("list") ? (
          <Button
            onClick={(e) => handleParsingFile(e)}
            backgroundColor={"green"}
            text={"업로드"}
          />
        ) : (
          ""
        )}​

filesInfo에 list라는 key를 가지고 있을 경우에는 handleParsingFile 함수를 실행하는 업로드 버튼을 보여준다.

 

2. 엑셀 파싱 작업 진행

 const handleParsingFile = (e) => { 
    let result = new Array(); //최종 배열을 담을 변수
    if (filesInfo.hasOwnProperty("list")) { 
      const reader = new FileReader(); 
      const files = filesInfo["list"];
      reader.onload = (e) => {
        let data = e.target.result;
        const wb = XLSX.read(data, { type: "binary" });
        const wsName = wb.SheetNames[0]; 
        let worksheet = wb.Sheets[wsName]; 
        let row;
        let rowNum;
        let colNum;
        let range = XLSX.utils.decode_range(worksheet["!ref"]);
        
        /*각 로우마다 새로운 배열을 만들고, 그 안에 컬럼을 push*/
        for (rowNum = range.s.r; rowNum <= range.e.r; rowNum++) {
          row = [];
          for (colNum = range.s.c; colNum <= range.e.c; colNum++) {
            var nextCell =
              worksheet[XLSX.utils.encode_cell({ r: rowNum, c: colNum })];
            if (typeof nextCell === "undefined") {
              row.push(void 0);
            } else row.push(nextCell.w);
          }
          result.push(row);
        }
        setExcelData({ ...excelData, result: result });
      };
      reader.readAsBinaryString(files);
    }
  };

reader.onload = (e) =>{}가 실행되기 위해서는 reader.readAsBinaryString(files);가 성공적으로 파일을 읽어야 실행된다.

해당 파싱된 엑셀 데이터를 setExcelData({...excelData, result:result});로 지정해줬다. 

 

3. 엑셀 데이터 화면에 보여주기 

          {Object.keys(excelData).length > 0 &&
            excelData["result"].map((item, idx) => { 
              return (
                <TR>
                  {item.map((it, ins) => {
                    return <TD>{it}</TD>;
                  })}
                </TR>
              );
            })}

엑셀 데이터가 있을 경우 map 을 통해 각 요소들을 반복하며 <td></td>를 보여준다.

 

 

 

---

확실히 props와 state 학습은 직접 기본 컴포넌트들을 개발하고, 사용하는데서 개념을 자연스레 익히게 되는 것 같다.

 

 

 

728x90
반응형