@@ -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 } ;
0 commit comments