/** * NUMLETRAS para Google Sheets (Apps Script) y referencia del algoritmo que siguen la fórmula LAMBDA y el módulo VBA. * Devuelve el importe en pesos con el formato de cheques y facturas: «MIL DOSCIENTOS TREINTA Y CUATRO PESOS 56/100 M.N.». * Límite: importes de 0 a 999,999,999,999.99 (la precisión de una hoja de cálculo no alcanza más). * * Uso en Sheets: Extensiones › Apps Script, pegar este archivo y usar =NUMLETRAS(A1) en la hoja. * @param {number} numero Importe positivo, con o sin centavos. * @return {string} Cantidad con letra en pesos mexicanos. * @customfunction */ function NUMLETRAS(numero) { var U = ['', 'UN', 'DOS', 'TRES', 'CUATRO', 'CINCO', 'SEIS', 'SIETE', 'OCHO', 'NUEVE', 'DIEZ', 'ONCE', 'DOCE', 'TRECE', 'CATORCE', 'QUINCE', 'DIECISÉIS', 'DIECISIETE', 'DIECIOCHO', 'DIECINUEVE', 'VEINTE', 'VEINTIÚN', 'VEINTIDÓS', 'VEINTITRÉS', 'VEINTICUATRO', 'VEINTICINCO', 'VEINTISÉIS', 'VEINTISIETE', 'VEINTIOCHO', 'VEINTINUEVE']; var D = ['', '', '', 'TREINTA', 'CUARENTA', 'CINCUENTA', 'SESENTA', 'SETENTA', 'OCHENTA', 'NOVENTA']; var C = ['', 'CIENTO', 'DOSCIENTOS', 'TRESCIENTOS', 'CUATROCIENTOS', 'QUINIENTOS', 'SEISCIENTOS', 'SETECIENTOS', 'OCHOCIENTOS', 'NOVECIENTOS']; // 1 a 999, siempre delante de un sustantivo (pesos, mil, millones): un, veintiún, treinta y un. function tres(x) { if (x === 100) return 'CIEN'; var h = Math.floor(x / 100); var r = x % 100; var resto = r < 30 ? U[r] : D[Math.floor(r / 10)] + (r % 10 > 0 ? ' Y ' + U[r % 10] : ''); return (C[h] + ' ' + resto).trim(); } // 1 a 999,999: «mil», no «un mil». function seis(x) { var miles = Math.floor(x / 1000); var resto = x % 1000; var parte = miles === 0 ? '' : miles === 1 ? 'MIL' : tres(miles) + ' MIL'; return (parte + ' ' + (resto > 0 ? tres(resto) : '')).trim(); } if (typeof numero !== 'number' || !isFinite(numero) || numero < 0 || numero >= 1e12) { return 'Escribe un importe de 0 a 999,999,999,999.99'; } // Desplazar el decimal de la representación de entrada evita 1.005 * 100 = 100.499999... // También contempla la notación científica que usa Number.toString para valores pequeños. var partes = String(numero).split('e'); var total = Math.round(Number(partes[0] + 'e' + (Number(partes[1] || 0) + 2))); if (total >= 1e14) return 'El redondeo supera el límite de 999,999,999,999.99'; var entero = Math.floor(total / 100); var centavos = total % 100; var millones = Math.floor(entero / 1e6); var bajo = entero % 1e6; var texto; if (entero === 0) { texto = 'CERO'; } else { var parteMillones = millones === 0 ? '' : millones === 1 ? 'UN MILLÓN' : seis(millones) + ' MILLONES'; texto = (parteMillones + ' ' + (bajo > 0 ? seis(bajo) : '')).trim(); } var moneda = entero === 1 ? 'PESO' : (millones > 0 && bajo === 0 ? 'DE PESOS' : 'PESOS'); return texto + ' ' + moneda + ' ' + (centavos < 10 ? '0' : '') + centavos + '/100 M.N.'; }