Skip to content

Commit 746eace

Browse files
committed
결과 데이터 집계 건수 추출 기능 추가
1 parent f373cf8 commit 746eace

File tree

3 files changed

+88
-7
lines changed

3 files changed

+88
-7
lines changed

queries/queries-sample.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<var name="endDate">2024-06-30</var>
2525
<var name="regionList">'서울','부산'</var>
2626
</vars>
27-
<sheet name="${envType}_주문_목록" use="true">
27+
<sheet name="${envType}_주문_목록" use="true" aggregateColumn="주문상태">
2828
<![CDATA[
2929
SELECT
3030
OrderNumber as 주문번호,
@@ -38,7 +38,7 @@
3838
ORDER BY OrderDate DESC
3939
]]>
4040
</sheet>
41-
<sheet name="고객_목록" use="true">
41+
<sheet name="고객_목록" use="true" aggregateColumn="지역">
4242
<![CDATA[
4343
SELECT
4444
CustomerCode as 고객코드,

src/excel-style-helper.js

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ function createTableOfContents(workbook, sheetNames) {
318318
{ header: 'No', key: 'no', width: 6 },
319319
{ header: 'Sheet Name', key: 'name', width: 25 },
320320
{ header: 'Records', key: 'records', width: 12 },
321+
{ header: 'Aggregate Info', key: 'aggregate', width: 35 },
321322
{ header: 'Note', key: 'note', width: 18 }
322323
];
323324

@@ -349,15 +350,25 @@ function populateTableOfContents(tocSheet, sheetNames) {
349350
tocSheet.spliceRows(1, tocSheet.rowCount);
350351

351352
// 헤더 추가
352-
tocSheet.addRow(['No', 'Sheet Name', 'Records', 'Note']);
353+
tocSheet.addRow(['No', 'Sheet Name', 'Records', 'Aggregate Info', 'Note']);
353354

354355
// 시트 목록 추가
355356
sheetNames.forEach((obj, idx) => {
356357
// 시트명이 잘렸는지 확인
357358
const isTruncated = obj.originalName && obj.originalName !== obj.tabName;
358359
const noteText = isTruncated ? '(31자 초과로 잘림)' : '';
359360

360-
const row = tocSheet.addRow([idx + 1, obj.displayName, obj.recordCount || 0, noteText]);
361+
// 집계 정보 텍스트 생성
362+
let aggregateInfo = '';
363+
if (obj.aggregateColumn && obj.aggregateData && obj.aggregateData.length > 0) {
364+
const topItems = obj.aggregateData.slice(0, 3); // 상위 3개만 표시
365+
aggregateInfo = `[${obj.aggregateColumn}] ${topItems.map(item => `${item.key}:${item.count}`).join(', ')}`;
366+
if (obj.aggregateData.length > 3) {
367+
aggregateInfo += ` 외 ${obj.aggregateData.length - 3}개`;
368+
}
369+
}
370+
371+
const row = tocSheet.addRow([idx + 1, obj.displayName, obj.recordCount || 0, aggregateInfo, noteText]);
361372

362373
// 하이퍼링크 설정 - 실제 시트명(tabName) 사용
363374
const sheetNameForLink = obj.tabName.replace(/'/g, "''"); // 작은따옴표 이스케이프
@@ -429,9 +440,53 @@ function populateTableOfContents(tocSheet, sheetNames) {
429440
recordCountCell.numFmt = '#,##0'; // 천 단위 구분자
430441
recordCountCell.alignment = { horizontal: 'right' };
431442

432-
// 비고 컬럼 스타일링
443+
// 집계 데이터 컬럼에 하이퍼링크 적용
444+
const aggregateCell = row.getCell(4);
445+
if (aggregateInfo) {
446+
// 집계 정보에도 하이퍼링크 적용
447+
const aggregateFormula = `HYPERLINK("#'${sheetNameForLink}'!A1","${aggregateInfo.replace(/"/g, '""')}")`;
448+
449+
try {
450+
aggregateCell.value = { formula: aggregateFormula };
451+
aggregateCell.font = {
452+
color: { argb: '0563C1' },
453+
underline: true
454+
};
455+
} catch (error) {
456+
// HYPERLINK 함수 실패 시 직접 하이퍼링크 방식 시도
457+
try {
458+
aggregateCell.value = {
459+
text: aggregateInfo,
460+
hyperlink: `#'${sheetNameForLink}'!A1`
461+
};
462+
aggregateCell.font = {
463+
color: { argb: '0563C1' },
464+
underline: true
465+
};
466+
} catch (error2) {
467+
// 모든 방법 실패 시 일반 텍스트로 표시
468+
aggregateCell.value = aggregateInfo;
469+
aggregateCell.font = {
470+
color: { argb: '2F5597' }
471+
};
472+
}
473+
}
474+
475+
// 집계 데이터 스타일링
476+
aggregateCell.alignment = { horizontal: 'left', vertical: 'middle' };
477+
aggregateCell.font = {
478+
...aggregateCell.font,
479+
size: 10
480+
};
481+
} else {
482+
// 집계 데이터가 없는 경우
483+
aggregateCell.value = '';
484+
aggregateCell.font = { color: { argb: '999999' } };
485+
}
486+
487+
// 비고 컬럼 스타일링 (5번째 컬럼)
433488
if (isTruncated) {
434-
row.getCell(4).font = {
489+
row.getCell(5).font = {
435490
italic: true,
436491
color: { argb: 'D2691E' } // 주황색으로 경고 표시
437492
};

src/index.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ async function loadQueriesFromXML(xmlPath) {
3737
}
3838
const sheets = parsed.queries.sheet.map(s => ({
3939
name: s.$.name,
40+
use: s.$.use,
41+
aggregateColumn: s.$.aggregateColumn || null,
4042
query: (s._ || (s["_"] ? s["_"] : (s["$"] ? s["$"] : '')) || (s["__cdata"] ? s["__cdata"] : '') || (s["cdata"] ? s["cdata"] : '') || (s["#cdata-section"] ? s["#cdata-section"] : '') || (s["__text"] ? s["__text"] : '') || (s["#text"] ? s["#text"] : '') || (s["$text"] ? s["$text"] : '') || (s["$value"] ? s["$value"] : '') || (s["value"] ? s["value"] : '') || '').toString().trim()
4143
}));
4244
return { globalVars, sheets, dbId, outputPath };
@@ -303,11 +305,35 @@ async function main() {
303305
// 실제 생성된 시트명 가져오기 (31자 초과시 잘린 이름)
304306
const actualSheetName = sheet.name;
305307

308+
// 집계 컬럼이 지정된 경우 집계 데이터 계산
309+
let aggregateData = null;
310+
if (sheetDef.aggregateColumn && recordCount > 0) {
311+
const aggregateColumn = sheetDef.aggregateColumn;
312+
const aggregateMap = {};
313+
314+
result.recordset.forEach(row => {
315+
const value = row[aggregateColumn];
316+
if (value !== null && value !== undefined) {
317+
const key = String(value).trim();
318+
aggregateMap[key] = (aggregateMap[key] || 0) + 1;
319+
}
320+
});
321+
322+
// 집계 결과를 배열로 변환 (건수가 많은 순으로 정렬)
323+
aggregateData = Object.entries(aggregateMap)
324+
.map(([key, count]) => ({ key, count }))
325+
.sort((a, b) => b.count - a.count);
326+
327+
console.log(`\t[집계] ${aggregateColumn} 컬럼 집계: ${aggregateData.map(item => `${item.key}(${item.count})`).join(', ')}`);
328+
}
329+
306330
createdSheetNames.push({
307331
displayName: sheetName,
308332
originalName: sheetName,
309333
tabName: actualSheetName,
310-
recordCount: recordCount
334+
recordCount: recordCount,
335+
aggregateColumn: sheetDef.aggregateColumn,
336+
aggregateData: aggregateData
311337
});
312338
createdSheetCounts.push(recordCount);
313339

0 commit comments

Comments
 (0)