Merge branch 'iipbs/sn/dev'

This commit is contained in:
2026-03-06 10:40:57 +09:00
24 changed files with 506 additions and 730 deletions
@@ -7,7 +7,8 @@
"use client"
import UnderComment from "@/app/components/common/UnderComment";
import { StoreContext, useFoStore } from "@/app/store";
import { ContentsDiv, downloadExcelFormat, MainDiv, SearchBaseForm, SearchInput, SelectBox, UiModal, UiTable, type ReturnType } from "@common/business_components";
import { ContentsDiv, downloadExcelFormat, MainDiv, SearchBaseForm, SearchInput, SelectBox
, UiModal, UiTable, type ReturnType } from "@common/business_components";
import ListDiv from "@common/business_components/ui/list_div";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
import { useCallback, useContext, useEffect, useRef, useState } from "react";
@@ -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]);
@@ -3,7 +3,7 @@
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import type { customHtdflBdst } from "@/app/store/ruseFcltMng/fcltReg/htdflReg";
import { tableData } from "@/components/lib/func/commom";
import { formatArchArea, tableData } from "@/components/lib/func/commom";
import HtdflRegForm from "@/components/ui/form/fcltReg/htdflReg/htdflRegForm";
import { BdstReg } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import {
@@ -58,14 +58,9 @@ export default function Home() {
if (htdflRes && htdflRes.length > 0) {
const htdflData = tableData(htdflRes, { code }).map(
(item: customHtdflBdst) => {
const archArea =
item?.archArea.split(".")[0] !== "-1"
? item?.archArea.split(".")[0]
: "확인불가";
return {
...item,
archArea: archArea,
archArea: formatArchArea(item?.archArea, 1),
cityText: item.ctpvCd === 0 ? "세종특별자치시" : (item as any).cityText,
sggText: (item as any).sggText === "없음" ? "-" : (item as any).sggText,
};
@@ -5,7 +5,7 @@ import {
rswtRegSize,
type customRswtBdst,
} from "@/app/store/ruseFcltMng/fcltReg/rswtReg";
import { tableData } from "@/components/lib/func/commom";
import { formatArchArea, tableData } from "@/components/lib/func/commom";
import RswtrRegForm from "@/components/ui/form/fcltReg/rswtrReg/rswtrRegForm";
import { BdstReg } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import {
@@ -71,13 +71,9 @@ export default function Home() {
if (rswtRes?.length > 0) {
const rswtData = tableData(rswtRes, { code })?.map(
(item: customRswtBdst) => {
const archArea =
item?.archArea.split(".")[0] !== "-1"
? item?.archArea.split(".")[0]
: "확인불가";
return {
...item,
archArea: archArea,
archArea: formatArchArea(item?.archArea, 1),
bdstChgYn: item.chgBuilding[0]?.bdstChgNm != null ? "Y" : "N",
bdstUsgCd: item.reuseBuilding[0]?.bdstUsgCd,
cityText: item.ctpvCd === 0 ? "세종특별자치시" : (item as any).cityText,
@@ -9,10 +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";
@@ -111,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'));
@@ -137,6 +147,11 @@ export default function HtdflSttn() {
...item.reuseBuilding[0],
...item.reuseBuilding[0].htdflObj,
chBuildingYn: item.chgBuilding[0]?.bdstChgNm !== null ? "Y" : "N",
archArea: formatArchArea(item?.archArea, 1),
prcsFcltCpct:
Number(item.reuseBuilding[0]?.htdflObj?.prcsFcltCpct) === -1
? "확인불가"
: formatCommaNumber(item.reuseBuilding[0]?.htdflObj?.prcsFcltCpct),
}))
.filter((item: any) => item.htdflObj !== undefined);
setBdstTable(chData);
@@ -213,20 +228,24 @@ export default function HtdflSttn() {
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
<UiTable
headName={undefined}
tableData={bdstTable || []}
headlist={htdflSttn.htdflSttHeadList}
pageSize={htdflSttnSize}
total={htdflSttnResCount || 0}
cellClick={(index: number | undefined, headId: string) => {
cellClick(index ?? undefined, headId);
}}
onPageChange={setPageNation}
resetPageNo={resetPage}
>
<HeadMakeColSpan upHeadList={htdflSttn.htdflSttNodeList} />
</UiTable>
<div className="h-full w-full overflow-x-scroll min-[1900px]:overflow-x-hidden">
<div className="w-[160%] min-[1900px]:w-[100%]">
<UiTable
headName={undefined}
tableData={bdstTable || []}
headlist={htdflSttn.htdflSttHeadList}
pageSize={htdflSttnSize}
total={htdflSttnResCount || 0}
cellClick={(index: number | undefined, headId: string) => {
cellClick(index ?? undefined, headId);
}}
onPageChange={setPageNation}
resetPageNo={resetPage}
>
<HeadMakeColSpan upHeadList={htdflSttn.htdflSttNodeList} />
</UiTable>
</div>
</div>
</ListDiv>
</div>
</div>
@@ -13,7 +13,8 @@ import { btnClass } from "@/app/store/common/code";
import { prfRegPageSize } from "@/app/store/prfmncReg/pbnstPrfmncReg";
import type { customPbnst } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
import type { WaterReuseFacility } from "@/app/store/ruseFcltMng/fcltSttn/pbnstSttn/type";
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 HeadChModal from "@/components/ui/modal/sttn/headChModal/headChModal";
import { PbnstSttnModal } from "@/components/ui/modal/sttn/pbnstSttnModal/pbnstSttnModal";
import {
@@ -103,13 +104,19 @@ export default function PbnstSttn() {
if (!isDownloadTriggered.current) {
return;
}
const sheetArray: SheetParameter[] = [{
data: pbnstSttn.excelList,
headerNum: 2,
headerRange: "A1:U2",
sheetName: 'sheet1',
startCol: 'A',
decimalArray0: [9,11,12,13,14,15,16] // 0부터 시작
}];
if (pbnstSttn.excelList.length > 0) {
excelDownload(
pbnstSttn.excelList,
excelDownloadNumStyle(
"하수재이용시설 현황",
"sample_pbnstSttn.xlsx",
"A1:U2",
3
sheetArray
);
} else {
toast.error(t("excelDownErrMsg"));
@@ -195,31 +202,35 @@ export default function PbnstSttn() {
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
<UiTable
headName={undefined}
tableData={bdstTable || []}
headlist={pbnstSttn.pbnstSttHeadList}
pageSize={15}
total={pbnstSttnResCount}
cellClick={(index: number | undefined) => {
cellCLick(index);
}}
onPageChange={(page: number) => {
pbnstSttnSearch(
false,
String(page),
String(prfRegPageSize),
ref.current,
pbnRuseNm,
searchYear,
fclts
);
setIsReset(false);
}}
resetPageNo={isReset}
>
<HeadMakeColSpan upHeadList={pbnstSttn.pbnstSttNodeList} />
</UiTable>
<div className="h-full w-full overflow-x-scroll min-[1900px]:overflow-x-hidden">
<div className="w-[160%] min-[1900px]:w-[100%]">
<UiTable
headName={undefined}
tableData={bdstTable || []}
headlist={pbnstSttn.pbnstSttHeadList}
pageSize={15}
total={pbnstSttnResCount}
cellClick={(index: number | undefined) => {
cellCLick(index);
}}
onPageChange={(page: number) => {
pbnstSttnSearch(
false,
String(page),
String(prfRegPageSize),
ref.current,
pbnRuseNm,
searchYear,
fclts
);
setIsReset(false);
}}
resetPageNo={isReset}
>
<HeadMakeColSpan upHeadList={pbnstSttn.pbnstSttNodeList} />
</UiTable>
</div>
</div>
</ListDiv>
</div>
</div>
@@ -9,10 +9,11 @@ import type {
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { rainSttnSize } from "@/app/store/ruseFcltMng/fcltSttn/rainSttn";
import {
excelDownload,
excelDownloadNumStyle,
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";
@@ -158,11 +159,18 @@ export default function RainSttn() {
return;
}
if (rainSttn.excelList.length > 0) {
excelDownload(
rainSttn.excelList,
const sheetArray: SheetParameter[] = [{
data: rainSttn.excelList,
headerNum: 3,
headerRange: "A1:W3",
sheetName: 'sheet1',
startCol: 'A',
decimalArray0: [6,10,12,14,16] // 0부터 시작
}];
excelDownloadNumStyle(
"빗물이용시설 현황",
"sample_rainSttn.xlsx",
"A1:W3"
"sample_rainSttn.xlsx", // public 폴더에 있는 template 파일 경로
sheetArray
);
} else {
toast.error(t("excelDownErrMsg"));
@@ -265,20 +273,24 @@ export default function RainSttn() {
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
<UiTable
headName={undefined}
tableData={bdstTable || []}
headlist={rainSttn.rainSttHeadList}
pageSize={rainSttnSize}
total={rainSttnResCount || 0}
cellClick={(index: number | undefined) => {
cellClick(index ?? undefined);
}}
onPageChange={setPageNation}
resetPageNo={resetPage}
>
<HeadMakeColSpan upHeadList={rainSttn.rainSttNodeList} />
</UiTable>
<div className="h-full w-full overflow-x-scroll min-[1900px]:overflow-x-hidden">
<div className="w-[160%] min-[1900px]:w-[100%]">
<UiTable
headName={undefined}
tableData={bdstTable || []}
headlist={rainSttn.rainSttHeadList}
pageSize={rainSttnSize}
total={rainSttnResCount || 0}
cellClick={(index: number | undefined) => {
cellClick(index ?? undefined);
}}
onPageChange={setPageNation}
resetPageNo={resetPage}
>
<HeadMakeColSpan upHeadList={rainSttn.rainSttNodeList} />
</UiTable>
</div>
</div>
</ListDiv>
</div>
</div>
@@ -7,10 +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";
@@ -106,7 +109,11 @@ export default function RswtSttn() {
chBuildingYn: item?.chgBuilding[0]?.bdstChgNm !== null && item?.chgBuilding.length > 0 ? 'Y' : 'N',
instlCst: item.reuseBuilding[0]?.instlCst === -1 ? "확인불가" : item.reuseBuilding[0]?.instlCst,
instlCstSprtAmt: item.reuseBuilding[0]?.instlCstSprtAmt === -1 ? "확인불가" : item.reuseBuilding[0]?.instlCstSprtAmt,
archArea: item?.archArea.split('.')[0] !== '-1' ? item?.archArea.split('.')[0] : '확인불가',
archArea: formatArchArea(item?.archArea, 1),
filtrTrtmfctCpct:
Number(item.reuseBuilding[0]?.rswtrObj?.filtrTrtmfctCpct) === -1
? "확인불가"
: formatCommaNumber(item.reuseBuilding[0]?.rswtrObj?.filtrTrtmfctCpct),
}
})
.filter(
@@ -122,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'));
@@ -218,18 +232,22 @@ export default function RswtSttn() {
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
<UiTable
headName={undefined}
tableData={bdstTable || []}
headlist={rswtSttn.rswtSttHeadList}
pageSize={rswtSttnSize}
total={rswtSttnResCount || 0}
cellClick={(index: number | undefined) => { cellClick(index ?? undefined) }}
onPageChange={setPageNation}
resetPageNo={resetPage}
>
<HeadMakeColSpan upHeadList={rswtSttn.rswtSttNodeList} />
</UiTable>
<div className="h-full w-full overflow-x-scroll min-[1900px]:overflow-x-hidden">
<div className="w-[160%] min-[1900px]:w-[100%]">
<UiTable
headName={undefined}
tableData={bdstTable || []}
headlist={rswtSttn.rswtSttHeadList}
pageSize={rswtSttnSize}
total={rswtSttnResCount || 0}
cellClick={(index: number | undefined) => { cellClick(index ?? undefined) }}
onPageChange={setPageNation}
resetPageNo={resetPage}
>
<HeadMakeColSpan upHeadList={rswtSttn.rswtSttNodeList} />
</UiTable>
</div>
</div>
</ListDiv>
</div>
</div>
@@ -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
);
}
};
@@ -248,29 +261,33 @@ export default function Page() {
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
{selFcltDiv === "RNB" ? (
<RainChkgdTable
deleteData={() => {}}
detailUp={() => {}}
handleClick={handleClick}
rainChkData={rainChkSttn.rainChkRes}
pageNation={rainPageNation}
onPageChange={rainPageChange}
pageCount={rainChkSttn.rainChkCount}
readonly={true}
/>
) : (
<RswtChkgdTable
detaiRswtlUpdate={() => {}}
deleteRswtData={() => {}}
handleRswtClick={handleClick}
rswtChkData={rswtChkSttn.rswtChkRes}
pageNation={rswtPageNation}
onPageChange={rswtPageChange}
pageCount={rswtChkSttn.rswtChkCount}
readonly={true}
/>
)}
<div className="h-full w-full overflow-x-scroll min-[1900px]:overflow-x-hidden">
<div className="w-[160%] min-[1900px]:w-[100%]">
{selFcltDiv === "RNB" ? (
<RainChkgdTable
deleteData={() => {}}
detailUp={() => {}}
handleClick={handleClick}
rainChkData={rainChkSttn.rainChkRes}
pageNation={rainPageNation}
onPageChange={rainPageChange}
pageCount={rainChkSttn.rainChkCount}
readonly={true}
/>
) : (
<RswtChkgdTable
detaiRswtlUpdate={() => {}}
deleteRswtData={() => {}}
handleRswtClick={handleClick}
rswtChkData={rswtChkSttn.rswtChkRes}
pageNation={rswtPageNation}
onPageChange={rswtPageChange}
pageCount={rswtChkSttn.rswtChkCount}
readonly={true}
/>
)}
</div>
</div>
</ListDiv>
</div>
</div>
@@ -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
);
}
@@ -7,27 +7,11 @@ import { z } from "zod";
export const pbnSttHeadListExport: z.infer<typeof sttnHeadListType> = [
{ id: "rvbsn", title: "권역", visible: true },
{
id: "lgbsn",
title: "단위유역",
visible: true,
},
{
id: "mdmbsn",
title: "중권역",
visible: true,
},
{ id: "lgbsn", title: "단위유역", visible: true, },
{ id: "mdmbsn", title: "중권역", visible: true, },
{ id: "rgnNm", title: "환경청", visible: true },
{
id: "sido",
title: "시도",
visible: true,
},
{
id: "gugun",
title: "시군구",
visible: true,
},
{ id: "sido", title: "시도", visible: true, },
{ id: "gugun", title: "시군구", visible: true, },
{ id: "bscFctNm", title: "시설명", visible: true },
{ id: "efflWqltStndrdNm", title: "지역구분", visible: true },
@@ -35,405 +19,69 @@ export const pbnSttHeadListExport: z.infer<typeof sttnHeadListType> = [
{ id: "fctCpc", title: "시설용량(톤/일)", visible: true },
{ id: "ruseUtztnFcltNm", title: "재이용시설명", visible: true },
{
id: "fcltCpct",
title: "시설용량(m³/일)",
visible: true,
},
{
id: "splyExtraCpct",
title: "하수처리량(m³/일)",
visible: true,
},
{
id: "ruseCpct",
title: "재이용량(m³/일)",
visible: true,
},
{ id: "fcltCpct", title: "시설용량(m³/일)", visible: true, },
{ id: "splyExtraCpct", title: "하수처리량(m³/일)", visible: true, },
{ id: "ruseCpct", title: "재이용량(m³/일)", visible: true, },
{
id: "usageTotal",
title: "합계",
visible: true,
},
{
id: "inUsage",
title: "장내용수",
visible: true,
},
{
id: "outUsage",
title: "장외용수",
visible: true,
},
{ id: "usageTotal", title: "합계", visible: true, },
{ id: "inUsage", title: "장내용수", visible: true, },
{ id: "outUsage", title: "장외용수", visible: true, },
{
id: "operMthd",
title: "운영방식",
visible: true,
},
{
id: "rprtvBzenty",
title: "대행업체",
visible: true,
},
{
id: "bgngDt",
title: "시작일",
visible: true,
},
{
id: "endDt",
title: "종료일",
visible: true,
},
{ id: "operMthd", title: "운영방식", visible: true, },
{ id: "rprtvBzenty", title: "대행업체", visible: true, },
{ id: "bgngDt", title: "시작일", visible: true, },
{ id: "endDt", title: "종료일", visible: true, },
];
// id는 다확인해야함
export const pbnstSttNodeListExport: CommonTableProps[] = [
{
id: "catchment",
title: "유역",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 3,
},
{
id: "rgnNm",
title: "환경청",
visible: true,
row: 1,
rowSpan: 2,
colSpan: 1,
},
{
id: "adminDiv",
title: "행정구역",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 2,
},
{
id: "bscFctNm",
title: "시설명",
visible: true,
row: 1,
rowSpan: 2,
colSpan: 1,
},
{
id: "efflWqltStndrdNm",
title: "지역구분",
visible: true,
row: 1,
rowSpan: 2,
colSpan: 1,
},
{
id: "tel",
title: "전화번호",
visible: true,
row: 1,
rowSpan: 2,
colSpan: 1,
},
{
id: "fctCpc",
title: "시설용량(m³/일)",
visible: true,
row: 1,
rowSpan: 2,
colSpan: 1,
},
{
id: "ruseUtztnFcltNm",
title: "재이용시설명",
visible: true,
row: 1,
rowSpan: 2,
colSpan: 1,
},
{
id: "rusSup",
title: "재이용수공급가능량(m³/일)",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 3,
},
{
id: "yearResult",
title: "연간실적정보(m³)",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 3,
},
{
id: "mngInfo",
title: "운영정보",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 4,
},
{
id: "rvbsn",
title: "권역",
upName: "catchment",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "lgbsn",
title: "단위유역",
upName: "catchment",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "mdmbsn",
title: "중권역",
upName: "catchment",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "sido",
title: "시도",
upName: "adminDiv",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "gugun",
title: "시군구",
upName: "adminDiv",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "fcltCpct",
title: "시설용량",
upName: "rusSup",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "splyExtraCpct",
title: "하수처리량",
upName: "rusSup",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "ruseCpct",
title: "재이용량",
upName: "rusSup",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "usageTotal",
title: "합계",
upName: "yearResult",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "inUsage",
title: "장내용수",
upName: "yearResult",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "outUsage",
title: "장외용수",
upName: "yearResult",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "operMthd",
title: "운영방식",
upName: "mngInfo",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "rprtvBzenty",
title: "대행업체",
upName: "mngInfo",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "bgngDt",
title: "시작일",
upName: "mngInfo",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "endDt",
title: "종료일",
upName: "mngInfo",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{ id: "catchment", title: "유역", visible: true, row: 1, rowSpan: 1, colSpan: 3, },
{ id: "rgnNm", title: "환경청", visible: true, row: 1, rowSpan: 2, colSpan: 1, },
{ id: "adminDiv", title: "행정구역", visible: true, row: 1, rowSpan: 1, colSpan: 2, },
{ id: "bscFctNm", title: "시설명", visible: true, row: 1, rowSpan: 2, colSpan: 1, },
{ id: "efflWqltStndrdNm", title: "지역구분", visible: true, row: 1, rowSpan: 2, colSpan: 1, },
{ id: "tel", title: "전화번호", visible: true, row: 1, rowSpan: 2, colSpan: 1, },
{ id: "fctCpc", title: "시설용량(m³/일)", visible: true, row: 1, rowSpan: 2, colSpan: 1, },
{ id: "ruseUtztnFcltNm", title: "재이용시설명", visible: true, row: 1, rowSpan: 2, colSpan: 1, },
{ id: "rusSup", title: "재이용수공급가능량(m³/일)", visible: true, row: 1, rowSpan: 1, colSpan: 3, },
{ id: "yearResult", title: "연간실적정보(m³)", visible: true, row: 1, rowSpan: 1, colSpan: 3, },
{ id: "mngInfo", title: "운영정보", visible: true, row: 1, rowSpan: 1, colSpan: 4, },
{ id: "rvbsn", title: "권역", upName: "catchment", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
{ id: "lgbsn", title: "단위유역", upName: "catchment", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
{ id: "mdmbsn", title: "중권역", upName: "catchment", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
{ id: "sido", title: "시도", upName: "adminDiv", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
{ id: "gugun", title: "시군구", upName: "adminDiv", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
{ id: "fcltCpct", title: "시설용량", upName: "rusSup", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
{ id: "splyExtraCpct", title: "하수처리량", upName: "rusSup", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
{ id: "ruseCpct", title: "재이용량", upName: "rusSup", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
{ id: "usageTotal", title: "합계", upName: "yearResult", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
{ id: "inUsage", title: "장내용수", upName: "yearResult", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
{ id: "outUsage", title: "장외용수", upName: "yearResult", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
{ id: "operMthd", title: "운영방식", upName: "mngInfo", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
{ id: "rprtvBzenty", title: "대행업체", upName: "mngInfo", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
{ id: "bgngDt", title: "시작일", upName: "mngInfo", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
{ id: "endDt", title: "종료일", upName: "mngInfo", visible: true, row: 2, rowSpan: 1, colSpan: 1, },
];
export const ruseFcltNodeListExport: TableUpperProps[] = [
{ id: "cycl", title: "차수", visible: true, row: 1, rowSpan: 3, colSpan: 1 },
{ id: "seCd", title: "구분", visible: true, row: 1, rowSpan: 3, colSpan: 1 },
{
id: "busiTotal",
title: "사업개요",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 9,
},
{
id: "ruseFclt",
title: "재처리시설",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 3,
},
{
id: "mainSplyPumpCpct",
title: "메인공급펌프용량(m³/일)",
visible: true,
row: 1,
rowSpan: 3,
colSpan: 1,
},
{
id: "buziFee",
title: "사업비(원)",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 5,
},
{
id: "instlAprvSncnDt",
title: "설치승인・인가일",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "bizCmcnDay",
title: "사업준공일",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "rprcsFcltCpct",
title: "시설용량(m³/일)",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "rprcsMthdCd",
title: "재처리방식",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "majorPrcsMsrcCd",
title: "주처리공법",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "inoutYn",
title: "위치처리장(내・외)",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "addr",
title: "위치(주소)",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{ id: "busiTotal", title: "사업개요", visible: true, row: 1, rowSpan: 1, colSpan: 9 },
{ id: "ruseFclt", title: "재처리시설", visible: true, row: 1, rowSpan: 1, colSpan: 3 },
{ id: "mainSplyPumpCpct", title: "메인공급펌프용량(m³/일)", visible: true, row: 1, rowSpan: 3, colSpan: 1 },
{ id: "buziFee", title: "사업비(원)", visible: true, row: 2, rowSpan: 1, colSpan: 5 },
{ id: "instlAprvSncnDt", title: "설치승인・인가일", visible: true, row: 2, rowSpan: 2, colSpan: 1 },
{ id: "bizCmcnDay", title: "사업준공일", visible: true, row: 2, rowSpan: 2, colSpan: 1 },
{ id: "rprcsFcltCpct", title: "시설용량(m³/일)", visible: true, row: 2, rowSpan: 2, colSpan: 1 },
{ id: "rprcsMthdCd", title: "재처리방식", visible: true, row: 2, rowSpan: 2, colSpan: 1 },
{ id: "majorPrcsMsrcCd", title: "주처리공법", visible: true, row: 2, rowSpan: 2, colSpan: 1 },
{ id: "inoutYn", title: "위치처리장(내・외)", visible: true, row: 2, rowSpan: 2, colSpan: 1 },
{ id: "addr", title: "위치(주소)", visible: true, row: 2, rowSpan: 2, colSpan: 1 },
{ id: "gvsbs", title: "국고", visible: true, row: 3, rowSpan: 1, colSpan: 1 },
{
id: "lcep",
title: "지방비",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "cusrAlotm",
title: "민간투자비",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{ id: "lcep", title: "지방비", visible: true, row: 3, rowSpan: 1, colSpan: 1 },
{ id: "cusrAlotm", title: "민간투자비", visible: true, row: 3, rowSpan: 1, colSpan: 1 },
{ id: "etc", title: "기타", visible: true, row: 3, rowSpan: 1, colSpan: 1 },
{
id: "totalMoney",
title: "합계",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{ id: "totalMoney", title: "합계", visible: true, row: 3, rowSpan: 1, colSpan: 1 },
];
export const ruseSplyHeadListExport: TableUpperProps[] = [
@@ -481,61 +129,16 @@ export const ruseFcltHeadListExport: CommonTableProps[] = [
{ id: "cycl", title: "차수", visible: true},
{ id: "seCd", title: "구분", visible: true},
{ id: "gvsbs", title: "국고", visible: true },
{
id: "lcep",
title: "지방비",
visible: true,
},
{
id: "cusrAlotm",
title: "민간투자비",
visible: true,
},
{ id: "lcep", title: "지방비", visible: true },
{ id: "cusrAlotm", title: "민간투자비", visible: true },
{ id: "etc", title: "기타", visible: true },
{
id: "totalMoney",
title: "합계",
visible: true,
},
{
id: "instlAprvSncnDt",
title: "설치승인・인가일",
visible: true,
},
{
id: "bizCmcnDay",
title: "사업준공일",
visible: true,
},
{
id: "rprcsFcltCpct",
title: "시설용량(m³/일)",
visible: true,
},
{
id: "rprcsMthdCd",
title: "재처리방식",
visible: true,
},
{
id: "majorPrcsMsrcCd",
title: "주처리공법",
visible: true,
},
{
id: "inoutYn",
title: "위치처리장(내・외)",
visible: true,
},
{
id: "addr",
title: "위치(주소)",
visible: true,
},
{
id: "mainSplyPumpCpct",
title: "메인공급펌프용량",
visible: true,
},
{ id: "totalMoney", title: "합계", visible: true },
{ id: "instlAprvSncnDt", title: "설치승인・인가일", visible: true },
{ id: "bizCmcnDay", title: "사업준공일", visible: true },
{ id: "rprcsFcltCpct", title: "시설용량(m³/일)", visible: true },
{ id: "rprcsMthdCd", title: "재처리방식", visible: true },
{ id: "majorPrcsMsrcCd", title: "주처리공법", visible: true },
{ id: "inoutYn", title: "위치처리장(내・외)", visible: true },
{ id: "addr", title: "위치(주소)", visible: true },
{ id: "mainSplyPumpCpct", title: "메인공급펌프용량", visible: true },
];
@@ -166,13 +166,14 @@ export const hasuListFetch = async (
const pbnList = await postFectch(
`/prcsFclt/ruseInfo/1/${filteredFclt.length}/` + url,
filteredFclt,
fetchType.COMMON
fetchType.COMMON // FO
);
const checkRuseFcltList =
searchNm && searchNm?.length > 0
? pbnList.data.map((item) => item.bscFctCd)
: filteredFclt;
const getRuseList = await postFectch(
`/reuseFc/pubDetailList/${year}/${filterData}/${page}/${total}`,
checkRuseFcltList,
+18
View File
@@ -2,6 +2,7 @@ import { lwCds, type comCodeState } from "@/app/store/common/code";
import {
filePickedBlob,
filePickedBlobArray,
filePickedBlobNumStyle,
type ReturnType,
type SelectDataType,
type SheetParameter,
@@ -100,6 +101,23 @@ export const excelDownload = (
});
};
export const excelDownloadNumStyle = (
fileNm: string,
sampleFile: string,
sheetArray: SheetParameter[]
) => {
// if (excelList.length === 0) return;
fetch(`/${sampleFile}`, {}).then(async (response) => { // excel Tamplate을 읽는다.
if (!response.ok) {
throw Error(response.statusText);
}
// 받은 파일 바인너리 처리
const blobRet = await response.arrayBuffer();
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
await filePickedBlobNumStyle(blobRet, fileNm, sheetArray);
});
};
export const excelArrayDownload = (
fileNm: string,
sampleFile: string,
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -17,6 +17,104 @@ type ExcelDownloadProps = {
decimalRange3?: string;
}
export type SheetParameter = {
data: unknown[][];
headerNum: number;
headerRange: string;
sheetName: string;
startCol?: string;
decimalArray0?: number[];
decimalArray1?: number[];
decimalArray2?: number[];
decimalArray3?: number[];
decimalRange0?: string;
decimalRange1?: string;
decimalRange2?: string;
decimalRange3?: string;
};
// Shared utility to apply number formatting to a sheet range
export const applyRangeFormat = (
sheet: XLSX.WorkSheet,
rangeStr: string | undefined,
decimal: number
) => {
if (!rangeStr) return;
const parts = rangeStr
.split(",")
.map((part) => part.trim())
.filter(Boolean);
for (const part of parts) {
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 });
const cell = sheet[cellAddr];
if (cell) {
if (typeof cell.v === "string") {
const parsed = Number(cell.v.replace(/,/g, "").trim());
if (!Number.isNaN(parsed)) {
cell.v = parsed;
cell.t = "n";
}
}
}
if (cell && typeof cell.v === "number") {
if (decimal === 1) {
cell.z = "#,##0.0";
} else if (decimal === 2) {
cell.z = "#,##0.00";
} else if (decimal === 3) {
cell.z = "#,##0.000";
} else {
cell.z = "#,##0";
}
}
}
}
}
};
// Shared utility to apply decimal formatting to specific columns in a sheet
export const applyDecimalColumns = (
sheet: XLSX.WorkSheet,
startRow: number,
range: XLSX.Range,
columns: number[],
decimal: number
) => {
for (let row = startRow; row <= range.e.r; row++) {
if (columns.length > 0) {
for (let idx = 0; idx < columns.length; idx++) {
const cellAddr = XLSX.utils.encode_cell({ r: row, c: Number(columns[idx]) });
const cell = sheet[cellAddr];
if (cell) {
if (typeof cell.v === "string") {
const parsed = Number(cell.v.replace(/,/g, "").trim());
if (!Number.isNaN(parsed)) {
cell.v = parsed;
cell.t = "n";
}
}
}
if (cell && typeof cell.v === "number") {
if (decimal === 1) {
cell.z = "#,##0.0"; // 소수점 1자리
} else if (decimal === 2) {
cell.z = "#,##0.00";
} else if (decimal === 3) {
cell.z = "#,##0.000";
} else {
cell.z = "#,##0"; // 기본 천단위 콤마
}
}
}
}
}
};
export const downloadExcel = ({ data, fileName = new Date().getTime().toString() + '.xlsx', sheetNameArray = ["Sheet1"], headerRange='A1:V3'}: ExcelDownloadProps) => {
const worksheet = XLSX.utils.json_to_sheet(Array.isArray(data) ? data : [data]);
const workbook = XLSX.utils.book_new();
@@ -50,78 +148,24 @@ 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);
const chaneValue = (array: number[], decimal: number) => {
for (let row = startRow; row <= range.e.r; row++) {
if(array.length>0){
for(let idx=0; idx<array.length; idx++){
const cellAddr = XLSX.utils.encode_cell({ r: row, c: Number(array[idx]) });
const cell = worksheet[cellAddr];
if (cell && typeof cell.v === "number") {
if(decimal===1){
cell.z = "#,##0.0"; // 소수점 3자리
}else if(decimal===2){
cell.z = "#,##0.00";
}else if(decimal===3){
cell.z = "#,##0.000";
}else{
cell.z = "#,##0"; // 기본 천단위 콤마
}
}
}
}
}
};
const applyRangeFormat = (rangeStr: string | undefined, decimal: number) => {
if (!rangeStr) return;
const rangeInfo = XLSX.utils.decode_range(rangeStr);
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 });
const cell = worksheet[cellAddr];
if (cell && typeof cell.v === "number") {
if (decimal === 1) {
cell.z = "#,##0.0";
} else if (decimal === 2) {
cell.z = "#,##0.00";
} else if (decimal === 3) {
cell.z = "#,##0.000";
} else {
cell.z = "#,##0";
}
}
}
}
};
chaneValue(decimalArray0, 0);
chaneValue(decimalArray1, 1);
chaneValue(decimalArray2, 2);
chaneValue(decimalArray3, 3);
applyRangeFormat(decimalRange0, 0);
applyRangeFormat(decimalRange1, 1);
applyRangeFormat(decimalRange2, 2);
applyRangeFormat(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);
};
export type SheetParameter = {
data: any[][];
headerNum: number;
headerRange: string;
sheetName: string;
startCol?: string;
decimalRange0?: string;
decimalRange1?: string;
decimalRange2?: string;
decimalRange3?: string;
};
export const downloadMultipleExcel = (fileName = new Date().getTime().toString() + '.xlsx', sheetArray: SheetParameter[]): Promise<JSON | undefined> => {
const workbook = XLSX.utils.book_new();
for (let i = 0; i < sheetArray.length; i++) {
@@ -199,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)
@@ -223,7 +267,13 @@ export const filePickedArray=(oFile: File, headerNum:number=0):Promise<JSON[] |
});
}
export const filePickedBlob=(oFile: ArrayBuffer, data:[][],fileNm:string, headerNum:number=0, headerRange='A1:V3', startCol?:number):Promise<JSON | undefined> =>{ // Create A File Reader HTML5
export const filePickedBlob = (
oFile: ArrayBuffer,
data:[][],fileNm:string,
headerNum:number=0,
headerRange='A1:V3',
startCol?:number
):Promise<JSON | undefined> =>{ // Create A File Reader HTML5
return new Promise<JSON | undefined>(() => {
// Ready The Event For When A File Gets Selected
const wb = XLSX.read(oFile, { type: 'binary' });
@@ -244,26 +294,57 @@ export const filePickedBlob=(oFile: ArrayBuffer, data:[][],fileNm:string, header
}
}
});
});
}
});
}
export const filePickedBlobNumStyle = async (
oFile: ArrayBuffer,
fileNm:string,
sheetArray: SheetParameter[]
):Promise<JSON | undefined> => { // Create A File Reader HTML5
// Ready The Event For When A File Gets Selected
const wb = XLSX.read(oFile, { type: "binary" });
wb.SheetNames.forEach((sheetName, index) => {
if (sheetArray[index]) {
const sheet = wb.Sheets[sheetName];
if (sheet) {
const startCol = sheetArray[index].startCol ?? "A";
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부터 시작
// 사용된 셀 범위(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); }
if(sheetArray[index].decimalArray2){ applyDecimalColumns(sheet, startRow, range, sheetArray[index].decimalArray2, 2); }
if(sheetArray[index].decimalArray3){ applyDecimalColumns(sheet, startRow, range, sheetArray[index].decimalArray3, 3); }
if(sheetArray[index].decimalRange0){ applyRangeFormat(sheet, sheetArray[index].decimalRange0, 0); }
if(sheetArray[index].decimalRange1){ applyRangeFormat(sheet, sheetArray[index].decimalRange1, 1); }
if(sheetArray[index].decimalRange2){ applyRangeFormat(sheet, sheetArray[index].decimalRange2, 2); }
if(sheetArray[index].decimalRange3){ applyRangeFormat(sheet, sheetArray[index].decimalRange3, 3); }
} else {
console.error(`Sheet "${sheetName}" is undefined.`);
}
}
});
await excelArrayStyle(
XLSX.write(wb, { bookType: "xlsx", type: "buffer" }),
sheetArray,
fileNm
);
return undefined;
};
// export const filePickedBlobArray = (oFile: ArrayBuffer, fileNm: string, sheetArray: SheetParameter[]): Promise<JSON | undefined> => {
// return new Promise<JSON | undefined>(async () => {
// const wb = XLSX.read(oFile, { type: 'binary' });
// wb.SheetNames.forEach(function (sheetName, index) {
// if (sheetArray[index]) {
// const sheet = wb.Sheets[sheetName];
// if (sheet) {
// const startCol = sheetArray[index].startCol ? sheetArray[index].startCol : 'A';
// XLSX.utils.sheet_add_aoa(sheet, sheetArray[index].data, { origin: startCol + sheetArray[index].headerNum });
// } else {
// console.error(`Sheet "${sheetName}" is undefined.`);
// }
// }
// });
// await excelArrayStyle(XLSX.write(wb, { bookType: "xlsx", type: "buffer" }), sheetArray, fileNm)
// });
// }
export const filePickedBlobArray = async (
oFile: ArrayBuffer,
fileNm: string,
@@ -301,34 +382,10 @@ export const filePickedBlobArrayFormat = async (
XLSX.utils.sheet_add_aoa(sheet, sheetArray[index].data, {
origin: startCol + sheetArray[index].headerNum,
});
const applyRangeFormat = (rangeStr: string | undefined, decimal: number) => {
if (!rangeStr) return;
const parts = rangeStr.split(",").map((part) => part.trim()).filter(Boolean);
for (const part of parts) {
const rangeInfo = XLSX.utils.decode_range(part);
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 });
const cell = sheet[cellAddr];
if (cell && typeof cell.v === "number") {
if (decimal === 1) {
cell.z = "#,##0.0";
} else if (decimal === 2) {
cell.z = "#,##0.00";
} else if (decimal === 3) {
cell.z = "#,##0.000";
} else {
cell.z = "#,##0";
}
}
}
}
}
};
applyRangeFormat(sheetArray[index].decimalRange0, 0);
applyRangeFormat(sheetArray[index].decimalRange1, 1);
applyRangeFormat(sheetArray[index].decimalRange2, 2);
applyRangeFormat(sheetArray[index].decimalRange3, 3);
applyRangeFormat(sheet, sheetArray[index].decimalRange0, 0);
applyRangeFormat(sheet, sheetArray[index].decimalRange1, 1);
applyRangeFormat(sheet, sheetArray[index].decimalRange2, 2);
applyRangeFormat(sheet, sheetArray[index].decimalRange3, 3);
} else {
console.error(`Sheet "${sheetName}" is undefined.`);
}