From 9386c6bbd09361d1ad49733095e5d1dfb48becbf Mon Sep 17 00:00:00 2001 From: wpxp123456 <2677556700@qq.com> Date: Tue, 13 Aug 2024 10:55:26 +0800 Subject: [PATCH] feat(formula): add some engineering function (#2893) Co-authored-by: wpxp123456 --- .../engine-formula/src/basics/engineering.ts | 470 +++++++++++++++++ .../besseli/__tests__/index.spec.ts | 107 ++++ .../functions/engineering/besseli/index.ts | 60 +++ .../besselj/__tests__/index.spec.ts | 107 ++++ .../functions/engineering/besselj/index.ts | 60 +++ .../besselk/__tests__/index.spec.ts | 107 ++++ .../functions/engineering/besselk/index.ts | 60 +++ .../bessely/__tests__/index.spec.ts | 107 ++++ .../functions/engineering/bessely/index.ts | 60 +++ .../bin2dec/__tests__/index.spec.ts | 83 +++ .../functions/engineering/bin2dec/index.ts | 54 ++ .../bin2hex/__tests__/index.spec.ts | 107 ++++ .../functions/engineering/bin2hex/index.ts | 89 ++++ .../bin2oct/__tests__/index.spec.ts | 107 ++++ .../functions/engineering/bin2oct/index.ts | 89 ++++ .../bitand/__tests__/index.spec.ts | 93 ++++ .../src/functions/engineering/bitand/index.ts | 100 ++++ .../bitlshift/__tests__/index.spec.ts | 93 ++++ .../functions/engineering/bitlshift/index.ts | 106 ++++ .../engineering/bitor/__tests__/index.spec.ts | 93 ++++ .../src/functions/engineering/bitor/index.ts | 100 ++++ .../bitrshift/__tests__/index.spec.ts | 93 ++++ .../functions/engineering/bitrshift/index.ts | 106 ++++ .../bitxor/__tests__/index.spec.ts | 93 ++++ .../src/functions/engineering/bitxor/index.ts | 100 ++++ .../complex/__tests__/index.spec.ts | 105 ++++ .../functions/engineering/complex/index.ts | 72 +++ .../convert/__tests__/index.spec.ts | 105 ++++ .../functions/engineering/convert/index.ts | 479 ++++++++++++++++++ .../dec2bin/__tests__/index.spec.ts | 107 ++++ .../functions/engineering/dec2bin/index.ts | 95 ++++ .../dec2hex/__tests__/index.spec.ts | 107 ++++ .../functions/engineering/dec2hex/index.ts | 93 ++++ .../dec2oct/__tests__/index.spec.ts | 107 ++++ .../functions/engineering/dec2oct/index.ts | 93 ++++ .../engineering/delta/__tests__/index.spec.ts | 90 ++++ .../src/functions/engineering/delta/index.ts | 50 ++ .../erf-precise/__tests__/index.spec.ts | 83 +++ .../engineering/erf-precise/index.ts | 47 ++ .../engineering/erf/__tests__/index.spec.ts | 87 ++++ .../src/functions/engineering/erf/index.ts | 68 +++ .../erfc-precise/__tests__/index.spec.ts | 83 +++ .../engineering/erfc-precise/index.ts | 47 ++ .../engineering/erfc/__tests__/index.spec.ts | 83 +++ .../src/functions/engineering/erfc/index.ts | 47 ++ .../src/functions/engineering/function-map.ts | 61 ++- .../hex2bin/__tests__/index.spec.ts | 107 ++++ .../functions/engineering/hex2bin/index.ts | 102 ++++ .../hex2dec/__tests__/index.spec.ts | 83 +++ .../functions/engineering/hex2dec/index.ts | 52 ++ .../hex2oct/__tests__/index.spec.ts | 107 ++++ .../functions/engineering/hex2oct/index.ts | 97 ++++ .../oct2bin/__tests__/index.spec.ts | 107 ++++ .../functions/engineering/oct2bin/index.ts | 102 ++++ .../oct2dec/__tests__/index.spec.ts | 83 +++ .../functions/engineering/oct2dec/index.ts | 52 ++ .../oct2hex/__tests__/index.spec.ts | 107 ++++ .../functions/engineering/oct2hex/index.ts | 92 ++++ .../src/functions/logical/function-map.ts | 2 + .../src/functions/logical/let/index.ts | 32 ++ .../src/functions/logical/makearray/index.ts | 7 +- .../src/functions/lookup/indirect/index.ts | 4 +- .../update-formula.controller.spec.ts | 2 - .../controllers/update-formula.controller.ts | 14 +- .../locale/function-list/engineering/en-US.ts | 108 ++-- .../locale/function-list/engineering/ja-JP.ts | 108 ++-- .../locale/function-list/engineering/vi-VN.ts | 258 ++-------- .../locale/function-list/engineering/zh-CN.ts | 108 ++-- .../locale/function-list/engineering/zh-TW.ts | 108 ++-- .../src/locale/function-list/logical/en-US.ts | 7 +- .../src/locale/function-list/logical/ja-JP.ts | 7 +- .../src/locale/function-list/logical/vi-VN.ts | 7 +- .../src/locale/function-list/logical/zh-CN.ts | 7 +- .../src/locale/function-list/logical/zh-TW.ts | 7 +- .../src/services/function-list/engineering.ts | 346 ++++++------- .../src/services/function-list/logical.ts | 33 +- 76 files changed, 6359 insertions(+), 650 deletions(-) create mode 100644 packages/engine-formula/src/basics/engineering.ts create mode 100644 packages/engine-formula/src/functions/engineering/besseli/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/besseli/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/besselj/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/besselj/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/besselk/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/besselk/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/bessely/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/bessely/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/bin2dec/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/bin2dec/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/bin2hex/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/bin2hex/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/bin2oct/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/bin2oct/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/bitand/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/bitand/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/bitlshift/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/bitlshift/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/bitor/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/bitor/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/bitrshift/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/bitrshift/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/bitxor/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/bitxor/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/complex/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/complex/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/convert/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/convert/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/dec2bin/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/dec2bin/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/dec2hex/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/dec2hex/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/dec2oct/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/dec2oct/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/delta/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/delta/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/erf-precise/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/erf-precise/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/erf/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/erf/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/erfc-precise/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/erfc-precise/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/erfc/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/erfc/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/hex2bin/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/hex2bin/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/hex2dec/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/hex2dec/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/hex2oct/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/hex2oct/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/oct2bin/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/oct2bin/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/oct2dec/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/oct2dec/index.ts create mode 100644 packages/engine-formula/src/functions/engineering/oct2hex/__tests__/index.spec.ts create mode 100644 packages/engine-formula/src/functions/engineering/oct2hex/index.ts create mode 100644 packages/engine-formula/src/functions/logical/let/index.ts diff --git a/packages/engine-formula/src/basics/engineering.ts b/packages/engine-formula/src/basics/engineering.ts new file mode 100644 index 00000000000..325b9987904 --- /dev/null +++ b/packages/engine-formula/src/basics/engineering.ts @@ -0,0 +1,470 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ArrayValueObject } from '../engine/value-object/array-value-object'; +import type { BaseValueObject } from '../engine/value-object/base-value-object'; +import { ErrorValueObject } from '../engine/value-object/base-value-object'; +import { ErrorType } from './error-type'; + +export function checkVariantsErrorIsArrayOrBoolean(...variants: BaseValueObject[]) { + for (let i = 0; i < variants.length; i++) { + let variant = variants[i]; + + if (variant.isArray()) { + const rowCount = (variant as ArrayValueObject).getRowCount(); + const columnCount = (variant as ArrayValueObject).getColumnCount(); + + if (rowCount > 1 || columnCount > 1) { + return { + isError: true, + errorObject: ErrorValueObject.create(ErrorType.VALUE), + }; + } + + variant = (variant as ArrayValueObject).get(0, 0) as BaseValueObject; + } + + if (variant.isError()) { + return { + isError: true, + errorObject: variant, + }; + } + + if (variant.isBoolean()) { + return { + isError: true, + errorObject: ErrorValueObject.create(ErrorType.VALUE), + }; + } + + variants[i] = variant; + } + + return { + isError: false, + variants, + }; +} + +// eslint-disable-next-line ts/no-namespace +export namespace BESSEL { + const W = 0.636619772; + + function _horner(arr: number[], v: number): number { + let z = 0; + + for (let i = 0; i < arr.length; ++i) { + z = v * z + arr[i]; + } + + return z; + } + + function _bessel_iter(x: number, n: number, f0: number, f1: number, sign: number): number { + if (n === 0) { + return f0; + } + + if (n === 1) { + return f1; + } + + const tdx = 2 / x; + let _f0 = f0; + let _f1 = f1; + let f2 = f1; + + for (let o = 1; o < n; ++o) { + f2 = _f1 * o * tdx + sign * _f0; + _f0 = _f1; + _f1 = f2; + } + + return f2; + } + + function _bessel_wrap(bessel0: Function, bessel1: Function, nonzero: number, sign: number) { + return function bessel(x: number, n: number) { + if (nonzero) { + if (x === 0) { + return nonzero === 1 ? -Infinity : Infinity; + } else if (x < 0) { + return Number.NaN; + } + } + + if (n === 0) { + return bessel0(x); + } + + if (n === 1) { + return bessel1(x); + } + + if (n < 0) { + return Number.NaN; + } + + const _n = n | 0; + + const b0 = bessel0(x); + const b1 = bessel1(x); + + return _bessel_iter(x, _n, b0, b1, sign); + }; + } + + export const besselj = (() => { + const b0_a1a = [-184.9052456, 77392.33017, -11214424.18, 651619640.7, -13362590354.0, 57568490574.0]; + const b0_a2a = [1.0, 267.8532712, 59272.64853, 9494680.718, 1029532985.0, 57568490411.0]; + const b0_a1b = [0.2093887211e-6, -0.2073370639e-5, 0.2734510407e-4, -0.1098628627e-2, 1.0]; + const b0_a2b = [-0.934935152e-7, 0.7621095161e-6, -0.6911147651e-5, 0.1430488765e-3, -0.1562499995e-1]; + + function bessel0(x: number): number { + let a = 0; + let a1 = 0; + let a2 = 0; + let y = x * x; + + if (x < 8) { + a1 = _horner(b0_a1a, y); + a2 = _horner(b0_a2a, y); + a = a1 / a2; + } else { + const xx = x - 0.785398164; + y = 64 / y; + a1 = _horner(b0_a1b, y); + a2 = _horner(b0_a2b, y); + a = Math.sqrt(W / x) * (Math.cos(xx) * a1 - Math.sin(xx) * a2 * 8 / x); + } + + return a; + } + + const b1_a1a = [-30.16036606, 15704.48260, -2972611.439, 242396853.1, -7895059235.0, 72362614232.0]; + const b1_a2a = [1.0, 376.9991397, 99447.43394, 18583304.74, 2300535178.0, 144725228442.0]; + const b1_a1b = [-0.240337019e-6, 0.2457520174e-5, -0.3516396496e-4, 0.183105e-2, 1.0]; + const b1_a2b = [0.105787412e-6, -0.88228987e-6, 0.8449199096e-5, -0.2002690873e-3, 0.04687499995]; + + function bessel1(x: number): number { + let a = 0; + let a1 = 0; + let a2 = 0; + let y = x * x; + const xx = Math.abs(x) - 2.356194491; + + if (Math.abs(x) < 8) { + a1 = x * _horner(b1_a1a, y); + a2 = _horner(b1_a2a, y); + a = a1 / a2; + } else { + y = 64 / y; + a1 = _horner(b1_a1b, y); + a2 = _horner(b1_a2b, y); + a = Math.sqrt(W / Math.abs(x)) * (Math.cos(xx) * a1 - Math.sin(xx) * a2 * 8 / Math.abs(x)); + + if (x < 0) { + a = -a; + } + } + + return a; + } + + return function besselj(x: number, n: number): number { + const _n = Math.round(n); + + if (!Number.isFinite(x)) { + return Number.isNaN(x) ? x : 0; + } + + if (_n < 0) { + return ((_n % 2) ? -1 : 1) * besselj(x, -_n); + } + + if (x < 0) { + return ((_n % 2) ? -1 : 1) * besselj(-x, _n); + } + + if (_n === 0) { + return bessel0(x); + } + + if (_n === 1) { + return bessel1(x); + } + + if (x === 0) { + return 0; + } + + let ret = 0.0; + + if (x > _n) { + ret = _bessel_iter(x, _n, bessel0(x), bessel1(x), -1); + } else { + const m = 2 * Math.floor((_n + Math.floor(Math.sqrt(40 * _n))) / 2); + let jsum = false; + let bjp = 0.0; + let sum = 0.0; + let bj = 1.0; + let bjm = 0.0; + const tox = 2 / x; + + for (let j = m; j > 0; j--) { + bjm = j * tox * bj - bjp; + bjp = bj; + bj = bjm; + + if (Math.abs(bj) > 1e10) { + bj *= 1e-10; + bjp *= 1e-10; + ret *= 1e-10; + sum *= 1e-10; + } + + if (jsum) { + sum += bj; + } + + jsum = !jsum; + + if (j === _n) { + ret = bjp; + } + } + + sum = 2.0 * sum - bj; + ret /= sum; + } + + return ret; + }; + })(); + + export const bessely = (() => { + const b0_a1a = [228.4622733, -86327.92757, 10879881.29, -512359803.6, 7062834065.0, -2957821389.0]; + const b0_a2a = [1.0, 226.1030244, 47447.26470, 7189466.438, 745249964.8, 40076544269.0]; + const b0_a1b = [0.2093887211e-6, -0.2073370639e-5, 0.2734510407e-4, -0.1098628627e-2, 1.0]; + const b0_a2b = [-0.934945152e-7, 0.7621095161e-6, -0.6911147651e-5, 0.1430488765e-3, -0.1562499995e-1]; + + function bessel0(x: number): number { + let a = 0; + let a1 = 0; + let a2 = 0; + let y = x * x; + const xx = x - 0.785398164; + + if (x < 8) { + a1 = _horner(b0_a1a, y); + a2 = _horner(b0_a2a, y); + a = a1 / a2 + W * besselj(x, 0) * Math.log(x); + } else { + y = 64 / y; + a1 = _horner(b0_a1b, y); + a2 = _horner(b0_a2b, y); + a = Math.sqrt(W / x) * (Math.sin(xx) * a1 + Math.cos(xx) * a2 * 8 / x); + } + + return a; + } + + const b1_a1a = [0.8511937935e4, -0.4237922726e7, 0.7349264551e9, -0.5153438139e11, 0.1275274390e13, -0.4900604943e13]; + const b1_a2a = [1, 0.3549632885e3, 0.1020426050e6, 0.2245904002e8, 0.3733650367e10, 0.4244419664e12, 0.2499580570e14]; + const b1_a1b = [-0.240337019e-6, 0.2457520174e-5, -0.3516396496e-4, 0.183105e-2, 1.0]; + const b1_a2b = [0.105787412e-6, -0.88228987e-6, 0.8449199096e-5, -0.2002690873e-3, 0.04687499995]; + + function bessel1(x: number): number { + let a = 0; + let a1 = 0; + let a2 = 0; + let y = x * x; + const xx = x - 2.356194491; + + if (x < 8) { + a1 = x * _horner(b1_a1a, y); + a2 = _horner(b1_a2a, y); + a = a1 / a2 + W * (besselj(x, 1) * Math.log(x) - 1 / x); + } else { + y = 64 / y; + a1 = _horner(b1_a1b, y); + a2 = _horner(b1_a2b, y); + a = Math.sqrt(W / x) * (Math.sin(xx) * a1 + Math.cos(xx) * a2 * 8 / x); + } + + return a; + } + + return _bessel_wrap(bessel0, bessel1, 1, -1); + })(); + + export const besseli = (() => { + const b0_a = [0.45813e-2, 0.360768e-1, 0.2659732, 1.2067492, 3.0899424, 3.5156229, 1.0]; + const b0_b = [0.392377e-2, -0.1647633e-1, 0.2635537e-1, -0.2057706e-1, 0.916281e-2, -0.157565e-2, 0.225319e-2, 0.1328592e-1, 0.39894228]; + + function bessel0(x: number): number { + if (x <= 3.75) { + return _horner(b0_a, x * x / (3.75 * 3.75)); + } + + return Math.exp(Math.abs(x)) / Math.sqrt(Math.abs(x)) * _horner(b0_b, 3.75 / Math.abs(x)); + } + + const b1_a = [0.32411e-3, 0.301532e-2, 0.2658733e-1, 0.15084934, 0.51498869, 0.87890594, 0.5]; + const b1_b = [-0.420059e-2, 0.1787654e-1, -0.2895312e-1, 0.2282967e-1, -0.1031555e-1, 0.163801e-2, -0.362018e-2, -0.3988024e-1, 0.39894228]; + + function bessel1(x: number): number { + if (x < 3.75) { + return x * _horner(b1_a, x * x / (3.75 * 3.75)); + } + + return (x < 0 ? -1 : 1) * Math.exp(Math.abs(x)) / Math.sqrt(Math.abs(x)) * _horner(b1_b, 3.75 / Math.abs(x)); + } + + return function besseli(x: number, n: number): number { + const _n = Math.round(n); + + if (_n === 0) { + return bessel0(x); + } + + if (_n === 1) { + return bessel1(x); + } + + if (_n < 0) { + return Number.NaN; + } + + if (Math.abs(x) === 0) { + return 0; + } + + if (x === Infinity) { + return Infinity; + } + + let ret = 0.0; + let j; + const tox = 2 / Math.abs(x); + let bip = 0.0; + let bi = 1.0; + let bim = 0.0; + + const m = 2 * Math.round((_n + Math.round(Math.sqrt(40 * _n))) / 2); + + for (j = m; j > 0; j--) { + bim = j * tox * bi + bip; + bip = bi; + bi = bim; + + if (Math.abs(bi) > 1e10) { + bi *= 1e-10; + bip *= 1e-10; + ret *= 1e-10; + } + + if (j === _n) ret = bip; + } + + ret *= besseli(x, 0) / bi; + + return x < 0 && (_n % 2) ? -ret : ret; + }; + })(); + + export const besselk = (() => { + const b0_a = [0.74e-5, 0.10750e-3, 0.262698e-2, 0.3488590e-1, 0.23069756, 0.42278420, -0.57721566]; + const b0_b = [0.53208e-3, -0.251540e-2, 0.587872e-2, -0.1062446e-1, 0.2189568e-1, -0.7832358e-1, 1.25331414]; + + function bessel0(x: number): number { + if (x <= 2) { + return -Math.log(x / 2) * besseli(x, 0) + _horner(b0_a, x * x / 4); + } + + return Math.exp(-x) / Math.sqrt(x) * _horner(b0_b, 2 / x); + } + + const b1_a = [-0.4686e-4, -0.110404e-2, -0.1919402e-1, -0.18156897, -0.67278579, 0.15443144, 1.0]; + const b1_b = [-0.68245e-3, 0.325614e-2, -0.780353e-2, 0.1504268e-1, -0.3655620e-1, 0.23498619, 1.25331414]; + + function bessel1(x: number): number { + if (x <= 2) { + return Math.log(x / 2) * besseli(x, 1) + (1 / x) * _horner(b1_a, x * x / 4); + } + + return Math.exp(-x) / Math.sqrt(x) * _horner(b1_b, 2 / x); + } + + return _bessel_wrap(bessel0, bessel1, 2, 1); + })(); +} + +export function isValidBinaryNumber(number: string): boolean { + return /^[01]{1,10}$/.test(number); +} + +export function isValidOctalNumber(number: string): boolean { + return /^[0-7]{1,10}$/.test(number); +} + +export function isValidHexadecimalNumber(number: string): boolean { + return /^[0-9A-Fa-f]{1,10}$/.test(number); +} + +export function erf(x: number): number { + if (x === 0) { + return 0; + } + + // eslint-disable-next-line + const cof = [-1.3026537197817094, 6.4196979235649026e-1, 1.9476473204185836e-2, + -9.561514786808631e-3, -9.46595344482036e-4, 3.66839497852761e-4, + 4.2523324806907e-5, -2.0278578112534e-5, -1.624290004647e-6, + 1.303655835580e-6, 1.5626441722e-8, -8.5238095915e-8, + 6.529054439e-9, 5.059343495e-9, -9.91364156e-10, + -2.27365122e-10, 9.6467911e-11, 2.394038e-12, + -6.886027e-12, 8.94487e-13, 3.13092e-13, + -1.12708e-13, 3.81e-16, 7.106e-15, + -1.523e-15, -9.4e-17, 1.21e-16, + -2.8e-17]; + + let _x = x; + let isneg = false; + + if (_x < 0) { + _x = -_x; + isneg = true; + } + + const t = 2 / (2 + _x); + const ty = 4 * t - 2; + + let d = 0; + let dd = 0; + let tmp; + + for (let j = cof.length - 1; j > 0; j--) { + tmp = d; + d = ty * d - dd + cof[j]; + dd = tmp; + } + + const res = t * Math.exp(-_x * _x + 0.5 * (cof[0] + ty * d) - dd); + + return isneg ? res - 1 : 1 - res; +}; diff --git a/packages/engine-formula/src/functions/engineering/besseli/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/besseli/__tests__/index.spec.ts new file mode 100644 index 00000000000..69bf17fce3c --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/besseli/__tests__/index.spec.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Besseli } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test besseli function', () => { + const testFunction = new Besseli(FUNCTION_NAMES_ENGINEERING.BESSELI); + + describe('Besseli', () => { + it('Value is normal number', () => { + const x = NumberValueObject.create(1.5); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(0.981666428475166); + }); + + it('Value is number string', () => { + const x = StringValueObject.create('-0.5'); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(-0.25789430328903556); + }); + + it('Value is normal string', () => { + const x = StringValueObject.create('test'); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const x = BooleanValueObject.create(true); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is null', () => { + const x = NullValueObject.create(); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.NA); + }); + + it('Value is blank cell', () => { + const x = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [null], + ]), + rowCount: 1, + columnCount: 1, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(0); + }); + + it('Value is error', () => { + const x = ErrorValueObject.create(ErrorType.NAME); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const x = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/besseli/index.ts b/packages/engine-formula/src/functions/engineering/besseli/index.ts new file mode 100644 index 00000000000..a6473b13c0c --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/besseli/index.ts @@ -0,0 +1,60 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BESSEL, checkVariantsErrorIsArrayOrBoolean } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; + +export class Besseli extends BaseFunction { + override minParams = 2; + + override maxParams = 2; + + override calculate(x: BaseValueObject, n: BaseValueObject) { + if (x.isNull() || n.isNull()) { + return ErrorValueObject.create(ErrorType.NA); + } + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(x, n); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [xObject, nObject] = variants as BaseValueObject[]; + + const xValue = +xObject.getValue(); + const nValue = Math.floor(+nObject.getValue()); + + if (Number.isNaN(xValue) || Number.isNaN(nValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + if (nValue < 0) { + return ErrorValueObject.create(ErrorType.NUM); + } + + const result = BESSEL.besseli(xValue, nValue); + + if (Number.isNaN(result) || !Number.isFinite(result)) { + return ErrorValueObject.create(ErrorType.NUM); + } + + return NumberValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/besselj/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/besselj/__tests__/index.spec.ts new file mode 100644 index 00000000000..c6bcdd401bb --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/besselj/__tests__/index.spec.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Besselj } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test besselj function', () => { + const testFunction = new Besselj(FUNCTION_NAMES_ENGINEERING.BESSELJ); + + describe('Besselj', () => { + it('Value is normal number', () => { + const x = NumberValueObject.create(1.5); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(0.5579365078908043); + }); + + it('Value is number string', () => { + const x = StringValueObject.create('-0.5'); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(-0.24226845767957006); + }); + + it('Value is normal string', () => { + const x = StringValueObject.create('test'); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const x = BooleanValueObject.create(true); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is null', () => { + const x = NullValueObject.create(); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.NA); + }); + + it('Value is blank cell', () => { + const x = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [null], + ]), + rowCount: 1, + columnCount: 1, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(0); + }); + + it('Value is error', () => { + const x = ErrorValueObject.create(ErrorType.NAME); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const x = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/besselj/index.ts b/packages/engine-formula/src/functions/engineering/besselj/index.ts new file mode 100644 index 00000000000..3c6a4cfdf4f --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/besselj/index.ts @@ -0,0 +1,60 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BESSEL, checkVariantsErrorIsArrayOrBoolean } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; + +export class Besselj extends BaseFunction { + override minParams = 2; + + override maxParams = 2; + + override calculate(x: BaseValueObject, n: BaseValueObject) { + if (x.isNull() || n.isNull()) { + return ErrorValueObject.create(ErrorType.NA); + } + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(x, n); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [xObject, nObject] = variants as BaseValueObject[]; + + const xValue = +xObject.getValue(); + const nValue = Math.floor(+nObject.getValue()); + + if (Number.isNaN(xValue) || Number.isNaN(nValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + if (nValue < 0) { + return ErrorValueObject.create(ErrorType.NUM); + } + + const result = BESSEL.besselj(xValue, nValue); + + if (Number.isNaN(result) || !Number.isFinite(result)) { + return ErrorValueObject.create(ErrorType.NUM); + } + + return NumberValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/besselk/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/besselk/__tests__/index.spec.ts new file mode 100644 index 00000000000..2bb7382c45f --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/besselk/__tests__/index.spec.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Besselk } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test besselk function', () => { + const testFunction = new Besselk(FUNCTION_NAMES_ENGINEERING.BESSELK); + + describe('Besselk', () => { + it('Value is normal number', () => { + const x = NumberValueObject.create(1.5); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(0.2773878036322587); + }); + + it('Value is number string', () => { + const x = StringValueObject.create('-0.5'); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is normal string', () => { + const x = StringValueObject.create('test'); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const x = BooleanValueObject.create(true); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is null', () => { + const x = NullValueObject.create(); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.NA); + }); + + it('Value is blank cell', () => { + const x = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [null], + ]), + rowCount: 1, + columnCount: 1, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is error', () => { + const x = ErrorValueObject.create(ErrorType.NAME); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const x = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/besselk/index.ts b/packages/engine-formula/src/functions/engineering/besselk/index.ts new file mode 100644 index 00000000000..5486bb1a0cd --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/besselk/index.ts @@ -0,0 +1,60 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BESSEL, checkVariantsErrorIsArrayOrBoolean } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; + +export class Besselk extends BaseFunction { + override minParams = 2; + + override maxParams = 2; + + override calculate(x: BaseValueObject, n: BaseValueObject) { + if (x.isNull() || n.isNull()) { + return ErrorValueObject.create(ErrorType.NA); + } + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(x, n); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [xObject, nObject] = variants as BaseValueObject[]; + + const xValue = +xObject.getValue(); + const nValue = Math.floor(+nObject.getValue()); + + if (Number.isNaN(xValue) || Number.isNaN(nValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + if (nValue < 0) { + return ErrorValueObject.create(ErrorType.NUM); + } + + const result = BESSEL.besselk(xValue, nValue); + + if (Number.isNaN(result) || !Number.isFinite(result)) { + return ErrorValueObject.create(ErrorType.NUM); + } + + return NumberValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/bessely/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/bessely/__tests__/index.spec.ts new file mode 100644 index 00000000000..36ca99bd739 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bessely/__tests__/index.spec.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Bessely } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test bessely function', () => { + const testFunction = new Bessely(FUNCTION_NAMES_ENGINEERING.BESSELY); + + describe('Bessely', () => { + it('Value is normal number', () => { + const x = NumberValueObject.create(1.5); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(-0.41230862689590375); + }); + + it('Value is number string', () => { + const x = StringValueObject.create('-0.5'); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is normal string', () => { + const x = StringValueObject.create('test'); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const x = BooleanValueObject.create(true); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is null', () => { + const x = NullValueObject.create(); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.NA); + }); + + it('Value is blank cell', () => { + const x = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [null], + ]), + rowCount: 1, + columnCount: 1, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is error', () => { + const x = ErrorValueObject.create(ErrorType.NAME); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const x = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const n = NumberValueObject.create(1); + const result = testFunction.calculate(x, n); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/bessely/index.ts b/packages/engine-formula/src/functions/engineering/bessely/index.ts new file mode 100644 index 00000000000..1fb1c840a59 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bessely/index.ts @@ -0,0 +1,60 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BESSEL, checkVariantsErrorIsArrayOrBoolean } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; + +export class Bessely extends BaseFunction { + override minParams = 2; + + override maxParams = 2; + + override calculate(x: BaseValueObject, n: BaseValueObject) { + if (x.isNull() || n.isNull()) { + return ErrorValueObject.create(ErrorType.NA); + } + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(x, n); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [xObject, nObject] = variants as BaseValueObject[]; + + const xValue = +xObject.getValue(); + const nValue = Math.floor(+nObject.getValue()); + + if (Number.isNaN(xValue) || Number.isNaN(nValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + if (nValue < 0) { + return ErrorValueObject.create(ErrorType.NUM); + } + + const result = BESSEL.bessely(xValue, nValue); + + if (Number.isNaN(result) || !Number.isFinite(result)) { + return ErrorValueObject.create(ErrorType.NUM); + } + + return NumberValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/bin2dec/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/bin2dec/__tests__/index.spec.ts new file mode 100644 index 00000000000..746d5b33fb0 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bin2dec/__tests__/index.spec.ts @@ -0,0 +1,83 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Bin2dec } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test bin2dec function', () => { + const testFunction = new Bin2dec(FUNCTION_NAMES_ENGINEERING.BIN2DEC); + + describe('Bin2dec', () => { + it('Value is normal number', () => { + const number = NumberValueObject.create(1100100); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(100); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('-0.5'); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is blank cell', () => { + const number = NullValueObject.create(); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(0); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const result = testFunction.calculate(number); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/bin2dec/index.ts b/packages/engine-formula/src/functions/engineering/bin2dec/index.ts new file mode 100644 index 00000000000..9973c8aed22 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bin2dec/index.ts @@ -0,0 +1,54 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { checkVariantsErrorIsArrayOrBoolean, isValidBinaryNumber } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; + +export class Bin2dec extends BaseFunction { + override minParams = 1; + + override maxParams = 1; + + override calculate(number: BaseValueObject) { + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(number); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [numberObject] = variants as BaseValueObject[]; + + const numberValue = `${numberObject.getValue()}`; + + // Return error if number is not binary or contains more than 10 characters (10 digits) + if (!isValidBinaryNumber(numberValue)) { + return ErrorValueObject.create(ErrorType.NUM); + } + + let result; + + if (numberValue.length === 10 && numberValue.substring(0, 1) === '1') { + result = Number.parseInt(numberValue.substring(1), 2) - 512; + } else { + result = Number.parseInt(numberValue, 2); + } + + return NumberValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/bin2hex/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/bin2hex/__tests__/index.spec.ts new file mode 100644 index 00000000000..24098351699 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bin2hex/__tests__/index.spec.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Bin2hex } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test bin2hex function', () => { + const testFunction = new Bin2hex(FUNCTION_NAMES_ENGINEERING.BIN2HEX); + + describe('Bin2hex', () => { + it('Value is normal number', () => { + const number = NumberValueObject.create(11111011); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('00FB'); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('-0.5'); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is null', () => { + const number = NullValueObject.create(); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NA); + }); + + it('Value is blank cell', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [null], + ]), + rowCount: 1, + columnCount: 1, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('0000'); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/bin2hex/index.ts b/packages/engine-formula/src/functions/engineering/bin2hex/index.ts new file mode 100644 index 00000000000..006260e37ec --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bin2hex/index.ts @@ -0,0 +1,89 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { checkVariantsErrorIsArrayOrBoolean, isValidBinaryNumber } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { StringValueObject } from '../../../engine/value-object/primitive-object'; + +export class Bin2hex extends BaseFunction { + override minParams = 1; + + override maxParams = 2; + + override calculate(number: BaseValueObject, places?: BaseValueObject) { + if (number.isNull()) { + return ErrorValueObject.create(ErrorType.NA); + } + + let placesValue = 0; + + if (places) { + // If places exists, it is prioritized. + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(places); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [placesObject] = variants as BaseValueObject[]; + + placesValue = Math.floor(+placesObject.getValue()); + + if (Number.isNaN(placesValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + if (placesValue < 0 || placesValue > 10) { + return ErrorValueObject.create(ErrorType.NUM); + } + } + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(number); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [numberObject] = variants as BaseValueObject[]; + + const numberValue = `${numberObject.getValue()}`; + + // Return error if number is not binary or contains more than 10 characters (10 digits) + if (!isValidBinaryNumber(numberValue)) { + return ErrorValueObject.create(ErrorType.NUM); + } + + let result; + + if (numberValue.length === 10 && numberValue.substring(0, 1) === '1') { + result = (1099511627264 + Number.parseInt(numberValue.substring(1), 2)).toString(16); + } else { + result = Number.parseInt(numberValue, 2).toString(16); + + if (places) { + if (placesValue < result.length) { + return ErrorValueObject.create(ErrorType.NUM); + } + + result = '0'.repeat(placesValue - result.length) + result; + } + } + + return StringValueObject.create(result.toLocaleUpperCase()); + } +} diff --git a/packages/engine-formula/src/functions/engineering/bin2oct/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/bin2oct/__tests__/index.spec.ts new file mode 100644 index 00000000000..ee5a3f42699 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bin2oct/__tests__/index.spec.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Bin2oct } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test bin2oct function', () => { + const testFunction = new Bin2oct(FUNCTION_NAMES_ENGINEERING.BIN2OCT); + + describe('Bin2oct', () => { + it('Value is normal number', () => { + const number = NumberValueObject.create(1001); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('011'); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('-0.5'); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is null', () => { + const number = NullValueObject.create(); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NA); + }); + + it('Value is blank cell', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [null], + ]), + rowCount: 1, + columnCount: 1, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('000'); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/bin2oct/index.ts b/packages/engine-formula/src/functions/engineering/bin2oct/index.ts new file mode 100644 index 00000000000..7b9ab63c3aa --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bin2oct/index.ts @@ -0,0 +1,89 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { checkVariantsErrorIsArrayOrBoolean, isValidBinaryNumber } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { StringValueObject } from '../../../engine/value-object/primitive-object'; + +export class Bin2oct extends BaseFunction { + override minParams = 1; + + override maxParams = 2; + + override calculate(number: BaseValueObject, places?: BaseValueObject) { + if (number.isNull()) { + return ErrorValueObject.create(ErrorType.NA); + } + + let placesValue = 0; + + if (places) { + // If places exists, it is prioritized. + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(places); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [placesObject] = variants as BaseValueObject[]; + + placesValue = Math.floor(+placesObject.getValue()); + + if (Number.isNaN(placesValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + if (placesValue < 0 || placesValue > 10) { + return ErrorValueObject.create(ErrorType.NUM); + } + } + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(number); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [numberObject] = variants as BaseValueObject[]; + + const numberValue = `${numberObject.getValue()}`; + + // Return error if number is not binary or contains more than 10 characters (10 digits) + if (!isValidBinaryNumber(numberValue)) { + return ErrorValueObject.create(ErrorType.NUM); + } + + let result; + + if (numberValue.length === 10 && numberValue.substring(0, 1) === '1') { + result = (1073741312 + Number.parseInt(numberValue.substring(1), 2)).toString(8); + } else { + result = Number.parseInt(numberValue, 2).toString(8); + + if (places) { + if (placesValue < result.length) { + return ErrorValueObject.create(ErrorType.NUM); + } + + result = '0'.repeat(placesValue - result.length) + result; + } + } + + return StringValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/bitand/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/bitand/__tests__/index.spec.ts new file mode 100644 index 00000000000..64f65e4bc74 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bitand/__tests__/index.spec.ts @@ -0,0 +1,93 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Bitand } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValue, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test bitand function', () => { + const testFunction = new Bitand(FUNCTION_NAMES_ENGINEERING.BITAND); + + describe('Bitand', () => { + it('Value is normal number', () => { + const number1 = NumberValueObject.create(13); + const number2 = NumberValueObject.create(25); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(9); + }); + + it('Value is number string', () => { + const number1 = StringValueObject.create('1'); + const number2 = NumberValueObject.create(5); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(1); + }); + + it('Value is normal string', () => { + const number1 = StringValueObject.create('test'); + const number2 = NumberValueObject.create(25); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const number1 = BooleanValueObject.create(true); + const number2 = NumberValueObject.create(25); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(1); + }); + + it('Value is blank cell', () => { + const number1 = NullValueObject.create(); + const number2 = NumberValueObject.create(25); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(0); + }); + + it('Value is error', () => { + const number1 = ErrorValueObject.create(ErrorType.NAME); + const number2 = NumberValueObject.create(25); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number1 = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const number2 = NumberValueObject.create(25); + const result = testFunction.calculate(number1, number2); + expect(transformToValue(result.getArrayValue())).toStrictEqual([ + [1, ErrorType.VALUE, ErrorType.NUM, 1, 0, 0], + [0, 0, ErrorType.NUM, ErrorType.VALUE, ErrorType.NUM, ErrorType.NAME], + ]); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/bitand/index.ts b/packages/engine-formula/src/functions/engineering/bitand/index.ts new file mode 100644 index 00000000000..42f7f124c0b --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bitand/index.ts @@ -0,0 +1,100 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; +import type { ArrayValueObject } from '../../../engine/value-object/array-value-object'; +import { expandArrayValueObject } from '../../../engine/utils/array-object'; + +export class Bitand extends BaseFunction { + override minParams = 2; + + override maxParams = 2; + + override calculate(number1: BaseValueObject, number2: BaseValueObject) { + if (number1.isError()) { + return number1; + } + + if (number2.isError()) { + return number2; + } + + const maxRowLength = Math.max( + number1.isArray() ? (number1 as ArrayValueObject).getRowCount() : 1, + number2.isArray() ? (number2 as ArrayValueObject).getRowCount() : 1 + ); + + const maxColumnLength = Math.max( + number1.isArray() ? (number1 as ArrayValueObject).getColumnCount() : 1, + number2.isArray() ? (number2 as ArrayValueObject).getColumnCount() : 1 + ); + + const number1Array = expandArrayValueObject(maxRowLength, maxColumnLength, number1, ErrorValueObject.create(ErrorType.NA)); + const number2Array = expandArrayValueObject(maxRowLength, maxColumnLength, number2, ErrorValueObject.create(ErrorType.NA)); + + const resultArray = number1Array.map((itemObject, rowIndex, columnIndex) => { + let number1Object = itemObject; + + if (number1Object.isString()) { + number1Object = number1Object.convertToNumberObjectValue(); + } + + if (number1Object.isError()) { + return number1Object; + } + + let number2Object = number2Array.get(rowIndex, columnIndex) as BaseValueObject; + + if (number2Object.isString()) { + number2Object = number2Object.convertToNumberObjectValue(); + } + + if (number2Object.isError()) { + return number2Object; + } + + const number1Value = +number1Object.getValue(); + const number2Value = +number2Object.getValue(); + + // Return error if either number is less than 0 + // Return error if either number is a non-integer + // Return error if either number is greater than (2^48)-1 + if ( + number1Value < 0 || + number2Value < 0 || + Math.floor(number1Value) !== number1Value || + Math.floor(number2Value) !== number2Value || + number1Value > 281474976710655 || + number2Value > 281474976710655 + ) { + return ErrorValueObject.create(ErrorType.NUM); + } + + const result = number1Value & number2Value; + + return NumberValueObject.create(result); + }); + + if (maxRowLength === 1 && maxColumnLength === 1) { + return (resultArray as ArrayValueObject).get(0, 0) as BaseValueObject; + } + + return resultArray; + } +} diff --git a/packages/engine-formula/src/functions/engineering/bitlshift/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/bitlshift/__tests__/index.spec.ts new file mode 100644 index 00000000000..8aa1100b5f6 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bitlshift/__tests__/index.spec.ts @@ -0,0 +1,93 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Bitlshift } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValue, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test bitlshift function', () => { + const testFunction = new Bitlshift(FUNCTION_NAMES_ENGINEERING.BITLSHIFT); + + describe('Bitlshift', () => { + it('Value is normal number', () => { + const number = NumberValueObject.create(4); + const shiftAmount = NumberValueObject.create(2); + const result = testFunction.calculate(number, shiftAmount); + expect(result.getValue()).toBe(16); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('1'); + const shiftAmount = NumberValueObject.create(2); + const result = testFunction.calculate(number, shiftAmount); + expect(result.getValue()).toBe(4); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const shiftAmount = NumberValueObject.create(2); + const result = testFunction.calculate(number, shiftAmount); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const shiftAmount = NumberValueObject.create(2); + const result = testFunction.calculate(number, shiftAmount); + expect(result.getValue()).toBe(4); + }); + + it('Value is blank cell', () => { + const number = NullValueObject.create(); + const shiftAmount = NumberValueObject.create(2); + const result = testFunction.calculate(number, shiftAmount); + expect(result.getValue()).toBe(0); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const shiftAmount = NumberValueObject.create(2); + const result = testFunction.calculate(number, shiftAmount); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const shiftAmount = NumberValueObject.create(2); + const result = testFunction.calculate(number, shiftAmount); + expect(transformToValue(result.getArrayValue())).toStrictEqual([ + [4, ErrorType.VALUE, ErrorType.NUM, 4, 0, 0], + [0, 400, ErrorType.NUM, ErrorType.VALUE, ErrorType.NUM, ErrorType.NAME], + ]); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/bitlshift/index.ts b/packages/engine-formula/src/functions/engineering/bitlshift/index.ts new file mode 100644 index 00000000000..2367eb3d437 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bitlshift/index.ts @@ -0,0 +1,106 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; +import type { ArrayValueObject } from '../../../engine/value-object/array-value-object'; +import { expandArrayValueObject } from '../../../engine/utils/array-object'; + +export class Bitlshift extends BaseFunction { + override minParams = 2; + + override maxParams = 2; + + override calculate(number: BaseValueObject, shiftAmount: BaseValueObject) { + if (number.isError()) { + return number; + } + + if (shiftAmount.isError()) { + return shiftAmount; + } + + const maxRowLength = Math.max( + number.isArray() ? (number as ArrayValueObject).getRowCount() : 1, + shiftAmount.isArray() ? (shiftAmount as ArrayValueObject).getRowCount() : 1 + ); + + const maxColumnLength = Math.max( + number.isArray() ? (number as ArrayValueObject).getColumnCount() : 1, + shiftAmount.isArray() ? (shiftAmount as ArrayValueObject).getColumnCount() : 1 + ); + + const numberArray = expandArrayValueObject(maxRowLength, maxColumnLength, number, ErrorValueObject.create(ErrorType.NA)); + const shiftAmountArray = expandArrayValueObject(maxRowLength, maxColumnLength, shiftAmount, ErrorValueObject.create(ErrorType.NA)); + + const resultArray = numberArray.map((itemObject, rowIndex, columnIndex) => { + let numberObject = itemObject; + + if (numberObject.isString()) { + numberObject = numberObject.convertToNumberObjectValue(); + } + + if (numberObject.isError()) { + return numberObject; + } + + let shiftAmountObject = shiftAmountArray.get(rowIndex, columnIndex) as BaseValueObject; + + if (shiftAmountObject.isString()) { + shiftAmountObject = shiftAmountObject.convertToNumberObjectValue(); + } + + if (shiftAmountObject.isError()) { + return shiftAmountObject; + } + + const numberValue = +numberObject.getValue(); + let shiftAmountValue = +shiftAmountObject.getValue(); + + // Return error if number is less than 0 + // Return error if number is a non-integer + // Return error if number is greater than (2^48)-1 + // Return error if the absolute value of shift is greater than 53 + if ( + numberValue < 0 || + Math.floor(numberValue) !== numberValue || + numberValue > 281474976710655 || + Math.abs(shiftAmountValue) > 53 + ) { + return ErrorValueObject.create(ErrorType.NUM); + } + + shiftAmountValue = Math.trunc(shiftAmountValue); + + // Return number shifted by shift bits to the left or to the right if shift is negative + const result = Number(shiftAmountValue >= 0 ? BigInt(numberValue) << BigInt(shiftAmountValue) : BigInt(numberValue) >> BigInt(-shiftAmountValue)); + + if (result > 281474976710655) { + return ErrorValueObject.create(ErrorType.NUM); + } + + return NumberValueObject.create(result); + }); + + if (maxRowLength === 1 && maxColumnLength === 1) { + return (resultArray as ArrayValueObject).get(0, 0) as BaseValueObject; + } + + return resultArray; + } +} diff --git a/packages/engine-formula/src/functions/engineering/bitor/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/bitor/__tests__/index.spec.ts new file mode 100644 index 00000000000..50170542f1f --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bitor/__tests__/index.spec.ts @@ -0,0 +1,93 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Bitor } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValue, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test bitor function', () => { + const testFunction = new Bitor(FUNCTION_NAMES_ENGINEERING.BITOR); + + describe('Bitor', () => { + it('Value is normal number', () => { + const number1 = NumberValueObject.create(23); + const number2 = NumberValueObject.create(10); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(31); + }); + + it('Value is number string', () => { + const number1 = StringValueObject.create('1'); + const number2 = NumberValueObject.create(10); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(11); + }); + + it('Value is normal string', () => { + const number1 = StringValueObject.create('test'); + const number2 = NumberValueObject.create(10); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const number1 = BooleanValueObject.create(true); + const number2 = NumberValueObject.create(10); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(11); + }); + + it('Value is blank cell', () => { + const number1 = NullValueObject.create(); + const number2 = NumberValueObject.create(10); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(10); + }); + + it('Value is error', () => { + const number1 = ErrorValueObject.create(ErrorType.NAME); + const number2 = NumberValueObject.create(10); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number1 = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const number2 = NumberValueObject.create(10); + const result = testFunction.calculate(number1, number2); + expect(transformToValue(result.getArrayValue())).toStrictEqual([ + [11, ErrorType.VALUE, ErrorType.NUM, 11, 10, 10], + [10, 110, ErrorType.NUM, ErrorType.VALUE, ErrorType.NUM, ErrorType.NAME], + ]); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/bitor/index.ts b/packages/engine-formula/src/functions/engineering/bitor/index.ts new file mode 100644 index 00000000000..b8ff50ef6cf --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bitor/index.ts @@ -0,0 +1,100 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; +import type { ArrayValueObject } from '../../../engine/value-object/array-value-object'; +import { expandArrayValueObject } from '../../../engine/utils/array-object'; + +export class Bitor extends BaseFunction { + override minParams = 2; + + override maxParams = 2; + + override calculate(number1: BaseValueObject, number2: BaseValueObject) { + if (number1.isError()) { + return number1; + } + + if (number2.isError()) { + return number2; + } + + const maxRowLength = Math.max( + number1.isArray() ? (number1 as ArrayValueObject).getRowCount() : 1, + number2.isArray() ? (number2 as ArrayValueObject).getRowCount() : 1 + ); + + const maxColumnLength = Math.max( + number1.isArray() ? (number1 as ArrayValueObject).getColumnCount() : 1, + number2.isArray() ? (number2 as ArrayValueObject).getColumnCount() : 1 + ); + + const number1Array = expandArrayValueObject(maxRowLength, maxColumnLength, number1, ErrorValueObject.create(ErrorType.NA)); + const number2Array = expandArrayValueObject(maxRowLength, maxColumnLength, number2, ErrorValueObject.create(ErrorType.NA)); + + const resultArray = number1Array.map((itemObject, rowIndex, columnIndex) => { + let number1Object = itemObject; + + if (number1Object.isString()) { + number1Object = number1Object.convertToNumberObjectValue(); + } + + if (number1Object.isError()) { + return number1Object; + } + + let number2Object = number2Array.get(rowIndex, columnIndex) as BaseValueObject; + + if (number2Object.isString()) { + number2Object = number2Object.convertToNumberObjectValue(); + } + + if (number2Object.isError()) { + return number2Object; + } + + const number1Value = +number1Object.getValue(); + const number2Value = +number2Object.getValue(); + + // Return error if either number is less than 0 + // Return error if either number is a non-integer + // Return error if either number is greater than (2^48)-1 + if ( + number1Value < 0 || + number2Value < 0 || + Math.floor(number1Value) !== number1Value || + Math.floor(number2Value) !== number2Value || + number1Value > 281474976710655 || + number2Value > 281474976710655 + ) { + return ErrorValueObject.create(ErrorType.NUM); + } + + const result = Number(BigInt(number1Value) | BigInt(number2Value)); + + return NumberValueObject.create(result); + }); + + if (maxRowLength === 1 && maxColumnLength === 1) { + return (resultArray as ArrayValueObject).get(0, 0) as BaseValueObject; + } + + return resultArray; + } +} diff --git a/packages/engine-formula/src/functions/engineering/bitrshift/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/bitrshift/__tests__/index.spec.ts new file mode 100644 index 00000000000..7bc7ecf94a3 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bitrshift/__tests__/index.spec.ts @@ -0,0 +1,93 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Bitrshift } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValue, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test bitrshift function', () => { + const testFunction = new Bitrshift(FUNCTION_NAMES_ENGINEERING.BITRSHIFT); + + describe('Bitrshift', () => { + it('Value is normal number', () => { + const number = NumberValueObject.create(13); + const shiftAmount = NumberValueObject.create(2); + const result = testFunction.calculate(number, shiftAmount); + expect(result.getValue()).toBe(3); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('1'); + const shiftAmount = NumberValueObject.create(2); + const result = testFunction.calculate(number, shiftAmount); + expect(result.getValue()).toBe(0); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const shiftAmount = NumberValueObject.create(2); + const result = testFunction.calculate(number, shiftAmount); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const shiftAmount = NumberValueObject.create(2); + const result = testFunction.calculate(number, shiftAmount); + expect(result.getValue()).toBe(0); + }); + + it('Value is blank cell', () => { + const number = NullValueObject.create(); + const shiftAmount = NumberValueObject.create(2); + const result = testFunction.calculate(number, shiftAmount); + expect(result.getValue()).toBe(0); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const shiftAmount = NumberValueObject.create(2); + const result = testFunction.calculate(number, shiftAmount); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const shiftAmount = NumberValueObject.create(2); + const result = testFunction.calculate(number, shiftAmount); + expect(transformToValue(result.getArrayValue())).toStrictEqual([ + [0, ErrorType.VALUE, ErrorType.NUM, 0, 0, 0], + [0, 25, ErrorType.NUM, ErrorType.VALUE, ErrorType.NUM, ErrorType.NAME], + ]); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/bitrshift/index.ts b/packages/engine-formula/src/functions/engineering/bitrshift/index.ts new file mode 100644 index 00000000000..cec017558da --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bitrshift/index.ts @@ -0,0 +1,106 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; +import type { ArrayValueObject } from '../../../engine/value-object/array-value-object'; +import { expandArrayValueObject } from '../../../engine/utils/array-object'; + +export class Bitrshift extends BaseFunction { + override minParams = 2; + + override maxParams = 2; + + override calculate(number: BaseValueObject, shiftAmount: BaseValueObject) { + if (number.isError()) { + return number; + } + + if (shiftAmount.isError()) { + return shiftAmount; + } + + const maxRowLength = Math.max( + number.isArray() ? (number as ArrayValueObject).getRowCount() : 1, + shiftAmount.isArray() ? (shiftAmount as ArrayValueObject).getRowCount() : 1 + ); + + const maxColumnLength = Math.max( + number.isArray() ? (number as ArrayValueObject).getColumnCount() : 1, + shiftAmount.isArray() ? (shiftAmount as ArrayValueObject).getColumnCount() : 1 + ); + + const numberArray = expandArrayValueObject(maxRowLength, maxColumnLength, number, ErrorValueObject.create(ErrorType.NA)); + const shiftAmountArray = expandArrayValueObject(maxRowLength, maxColumnLength, shiftAmount, ErrorValueObject.create(ErrorType.NA)); + + const resultArray = numberArray.map((itemObject, rowIndex, columnIndex) => { + let numberObject = itemObject; + + if (numberObject.isString()) { + numberObject = numberObject.convertToNumberObjectValue(); + } + + if (numberObject.isError()) { + return numberObject; + } + + let shiftAmountObject = shiftAmountArray.get(rowIndex, columnIndex) as BaseValueObject; + + if (shiftAmountObject.isString()) { + shiftAmountObject = shiftAmountObject.convertToNumberObjectValue(); + } + + if (shiftAmountObject.isError()) { + return shiftAmountObject; + } + + const numberValue = +numberObject.getValue(); + let shiftAmountValue = +shiftAmountObject.getValue(); + + // Return error if number is less than 0 + // Return error if number is a non-integer + // Return error if number is greater than (2^48)-1 + // Return error if the absolute value of shift is greater than 53 + if ( + numberValue < 0 || + Math.floor(numberValue) !== numberValue || + numberValue > 281474976710655 || + Math.abs(shiftAmountValue) > 53 + ) { + return ErrorValueObject.create(ErrorType.NUM); + } + + shiftAmountValue = Math.trunc(shiftAmountValue); + + // Return number shifted by shift bits to the right or to the left if shift is negative + const result = Number(shiftAmountValue >= 0 ? BigInt(numberValue) >> BigInt(shiftAmountValue) : BigInt(numberValue) << BigInt(-shiftAmountValue)); + + if (result > 281474976710655) { + return ErrorValueObject.create(ErrorType.NUM); + } + + return NumberValueObject.create(result); + }); + + if (maxRowLength === 1 && maxColumnLength === 1) { + return (resultArray as ArrayValueObject).get(0, 0) as BaseValueObject; + } + + return resultArray; + } +} diff --git a/packages/engine-formula/src/functions/engineering/bitxor/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/bitxor/__tests__/index.spec.ts new file mode 100644 index 00000000000..b4b2a34b821 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bitxor/__tests__/index.spec.ts @@ -0,0 +1,93 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Bitxor } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValue, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test bitxor function', () => { + const testFunction = new Bitxor(FUNCTION_NAMES_ENGINEERING.BITXOR); + + describe('Bitxor', () => { + it('Value is normal number', () => { + const number1 = NumberValueObject.create(5); + const number2 = NumberValueObject.create(3); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(6); + }); + + it('Value is number string', () => { + const number1 = StringValueObject.create('1'); + const number2 = NumberValueObject.create(3); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(2); + }); + + it('Value is normal string', () => { + const number1 = StringValueObject.create('test'); + const number2 = NumberValueObject.create(3); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const number1 = BooleanValueObject.create(true); + const number2 = NumberValueObject.create(3); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(2); + }); + + it('Value is blank cell', () => { + const number1 = NullValueObject.create(); + const number2 = NumberValueObject.create(3); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(3); + }); + + it('Value is error', () => { + const number1 = ErrorValueObject.create(ErrorType.NAME); + const number2 = NumberValueObject.create(3); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number1 = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const number2 = NumberValueObject.create(3); + const result = testFunction.calculate(number1, number2); + expect(transformToValue(result.getArrayValue())).toStrictEqual([ + [2, ErrorType.VALUE, ErrorType.NUM, 2, 3, 3], + [3, 103, ErrorType.NUM, ErrorType.VALUE, ErrorType.NUM, ErrorType.NAME], + ]); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/bitxor/index.ts b/packages/engine-formula/src/functions/engineering/bitxor/index.ts new file mode 100644 index 00000000000..8eaeb0dd757 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/bitxor/index.ts @@ -0,0 +1,100 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; +import type { ArrayValueObject } from '../../../engine/value-object/array-value-object'; +import { expandArrayValueObject } from '../../../engine/utils/array-object'; + +export class Bitxor extends BaseFunction { + override minParams = 2; + + override maxParams = 2; + + override calculate(number1: BaseValueObject, number2: BaseValueObject) { + if (number1.isError()) { + return number1; + } + + if (number2.isError()) { + return number2; + } + + const maxRowLength = Math.max( + number1.isArray() ? (number1 as ArrayValueObject).getRowCount() : 1, + number2.isArray() ? (number2 as ArrayValueObject).getRowCount() : 1 + ); + + const maxColumnLength = Math.max( + number1.isArray() ? (number1 as ArrayValueObject).getColumnCount() : 1, + number2.isArray() ? (number2 as ArrayValueObject).getColumnCount() : 1 + ); + + const number1Array = expandArrayValueObject(maxRowLength, maxColumnLength, number1, ErrorValueObject.create(ErrorType.NA)); + const number2Array = expandArrayValueObject(maxRowLength, maxColumnLength, number2, ErrorValueObject.create(ErrorType.NA)); + + const resultArray = number1Array.map((itemObject, rowIndex, columnIndex) => { + let number1Object = itemObject; + + if (number1Object.isString()) { + number1Object = number1Object.convertToNumberObjectValue(); + } + + if (number1Object.isError()) { + return number1Object; + } + + let number2Object = number2Array.get(rowIndex, columnIndex) as BaseValueObject; + + if (number2Object.isString()) { + number2Object = number2Object.convertToNumberObjectValue(); + } + + if (number2Object.isError()) { + return number2Object; + } + + const number1Value = +number1Object.getValue(); + const number2Value = +number2Object.getValue(); + + // Return error if either number is less than 0 + // Return error if either number is a non-integer + // Return error if either number is greater than (2^48)-1 + if ( + number1Value < 0 || + number2Value < 0 || + Math.floor(number1Value) !== number1Value || + Math.floor(number2Value) !== number2Value || + number1Value > 281474976710655 || + number2Value > 281474976710655 + ) { + return ErrorValueObject.create(ErrorType.NUM); + } + + const result = number1Value ^ number2Value; + + return NumberValueObject.create(result); + }); + + if (maxRowLength === 1 && maxColumnLength === 1) { + return (resultArray as ArrayValueObject).get(0, 0) as BaseValueObject; + } + + return resultArray; + } +} diff --git a/packages/engine-formula/src/functions/engineering/complex/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/complex/__tests__/index.spec.ts new file mode 100644 index 00000000000..b17217f4db9 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/complex/__tests__/index.spec.ts @@ -0,0 +1,105 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Complex } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test complex function', () => { + const testFunction = new Complex(FUNCTION_NAMES_ENGINEERING.COMPLEX); + + describe('Complex', () => { + it('Value is normal number', () => { + const realNum = NumberValueObject.create(3); + const iNum = NumberValueObject.create(4); + const suffix = StringValueObject.create('i'); + const result = testFunction.calculate(realNum, iNum, suffix); + expect(result.getValue()).toBe('3+4i'); + }); + + it('Value is number string', () => { + const realNum = StringValueObject.create('-0.5'); + const iNum = NumberValueObject.create(4); + const suffix = StringValueObject.create('i'); + const result = testFunction.calculate(realNum, iNum, suffix); + expect(result.getValue()).toBe('-0.5+4i'); + }); + + it('Value is normal string', () => { + const realNum = StringValueObject.create('test'); + const iNum = NumberValueObject.create(4); + const suffix = StringValueObject.create('i'); + const result = testFunction.calculate(realNum, iNum, suffix); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const realNum = BooleanValueObject.create(true); + const iNum = NumberValueObject.create(4); + const suffix = StringValueObject.create('i'); + const result = testFunction.calculate(realNum, iNum, suffix); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is blank cell', () => { + const realNum = NullValueObject.create(); + const iNum = NumberValueObject.create(4); + const suffix = StringValueObject.create('i'); + const result = testFunction.calculate(realNum, iNum, suffix); + expect(result.getValue()).toBe('4i'); + }); + + it('Value is error', () => { + const realNum = ErrorValueObject.create(ErrorType.NAME); + const iNum = NumberValueObject.create(4); + const suffix = StringValueObject.create('i'); + const result = testFunction.calculate(realNum, iNum, suffix); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Suffix value is not i or j', () => { + const realNum = NumberValueObject.create(3); + const iNum = NumberValueObject.create(4); + const suffix = StringValueObject.create('test'); + const result = testFunction.calculate(realNum, iNum, suffix); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is array', () => { + const realNum = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const iNum = NumberValueObject.create(4); + const suffix = StringValueObject.create('i'); + const result = testFunction.calculate(realNum, iNum, suffix); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/complex/index.ts b/packages/engine-formula/src/functions/engineering/complex/index.ts new file mode 100644 index 00000000000..8e32664597a --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/complex/index.ts @@ -0,0 +1,72 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { checkVariantsErrorIsArrayOrBoolean } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject, StringValueObject } from '../../../engine/value-object/primitive-object'; + +export class Complex extends BaseFunction { + override minParams = 2; + + override maxParams = 3; + + override calculate(realNum: BaseValueObject, iNum: BaseValueObject, suffix?: BaseValueObject) { + const _suffix = suffix ?? StringValueObject.create('i'); + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(realNum, iNum, _suffix); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [realNumObject, iNumObject, suffixObject] = variants as BaseValueObject[]; + + const realNumValue = +realNumObject.getValue(); + const iNumValue = +iNumObject.getValue(); + const suffixValue = `${suffixObject.getValue()}`; + + if ( + Number.isNaN(realNumValue) || + Number.isNaN(iNumValue) || + (suffixValue !== 'i' && suffixValue !== 'j') + ) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + if (realNumValue === 0 && iNumValue === 0) { + return NumberValueObject.create(0); + } + + if (realNumValue === 0) { + if (iNumValue === 1) { + return StringValueObject.create(suffixValue); + } + + return StringValueObject.create(`${iNumValue}${suffixValue}`); + } + + if (iNumValue === 0) { + return NumberValueObject.create(realNumValue); + } + + const sign = iNumValue > 0 ? '+' : ''; + const suffixStr = iNumValue === 1 ? suffixValue : `${iNumValue}${suffixValue}`; + + return StringValueObject.create(`${realNumValue}${sign}${suffixStr}`); + } +} diff --git a/packages/engine-formula/src/functions/engineering/convert/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/convert/__tests__/index.spec.ts new file mode 100644 index 00000000000..6ec66e9709d --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/convert/__tests__/index.spec.ts @@ -0,0 +1,105 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Convert } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test convert function', () => { + const testFunction = new Convert(FUNCTION_NAMES_ENGINEERING.CONVERT); + + describe('Convert', () => { + it('Value is normal number', () => { + const number = NumberValueObject.create(1); + const fromUnit = StringValueObject.create('lbm'); + const toUnit = StringValueObject.create('kg'); + const result = testFunction.calculate(number, fromUnit, toUnit); + expect(result.getValue()).toBe(0.45359237); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('-0.5'); + const fromUnit = StringValueObject.create('lbm'); + const toUnit = StringValueObject.create('kg'); + const result = testFunction.calculate(number, fromUnit, toUnit); + expect(result.getValue()).toBe(-0.226796185); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const fromUnit = StringValueObject.create('lbm'); + const toUnit = StringValueObject.create('kg'); + const result = testFunction.calculate(number, fromUnit, toUnit); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const fromUnit = StringValueObject.create('lbm'); + const toUnit = StringValueObject.create('kg'); + const result = testFunction.calculate(number, fromUnit, toUnit); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is blank cell', () => { + const number = NullValueObject.create(); + const fromUnit = StringValueObject.create('lbm'); + const toUnit = StringValueObject.create('kg'); + const result = testFunction.calculate(number, fromUnit, toUnit); + expect(result.getValue()).toBe(0); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const fromUnit = StringValueObject.create('lbm'); + const toUnit = StringValueObject.create('kg'); + const result = testFunction.calculate(number, fromUnit, toUnit); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Units represent different quantities', () => { + const number = NumberValueObject.create(2.5); + const fromUnit = StringValueObject.create('ft'); + const toUnit = StringValueObject.create('sec'); + const result = testFunction.calculate(number, fromUnit, toUnit); + expect(result.getValue()).toBe(ErrorType.NA); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const fromUnit = StringValueObject.create('lbm'); + const toUnit = StringValueObject.create('kg'); + const result = testFunction.calculate(number, fromUnit, toUnit); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/convert/index.ts b/packages/engine-formula/src/functions/engineering/convert/index.ts new file mode 100644 index 00000000000..4376fdf2b09 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/convert/index.ts @@ -0,0 +1,479 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { checkVariantsErrorIsArrayOrBoolean } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; + +type IUnitItem = Array | number | boolean | null>; + +interface IPrefixesKey { + [index: string]: Array; +} + +export class Convert extends BaseFunction { + override minParams = 3; + + override maxParams = 3; + + override calculate(number: BaseValueObject, fromUnit: BaseValueObject, toUnit: BaseValueObject) { + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(number, fromUnit, toUnit); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [numberObject, fromUnitObject, toUnitObject] = variants as BaseValueObject[]; + + const numberValue = +numberObject.getValue(); + const fromUnitValue = `${fromUnitObject.getValue()}`; + const toUnitValue = `${toUnitObject.getValue()}`; + + if (Number.isNaN(numberValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + // Initialize units and multipliers + let from: IUnitItem | null; + let fromMultiplier = 1; + + let to: IUnitItem | null; + let toMultiplier = 1; + + // Lookup from and to units + const { _from, _to } = this._lookupFromAndToUnits(fromUnitValue, toUnitValue); + + from = _from; + to = _to; + + // Lookup from prefix + if (from === null) { + const { _from, _fromMultiplier } = this._lookupFromPrefix(fromUnitValue); + from = _from; + fromMultiplier = _fromMultiplier; + } + + // Lookup to prefix + if (to === null) { + const { _to, _toMultiplier } = this._lookupToPrefix(toUnitValue); + to = _to; + toMultiplier = _toMultiplier; + } + + // Return error if a unit does not exist + if (from === null || to === null) { + return ErrorValueObject.create(ErrorType.NA); + } + + // Return error if units represent different quantities + if (from[3] !== to[3]) { + return ErrorValueObject.create(ErrorType.NA); + } + + let result; + + if (from[3] === 'temperature') { + result = this._getTemperatureConversion(numberValue, from[1] as string, to[1] as string); + } else { + result = (numberValue * (from[6] as number) * fromMultiplier) / ((to[6] as number) * toMultiplier); + } + + return NumberValueObject.create(result); + } + + private _lookupFromAndToUnits(fromUnitValue: string, toUnitValue: string) { + let _from = null; + let _to = null; + let alt; + + for (let i = 0; i < this._units.length; i++) { + alt = this._units[i][2] === null ? [] : this._units[i][2]; + + if (this._units[i][1] === fromUnitValue || (alt as Array).indexOf(fromUnitValue) >= 0) { + _from = this._units[i]; + } + + if (this._units[i][1] === toUnitValue || (alt as Array).indexOf(toUnitValue) >= 0) { + _to = this._units[i]; + } + } + + return { + _from, + _to, + }; + } + + private _lookupFromPrefix(fromUnitValue: string) { + let _from = null; + let _fromMultiplier = 1; + let baseFromUnit = fromUnitValue; + let alt; + + const fromBinaryPrefix = this._binaryPrefixes[fromUnitValue.substring(0, 2)]; + let fromUnitPrefix = this._unitPrefixes[fromUnitValue.substring(0, 1)]; + + // Handle dekao unit prefix (only unit prefix with two characters) + if (fromUnitValue.substring(0, 2) === 'da') { + fromUnitPrefix = ['dekao', 1e1, 'da']; + } + + // Handle binary prefixes first (so that 'Yi' is processed before 'Y') + if (fromBinaryPrefix) { + _fromMultiplier = fromBinaryPrefix[2] as number; + baseFromUnit = fromUnitValue.substring(2); + } else if (fromUnitPrefix) { + _fromMultiplier = fromUnitPrefix[1] as number; + baseFromUnit = fromUnitValue.substring((fromUnitPrefix[2] as string).length); + } + + // Lookup from unit + for (let j = 0; j < this._units.length; j++) { + alt = this._units[j][2] === null ? [] : this._units[j][2]; + + if (this._units[j][1] === baseFromUnit || (alt as Array).indexOf(baseFromUnit) >= 0) { + _from = this._units[j]; + } + } + + return { + _from, + _fromMultiplier, + }; + } + + private _lookupToPrefix(toUnitValue: string) { + let _to = null; + let _toMultiplier = 1; + let baseToUnit = toUnitValue; + let alt; + + const toBinaryPrefix = this._binaryPrefixes[toUnitValue.substring(0, 2)]; + let toUnitPrefix = this._unitPrefixes[toUnitValue.substring(0, 1)]; + + // Handle dekao unit prefix (only unit prefix with two characters) + if (toUnitValue.substring(0, 2) === 'da') { + toUnitPrefix = ['dekao', 1e1, 'da']; + } + + // Handle binary prefixes first (so that 'Yi' is processed before 'Y') + if (toBinaryPrefix) { + _toMultiplier = toBinaryPrefix[2] as number; + baseToUnit = toUnitValue.substring(2); + } else if (toUnitPrefix) { + _toMultiplier = toUnitPrefix[1] as number; + baseToUnit = toUnitValue.substring((toUnitPrefix[2] as string).length); + } + + // Lookup to unit + for (let k = 0; k < this._units.length; k++) { + alt = this._units[k][2] === null ? [] : this._units[k][2]; + + if (this._units[k][1] === baseToUnit || (alt as Array).indexOf(baseToUnit) >= 0) { + _to = this._units[k]; + } + } + + return { + _to, + _toMultiplier, + }; + } + + private _getTemperatureConversion(number: number, from: string, to: string) { + switch (from) { + case 'C': + return this._centigradeConversion(number, to); + case 'F': + return this._fahrenheitConversion(number, to); + case 'K': + return this._kelvinConversion(number, to); + case 'Rank': + return this._rankineConversion(number, to); + case 'Reau': + return this._reaumurConversion(number, to); + default: + return number; + } + } + + private _centigradeConversion(number: number, to: string) { + switch (to) { + case 'F': + return (number * 9 / 5) + 32; + case 'K': + return number + 273.15; + case 'Rank': + return (number + 273.15) * 9 / 5; + case 'Reau': + return number * 4 / 5; + default: + return number; + } + } + + private _fahrenheitConversion(number: number, to: string) { + switch (to) { + case 'C': + return (number - 32) * 5 / 9; + case 'K': + return (number - 32) * 5 / 9 + 273.15; + case 'Rank': + return number + 459.67; + case 'Reau': + return (number - 32) * 4 / 9; + default: + return number; + } + } + + private _kelvinConversion(number: number, to: string) { + switch (to) { + case 'C': + return number - 273.15; + case 'F': + return (number - 273.15) * 9 / 5 + 32; + case 'Rank': + return number * 9 / 5; + case 'Reau': + return (number - 273.15) * 4 / 5; + default: + return number; + } + } + + private _rankineConversion(number: number, to: string) { + switch (to) { + case 'C': + return (number - 491.67) * 5 / 9; + case 'F': + return number - 459.67; + case 'K': + return number * 5 / 9; + case 'Reau': + return (number - 491.67) * 4 / 9; + default: + return number; + } + } + + private _reaumurConversion(number: number, to: string) { + switch (to) { + case 'C': + return number * 5 / 4; + case 'F': + return (number * 9 / 4) + 32; + case 'K': + return (number * 5 / 4) + 273.15; + case 'Rank': + return (number * 9 / 4) + 491.67; + default: + return number; + } + } + + // List of units supported by CONVERT and units defined by the International System of Units + // [Name, Symbol, Alternate symbols, Quantity, ISU, CONVERT, Conversion ratio] + private _units: Array = [ + ['a.u. of action', '?', null, 'action', false, false, 1.05457168181818e-34], + ['a.u. of charge', 'e', null, 'electric_charge', false, false, 1.60217653141414e-19], + ['a.u. of energy', 'Eh', null, 'energy', false, false, 4.35974417757576e-18], + ['a.u. of length', 'a?', null, 'length', false, false, 5.29177210818182e-11], + ['a.u. of mass', 'm?', null, 'mass', false, false, 9.10938261616162e-31], + ['a.u. of time', '?/Eh', null, 'time', false, false, 2.41888432650516e-17], + ['admiralty knot', 'admkn', null, 'speed', false, true, 0.514773333], + ['ampere', 'A', null, 'electric_current', true, false, 1], + ['ampere per meter', 'A/m', null, 'magnetic_field_intensity', true, false, 1], + ['ångström', 'Å', ['ang'], 'length', false, true, 1e-10], + ['are', 'ar', null, 'area', false, true, 100], + ['astronomical unit', 'ua', null, 'length', false, false, 1.49597870691667e-11], + ['bar', 'bar', null, 'pressure', false, false, 100000], + ['barn', 'b', null, 'area', false, false, 1e-28], + ['becquerel', 'Bq', null, 'radioactivity', true, false, 1], + ['bit', 'bit', ['b'], 'information', false, true, 1], + ['btu', 'BTU', ['btu'], 'energy', false, true, 1055.05585262], + ['byte', 'byte', null, 'information', false, true, 8], + ['candela', 'cd', null, 'luminous_intensity', true, false, 1], + ['candela per square metre', 'cd/m?', null, 'luminance', true, false, 1], + ['centigrade', 'C', ['cel'], 'temperature', true, false, 1], + ['cubic ångström', 'ang3', ['ang^3'], 'volume', false, true, 1e-30], + ['cubic foot', 'ft3', ['ft^3'], 'volume', false, true, 0.028316846592], + ['cubic inch', 'in3', ['in^3'], 'volume', false, true, 0.000016387064], + ['cubic light-year', 'ly3', ['ly^3'], 'volume', false, true, 8.46786664623715e-47], + ['cubic metre', 'm3', ['m^3'], 'volume', true, true, 1], + ['cubic mile', 'mi3', ['mi^3'], 'volume', false, true, 4168181825.44058], + ['cubic nautical mile', 'Nmi3', ['Nmi^3'], 'volume', false, true, 6352182208], + ['cubic Pica', 'Pica3', ['Picapt3', 'Pica^3', 'Picapt^3'], 'volume', false, true, 7.58660370370369e-8], + ['cubic yard', 'yd3', ['yd^3'], 'volume', false, true, 0.764554857984], + ['cup', 'cup', null, 'volume', false, true, 0.0002365882365], + ['dalton', 'Da', ['u'], 'mass', false, false, 1.66053886282828e-27], + ['day', 'd', ['day'], 'time', false, true, 86400], + ['degree', '°', null, 'angle', false, false, 0.0174532925199433], + ['dyne', 'dyn', ['dy'], 'force', false, true, 0.00001], + ['electronvolt', 'eV', ['ev'], 'energy', false, true, 1.60217656514141], + ['ell', 'ell', null, 'length', false, true, 1.143], + ['erg', 'erg', ['e'], 'energy', false, true, 1e-7], + ['fahrenheit', 'F', ['fah'], 'temperature', true, false, 1], + ['fluid ounce', 'oz', null, 'volume', false, true, 0.0000295735295625], + ['foot', 'ft', null, 'length', false, true, 0.3048], + ['foot-pound', 'flb', null, 'energy', false, true, 1.3558179483314], + ['gal', 'Gal', null, 'acceleration', false, false, 0.01], + ['gallon', 'gal', null, 'volume', false, true, 0.003785411784], + ['gauss', 'G', ['ga'], 'magnetic_flux_density', false, true, 1], + ['grain', 'grain', null, 'mass', false, true, 0.0000647989], + ['gram', 'g', null, 'mass', false, true, 0.001], + ['gray', 'Gy', null, 'absorbed_dose', true, false, 1], + ['gross registered ton', 'GRT', ['regton'], 'volume', false, true, 2.8316846592], + ['hectare', 'ha', null, 'area', false, true, 10000], + ['henry', 'H', null, 'inductance', true, false, 1], + ['hertz', 'Hz', null, 'frequency', true, false, 1], + ['horsepower', 'HP', ['h'], 'power', false, true, 745.69987158227], + ['horsepower-hour', 'HPh', ['hh', 'hph'], 'energy', false, true, 2684519.538], + ['hour', 'h', ['hr'], 'time', false, true, 3600], + ['imperial gallon (U.K.)', 'uk_gal', null, 'volume', false, true, 0.00454609], + ['imperial hundredweight', 'lcwt', ['uk_cwt', 'hweight'], 'mass', false, true, 50.802345], + ['imperial quart (U.K)', 'uk_qt', null, 'volume', false, true, 0.0011365225], + ['imperial ton', 'brton', ['uk_ton', 'LTON'], 'mass', false, true, 1016.046909], + ['inch', 'in', null, 'length', false, true, 0.0254], + ['international acre', 'uk_acre', null, 'area', false, true, 4046.8564224], + ['IT calorie', 'cal', null, 'energy', false, true, 4.1868], + ['joule', 'J', null, 'energy', true, true, 1], + ['katal', 'kat', null, 'catalytic_activity', true, false, 1], + ['kelvin', 'K', ['kel'], 'temperature', true, true, 1], + ['kilogram', 'kg', null, 'mass', true, true, 1], + ['knot', 'kn', null, 'speed', false, true, 0.514444444444444], + ['light-year', 'ly', null, 'length', false, true, 9460730472580800], + ['litre', 'L', ['l', 'lt'], 'volume', false, true, 0.001], + ['lumen', 'lm', null, 'luminous_flux', true, false, 1], + ['lux', 'lx', null, 'illuminance', true, false, 1], + ['maxwell', 'Mx', null, 'magnetic_flux', false, false, 1e-18], + ['measurement ton', 'MTON', null, 'volume', false, true, 1.13267386368], + ['meter per hour', 'm/h', ['m/hr'], 'speed', false, true, 0.00027777777777778], + ['meter per second', 'm/s', ['m/sec'], 'speed', true, true, 1], + ['meter per second squared', 'm?s??', null, 'acceleration', true, false, 1], + ['parsec', 'pc', ['parsec'], 'length', false, true, 30856775814671900], + ['meter squared per second', 'm?/s', null, 'kinematic_viscosity', true, false, 1], + ['metre', 'm', null, 'length', true, true, 1], + ['miles per hour', 'mph', null, 'speed', false, true, 0.44704], + ['millimetre of mercury', 'mmHg', null, 'pressure', false, false, 133.322], + ['minute', '?', null, 'angle', false, false, 0.000290888208665722], + ['minute', 'min', ['mn'], 'time', false, true, 60], + ['modern teaspoon', 'tspm', null, 'volume', false, true, 0.000005], + ['mole', 'mol', null, 'amount_of_substance', true, false, 1], + ['morgen', 'Morgen', null, 'area', false, true, 2500], + ['n.u. of action', '?', null, 'action', false, false, 1.05457168181818e-34], + ['n.u. of mass', 'm?', null, 'mass', false, false, 9.10938261616162e-31], + ['n.u. of speed', 'c?', null, 'speed', false, false, 299792458], + ['n.u. of time', '?/(me?c??)', null, 'time', false, false, 1.28808866778687e-21], + ['nautical mile', 'M', ['Nmi'], 'length', false, true, 1852], + ['newton', 'N', null, 'force', true, true, 1], + ['œrsted', 'Oe ', null, 'magnetic_field_intensity', false, false, 79.5774715459477], + ['ohm', 'Ω', null, 'electric_resistance', true, false, 1], + ['ounce mass', 'ozm', null, 'mass', false, true, 0.028349523125], + ['pascal', 'Pa', null, 'pressure', true, false, 1], + ['pascal second', 'Pa?s', null, 'dynamic_viscosity', true, false, 1], + ['pferdestärke', 'PS', null, 'power', false, true, 735.49875], + ['phot', 'ph', null, 'illuminance', false, false, 0.0001], + ['pica (1/6 inch)', 'pica', null, 'length', false, true, 0.00035277777777778], + ['pica (1/72 inch)', 'Pica', ['Picapt'], 'length', false, true, 0.00423333333333333], + ['poise', 'P', null, 'dynamic_viscosity', false, false, 0.1], + ['pond', 'pond', null, 'force', false, true, 0.00980665], + ['pound force', 'lbf', null, 'force', false, true, 4.4482216152605], + ['pound mass', 'lbm', null, 'mass', false, true, 0.45359237], + ['quart', 'qt', null, 'volume', false, true, 0.000946352946], + ['radian', 'rad', null, 'angle', true, false, 1], + ['rankine', 'Rank', null, 'temperature', false, true, 1], + ['reaumur', 'Reau', null, 'temperature', false, true, 1], + ['second', '?', null, 'angle', false, false, 0.00000484813681109536], + ['second', 's', ['sec'], 'time', true, true, 1], + ['short hundredweight', 'cwt', ['shweight'], 'mass', false, true, 45.359237], + ['siemens', 'S', null, 'electrical_conductance', true, false, 1], + ['sievert', 'Sv', null, 'equivalent_dose', true, false, 1], + ['slug', 'sg', null, 'mass', false, true, 14.59390294], + ['square ångström', 'ang2', ['ang^2'], 'area', false, true, 1e-20], + ['square foot', 'ft2', ['ft^2'], 'area', false, true, 0.09290304], + ['square inch', 'in2', ['in^2'], 'area', false, true, 0.00064516], + ['square light-year', 'ly2', ['ly^2'], 'area', false, true, 8.95054210748189e31], + ['square meter', 'm?', null, 'area', true, true, 1], + ['square mile', 'mi2', ['mi^2'], 'area', false, true, 2589988.110336], + ['square nautical mile', 'Nmi2', ['Nmi^2'], 'area', false, true, 3429904], + ['square Pica', 'Pica2', ['Picapt2', 'Pica^2', 'Picapt^2'], 'area', false, true, 0.00001792111111111], + ['square yard', 'yd2', ['yd^2'], 'area', false, true, 0.83612736], + ['statute mile', 'mi', null, 'length', false, true, 1609.344], + ['steradian', 'sr', null, 'solid_angle', true, false, 1], + ['stilb', 'sb', null, 'luminance', false, false, 0.0001], + ['stokes', 'St', null, 'kinematic_viscosity', false, false, 0.0001], + ['stone', 'stone', null, 'mass', false, true, 6.35029318], + ['tablespoon', 'tbs', null, 'volume', false, true, 0.0000147868], + ['teaspoon', 'tsp', null, 'volume', false, true, 0.00000492892], + ['tesla', 'T', null, 'magnetic_flux_density', true, true, 1], + ['thermodynamic calorie', 'c', null, 'energy', false, true, 4.184], + ['ton', 'ton', null, 'mass', false, true, 907.18474], + ['tonne', 't', null, 'mass', false, false, 1000], + ['U.K. pint', 'uk_pt', null, 'volume', false, true, 0.00056826125], + ['U.S. bushel', 'bushel', null, 'volume', false, true, 0.03523907], + ['U.S. oil barrel', 'barrel', null, 'volume', false, true, 0.158987295], + ['U.S. pint', 'pt', ['us_pt'], 'volume', false, true, 0.000473176473], + ['U.S. survey mile', 'survey_mi', null, 'length', false, true, 1609.347219], + ['U.S. survey/statute acre', 'us_acre', null, 'area', false, true, 4046.87261], + ['volt', 'V', null, 'voltage', true, false, 1], + ['watt', 'W', null, 'power', true, true, 1], + ['watt-hour', 'Wh', ['wh'], 'energy', false, true, 3600], + ['weber', 'Wb', null, 'magnetic_flux', true, false, 1], + ['yard', 'yd', null, 'length', false, true, 0.9144], + ['year', 'yr', null, 'time', false, true, 31557600], + ]; + + // Binary prefixes + // [Name, Prefix power of 2 value, Previx value, Abbreviation, Derived from] + private _binaryPrefixes: IPrefixesKey = { + Yi: ['yobi', 80, 1208925819614629174706176, 'Yi', 'yotta'], + Zi: ['zebi', 70, 1180591620717411303424, 'Zi', 'zetta'], + Ei: ['exbi', 60, 1152921504606846976, 'Ei', 'exa'], + Pi: ['pebi', 50, 1125899906842624, 'Pi', 'peta'], + Ti: ['tebi', 40, 1099511627776, 'Ti', 'tera'], + Gi: ['gibi', 30, 1073741824, 'Gi', 'giga'], + Mi: ['mebi', 20, 1048576, 'Mi', 'mega'], + ki: ['kibi', 10, 1024, 'ki', 'kilo'], + }; + + // Unit prefixes + // [Name, Multiplier, Abbreviation] + private _unitPrefixes: IPrefixesKey = { + Y: ['yotta', 1e24, 'Y'], + Z: ['zetta', 1e21, 'Z'], + E: ['exa', 1e18, 'E'], + P: ['peta', 1e15, 'P'], + T: ['tera', 1e12, 'T'], + G: ['giga', 1e9, 'G'], + M: ['mega', 1e6, 'M'], + k: ['kilo', 1e3, 'k'], + h: ['hecto', 1e2, 'h'], + e: ['dekao', 1e1, 'e'], + d: ['deci', 1e-1, 'd'], + c: ['centi', 1e-2, 'c'], + m: ['milli', 1e-3, 'm'], + u: ['micro', 1e-6, 'u'], + n: ['nano', 1e-9, 'n'], + p: ['pico', 1e-12, 'p'], + f: ['femto', 1e-15, 'f'], + a: ['atto', 1e-18, 'a'], + z: ['zepto', 1e-21, 'z'], + y: ['yocto', 1e-24, 'y'], + }; +} diff --git a/packages/engine-formula/src/functions/engineering/dec2bin/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/dec2bin/__tests__/index.spec.ts new file mode 100644 index 00000000000..7a0ee830542 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/dec2bin/__tests__/index.spec.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Dec2bin } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test dec2bin function', () => { + const testFunction = new Dec2bin(FUNCTION_NAMES_ENGINEERING.DEC2BIN); + + describe('Dec2bin', () => { + it('Value is normal number', () => { + const number = NumberValueObject.create(9); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('1001'); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('-0.5'); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('0000'); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is null', () => { + const number = NullValueObject.create(); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NA); + }); + + it('Value is blank cell', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [null], + ]), + rowCount: 1, + columnCount: 1, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('0000'); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/dec2bin/index.ts b/packages/engine-formula/src/functions/engineering/dec2bin/index.ts new file mode 100644 index 00000000000..b87b0257d0c --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/dec2bin/index.ts @@ -0,0 +1,95 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { checkVariantsErrorIsArrayOrBoolean } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { StringValueObject } from '../../../engine/value-object/primitive-object'; + +export class Dec2bin extends BaseFunction { + override minParams = 1; + + override maxParams = 2; + + override calculate(number: BaseValueObject, places?: BaseValueObject) { + if (number.isNull()) { + return ErrorValueObject.create(ErrorType.NA); + } + + let placesValue = 0; + + if (places) { + // If places exists, it is prioritized. + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(places); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [placesObject] = variants as BaseValueObject[]; + + placesValue = Math.floor(+placesObject.getValue()); + + if (Number.isNaN(placesValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + if (placesValue < 0 || placesValue > 10) { + return ErrorValueObject.create(ErrorType.NUM); + } + } + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(number); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [numberObject] = variants as BaseValueObject[]; + + const numberValue = Math.trunc(+numberObject.getValue()); + + if (Number.isNaN(numberValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + // Return error if number is not decimal, is lower than -512, or is greater than 511 + if (!/^-?[0-9]{1,3}$/.test(`${numberValue}`) || numberValue < -512 || numberValue > 511) { + return ErrorValueObject.create(ErrorType.NUM); + } + + let result; + + if (numberValue < 0) { + const toStr = (512 + numberValue).toString(2); + + result = `1${'0'.repeat(9 - toStr.length)}${toStr}`; + } else { + result = Number.parseInt(`${numberValue}`, 10).toString(2); + + if (places) { + if (placesValue < result.length) { + return ErrorValueObject.create(ErrorType.NUM); + } + + result = '0'.repeat(placesValue - result.length) + result; + } + } + + return StringValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/dec2hex/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/dec2hex/__tests__/index.spec.ts new file mode 100644 index 00000000000..6d9ffae5b27 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/dec2hex/__tests__/index.spec.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Dec2hex } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test dec2hex function', () => { + const testFunction = new Dec2hex(FUNCTION_NAMES_ENGINEERING.DEC2HEX); + + describe('Dec2hex', () => { + it('Value is normal number', () => { + const number = NumberValueObject.create(100); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('0064'); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('-0.5'); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('0000'); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is null', () => { + const number = NullValueObject.create(); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NA); + }); + + it('Value is blank cell', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [null], + ]), + rowCount: 1, + columnCount: 1, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('0000'); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/dec2hex/index.ts b/packages/engine-formula/src/functions/engineering/dec2hex/index.ts new file mode 100644 index 00000000000..511d4af70aa --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/dec2hex/index.ts @@ -0,0 +1,93 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { checkVariantsErrorIsArrayOrBoolean } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { StringValueObject } from '../../../engine/value-object/primitive-object'; + +export class Dec2hex extends BaseFunction { + override minParams = 1; + + override maxParams = 2; + + override calculate(number: BaseValueObject, places?: BaseValueObject) { + if (number.isNull()) { + return ErrorValueObject.create(ErrorType.NA); + } + + let placesValue = 0; + + if (places) { + // If places exists, it is prioritized. + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(places); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [placesObject] = variants as BaseValueObject[]; + + placesValue = Math.floor(+placesObject.getValue()); + + if (Number.isNaN(placesValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + if (placesValue < 0 || placesValue > 10) { + return ErrorValueObject.create(ErrorType.NUM); + } + } + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(number); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [numberObject] = variants as BaseValueObject[]; + + const numberValue = Math.trunc(+numberObject.getValue()); + + if (Number.isNaN(numberValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + // Return error if number is not decimal, is lower than -549755813888, or is greater than 549755813887 + if (!/^-?[0-9]{1,12}$/.test(`${numberValue}`) || numberValue < -549755813888 || numberValue > 549755813887) { + return ErrorValueObject.create(ErrorType.NUM); + } + + let result; + + if (numberValue < 0) { + result = (1099511627776 + numberValue).toString(16); + } else { + result = Number.parseInt(`${numberValue}`, 10).toString(16); + + if (places) { + if (placesValue < result.length) { + return ErrorValueObject.create(ErrorType.NUM); + } + + result = '0'.repeat(placesValue - result.length) + result; + } + } + + return StringValueObject.create(result.toLocaleUpperCase()); + } +} diff --git a/packages/engine-formula/src/functions/engineering/dec2oct/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/dec2oct/__tests__/index.spec.ts new file mode 100644 index 00000000000..e6a405aeffa --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/dec2oct/__tests__/index.spec.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Dec2oct } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test Dec2oct function', () => { + const testFunction = new Dec2oct(FUNCTION_NAMES_ENGINEERING.DEC2OCT); + + describe('Dec2oct', () => { + it('Value is normal number', () => { + const number = NumberValueObject.create(58); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('072'); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('-0.5'); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('000'); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is null', () => { + const number = NullValueObject.create(); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NA); + }); + + it('Value is blank cell', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [null], + ]), + rowCount: 1, + columnCount: 1, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('000'); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/dec2oct/index.ts b/packages/engine-formula/src/functions/engineering/dec2oct/index.ts new file mode 100644 index 00000000000..6fa43bfa24c --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/dec2oct/index.ts @@ -0,0 +1,93 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { checkVariantsErrorIsArrayOrBoolean } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { StringValueObject } from '../../../engine/value-object/primitive-object'; + +export class Dec2oct extends BaseFunction { + override minParams = 1; + + override maxParams = 2; + + override calculate(number: BaseValueObject, places?: BaseValueObject) { + if (number.isNull()) { + return ErrorValueObject.create(ErrorType.NA); + } + + let placesValue = 0; + + if (places) { + // If places exists, it is prioritized. + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(places); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [placesObject] = variants as BaseValueObject[]; + + placesValue = Math.floor(+placesObject.getValue()); + + if (Number.isNaN(placesValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + if (placesValue < 0 || placesValue > 10) { + return ErrorValueObject.create(ErrorType.NUM); + } + } + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(number); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [numberObject] = variants as BaseValueObject[]; + + const numberValue = Math.trunc(+numberObject.getValue()); + + if (Number.isNaN(numberValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + // Return error if number is not decimal, is lower than -536870912, or is greater than 536870911 + if (!/^-?[0-9]{1,9}$/.test(`${numberValue}`) || numberValue < -536870912 || numberValue > 536870911) { + return ErrorValueObject.create(ErrorType.NUM); + } + + let result; + + if (numberValue < 0) { + result = (1073741824 + numberValue).toString(8); + } else { + result = Number.parseInt(`${numberValue}`, 10).toString(8); + + if (places) { + if (placesValue < result.length) { + return ErrorValueObject.create(ErrorType.NUM); + } + + result = '0'.repeat(placesValue - result.length) + result; + } + } + + return StringValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/delta/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/delta/__tests__/index.spec.ts new file mode 100644 index 00000000000..59b07ada7d7 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/delta/__tests__/index.spec.ts @@ -0,0 +1,90 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Delta } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test delta function', () => { + const testFunction = new Delta(FUNCTION_NAMES_ENGINEERING.DELTA); + + describe('Delta', () => { + it('Value is normal number', () => { + const number1 = NumberValueObject.create(5); + const number2 = NumberValueObject.create(4); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(0); + }); + + it('Value is number string', () => { + const number1 = StringValueObject.create('1'); + const number2 = NumberValueObject.create(4); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(0); + }); + + it('Value is normal string', () => { + const number1 = StringValueObject.create('test'); + const number2 = NumberValueObject.create(4); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const number1 = BooleanValueObject.create(true); + const number2 = NumberValueObject.create(4); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is blank cell', () => { + const number1 = NullValueObject.create(); + const number2 = NumberValueObject.create(4); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(0); + }); + + it('Value is error', () => { + const number1 = ErrorValueObject.create(ErrorType.NAME); + const number2 = NumberValueObject.create(4); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number1 = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const number2 = NumberValueObject.create(4); + const result = testFunction.calculate(number1, number2); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/delta/index.ts b/packages/engine-formula/src/functions/engineering/delta/index.ts new file mode 100644 index 00000000000..99de46ec915 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/delta/index.ts @@ -0,0 +1,50 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; +import { checkVariantsErrorIsArrayOrBoolean } from '../../../basics/engineering'; + +export class Delta extends BaseFunction { + override minParams = 1; + + override maxParams = 2; + + override calculate(number1: BaseValueObject, number2?: BaseValueObject) { + const _number2 = number2 ?? NumberValueObject.create(0); + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(number1, _number2); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [number1Object, number2Object] = variants as BaseValueObject[]; + + const number1Value = +number1Object.getValue(); + const number2Value = +number2Object.getValue(); + + if (Number.isNaN(number1Value) || Number.isNaN(number2Value)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + const result = number1Value === number2Value ? 1 : 0; + + return NumberValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/erf-precise/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/erf-precise/__tests__/index.spec.ts new file mode 100644 index 00000000000..f7e95061bb9 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/erf-precise/__tests__/index.spec.ts @@ -0,0 +1,83 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { ErfPrecise } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test erf.precise function', () => { + const testFunction = new ErfPrecise(FUNCTION_NAMES_ENGINEERING.ERF_PRECISE); + + describe('ErfPrecise', () => { + it('Value is normal number', () => { + const x = NumberValueObject.create(1); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(0.8427007929497149); + }); + + it('Value is number string', () => { + const x = StringValueObject.create('1.5'); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(0.9661051464753108); + }); + + it('Value is normal string', () => { + const x = StringValueObject.create('test'); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const x = BooleanValueObject.create(true); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is blank cell', () => { + const x = NullValueObject.create(); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(0); + }); + + it('Value is error', () => { + const x = ErrorValueObject.create(ErrorType.NAME); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const x = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const result = testFunction.calculate(x); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/erf-precise/index.ts b/packages/engine-formula/src/functions/engineering/erf-precise/index.ts new file mode 100644 index 00000000000..75eb0ed2c50 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/erf-precise/index.ts @@ -0,0 +1,47 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; +import { checkVariantsErrorIsArrayOrBoolean, erf } from '../../../basics/engineering'; + +export class ErfPrecise extends BaseFunction { + override minParams = 1; + + override maxParams = 1; + + override calculate(x: BaseValueObject) { + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(x); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [xObject] = variants as BaseValueObject[]; + + const xValue = +xObject.getValue(); + + if (Number.isNaN(xValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + const result = erf(xValue); + + return NumberValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/erf/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/erf/__tests__/index.spec.ts new file mode 100644 index 00000000000..f273f5f6d36 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/erf/__tests__/index.spec.ts @@ -0,0 +1,87 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Erf } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test erf function', () => { + const testFunction = new Erf(FUNCTION_NAMES_ENGINEERING.ERF); + + describe('Erf', () => { + it('Value is normal number', () => { + const lowerLimit = NumberValueObject.create(1); + const result = testFunction.calculate(lowerLimit); + expect(result.getValue()).toBe(0.8427007929497149); + + const upperLimit = NumberValueObject.create(4); + const result2 = testFunction.calculate(lowerLimit, upperLimit); + expect(result2.getValue()).toBe(0.1572991916330272); + }); + + it('Value is number string', () => { + const lowerLimit = StringValueObject.create('1.5'); + const result = testFunction.calculate(lowerLimit); + expect(result.getValue()).toBe(0.9661051464753108); + }); + + it('Value is normal string', () => { + const lowerLimit = StringValueObject.create('test'); + const result = testFunction.calculate(lowerLimit); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const lowerLimit = BooleanValueObject.create(true); + const result = testFunction.calculate(lowerLimit); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is blank cell', () => { + const lowerLimit = NullValueObject.create(); + const result = testFunction.calculate(lowerLimit); + expect(result.getValue()).toBe(0); + }); + + it('Value is error', () => { + const lowerLimit = ErrorValueObject.create(ErrorType.NAME); + const result = testFunction.calculate(lowerLimit); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const lowerLimit = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const result = testFunction.calculate(lowerLimit); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/erf/index.ts b/packages/engine-formula/src/functions/engineering/erf/index.ts new file mode 100644 index 00000000000..2a0095d7727 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/erf/index.ts @@ -0,0 +1,68 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; +import { checkVariantsErrorIsArrayOrBoolean, erf } from '../../../basics/engineering'; + +export class Erf extends BaseFunction { + override minParams = 1; + + override maxParams = 2; + + override calculate(lowerLimit: BaseValueObject, upperLimit?: BaseValueObject) { + let result; + + if (upperLimit) { + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(lowerLimit, upperLimit); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [lowerLimitObject, upperLimitObject] = variants as BaseValueObject[]; + + const lowerLimitValue = +lowerLimitObject.getValue(); + const upperLimitValue = +upperLimitObject.getValue(); + + if (Number.isNaN(lowerLimitValue) || Number.isNaN(upperLimitValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + result = erf(upperLimitValue) - erf(lowerLimitValue); + } else { + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(lowerLimit); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [lowerLimitObject] = variants as BaseValueObject[]; + + const lowerLimitValue = +lowerLimitObject.getValue(); + + if (Number.isNaN(lowerLimitValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + result = erf(lowerLimitValue); + } + + return NumberValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/erfc-precise/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/erfc-precise/__tests__/index.spec.ts new file mode 100644 index 00000000000..4a9b4bfb385 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/erfc-precise/__tests__/index.spec.ts @@ -0,0 +1,83 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { ErfcPrecise } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test erfc.precise function', () => { + const testFunction = new ErfcPrecise(FUNCTION_NAMES_ENGINEERING.ERFC_PRECISE); + + describe('ErfcPrecise', () => { + it('Value is normal number', () => { + const x = NumberValueObject.create(1); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(0.1572992070502851); + }); + + it('Value is number string', () => { + const x = StringValueObject.create('1.5'); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(0.03389485352468924); + }); + + it('Value is normal string', () => { + const x = StringValueObject.create('test'); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const x = BooleanValueObject.create(true); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is blank cell', () => { + const x = NullValueObject.create(); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(1); + }); + + it('Value is error', () => { + const x = ErrorValueObject.create(ErrorType.NAME); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const x = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const result = testFunction.calculate(x); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/erfc-precise/index.ts b/packages/engine-formula/src/functions/engineering/erfc-precise/index.ts new file mode 100644 index 00000000000..a7b11233f6e --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/erfc-precise/index.ts @@ -0,0 +1,47 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; +import { checkVariantsErrorIsArrayOrBoolean, erf } from '../../../basics/engineering'; + +export class ErfcPrecise extends BaseFunction { + override minParams = 1; + + override maxParams = 1; + + override calculate(x: BaseValueObject) { + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(x); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [xObject] = variants as BaseValueObject[]; + + const xValue = +xObject.getValue(); + + if (Number.isNaN(xValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + const result = 1 - erf(xValue); + + return NumberValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/erfc/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/erfc/__tests__/index.spec.ts new file mode 100644 index 00000000000..f7073a99444 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/erfc/__tests__/index.spec.ts @@ -0,0 +1,83 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Erfc } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test erfc function', () => { + const testFunction = new Erfc(FUNCTION_NAMES_ENGINEERING.ERFC); + + describe('Erfc', () => { + it('Value is normal number', () => { + const x = NumberValueObject.create(1); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(0.1572992070502851); + }); + + it('Value is number string', () => { + const x = StringValueObject.create('1.5'); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(0.03389485352468924); + }); + + it('Value is normal string', () => { + const x = StringValueObject.create('test'); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is boolean', () => { + const x = BooleanValueObject.create(true); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is blank cell', () => { + const x = NullValueObject.create(); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(1); + }); + + it('Value is error', () => { + const x = ErrorValueObject.create(ErrorType.NAME); + const result = testFunction.calculate(x); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const x = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const result = testFunction.calculate(x); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/erfc/index.ts b/packages/engine-formula/src/functions/engineering/erfc/index.ts new file mode 100644 index 00000000000..4ddfa1cb693 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/erfc/index.ts @@ -0,0 +1,47 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; +import { checkVariantsErrorIsArrayOrBoolean, erf } from '../../../basics/engineering'; + +export class Erfc extends BaseFunction { + override minParams = 1; + + override maxParams = 1; + + override calculate(x: BaseValueObject) { + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(x); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [xObject] = variants as BaseValueObject[]; + + const xValue = +xObject.getValue(); + + if (Number.isNaN(xValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + const result = 1 - erf(xValue); + + return NumberValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/function-map.ts b/packages/engine-formula/src/functions/engineering/function-map.ts index 5e65e0ae5eb..305e711672e 100644 --- a/packages/engine-formula/src/functions/engineering/function-map.ts +++ b/packages/engine-formula/src/functions/engineering/function-map.ts @@ -14,4 +14,63 @@ * limitations under the License. */ -export const functionEngineering = []; +import { FUNCTION_NAMES_ENGINEERING } from './function-names'; +import { Besseli } from './besseli'; +import { Besselj } from './besselj'; +import { Besselk } from './besselk'; +import { Bessely } from './bessely'; +import { Bin2dec } from './bin2dec'; +import { Bin2hex } from './bin2hex'; +import { Bin2oct } from './bin2oct'; +import { Bitand } from './bitand'; +import { Bitlshift } from './bitlshift'; +import { Bitor } from './bitor'; +import { Bitrshift } from './bitrshift'; +import { Bitxor } from './bitxor'; +import { Complex } from './complex'; +import { Convert } from './convert'; +import { Dec2bin } from './dec2bin'; +import { Dec2hex } from './dec2hex'; +import { Dec2oct } from './dec2oct'; +import { Delta } from './delta'; +import { Erf } from './erf'; +import { ErfPrecise } from './erf-precise'; +import { Erfc } from './erfc'; +import { ErfcPrecise } from './erfc-precise'; +import { Hex2bin } from './hex2bin'; +import { Hex2dec } from './hex2dec'; +import { Hex2oct } from './hex2oct'; +import { Oct2bin } from './oct2bin'; +import { Oct2dec } from './oct2dec'; +import { Oct2hex } from './oct2hex'; + +export const functionEngineering = [ + [Besseli, FUNCTION_NAMES_ENGINEERING.BESSELI], + [Besselj, FUNCTION_NAMES_ENGINEERING.BESSELJ], + [Besselk, FUNCTION_NAMES_ENGINEERING.BESSELK], + [Bessely, FUNCTION_NAMES_ENGINEERING.BESSELY], + [Bin2dec, FUNCTION_NAMES_ENGINEERING.BIN2DEC], + [Bin2hex, FUNCTION_NAMES_ENGINEERING.BIN2HEX], + [Bin2oct, FUNCTION_NAMES_ENGINEERING.BIN2OCT], + [Bitand, FUNCTION_NAMES_ENGINEERING.BITAND], + [Bitlshift, FUNCTION_NAMES_ENGINEERING.BITLSHIFT], + [Bitor, FUNCTION_NAMES_ENGINEERING.BITOR], + [Bitrshift, FUNCTION_NAMES_ENGINEERING.BITRSHIFT], + [Bitxor, FUNCTION_NAMES_ENGINEERING.BITXOR], + [Complex, FUNCTION_NAMES_ENGINEERING.COMPLEX], + [Convert, FUNCTION_NAMES_ENGINEERING.CONVERT], + [Dec2bin, FUNCTION_NAMES_ENGINEERING.DEC2BIN], + [Dec2hex, FUNCTION_NAMES_ENGINEERING.DEC2HEX], + [Dec2oct, FUNCTION_NAMES_ENGINEERING.DEC2OCT], + [Delta, FUNCTION_NAMES_ENGINEERING.DELTA], + [Erf, FUNCTION_NAMES_ENGINEERING.ERF], + [ErfPrecise, FUNCTION_NAMES_ENGINEERING.ERF_PRECISE], + [Erfc, FUNCTION_NAMES_ENGINEERING.ERFC], + [ErfcPrecise, FUNCTION_NAMES_ENGINEERING.ERFC_PRECISE], + [Hex2bin, FUNCTION_NAMES_ENGINEERING.HEX2BIN], + [Hex2dec, FUNCTION_NAMES_ENGINEERING.HEX2DEC], + [Hex2oct, FUNCTION_NAMES_ENGINEERING.HEX2OCT], + [Oct2bin, FUNCTION_NAMES_ENGINEERING.OCT2BIN], + [Oct2dec, FUNCTION_NAMES_ENGINEERING.OCT2DEC], + [Oct2hex, FUNCTION_NAMES_ENGINEERING.OCT2HEX], +]; diff --git a/packages/engine-formula/src/functions/engineering/hex2bin/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/hex2bin/__tests__/index.spec.ts new file mode 100644 index 00000000000..2f15c66401c --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/hex2bin/__tests__/index.spec.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Hex2bin } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test hex2bin function', () => { + const testFunction = new Hex2bin(FUNCTION_NAMES_ENGINEERING.HEX2BIN); + + describe('Hex2bin', () => { + it('Value is normal number', () => { + const number = StringValueObject.create('F'); + const places = NumberValueObject.create(8); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('00001111'); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('-0.5'); + const places = NumberValueObject.create(8); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const places = NumberValueObject.create(8); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const places = NumberValueObject.create(8); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is null', () => { + const number = NullValueObject.create(); + const places = NumberValueObject.create(8); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NA); + }); + + it('Value is blank cell', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [null], + ]), + rowCount: 1, + columnCount: 1, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(8); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('00000000'); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const places = NumberValueObject.create(8); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(8); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/hex2bin/index.ts b/packages/engine-formula/src/functions/engineering/hex2bin/index.ts new file mode 100644 index 00000000000..0dcacc0155a --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/hex2bin/index.ts @@ -0,0 +1,102 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { checkVariantsErrorIsArrayOrBoolean, isValidHexadecimalNumber } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { StringValueObject } from '../../../engine/value-object/primitive-object'; + +export class Hex2bin extends BaseFunction { + override minParams = 1; + + override maxParams = 2; + + override calculate(number: BaseValueObject, places?: BaseValueObject) { + if (number.isNull()) { + return ErrorValueObject.create(ErrorType.NA); + } + + let placesValue = 0; + + if (places) { + // If places exists, it is prioritized. + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(places); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [placesObject] = variants as BaseValueObject[]; + + placesValue = Math.floor(+placesObject.getValue()); + + if (Number.isNaN(placesValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + if (placesValue < 0 || placesValue > 10) { + return ErrorValueObject.create(ErrorType.NUM); + } + } + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(number); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [numberObject] = variants as BaseValueObject[]; + + const numberValue = `${numberObject.getValue()}`; + + // Return error if number is not hexadecimal or contains more than ten characters (10 digits) + if (!isValidHexadecimalNumber(numberValue)) { + return ErrorValueObject.create(ErrorType.NUM); + } + + // Check if number is negative + const negative = !!(numberValue.length === 10 && numberValue.substring(0, 1).toLocaleUpperCase() === 'F'); + + // Convert hexadecimal number to decimal + const decimal = negative ? Number.parseInt(numberValue, 16) - 1099511627776 : Number.parseInt(numberValue, 16); + + // Return error if number is lower than -512 or greater than 511 + if (decimal < -512 || decimal > 511) { + return ErrorValueObject.create(ErrorType.NUM); + } + + let result; + + if (negative) { + const toStr = (512 + decimal).toString(2); + + result = `1${'0'.repeat(9 - toStr.length)}${toStr}`; + } else { + result = decimal.toString(2); + + if (places) { + if (placesValue < result.length) { + return ErrorValueObject.create(ErrorType.NUM); + } + + result = '0'.repeat(placesValue - result.length) + result; + } + } + + return StringValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/hex2dec/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/hex2dec/__tests__/index.spec.ts new file mode 100644 index 00000000000..5371ada73cd --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/hex2dec/__tests__/index.spec.ts @@ -0,0 +1,83 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Hex2dec } from '../index'; +import { BooleanValueObject, NullValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test hex2dec function', () => { + const testFunction = new Hex2dec(FUNCTION_NAMES_ENGINEERING.HEX2DEC); + + describe('Hex2dec', () => { + it('Value is normal number', () => { + const number = StringValueObject.create('A5'); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(165); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('-0.5'); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is blank cell', () => { + const number = NullValueObject.create(); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(0); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const result = testFunction.calculate(number); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/hex2dec/index.ts b/packages/engine-formula/src/functions/engineering/hex2dec/index.ts new file mode 100644 index 00000000000..126e8cb1153 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/hex2dec/index.ts @@ -0,0 +1,52 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { checkVariantsErrorIsArrayOrBoolean, isValidHexadecimalNumber } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; + +export class Hex2dec extends BaseFunction { + override minParams = 1; + + override maxParams = 1; + + override calculate(number: BaseValueObject) { + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(number); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [numberObject] = variants as BaseValueObject[]; + + const numberValue = `${numberObject.getValue()}`; + + // Return error if number is not hexadecimal or contains more than ten characters (10 digits) + if (!isValidHexadecimalNumber(numberValue)) { + return ErrorValueObject.create(ErrorType.NUM); + } + + let result = Number.parseInt(numberValue, 16); + + if (result >= 549755813888) { + result -= 1099511627776; + } + + return NumberValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/hex2oct/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/hex2oct/__tests__/index.spec.ts new file mode 100644 index 00000000000..b8c7fed236e --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/hex2oct/__tests__/index.spec.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Hex2oct } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test hex2oct function', () => { + const testFunction = new Hex2oct(FUNCTION_NAMES_ENGINEERING.HEX2OCT); + + describe('Hex2oct', () => { + it('Value is normal number', () => { + const number = StringValueObject.create('F'); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('017'); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('-0.5'); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is null', () => { + const number = NullValueObject.create(); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NA); + }); + + it('Value is blank cell', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [null], + ]), + rowCount: 1, + columnCount: 1, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('000'); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/hex2oct/index.ts b/packages/engine-formula/src/functions/engineering/hex2oct/index.ts new file mode 100644 index 00000000000..44765be4349 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/hex2oct/index.ts @@ -0,0 +1,97 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { checkVariantsErrorIsArrayOrBoolean, isValidHexadecimalNumber } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { StringValueObject } from '../../../engine/value-object/primitive-object'; + +export class Hex2oct extends BaseFunction { + override minParams = 1; + + override maxParams = 2; + + override calculate(number: BaseValueObject, places?: BaseValueObject) { + if (number.isNull()) { + return ErrorValueObject.create(ErrorType.NA); + } + + let placesValue = 0; + + if (places) { + // If places exists, it is prioritized. + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(places); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [placesObject] = variants as BaseValueObject[]; + + placesValue = Math.floor(+placesObject.getValue()); + + if (Number.isNaN(placesValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + if (placesValue < 0 || placesValue > 10) { + return ErrorValueObject.create(ErrorType.NUM); + } + } + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(number); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [numberObject] = variants as BaseValueObject[]; + + const numberValue = `${numberObject.getValue()}`; + + // Return error if number is not hexadecimal or contains more than ten characters (10 digits) + if (!isValidHexadecimalNumber(numberValue)) { + return ErrorValueObject.create(ErrorType.NUM); + } + + // Convert hexadecimal number to decimal + const decimal = Number.parseInt(numberValue, 16); + + // Return error if number is positive and greater than 0x1fffffff (536870911) + if (decimal > 536870911 && decimal < 1098974756864) { + return ErrorValueObject.create(ErrorType.NUM); + } + + let result; + + if (decimal >= 1098974756864) { + result = (decimal - 1098437885952).toString(8); + } else { + result = decimal.toString(8); + + if (places) { + if (placesValue < result.length) { + return ErrorValueObject.create(ErrorType.NUM); + } + + result = '0'.repeat(placesValue - result.length) + result; + } + } + + return StringValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/oct2bin/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/oct2bin/__tests__/index.spec.ts new file mode 100644 index 00000000000..c1bdd941a73 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/oct2bin/__tests__/index.spec.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Oct2bin } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test oct2bin function', () => { + const testFunction = new Oct2bin(FUNCTION_NAMES_ENGINEERING.OCT2BIN); + + describe('Oct2bin', () => { + it('Value is normal number', () => { + const number = NumberValueObject.create(3); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('011'); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('-0.5'); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is null', () => { + const number = NullValueObject.create(); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NA); + }); + + it('Value is blank cell', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [null], + ]), + rowCount: 1, + columnCount: 1, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('000'); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(3); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/oct2bin/index.ts b/packages/engine-formula/src/functions/engineering/oct2bin/index.ts new file mode 100644 index 00000000000..950592778c0 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/oct2bin/index.ts @@ -0,0 +1,102 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { checkVariantsErrorIsArrayOrBoolean, isValidOctalNumber } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { StringValueObject } from '../../../engine/value-object/primitive-object'; + +export class Oct2bin extends BaseFunction { + override minParams = 1; + + override maxParams = 2; + + override calculate(number: BaseValueObject, places?: BaseValueObject) { + if (number.isNull()) { + return ErrorValueObject.create(ErrorType.NA); + } + + let placesValue = 0; + + if (places) { + // If places exists, it is prioritized. + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(places); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [placesObject] = variants as BaseValueObject[]; + + placesValue = Math.floor(+placesObject.getValue()); + + if (Number.isNaN(placesValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + if (placesValue < 0 || placesValue > 10) { + return ErrorValueObject.create(ErrorType.NUM); + } + } + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(number); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [numberObject] = variants as BaseValueObject[]; + + const numberValue = `${numberObject.getValue()}`; + + // Return error if number is not octal or contains more than ten characters (10 digits) + if (!isValidOctalNumber(numberValue)) { + return ErrorValueObject.create(ErrorType.NUM); + } + + // Check if number is negative + const negative = !!(numberValue.length === 10 && numberValue.substring(0, 1) === '7'); + + // Convert octal number to decimal + const decimal = negative ? Number.parseInt(numberValue, 8) - 1073741824 : Number.parseInt(numberValue, 8); + + // Return error if number is lower than -512 or greater than 511 + if (decimal < -512 || decimal > 511) { + return ErrorValueObject.create(ErrorType.NUM); + } + + let result; + + if (negative) { + const toStr = (512 + decimal).toString(2); + + result = `1${'0'.repeat(9 - toStr.length)}${toStr}`; + } else { + result = decimal.toString(2); + + if (places) { + if (placesValue < result.length) { + return ErrorValueObject.create(ErrorType.NUM); + } + + result = '0'.repeat(placesValue - result.length) + result; + } + } + + return StringValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/oct2dec/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/oct2dec/__tests__/index.spec.ts new file mode 100644 index 00000000000..9d6939ccde8 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/oct2dec/__tests__/index.spec.ts @@ -0,0 +1,83 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Oct2dec } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test oct2dec function', () => { + const testFunction = new Oct2dec(FUNCTION_NAMES_ENGINEERING.OCT2DEC); + + describe('Oct2dec', () => { + it('Value is normal number', () => { + const number = NumberValueObject.create(54); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(44); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('-0.5'); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is blank cell', () => { + const number = NullValueObject.create(); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(0); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const result = testFunction.calculate(number); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const result = testFunction.calculate(number); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/oct2dec/index.ts b/packages/engine-formula/src/functions/engineering/oct2dec/index.ts new file mode 100644 index 00000000000..a3ebb42e24e --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/oct2dec/index.ts @@ -0,0 +1,52 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { checkVariantsErrorIsArrayOrBoolean, isValidOctalNumber } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { NumberValueObject } from '../../../engine/value-object/primitive-object'; + +export class Oct2dec extends BaseFunction { + override minParams = 1; + + override maxParams = 1; + + override calculate(number: BaseValueObject) { + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(number); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [numberObject] = variants as BaseValueObject[]; + + const numberValue = `${numberObject.getValue()}`; + + // Return error if number is not octal or contains more than ten characters (10 digits) + if (!isValidOctalNumber(numberValue)) { + return ErrorValueObject.create(ErrorType.NUM); + } + + let result = Number.parseInt(numberValue, 8); + + if (result >= 536870912) { + result -= 1073741824; + } + + return NumberValueObject.create(result); + } +} diff --git a/packages/engine-formula/src/functions/engineering/oct2hex/__tests__/index.spec.ts b/packages/engine-formula/src/functions/engineering/oct2hex/__tests__/index.spec.ts new file mode 100644 index 00000000000..715f2e50d15 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/oct2hex/__tests__/index.spec.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; + +import { FUNCTION_NAMES_ENGINEERING } from '../../function-names'; +import { Oct2hex } from '../index'; +import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object'; +import { ArrayValueObject, transformToValueObject } from '../../../../engine/value-object/array-value-object'; +import { ErrorType } from '../../../../basics/error-type'; +import { ErrorValueObject } from '../../../../engine/value-object/base-value-object'; + +describe('Test oct2hex function', () => { + const testFunction = new Oct2hex(FUNCTION_NAMES_ENGINEERING.OCT2HEX); + + describe('Oct2hex', () => { + it('Value is normal number', () => { + const number = NumberValueObject.create(100); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('0040'); + }); + + it('Value is number string', () => { + const number = StringValueObject.create('-0.5'); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is normal string', () => { + const number = StringValueObject.create('test'); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NUM); + }); + + it('Value is boolean', () => { + const number = BooleanValueObject.create(true); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.VALUE); + }); + + it('Value is null', () => { + const number = NullValueObject.create(); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NA); + }); + + it('Value is blank cell', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [null], + ]), + rowCount: 1, + columnCount: 1, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe('0000'); + }); + + it('Value is error', () => { + const number = ErrorValueObject.create(ErrorType.NAME); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toBe(ErrorType.NAME); + }); + + it('Value is array', () => { + const number = ArrayValueObject.create({ + calculateValueList: transformToValueObject([ + [1, ' ', 1.23, true, false, null], + [0, '100', '2.34', 'test', -3, ErrorType.NAME], + ]), + rowCount: 2, + columnCount: 6, + unitId: '', + sheetId: '', + row: 0, + column: 0, + }); + const places = NumberValueObject.create(4); + const result = testFunction.calculate(number, places); + expect(result.getValue()).toStrictEqual(ErrorType.VALUE); + }); + }); +}); diff --git a/packages/engine-formula/src/functions/engineering/oct2hex/index.ts b/packages/engine-formula/src/functions/engineering/oct2hex/index.ts new file mode 100644 index 00000000000..990f9787389 --- /dev/null +++ b/packages/engine-formula/src/functions/engineering/oct2hex/index.ts @@ -0,0 +1,92 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { checkVariantsErrorIsArrayOrBoolean, isValidOctalNumber } from '../../../basics/engineering'; +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; +import { StringValueObject } from '../../../engine/value-object/primitive-object'; + +export class Oct2hex extends BaseFunction { + override minParams = 1; + + override maxParams = 2; + + override calculate(number: BaseValueObject, places?: BaseValueObject) { + if (number.isNull()) { + return ErrorValueObject.create(ErrorType.NA); + } + + let placesValue = 0; + + if (places) { + // If places exists, it is prioritized. + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(places); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [placesObject] = variants as BaseValueObject[]; + + placesValue = Math.floor(+placesObject.getValue()); + + if (Number.isNaN(placesValue)) { + return ErrorValueObject.create(ErrorType.VALUE); + } + + if (placesValue < 0 || placesValue > 10) { + return ErrorValueObject.create(ErrorType.NUM); + } + } + + const { isError, errorObject, variants } = checkVariantsErrorIsArrayOrBoolean(number); + + if (isError) { + return errorObject as ErrorValueObject; + } + + const [numberObject] = variants as BaseValueObject[]; + + const numberValue = `${numberObject.getValue()}`; + + // Return error if number is not octal or contains more than ten characters (10 digits) + if (!isValidOctalNumber(numberValue)) { + return ErrorValueObject.create(ErrorType.NUM); + } + + // Convert octal number to decimal + const decimal = Number.parseInt(numberValue, 8); + + let result; + + if (decimal >= 536870912) { + result = `ff${(decimal + 3221225472).toString(16)}`; + } else { + result = decimal.toString(16); + + if (places) { + if (placesValue < result.length) { + return ErrorValueObject.create(ErrorType.NUM); + } + + result = '0'.repeat(placesValue - result.length) + result; + } + } + + return StringValueObject.create(result.toLocaleUpperCase()); + } +} diff --git a/packages/engine-formula/src/functions/logical/function-map.ts b/packages/engine-formula/src/functions/logical/function-map.ts index ab5a73f83a2..a6575e1c0fb 100644 --- a/packages/engine-formula/src/functions/logical/function-map.ts +++ b/packages/engine-formula/src/functions/logical/function-map.ts @@ -22,6 +22,7 @@ import { Iferror } from './iferror'; import { Ifna } from './ifna'; import { Ifs } from './ifs'; import { Lambda } from './lambda'; +import { Let } from './let'; import { Makearray } from './makearray'; import { Not } from './not'; import { Or } from './or'; @@ -37,6 +38,7 @@ export const functionLogical = [ [Ifna, FUNCTION_NAMES_LOGICAL.IFNA], [Ifs, FUNCTION_NAMES_LOGICAL.IFS], [Lambda, FUNCTION_NAMES_LOGICAL.LAMBDA], + [Let, FUNCTION_NAMES_LOGICAL.LET], [Makearray, FUNCTION_NAMES_LOGICAL.MAKEARRAY], [Not, FUNCTION_NAMES_LOGICAL.NOT], [Or, FUNCTION_NAMES_LOGICAL.OR], diff --git a/packages/engine-formula/src/functions/logical/let/index.ts b/packages/engine-formula/src/functions/logical/let/index.ts new file mode 100644 index 00000000000..9e107ba9404 --- /dev/null +++ b/packages/engine-formula/src/functions/logical/let/index.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ErrorType } from '../../../basics/error-type'; +import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; +import { BaseFunction } from '../../base-function'; + +/** + * Please refer to the _changeLetToLambda function; here, it serves the purpose of a placeholder for the formula. + */ +export class Let extends BaseFunction { + override minParams = 3; + + override maxParams = 255; + + override calculate(...variants: BaseValueObject[]) { + return ErrorValueObject.create(ErrorType.VALUE); + } +} diff --git a/packages/engine-formula/src/functions/logical/makearray/index.ts b/packages/engine-formula/src/functions/logical/makearray/index.ts index a14c5838b16..510440ab777 100644 --- a/packages/engine-formula/src/functions/logical/makearray/index.ts +++ b/packages/engine-formula/src/functions/logical/makearray/index.ts @@ -17,6 +17,7 @@ import { ErrorType } from '../../../basics/error-type'; import type { AsyncObject } from '../../../engine/reference-object/base-reference-object'; import { AsyncArrayObject } from '../../../engine/reference-object/base-reference-object'; +import type { ArrayValueObject } from '../../../engine/value-object/array-value-object'; import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object'; import type { LambdaValueObjectObject } from '../../../engine/value-object/lambda-value-object'; import { NumberValueObject } from '../../../engine/value-object/primitive-object'; @@ -53,7 +54,11 @@ export class Makearray extends BaseFunction { result[r] = []; } for (let c = 0; c < column; c++) { - const value = lambda.execute(NumberValueObject.create(r + 1), NumberValueObject.create(c + 1)); + let value = lambda.execute(NumberValueObject.create(r + 1), NumberValueObject.create(c + 1)); + + if (value.isArray()) { + value = (value as ArrayValueObject).get(0, 0) as BaseValueObject; + } result[r][c] = value; } diff --git a/packages/engine-formula/src/functions/lookup/indirect/index.ts b/packages/engine-formula/src/functions/lookup/indirect/index.ts index 540433a7901..5e808de1159 100644 --- a/packages/engine-formula/src/functions/lookup/indirect/index.ts +++ b/packages/engine-formula/src/functions/lookup/indirect/index.ts @@ -59,7 +59,7 @@ export class Indirect extends BaseFunction { const columnCount = (refText as ArrayValueObject).getColumnCount(); if (rowCount > 1 || columnCount > 1) { - // TO DO... + // TODO return refText.map(() => { return ErrorValueObject.create(ErrorType.VALUE); }); @@ -108,7 +108,7 @@ export class Indirect extends BaseFunction { const { range, sheetName, unitId } = gridRange; - if (Number.isNaN(range.startRow)) { + if (Number.isNaN(range.startRow) || range.endRow + 1 > 1048576 || Number.isNaN(range.startColumn) || range.endColumn + 1 > 16384) { return ErrorValueObject.create(ErrorType.REF); } diff --git a/packages/sheets-formula/src/controllers/__tests__/update-formula.controller.spec.ts b/packages/sheets-formula/src/controllers/__tests__/update-formula.controller.spec.ts index c56f2fdc152..c7f881b5a29 100644 --- a/packages/sheets-formula/src/controllers/__tests__/update-formula.controller.spec.ts +++ b/packages/sheets-formula/src/controllers/__tests__/update-formula.controller.spec.ts @@ -947,7 +947,6 @@ describe('Test insert function operation', () => { t: 2, }, { f: '=OFFSET(#REF!,1,1)', - si: 'id2', v: 1, t: 2, }, { @@ -981,7 +980,6 @@ describe('Test insert function operation', () => { t: 2, }, { f: '=OFFSET(#REF!,1,1)', - si: 'id2', v: 1, t: 2, }, { diff --git a/packages/sheets-formula/src/controllers/update-formula.controller.ts b/packages/sheets-formula/src/controllers/update-formula.controller.ts index 2801eaeec5a..5fd4b2265d6 100644 --- a/packages/sheets-formula/src/controllers/update-formula.controller.ts +++ b/packages/sheets-formula/src/controllers/update-formula.controller.ts @@ -843,17 +843,9 @@ export class UpdateFormulaController extends Disposable { const newSequenceNodes = this._updateRefOffset(sequenceNodes, refChangeIds, x, y); - // The formula f that originally depended on si has been actually calculated and does not require si and x,y. - if ((x !== undefined && (x > 0)) || (y !== undefined && (y > 0))) { - newFormulaDataItem.setValue(row, column, { - f: `=${generateStringWithSequence(newSequenceNodes)}`, - }); - } else { - newFormulaDataItem.setValue(row, column, { - f: `=${generateStringWithSequence(newSequenceNodes)}`, - si, - }); - } + newFormulaDataItem.setValue(row, column, { + f: `=${generateStringWithSequence(newSequenceNodes)}`, + }); }); if (newFormulaData[unitId]) { diff --git a/packages/sheets-formula/src/locale/function-list/engineering/en-US.ts b/packages/sheets-formula/src/locale/function-list/engineering/en-US.ts index 8c857a88d71..450187ecbb7 100644 --- a/packages/sheets-formula/src/locale/function-list/engineering/en-US.ts +++ b/packages/sheets-formula/src/locale/function-list/engineering/en-US.ts @@ -25,8 +25,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: 'The value at which to evaluate the function.' }, + n: { name: 'N', detail: 'The order of the Bessel function. If n is not an integer, it is truncated.' }, }, }, BESSELJ: { @@ -39,8 +39,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: 'The value at which to evaluate the function.' }, + n: { name: 'N', detail: 'The order of the Bessel function. If n is not an integer, it is truncated.' }, }, }, BESSELK: { @@ -53,8 +53,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: 'The value at which to evaluate the function.' }, + n: { name: 'N', detail: 'The order of the Bessel function. If n is not an integer, it is truncated.' }, }, }, BESSELY: { @@ -67,8 +67,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: 'The value at which to evaluate the function.' }, + n: { name: 'N', detail: 'The order of the Bessel function. If n is not an integer, it is truncated.' }, }, }, BIN2DEC: { @@ -81,8 +81,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'The binary number you want to convert.' }, }, }, BIN2HEX: { @@ -95,8 +94,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'The binary number you want to convert.' }, + places: { name: 'places', detail: 'The number of characters to use.' }, }, }, BIN2OCT: { @@ -109,8 +108,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'The binary number you want to convert.' }, + places: { name: 'places', detail: 'The number of characters to use.' }, }, }, BITAND: { @@ -123,8 +122,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: 'number1', detail: 'Must be in decimal form and greater than or equal to 0.' }, + number2: { name: 'number2', detail: 'Must be in decimal form and greater than or equal to 0.' }, }, }, BITLSHIFT: { @@ -137,8 +136,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'Number must be an integer greater than or equal to 0.' }, + shiftAmount: { name: 'shift_amount', detail: 'Shift_amount must be an integer.' }, }, }, BITOR: { @@ -151,8 +150,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: 'number1', detail: 'Must be in decimal form and greater than or equal to 0.' }, + number2: { name: 'number2', detail: 'Must be in decimal form and greater than or equal to 0.' }, }, }, BITRSHIFT: { @@ -165,8 +164,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'Number must be an integer greater than or equal to 0.' }, + shiftAmount: { name: 'shift_amount', detail: 'Shift_amount must be an integer.' }, }, }, BITXOR: { @@ -179,8 +178,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: 'number1', detail: 'Must be in decimal form and greater than or equal to 0.' }, + number2: { name: 'number2', detail: 'Must be in decimal form and greater than or equal to 0.' }, }, }, COMPLEX: { @@ -193,8 +192,9 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + realNum: { name: 'real_num', detail: 'The real coefficient of the complex number.' }, + iNum: { name: 'i_num', detail: 'The imaginary coefficient of the complex number.' }, + suffix: { name: 'suffix', detail: 'The suffix for the imaginary component of the complex number. If omitted, suffix is assumed to be "i".' }, }, }, CONVERT: { @@ -207,8 +207,9 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'is the value in from_units to convert.' }, + fromUnit: { name: 'from_unit', detail: 'is the units for number.' }, + toUnit: { name: 'to_unit', detail: 'is the units for the result.' }, }, }, DEC2BIN: { @@ -221,8 +222,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'The decimal number you want to convert.' }, + places: { name: 'places', detail: 'The number of characters to use.' }, }, }, DEC2HEX: { @@ -235,8 +236,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'The decimal number you want to convert.' }, + places: { name: 'places', detail: 'The number of characters to use.' }, }, }, DEC2OCT: { @@ -249,8 +250,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'The decimal number you want to convert.' }, + places: { name: 'places', detail: 'The number of characters to use.' }, }, }, DELTA: { @@ -263,8 +264,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: 'number1', detail: 'The first number.' }, + number2: { name: 'number2', detail: 'The second number. If omitted, number2 is assumed to be zero.' }, }, }, ERF: { @@ -277,8 +278,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + lowerLimit: { name: 'lower_limit', detail: 'The lower bound for integrating ERF.' }, + upperLimit: { name: 'upper_limit', detail: 'The upper bound for integrating ERF. If omitted, ERF integrates between zero and lower_limit.' }, }, }, ERF_PRECISE: { @@ -291,8 +292,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'x', detail: 'The lower bound for integrating ERF.PRECISE.' }, }, }, ERFC: { @@ -305,8 +305,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'x', detail: 'The lower bound for integrating ERFC.' }, }, }, ERFC_PRECISE: { @@ -319,8 +318,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'x', detail: 'The lower bound for integrating ERFC.PRECISE.' }, }, }, GESTEP: { @@ -347,8 +345,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'The hexadecimal number you want to convert.' }, + places: { name: 'places', detail: 'The number of characters to use.' }, }, }, HEX2DEC: { @@ -361,8 +359,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'The hexadecimal number you want to convert.' }, }, }, HEX2OCT: { @@ -375,8 +372,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'The hexadecimal number you want to convert.' }, + places: { name: 'places', detail: 'The number of characters to use.' }, }, }, IMABS: { @@ -739,8 +736,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'The octal number you want to convert.' }, + places: { name: 'places', detail: 'The number of characters to use.' }, }, }, OCT2DEC: { @@ -753,8 +750,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'The octal number you want to convert.' }, }, }, OCT2HEX: { @@ -767,8 +763,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: 'number', detail: 'The octal number you want to convert.' }, + places: { name: 'places', detail: 'The number of characters to use.' }, }, }, }; diff --git a/packages/sheets-formula/src/locale/function-list/engineering/ja-JP.ts b/packages/sheets-formula/src/locale/function-list/engineering/ja-JP.ts index d9caf242764..bb3aa69dad1 100644 --- a/packages/sheets-formula/src/locale/function-list/engineering/ja-JP.ts +++ b/packages/sheets-formula/src/locale/function-list/engineering/ja-JP.ts @@ -25,8 +25,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: '関数に代入する値を指定します。' }, + n: { name: 'N', detail: 'ベッセル関数の次数を指定します。n に整数以外の値を指定すると、小数点以下が切り捨てられます。' }, }, }, BESSELJ: { @@ -39,8 +39,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: '関数に代入する値を指定します。' }, + n: { name: 'N', detail: 'ベッセル関数の次数を指定します。n に整数以外の値を指定すると、小数点以下が切り捨てられます。' }, }, }, BESSELK: { @@ -53,8 +53,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: '関数に代入する値を指定します。' }, + n: { name: 'N', detail: 'ベッセル関数の次数を指定します。n に整数以外の値を指定すると、小数点以下が切り捨てられます。' }, }, }, BESSELY: { @@ -67,8 +67,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: '関数に代入する値を指定します。' }, + n: { name: 'N', detail: 'ベッセル関数の次数を指定します。n に整数以外の値を指定すると、小数点以下が切り捨てられます。' }, }, }, BIN2DEC: { @@ -81,8 +81,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '2 進数', detail: '変換する 2 進数を指定します。' }, }, }, BIN2HEX: { @@ -95,8 +94,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '2 進数', detail: '変換する 2 進数を指定します。' }, + places: { name: '桁数', detail: '使用する文字数を指定します。' }, }, }, BIN2OCT: { @@ -109,8 +108,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '2 進数', detail: '変換する 2 進数を指定します。' }, + places: { name: '桁数', detail: '使用する文字数を指定します。' }, }, }, BITAND: { @@ -123,8 +122,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: '数値1', detail: '小数点の表示形式になっている必要があります。 0 以上の数値を指定します。' }, + number2: { name: '数値2', detail: '小数点の表示形式になっている必要があります。 0 以上の数値を指定します。' }, }, }, BITLSHIFT: { @@ -137,8 +136,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '数値', detail: '数値は、0 以上の整数である必要があります。' }, + shiftAmount: { name: 'シフト量', detail: 'は整数である必要があります。' }, }, }, BITOR: { @@ -151,8 +150,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: '数値1', detail: '小数点の表示形式になっている必要があります。 0 以上の数値を指定します。' }, + number2: { name: '数値2', detail: '小数点の表示形式になっている必要があります。 0 以上の数値を指定します。' }, }, }, BITRSHIFT: { @@ -165,8 +164,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '数値', detail: '数値は、0 以上の整数である必要があります。' }, + shiftAmount: { name: 'シフト量', detail: 'は整数である必要があります。' }, }, }, BITXOR: { @@ -179,8 +178,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: '数値1', detail: '小数点の表示形式になっている必要があります。 0 以上の数値を指定します。' }, + number2: { name: '数値2', detail: '小数点の表示形式になっている必要があります。 0 以上の数値を指定します。' }, }, }, COMPLEX: { @@ -193,8 +192,9 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + realNum: { name: '実数', detail: '複素数の実数係数を指定します。' }, + iNum: { name: '虚数', detail: '複素数の虚数係数を指定します。' }, + suffix: { name: '虚数単位', detail: '複素数の虚数部分の単位を指定します。省略すると、"i" を指定したと見なされます。' }, }, }, CONVERT: { @@ -207,8 +207,9 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '数値', detail: '変換する値を指定します。' }, + fromUnit: { name: '変換前単位', detail: '数値の単位を指定します。' }, + toUnit: { name: '変換後単位', detail: '結果の単位を指定します。' }, }, }, DEC2BIN: { @@ -221,8 +222,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '10 進数', detail: '変換する 10 進数を指定します。' }, + places: { name: '桁数', detail: '使用する文字数を指定します。' }, }, }, DEC2HEX: { @@ -235,8 +236,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '10 進数', detail: '変換する 10 進数を指定します。' }, + places: { name: '桁数', detail: '使用する文字数を指定します。' }, }, }, DEC2OCT: { @@ -249,8 +250,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '10 進数', detail: '変換する 10 進数を指定します。' }, + places: { name: '桁数', detail: '使用する文字数を指定します。' }, }, }, DELTA: { @@ -263,8 +264,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: '数値1', detail: '一方の数値を指定します。' }, + number2: { name: '数値2', detail: 'もう一方の数値を指定します。数値 2 を省略すると、0 を指定したと見なされます。' }, }, }, ERF: { @@ -277,8 +278,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + lowerLimit: { name: '下限', detail: '誤差関数を積分するときの下限値を指定します。' }, + upperLimit: { name: '上限', detail: '誤差関数を積分するときの上限値を指定します。上限を省略すると、0 ~下限の範囲で積分が行われます。' }, }, }, ERF_PRECISE: { @@ -291,8 +292,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: '下限', detail: '誤差関数を積分するときの下限値を指定します。' }, }, }, ERFC: { @@ -305,8 +305,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: '下限', detail: '相補誤差関数を積分するときの下限値を指定します。' }, }, }, ERFC_PRECISE: { @@ -319,8 +318,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: '下限', detail: '相補誤差関数を積分するときの下限値を指定します。' }, }, }, GESTEP: { @@ -347,8 +345,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '16 進数', detail: '変換する 16 進数を指定します。' }, + places: { name: '桁数', detail: '使用する文字数を指定します。' }, }, }, HEX2DEC: { @@ -361,8 +359,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '16 進数', detail: '変換する 16 進数を指定します。' }, }, }, HEX2OCT: { @@ -375,8 +372,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '16 進数', detail: '変換する 16 進数を指定します。' }, + places: { name: '桁数', detail: '使用する文字数を指定します。' }, }, }, IMABS: { @@ -739,8 +736,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '8 進数', detail: '変換する 8 進数を指定します。' }, + places: { name: '桁数', detail: '使用する文字数を指定します。' }, }, }, OCT2DEC: { @@ -753,8 +750,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '8 進数', detail: '変換する 8 進数を指定します。' }, }, }, OCT2HEX: { @@ -767,8 +763,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '8 進数', detail: '変換する 8 進数を指定します。' }, + places: { name: '桁数', detail: '使用する文字数を指定します。' }, }, }, }; diff --git a/packages/sheets-formula/src/locale/function-list/engineering/vi-VN.ts b/packages/sheets-formula/src/locale/function-list/engineering/vi-VN.ts index bdba026e1b1..8c6099a1c6d 100644 --- a/packages/sheets-formula/src/locale/function-list/engineering/vi-VN.ts +++ b/packages/sheets-formula/src/locale/function-list/engineering/vi-VN.ts @@ -25,14 +25,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + x: { name: 'X', detail: 'Giá trị để đánh giá hàm.' }, + n: { name: 'N', detail: 'Bậc của hàm Bessel. Nếu n không phải là số nguyên thì nó bị cắt cụt.' }, }, }, BESSELJ: { @@ -45,14 +39,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + x: { name: 'X', detail: 'Giá trị để đánh giá hàm.' }, + n: { name: 'N', detail: 'Bậc của hàm Bessel. Nếu n không phải là số nguyên thì nó bị cắt cụt.' }, }, }, BESSELK: { @@ -65,14 +53,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + x: { name: 'X', detail: 'Giá trị để đánh giá hàm.' }, + n: { name: 'N', detail: 'Bậc của hàm Bessel. Nếu n không phải là số nguyên thì nó bị cắt cụt.' }, }, }, BESSELY: { @@ -85,14 +67,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + x: { name: 'X', detail: 'Giá trị để đánh giá hàm.' }, + n: { name: 'N', detail: 'Bậc của hàm Bessel. Nếu n không phải là số nguyên thì nó bị cắt cụt.' }, }, }, BIN2DEC: { @@ -105,14 +81,7 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number: { name: 'Số nhị phân', detail: 'Số nhị phân mà bạn muốn chuyển đổi.' }, }, }, BIN2HEX: { @@ -125,14 +94,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number: { name: 'Số nhị phân', detail: 'Số nhị phân mà bạn muốn chuyển đổi.' }, + places: { name: 'Số ký tự', detail: 'Số ký tự sử dụng.' }, }, }, BIN2OCT: { @@ -145,14 +108,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number: { name: 'Số nhị phân', detail: 'Số nhị phân mà bạn muốn chuyển đổi.' }, + places: { name: 'Số ký tự', detail: 'Số ký tự sử dụng.' }, }, }, BITAND: { @@ -165,14 +122,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number1: { name: 'Giá trị 1', detail: 'Phải là dạng thập phân và lớn hơn hoặc bằng 0.' }, + number2: { name: 'Giá trị 2', detail: 'Phải là dạng thập phân và lớn hơn hoặc bằng 0.' }, }, }, @@ -186,14 +137,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number: { name: 'giá trị số', detail: 'phải là số nguyên lớn hơn hoặc bằng 0.' }, + shiftAmount: { name: 'Số tiền ca', detail: 'phải là số nguyên.' }, }, }, BITOR: { @@ -206,14 +151,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number1: { name: 'Giá trị 1', detail: 'Phải là dạng thập phân và lớn hơn hoặc bằng 0.' }, + number2: { name: 'Giá trị 2', detail: 'Phải là dạng thập phân và lớn hơn hoặc bằng 0.' }, }, }, BITRSHIFT: { @@ -226,14 +165,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number: { name: 'giá trị số', detail: 'phải là số nguyên lớn hơn hoặc bằng 0.' }, + shiftAmount: { name: 'Số tiền ca', detail: 'phải là số nguyên.' }, }, }, BITXOR: { @@ -246,14 +179,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number1: { name: 'Giá trị 1', detail: 'Phải là dạng thập phân và lớn hơn hoặc bằng 0.' }, + number2: { name: 'Giá trị 2', detail: 'Phải là dạng thập phân và lớn hơn hoặc bằng 0.' }, }, }, COMPLEX: { @@ -266,14 +193,9 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + realNum: { name: 'hệ số thực', detail: 'Hệ số thực của số phức.' }, + iNum: { name: 'hệ số ảo', detail: 'Hệ số ảo của số phức.' }, + suffix: { name: 'hậu tố', detail: 'Hậu tố cho thành phần ảo của số phức. Nếu bị bỏ qua, hậu tố được giả định là "i".' }, }, }, CONVERT: { @@ -286,14 +208,9 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number: { name: 'giá trị số', detail: 'Giá trị cần chuyển đổi.' }, + fromUnit: { name: 'Đơn vị trước khi chuyển đổi', detail: 'là đơn vị của giá trị số.' }, + toUnit: { name: 'Đơn vị chuyển đổi', detail: 'là đơn vị của kết quả.' }, }, }, DEC2BIN: { @@ -306,14 +223,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number: { name: 'Số thập phân', detail: 'Số nguyên thập phân mà bạn muốn chuyển đổi.' }, + places: { name: 'Số ký tự', detail: 'Số ký tự sử dụng.' }, }, }, DEC2HEX: { @@ -326,14 +237,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number: { name: 'Số thập phân', detail: 'Số nguyên thập phân mà bạn muốn chuyển đổi.' }, + places: { name: 'Số ký tự', detail: 'Số ký tự sử dụng.' }, }, }, DEC2OCT: { @@ -346,14 +251,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number: { name: 'Số thập phân', detail: 'Số nguyên thập phân mà bạn muốn chuyển đổi.' }, + places: { name: 'Số ký tự', detail: 'Số ký tự sử dụng.' }, }, }, DELTA: { @@ -366,14 +265,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number1: { name: 'giá trị số 1', detail: 'Số thứ nhất.' }, + number2: { name: 'giá trị số 2', detail: 'Số thứ hai. Nếu bị bỏ qua, number2 được cho là bằng không.' }, }, }, ERF: { @@ -386,14 +279,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + lowerLimit: { name: 'Giơi hạn dươi', detail: 'Giới hạn dưới để lấy tích phân hàm ERF.' }, + upperLimit: { name: 'giới hạn trên', detail: 'Giới hạn trên để lấy tích phân hàm ERF. Nếu bị bỏ qua, hàm ERF lấy tích phân giữa số không và lower_limit.' }, }, }, ERF_PRECISE: { @@ -406,14 +293,7 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + x: { name: 'Giơi hạn dươi', detail: 'Giới hạn dưới để lấy tích phân hàm ERF.PRECISE.' }, }, }, ERFC: { @@ -426,14 +306,7 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + x: { name: 'Giơi hạn dươi', detail: 'Giới hạn dưới để lấy tích phân hàm ERFC.' }, }, }, ERFC_PRECISE: { @@ -446,14 +319,7 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + x: { name: 'Giơi hạn dươi', detail: 'Giới hạn dưới để lấy tích phân hàm ERFC.PRECISE.' }, }, }, GESTEP: { @@ -486,14 +352,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number: { name: 'số thập lục phân', detail: 'Số thập lục phân mà bạn muốn chuyển đổi.' }, + places: { name: 'Số ký tự', detail: 'Số ký tự sử dụng.' }, }, }, HEX2DEC: { @@ -506,14 +366,7 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number: { name: 'số thập lục phân', detail: 'Số thập lục phân mà bạn muốn chuyển đổi.' }, }, }, HEX2OCT: { @@ -526,14 +379,8 @@ export default { }, ], functionParameter: { - number1: { - name: 'number1', - detail: 'đầu tiên', - }, - number2: { - name: 'number2', - detail: 'thứ hai', - }, + number: { name: 'số thập lục phân', detail: 'Số thập lục phân mà bạn muốn chuyển đổi.' }, + places: { name: 'Số ký tự', detail: 'Số ký tự sử dụng.' }, }, }, IMABS: { @@ -981,8 +828,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'đầu tiên' }, - number2: { name: 'number2', detail: 'thứ hai' }, + number: { name: 'Số bát phân', detail: 'Số bát phân mà bạn muốn chuyển đổi.' }, + places: { name: 'Số ký tự', detail: 'Số ký tự sử dụng.' }, }, }, OCT2DEC: { @@ -995,8 +842,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'đầu tiên' }, - number2: { name: 'number2', detail: 'thứ hai' }, + number: { name: 'Số bát phân', detail: 'Số bát phân mà bạn muốn chuyển đổi.' }, }, }, OCT2HEX: { @@ -1009,8 +855,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'đầu tiên' }, - number2: { name: 'number2', detail: 'thứ hai' }, + number: { name: 'Số bát phân', detail: 'Số bát phân mà bạn muốn chuyển đổi.' }, + places: { name: 'Số ký tự', detail: 'Số ký tự sử dụng.' }, }, }, }; diff --git a/packages/sheets-formula/src/locale/function-list/engineering/zh-CN.ts b/packages/sheets-formula/src/locale/function-list/engineering/zh-CN.ts index cf6d1ac700c..f83e61a3ab3 100644 --- a/packages/sheets-formula/src/locale/function-list/engineering/zh-CN.ts +++ b/packages/sheets-formula/src/locale/function-list/engineering/zh-CN.ts @@ -25,8 +25,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: '用来计算函数的值。' }, + n: { name: 'N', detail: '贝赛耳函数的阶数。如果n不是整数,将被截尾取整。' }, }, }, BESSELJ: { @@ -39,8 +39,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: '用来计算函数的值。' }, + n: { name: 'N', detail: '贝赛耳函数的阶数。如果n不是整数,将被截尾取整。' }, }, }, BESSELK: { @@ -53,8 +53,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: '用来计算函数的值。' }, + n: { name: 'N', detail: '贝赛耳函数的阶数。如果n不是整数,将被截尾取整。' }, }, }, BESSELY: { @@ -67,8 +67,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: '用来计算函数的值。' }, + n: { name: 'N', detail: '贝赛耳函数的阶数。如果n不是整数,将被截尾取整。' }, }, }, BIN2DEC: { @@ -81,8 +81,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '二进制数', detail: '要转换的二进制数。' }, }, }, BIN2HEX: { @@ -95,8 +94,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '二进制数', detail: '要转换的二进制数。' }, + places: { name: '字符数', detail: '要使用的字符数。' }, }, }, BIN2OCT: { @@ -109,8 +108,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '二进制数', detail: '要转换的二进制数。' }, + places: { name: '字符数', detail: '要使用的字符数。' }, }, }, BITAND: { @@ -123,8 +122,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: '数值1', detail: '必须为十进制格式且大于等于 0。' }, + number2: { name: '数值2', detail: '必须为十进制格式且大于等于 0。' }, }, }, BITLSHIFT: { @@ -137,8 +136,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '数值', detail: '必须是大于或等于 0 的整数。' }, + shiftAmount: { name: '移位量', detail: '必须为整数。' }, }, }, BITOR: { @@ -151,8 +150,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: '数值1', detail: '必须为十进制格式且大于等于 0。' }, + number2: { name: '数值2', detail: '必须为十进制格式且大于等于 0。' }, }, }, BITRSHIFT: { @@ -165,8 +164,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '数值', detail: '必须是大于或等于 0 的整数。' }, + shiftAmount: { name: '移位量', detail: '必须为整数。' }, }, }, BITXOR: { @@ -179,8 +178,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: '数值1', detail: '必须为十进制格式且大于等于 0。' }, + number2: { name: '数值2', detail: '必须为十进制格式且大于等于 0。' }, }, }, COMPLEX: { @@ -193,8 +192,9 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + realNum: { name: '实系数', detail: '复数的实系数。' }, + iNum: { name: '虚系数', detail: '复数的虚系数。' }, + suffix: { name: '后缀', detail: '复数中虚系数的后缀。如果省略,则认为它是“i”。' }, }, }, CONVERT: { @@ -207,8 +207,9 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '数值', detail: '需要进行转换的数值。' }, + fromUnit: { name: '转换前单位', detail: '是数值的单位。' }, + toUnit: { name: '转换后单位', detail: '是结果的单位。' }, }, }, DEC2BIN: { @@ -221,8 +222,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '十进制数', detail: '要转换的十进制数。' }, + places: { name: '字符数', detail: '要使用的字符数。' }, }, }, DEC2HEX: { @@ -235,8 +236,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '十进制数', detail: '要转换的十进制数。' }, + places: { name: '字符数', detail: '要使用的字符数。' }, }, }, DEC2OCT: { @@ -249,8 +250,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '十进制数', detail: '要转换的十进制数。' }, + places: { name: '字符数', detail: '要使用的字符数。' }, }, }, DELTA: { @@ -263,8 +264,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: '数值1', detail: '第一个数值。' }, + number2: { name: '数值2', detail: '第二个数值。如果省略,则假设数值2为零。' }, }, }, ERF: { @@ -277,8 +278,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + lowerLimit: { name: '下限', detail: 'ERF函数的积分下限。' }, + upperLimit: { name: '上限', detail: 'ERF函数的积分上限。如果省略,ERF积分将在零到下限之间。' }, }, }, ERF_PRECISE: { @@ -291,8 +292,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: '下限', detail: 'ERF.PRECISE函数的积分下限。' }, }, }, ERFC: { @@ -305,8 +305,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: '下限', detail: 'ERFC函数的积分下限。' }, }, }, ERFC_PRECISE: { @@ -319,8 +318,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: '下限', detail: 'ERFC.PRECISE函数的积分下限。' }, }, }, GESTEP: { @@ -347,8 +345,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '十六进制数', detail: '要转换的十六进制数。' }, + places: { name: '字符数', detail: '要使用的字符数。' }, }, }, HEX2DEC: { @@ -361,8 +359,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '十六进制数', detail: '要转换的十六进制数。' }, }, }, HEX2OCT: { @@ -375,8 +372,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '十六进制数', detail: '要转换的十六进制数。' }, + places: { name: '字符数', detail: '要使用的字符数。' }, }, }, IMABS: { @@ -739,8 +736,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '八进制数', detail: '要转换的八进制数。' }, + places: { name: '字符数', detail: '要使用的字符数。' }, }, }, OCT2DEC: { @@ -753,8 +750,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '八进制数', detail: '要转换的八进制数。' }, }, }, OCT2HEX: { @@ -767,8 +763,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '八进制数', detail: '要转换的八进制数。' }, + places: { name: '字符数', detail: '要使用的字符数。' }, }, }, }; diff --git a/packages/sheets-formula/src/locale/function-list/engineering/zh-TW.ts b/packages/sheets-formula/src/locale/function-list/engineering/zh-TW.ts index d4503f5e49a..872cda9d3c3 100644 --- a/packages/sheets-formula/src/locale/function-list/engineering/zh-TW.ts +++ b/packages/sheets-formula/src/locale/function-list/engineering/zh-TW.ts @@ -25,8 +25,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: '這是用於評估函數的值。' }, + n: { name: 'N', detail: '這是Bessel函數的順序。如果n不是整數,則會取至整數。' }, }, }, BESSELJ: { @@ -39,8 +39,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: '這是用於評估函數的值。' }, + n: { name: 'N', detail: '這是Bessel函數的順序。如果n不是整數,則會取至整數。' }, }, }, BESSELK: { @@ -53,8 +53,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: '這是用於評估函數的值。' }, + n: { name: 'N', detail: '這是Bessel函數的順序。如果n不是整數,則會取至整數。' }, }, }, BESSELY: { @@ -67,8 +67,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: 'X', detail: '這是用於評估函數的值。' }, + n: { name: 'N', detail: '這是Bessel函數的順序。如果n不是整數,則會取至整數。' }, }, }, BIN2DEC: { @@ -81,8 +81,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '二進制數', detail: '您要轉換的二進制數。' }, }, }, BIN2HEX: { @@ -95,8 +94,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '二進制數', detail: '您要轉換的二進制數。' }, + places: { name: '字元數', detail: '這是要使用的字元數。' }, }, }, BIN2OCT: { @@ -109,8 +108,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '二進制數', detail: '您要轉換的二進制數。' }, + places: { name: '字元數', detail: '這是要使用的字元數。' }, }, }, BITAND: { @@ -123,8 +122,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: '數值1', detail: '必須是十進位格式,且大於或等於 0。' }, + number2: { name: '數值2', detail: '必須是十進位格式,且大於或等於 0。' }, }, }, BITLSHIFT: { @@ -137,8 +136,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '數值', detail: '必須是大於或等於 0 的整數。' }, + shiftAmount: { name: '移位量', detail: '必須是整數。' }, }, }, BITOR: { @@ -151,8 +150,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: '數值1', detail: '必須是十進位格式,且大於或等於 0。' }, + number2: { name: '數值2', detail: '必須是十進位格式,且大於或等於 0。' }, }, }, BITRSHIFT: { @@ -165,8 +164,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '數值', detail: '必須是大於或等於 0 的整數。' }, + shiftAmount: { name: '移位量', detail: '必須是整數。' }, }, }, BITXOR: { @@ -179,8 +178,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: '數值1', detail: '必須是十進位格式,且大於或等於 0。' }, + number2: { name: '數值2', detail: '必須是十進位格式,且大於或等於 0。' }, }, }, COMPLEX: { @@ -193,8 +192,9 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + realNum: { name: '實係數', detail: '這是複數的實係數。' }, + iNum: { name: '虛係數', detail: '這是複數的虛係數。' }, + suffix: { name: '字尾', detail: '這是複數虛數元件的字尾。如果省略,會將字尾假設為 "i"。' }, }, }, CONVERT: { @@ -207,8 +207,9 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '數值', detail: '要轉換的值。' }, + fromUnit: { name: '轉換前單位', detail: '這是數值的單位。' }, + toUnit: { name: '轉換后單位', detail: '這是結果的單位。' }, }, }, DEC2BIN: { @@ -221,8 +222,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '十進制數', detail: '您要轉換的十進制數。' }, + places: { name: '字元數', detail: '這是要使用的字元數。' }, }, }, DEC2HEX: { @@ -235,8 +236,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '十進制數', detail: '您要轉換的十進制數。' }, + places: { name: '字元數', detail: '這是要使用的字元數。' }, }, }, DEC2OCT: { @@ -249,8 +250,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '十進制數', detail: '您要轉換的十進制數。' }, + places: { name: '字元數', detail: '這是要使用的字元數。' }, }, }, DELTA: { @@ -263,8 +264,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number1: { name: '數值1', detail: '這是第一個數值。' }, + number2: { name: '數值2', detail: '這是第二個數值。如果省略,會將數值2假設為零。' }, }, }, ERF: { @@ -277,8 +278,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + lowerLimit: { name: '下限', detail: '這是整合ERF的下限。' }, + upperLimit: { name: '上限', detail: '這是整合ERF的上限。如果省略,ERF會在零和下限之間整合。' }, }, }, ERF_PRECISE: { @@ -291,8 +292,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: '下限', detail: '這是整合ERF.PRECISE的下限。' }, }, }, ERFC: { @@ -305,8 +305,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: '下限', detail: '這是整合ERFC的下限。' }, }, }, ERFC_PRECISE: { @@ -319,8 +318,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + x: { name: '下限', detail: '這是整合ERFC.PRECISE的下限。' }, }, }, GESTEP: { @@ -347,8 +345,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '十六進制數', detail: '您要轉換的十六進制數。' }, + places: { name: '字元數', detail: '這是要使用的字元數。' }, }, }, HEX2DEC: { @@ -361,8 +359,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '十六進制數', detail: '您要轉換的十六進制數。' }, }, }, HEX2OCT: { @@ -375,8 +372,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '十六進制數', detail: '您要轉換的十六進制數。' }, + places: { name: '字元數', detail: '這是要使用的字元數。' }, }, }, IMABS: { @@ -739,8 +736,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '八進制數', detail: '您要轉換的八進制數。' }, + places: { name: '字元數', detail: '這是要使用的字元數。' }, }, }, OCT2DEC: { @@ -753,8 +750,7 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '八進制數', detail: '您要轉換的八進制數。' }, }, }, OCT2HEX: { @@ -767,8 +763,8 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + number: { name: '八進制數', detail: '您要轉換的八進制數。' }, + places: { name: '字元數', detail: '這是要使用的字元數。' }, }, }, }; diff --git a/packages/sheets-formula/src/locale/function-list/logical/en-US.ts b/packages/sheets-formula/src/locale/function-list/logical/en-US.ts index b1e0ab8306d..5511906c075 100644 --- a/packages/sheets-formula/src/locale/function-list/logical/en-US.ts +++ b/packages/sheets-formula/src/locale/function-list/logical/en-US.ts @@ -163,8 +163,11 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + name1: { name: 'name1', detail: 'The first name to assign. Must start with a letter. Cannot be the output of a formula or conflict with range syntax.' }, + nameValue1: { name: 'name_value1', detail: 'The value that is assigned to name1.' }, + calculationOrName2: { name: 'calculation_or_name2', detail: 'One of the following:\n1.A calculation that uses all names within the LET function. This must be the last argument in the LET function.\n2.A second name to assign to a second name_value. If a name is specified, name_value2 and calculation_or_name3 become required.' }, + nameValue2: { name: 'name_value2', detail: 'The value that is assigned to calculation_or_name2.' }, + calculationOrName3: { name: 'calculation_or_name3', detail: 'One of the following:\n1.A calculation that uses all names within the LET function. The last argument in the LET function must be a calculation.\n2.A third name to assign to a third name_value. If a name is specified, name_value3 and calculation_or_name4 become required.' }, }, }, MAKEARRAY: { diff --git a/packages/sheets-formula/src/locale/function-list/logical/ja-JP.ts b/packages/sheets-formula/src/locale/function-list/logical/ja-JP.ts index 3245fa71ca2..83487f2608c 100644 --- a/packages/sheets-formula/src/locale/function-list/logical/ja-JP.ts +++ b/packages/sheets-formula/src/locale/function-list/logical/ja-JP.ts @@ -157,8 +157,11 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + name1: { name: '名前1', detail: '最初に割り当てる名前。文字で始まる必要があります。数式の出力であったり、範囲の構文と競合していたりしてはなりません。' }, + nameValue1: { name: '値1', detail: 'name1 に割り当てられている値。' }, + calculationOrName2: { name: '計算または名前2', detail: '以下のいずれかになります。\n1.LET 関数内のすべての名前を使用する計算。LET 関数の最後の引数でなければなりません。\n2.2 番目の name_value に割り当てる 2 番目の名前。名前が指定されている場合、name_value2 と calculation_or_name3 が必須です。' }, + nameValue2: { name: '値2', detail: 'calculation_or_name2 に割り当てられている値。' }, + calculationOrName3: { name: '計算または名前3', detail: '以下のいずれかになります。\n1.LET 関数内のすべての名前を使用する計算。LET 関数の最後の引数は計算でなければなりません。\n2.3 番目の name_value に割り当てる 3 番目の名前。名前が指定されている場合、name_value3 と calculation_or_name4 が必須です。' }, }, }, MAKEARRAY: { diff --git a/packages/sheets-formula/src/locale/function-list/logical/vi-VN.ts b/packages/sheets-formula/src/locale/function-list/logical/vi-VN.ts index 7fd13bb40aa..aec8fab9403 100644 --- a/packages/sheets-formula/src/locale/function-list/logical/vi-VN.ts +++ b/packages/sheets-formula/src/locale/function-list/logical/vi-VN.ts @@ -158,8 +158,11 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'đầu tiên' }, - number2: { name: 'number2', detail: 'thứ hai' }, + name1: { name: 'tên 1', detail: 'Tên đầu tiên cần phải gán. Phải bắt đầu bằng một chữ cái. Không thể là kết quả của công thức hoặc xung đột với cú pháp dải ô.' }, + nameValue1: { name: 'giá trị 1', detail: 'Giá trị gán cho name1.' }, + calculationOrName2: { name: 'tính toán hoặc tên 2', detail: 'Một trong những điều sau:\n1.Phép tính sử dụng tất cả các tên trong hàm LET. Đây phải là đối số cuối cùng trong hàm LET.\n2.Tên thứ hai cần gán cho name_value thứ hai. Nếu tên đã được xác định, name_value2 và calculation_or_name3 sẽ trở thành bắt buộc.' }, + nameValue2: { name: 'giá trị 2', detail: 'Giá trị gán cho calculation_or_name2.' }, + calculationOrName3: { name: 'tính toán hoặc tên 3', detail: 'Một trong những điều sau:\n1.Phép tính sử dụng tất cả các tên trong hàm LET. Đối số cuối cùng trong hàm LET phải là một phép tính.\n2.Tên thứ ba cần gán cho name_value thứ ba. Nếu tên đã được xác định, name_value3 và calculation_or_name4 sẽ trở thành bắt buộc.' }, }, }, MAKEARRAY: { diff --git a/packages/sheets-formula/src/locale/function-list/logical/zh-CN.ts b/packages/sheets-formula/src/locale/function-list/logical/zh-CN.ts index cd7dce8b52f..f239077b5dd 100644 --- a/packages/sheets-formula/src/locale/function-list/logical/zh-CN.ts +++ b/packages/sheets-formula/src/locale/function-list/logical/zh-CN.ts @@ -158,8 +158,11 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + name1: { name: '名称1', detail: '要分配的第一个名称。必须以字母开头。不能是公式的输出,也不能与范围语法冲突。' }, + nameValue1: { name: '值1', detail: '分配给 name1 的值。' }, + calculationOrName2: { name: '计算或名称2', detail: '下列任一项:\n1.使用 LET 函数中的所有名称的计算。这必须是 LET 函数中的最后一个参数。\n2.分配给第二个 name_value 的第二个名称。如果指定了名称,则 name_value2 和 calculation_or_name3 是必需的。' }, + nameValue2: { name: '值2', detail: '分配给 calculation_or_name2 的值。' }, + calculationOrName3: { name: '计算或名称3', detail: '下列任一项:\n1.使用 LET 函数中的所有名称的计算。LET 函数中的最后一个参数必须是一个计算。\n2.分配给第三个 name_value 的第三个名称。如果指定了名称,则 name_value3 和 calculation_or_name4 是必需的。' }, }, }, MAKEARRAY: { diff --git a/packages/sheets-formula/src/locale/function-list/logical/zh-TW.ts b/packages/sheets-formula/src/locale/function-list/logical/zh-TW.ts index 4dd7464944c..df1bf376856 100644 --- a/packages/sheets-formula/src/locale/function-list/logical/zh-TW.ts +++ b/packages/sheets-formula/src/locale/function-list/logical/zh-TW.ts @@ -159,8 +159,11 @@ export default { }, ], functionParameter: { - number1: { name: 'number1', detail: 'first' }, - number2: { name: 'number2', detail: 'second' }, + name1: { name: '名稱1', detail: '第一個指派的名稱。必須以字母開頭。不能是公式的輸出結果,或與範圍語法衝突。' }, + nameValue1: { name: '值1', detail: '指派給名稱1(name 1)的值。' }, + calculationOrName2: { name: '計算或名稱2', detail: '下列其中一項:\n1.使用 LET 函數中所有名稱的計算。這必須是 LET 函數中的最後一個引數。\n2.指派給第二個 name_value 的第二個名稱。若有指定名稱,則必須要有 name_value2 和 calculation_ 或 _name3。' }, + nameValue2: { name: '值2', detail: '指派給 calculation_or_name2 的值。' }, + calculationOrName3: { name: '計算或名稱3', detail: '下列其中一項:\n1.使用 LET 函數中所有名稱的計算。LET 函數中的最後一個引數必須是計算。\n2.指派給第三個 name_value 的第三個名稱。若有指定名稱,則必須要有 name_value3 和 calculation_ 或 _name4。' }, }, }, MAKEARRAY: { diff --git a/packages/sheets-formula/src/services/function-list/engineering.ts b/packages/sheets-formula/src/services/function-list/engineering.ts index acdc09a5c75..ed7244374f7 100644 --- a/packages/sheets-formula/src/services/function-list/engineering.ts +++ b/packages/sheets-formula/src/services/function-list/engineering.ts @@ -24,16 +24,16 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.BESSELI.abstract', functionParameter: [ { - name: 'formula.functionList.BESSELI.functionParameter.number1.name', - detail: 'formula.functionList.BESSELI.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.BESSELI.functionParameter.x.name', + detail: 'formula.functionList.BESSELI.functionParameter.x.detail', + example: '1.5', require: 1, repeat: 0, }, { - name: 'formula.functionList.BESSELI.functionParameter.number2.name', - detail: 'formula.functionList.BESSELI.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.BESSELI.functionParameter.n.name', + detail: 'formula.functionList.BESSELI.functionParameter.n.detail', + example: '1', require: 1, repeat: 0, }, @@ -46,16 +46,16 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.BESSELJ.abstract', functionParameter: [ { - name: 'formula.functionList.BESSELJ.functionParameter.number1.name', - detail: 'formula.functionList.BESSELJ.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.BESSELJ.functionParameter.x.name', + detail: 'formula.functionList.BESSELJ.functionParameter.x.detail', + example: '1.5', require: 1, repeat: 0, }, { - name: 'formula.functionList.BESSELJ.functionParameter.number2.name', - detail: 'formula.functionList.BESSELJ.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.BESSELJ.functionParameter.n.name', + detail: 'formula.functionList.BESSELJ.functionParameter.n.detail', + example: '1', require: 1, repeat: 0, }, @@ -68,16 +68,16 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.BESSELK.abstract', functionParameter: [ { - name: 'formula.functionList.BESSELK.functionParameter.number1.name', - detail: 'formula.functionList.BESSELK.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.BESSELK.functionParameter.x.name', + detail: 'formula.functionList.BESSELK.functionParameter.x.detail', + example: '1.5', require: 1, repeat: 0, }, { - name: 'formula.functionList.BESSELK.functionParameter.number2.name', - detail: 'formula.functionList.BESSELK.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.BESSELK.functionParameter.n.name', + detail: 'formula.functionList.BESSELK.functionParameter.n.detail', + example: '1', require: 1, repeat: 0, }, @@ -90,16 +90,16 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.BESSELY.abstract', functionParameter: [ { - name: 'formula.functionList.BESSELY.functionParameter.number1.name', - detail: 'formula.functionList.BESSELY.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.BESSELY.functionParameter.x.name', + detail: 'formula.functionList.BESSELY.functionParameter.x.detail', + example: '1.5', require: 1, repeat: 0, }, { - name: 'formula.functionList.BESSELY.functionParameter.number2.name', - detail: 'formula.functionList.BESSELY.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.BESSELY.functionParameter.n.name', + detail: 'formula.functionList.BESSELY.functionParameter.n.detail', + example: '1', require: 1, repeat: 0, }, @@ -112,16 +112,9 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.BIN2DEC.abstract', functionParameter: [ { - name: 'formula.functionList.BIN2DEC.functionParameter.number1.name', - detail: 'formula.functionList.BIN2DEC.functionParameter.number1.detail', - example: 'A1:A20', - require: 1, - repeat: 0, - }, - { - name: 'formula.functionList.BIN2DEC.functionParameter.number2.name', - detail: 'formula.functionList.BIN2DEC.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.BIN2DEC.functionParameter.number.name', + detail: 'formula.functionList.BIN2DEC.functionParameter.number.detail', + example: '1100100', require: 1, repeat: 0, }, @@ -134,17 +127,17 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.BIN2HEX.abstract', functionParameter: [ { - name: 'formula.functionList.BIN2HEX.functionParameter.number1.name', - detail: 'formula.functionList.BIN2HEX.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.BIN2HEX.functionParameter.number.name', + detail: 'formula.functionList.BIN2HEX.functionParameter.number.detail', + example: '11111011', require: 1, repeat: 0, }, { - name: 'formula.functionList.BIN2HEX.functionParameter.number2.name', - detail: 'formula.functionList.BIN2HEX.functionParameter.number2.detail', - example: 'A1:A20', - require: 1, + name: 'formula.functionList.BIN2HEX.functionParameter.places.name', + detail: 'formula.functionList.BIN2HEX.functionParameter.places.detail', + example: '4', + require: 0, repeat: 0, }, ], @@ -156,17 +149,17 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.BIN2OCT.abstract', functionParameter: [ { - name: 'formula.functionList.BIN2OCT.functionParameter.number1.name', - detail: 'formula.functionList.BIN2OCT.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.BIN2OCT.functionParameter.number.name', + detail: 'formula.functionList.BIN2OCT.functionParameter.number.detail', + example: '1001', require: 1, repeat: 0, }, { - name: 'formula.functionList.BIN2OCT.functionParameter.number2.name', - detail: 'formula.functionList.BIN2OCT.functionParameter.number2.detail', - example: 'A1:A20', - require: 1, + name: 'formula.functionList.BIN2OCT.functionParameter.places.name', + detail: 'formula.functionList.BIN2OCT.functionParameter.places.detail', + example: '3', + require: 0, repeat: 0, }, ], @@ -180,14 +173,14 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ { name: 'formula.functionList.BITAND.functionParameter.number1.name', detail: 'formula.functionList.BITAND.functionParameter.number1.detail', - example: 'A1:A20', + example: '13', require: 1, repeat: 0, }, { name: 'formula.functionList.BITAND.functionParameter.number2.name', detail: 'formula.functionList.BITAND.functionParameter.number2.detail', - example: 'A1:A20', + example: '25', require: 1, repeat: 0, }, @@ -200,16 +193,16 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.BITLSHIFT.abstract', functionParameter: [ { - name: 'formula.functionList.BITLSHIFT.functionParameter.number1.name', - detail: 'formula.functionList.BITLSHIFT.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.BITLSHIFT.functionParameter.number.name', + detail: 'formula.functionList.BITLSHIFT.functionParameter.number.detail', + example: '4', require: 1, repeat: 0, }, { - name: 'formula.functionList.BITLSHIFT.functionParameter.number2.name', - detail: 'formula.functionList.BITLSHIFT.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.BITLSHIFT.functionParameter.shiftAmount.name', + detail: 'formula.functionList.BITLSHIFT.functionParameter.shiftAmount.detail', + example: '2', require: 1, repeat: 0, }, @@ -224,14 +217,14 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ { name: 'formula.functionList.BITOR.functionParameter.number1.name', detail: 'formula.functionList.BITOR.functionParameter.number1.detail', - example: 'A1:A20', + example: '23', require: 1, repeat: 0, }, { name: 'formula.functionList.BITOR.functionParameter.number2.name', detail: 'formula.functionList.BITOR.functionParameter.number2.detail', - example: 'A1:A20', + example: '10', require: 1, repeat: 0, }, @@ -244,16 +237,16 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.BITRSHIFT.abstract', functionParameter: [ { - name: 'formula.functionList.BITRSHIFT.functionParameter.number1.name', - detail: 'formula.functionList.BITRSHIFT.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.BITRSHIFT.functionParameter.number.name', + detail: 'formula.functionList.BITRSHIFT.functionParameter.number.detail', + example: '13', require: 1, repeat: 0, }, { - name: 'formula.functionList.BITRSHIFT.functionParameter.number2.name', - detail: 'formula.functionList.BITRSHIFT.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.BITRSHIFT.functionParameter.shiftAmount.name', + detail: 'formula.functionList.BITRSHIFT.functionParameter.shiftAmount.detail', + example: '2', require: 1, repeat: 0, }, @@ -268,14 +261,14 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ { name: 'formula.functionList.BITXOR.functionParameter.number1.name', detail: 'formula.functionList.BITXOR.functionParameter.number1.detail', - example: 'A1:A20', + example: '5', require: 1, repeat: 0, }, { name: 'formula.functionList.BITXOR.functionParameter.number2.name', detail: 'formula.functionList.BITXOR.functionParameter.number2.detail', - example: 'A1:A20', + example: '3', require: 1, repeat: 0, }, @@ -288,19 +281,26 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.COMPLEX.abstract', functionParameter: [ { - name: 'formula.functionList.COMPLEX.functionParameter.number1.name', - detail: 'formula.functionList.COMPLEX.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.COMPLEX.functionParameter.realNum.name', + detail: 'formula.functionList.COMPLEX.functionParameter.realNum.detail', + example: '3', require: 1, repeat: 0, }, { - name: 'formula.functionList.COMPLEX.functionParameter.number2.name', - detail: 'formula.functionList.COMPLEX.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.COMPLEX.functionParameter.iNum.name', + detail: 'formula.functionList.COMPLEX.functionParameter.iNum.detail', + example: '4', require: 1, repeat: 0, }, + { + name: 'formula.functionList.COMPLEX.functionParameter.suffix.name', + detail: 'formula.functionList.COMPLEX.functionParameter.suffix.detail', + example: '"i"', + require: 0, + repeat: 0, + }, ], }, { @@ -310,16 +310,23 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.CONVERT.abstract', functionParameter: [ { - name: 'formula.functionList.CONVERT.functionParameter.number1.name', - detail: 'formula.functionList.CONVERT.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.CONVERT.functionParameter.number.name', + detail: 'formula.functionList.CONVERT.functionParameter.number.detail', + example: '1', require: 1, repeat: 0, }, { - name: 'formula.functionList.CONVERT.functionParameter.number2.name', - detail: 'formula.functionList.CONVERT.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.CONVERT.functionParameter.fromUnit.name', + detail: 'formula.functionList.CONVERT.functionParameter.fromUnit.detail', + example: '"lbm"', + require: 1, + repeat: 0, + }, + { + name: 'formula.functionList.CONVERT.functionParameter.toUnit.name', + detail: 'formula.functionList.CONVERT.functionParameter.toUnit.detail', + example: '"kg"', require: 1, repeat: 0, }, @@ -332,17 +339,17 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.DEC2BIN.abstract', functionParameter: [ { - name: 'formula.functionList.DEC2BIN.functionParameter.number1.name', - detail: 'formula.functionList.DEC2BIN.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.DEC2BIN.functionParameter.number.name', + detail: 'formula.functionList.DEC2BIN.functionParameter.number.detail', + example: '9', require: 1, repeat: 0, }, { - name: 'formula.functionList.DEC2BIN.functionParameter.number2.name', - detail: 'formula.functionList.DEC2BIN.functionParameter.number2.detail', - example: 'A1:A20', - require: 1, + name: 'formula.functionList.DEC2BIN.functionParameter.places.name', + detail: 'formula.functionList.DEC2BIN.functionParameter.places.detail', + example: '4', + require: 0, repeat: 0, }, ], @@ -354,17 +361,17 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.DEC2HEX.abstract', functionParameter: [ { - name: 'formula.functionList.DEC2HEX.functionParameter.number1.name', - detail: 'formula.functionList.DEC2HEX.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.DEC2HEX.functionParameter.number.name', + detail: 'formula.functionList.DEC2HEX.functionParameter.number.detail', + example: '100', require: 1, repeat: 0, }, { - name: 'formula.functionList.DEC2HEX.functionParameter.number2.name', - detail: 'formula.functionList.DEC2HEX.functionParameter.number2.detail', - example: 'A1:A20', - require: 1, + name: 'formula.functionList.DEC2HEX.functionParameter.places.name', + detail: 'formula.functionList.DEC2HEX.functionParameter.places.detail', + example: '4', + require: 0, repeat: 0, }, ], @@ -376,17 +383,17 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.DEC2OCT.abstract', functionParameter: [ { - name: 'formula.functionList.DEC2OCT.functionParameter.number1.name', - detail: 'formula.functionList.DEC2OCT.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.DEC2OCT.functionParameter.number.name', + detail: 'formula.functionList.DEC2OCT.functionParameter.number.detail', + example: '58', require: 1, repeat: 0, }, { - name: 'formula.functionList.DEC2OCT.functionParameter.number2.name', - detail: 'formula.functionList.DEC2OCT.functionParameter.number2.detail', - example: 'A1:A20', - require: 1, + name: 'formula.functionList.DEC2OCT.functionParameter.places.name', + detail: 'formula.functionList.DEC2OCT.functionParameter.places.detail', + example: '3', + require: 0, repeat: 0, }, ], @@ -400,15 +407,15 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ { name: 'formula.functionList.DELTA.functionParameter.number1.name', detail: 'formula.functionList.DELTA.functionParameter.number1.detail', - example: 'A1:A20', + example: '5', require: 1, repeat: 0, }, { name: 'formula.functionList.DELTA.functionParameter.number2.name', detail: 'formula.functionList.DELTA.functionParameter.number2.detail', - example: 'A1:A20', - require: 1, + example: '4', + require: 0, repeat: 0, }, ], @@ -420,17 +427,17 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.ERF.abstract', functionParameter: [ { - name: 'formula.functionList.ERF.functionParameter.number1.name', - detail: 'formula.functionList.ERF.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.ERF.functionParameter.lowerLimit.name', + detail: 'formula.functionList.ERF.functionParameter.lowerLimit.detail', + example: '0.745', require: 1, repeat: 0, }, { - name: 'formula.functionList.ERF.functionParameter.number2.name', - detail: 'formula.functionList.ERF.functionParameter.number2.detail', - example: 'A1:A20', - require: 1, + name: 'formula.functionList.ERF.functionParameter.upperLimit.name', + detail: 'formula.functionList.ERF.functionParameter.upperLimit.detail', + example: '2', + require: 0, repeat: 0, }, ], @@ -442,16 +449,9 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.ERF_PRECISE.abstract', functionParameter: [ { - name: 'formula.functionList.ERF_PRECISE.functionParameter.number1.name', - detail: 'formula.functionList.ERF_PRECISE.functionParameter.number1.detail', - example: 'A1:A20', - require: 1, - repeat: 0, - }, - { - name: 'formula.functionList.ERF_PRECISE.functionParameter.number2.name', - detail: 'formula.functionList.ERF_PRECISE.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.ERF_PRECISE.functionParameter.x.name', + detail: 'formula.functionList.ERF_PRECISE.functionParameter.x.detail', + example: '1', require: 1, repeat: 0, }, @@ -464,16 +464,9 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.ERFC.abstract', functionParameter: [ { - name: 'formula.functionList.ERFC.functionParameter.number1.name', - detail: 'formula.functionList.ERFC.functionParameter.number1.detail', - example: 'A1:A20', - require: 1, - repeat: 0, - }, - { - name: 'formula.functionList.ERFC.functionParameter.number2.name', - detail: 'formula.functionList.ERFC.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.ERFC.functionParameter.x.name', + detail: 'formula.functionList.ERFC.functionParameter.x.detail', + example: '1', require: 1, repeat: 0, }, @@ -486,16 +479,9 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.ERFC_PRECISE.abstract', functionParameter: [ { - name: 'formula.functionList.ERFC_PRECISE.functionParameter.number1.name', - detail: 'formula.functionList.ERFC_PRECISE.functionParameter.number1.detail', - example: 'A1:A20', - require: 1, - repeat: 0, - }, - { - name: 'formula.functionList.ERFC_PRECISE.functionParameter.number2.name', - detail: 'formula.functionList.ERFC_PRECISE.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.ERFC_PRECISE.functionParameter.x.name', + detail: 'formula.functionList.ERFC_PRECISE.functionParameter.x.detail', + example: '1', require: 1, repeat: 0, }, @@ -530,17 +516,17 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.HEX2BIN.abstract', functionParameter: [ { - name: 'formula.functionList.HEX2BIN.functionParameter.number1.name', - detail: 'formula.functionList.HEX2BIN.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.HEX2BIN.functionParameter.number.name', + detail: 'formula.functionList.HEX2BIN.functionParameter.number.detail', + example: '"F"', require: 1, repeat: 0, }, { - name: 'formula.functionList.HEX2BIN.functionParameter.number2.name', - detail: 'formula.functionList.HEX2BIN.functionParameter.number2.detail', - example: 'A1:A20', - require: 1, + name: 'formula.functionList.HEX2BIN.functionParameter.places.name', + detail: 'formula.functionList.HEX2BIN.functionParameter.places.detail', + example: '8', + require: 0, repeat: 0, }, ], @@ -552,16 +538,9 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.HEX2DEC.abstract', functionParameter: [ { - name: 'formula.functionList.HEX2DEC.functionParameter.number1.name', - detail: 'formula.functionList.HEX2DEC.functionParameter.number1.detail', - example: 'A1:A20', - require: 1, - repeat: 0, - }, - { - name: 'formula.functionList.HEX2DEC.functionParameter.number2.name', - detail: 'formula.functionList.HEX2DEC.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.HEX2DEC.functionParameter.number.name', + detail: 'formula.functionList.HEX2DEC.functionParameter.number.detail', + example: '"A5"', require: 1, repeat: 0, }, @@ -574,17 +553,17 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.HEX2OCT.abstract', functionParameter: [ { - name: 'formula.functionList.HEX2OCT.functionParameter.number1.name', - detail: 'formula.functionList.HEX2OCT.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.HEX2OCT.functionParameter.number.name', + detail: 'formula.functionList.HEX2OCT.functionParameter.number.detail', + example: '"F"', require: 1, repeat: 0, }, { - name: 'formula.functionList.HEX2OCT.functionParameter.number2.name', - detail: 'formula.functionList.HEX2OCT.functionParameter.number2.detail', - example: 'A1:A20', - require: 1, + name: 'formula.functionList.HEX2OCT.functionParameter.places.name', + detail: 'formula.functionList.HEX2OCT.functionParameter.places.detail', + example: '3', + require: 0, repeat: 0, }, ], @@ -1146,17 +1125,17 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.OCT2BIN.abstract', functionParameter: [ { - name: 'formula.functionList.OCT2BIN.functionParameter.number1.name', - detail: 'formula.functionList.OCT2BIN.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.OCT2BIN.functionParameter.number.name', + detail: 'formula.functionList.OCT2BIN.functionParameter.number.detail', + example: '3', require: 1, repeat: 0, }, { - name: 'formula.functionList.OCT2BIN.functionParameter.number2.name', - detail: 'formula.functionList.OCT2BIN.functionParameter.number2.detail', - example: 'A1:A20', - require: 1, + name: 'formula.functionList.OCT2BIN.functionParameter.places.name', + detail: 'formula.functionList.OCT2BIN.functionParameter.places.detail', + example: '3', + require: 0, repeat: 0, }, ], @@ -1168,16 +1147,9 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.OCT2DEC.abstract', functionParameter: [ { - name: 'formula.functionList.OCT2DEC.functionParameter.number1.name', - detail: 'formula.functionList.OCT2DEC.functionParameter.number1.detail', - example: 'A1:A20', - require: 1, - repeat: 0, - }, - { - name: 'formula.functionList.OCT2DEC.functionParameter.number2.name', - detail: 'formula.functionList.OCT2DEC.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.OCT2DEC.functionParameter.number.name', + detail: 'formula.functionList.OCT2DEC.functionParameter.number.detail', + example: '54', require: 1, repeat: 0, }, @@ -1190,17 +1162,17 @@ export const FUNCTION_LIST_ENGINEERING: IFunctionInfo[] = [ abstract: 'formula.functionList.OCT2HEX.abstract', functionParameter: [ { - name: 'formula.functionList.OCT2HEX.functionParameter.number1.name', - detail: 'formula.functionList.OCT2HEX.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.OCT2HEX.functionParameter.number.name', + detail: 'formula.functionList.OCT2HEX.functionParameter.number.detail', + example: '100', require: 1, repeat: 0, }, { - name: 'formula.functionList.OCT2HEX.functionParameter.number2.name', - detail: 'formula.functionList.OCT2HEX.functionParameter.number2.detail', - example: 'A1:A20', - require: 1, + name: 'formula.functionList.OCT2HEX.functionParameter.places.name', + detail: 'formula.functionList.OCT2HEX.functionParameter.places.detail', + example: '4', + require: 0, repeat: 0, }, ], diff --git a/packages/sheets-formula/src/services/function-list/logical.ts b/packages/sheets-formula/src/services/function-list/logical.ts index 55a83c54d10..35c641d91c5 100644 --- a/packages/sheets-formula/src/services/function-list/logical.ts +++ b/packages/sheets-formula/src/services/function-list/logical.ts @@ -229,19 +229,40 @@ export const FUNCTION_LIST_LOGICAL: IFunctionInfo[] = [ abstract: 'formula.functionList.LET.abstract', functionParameter: [ { - name: 'formula.functionList.LET.functionParameter.number1.name', - detail: 'formula.functionList.LET.functionParameter.number1.detail', - example: 'A1:A20', + name: 'formula.functionList.LET.functionParameter.name1.name', + detail: 'formula.functionList.LET.functionParameter.name1.detail', + example: 'x', require: 1, repeat: 0, }, { - name: 'formula.functionList.LET.functionParameter.number2.name', - detail: 'formula.functionList.LET.functionParameter.number2.detail', - example: 'A1:A20', + name: 'formula.functionList.LET.functionParameter.nameValue1.name', + detail: 'formula.functionList.LET.functionParameter.nameValue1.detail', + example: '5', require: 1, repeat: 0, }, + { + name: 'formula.functionList.LET.functionParameter.calculationOrName2.name', + detail: 'formula.functionList.LET.functionParameter.calculationOrName2.detail', + example: 'y', + require: 1, + repeat: 0, + }, + { + name: 'formula.functionList.LET.functionParameter.nameValue2.name', + detail: 'formula.functionList.LET.functionParameter.nameValue2.detail', + example: '6', + require: 0, + repeat: 1, + }, + { + name: 'formula.functionList.LET.functionParameter.calculationOrName3.name', + detail: 'formula.functionList.LET.functionParameter.calculationOrName3.detail', + example: 'SUM(x,y)', + require: 0, + repeat: 1, + }, ], }, {