본문 바로가기
개발/React

React Handsontable로 csv 편집기 만들기 (16)

by 피로물든딸기 2021. 6. 14.
반응형

프로젝트 전체 링크

 

이전 - (15) callback function으로 선택된 Cell 보여주기 / 수정하기

현재 - (16) colWidths 옵션 / csv 파일 파싱 보완

다음 - (17) redux로 File Upload 상태 관리하기

 

깃허브 코드 확인하기


현재 myTable의 옵션 중 colWidths는 아래와 같다.

colWidths: [60, 60, 60, 60, 60, 60, 60],

 

이렇게 해두면, width가 배열의 길이보다 많은 경우, column의 길이는 60이 안된다.

따라서 csvFile의 width만큼 배열을 만들고 옵션으로 주면 된다.

let colWidths = [];
for(let i = 0; i < csvFile.width; i++) colWidths.push(60);

myTable = new Handsontable(container, {
  data: lib.makeTable(csvFile, 2, 3),
  ...
  colWidths,
  ...
}

 

모든 column의 길이가 60으로 고정되었다.


아래와 같이 잘못된 csv file이 있다. (","가 빠졌다.)

 

이 파일을 그대로 업로드하면 아래와 같이 잘못 parsing 된다.

 

 

현재 CSV 파일을 파싱할 때, 매 라인 마다 ","가 일정하다고 가정하고 함수를 만들었다.

하지만 wrong.csv와 같은 잘못된 파일도 아래와 같이 정상적으로 보이고 download 하도록 보완해보자.


library.js의 parsingCsv를 수정하면 된다.

sptLine을 줄바꿈에 대해 split하였었다.

각 line 중 가장 긴 length를 maxLength에 저장한다.

let sptLine = file.split(/\r\n|\n/);

/* 추가 */
let maxLength = 0;
for(let line of sptLine) {
  let spt = mySplit(line, DELIMITER, APOSTROPHE);
  if(maxLength < spt.length) maxLength = spt.length;
}

 

기존 for of 문에 pushCount를 선언하여 모자란 length만큼 빈 문자열을 push하면 올바른 csv가 만들어진다.

height = 0;
for(let line of sptLine)
{
  if(line === "") continue;

  let spt = mySplit(line, DELIMITER, APOSTROPHE);
  let pushCount = maxLength - spt.length;
  for(let i = 0; i < pushCount; i++) spt.push("");

  obj.csv.push(spt);
  height++;
}

 

이제 아래와 같이 잘못된 csv도 올바르게 parsing하게 되었다.

 

DOWNLOAD 버튼을 누르면 정상 csv로 변경된 것을 알 수 있다.

 

parsingCsv의 최종 코드는 아래를 참고하자.

// library.js

...

export const parsingCsv = (file, setCsvObject) => {
  let height, width;
  let obj = {
    HEIGHT: 0,
    WIDTH: 0,
    csv: [],
  };

  obj.csv = [];

  let sptLine = file.split(/\r\n|\n/);
  
  let maxLength = 0;
  for(let line of sptLine) {
    let spt = mySplit(line, DELIMITER, APOSTROPHE);
    if(maxLength < spt.length) maxLength = spt.length;
  }
  
  height = 0;
  for(let line of sptLine)
  {
    if(line === "") continue;

    let spt = mySplit(line, DELIMITER, APOSTROPHE);
    let pushCount = maxLength - spt.length;
    for(let i = 0; i < pushCount; i++) spt.push("");

    obj.csv.push(spt);
    height++;
  }

  width = obj.csv[0].length;

  obj.HEIGHT = height;
  obj.WIDTH = width;

  setCsvObject(obj);

  return;
}

이전 - (15) callback function으로 선택된 Cell 보여주기 / 수정하기

다음 - (17) redux로 File Upload 상태 관리하기

반응형

댓글