Skip to content

Commit 04fe7f4

Browse files
committed
각 시트 상단에 출처 DB명 출력 기능 추가
1 parent 7363294 commit 04fe7f4

File tree

3 files changed

+111
-9
lines changed

3 files changed

+111
-9
lines changed

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ node src/index.js -q resources/queries-sample.json --db main --out output/result
140140
- **컬럼별 집계 데이터 표시** (목차 시트에서 한눈에 확인)
141141
- **조회 건수 제한 기능** (대용량 데이터 처리 시 안전장치)
142142
- **시트별 다중 DB 연결** (여러 데이터베이스의 데이터를 하나의 엑셀로 통합)
143+
- **DB 출처 표시** (각 시트 상단에 데이터 출처 DB 자동 표시)
143144

144145
---
145146

@@ -281,6 +282,7 @@ node src/index.js -q resources/queries-sample.json --db main --out output/result
281282
- DB 연결 풀을 효율적으로 관리하여 동일 DB는 재사용
282283
- 시트별 DB 설정이 없으면 기본 DB 사용
283284
- 모든 작업 완료 후 자동으로 모든 DB 연결 정리
285+
- **각 시트 상단에 데이터 출처 DB명 자동 표시** (연한 파란색 배경)
284286

285287
#### XML에서 시트별 DB 지정
286288
```xml
@@ -357,6 +359,36 @@ node src/index.js -q resources/queries-sample.json --db main --out output/result
357359
- **환경별 비교**: 개발/스테이징/운영 DB의 동일 테이블 비교
358360
- **데이터 마이그레이션**: 구버전과 신버전 DB 데이터 비교
359361

362+
### DB 출처 표시 기능
363+
각 데이터 시트의 맨 위에 해당 데이터가 어떤 데이터베이스에서 가져온 것인지 자동으로 표시됩니다.
364+
365+
#### 표시 형태
366+
```
367+
📊 데이터 출처: sampleDB 데이터베이스
368+
[빈 행]
369+
[헤더 행]
370+
[데이터 행들...]
371+
```
372+
373+
#### 스타일링
374+
- **배경색**: 연한 파란색 (`#E7F3FF`)
375+
- **글꼴**: 굵게, 11pt, 파란색 (`#2F5597`)
376+
- **아이콘**: 📊 차트 이모지로 시각적 구분
377+
- **구분**: 빈 행으로 DB 정보와 데이터 구분
378+
379+
#### 데이터 없는 경우
380+
```
381+
📊 데이터 출처: orderDB 데이터베이스
382+
[빈 행]
383+
데이터가 없습니다.
384+
```
385+
386+
#### 장점
387+
- **데이터 추적성**: 각 시트의 데이터 출처를 명확하게 파악
388+
- **신뢰성**: 여러 DB 통합 시 데이터 혼동 방지
389+
- **문서화**: 별도 설명 없이도 데이터 출처 자동 기록
390+
- **시각적 구분**: 연한 파란색 배경으로 쉽게 식별 가능
391+
360392
### 목차 시트 특징
361393
- **하이퍼링크**: 시트명, 데이터 건수, 집계 정보 클릭 시 해당 시트로 즉시 이동
362394
- **시트명 자동 처리**: 31자 초과 시 자동 잘림 및 원본명 주석 표시

src/excel-style-helper.js

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,22 @@ function applyHeaderStyle(sheet, columns, headerStyle) {
139139
}
140140
}
141141

142+
/**
143+
* 지정된 행에 헤더 스타일을 적용
144+
* @param {Object} sheet - ExcelJS 워크시트 객체
145+
* @param {Array} columns - 컬럼 배열
146+
* @param {Object} headerStyle - 헤더 스타일 객체
147+
* @param {number} rowNumber - 헤더가 위치할 행 번호
148+
*/
149+
function applyHeaderStyleAtRow(sheet, columns, headerStyle, rowNumber) {
150+
if (!headerStyle || !sheet || !columns) return;
151+
152+
for (let i = 1; i <= columns.length; i++) {
153+
const cell = sheet.getRow(rowNumber).getCell(i);
154+
applyCellStyle(cell, headerStyle);
155+
}
156+
}
157+
142158
/**
143159
* 데이터 행들에 스타일을 적용
144160
* @param {Object} sheet - ExcelJS 워크시트 객체
@@ -158,6 +174,26 @@ function applyBodyStyle(sheet, columns, dataRowCount, bodyStyle) {
158174
}
159175
}
160176

177+
/**
178+
* 지정된 시작 행부터 데이터 행들에 스타일을 적용
179+
* @param {Object} sheet - ExcelJS 워크시트 객체
180+
* @param {Array} columns - 컬럼 배열
181+
* @param {number} dataRowCount - 데이터 행 수
182+
* @param {Object} bodyStyle - 데이터 스타일 객체
183+
* @param {number} startRow - 데이터 시작 행 번호
184+
*/
185+
function applyBodyStyleAtRow(sheet, columns, dataRowCount, bodyStyle, startRow) {
186+
if (!bodyStyle || !sheet || !columns || dataRowCount <= 0) return;
187+
188+
for (let r = 0; r < dataRowCount; r++) {
189+
const row = sheet.getRow(startRow + r);
190+
for (let i = 1; i <= columns.length; i++) {
191+
const cell = row.getCell(i);
192+
applyCellStyle(cell, bodyStyle);
193+
}
194+
}
195+
}
196+
161197
/**
162198
* 컬럼 너비를 자동으로 계산
163199
* @param {Array} columns - 컬럼명 배열
@@ -194,7 +230,7 @@ function calculateColumnWidths(columns, data, colwidths = { min: 10, max: 30 })
194230
* @param {Object} excelStyle.header - 헤더 스타일
195231
* @param {Object} excelStyle.body - 데이터 스타일
196232
*/
197-
function applySheetStyle(sheet, data, excelStyle) {
233+
function applySheetStyle(sheet, data, excelStyle, startRow = 1) {
198234
if (!sheet || !data || data.length === 0) return;
199235

200236
const columns = Object.keys(data[0]);
@@ -217,17 +253,28 @@ function applySheetStyle(sheet, data, excelStyle) {
217253
sheet.columns = columns.map(key => ({ header: key, key }));
218254
}
219255

220-
// 데이터 추가
221-
sheet.addRows(data);
256+
// 헤더 행 추가 (startRow 위치에)
257+
const headerRow = sheet.getRow(startRow);
258+
columns.forEach((col, index) => {
259+
headerRow.getCell(index + 1).value = col;
260+
});
261+
262+
// 데이터 행 추가 (startRow + 1부터)
263+
data.forEach((row, rowIndex) => {
264+
const dataRow = sheet.getRow(startRow + 1 + rowIndex);
265+
columns.forEach((col, colIndex) => {
266+
dataRow.getCell(colIndex + 1).value = row[col];
267+
});
268+
});
222269

223-
// 헤더 스타일 적용
270+
// 헤더 스타일 적용 (startRow에 적용)
224271
if (excelStyle.header) {
225-
applyHeaderStyle(sheet, columns, excelStyle.header);
272+
applyHeaderStyleAtRow(sheet, columns, excelStyle.header, startRow);
226273
}
227274

228-
// 데이터 스타일 적용
275+
// 데이터 스타일 적용 (startRow + 1부터)
229276
if (excelStyle.body) {
230-
applyBodyStyle(sheet, columns, data.length, excelStyle.body);
277+
applyBodyStyleAtRow(sheet, columns, data.length, excelStyle.body, startRow + 1);
231278
}
232279
}
233280

src/index.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,31 @@ async function main() {
388388
}
389389

390390
if (recordCount > 0) {
391-
// 헬퍼 함수를 사용하여 시트에 데이터와 스타일 적용
392-
excelStyleHelper.applySheetStyle(sheet, result.recordset, excelStyle);
391+
// 데이터와 스타일 적용 (1행부터 시작)
392+
excelStyleHelper.applySheetStyle(sheet, result.recordset, excelStyle, 1);
393+
394+
// 데이터 추가 후 맨 앞에 DB 정보 행 삽입
395+
sheet.spliceRows(1, 0, [`📊 출처: ${sheetDbKey} DB`]);
396+
sheet.spliceRows(2, 0, []); // 빈 행 추가
397+
398+
// DB 정보 셀 스타일링
399+
const dbCell = sheet.getCell('A1');
400+
dbCell.font = { bold: true, size: 11, color: { argb: 'FFFFFF' } };
401+
dbCell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: '366092' } };
402+
403+
console.log(`\t[DB정보] ${sheetDbKey} DB 출처 표시 완료`);
404+
} else {
405+
// 데이터가 없는 경우
406+
sheet.addRow([`📊 출처: ${sheetDbKey} DB`]);
407+
sheet.addRow([]);
408+
sheet.addRow(['데이터가 없습니다.']);
409+
410+
// 스타일링
411+
sheet.getCell('A1').font = { bold: true, size: 11, color: { argb: 'FFFFFF' } };
412+
sheet.getCell('A1').fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: '366092' } };
413+
sheet.getCell('A3').font = { italic: true, color: { argb: '999999' } };
414+
415+
console.log(`\t[DB정보] ${sheetDbKey} DB 출처 표시 완료 (데이터 없음)`);
393416
}
394417
console.log(`\t---> ${recordCount} rows were selected `);
395418
} catch (error) {

0 commit comments

Comments
 (0)