엑셀에서 병합된 셀을 불러오는 경우
이런식으로 엑셀의 행 중에 병합된 요소가 존재할때 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)은 물질과 관련된 데이터를 테이블의 열로 변환합니다.
뒤에 마저 병합될 요소들도 마찬가지 작업을 반복해줍니다.
완성된 모습
'💻 프론트엔드 : Frontend > Javascript | Typescript' 카테고리의 다른 글
헷갈리는 Lodash import 구문 : import * as _는 되고 import _는 안 되는 이유 (0) | 2025.06.24 |
---|---|
validation library 비교 (zod, class-validator, joi) (1) | 2024.10.11 |
zod : 원하는 message가 아닌 ‘expected ~ but got ~’ 라 alert가 뜨는 현상 (0) | 2024.10.04 |
브라켓[]을 활용한 동적 라우팅 (0) | 2024.09.06 |