1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
|
import * as ExcelJS from 'exceljs';
import { saveAs } from "file-saver";
/**
* 기술영업 벤더 가능 아이템 Import를 위한 Excel 템플릿 파일 생성 및 다운로드 (새로운 스키마 버전)
*/
export async function exportTechVendorPossibleItemsTemplate() {
// 워크북 생성
const workbook = new ExcelJS.Workbook();
workbook.creator = 'Tech Vendor Possible Items Management System';
workbook.created = new Date();
// 워크시트 생성
const worksheet = workbook.addWorksheet('기술영업 벤더 가능 아이템');
// 컬럼 헤더 정의 및 스타일 적용 (새로운 스키마에 맞춰)
worksheet.columns = [
{ header: '벤더이메일 (필수)', key: 'vendorEmail', width: 30 },
{ header: '아이템코드 (필수)', key: 'itemCode', width: 20 },
{ header: '공종 (선택)', key: 'workType', width: 15 },
{ header: '선종 (선택)', key: 'shipTypes', width: 20 },
{ header: '아이템리스트 (선택)', key: 'itemList', width: 35 },
{ header: '서브아이템리스트 (선택)', key: 'subItemList', width: 35 },
{ header: '벤더코드 (호환성)', key: 'vendorCode', width: 15 },
];
// 헤더 스타일 적용
const headerRow = worksheet.getRow(1);
headerRow.eachCell((cell) => {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFE6F3FF' }
};
cell.font = {
bold: true,
color: { argb: 'FF1F4E79' }
};
cell.border = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
};
cell.alignment = {
vertical: 'middle',
horizontal: 'center'
};
});
// 샘플 데이터 추가 (새로운 스키마에 맞춰)
const sampleData = [
{
vendorEmail: 'vendor1@example.com',
itemCode: 'ITEM001',
workType: '용접',
shipTypes: '컨테이너선',
itemList: '선체 용접 작업',
subItemList: '외판 용접, 내부 구조 용접',
vendorCode: 'V001'
},
{
vendorEmail: 'vendor2@example.com',
itemCode: 'ITEM002',
workType: '도장',
shipTypes: '벌크선',
itemList: '선체 도장 작업',
subItemList: '프라이머, 탑코트',
vendorCode: ''
},
{
vendorEmail: 'vendor3@example.com',
itemCode: 'ITEM003',
workType: '기계',
shipTypes: '탱커',
itemList: '기계 설비 설치',
subItemList: '엔진, 펌프, 배관',
vendorCode: ''
},
{
vendorEmail: 'vendor1@example.com',
itemCode: 'ITEM004',
workType: '용접',
shipTypes: '컨테이너선, 벌크선',
itemList: '특수 용접 작업',
subItemList: '',
vendorCode: 'V001'
},
{
vendorEmail: 'vendor4@example.com',
itemCode: 'ITEM005',
workType: '',
shipTypes: '',
itemList: '',
subItemList: '',
vendorCode: 'V004'
},
];
sampleData.forEach((data) => {
const row = worksheet.addRow(data);
row.eachCell((cell, colNumber) => {
cell.border = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
};
cell.alignment = {
vertical: 'middle',
horizontal: 'left'
};
// 긴 텍스트 필드는 줄바꿈 허용
if (colNumber >= 5 && colNumber <= 6) { // itemList, subItemList
cell.alignment = {
vertical: 'top',
horizontal: 'left',
wrapText: true
};
}
});
});
// 안내사항 워크시트 생성 (새로운 스키마에 맞춰)
const guideSheet = workbook.addWorksheet('사용 가이드');
const guideData = [
['기술영업 벤더 가능 아이템 Import 템플릿 (새로운 스키마)', ''],
['', ''],
['📋 새로운 스키마 특징:', ''],
['- 더욱 구체적인 아이템 정보 관리', ''],
['- 공종과 선종으로 세분화된 분류', ''],
['- 아이템 상세 설명 및 서브 아이템 정보', ''],
['- 중복 아이템도 공종/선종이 다르면 별도 관리', ''],
['', ''],
['📌 필수 입력 필드:', ''],
['1. 벤더이메일: 시스템에 등록된 벤더의 이메일 주소', ''],
[' 예: vendor@company.com', ''],
['2. 아이템코드: 처리할 아이템의 고유 코드', ''],
[' 예: ITEM001, WELD_001, PAINT_002', ''],
['', ''],
['📝 선택 입력 필드:', ''],
['3. 공종: 작업 유형 분류', ''],
[' 예: 용접, 도장, 기계, 전기, 배관 등', ''],
['4. 선종: 적용 가능한 선박 유형', ''],
[' 예: 컨테이너선, 벌크선, 탱커, LNG선 등', ''],
[' - 여러 선종은 콤마로 구분: "컨테이너선, 벌크선"', ''],
['5. 아이템리스트: 아이템에 대한 상세 설명', ''],
[' 예: "선체 용접 작업", "외판 도장 및 마감"', ''],
['6. 서브아이템리스트: 세부 작업 항목들', ''],
[' 예: "외판 용접, 내부 구조 용접, 배관 용접"', ''],
['7. 벤더코드: 기존 호환성을 위한 선택 필드', ''],
['', ''],
['🔍 중복 처리 로직:', ''],
['- 동일한 벤더 + 아이템코드 + 공종 + 선종 = 중복으로 처리', ''],
['- 아이템코드가 같아도 공종이나 선종이 다르면 별도 항목', ''],
['- 예: ITEM001 + 용접 + 컨테이너선 ≠ ITEM001 + 도장 + 컨테이너선', ''],
['', ''],
['💡 사용 방법:', ''],
['1. "기술영업 벤더 가능 아이템" 시트에 데이터를 입력하세요', ''],
['2. 필수 필드(벤더이메일, 아이템코드)는 반드시 입력', ''],
['3. 선택 필드는 필요에 따라 입력 (빈 칸으로 두어도 됨)', ''],
['4. 한 벤더가 여러 아이템을 담당할 수 있습니다 (1:N 관계)', ''],
['5. 한 아이템에 여러 벤더를 배정할 수 있습니다 (N:M 관계)', ''],
['6. 파일 저장 후 시스템에서 업로드하세요', ''],
['', ''],
['⚠️ 주의사항:', ''],
['- 벤더이메일은 시스템에 이미 등록된 이메일이어야 함', ''],
['- 이메일 형식 확인: @를 포함한 올바른 이메일 형식', ''],
['- 아이템코드는 특수문자나 공백 주의', ''],
['- 긴 텍스트 필드(아이템리스트, 서브아이템리스트)는 줄바꿈 가능', ''],
['- 오류가 있는 항목은 별도 파일로 다운로드됩니다', ''],
['', ''],
['📊 데이터 예시:', ''],
['벤더이메일: welding@company.com', ''],
['아이템코드: WELD_HULL_001', ''],
['공종: 용접', ''],
['선종: 컨테이너선, 벌크선', ''],
['아이템리스트: 선체 구조 용접 작업', ''],
['서브아이템리스트: 외판 용접, 격벽 용접, 갑판 용접', ''],
['', ''],
['📞 문의사항이 있으시면 시스템 관리자에게 연락하세요.', ''],
];
guideData.forEach((rowData, index) => {
const row = guideSheet.addRow(rowData);
if (index === 0) {
// 제목 스타일
row.getCell(1).font = { bold: true, size: 16, color: { argb: 'FF1F4E79' } };
} else if (rowData[0]?.includes('📋') || rowData[0]?.includes('📌') || rowData[0]?.includes('📝') || rowData[0]?.includes('🔍') || rowData[0]?.includes('💡') || rowData[0]?.includes('⚠️') || rowData[0]?.includes('📊')) {
// 섹션 제목 스타일 (이모지 포함)
row.getCell(1).font = { bold: true, color: { argb: 'FF1F4E79' } };
} else if (rowData[0]?.includes(':')) {
// 일반 제목 스타일
row.getCell(1).font = { bold: true, color: { argb: 'FF1F4E79' } };
} else if (rowData[0]?.includes('-') || rowData[0]?.includes('•') || rowData[0]?.includes('예:')) {
// 리스트 아이템 스타일
row.getCell(1).font = { color: { argb: 'FF333333' } };
}
});
guideSheet.getColumn(1).width = 80;
guideSheet.getColumn(2).width = 20;
// 파일 생성 및 다운로드
try {
const buffer = await workbook.xlsx.writeBuffer();
const blob = new Blob([buffer], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
});
const fileName = `기술영업_벤더_가능_아이템_템플릿_${new Date().toISOString().split('T')[0]}.xlsx`;
saveAs(blob, fileName);
return { success: true };
} catch (error) {
console.error("Excel 템플릿 생성 중 오류:", error);
return {
success: false,
error: error instanceof Error ? error.message : "템플릿 생성 중 오류가 발생했습니다."
};
}
}
|