st: refactor: 구분 별 footer 평균 값 계산 함수 추가

This commit is contained in:
2026-02-03 16:46:06 +09:00
parent 9eb40c46e5
commit 830cbf97d1
2 changed files with 91 additions and 5 deletions
@@ -1,5 +1,5 @@
import { ValueType } from "realgrid";
import { footerIntArrayByDivision, footerDecimal3ArrayByDivision } from "@/components/util/grid/footerSummary";
import { footerIntArrayByDivision, footerDecimal3ArrayByDivision, footerAvgDecimalArrayByDivision } from "@/components/util/grid/footerSummary";
import type { GridView, DataColumn, ColumnFooter } from "@/components/type/DataGrid.type";
// 하수도 통계 관리 01. 하수도 보급률
@@ -166,9 +166,9 @@ export const SeweragePenetrationRateInfoList = {
{ name: 'town_swtt_popltn', fieldName: '오수처리인구', header: { text: '오수처리인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'town_wrrtn_popltn', fieldName: '정화조인구', header: { text: '정화조인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'swge_proc_zone_outer_ar', fieldName: 'swge_proc_zone_outer_ar', header: { text: '면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' },
{ name: 'pblswrg_popltn_suprt', fieldName: '공공하수처리구역인구보급율(%)', header: { text: '공공하수처리구역인구보급율(%)' } },
{ name: 'adtrt_popltn_suprt', fieldName: '고도처리인구보급율(%)', header: { text: `고도처리인구보급율(%)` } },
{ name: 'swrg_instlrt', fieldName: '하수도설치율(%)', header: { text: '하수도설치율(%)' } },
{ name: 'pblswrg_popltn_suprt', fieldName: '공공하수처리구역인구보급율(%)', header: { text: '공공하수처리구역인구보급율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' },
{ name: 'adtrt_popltn_suprt', fieldName: '고도처리인구보급율(%)', header: { text: `고도처리인구보급율(%)` }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' },
{ name: 'swrg_instlrt', fieldName: '하수도설치율(%)', header: { text: '하수도설치율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' },
{ name: 'rmk', fieldName: '비고', header: { text: '비고' } },
],
columnLayout: [
@@ -107,6 +107,55 @@ export const getFooterSummaryByDivision = (
return sum;
};
// "구분" 필드 값에 따라 필터링하여 평균 계산하는 함수
// divisionIndex: 0 = 첫 번째 고유값, 1 = 두 번째 고유값
export const getFooterAvgSummaryByDivision = (
grid: GridView,
column: DataColumn,
divisionIndex: number,
divisionFieldName: string = '구분'
) => {
const dataSource = grid.getDataSource();
const rowCount = dataSource.getRowCount();
let sum = 0;
let count = 0;
// "구분" 필드의 고유값 찾기
const divisionValues = getDivisionValues(grid, divisionFieldName);
if (divisionValues.length <= divisionIndex) {
return 0; // 해당 인덱스의 고유값이 없으면 0 반환
}
const targetDivision = divisionValues[divisionIndex];
for (let i = 0; i < rowCount; i++) {
// "구분" 필드 값 확인
const divisionValue = dataSource.getValue(i, divisionFieldName);
if (String(divisionValue) !== targetDivision) {
continue; // 해당 "구분" 값이 아니면 스킵
}
const cellValue = dataSource.getValue(i, column.fieldName);
// 문자열인 경우 숫자로 변환
const numericValue = typeof cellValue === 'string'
? Number(String(cellValue).replace(/,/g, ''))
: Number(cellValue);
if (!isNaN(numericValue) && numericValue !== null && numericValue !== undefined) {
sum += numericValue;
count += 1;
}
}
if (count === 0) {
return 0;
}
const avg = sum / count;
return Math.floor(avg * 10) / 10;
};
// Footer 설정 객체 생성 함수
const createSumFooter = (format: string) => ({
expression: 'sum' as const,
@@ -156,6 +205,38 @@ const createSumFooterArrayByDivision = (format: string) => [
},
];
// "구분" 값에 따라 필터링하는 평균 Footer 배열 생성 함수 (2줄)
const createAvgFooterArrayByDivision = (format: string) => [
{
numberFormat: format,
valueCallback: (
grid: GridView,
column: DataColumn,
footerIndex: number,
columnFooter: unknown,
value: number | string | undefined
) => {
// footerIndex: 0 = 첫 번째 footer 행 (첫 번째 "구분" 값), 1 = 두 번째 footer 행 (두 번째 "구분" 값)
// footerIndex를 divisionIndex로 사용
return getFooterAvgSummaryByDivision(grid, column, footerIndex);
},
},
{
numberFormat: format,
valueCallback: (
grid: GridView,
column: DataColumn,
footerIndex: number,
columnFooter: unknown,
value: number | string | undefined
) => {
// footerIndex: 0 = 첫 번째 footer 행 (첫 번째 "구분" 값), 1 = 두 번째 footer 행 (두 번째 "구분" 값)
// footerIndex를 divisionIndex로 사용
return getFooterAvgSummaryByDivision(grid, column, footerIndex);
},
},
];
// 1. 정수형 : #,##0
export const footerInt = createSumFooter('#,##0');
@@ -171,12 +252,17 @@ export const footerDecimal3 = createSumFooter('#,##0.000');
// "구분" 값에 따라 필터링하는 Footer 배열 (정수형, 2줄)
export const footerIntArrayByDivision = createSumFooterArrayByDivision('#,##0');
// "구분" 값에 따라 필터링하는 Footer 배열 (소수점 1자리, 2줄)
export const footerDecimal1ArrayByDivision = createSumFooterArrayByDivision('#,##0.0');
// "구분" 값에 따라 필터링하는 Footer 배열 (소수점 2자리, 2줄)
export const footerDecimal2ArrayByDivision = createSumFooterArrayByDivision('#,##0.00');
// "구분" 값에 따라 필터링하는 Footer 배열 (소수점 3자리, 2줄)
export const footerDecimal3ArrayByDivision = createSumFooterArrayByDivision('#,##0.000');
// 률(%) 평균 값(기본 소수점 1자리)
export const footerAvgDecimal = createAvgFooter('#,##0.0');
export const footerAvgDecimal = createAvgFooter('#,##0.0');
// "구분" 값에 따라 필터링하는 평균 Footer 배열 (소수점 1자리, 2줄)
export const footerAvgDecimalArrayByDivision = createAvgFooterArrayByDivision('#,##0.0');