wr: exceldown 천단위 콤마

This commit is contained in:
2026-03-04 11:42:02 +09:00
parent aa05cb5d73
commit c1813ba4f3
10 changed files with 120 additions and 69 deletions
@@ -8,7 +8,7 @@ import RuseCaseMngExcel from "@/components/ui/modal/coMat/ruseCaseMng/ruseCaseMn
import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import {
ContentsDiv,
filePickedBlobArray,
filePickedBlobNumStyle,
SearchDiv,
SearchFormLeft,
SearchFormRight,
@@ -112,6 +112,8 @@ export default function RuseCaseMng() {
if (next !== cell.v) cell.v = next;
});
});
// 엑셀 Workbook 객체를 파일 형식으로 변환
const updatedBlob = XLSX.write(wb, { bookType: "xlsx", type: "array" });
const excelData1 = excelList.map((item) => {
@@ -172,14 +174,17 @@ export default function RuseCaseMng() {
const sheetParameter: SheetParameter[] = [
{
data: excelData1,
headerNum: 2,
headerNum: 1,
headerRange: "A1:AX1",
sheetName: "물재이용사례",
startCol: "A",
decimalArray0: [5,8,11,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49]
},
];
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
await filePickedBlobArray(updatedBlob, "물재이용사례현황", sheetParameter);
// await filePickedBlobArray(updatedBlob, "물재이용사례현황", sheetParameter);
await filePickedBlobNumStyle(updatedBlob, "물재이용사례현황", sheetParameter);
});
}, [excelList]);
@@ -9,12 +9,13 @@ import type {
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { htdflSttnSize } from "@/app/store/ruseFcltMng/fcltSttn/htdflSttn";
import {
excelDownload,
excelDownloadNumStyle,
formatArchArea,
formatCommaNumber,
getCity,
tableData
} from "@/components/lib/func/commom";
import { type SheetParameter } from "@common/business_components/ui";
import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import HeadChModal from "@/components/ui/modal/sttn/headChModal/headChModal";
import SttnDetailModal from "@/components/ui/modal/sttn/sttnDetailModal/sttnDetailModal";
@@ -113,11 +114,18 @@ export default function HtdflSttn() {
return;
}
if (htdflSttn.excelList.length > 0) {
excelDownload(
htdflSttn.excelList,
const sheetArray: SheetParameter[] = [{
data: htdflSttn.excelList,
headerNum: 3,
headerRange: "A1:R3",
sheetName: 'sheet1',
startCol: 'A',
decimalArray0: [6,11,13,15], // 0부터 시작
}];
excelDownloadNumStyle(
"온배수시설 현황",
"sample_htdflSttn.xlsx",
"A1:R3"
sheetArray
);
} else {
toast.error(t('excelDownErrMsg'));
@@ -9,7 +9,7 @@ import type {
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { rainSttnSize } from "@/app/store/ruseFcltMng/fcltSttn/rainSttn";
import {
excelDownloadStyle,
excelDownloadNumStyle,
getCity,
tableData,
} from "@/components/lib/func/commom";
@@ -164,11 +164,10 @@ export default function RainSttn() {
headerNum: 3,
headerRange: "A1:W3",
sheetName: 'sheet1',
writeLine: 4,
startCol: 'A',
decimalArray0: [6,10,12,14,16]
decimalArray0: [6,10,12,14,16] // 0부터 시작
}];
excelDownloadStyle(
excelDownloadNumStyle(
"빗물이용시설 현황",
"sample_rainSttn.xlsx", // public 폴더에 있는 template 파일 경로
sheetArray
@@ -7,12 +7,13 @@ import { btnClass } from "@/app/store/common/code";
import type { customRswtBdst } from "@/app/store/ruseFcltMng/fcltReg/rswtReg";
import { rswtSttnSize } from "@/app/store/ruseFcltMng/fcltSttn/rswtSttn";
import {
excelDownload,
excelDownloadNumStyle,
formatArchArea,
formatCommaNumber,
getCity,
tableData
} from "@/components/lib/func/commom";
import { type SheetParameter } from "@common/business_components/ui";
import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import HeadChModal from "@/components/ui/modal/sttn/headChModal/headChModal";
import SttnDetailModal from "@/components/ui/modal/sttn/sttnDetailModal/sttnDetailModal";
@@ -128,11 +129,18 @@ export default function RswtSttn() {
return;
}
if (rswtSttn.excelList.length > 0) {
excelDownload(
rswtSttn.excelList,
const sheetArray: SheetParameter[] = [{
data: rswtSttn.excelList,
headerNum: 3,
headerRange: "A1:W3",
sheetName: 'sheet1',
startCol: 'A',
decimalArray0: [6,10,12,16], // 0부터 시작
}];
excelDownloadNumStyle(
"중수도시설 현황",
"sample_rswtSttn.xlsx",
"A1:W3",
sheetArray
);
} else {
toast.error(t('excelDownErrMsg'));
@@ -4,7 +4,8 @@ import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import { rainPageSize } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn";
import { rswtPageSize } from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn";
import { excelDownload, yearOptions } from "@/components/lib/func/commom";
import { excelDownloadNumStyle, yearOptions } from "@/components/lib/func/commom";
import { type SheetParameter } from "@common/business_components/ui";
import ChkgdModal from "@/components/ui/modal/chkgd/chkgdModal/chkgdModal";
import RainChkgdTable from "@/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable";
import RswtChkgdTable from "@/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable";
@@ -145,12 +146,18 @@ export default function Page() {
toast.error(t("excelDownErrMsg"));
return;
}
excelDownload(
rainChkSttn.sttnExcelList,
const sheetArray: SheetParameter[] = [{
data: rainChkSttn.sttnExcelList,
headerNum: 2,
headerRange: "A1:Q2",
sheetName: 'sheet1',
startCol: 'A',
decimalArray0: [5,6,7,9,10,11,12,13,16], // 0부터 시작
}];
excelDownloadNumStyle(
"빗물이용시설 지도점검 현황",
"sample_rainChkSttn.xlsx",
"A1:Q2",
3
sheetArray
);
} else if (rswtChkSttn.sttnExcelList && selFcltDiv === "RST") {
if (
@@ -160,12 +167,18 @@ export default function Page() {
toast.error(t("excelDownErrMsg"));
return;
}
excelDownload(
rswtChkSttn.sttnExcelList,
const sheetArray: SheetParameter[] = [{
data: rswtChkSttn.sttnExcelList,
headerNum: 2,
headerRange: "A1:X2",
sheetName: 'sheet1',
startCol: 'A',
decimalArray0: [4,5,9,10,11,12,13,14,17,18,19,23], // 0부터 시작
}];
excelDownloadNumStyle(
"중수도시설 지도점검 현황",
"sample_rswtChkSttn.xlsx",
"A1:X2",
3
sheetArray
);
}
};
@@ -4,7 +4,8 @@ import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import { initValInUsage, initValOutUsage, subTotalObj, totalObj, type FcPrfType, type PrfType } from "@/app/store/prfmncReg/pbnstPrfmncReg/type";
import { excelPrfmncSttnParsing } from "@/app/store/prfmncSttn/pbnstPrfmncSttn/excel";
import { excelDownload, yearOptions } from "@/components/lib/func/commom";
import { excelDownloadNumStyle, yearOptions } from "@/components/lib/func/commom";
import { type SheetParameter } from "@common/business_components/ui";
import { InputTableBody } from "@/components/lib/func/TableData";
import { CHART_FORM, ContentsDiv, MainChart, ScrollArea, SearchBaseForm, SearchInput, SelectBox, UiTable, type ChartConfig, type ReturnType } from "@common/business_components";
import ListDiv from "@common/business_components/ui/list_div";
@@ -46,12 +47,18 @@ export default function PbnstPrfmncSttn() {
toast.error(t('excelDownErrMsg'));
return;
}
excelDownload(
excelData,
const sheetArray: SheetParameter[] = [{
data: excelData,
headerNum: 1,
headerRange: "A1:N1",
sheetName: 'sheet1',
startCol: 'A',
decimalArray0: [1,2,3,4,5,6,7,8,9,10,11,12,13], // 0부터 시작
}];
excelDownloadNumStyle(
"하수재이용실적 현황",
"sample_pbnstPrfmncSttn.xlsx",
"A1:N1",
2
sheetArray
);
}, [excelData]);
const [chartConfig, setChartConfig] = useState<ChartConfig>({});
@@ -3,8 +3,9 @@
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import type { RainStatProps } from "@/app/store/stats/rainStat";
import { excelDownload, tableData, yearOptions } from "@/components/lib/func/commom";
import { downloadExcel } from "@common/business_components";
import { excelDownloadNumStyle, tableData, yearOptions } from "@/components/lib/func/commom";
import { type SheetParameter } from "@common/business_components/ui";
import { downloadExcelFormat } from "@common/business_components";
import {
ContentsDiv,
@@ -140,13 +141,19 @@ export default function RainStat() {
const excelData = [...sidoTotalSummary, ...sidoSummaryList, ...summaryExcelData];
console.log(' excelData ', excelData)
excelDownload(
excelData as unknown as [][],
// console.log(' excelData ', excelData);
const sheetArray: SheetParameter[] = [{
data: excelData,
headerNum: 3,
headerRange: "A1:O3",
sheetName: 'sheet1',
startCol: 'A',
decimalArray0: [1,2,3,4,5,6,7,8,9,10,11,12], // 0부터 시작
}];
excelDownloadNumStyle(
"빗물이용시설 통계",
"sample_rainStats.xlsx",
"A1:O3",
4
sheetArray
);
}
@@ -169,11 +176,12 @@ export default function RainStat() {
"연간운영비(백만원/년)": item.anlOperCst,
};
})
downloadExcel({
downloadExcelFormat({
data: (tbData as unknown as JSON[]) ?? [],
fileName: "재이용통계",
sheetNameArray: ["Sheet1"],
headerRange: "A1:M1"
headerRange: "A1:M1",
decimalArray0: [1,2,3,4,5,6,7,8,9,10,11,12], // 0부터 시작
})
}else{
toast.error(t('excelDownErrMsg'));
@@ -2,10 +2,11 @@
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import type { RswtStatProps } from "@/app/store/stats/rswtStat";
import { excelDownload, tableData, yearOptions } from "@/components/lib/func/commom";
import { excelDownloadNumStyle, tableData, yearOptions } from "@/components/lib/func/commom";
import { type SheetParameter } from "@common/business_components/ui";
import { downloadExcelFormat } from "@common/business_components";
import {
ContentsDiv,
downloadExcel,
ScrollArea,
SearchDiv,
SelectBox,
@@ -53,11 +54,12 @@ export default function RswtStat() {
};
})
downloadExcel({
downloadExcelFormat({
data: (data as unknown as JSON[]) ?? [],
fileName: "중수도재이용통계",
sheetNameArray: ["Sheet1"],
headerRange: "A1:N1"
headerRange: "A1:N1",
decimalArray0: [1,2,3,4,5,6,7,8,9,10,11,12,13], // 0부터 시작
})
} else {
toast.error(t("excelDownErrMsg"))
@@ -220,12 +222,18 @@ export default function RswtStat() {
// sidoSummaryList와 rainDetailList를 합쳐서 엑셀 데이터 생성
const excelData = [...sidoTotalSummary, ...sidoSummaryList, ...summaryExcelData];
excelDownload(
excelData as unknown as [][],
const sheetArray: SheetParameter[] = [{
data: excelData,
headerNum: 3,
headerRange: "A1:P3",
sheetName: 'sheet1',
startCol: 'A',
decimalArray0: [1,2,3,4,5,6,7,8,9,10,11,12], // 0부터 시작
}];
excelDownloadNumStyle(
"중수도시설 통계",
"sample_rswtStats.xlsx",
"A1:P3",
4
sheetArray
);
}
+2 -7
View File
@@ -2,14 +2,12 @@ import { lwCds, type comCodeState } from "@/app/store/common/code";
import {
filePickedBlob,
filePickedBlobArray,
filePickedBlobArrayFormat,
filePickedBlobNumStyle,
type ReturnType,
type SelectDataType,
type SheetParameter,
} from "@common/business_components/ui";
import { Button } from "@common/components/ui";
import { write } from "fs";
import moment from "moment";
import type { RefObject } from "react";
import toast from "react-hot-toast";
@@ -103,22 +101,19 @@ export const excelDownload = (
});
};
export const excelDownloadStyle = (
// excelList: [][],
export const excelDownloadNumStyle = (
fileNm: string,
sampleFile: string,
sheetArray: SheetParameter[]
) => {
// if (excelList.length === 0) return;
fetch(`/${sampleFile}`, {}).then(async (response) => {
fetch(`/${sampleFile}`, {}).then(async (response) => { // excel Tamplate을 읽는다.
if (!response.ok) {
throw Error(response.statusText);
}
// 받은 파일 바인너리 처리
const blobRet = await response.arrayBuffer();
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
// await filePickedBlob(blobRet, excelList, fileNm, writeLine, headerRange);
await filePickedBlobNumStyle(blobRet, fileNm, sheetArray);
});
};
@@ -18,11 +18,10 @@ type ExcelDownloadProps = {
}
export type SheetParameter = {
data: any[][];
data: unknown[][];
headerNum: number;
headerRange: string;
sheetName: string;
writeLine?: number;
startCol?: string;
decimalArray0?: number[];
decimalArray1?: number[];
@@ -46,7 +45,7 @@ export const applyRangeFormat = (
.map((part) => part.trim())
.filter(Boolean);
for (const part of parts) {
const rangeInfo = XLSX.utils.decode_range(part);
const rangeInfo = XLSX.utils.decode_range(part); // 셀 범위 문자열(ex. A1:D10)을 행/열 인덱스 객체로 변환
for (let row = rangeInfo.s.r; row <= rangeInfo.e.r; row++) {
for (let col = rangeInfo.s.c; col <= rangeInfo.e.c; col++) {
const cellAddr = XLSX.utils.encode_cell({ r: row, c: col });
@@ -149,21 +148,21 @@ export const downloadExcelFormat = ({
const worksheet = XLSX.utils.json_to_sheet(Array.isArray(data) ? data : [data]);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, sheetNameArray[0]);
console.log('decimalArray0 : ', decimalArray0);
// console.log('decimalArray0 : ', decimalArray0);
const headerEnd = XLSX.utils.decode_range(headerRange).e.r; // 0-based index
const startRow = headerEnd + 1;
// 🔹 전체 범위
const range = XLSX.utils.decode_range(worksheet["!ref"] as string);
applyDecimalColumns(worksheet, startRow, range, decimalArray0, 0);
applyDecimalColumns(worksheet, startRow, range, decimalArray1, 1);
applyDecimalColumns(worksheet, startRow, range, decimalArray2, 2);
applyDecimalColumns(worksheet, startRow, range, decimalArray3, 3);
applyRangeFormat(worksheet, decimalRange0, 0);
applyRangeFormat(worksheet, decimalRange1, 1);
applyRangeFormat(worksheet, decimalRange2, 2);
applyRangeFormat(worksheet, decimalRange3, 3);
if(decimalArray0) {applyDecimalColumns(worksheet, startRow, range, decimalArray0, 0);}
if(decimalArray1) {applyDecimalColumns(worksheet, startRow, range, decimalArray1, 1);}
if(decimalArray2) {applyDecimalColumns(worksheet, startRow, range, decimalArray2, 2);}
if(decimalArray3) {applyDecimalColumns(worksheet, startRow, range, decimalArray3, 3);}
if(decimalRange0) {applyRangeFormat(worksheet, decimalRange0, 0);}
if(decimalRange1) {applyRangeFormat(worksheet, decimalRange1, 1);}
if(decimalRange2) {applyRangeFormat(worksheet, decimalRange2, 2);}
if(decimalRange3) {applyRangeFormat(worksheet, decimalRange3, 3);}
excelStyle(XLSX.write(workbook, { bookType: "xlsx", type: "buffer" }), headerRange, fileName);
};
@@ -244,7 +243,7 @@ export const filePickedArray=(oFile: File, headerNum:number=0):Promise<JSON[] |
const arrayXls: JSON[] = []
let jsonXls: JSON | undefined;
// Loop Over Each Sheet
wb.SheetNames.forEach(function (sheetName,index ) {
wb.SheetNames.forEach(function (sheetName) {
const sheet = wb.Sheets[sheetName];
if (sheet) {
console.log(sheet)
@@ -311,15 +310,16 @@ export const filePickedBlobNumStyle = async (
const sheet = wb.Sheets[sheetName];
if (sheet) {
const startCol = sheetArray[index].startCol ?? "A";
const dataStartLine = sheetArray[index].writeLine ?? sheetArray[index].headerNum;
const dataStartLine = sheetArray[index].headerNum + 1;
// 2차원 배열(Array of Arrays, AOA) 형태의 데이터를 엑셀 시트(sheet)에 추가
XLSX.utils.sheet_add_aoa(sheet, sheetArray[index].data, {
origin: startCol + dataStartLine, // startLine 은 1부터 시작
});
const startRow = Math.max(dataStartLine - 1, 0); // 행은 0부터 시작
// 🔹 전체 범위
const range = XLSX.utils.decode_range(sheet["!ref"] as string);
// 사용된 셀 범위(range) 를 행(row)과 열(column)의 시작/끝 좌표로 변환 - 전체 범위
const range = XLSX.utils.decode_range(sheet["!ref"] as string); // !ref - 시트에서 실제 데이터가 존재하는 영역을 의미
if(sheetArray[index].decimalArray0){ applyDecimalColumns(sheet, startRow, range, sheetArray[index].decimalArray0, 0); }
if(sheetArray[index].decimalArray1){ applyDecimalColumns(sheet, startRow, range, sheetArray[index].decimalArray1, 1); }