/** * Сумма в рублях прописью. В таблице: =RUBWORDS(A2) * Для столбца: =RUBWORDS(A2:A100), если ячейки результата пусты. * Вход: число от 0 до 999999999999,99 с точностью до копейки. * @param {number|number[][]} input Сумма или диапазон сумм. * @return {string|string[][]} Рубли словами, копейки двумя цифрами. * @customfunction */ function RUBWORDS(input) { if (Array.isArray(input)) { return input.map(row => row.map(rubwordsOne_)); } return rubwordsOne_(input); } function rubwordsOne_(value) { if (value === '' || value === null) return ''; if (typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value > 999999999999.99) { return 'Ошибка: нужна неотрицательная сумма числом'; } var scaled = value * 100; var totalKopecks = Math.round(scaled); if (Math.abs(scaled - totalKopecks) > 0.000001) { return 'Ошибка: сначала округлите сумму до копеек'; } var rubles = Math.floor(totalKopecks / 100); var kopecks = totalKopecks % 100; var units = [ ['', 'один', 'два', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять'], ['', 'одна', 'две', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять'] ]; var teens = ['десять', 'одиннадцать', 'двенадцать', 'тринадцать', 'четырнадцать', 'пятнадцать', 'шестнадцать', 'семнадцать', 'восемнадцать', 'девятнадцать']; var tens = ['', '', 'двадцать', 'тридцать', 'сорок', 'пятьдесят', 'шестьдесят', 'семьдесят', 'восемьдесят', 'девяносто']; var hundreds = ['', 'сто', 'двести', 'триста', 'четыреста', 'пятьсот', 'шестьсот', 'семьсот', 'восемьсот', 'девятьсот']; var scales = [ null, ['тысяча', 'тысячи', 'тысяч'], ['миллион', 'миллиона', 'миллионов'], ['миллиард', 'миллиарда', 'миллиардов'] ]; function form(n, variants) { var lastTwo = n % 100; if (lastTwo >= 11 && lastTwo <= 14) return variants[2]; var last = n % 10; return last === 1 ? variants[0] : last >= 2 && last <= 4 ? variants[1] : variants[2]; } function triad(n, female) { var words = []; var h = Math.floor(n / 100); var rem = n % 100; if (h) words.push(hundreds[h]); if (rem >= 10 && rem <= 19) { words.push(teens[rem - 10]); } else { var t = Math.floor(rem / 10); var u = rem % 10; if (t) words.push(tens[t]); if (u) words.push(units[female ? 1 : 0][u]); } return words.join(' '); } var words = []; for (var index = 3; index >= 0; index--) { var group = Math.floor(rubles / Math.pow(1000, index)) % 1000; if (!group) continue; words.push(triad(group, index === 1)); if (index) words.push(form(group, scales[index])); } if (!rubles) words.push('ноль'); words.push(form(rubles, ['рубль', 'рубля', 'рублей'])); words.push(String(kopecks).padStart(2, '0')); words.push(form(kopecks, ['копейка', 'копейки', 'копеек'])); var result = words.join(' '); return result[0].toUpperCase() + result.slice(1); }