본문 바로가기
💻 프론트엔드 : Frontend/Javascript | Typescript

readExcelFile로 병합된 셀을 잘 받아오는 법

by 예옹이 2024. 10. 4.

엑셀에서 병합된 셀을 불러오는 경우

이런식으로 엑셀의 행 중에 병합된 요소가 존재할때 readExcelFile을 사용해 읽어오면

제조사 월사용량(kg) 단위 물질명 Cas No 함유량(%) 관리대상물질 개정일자 비고
기타 제조사 50 kg 아르곤 7440-37-1 10 1 2024.9.29 비고
      수소 1333-74-0 5 2    
공업 제조사 200 g 메탄올 67-56-1 5 3 2025.4.2 이상없음

이렇게 공통된 요소가 빈값으로 넘어오게 됩니다.

 

병합된 셀을 잘 받아오기 위해

let content = data.slice(1).filter((items) => items?.length > 0);
    let currentProduct = null;
    // 앞에서부터 9개의 아이템 + 뒤에 2개의 아이템이 null이면 병합된 셀로 판단
    // 물질명 ~ 유해화학물질을 배열로 받기
    content.forEach((items) => {
      if (items[0]) {
        currentProduct = {
          use_state: items[0] || null,
          use_team: items[1] || null,
          use_work_process: items[2] || null,
          use_unit_operation: items[3] || null,
          use_purpose: items[4] || null,
          product_name: items[5] || null,
          manufacture: items[6] || null,
          monthly_usage: items[7] || null,
          unit: items[8] || null,
          msds_renewal_date: DateTime.fromJSDate(items[17]).plus({ minutes: 1 }).toFormat("yyyy-MM-dd") || null,
          etc: items[18] || null,
          materials: [],
        };
        excelData.push(currentProduct);
      }
      if (items[9]) {
        currentProduct.materials.push({
          msds_name: items[9] || null,
          msds_cas_no: items[10] || null,
          msds_content: items[11] || null,
          management_target: items[12] !== undefined ? items[12] : null,
          special_management: items[13] !== undefined ? items[13] : null,
          work_environment: items[14] !== undefined ? items[14] : null,
          special_health_diagnosis: items[15] !== undefined ? items[15] : null,
          harmful_chemical: items[16] !== undefined ? items[16] : null,
        });
      }
    });

불러온 행의 첫번째 요소가 채워져있는지 확인해줍니다.

그리고 새로운 배열을(materials) 같이 넣어서 받아온 뒤에

병합되지 않은 요소들을 배열에 전부 집어넣어줍니다.

이해를 돕기 위한 이미지입니다.

병합된 셀을 표시해주고싶다면

{#each excelData as data}
  {#each data.materials as item, mat_index}
    <tr>
      <!--제품란-->
      {#if mat_index === 0}
        {#each Object.keys(data).slice(0, 9) as key}
          <td rowspan={data.materials.length} class={data[key] ? "" : "bg-red"}>
            <span class="wbreak">{data[key] || "오류"}</span>
          </td>
        {/each}
      {/if}
      <!--물질란-->
      {#each Object.keys(item).slice(0, 8) as key}
        <td class={!_.isNil(item[key]) ? "" : "bg-red"}>
          <span class="wbreak">{!_.isNil(item[key]) ? item[key] : "오류"}</span>
        </td>
      {/each}
      <!--개정일자,비고란-->
      {#if mat_index === 0}
        <td rowspan={data.materials.length} class={data.msds_renewal_date ? "" : "bg-red"}>
          <span class="wbreak">{data.msds_renewal_date || "오류"}</span>
        </td>
        <td rowspan={data.materials.length} class={data.etc ? "" : "bg-red"}>
          <span class="wbreak">{data.etc || "오류"}</span>
        </td>
      {/if}
    </tr>
  {/each}

엑셀 데이터의 병합되지 않은 요소들을 집어넣어준 새로운 배열만큼 반복을 돌면서

{#if mat_index === 0} mat_index가 0일 때(즉, 첫 번째 물질일 때만) 해당 제품의 데이터를 출력하고, 나머지 물질에는 중복해서 제품 정보를 표시하지 않도록 처리합니다.

{#each Object.keys(data).slice(0, 9) as key} data 객체에서 제품 관련 정보를 추출해 테이블의 열을 생성합니다.

rowspan={data.materials.length}를 사용하여 해당 셀이 제품의 물질 개수만큼 세로로 병합되도록 설정합니다.

Object.keys(item).slice(0, 8)은 물질과 관련된 데이터를 테이블의 열로 변환합니다.

뒤에 마저 병합될 요소들도 마찬가지 작업을 반복해줍니다.

 

 

완성된 모습