wr: 빗물사용시설 excel 천단위 처리
This commit is contained in:
@@ -9,10 +9,11 @@ import type {
|
||||
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
|
||||
import { rainSttnSize } from "@/app/store/ruseFcltMng/fcltSttn/rainSttn";
|
||||
import {
|
||||
excelDownload,
|
||||
excelDownloadStyle,
|
||||
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,19 @@ 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',
|
||||
writeLine: 4,
|
||||
startCol: 'A',
|
||||
decimalArray0: [6,10,12,14,16]
|
||||
}];
|
||||
excelDownloadStyle(
|
||||
"빗물이용시설 현황",
|
||||
"sample_rainSttn.xlsx",
|
||||
"A1:W3"
|
||||
"sample_rainSttn.xlsx", // public 폴더에 있는 template 파일 경로
|
||||
sheetArray
|
||||
);
|
||||
} else {
|
||||
toast.error(t("excelDownErrMsg"));
|
||||
|
||||
@@ -2,11 +2,14 @@ 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";
|
||||
@@ -100,6 +103,26 @@ export const excelDownload = (
|
||||
});
|
||||
};
|
||||
|
||||
export const excelDownloadStyle = (
|
||||
// excelList: [][],
|
||||
fileNm: string,
|
||||
sampleFile: string,
|
||||
sheetArray: SheetParameter[]
|
||||
) => {
|
||||
// if (excelList.length === 0) return;
|
||||
fetch(`/${sampleFile}`, {}).then(async (response) => {
|
||||
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);
|
||||
});
|
||||
};
|
||||
|
||||
export const excelArrayDownload = (
|
||||
fileNm: string,
|
||||
sampleFile: string,
|
||||
|
||||
@@ -17,6 +17,105 @@ type ExcelDownloadProps = {
|
||||
decimalRange3?: string;
|
||||
}
|
||||
|
||||
export type SheetParameter = {
|
||||
data: any[][];
|
||||
headerNum: number;
|
||||
headerRange: string;
|
||||
sheetName: string;
|
||||
writeLine?: number;
|
||||
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);
|
||||
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();
|
||||
@@ -57,71 +156,17 @@ export const downloadExcelFormat = ({
|
||||
// 🔹 전체 범위
|
||||
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);
|
||||
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);
|
||||
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++) {
|
||||
@@ -223,7 +268,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 +295,56 @@ 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].writeLine ?? sheetArray[index].headerNum;
|
||||
|
||||
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);
|
||||
|
||||
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.`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user