사건의 전말
테이블의 특정 칼럼은 int, 즉 , 정수 타입이다. 정수는 앞에 0이 붙지 못한다.
하지만 0이 들어와야 하는 경우가 발생하고 이 0을 사용자는 화면에서 보고, 출력을 할 수 있어야 한다.
백엔드에서든, 앞단에서든 0이야 digit 수 만큼 붙여줄 수 있다.
하지만 출력을 할 때는 얘기가 다르다.
만약 csv 포맷으로 출력을 한다면 해당 칼럼의 서식은 변경할 수 없다.
아무리 앞단에서 0이 붙어진 데이터를 display 했다고 하더라도 csv로 출력하고 여는순간 앞에 0은 사라질 것이다.
왜? 숫자이기 때문이다. 출력하기 전에 문자열로 바꿨다 하더라도 상관없다.
이를 위해 엑셀 전용 포맷인 xlsx를 사용해야 하며
위와 같은 이유로 xlsx로 추출할 때 어떻게 해야하는지 공유하려고 한다.
제일 먼저
Xlsx 관련 라이브러리를 사용할 것이다.
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
시연의 용이성을 위해 cdn을 사용할 것이고 위 cdn은 해당 화면의 html head부분에 넣어두면된다.
이후 실질적인 xlsx 포맷으로의 추출 방법이다.
가장 기본이 되는 헤더를 설정해주고
db에서 was를 통해 받아온 값을 반복문을 통해 객체에 담고
현재 날짜로 파일의 이름을 넘겨주는 작업이다.
SAMPLE.SetXlsxExport = function setSampleXlsxExport(dataDict) {
const querySet = dataDict.querySet;
let fileTitle = `${$('.cont_title').text()}_${COMMON_MOD.getToday()}`;
let headers = {
rnum: "No",
user_id: "User ID",
};
let itemsFormatted = [];
querySet.forEach((item) => {
itemsFormatted.push({
rnum: item.rnum,
user_id: item.user_id.toString().padStart(5, '0'),
});
});
exportExcelFile(headers, itemsFormatted, fileTitle);
};
여기서 눈여겨볼 점은
user_id: item.user_id.toString().padStart(5, '0'),
인데 이는 user_id 라고 하는 변수/칼럼 값의 타입은 정수(int)이기 때문에 제일 먼저 문자열로 형변환을 해준 것이고
padStart라는 함수를 통해 총 몇 자리이고 앞에서부터 그 빈 곳에 0으로 채우라는 뜻이다.
이렇게 되면 일단 객체에 user_id라는 키에는 문자열이면서 0이 채워진 값이 들어가있는 것이다.
그리고 xlsx로 추출 및 다운로드를 할 수 있게 해주는 함수는 다음과 같은데
주석을 참고하면 될 것이다.
function exportExcelFile(headers, items, fileTitle) {
// 새 워크북 생성
let workbook = XLSX.utils.book_new();
// 새 워크시트에 들어갈 배열 초기화
let worksheet_data = [];
// 해더 객체를 배열로 넣는 작업
worksheet_data.push(Object.values(headers));
// 값 객체를 배열로 넣는 작업
items.forEach(function(item) {
worksheet_data.push(Object.values(item));
});
// 위에서 넣은 배열을 통해 워크시트에 변환해서 넣는 작업
let worksheet = XLSX.utils.aoa_to_sheet(worksheet_data);
// 위에서 넣은 워크시트를 워크북에 넣는 작업
XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
// 파일명 정의 : 좀전에 받아온 날짜값의 파일명을 사용한 것을 알 수 있음
let exportedFileName = fileTitle + '.xlsx' || 'export.xlsx';
// 대망의 다운로드 버튼 > 저장한 데이터를 파일로 쓰는 작업
XLSX.writeFile(workbook, exportedFileName);
}
이해를 돕기 위한 부연설명을 하자면
워크북이 엑셀파일 그 자체이고
워크시트가 말 그대로 하나의 Sheet이고
그 워크시트에 값을 넣을 때 배열이 필요하기 때문에 좀전에 객체형태로 보내준 값을 배열로 변환해서 넣어준 것이며
헤더부터 배열로 한줄 넣고
값을 두번 째 줄부터 배열로 변환해서 넣은 것이라 보면 된다.
그렇다면 의문!
왜 객체형태로 보내주지? 그냥 처음부터 배열로 보내주면 되잖아?
그러면 변환할 필요도 없고 바로 워크시트에 넣어줄 수 있지 않나?
충분히 합리적은 의심이다.
이유는? 기존 레거시코드를 바꿀 수 없었기 때문 그 이상 그 이하도 아니었다.
만약 배열로 바꾼다면 데이터를 넘겨줬던 위의 함수는 아래와 같이 될 것이다.
SAMPLE.SetXlsxExport = function setSampleXlsxExport(dataDict) {
const querySet = dataDict.querySet;
let fileTitle = `${$('.cont_title').text()}_${COMMON_MOD.getToday()}`;
// Headers as an array
let headers = ["No", "User ID"];
// Format items as arrays
let itemsFormatted = querySet.map(item => [
item.rnum,
item.user_id.toString().padStart(5, '0')
]);
exportExcelFile(headers, itemsFormatted, fileTitle);
};
이렇게 array가 된다면?
아래 함수는 변환 작업이 줄어들 게 될 것이다.
function exportExcelFile(headers, items, fileTitle) {
// 새 워크북 생성
let workbook = XLSX.utils.book_new();
// 새 워크시트에 들어갈 배열 초기화
let worksheet_data = [];
// 해더 배열을 워크시트 데이터에 넣기
worksheet_data.push(headers);
// 데이터 배열을 워크시트 데이터에 넣기
items.forEach(function(item) {
worksheet_data.push(item);
});
// 위에서 넣은 배열을 통해 워크시트에 변환해서 넣는 작업
let worksheet = XLSX.utils.aoa_to_sheet(worksheet_data);
// 위에서 넣은 워크시트를 워크북에 넣는 작업
XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
// 파일명 정의 : 좀전에 받아온 날짜값의 파일명을 사용한 것을 알 수 있음
let exportedFileName = fileTitle + '.xlsx' || 'export.xlsx';
// 대망의 다운로드 버튼 > 저장한 데이터를 파일로 쓰는 작업
XLSX.writeFile(workbook, exportedFileName);
}
차이가 안보인다면 배열로 넘겨준다면 받아온 인자값을 Object.values()로 감쌀 필요가 없다는 것이다.
Object.values(인자값)
'개발자 전향 프로젝트' 카테고리의 다른 글
페이징의 종류와 각각의 장단점 (파이썬+장고) (0) | 2025.01.23 |
---|---|
initdb와 pg_dump 통해서 Postgres DB 통채로 Migrate 하는법 (Feat. Docker) (3) | 2024.10.04 |
JMeter - Recording 으로 실시간 브라우저 상호작용 테스트하기 (0) | 2024.09.26 |
무한 스크롤 이해하기 (0) | 2024.08.22 |
Apache Jmeter로 k8s HPA 하기 + 전용 시각화 툴로 모니터링 하기 (2) | 2024.07.26 |