@gingkoo/base-server 0.0.4-alpha.28 → 0.0.4-alpha.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/backend/utils/excel.js +77 -1
- package/package.json +2 -2
package/backend/utils/excel.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
const ExcelJS = require('exceljs');
|
|
3
3
|
const { sse, bgTaskEnum } = require('../common/sse');
|
|
4
|
-
|
|
5
4
|
const fillHeader = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'ff4576B5' } };
|
|
6
5
|
const fontHeader = {
|
|
7
6
|
name: 'Arial Black',
|
|
@@ -336,6 +335,70 @@ function getSheetData(worksheet, mapping, linkColumn, linkWorksheetMap, linkMapp
|
|
|
336
335
|
return data;
|
|
337
336
|
}
|
|
338
337
|
|
|
338
|
+
/**
|
|
339
|
+
* 手动解析 VLOOKUP 公式(简化版,仅支持基本场景)
|
|
340
|
+
* @param {string} formula - 如 "=VLOOKUP($C26,'data mart'!$B:$E,2,0)"
|
|
341
|
+
* @param {ExcelJS.worksheet} worksheet - ExcelJS 当前工作簿对象
|
|
342
|
+
* @param {ExcelJS.Workbook} workbook - ExcelJS 工作簿对象
|
|
343
|
+
* @returns {string|number|null} 查找结果
|
|
344
|
+
*/
|
|
345
|
+
function manualVLOOKUP(formula, worksheet, workbook) {
|
|
346
|
+
// 1. 提取 VLOOKUP 参数
|
|
347
|
+
// VLOOKUP(C3,catalog!E:I,4,FALSE) 支持
|
|
348
|
+
// VLOOKUP($C5,'data mart'!$B:$F,5,0) 支持
|
|
349
|
+
// VLOOKUP(E2, A2:C4, 3, 0) 不支持当前表的
|
|
350
|
+
|
|
351
|
+
const match = formula.match(/VLOOKUP\((.+),(.+)!(.+):(.+),(\d+),(.+)\)/i);
|
|
352
|
+
if (!match) {
|
|
353
|
+
console.error('无法解析 VLOOKUP 公式:', formula);
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
let [_, lookupValue, sheetName, start, end, colIndex, matchType] = match;
|
|
358
|
+
|
|
359
|
+
// 2. 获取查找值(如 $C26 的实际值)
|
|
360
|
+
const lookupCell = worksheet.getCell(lookupValue);
|
|
361
|
+
const searchKey = lookupCell.value?.result ?? lookupCell.value;
|
|
362
|
+
|
|
363
|
+
// 3. 获取目标工作表和数据范围(如 'data mart'!B:E)
|
|
364
|
+
|
|
365
|
+
if (/'.+'/.test(sheetName)) {
|
|
366
|
+
sheetName = sheetName.slice(1, -1);
|
|
367
|
+
}
|
|
368
|
+
const targetSheet = workbook.getWorksheet(sheetName);
|
|
369
|
+
|
|
370
|
+
if (!targetSheet) {
|
|
371
|
+
console.error('工作表不存在:', sheetName);
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// 4. 解析范围(如 B:E → { startCol: 2, endCol: 5 })
|
|
376
|
+
if (start.startsWith('$')) {
|
|
377
|
+
start = start.slice(1);
|
|
378
|
+
}
|
|
379
|
+
if (end.startsWith('$')) {
|
|
380
|
+
end = end.slice(1);
|
|
381
|
+
}
|
|
382
|
+
const startCol = columnToNumber(start) + 1; // B → 2
|
|
383
|
+
const endCol = columnToNumber(end) + 1; // E → 5
|
|
384
|
+
|
|
385
|
+
// 5. 遍历目标范围,查找匹配行
|
|
386
|
+
let result = null;
|
|
387
|
+
targetSheet.eachRow((row, rowNum) => {
|
|
388
|
+
const keyCell = row.getCell(startCol); // 查找列(如 B 列 2)
|
|
389
|
+
const keyValue = keyCell.value?.result ?? keyCell.value;
|
|
390
|
+
|
|
391
|
+
if (keyValue === searchKey) {
|
|
392
|
+
// 找到匹配行,返回指定列的值(如 colIndex=2 → C 列)
|
|
393
|
+
const resultCell = row.getCell(startCol + parseInt(colIndex) - 1);
|
|
394
|
+
result = resultCell.value?.result ?? resultCell.value;
|
|
395
|
+
return false; // 停止遍历
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
return result;
|
|
400
|
+
}
|
|
401
|
+
|
|
339
402
|
/**
|
|
340
403
|
* 导入多 sheet 他只负责拿数据 给业务那边处理
|
|
341
404
|
* @param {string} filePath
|
|
@@ -365,6 +428,19 @@ const _excelImportMultisheet2 = async (filePath = '') => {
|
|
|
365
428
|
if (rowNumber == 1) {
|
|
366
429
|
sheetInfo.header[colNumber - 1] = colValue;
|
|
367
430
|
} else {
|
|
431
|
+
if (cell.formula && cell.formula.includes('VLOOKUP')) {
|
|
432
|
+
colValue = manualVLOOKUP(cell.formula, worksheet, workbook);
|
|
433
|
+
if (colValue === null) {
|
|
434
|
+
colValue = cell.value?.result ?? cell.value; // 降级使用原始值
|
|
435
|
+
if (typeof colValue === 'number') {
|
|
436
|
+
colValue = colValue.toString();
|
|
437
|
+
}
|
|
438
|
+
if (!colValue) {
|
|
439
|
+
colValue = '';
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
368
444
|
rowData[colNumber - 1] = colValue;
|
|
369
445
|
}
|
|
370
446
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gingkoo/base-server",
|
|
3
|
-
"version": "0.0.4-alpha.
|
|
3
|
+
"version": "0.0.4-alpha.29",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "app.js",
|
|
6
6
|
"scripts": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"date-fns": "^2.29.3",
|
|
31
31
|
"dayjs": "^1.11.6",
|
|
32
32
|
"express": "^4.19.1",
|
|
33
|
-
"exceljs": "^4.
|
|
33
|
+
"exceljs": "^4.4.0",
|
|
34
34
|
"express-xml-bodyparser": "^0.3.0",
|
|
35
35
|
"getavataaars": "^1.0.0",
|
|
36
36
|
"http-proxy-middleware": "^2.0.1",
|