Все функции VBA MS Office и их аналоги в JavaScript
Математические функции VBA и
их аналоги в JavaScript (14)
Математические функции являются основой программы на любом языке программирования. Список всех математических функций на VBA и их аналогов в JavaScript (встроенная библиотека Math) приведен ниже:
VBA: Abs - JavaScript: Math.abs(x).
VBA: Atn - JavaScript: Math.atan(x)
VBA: Cos - JavaScript: Math.cos(x)
VBA: Exp - JavaScript: Math.exp(x)
VBA: Fix - JavaScript: x < 0 ? Math.ceil(x) : Math.floor(x)
VBA: Int - JavaScript: Math.floor(x)
VBA: IsNumeric - JavaScript: !isNaN(x);
VBA: Log - JavaScript: Math.log(x)
VBA: Round - JavaScript: Math.round(x)
VBA: Rnd - JavaScript: Math.random()
VBA: Sin - JavaScript: Math.sin(x)
VBA: Sqr - JavaScript: Math.sqrt(x)
VBA: Sgn - JavaScript: Math.sign(x)
VBA: Tan - JavaScript: Math.tan(x)
Функции VBA обработки строк и их аналоги (27)
При программировании интерфейсов программ на VBA большое значение имеют функции обработки строк. В JavaScript функции, аналогичные функциям обработки строк в VBA имеются в неполном объеме, но создание их аналогов не слишком сложная задача. Приведем список таких функций в VBA и их замену в JavaScript.
Asc(String)=>Integer ASCII AscB(String) =>Byte AscW(String)=>Unicode
Аналог:

function asc(str) {    return str.charCodeAt(0); }
Chr(CharCode)=>String
Аналог:

function chr(asciiCode) {    return String.fromCharCode(asciiCode);}
Filter(SourceArray, Match[, Inclule, [Compare]])=>OutStringArray
Аналог:

function filterArray(sourceArray, match, include = true, caseInsensitive = false) {
    return sourceArray.filter(item => {
        if (typeof item !== 'string') {
            return false;
        }
        // Приведение строки и критерия к нужному регистру, если нужно игнорировать регистр
        const checkItem = caseInsensitive ? item.toLowerCase() : item;
        const checkMatch = caseInsensitive ? match.toLowerCase() : match;
        // Проверка на включение или исключение элементов
        const containsMatch = checkItem.includes(checkMatch);
        return include ? containsMatch : !containsMatch;
    });
}
InStr([Start,]String1,String2[,Compare])=>Long
Аналог:

function instr(start = 1, string1, string2, caseInsensitive = false) {
    // Приведение строк к нужному регистру, если нужно игнорировать регистр
    const checkString = caseInsensitive ? string1.toLowerCase() : string1;
    const searchString = caseInsensitive ? string2.toLowerCase() : string2;    
    // Поиск позиции первого вхождения
    const position = checkString.indexOf(searchString, start - 1);
    // Возвращаем позицию в 1-индексации или 0, если совпадение не найдено
    return position !== -1 ? position + 1 : 0;
}
InStrRev(StringCheck,StringMatch[,Start[,Compare]])=>Long
Аналог:

function instrRev(stringCheck, stringMatch, start = stringCheck.length, caseInsensitive = false) {
    // Приведение строк к нужному регистру, если нужно игнорировать регистр
    const checkString = caseInsensitive ? stringCheck.toLowerCase() : stringCheck;
    const matchString = caseInsensitive ? stringMatch.toLowerCase() : stringMatch;    
    // Обрезаем строку до позиции start
    const substring = checkString.slice(0, start);    
    // Находим последнюю позицию вхождения
    const position = substring.lastIndexOf(matchString);
    // Возвращаем позицию, если она больше 0, иначе возвращаем -1
    return position !== -1 ? position + 1 : -1;
}
Join(SourceArray,[Delimiter])=>String
Аналог:

function join(arr, separator = ',') {    return arr.join(separator); }
LСase(String)=>String
Аналог:

function lcase(str) {    return str.toLowerCase(); }
Left(String, Length)=>String
Аналог:

function left(str, length) {    return str.slice(0, length); }
Len(String)=>Number
Аналог:

function len(str) {    return str.length; }
LTrim(String)=>String
Аналог:

function ltrim(str) {    return str.trimStart();  }
Mid(String,start-Long,[length-Long])=>String
Аналог:

function mid(str, start, length) { // JavaScript строки индекс от 0, поэтому уменьшаем start на 1 
  // return str.substr(start - 1, length);
return str.substring(start - 1, start - 1 + length); }
Partition(Number, Start, Stop, Interval)=>String
Используется редко для статистики.
Replace(Expression,Find,Replace,[Start],[Count],[Compare])=>String
Аналог:

function replaceAll(str, search, replacement) {
    // Создаем регулярное выражение для поиска всех вхождений
    // Используем глобальный флаг 'g' для замены всех вхождений
    const regex = new RegExp(search.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'), 'g');
    return str.replace(regex, replacement);
}
Right(String)=>String
Аналог:

function right(str, length) {
    if (length >= str.length) {
        return str;
    }
    return str.substring(str.length - length);
}
RTrim(String)=>String
Аналог:

function rtrim(str) {    return str.replace(/\s+$/, ''); 
Space(n)=>String
Аналог:

function space(n) {    return ' '.repeat(n); }
Spc(n)=>String
Аналог:

function spc(n) {    return ' '.repeat(n); }
Str(Number)=>String
Аналог:

function str(value) { return String(value); }
StrComp(String1, String2[, Compare])=>Integer
Аналог:

function strComp(string1, string2, compareMethod = 0) {
    // если compareMethod == 1, регистр не важен
    if (compareMethod === 1) {
        string1 = string1.toLowerCase();
        string2 = string2.toLowerCase();
    }    
    if (string1 < string2) {
        return -1;
    } else if (string1 > string2) {
        return 1;
    } else {
        return 0;
    }
}
StrConv(String,Conversion,[LocaleID])
Специфическая функция, включающая в себя различные варианты простых преобразований (Верхний регистр, нижний, Unicode и т.д.), большинство которых имеют аналоги в JavaScript и разобраны нами в этом разделе.
String(Long, char)=>String
Аналог:

function repeatString(count, character) { return character.repeat(count); }
StrReverse(String)=>String
Аналог:

function strReverse(str) { return str.split('').reverse().join(''); }
Tab(n)
Редко используется. Можно использовать в строке вывода "\t".
Trim(String)=>String
Аналог:

function trim(str) { return str.trim(); }
TypeName(Object)=>String
Аналог:

function typeName(variable) {
    if (variable === null) return "Null";
    if (variable === undefined) return "Undefined";
    const type = typeof variable;
    switch (type) {
        case "boolean":
            return "Boolean";
        case "number":
            return Number.isInteger(variable) ? "Integer" : "Double";
        case "string":
            return "String";
        case "function":
            return "Function";
        case "object":
            if (Array.isArray(variable)) return "Array";
            if (variable instanceof Date) return "Date";
            return "Object";
        default:
            return "Unknown";
    }
}
Ucase(String)=>String
Аналог:

function ucase(str) {    return str.toUpperCase(); }
Val(String)=>Numeric
Аналог:

function val(str) {   // return parseInt(str);
    return parseFloat(str); }

Функции работы с массивами в VBA и
их аналоги в JavaScript (4)
При преобразовании кода VBA, использующего многомерные массивы, возникают проблемы, требующие усложнения логики работы программы. При использовании одномерных массивов следует обратить внимание на настройки VBA (Option Base).
Array(ParamArray)=>Array
Аналог:

let array1 = [1, 2, 3]; // Массив с элементами 1, 2, 3
let array2 = new Array(1, 2, 3); // Массив с элементами 1, 2, 3, созданный через конструктор
//Вариант
function createArray(...elements) {    return elements;  }
let myArray = createArray(1, 2, 3, 4, 5); // Создаст массив [1, 2, 3, 4, 5]

IsArray(VarName)=>Boolean
Аналог:

function isArray(variable) {    return Array.isArray(variable);  }
LBound(ArrayName[,Dimension])=>Long
Аналог:

function LBound(arr, dimension) {
    if (!Array.isArray(arr)) {
        throw new Error("Не массив");
    }
    // Проверка на измерение (в JavaScript массивы одномерные, поэтому проверка на измерение)
    if (dimension && dimension !== 1) {
        throw new Error("в JavaScript только одномерные массивы ");
    }    
    // Возвращаемый начальный индекс для массива в JavaScript всегда 0
    return 0;
}

UBound(ArrayName[,Dimension])=>Long
Аналог:

function UBound(arr, dimension) {
    if (!Array.isArray(arr)) {
        throw new Error("Не массив!");
    }
    // Проверка на измерение (в JavaScript массивы одномерные, поэтому проверка на измерение)
    if (dimension && dimension !== 1) {
        throw new Error("в JavaScript только одномерные массивы");
    }
    // Возвращаем последний индекс массива
    return arr.length - 1;
}

Функции преобразования типа данных в VBA и
их аналоги в JavaScript (11)
CByte(Expression)=>Byte
Аналог: нет такого типа (0..255) в JavaScript. Можно попробовать так.

function CByte(expression) {
    let number = Number(expression);
    if (isNaN(number) || number < 0 || number > 255 || !Number.isInteger(number)) {
        throw new Error("Invalid byte value");
    }
    return number;
}
CCur(Expression)=>Currence
Аналог: нет такого типа в JavaScript. Можно попробовать функцию Number с округлением до второго знака после запятой.

function CCur(expression) {
    let number = Number(expression);
    if (isNaN(number)) {
        throw new Error("Invalid currency value");
    }
    return number.toFixed(2); // Округляет до двух знаков после запятой для валюты
}
CDate(String)=>Date
Аналог (с проверкой корректности формата строки как даты)

function CDate(dateString) {
    const date = new Date(dateString);
    // Проверка на корректность даты
    if (isNaN(date)) {
        throw new Error("Invalid date string");
    }
    return date;
} 
CVDate(String)=>Date
Устаревшая функция. Есть более современная CDate (Выше).
CDec(Expression)=>Decimal
(максимальная точность VBA)
Аналог (с проверкой превышения точности для JavaScript):

function CDate(dateString) {
    const date = new Date(dateString);
    // Проверка на корректность даты
    if (isNaN(date)) {
        throw new Error("Invalid date string");
    }
    return date;
} 
CDbl(Expression)=>Double
Аналог(с проверкой превышения точности дляJavaScript):

function CDbl(expression) {
    let number = Number(expression);
    if (isNaN(number)) {
        throw new Error("Invalid number");
    }
    return number;
}
CInt(Expression)=>Integer
Аналог:

function CInt(expression) {    return Math.round(Number(expression));}
CLng(Expression)=>Long
Аналог:

function CLng(expression) {    return parseInt(expression, 10); }
CStr(Expression)=>String
Аналог:

function CStr(expression) {    return String(expression); }
CSng(expression)=>Float
Аналог:

function CSng(expression) {    return parseFloat(expression);} 
CVar(Expression)=>Variant
Аналог: Нет нужды в аналоге, так как используется динамическая типизация. Однако имеются и функции явной типизации:

function toString(value) {    return String(value); }
function toNumber(value) {    return Number(value); }
function toBoolean(value) {    return Boolean(value); }
function toObject(value) {    return Object(value); }

Функции работы с файлами (12)
Из-за ограничений JavaScript в Р7, разобранных выше, аналогов нет. Возможно использование аналогов в Node.js или файловых потоках.
CurDir[ (Drive) ]=>Variant(String)CurDir$=>String
Dir [(PathName[, Attributes])]=>String
EOF(FileNumber)=>Boolean (Integer)
FreeFile([RangeNumber])=>Integer (0-511)
FileLen(PathName)=>Long
FileDateTime(PathName)=>Variant(Date)
FileAttr(FileNumber[,ReturnType])=>Long
GetAttr(Pathname)=>Integer
Input(Number, [#]FileNumber)=>String
LOF(FileNumber)=>Long
Loc(FileNumber)=>Long
Seek(FileNumber)=>Long
Системные функции (16)
Switch(Expr-1, Value-1[, Expr-2, Value-2 … [, Expr-n,Value-n]])
Аналог:

function switchCase(expr, ...cases) {
    for (let i = 0; i < cases.length; i += 2) {
        const caseExpr = cases[i];
        const caseValue = cases[i + 1];
        if (expr === caseExpr) {
            return caseValue;
        }
    }
    // Если не найдено совпадений, возвращаем значение по умолчанию
    return undefined;
}
Shell(PathName,[WindowStyle])=>Variant(Double)
Аналог: В связи с ограничениями, разобранными выше, аналога нет.
Для общего развития в Node.js:

const { exec } = require('child_process');
function shell(command, windowStyle) {
    // Список возможных значений для windowStyle
    const windowStyles = {
        'hide': 0,       // Скрытое окно
        'normal': 1,     // Обычное окно
        'minimized': 2,  // Свернутое окно
        'maximized': 3   // Развернутое окно
    };
    // Устанавливаем параметры окна, если указано
    let style = windowStyles[windowStyle] !== undefined ? windowStyles[windowStyle] : windowStyles['normal'];
    // Запускаем команду
    exec(command, (error, stdout, stderr) => {
        if (error) {
            console.error(`Ошибка: ${error.message}`);
            return;
        }
        if (stderr) {
            console.error(`Стандартный поток ошибок: ${stderr}`);
            return;
        }
        console.log(`Стандартный вывод: ${stdout}`);
    });
}
// Пример использования
shell('notepad', 'normal');  // Запускает Notepad с обычным окном
IsNull(Expression=>Boolean
Аналог:

function isNull(expression) {    return expression === null || expression === undefined; }
IsMissing(ArgName)=>Boolean
Аналог:

function isMissing(arg) {    return typeof arg === 'undefined';}
IsError(Expression)=>Boolean
Аналог:

function isError(expression) {    return expression instanceof Error;}
IsEmpty(Expression)=>Boolean
Аналог:

function isEmpty(expression) {    return expression === undefined || expression === null || expression === "";}
IMEStatus[( )]=>Integer
Аналог не нужен. Только для восточно-азиатских версий.
GetSetting(AppName,Section,Key[,Default])=>String
Специфичная функция для VBA (параметр реестра для VB и VBA). Доступа к реестру в JavaScript нет. Можно попробовать использовать локальное хранилище localStorage:

function getSetting(appName, section, key, defaultValue) {
    const storageKey = `${appName}.${section}.${key}`;
    const value = localStorage.getItem(storageKey);
    return value !== null ? value : defaultValue;
}
// Примеры использования
localStorage.setItem('MyApp.Settings.Theme', 'dark');
console.log(getSetting('MyApp', 'Settings', 'Theme', 'light')); // "dark"
GetAllSettings(Appname,Section)=>String
Специфичная функция для VBA (параметр реестра для VB и VBA). Доступа к реестру в JavaScript нет. Можно попробовать использовать локальное хранилище localStorage:

function setSetting(appName, section, key, value) {
    const storageKey = `${appName}.${section}.${key}`;
    localStorage.setItem(storageKey, value);
}
function getAllSettings(appName, section) {
    const settings = {};
    const prefix = `${appName}.${section}.`;
    for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i);
        if (key.startsWith(prefix)) {
            const settingKey = key.substring(prefix.length);
            settings[settingKey] = localStorage.getItem(key);
        }
    }
    return settings;
}
// Установка значений
setSetting('MyApp', 'Settings', 'Theme', 'dark');
setSetting('MyApp', 'Settings', 'FontSize', '16px');
setSetting('MyApp', 'User', 'Name', 'JohnDoe');
// Получение всех настроек
console.log(getAllSettings('MyApp', 'Settings'));  // { Theme: 'dark', FontSize: '16px' }
console.log(getAllSettings('MyApp', 'User'));  // { Name: 'JohnDoe' }
Error[(ErrorNumber)]=>Variant(String)
Аналог:

// Определяем свой набор сообщений об ошибках
const errorMessages = {
    1: "Ошибка: Недопустимый аргумент.",
    2: "Ошибка: Доступ запрещен.",
    3: "Ошибка: Элемент не найден.",
    4: "Ошибка: Превышен лимит времени.",
    5: "Ошибка: Недостаточно памяти.",
};
function getError(errorNumber) {
    return errorMessages[errorNumber] || `Неизвестная ошибка: ${errorNumber}`;
}
Erl()=Long
Аналог: Аналог может не сработать, требует проверки!:

function getErrorLine(error) {
    if (error.stack) {
        // Разбираем стек вызовов
        const stackLines = error.stack.split('\n');
        // Возвращаем первую строку стека, которая содержит номер строки ошибки
        // Обычно это третья строка стека, но это может варьироваться
        const lineInfo = stackLines[1].match(/:(\d+):\d+\)?$/);
        if (lineInfo) {
            return parseInt(lineInfo[1], 10);
        }
    }
    return null;
}
// Пример использования
try {
    // Код, который может вызвать ошибку
    nonExistentFunction(); // Эта строка вызовет ошибку
} catch (error) {
    const line = getErrorLine(error);
    console.log(`Ошибка произошла на строке: ${line}`);
}
Environ(Expression)=>String
Специфичная функция для VBA. Аналога нет.
Для общего развития в Node.js:

function getEnvironmentVariable(name) {    return process.env[name] || null;}
DoEvents()=>Integer
Аналог:

function doEvents(callback) {
    setTimeout(callback, 0);
}
// Пример использования
console.log("Start");
doEvents(() => {
    console.log("DoEvents callback");
});
console.log("End");
CVErr(errornumber)
Аналог (имя функции для лучшего понимания функционирования не совпадает с именем исходной функции):

function createCustomError(errorNumber) {
    let error = new Error(`Custom error with number: ${errorNumber}`);
    error.number = errorNumber;
    return error;
}
// Примеры использования
try {
    throw createCustomError(1001);
} catch (e) {
    console.log(e.message); // "Custom error with number: 1001"
    console.log(e.number);  // 1001
}
Command()=>String
Аналога нет, так как нет прямого доступа к командной строке.
Для общего развития в Node.js:

// Получение аргументов командной строки
const args = process.argv.slice(2); // slice(2) чтобы исключить первые два элемента (путь к Node.js и скрипту)
// Вывод аргументов
console.log("Command-line arguments:");
args.forEach((arg, index) => {    console.log(`Argument ${index + 1}: ${arg}`); });
CallByName(Object,ProcName,CallType,[Args() ])
Аналог:

function callByName(object, methodName, args) {
    if (typeof object[methodName] === 'function') {
        // Если метод существует, вызываем его с переданными аргументами
        return object[methodName](...args);
    } else {
        throw new Error(`Method ${methodName} does not exist on the object.`);
    }
}
// Пример объекта с методами
const myObject = {
    greet(name) {
        return `Hello, ${name}!`;
    },
    add(a, b) {
        return a + b;
    }
};
// Использование функции callByName
try {
    const greeting = callByName(myObject, 'greet', ['Alice']);
    console.log(greeting); // Output: Hello, Alice!

    const sum = callByName(myObject, 'add', [5, 3]);
    console.log(sum); // Output: 8
} catch (error) {
    console.error(error.message);
}
Функции обработки цвета (2)
RGB(Red, Green, Blue)=>Long
Аналог для CSS (возвращает String ‘rgb(r,g,b)’):

function RGB(red, green, blue) {
    // Проверка, чтобы значения были в пределах от 0 до 255
    if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) {
        throw new Error('Values must be between 0 and 255');
    }
    // Преобразование в строку формата RGB
    return `rgb(${red}, ${green}, ${blue})`;
}
// Примеры использования
try {
    const color1 = RGB(255, 0, 0); // Красный цвет
    console.log(color1); // Output: rgb(255, 0, 0)
    const color4 = RGB(128, 128, 128); // Серый цвет
    console.log(color4); // Output: rgb(128, 128, 128)
} catch (error) {
    console.error(error.message);
}
QBColor(Color)=>Long
Аналог:

function QBColor(index) {
    // Палитра цветов QB64
    const colors = [
        "#000000", // 0: Black
        "#FF0000", // 1: Red
        "#00FF00", // 2: Green
        "#FFFF00", // 3: Yellow
        "#0000FF", // 4: Blue
        "#FF00FF", // 5: Magenta
        "#00FFFF", // 6: Cyan
        "#C0C0C0", // 7: Light Gray
        "#808080", // 8: Gray
        "#FF0000", // 9: Red (same as index 1)
        "#00FF00", // 10: Green (same as index 2)
        "#FFFF00", // 11: Yellow (same as index 3)
        "#0000FF", // 12: Blue (same as index 4)
        "#FF00FF", // 13: Magenta (same as index 5)
        "#00FFFF", // 14: Cyan (same as index 6)
        "#FFFFFF"  // 15: White
    ];
    // Проверка, чтобы индекс был в допустимом диапазоне
    if (index < 0 || index > 15) {
        throw new Error('Index must be between 0 and 15');
    }
    return colors[index];
}
// Примеры использования
try {
    console.log(QBColor(0));  // Output: #000000 (Black)
    console.log(QBColor(3));  // Output: #FFFF00 (Yellow)
    console.log(QBColor(7));  // Output: #C0C0C0 (Light Gray)
    console.log(QBColor(15)); // Output: #FFFFFF (White)
} catch (error) {
    console.error(error.message);
}
Функции преобразования чисел в
разные системы счисления (3)
VarType (VarName)=>Integer
Аналог:

function VarType(value) {
    if (value === null) return 'Null';
    if (value === undefined) return 'Undefined';
    if (typeof value === 'boolean') return 'Boolean';
    if (typeof value === 'number') return 'Number';
    if (typeof value === 'string') return 'String';
    if (typeof value === 'object') {
        if (Array.isArray(value)) return 'Array';
        if (value instanceof Date) return 'Date';
        return 'Object';
    }
    if (typeof value === 'function') return 'Function';
    return 'Unknown';
}
Oct(Number)=>Variant(String)
Аналог:

function Oct(number) {
    if (typeof number !== 'number' || isNaN(number) || !Number.isInteger(number)) {
        throw new TypeError('Input must be an integer.');
    }
    return number.toString(8);
}
Hex(Number)=>Variant(String)
Аналог:

function Hex(number) {
    if (typeof number !== 'number' || isNaN(number) || !Number.isInteger(number)) {
        throw new TypeError('Input must be an integer.');
    }
    return number.toString(16).toUpperCase();
}
Функции работы с объектами (4)
IsObject(Expression)=>Boolean
Аналог:

function IsObject(expression) {    return typeof expression === 'object' && expression !== null;}
GetObject([Pathname] [Class])
Аналог: Прямого аналога в JavaScript нет в связи с ограничениями, разобранными выше. Возможна частичная аналогия в частных случаях.
1.Непосредственная работа с объектами в JavaScript.

const myObject = {    //Объект
    name: 'John',
    age: 30,
    greet: function() {
        console.log('Hello, ' + this.name);
    }
};
// Доступ к свойствам объекта
console.log(myObject.name); // John
myObject.greet(); // Hello, John
2.Объекты в DOM.

const myElement = document.getElementById('myElementId');
console.log(myElement);
3.Объекты API через fetch()

fetch('https://api.example.com/data')
    .then(response => response.json())
    .then(data => {
        console.log('Data from API:', data);
    })
    .catch(error => {
        console.error('Error fetching data:', error);
    });
4.Node.js

const fs = require('fs');
// Чтение содержимого файла
fs.readFile('path/to/file.txt', 'utf8', (err, data) => {
    if (err) {
        console.error('Error reading file:', err);
        return;
    }
    console.log('File content:', data);
});
GetAutoServerSettings([Progid], [CLSID])=>Variant
Аналог: Прямого аналога в JavaScript нет в связи с ограничениями, разобранными выше.
CreateObject(Class,[ServerName])=>Object
Аналог: Прямого аналога в JavaScript нет в связи с ограничениями, разобранными выше.
Для общего развития в Node.js:

const fs = require('fs'); // Built-in Node.js module for file system operations
// Create an instance of a class from a Node.js module
fs.readFile('example.txt', 'utf8', (err, data) => {
    if (err) throw err;
    console.log(data);
});
Функции форматирования (5)
FormatPercent(Expression[,NumDigitsAfterDecimal [,IncludeLeadingDigit [,UseParensForNegativeNumbers [,GroupDigits]]]])=>String or Number
Аналог:

function formatPercent(value, numDigitsAfterDecimal = 2, includeLeadingDigit = true, useParensForNegativeNumbers = false, groupDigits = false) {
    // Convert value to a percentage
    let percentage = (value * 100).toFixed(numDigitsAfterDecimal);
    // Handle leading zero
    if (!includeLeadingDigit && percentage.startsWith('0.')) {
        percentage = percentage.slice(1); // Remove the leading zero
    }
    // Handle grouping of digits
    if (groupDigits) {
        let parts = percentage.split('.');
        parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); // Add commas for thousands
        percentage = parts.join('.');
    }
    // Handle parentheses for negative numbers
    if (useParensForNegativeNumbers && value < 0) {
        percentage = `(${percentage})`;
    } else if (value < 0) {
        percentage = `-${percentage}`;
    }
    // Append percentage sign
    return `${percentage}%`;
}
// Примеры использования
console.log(formatPercent(0.12345)); // "12.35%"
console.log(formatPercent(0.12345, 1)); // "12.3%"
console.log(formatPercent(0.12345, 2, false)); // "12.35%"
console.log(formatPercent(-0.12345, 2, true, true)); // "(12.35%)"
console.log(formatPercent(12345.678, 2, true, false, true)); // "1,234,567.68%"
FormatNumber(Expression[,NumDigitsAfterDecimal [,IncludeLeadingDigit [,UseParensForNegativeNumbers [,GroupDigits]]]])=>Variant(String)
Аналог:

function formatNumber(value, numDigitsAfterDecimal = 2, includeLeadingDigit = true, useParensForNegativeNumbers = false, groupDigits = false) {
    let formattedNumber = value.toFixed(numDigitsAfterDecimal);
    // Обработка ведущего нуля
    if (!includeLeadingDigit && formattedNumber.startsWith('0.')) {
        formattedNumber = formattedNumber.slice(1); // Удаляем ведущий ноль
    }
    // Обработка группировки цифр (тысячные разделители)
    if (groupDigits) {
        let parts = formattedNumber.split('.'); // Разделяем целую и дробную части
        parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); // Добавляем запятые для тысячных
        formattedNumber = parts.join('.'); // Соединяем части обратно
    }
    // Обработка скобок для отрицательных чисел
    if (useParensForNegativeNumbers && value < 0) {
        formattedNumber = `(${formattedNumber})`; // Оборачиваем отрицательное число в скобки
    } else if (value < 0) {
        formattedNumber = `-${formattedNumber}`; // Добавляем минус перед числом
    }
    return formattedNumber;
}
// Примеры использования
console.log(formatNumber(12345.6789, 1)); // "12,345.7" - 1 знак после запятой
console.log(formatNumber(12345.6789, 2, false)); // "12,345.68" - ведущий ноль не включается
console.log(formatNumber(-12345.6789, 2, true, true)); // "(12,345.68)" - отрицательное число в скобках
console.log(formatNumber(12345.6789, 2, true, false, true)); // "12,345.68" - группировка цифр включена
FormatDateTime(Date[,NamedFormat])=>Variant(String)
Аналог:

function formatDateTime(date, namedFormat) {
    if (!(date instanceof Date)) {
        throw new TypeError("Первый аргумент должен быть объектом Date.");
    }
    // Если формат не указан, используем формат по умолчанию (краткий формат даты и времени)
    namedFormat = namedFormat || "short";
    // Функция для добавления нулей в однозначные числа
    const pad = (num) => num.toString().padStart(2, '0');
    // Определяем форматирование в зависимости от указанного namedFormat
    switch (namedFormat.toLowerCase()) {
        case "short":
            // Краткий формат даты и времени
            return `${pad(date.getDate())}/${pad(date.getMonth() + 1)}/${date.getFullYear()}
                            ${pad(date.getHours())}:${pad(date.getMinutes())}`;
        case "long":
            // Длинный формат даты и времени
            return `${date.getDate()} ${date.toLocaleString('default', { month: 'long' })} ${date.getFullYear()}, 
                          ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
        case "shortdate":
            // Краткий формат даты
            return `${pad(date.getDate())}/${pad(date.getMonth() + 1)}/${date.getFullYear()}`;
        case "longdate":
            // Длинный формат даты
            return `${date.getDate()} ${date.toLocaleString('default', { month: 'long' })} ${date.getFullYear()}`;
        case "shorttime":
            // Краткий формат времени
            return `${pad(date.getHours())}:${pad(date.getMinutes())}`;
        case "longtime":
            // Длинный формат времени
            return `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
        default:
            throw new Error("Неизвестный формат даты/времени.");
    }
}
// Примеры использования
const now = new Date();
console.log(formatDateTime(now)); // Краткий формат даты и времени по умолчанию
console.log(formatDateTime(now, "short")); // Краткий формат даты и времени
console.log(formatDateTime(now, "long")); // Длинный формат даты и времени
console.log(formatDateTime(now, "shortdate")); // Краткий формат даты
console.log(formatDateTime(now, "longdate")); // Длинный формат даты
console.log(formatDateTime(now, "shorttime")); // Краткий формат времени
console.log(formatDateTime(now, "longtime")); // Длинный формат времени
FormatCurrency(Expression[,NumDigitsAfterDecimal
[,IncludeLeadingDigit,[UseParensForNegativeNumbers[,GroupDigits]]]])=>
Variant(String)

Аналог:

function formatCurrency(expression, numDigitsAfterDecimal = 2, includeLeadingDigit = false,
                              useParensForNegativeNumbers = false, groupDigits = true) {
    if (typeof expression !== 'number' || isNaN(expression)) {
        throw new TypeError("Первый аргумент должен быть числом.");
    }
    // Создаем объект Intl.NumberFormat для форматирования чисел в денежном формате
    const options = {
        style: 'currency',
        currency: 'USD', // Установите валюту по умолчанию, если необходимо
        minimumFractionDigits: numDigitsAfterDecimal,
        maximumFractionDigits: numDigitsAfterDecimal,
        useGrouping: groupDigits
    };
    // Создаем экземпляр Intl.NumberFormat
    const formatter = new Intl.NumberFormat('en-US', options);
    // Форматируем число
    let formattedNumber = formatter.format(expression);
    // Если нужно добавить ведущий ноль, если число меньше 1
    if (includeLeadingDigit && expression < 1 && expression > -1) {
        formattedNumber = formattedNumber.replace(/^(?!\$\s*0)/, '$0');
    }
    // Если нужно использовать скобки для отрицательных чисел
    if (useParensForNegativeNumbers && expression < 0) {
        formattedNumber = formattedNumber.replace(/^\(\$/, '$(').replace(/\)$/, ')');
    }
    return formattedNumber;
}
// Примеры использования
console.log(formatCurrency(1234.567)); // Форматирование с двумя знаками после запятой и группировкой
console.log(formatCurrency(1234.567, 3)); // Форматирование с тремя знаками после запятой
console.log(formatCurrency(1234.567, 2, true)); // Форматирование с ведущим нулем, если число < 1
console.log(formatCurrency(1234.567, 2, false, false, false)); // Форматирование без группировки
Format (Expression[, Format[, FirstDayOfWeek[, FirstWeekOfYear]]])=>Variant (String)
Аналог: Единого аналога нет. Для разных типов входных данных:
1.Число.

function formatNumber(expression, format) {
    if (typeof expression !== 'number' || isNaN(expression)) {
        throw new TypeError("Первый аргумент должен быть числом.");
    }
    // Применяем форматирование чисел, если формат задан
    if (format === 'currency') {
        return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(expression);
    } else if (format === 'percent') {
        return new Intl.NumberFormat('en-US', { style: 'percent' }).format(expression);
    } else if (format === 'fixed') {
        return expression.toFixed(2); // Форматирование числа с двумя знаками после запятой
    } else {
        return expression.toString(); // По умолчанию просто преобразуем число в строку
    }
}
// Примеры использования
console.log(formatNumber(1234.567, 'currency')); // $1,234.57
console.log(formatNumber(0.1234, 'percent')); // 12.34%
console.log(formatNumber(1234.567, 'fixed')); // 1234.57
2.Дата.

function formatDate(expression, format, firstDayOfWeek = 0, firstWeekOfYear = 0) {
    if (!(expression instanceof Date)) {
        throw new TypeError("Первый аргумент должен быть объектом Date.");
    }
    const options = {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit'
    };

    if (format === 'shortDate') {
        return new Intl.DateTimeFormat('en-US', options).format(expression);
    } else if (format === 'longDate') {
        return new Intl.DateTimeFormat('en-US', { ...options, weekday: 'long' }).format(expression);
    } else if (format === 'time') {
        return new Intl.DateTimeFormat('en-US', { hour: '2-digit', minute: '2-digit' }).format(expression);
    } else {
        return expression.toLocaleDateString(); // По умолчанию просто преобразуем дату в строку
    }
}
// Примеры использования
console.log(formatDate(new Date(), 'shortDate')); // 07/10/2024
console.log(formatDate(new Date(), 'longDate')); // Wednesday, July 10, 2024
console.log(formatDate(new Date(), 'time')); // 10:30 AM
Финансовые функции (13)
Финансовые функции имеют специализованное применение, но для некоторых задач могут облегчить процесс программирования.
SYD(Cost, Salvage, Life, Period)=>Double
Вычисление годовой амортизации фондов для заданного года с использованием метода линейной амортизации.
Аналог:

function SYD(cost, salvage, life, period) {
// life - Полный срок службы актива
// cost - Первоначальная стоимость актива
// salvage - Остаточная стоимость актива в конце срока службы
// period - Период, для которого рассчитывается амортизация
    if (life <= 0 || period <= 0 || period > life) {
        throw new Error("Некорректные значения для срока службы или периода.");
    }
    // Рассчитываем количество лет
    const sumOfYearsDigits = (life * (life + 1)) / 2;
    // Рассчитываем амортизацию для указанного периода
    const depreciation = ((cost - salvage) * (life - period + 1)) / sumOfYearsDigits;
    
    return depreciation;
}
// Примеры использования
console.log(SYD(10000, 2000, 5, 1)); // Амортизация за 1-й период
console.log(SYD(10000, 2000, 5, 2)); // Амортизация за 2-й период
console.log(SYD(10000, 2000, 5, 3)); // Амортизация за 3-й период
SLN(Cost, Salvage, Life)=>Double
Вычисление годовой амортизации фондов при фиксированных нормативах амортизации.
Аналог:

function SLN(cost, salvage, life) {
// life - Полный срок службы актива
// cost - Первоначальная стоимость актива
// salvage - Остаточная стоимость актива в конце срока службы
    if (life <= 0) {
        throw new Error("Срок службы должен быть больше нуля.");
    }
    
    // Рассчитываем амортизацию по методу прямолинейной амортизации
    const depreciation = (cost - salvage) / life;
    
    return depreciation;
}
Rate(NPer, Pmt, PV, [FV], [Due], [Guess])=>Double
Вычисление  расчета выплат по закладной (например за дом), аннуитетов или итогов накоплений при ежемесячных банковских взносах.
Аналог:

function Rate(nper, pmt, pv, fv = 0, due = 0, guess = 0.1) {
// nper - Общее количество периодов
// pmt - Платеж за период
// pv - Приведенная стоимость (сумма займа)
// fv - Будущая стоимость (в конце).
// due - Тайминг платежей: 0 - конец периода, 1 - начало периода.
// guess - Начальное предположение для процентной ставки.
    const epsMax = 1e-10; // Максимальная ошибка
    const iterMax = 50; // Максимальное количество итераций
    let y, y0, y1, x0, x1 = 0, f = 0, i = 0;
    let rate = guess;
    if (Math.abs(rate) < epsMax) {
        y = pv * (1 + nper * rate) + pmt * (1 + rate * due) * nper + fv;
    } else {
        f = Math.exp(nper * Math.log(1 + rate));
        y = pv * f + pmt * (1 / rate + due) * (f - 1) + fv;
    }
    y0 = pv + pmt * nper + fv;
    y1 = pv * f + pmt * (1 / rate + due) * (f - 1) + fv;
    x0 = 0.0;
    x1 = rate;
    i = y0 * y1 >= 0 ? 0 : 1;
    while ((Math.abs(y0 - y1) > epsMax) && (i < iterMax)) {
        rate = (y1 * x0 - y0 * x1) / (y1 - y0);
        x0 = x1;
        x1 = rate;

        if (Math.abs(rate) < epsMax) {
            y = pv * (1 + nper * rate) + pmt * (1 + rate * due) * nper + fv;
        } else {
            f = Math.exp(nper * Math.log(1 + rate));
            y = pv * f + pmt * (1 / rate + due) * (f - 1) + fv;
        }
        y0 = y1;
        y1 = y;
        i++;
    }
    return rate;
}
PV(rate, nper, pmt, fv, type)=>Double
Вычисление приведенной стоимости (Present Value) аннуитета.
Аналог:

function PV(rate, nper, pmt, fv = 0, type = 0) {
// nper - Общее количество периодов
// rate - Процентная ставка за период
// pmt - Платеж за период
// type - Тайминг платежей: 0 - конец периода, 1 - начало периода.
// fv - Будущая стоимость (в конце).
    let pv;
    if (rate === 0) {
        pv = -pmt * nper - fv;
    } else {
        pv = (-pmt * (1 + rate * type) * (1 - Math.pow(1 + rate, -nper)) / rate - fv * Math.pow(1 + rate, -nper));
    }
    return pv;
}
PPmt(Rate, Per, NPer, PV, [FV], [Due])=>Double
Вычисление платежа по основной сумме кредита (Principal Payment) на конкретный период.
Аналог:

function PPmt(rate, per, nper, pv, fv = 0, type = 0) {
// rate - Процентная ставка за период
// per - Период, для которого рассчитывается платеж
// nper - Общее количество периодов
// pv - Приведенная стоимость (сумма займа)
// fv - Будущая стоимость (в конце).
// type - Тайминг платежей: 0 - конец периода, 1 - начало периода.
    const pmt = Pmt(rate, nper, pv, fv, type);    
    // Рассчитываем процентный платеж на данный период
    let ipmt;
    if (type === 1) {
        if (per === 1) {
            ipmt = 0;
        } else {
            ipmt = (pv * rate) * Math.pow(1 + rate, per - 2);
        }
    } else {
        ipmt = (pv * rate) * Math.pow(1 + rate, per - 1);
    }
    // Возвращаем разницу между общим платежом и процентным платежом
    return pmt - ipmt;
}
//Рассчитывает периодический платеж по аннуитету.
function Pmt(rate, nper, pv, fv = 0, type = 0) {
    let pmt;
    if (rate === 0) {
        pmt = -(pv + fv) / nper;
    } else {
        pmt = - (pv * Math.pow(1 + rate, nper) + fv) * rate / ((1 + rate * type) * (Math.pow(1 + rate, nper) - 1));
    }
    return pmt;
}
// Примеры использования
console.log(PPmt(0.05 / 12, 1, 60, 10000)); // Платеж по основной сумме кредита на первый период
console.log(PPmt(0.05 / 12, 12, 60, 10000)); // Платеж по основной сумме кредита на двенадцатый период
NPV(Rate, ValueArray())=>Double
Вычисление приведенного на текущий момент сальдо ряда будущих финансовых операций с учетом уценки капитала по модели финансового потока. Иначе, вычисление чистой приведенной стоимости (Net Present Value) ряда денежных потоков, дисконтированных по заданной ставке.
Аналог:

function NPV(rate, valueArray) {
// rate - Дисконтная ставка за период
// {Array<number>} valueArray - Массив денежных потоков
// {number} - Чистая приведенная стоимость
    if (!Array.isArray(valueArray)) {
        throw new Error("valueArray should be an array");
    }
    let npv = 0;
    for (let i = 0; i < valueArray.length; i++) {
        npv += valueArray[i] / Math.pow(1 + rate, i + 1);
    }
    return npv;
}
// Пример использования
const rate = 0.1; // Дисконтная ставка
const cashFlows = [-1000, 300, 400, 500, 600]; // Массив денежных потоков
console.log(NPV(rate, cashFlows)); // Чистая приведенная стоимость
NPer(Rate, Pmt, PV, [FV], [Due])=>Double
Вычисление количества периодов для аннуитета на основе постоянных периодических платежей и постоянной процентной ставки.
Аналог:

function NPer(rate, pmt, pv, fv = 0, due = 0) {
    if (rate === 0) {
        return -(pv + fv) / pmt;
    } else {
        const adjustedRate = 1 + rate * due;
        return Math.log((pmt * adjustedRate - fv * rate) / (pv * rate + pmt * adjustedRate)) / Math.log(1 + rate);
    }
}
// Примеры использования
const rate = 0.05; // Процентная ставка за период
const pmt = -200; // Платеж за период
const pv = 1000; // Приведенная стоимость
const fv = 0; // Будущая стоимость (по умолчанию 0)
const due = 0; // Платежи в конце периода (по умолчанию)
console.log(NPer(rate, pmt, pv, fv, due)); // Количество периодов
MIRR(ValueArray(), FinanceRate, ReinvestRate)=>Double
Вычисление модифицированной внутренней нормы прибыли для ряда периодических денежных потоков.
Аналог:

function MIRR(values, financeRate, reinvestRate) {
    let npvPositive = 0;
    let npvNegative = 0;
    for (let i = 0; i < values.length; i++) {
        if (values[i] > 0) {
            npvPositive += values[i] / Math.pow(1 + reinvestRate, i);
        } else {
            npvNegative += values[i] / Math.pow(1 + financeRate, i);
        }
    }
    if (npvNegative === 0 || npvPositive === 0) {
        return 0;
    }
    const totalPeriods = values.length - 1;
    const mirr = 
        Math.pow(-npvPositive * Math.pow(1 + reinvestRate, totalPeriods) / npvNegative, 1 / totalPeriods) - 1;    
    return mirr;
}
// Пример использования
const values = [-1000, 200, 300, 400, 500]; // Пример денежных потоков
const financeRate = 0.05; // Процентная ставка для отрицательных денежных потоков
const reinvestRate = 0.10; // Процентная ставка для положительных денежных потоков
console.log(MIRR(values, financeRate, reinvestRate));
IRR(ValueArray()[,Guess])=>Double
Вычисление внутренней нормы прибыли для ряда периодических денежных потоков.
Аналог:

function IRR(values, guess = 0.1) {
    const maxIteration = 1000;
    const precision = 1e-7;
    let rate = guess;
    let iteration = 0;
    let newRate;
    while (iteration < maxIteration) {
        let npv = 0;
        let dNpV = 0;
        for (let i = 0; i < values.length; i++) {
            npv += values[i] / Math.pow(1 + rate, i);
            dNpV -= (i * values[i]) / Math.pow(1 + rate, i + 1);
        }
        newRate = rate - npv / dNpV;
        if (Math.abs(newRate - rate) < precision) {
            return newRate;
        }
        rate = newRate;
        iteration++;
    }
    throw new Error("IRR calculation did not converge");
}
// Пример использования
const values = [-1000, 200, 300, 400, 500]; // Пример денежных потоков (расходы/доходы)
const guess = 0.1; // Начальное предположение для IRR (необязательно)
console.log(IRR(values, guess)); // Результат: внутренняя норма прибыли
IPmt(Rate,Per,NPer,PV[,FV[,Due]])=>Double
Вычисление процентного платежа за определенный период инвестиции, основанного на фиксированных периодических платежах и фиксированной процентной ставке.
Аналог:

function IPmt(rate, per, nper, pv, fv = 0, type = 0) {
    if (per < 1 || per > nper) {
        throw new Error("Период должен быть между 1 и общим количеством периодов (nper).");
    }
    // Рассчитываем общую сумму платежа (PMT)
    const PMT = (rate !== 0) 
        ? (pv * rate * Math.pow(1 + rate, nper) + fv * rate) / (Math.pow(1 + rate, nper) - 1)
        : (pv + fv) / nper;
    // Рассчитываем процентную часть платежа
    const IPMT = (rate !== 0)
        ? (pv * Math.pow(1 + rate, per - 1)) * rate - (type === 1 ? PMT / (1 + rate) : 0)
        : pv * rate;
    return IPMT;
}
// Пример использования
const rate = 0.05 / 12; // Месячная процентная ставка
const per = 5; // Номер периода
const nper = 360; // Общее количество периодов
const pv = 100000; // Приведенная стоимость
const fv = 0; // Будущая стоимость (по умолчанию 0)
const type = 0; // Платеж в конце периода (по умолчанию 0)
console.log(IPmt(rate, per, nper, pv, fv, type)); // Результат: процентный платеж
FV(Rate, NPer, Pmt[, PV[, Due]])=>Double
Вычисление будущей стоимости инвестиции или сбережений на основе фиксированных периодических платежей и фиксированной процентной ставки.
Аналог:

function FV(rate, nper, pmt, pv = 0, due = 0) {
    if (rate === 0) {
        return -(pv + pmt * nper);
    }
    const typeAdjustment = due === 1 ? 1 : 0;
    const futureValue = -((pv * Math.pow(1 + rate, nper)) + (pmt * (1 + rate * typeAdjustment) * ((Math.pow(1 + rate, nper) - 1) / rate)));
    return futureValue;
}
// Пример использования
const rate = 0.05 / 12; // Месячная процентная ставка
const nper = 360; // Общее количество периодов
const pmt = -1000; // Ежемесячный платеж
const pv = 0; // Приведенная стоимость (по умолчанию 0)
const due = 0; // Платеж в конце периода (по умолчанию 0)
console.log(FV(rate, nper, pmt, pv, due)); // Результат: будущая стоимость
DDB(Cost, Salvage, Life, Period, [Factor])=>Double
Вычисление амортизации по методу двойного уменьшающегося остатка за определенный период.
Аналог:

function DDB(cost, salvage, life, period, factor = 2) {
    let bookValue = cost;
    let depreciation = 0;
    for (let i = 1; i <= period; i++) {
        depreciation = Math.min((bookValue * factor) / life, bookValue - salvage);
        bookValue -= depreciation;
    }
    return depreciation;
}
// Пример использования
const cost = 10000; // Начальная стоимость
const salvage = 1000; // Ликвидационная стоимость
const life = 5; // Срок службы (в периодах)
const period = 3; // Период для которого рассчитывается амортизация
const factor = 2; // Коэффициент ускорения (по умолчанию 2)
console.log(DDB(cost, salvage, life, period, factor)); // Результат: амортизация за указанный период
Функции работы с датами и временем (21)
Year(Date)=>Variant(Integer)
Аналог:

function getYear(date) {    return date.getFullYear();}