- Blog
- Integración
Consultar RUC desde Google Sheets con Apps Script
Consulta RUC en Google Sheets con Apps Script: una función personalizada que llena razón social y estado, el token en propiedades del script y las cuotas.
Tienes una hoja con 800 proveedores: en la columna A está el RUC, la columna B debería tener la razón social y en la C el contador quiere ver si cada uno está ACTIVO y HABIDO antes de pagar. La alternativa manual es abrir la consulta de SUNAT 800 veces y copiar a mano. La alternativa buena toma veinte minutos: una fórmula =CONSULTA_RUC(A2) que llena las tres columnas sola y un menú que procesa toda la lista de una vez y deja valores fijos.
En este artículo vas a construir las dos cosas con Google Apps Script, el JavaScript que viene incluido en Google Sheets. Vas a ver dónde guardar el token para que no quede en una celda, cómo llamar a la API con UrlFetchApp, cómo convertir esa llamada en una función personalizada, cómo llenar columnas en lote y qué límites de cuota tiene Apps Script para que no te sorprendan a mitad de la lista.
Qué vas a construir
Apps Script se abre desde el menú Extensiones de cualquier hoja de cálculo. Escribes JavaScript, se ejecuta en los servidores de Google y tiene acceso a la hoja, a un almacén de propiedades, a una caché y a un cliente HTTP. No necesitas servidor propio ni instalar nada: todo vive dentro del archivo de Sheets.
Vas a crear tres funciones. Una privada, consultarRuc_, que hace la llamada a la API de RUC y devuelve el resultado o un error legible. Una función personalizada, CONSULTA_RUC, que puedes escribir en una celda como cualquier fórmula y que devuelve razón social, estado y condición en tres celdas contiguas. Y un menú que recorre la selección y escribe los resultados como valores, para que la hoja no vuelva a consultar cada vez que alguien la abre.
Lo único que necesitas de antemano es un token. Si no tienes cuenta en endpoint.pe, créala: incluye 150 consultas gratis al mes sin tarjeta, suficiente para armar y probar todo esto.
Guarda el token en las propiedades del script
La tentación es poner el token en una celda oculta o en una constante dentro del código. No lo hagas: cualquiera que abra el editor o muestre la columna lo ve, y de ahí a que termine en un correo reenviado hay un paso. Apps Script tiene un lugar pensado para esto: las propiedades del script.
En el editor de Apps Script, abre la configuración del proyecto (el ícono de engranaje) y busca la sección de propiedades del script. Añade una propiedad con el nombre ENDPOINT_TOKEN y pega el token como valor. Desde el código se lee así:
function tokenEndpoint_() {
const token = PropertiesService.getScriptProperties().getProperty('ENDPOINT_TOKEN');
if (!token) {
throw new Error('Falta ENDPOINT_TOKEN en las propiedades del script');
}
return token;
}
El guion bajo al final del nombre marca la función como privada: Apps Script no la muestra como fórmula ni permite ejecutarla desde un menú. Úsalo en todas las funciones auxiliares.
Las propiedades del script son visibles para cualquier persona con permiso de edición sobre el archivo, porque puede abrir el editor. Si compartes la hoja, hazlo como lector, o usa un token exclusivo para esa hoja que puedas revocar sin afectar a tus otros sistemas.
Las demás reglas de higiene (un token por aplicación, rotación, qué hacer si se filtra) están en seguridad de tokens de API.
La función que llama a la API
UrlFetchApp.fetch es el cliente HTTP de Apps Script. Recibe la URL y un objeto de opciones donde van las cabeceras. La opción muteHttpExceptions es clave: sin ella, cualquier respuesta que no sea 200 lanza una excepción y la celda muestra un error genérico. Con ella, tú decides qué hacer con cada código.
const BASE = 'https://api.endpoint.pe/v1';
function consultarRuc_(ruc) {
ruc = String(ruc).trim();
if (!/^\d{11}$/.test(ruc)) return { error: 'RUC inválido' };
const cache = CacheService.getScriptCache();
const enCache = cache.get('ruc:' + ruc);
if (enCache) return JSON.parse(enCache);
const res = UrlFetchApp.fetch(BASE + '/ruc/' + ruc, {
headers: { Authorization: 'Bearer ' + tokenEndpoint_() },
muteHttpExceptions: true,
});
const codigo = res.getResponseCode();
if (codigo === 404) return { error: 'No encontrado' };
if (codigo === 401) return { error: 'Token inválido' };
if (codigo === 402) return { error: 'Sin créditos' };
if (codigo === 429) return { error: 'Demasiadas consultas, espera un momento' };
if (codigo !== 200) return { error: 'HTTP ' + codigo };
const dato = JSON.parse(res.getContentText());
cache.put('ruc:' + ruc, JSON.stringify(dato), 21600); // 6 horas, el máximo
return dato;
}
Fíjate en cuatro decisiones. Primero, se valida el formato antes de llamar: once dígitos o nada, así no gastas una llamada en un RUC con un espacio al final. Segundo, se usa CacheService para recordar cada respuesta hasta seis horas (es el máximo que permite); si la misma hoja consulta el mismo RUC dos veces en la tarde, la segunda no llega a la API. Tercero, el 404 se devuelve como texto, no como excepción, porque "no encontrado" es un resultado válido y además no consume créditos. Cuarto, el resto de códigos se convierten en mensajes que un contador entiende sin leer documentación. Si quieres el detalle de cada código, está en manejo de errores y reintentos.
Úsala como fórmula en la hoja
Una función personalizada es una función normal de Apps Script con un comentario especial encima. La etiqueta @customfunction hace que Sheets la ofrezca en el autocompletado de fórmulas, con su descripción. Si la función devuelve una matriz de filas y columnas, el resultado se expande a las celdas vecinas.
/**
* Devuelve razón social, estado y condición de un RUC.
*
* @param {string} ruc RUC de 11 dígitos.
* @return {string[][]} Razón social, estado y condición en tres celdas.
* @customfunction
*/
function CONSULTA_RUC(ruc) {
if (!ruc) return [['', '', '']];
const r = consultarRuc_(ruc);
if (r.error) return [[r.error, '', '']];
return [[r.razon_social, r.estado, r.condicion]];
}
Guarda el proyecto, vuelve a la hoja y escribe en B2:
=CONSULTA_RUC(A2)
Mientras carga, la celda muestra "Loading..."; después, B2 tiene la razón social, C2 el estado y D2 la condición. Con el RUC de ejemplo 20131312955 deberías ver la razón social de SUNAT, ACTIVO y HABIDO. Arrastra la fórmula hacia abajo y la hoja se llena sola.
Dos avisos sobre las funciones personalizadas. Tienen un tiempo máximo de ejecución corto (del orden de medio minuto), así que cada una debe hacer una sola consulta; no intentes procesar un rango completo dentro de CONSULTA_RUC. Y Sheets puede volver a evaluarlas en momentos que no controlas: al abrir el archivo, al copiar la celda a otra hoja, cuando cambia una referencia. Cada evaluación que no encuentre la respuesta en la caché es una llamada a la API y un crédito. Para una lista que ya no va a cambiar, convierte las fórmulas en valores (copiar y pegar solo valores) o usa el menú de la siguiente sección.
Llenar columnas en lote con un menú
Para listas largas, una función que se ejecuta desde un menú es mejor que 800 fórmulas: controla el ritmo de las llamadas, escribe valores fijos y no se vuelve a ejecutar sola. La función onOpen es especial: Apps Script la llama cada vez que se abre la hoja y es donde se registra el menú.
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Consultas RUC')
.addItem('Completar selección', 'completarSeleccion')
.addToUi();
}
function completarSeleccion() {
const hoja = SpreadsheetApp.getActiveSheet();
const rango = hoja.getActiveRange(); // la columna con los RUC
const rucs = rango.getValues();
const salida = [];
for (let i = 0; i < rucs.length; i++) {
const ruc = rucs[i][0];
if (!ruc) {
salida.push(['', '', '']);
continue;
}
const r = consultarRuc_(ruc);
salida.push(r.error ? [r.error, '', ''] : [r.razon_social, r.estado, r.condicion]);
Utilities.sleep(150); // pausa breve entre llamadas
}
hoja
.getRange(rango.getRow(), rango.getColumn() + 1, salida.length, 3)
.setValues(salida);
}
El uso es directo: seleccionas A2:A801, abres el menú "Consultas RUC" y eliges "Completar selección". La primera vez, Google te pide autorizar el script para conectarse a un servicio externo; es normal y se hace una sola vez. Al terminar, las columnas B, C y D tienen valores, no fórmulas.
Dos mejoras que valen la pena. Con un formato condicional sobre la columna C que pinte de rojo todo lo que no sea ACTIVO, y sobre la D todo lo que no sea HABIDO, el contador ve de un vistazo a quién no debe pagar; en qué significan ACTIVO y HABIDO está la explicación de cada valor. Y si la lista supera varios cientos de filas, procesa por bloques (seleccionar 300, ejecutar, seleccionar los 300 siguientes) para no acercarte al tiempo máximo de ejecución.
Límites de Apps Script y cómo convivir con ellos
Apps Script es gratuito, pero tiene cuotas. Las que te afectan en este caso son tres, y las cifras exactas dependen del tipo de cuenta (personal o Google Workspace), así que revisa la tabla oficial de cuotas antes de planificar un proceso grande.
Llamadas HTTP por día. Hay un máximo diario de llamadas con UrlFetchApp, del orden de decenas de miles en cuentas personales y mayor en Workspace. Para una hoja de proveedores no es un problema; para un proceso que valida cientos de miles de registros, sí, y en ese caso conviene pasar a un script fuera de Sheets.
Tiempo por ejecución. Una función ejecutada desde un menú tiene un tope de varios minutos; una función personalizada, de segundos. Con una pausa de 150 milisegundos y llamadas que tardan unos cientos de milisegundos, unos 300 RUC por ejecución es un bloque seguro.
Caché de seis horas. CacheService no guarda nada más allá de ese plazo. Si necesitas conservar resultados, escríbelos como valores en la hoja o en una pestaña auxiliar que funcione como tabla de consultas con fecha, el mismo patrón que describimos en caché de consultas RUC y DNI.
Del lado de la API, el límite que puedes encontrarte es el 429 si lanzas demasiadas consultas seguidas. La pausa entre llamadas y los bloques de 300 lo evitan en la práctica. Y recuerda que cada consulta exitosa cuesta un crédito: 800 proveedores son 800 créditos la primera vez, y muchos menos las siguientes si solo revalidas los que cambian.
En resumen
- Apps Script te permite consultar RUC desde Google Sheets sin servidor propio:
UrlFetchApphace la llamada yPropertiesServiceguarda el token fuera de las celdas y del código. - La función personalizada
CONSULTA_RUCdevuelve razón social, estado y condición en tres celdas; usamuteHttpExceptionsy convierte cada código HTTP en un mensaje legible. - Las fórmulas pueden volver a evaluarse al abrir o copiar la hoja; para listas definitivas, usa el menú que escribe valores fijos.
CacheServiceevita repetir consultas durante seis horas; más allá de eso, guarda los resultados en la hoja.- Procesa en bloques de unos 300 RUC con una pausa breve entre llamadas para respetar el tiempo de ejecución y evitar el 429.
- Cualquier editor del archivo puede ver el token: comparte como lector o usa un token exclusivo para la hoja.
Preguntas frecuentes
¿Por qué mis fórmulas vuelven a consultar cuando abro el archivo?
Sheets decide cuándo recalcular una función personalizada, y abrir el archivo o copiar celdas puede disparar una nueva evaluación. La caché de seis horas amortigua el efecto, pero la solución definitiva es convertir las fórmulas en valores o llenar la lista con el menú.
¿Puedo consultar DNI con el mismo método?
Sí: la API de DNI responde al mismo patrón, cambiando la ruta a /dni/ y los campos a nombres y apellidos. Ten presente que son datos personales protegidos por la Ley 29733: no compartas esa hoja con quien no la necesite y no conserves los datos más tiempo del necesario.
¿Funciona en Excel?
No con Apps Script, que es exclusivo de Google. En Excel el camino es Power Query u Office Scripts, consumiendo la misma API con la misma cabecera de autorización. La lógica (validar formato, tratar el 404 como resultado, guardar valores) es idéntica.
¿Cuánto cuesta cada consulta desde la hoja?
Lo mismo que desde cualquier otro lugar: un crédito por consulta con resultado, nada por las que no encuentran el RUC. La cuenta gratuita incluye 150 consultas al mes, y los detalles de los planes están en la página de precios.






