@fileverse-dev/formulajs 4.4.12-mod-3 → 4.4.12-mod-3-patch-1
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/lib/browser/formula.js +113 -58
- package/lib/browser/formula.min.js +2 -2
- package/lib/browser/formula.min.js.map +1 -1
- package/lib/cjs/index.cjs +88 -20
- package/lib/esm/index.mjs +88 -20
- package/package.json +1 -1
- package/types/cjs/index.d.cts +1 -1
- package/types/esm/index.d.mts +1 -1
package/lib/cjs/index.cjs
CHANGED
|
@@ -1271,6 +1271,7 @@ function ROWS(array) {
|
|
|
1271
1271
|
* @returns
|
|
1272
1272
|
*/
|
|
1273
1273
|
function SORT(array, sort_index = 1, sort_order = 1, by_col = false) {
|
|
1274
|
+
// Accept multiple sort keys like Google Sheets: SORT(range, sort_column, is_ascending, [sort_column2, is_ascending2, ...])
|
|
1274
1275
|
if (!array || !Array.isArray(array)) {
|
|
1275
1276
|
return na
|
|
1276
1277
|
}
|
|
@@ -1279,37 +1280,104 @@ function SORT(array, sort_index = 1, sort_order = 1, by_col = false) {
|
|
|
1279
1280
|
return 0
|
|
1280
1281
|
}
|
|
1281
1282
|
|
|
1282
|
-
|
|
1283
|
-
if (
|
|
1284
|
-
return
|
|
1283
|
+
by_col = parseBool(by_col);
|
|
1284
|
+
if (typeof by_col !== 'boolean') {
|
|
1285
|
+
return name
|
|
1285
1286
|
}
|
|
1286
1287
|
|
|
1287
|
-
|
|
1288
|
-
|
|
1288
|
+
// Collect sort keys (index and order). First key comes from sort_index/sort_order.
|
|
1289
|
+
const sortKeys = [];
|
|
1290
|
+
|
|
1291
|
+
const normalizeOrder = (o) => {
|
|
1292
|
+
// Try boolean first (TRUE -> ascending)
|
|
1293
|
+
const b = parseBool(o);
|
|
1294
|
+
if (typeof b === 'boolean') {
|
|
1295
|
+
return b ? 1 : -1
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
const n = parseNumber(o);
|
|
1299
|
+
if (n === 1 || n === -1) {
|
|
1300
|
+
return n
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
return null
|
|
1304
|
+
};
|
|
1305
|
+
|
|
1306
|
+
const firstIndex = parseNumber(sort_index);
|
|
1307
|
+
if (!firstIndex || firstIndex < 1) {
|
|
1289
1308
|
return value
|
|
1290
1309
|
}
|
|
1291
1310
|
|
|
1292
|
-
|
|
1293
|
-
if (
|
|
1294
|
-
return
|
|
1311
|
+
const firstOrder = normalizeOrder(sort_order);
|
|
1312
|
+
if (firstOrder === null) {
|
|
1313
|
+
return value
|
|
1295
1314
|
}
|
|
1296
1315
|
|
|
1297
|
-
|
|
1298
|
-
arr.sort((a, b) => {
|
|
1299
|
-
a = parseString(a[sort_index - 1]);
|
|
1300
|
-
b = parseString(b[sort_index - 1]);
|
|
1316
|
+
sortKeys.push({ index: firstIndex, order: firstOrder });
|
|
1301
1317
|
|
|
1302
|
-
|
|
1303
|
-
|
|
1318
|
+
// Additional args may contain more sort_index/sort_order pairs
|
|
1319
|
+
if (arguments.length > 4) {
|
|
1320
|
+
// arguments: 0=array,1=sort_index,2=sort_order,3=by_col,4=nextIndex,5=nextOrder,...
|
|
1321
|
+
for (let i = 4; i < arguments.length; i += 2) {
|
|
1322
|
+
const idx = parseNumber(arguments[i]);
|
|
1323
|
+
if (!idx || idx < 1) {
|
|
1324
|
+
return value
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
const ordArg = i + 1 < arguments.length ? arguments[i + 1] : 1;
|
|
1328
|
+
const ord = normalizeOrder(ordArg);
|
|
1329
|
+
if (ord === null) {
|
|
1330
|
+
return value
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
sortKeys.push({ index: idx, order: ord });
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1304
1336
|
|
|
1305
1337
|
const matrix = fillMatrix(array);
|
|
1306
|
-
const
|
|
1338
|
+
const working = by_col ? transpose(matrix) : matrix;
|
|
1339
|
+
|
|
1340
|
+
// Validate that all sort indexes are within column bounds
|
|
1341
|
+
const numCols = working[0] ? working[0].length : 0;
|
|
1342
|
+
for (const k of sortKeys) {
|
|
1343
|
+
if (k.index < 1 || k.index > numCols) {
|
|
1344
|
+
return value
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
const parseForCompare = (val) => {
|
|
1349
|
+
// Preserve numbers when possible
|
|
1350
|
+
if (typeof val === 'number') return val
|
|
1351
|
+
const num = parseNumber(val);
|
|
1352
|
+
if (typeof num === 'number' && !Number.isNaN(num)) return num
|
|
1353
|
+
return parseString(val)
|
|
1354
|
+
};
|
|
1355
|
+
|
|
1356
|
+
const comparator = (aRow, bRow) => {
|
|
1357
|
+
for (const k of sortKeys) {
|
|
1358
|
+
const aVal = parseForCompare(aRow[k.index - 1]);
|
|
1359
|
+
const bVal = parseForCompare(bRow[k.index - 1]);
|
|
1360
|
+
|
|
1361
|
+
if (aVal === bVal) continue
|
|
1362
|
+
|
|
1363
|
+
// Numeric comparison if both are numbers
|
|
1364
|
+
if (typeof aVal === 'number' && typeof bVal === 'number') {
|
|
1365
|
+
return (aVal < bVal ? -1 : 1) * k.order
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
// String comparison
|
|
1369
|
+
const aStr = String(aVal).toLowerCase();
|
|
1370
|
+
const bStr = String(bVal).toLowerCase();
|
|
1371
|
+
return aStr.localeCompare(bStr) * k.order
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
return 0
|
|
1375
|
+
};
|
|
1376
|
+
|
|
1377
|
+
// Sort in-place and return
|
|
1378
|
+
working.sort(comparator);
|
|
1307
1379
|
|
|
1308
|
-
return
|
|
1309
|
-
? by_col
|
|
1310
|
-
? transpose(sortArray(result))
|
|
1311
|
-
: sortArray(result)
|
|
1312
|
-
: value
|
|
1380
|
+
return by_col ? transpose(working) : working
|
|
1313
1381
|
}
|
|
1314
1382
|
|
|
1315
1383
|
/**
|
package/lib/esm/index.mjs
CHANGED
|
@@ -1269,6 +1269,7 @@ function ROWS(array) {
|
|
|
1269
1269
|
* @returns
|
|
1270
1270
|
*/
|
|
1271
1271
|
function SORT(array, sort_index = 1, sort_order = 1, by_col = false) {
|
|
1272
|
+
// Accept multiple sort keys like Google Sheets: SORT(range, sort_column, is_ascending, [sort_column2, is_ascending2, ...])
|
|
1272
1273
|
if (!array || !Array.isArray(array)) {
|
|
1273
1274
|
return na
|
|
1274
1275
|
}
|
|
@@ -1277,37 +1278,104 @@ function SORT(array, sort_index = 1, sort_order = 1, by_col = false) {
|
|
|
1277
1278
|
return 0
|
|
1278
1279
|
}
|
|
1279
1280
|
|
|
1280
|
-
|
|
1281
|
-
if (
|
|
1282
|
-
return
|
|
1281
|
+
by_col = parseBool(by_col);
|
|
1282
|
+
if (typeof by_col !== 'boolean') {
|
|
1283
|
+
return name
|
|
1283
1284
|
}
|
|
1284
1285
|
|
|
1285
|
-
|
|
1286
|
-
|
|
1286
|
+
// Collect sort keys (index and order). First key comes from sort_index/sort_order.
|
|
1287
|
+
const sortKeys = [];
|
|
1288
|
+
|
|
1289
|
+
const normalizeOrder = (o) => {
|
|
1290
|
+
// Try boolean first (TRUE -> ascending)
|
|
1291
|
+
const b = parseBool(o);
|
|
1292
|
+
if (typeof b === 'boolean') {
|
|
1293
|
+
return b ? 1 : -1
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
const n = parseNumber(o);
|
|
1297
|
+
if (n === 1 || n === -1) {
|
|
1298
|
+
return n
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
return null
|
|
1302
|
+
};
|
|
1303
|
+
|
|
1304
|
+
const firstIndex = parseNumber(sort_index);
|
|
1305
|
+
if (!firstIndex || firstIndex < 1) {
|
|
1287
1306
|
return value
|
|
1288
1307
|
}
|
|
1289
1308
|
|
|
1290
|
-
|
|
1291
|
-
if (
|
|
1292
|
-
return
|
|
1309
|
+
const firstOrder = normalizeOrder(sort_order);
|
|
1310
|
+
if (firstOrder === null) {
|
|
1311
|
+
return value
|
|
1293
1312
|
}
|
|
1294
1313
|
|
|
1295
|
-
|
|
1296
|
-
arr.sort((a, b) => {
|
|
1297
|
-
a = parseString(a[sort_index - 1]);
|
|
1298
|
-
b = parseString(b[sort_index - 1]);
|
|
1314
|
+
sortKeys.push({ index: firstIndex, order: firstOrder });
|
|
1299
1315
|
|
|
1300
|
-
|
|
1301
|
-
|
|
1316
|
+
// Additional args may contain more sort_index/sort_order pairs
|
|
1317
|
+
if (arguments.length > 4) {
|
|
1318
|
+
// arguments: 0=array,1=sort_index,2=sort_order,3=by_col,4=nextIndex,5=nextOrder,...
|
|
1319
|
+
for (let i = 4; i < arguments.length; i += 2) {
|
|
1320
|
+
const idx = parseNumber(arguments[i]);
|
|
1321
|
+
if (!idx || idx < 1) {
|
|
1322
|
+
return value
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
const ordArg = i + 1 < arguments.length ? arguments[i + 1] : 1;
|
|
1326
|
+
const ord = normalizeOrder(ordArg);
|
|
1327
|
+
if (ord === null) {
|
|
1328
|
+
return value
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
sortKeys.push({ index: idx, order: ord });
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1302
1334
|
|
|
1303
1335
|
const matrix = fillMatrix(array);
|
|
1304
|
-
const
|
|
1336
|
+
const working = by_col ? transpose(matrix) : matrix;
|
|
1337
|
+
|
|
1338
|
+
// Validate that all sort indexes are within column bounds
|
|
1339
|
+
const numCols = working[0] ? working[0].length : 0;
|
|
1340
|
+
for (const k of sortKeys) {
|
|
1341
|
+
if (k.index < 1 || k.index > numCols) {
|
|
1342
|
+
return value
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
const parseForCompare = (val) => {
|
|
1347
|
+
// Preserve numbers when possible
|
|
1348
|
+
if (typeof val === 'number') return val
|
|
1349
|
+
const num = parseNumber(val);
|
|
1350
|
+
if (typeof num === 'number' && !Number.isNaN(num)) return num
|
|
1351
|
+
return parseString(val)
|
|
1352
|
+
};
|
|
1353
|
+
|
|
1354
|
+
const comparator = (aRow, bRow) => {
|
|
1355
|
+
for (const k of sortKeys) {
|
|
1356
|
+
const aVal = parseForCompare(aRow[k.index - 1]);
|
|
1357
|
+
const bVal = parseForCompare(bRow[k.index - 1]);
|
|
1358
|
+
|
|
1359
|
+
if (aVal === bVal) continue
|
|
1360
|
+
|
|
1361
|
+
// Numeric comparison if both are numbers
|
|
1362
|
+
if (typeof aVal === 'number' && typeof bVal === 'number') {
|
|
1363
|
+
return (aVal < bVal ? -1 : 1) * k.order
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
// String comparison
|
|
1367
|
+
const aStr = String(aVal).toLowerCase();
|
|
1368
|
+
const bStr = String(bVal).toLowerCase();
|
|
1369
|
+
return aStr.localeCompare(bStr) * k.order
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
return 0
|
|
1373
|
+
};
|
|
1374
|
+
|
|
1375
|
+
// Sort in-place and return
|
|
1376
|
+
working.sort(comparator);
|
|
1305
1377
|
|
|
1306
|
-
return
|
|
1307
|
-
? by_col
|
|
1308
|
-
? transpose(sortArray(result))
|
|
1309
|
-
: sortArray(result)
|
|
1310
|
-
: value
|
|
1378
|
+
return by_col ? transpose(working) : working
|
|
1311
1379
|
}
|
|
1312
1380
|
|
|
1313
1381
|
/**
|
package/package.json
CHANGED
package/types/cjs/index.d.cts
CHANGED
|
@@ -3788,7 +3788,7 @@ export function SMARTCONTRACT(...args: any[]): Promise<any>;
|
|
|
3788
3788
|
* @param {*} by_col Optional. A logical value indicating the desired sort direction; FALSE to sort by row (default), TRUE to sort by column
|
|
3789
3789
|
* @returns
|
|
3790
3790
|
*/
|
|
3791
|
-
export function SORT(array: any, sort_index?: any, sort_order?: any, by_col?: any): any;
|
|
3791
|
+
export function SORT(array: any, sort_index?: any, sort_order?: any, by_col?: any, ...args: any[]): any;
|
|
3792
3792
|
/**
|
|
3793
3793
|
* Returns a positive square root.
|
|
3794
3794
|
*
|
package/types/esm/index.d.mts
CHANGED
|
@@ -3788,7 +3788,7 @@ export function SMARTCONTRACT(...args: any[]): Promise<any>;
|
|
|
3788
3788
|
* @param {*} by_col Optional. A logical value indicating the desired sort direction; FALSE to sort by row (default), TRUE to sort by column
|
|
3789
3789
|
* @returns
|
|
3790
3790
|
*/
|
|
3791
|
-
export function SORT(array: any, sort_index?: any, sort_order?: any, by_col?: any): any;
|
|
3791
|
+
export function SORT(array: any, sort_index?: any, sort_order?: any, by_col?: any, ...args: any[]): any;
|
|
3792
3792
|
/**
|
|
3793
3793
|
* Returns a positive square root.
|
|
3794
3794
|
*
|