Precio del oro en Google Sheets y Excel: precios en vivo por API
Precio del oro en vivo en Google Sheets con una función de Apps Script y en Excel con Power Query, con actualización programada y tu clave API protegida.
Precios del oro en vivo en una hoja de cálculo
Gran parte de la fijación de precios del oro sigue haciéndose en hojas de cálculo: la lista de precios de un joyero, un inventario de lingotes, una hoja de cotizaciones de oro para fundir o un seguimiento de cartera. Con un precio del oro en vivo en Google Sheets o Excel, esas cifras se actualizan solas en lugar de copiarse de un sitio web. Esta guía crea ambas cosas: una función personalizada =GOLDPRICE("EUR", "gram") en Google Sheets con Apps Script y una tabla de Power Query en Excel, ambas actualizadas automáticamente y con la clave API fuera de las celdas.
Las dos necesitan un poco de código. MetalAPI devuelve JSON, y ninguna de las dos hojas de cálculo tiene una fórmula que analice JSON desde una URL y envíe una clave API en una cabecera. Apps Script y Power Query hacen ambas cosas.
Necesitas una clave de MetalAPI: crea una cuenta gratuita, sin tarjeta de crédito, con 100 solicitudes al mes y actualización diaria de precios. Para Excel también necesitas una versión con Power Query (Obtener y transformar, Get & Transform), como Excel para Microsoft 365 o Excel 2016 y posteriores en Windows. Los precios son tan recientes como permita tu plan: a diario en Free, cada 30 minutos en Lite, cada 10 minutos en Standard y hasta cada 5 segundos en Enterprise.
Cada respuesta incluye cada símbolo dos veces: USDXAU (o EURXAU con base=EUR) es el precio de una onza troy de oro, y la clave simple XAU es su inverso. El código de esta guía siempre lee la clave con prefijo.
Cómo obtener precios del oro en vivo en Google Sheets
La configuración es un pequeño proyecto de Apps Script vinculado a tu hoja de cálculo: lee la clave de una propiedad de la secuencia de comandos, obtiene los precios con UrlFetchApp, los guarda en caché con CacheService y ofrece funciones personalizadas para tus celdas. Un activador por tiempo los mantiene actualizados.
- Abre la hoja de cálculo y elige Extensiones → Apps Script (Extensions → Apps Script). Así se crea un proyecto de Apps Script vinculado a ese archivo.
- En el editor de Apps Script, abre Configuración del proyecto (Project Settings, el icono del engranaje), desplázate hasta Propiedades de la secuencia de comandos (Script Properties) y haz clic en Añadir propiedad de secuencia de comandos (Add script property). Escribe
METALAPI_KEYcomo propiedad, pega tu clave como valor y haz clic en Guardar propiedades de la secuencia de comandos (Save script properties). - De vuelta en el Editor, sustituye el contenido de
Code.gspor los dos bloques de código de abajo y guarda. - Elige
refreshPricesen el menú de funciones y haz clic en Ejecutar (Run). Google te pide una sola vez que autorices a la secuencia de comandos a conectarse a un servicio externo y a editar la hoja de cálculo.
Mantén tu clave API fuera de las celdas
No pegues la clave en una celda para construir la URL con una fórmula. Una clave en una celda es visible para cualquiera que pueda abrir la hoja de cálculo, viaja con cada copia y exportación, y permanece en el historial de versiones después de borrarla. Quien la tenga puede gastar tu cuota.
Las propiedades de la secuencia de comandos son un lugar mejor: no forman parte de la cuadrícula, así que no aparecen en las celdas, las exportaciones ni el historial de versiones. Pero no son una caja fuerte. Cualquiera con acceso de edición a la hoja de cálculo puede abrir Extensiones → Apps Script (Extensions → Apps Script) y leerlas. Por eso:
- Usa una clave distinta para cada hoja de cálculo, para poder revocarla sin romper otras integraciones. La guía de autenticación explica cómo crear y rotar claves.
- Da acceso de edición solo a las personas a las que darías la clave. Los lectores y comentadores no pueden abrir el editor de secuencias de comandos, pero una copia de la hoja de cálculo incluye una copia de su proyecto vinculado. Para archivos muy compartidos, desactiva la opción de copiar para lectores y comentadores en la configuración de uso compartido.
- Envía la clave en una cabecera. La secuencia de comandos usa
X-API-Keyen lugar del parámetroapi_key, para que la clave no acabe en URL registradas. - Ante la duda, rota la clave: crea una nueva, actualiza la propiedad de la secuencia de comandos y después revoca la antigua en el panel.
Una función personalizada GOLDPRICE para Google Sheets
Pega esto en Code.gs. METALPRICE cubre los cuatro metales preciosos y GOLDPRICE es un atajo para el oro. Una solicitud devuelve los cuatro metales, así que el oro y la plata en la misma divisa y unidad comparten una única respuesta en caché.
// Precios de MetalAPI para Google Sheets. La clave API se lee de la
// propiedad METALAPI_KEY (Configuración del proyecto), nunca de una celda.
const API = "https://metalapi.com/api/v1";
const SYMBOLS = ["XAU", "XAG", "XPT", "XPD"];
const CACHE_SECONDS = 3600; // 1 hora; Apps Script permite hasta 21600
function fetchLatest_(base, unit) {
const key = PropertiesService.getScriptProperties().getProperty("METALAPI_KEY");
if (!key) throw new Error("Add the script property METALAPI_KEY first.");
const url = API + "/latest?base=" + encodeURIComponent(base) +
"¤cies=" + SYMBOLS.join(",") + "&unit=" + encodeURIComponent(unit);
const res = UrlFetchApp.fetch(url, {
headers: { "X-API-Key": key },
muteHttpExceptions: true, // devuelve las respuestas de error en lugar de lanzar una excepción
});
let data;
try {
data = JSON.parse(res.getContentText());
} catch (e) {
throw new Error("MetalAPI: unexpected HTTP " + res.getResponseCode() + " response");
}
if (!data.success) {
throw new Error("MetalAPI " + data.error.code + " (" + data.error.type + "): " + data.error.info);
}
return data;
}
function cachedLatest_(base, unit, refresh) {
const cache = CacheService.getScriptCache();
const cacheKey = ["latest", base, unit, refresh].join("|");
const hit = cache.get(cacheKey);
if (hit) return JSON.parse(hit);
const data = fetchLatest_(base, unit);
cache.put(cacheKey, JSON.stringify(data), CACHE_SECONDS);
return data;
}
/**
* Último precio de un metal precioso según MetalAPI.
*
* @param {string} symbol XAU (oro), XAG (plata), XPT (platino) o XPD (paladio).
* @param {string} currency Código de divisa como USD, EUR o GBP. Por defecto, USD.
* @param {string} unit troy_oz (por defecto), gram o kilogram.
* @param {any} refresh Celda opcional como Prices!B1. Cuando cambia, se vuelven a obtener los precios.
* @return El precio de una unidad del metal en la divisa.
* @customfunction
*/
function METALPRICE(symbol, currency, unit, refresh) {
const s = String(symbol || "XAU").trim().toUpperCase();
const base = String(currency || "USD").trim().toUpperCase();
const u = String(unit || "troy_oz").trim().toLowerCase();
const data = cachedLatest_(base, u, String(refresh || ""));
const price = data.rates[data.base + s];
if (price === undefined) throw new Error("No " + s + " price in " + base + ".");
return price;
}
/**
* Último precio del oro según MetalAPI, por ejemplo =GOLDPRICE("EUR", "gram").
*
* @param {string} currency Código de divisa como USD, EUR o GBP. Por defecto, USD.
* @param {string} unit troy_oz (por defecto), gram o kilogram.
* @param {any} refresh Celda opcional como Prices!B1. Cuando cambia, se vuelven a obtener los precios.
* @return El precio del oro en la divisa por unidad.
* @customfunction
*/
function GOLDPRICE(currency, unit, refresh) {
return METALPRICE("XAU", currency, unit, refresh);
}Ahora escribe una fórmula en cualquier celda (si tu configuración regional usa la coma como separador decimal, separa los argumentos con punto y coma):
| Fórmula | Devuelve |
|---|---|
=GOLDPRICE() | Oro en dólares estadounidenses por onza troy |
=GOLDPRICE("EUR", "gram") | Oro en euros por gramo |
=GOLDPRICE("GBP", "kilogram") | Oro en libras esterlinas por kilogramo |
=METALPRICE("XAG", "USD", "troy_oz") | Plata en dólares estadounidenses por onza troy |
Por dentro:
@customfunctionañade las funciones al autocompletado de fórmulas, con el comentario como texto de ayuda.muteHttpExceptions: truedevuelve las respuestas de error en lugar de lanzar una excepción, así que la celda muestra#ERROR!con el código y el mensaje de MetalAPI al pasar el cursor, como201(invalid_base) para una divisa desconocida.CacheServiceconserva cada respuesta duranteCACHE_SECONDS, como máximo seis horas. Las celdas con la misma divisa, unidad y valor de actualización la comparten.- Cada divisa y unidad sin caché cuesta una solicitud, y cada celda con fórmula es una llamada independiente a los servidores de Google. En hojas con cientos de celdas de precios, haz referencia a la hoja
Pricesque verás más abajo.
Los errores de validación, como una divisa desconocida, se facturan, así que corrige pronto las fórmulas erróneas. La guía de límites de solicitudes indica qué cuenta.
Actualiza el precio del oro en Google Sheets con un activador por tiempo
Google Sheets vuelve a ejecutar una función personalizada cuando cambian sus argumentos, no según un reloj; la opción de recálculo de Archivo → Configuración → Cálculo (File → Settings → Calculation) solo afecta a funciones como NOW y RAND (AHORA y ALEATORIO en español). Para actualizaciones programadas, deja que un activador por tiempo escriba los precios en una hoja. Añade esto debajo de la parte 1:
/** Escribe los últimos precios en una hoja llamada "Prices". Ejecútalo desde un activador por tiempo. */
function refreshPrices() {
const data = fetchLatest_("USD", "troy_oz");
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName("Prices") || ss.insertSheet("Prices");
const rows = [
["Updated", new Date(data.timestamp * 1000)],
["Symbol", data.base + " per troy oz"],
];
SYMBOLS.forEach(function (s) {
rows.push([s, data.rates[data.base + s]]);
});
sheet.getRange(1, 1, rows.length, 2).setValues(rows);
}
/** Ejecútalo una vez desde el editor. Sustituye cualquier programación existente de refreshPrices. */
function installTrigger() {
ScriptApp.getProjectTriggers().forEach(function (t) {
if (t.getHandlerFunction() === "refreshPrices") ScriptApp.deleteTrigger(t);
});
ScriptApp.newTrigger("refreshPrices").timeBased().everyHours(1).create();
}Ejecuta installTrigger una vez desde el editor, o añade el activador a mano en Activadores (Triggers, el icono del reloj) → Añadir activador (Add Trigger) con refreshPrices, Según tiempo (Time-driven) y un intervalo.
Cada ejecución cuesta una solicitud y escribe la hora de los datos en Prices!B1 y una fila por metal debajo; Prices!B3 es el oro en dólares estadounidenses por onza troy. Haz referencia directa a esas celdas, o pasa Prices!B1 como argumento de actualización: =GOLDPRICE("EUR", "gram", Prices!B1) vuelve a obtener los precios cada vez que el activador escribe una nueva hora de datos, una vez por divisa y unidad, y nunca durante un fin de semana, cuando la hora no cambia. Para tener la hoja Prices en otra divisa o unidad, cambia los argumentos de fetchLatest_ en refreshPrices.
Ajusta el intervalo a tu plan; actualizar más rápido de lo que cambian los precios solo los repite:
| Plan | Actualización de precios | Activador | Solicitudes del activador / mes |
|---|---|---|---|
| Free (100 solicitudes) | Diaria | .everyDays(1).atHour(6) | Unas 31 |
| Lite (1000 solicitudes) | Cada 30 minutos | .everyHours(1) | Unas 744 |
| Standard (10.000 solicitudes) | Cada 10 minutos | .everyMinutes(10) | Unas 4500 |
Las funciones personalizadas con el argumento de actualización añaden una solicitud por actualización para cada divisa y unidad. En Lite, un activador cada hora más GOLDPRICE("EUR", "gram", Prices!B1) puede llegar a unas 1500 solicitudes al mes, por encima de las 1000 del plan; usa .everyHours(2) o solo la hoja Prices. Los activadores se ejecutan cerca de la hora programada, no exactamente a esa hora, y atHour usa la zona horaria de la secuencia de comandos.
Precio del oro en Excel con Power Query
En Excel, Power Query llama a la API, analiza el JSON y carga una tabla que se actualiza de forma programada:
- En la pestaña Datos (Data), elige Obtener datos → De otras fuentes → Consulta en blanco (Get Data → From Other Sources → Blank Query).
- En el Editor de Power Query, elige Inicio → Editor avanzado (Home → Advanced Editor), pega la consulta de abajo y haz clic en Listo (Done).
- Cuando te pregunte cómo conectarte a
https://metalapi.com/, haz clic en Editar credenciales (Edit Credentials), elige API web (Web API), pega tu clave en Clave (Key) y haz clic en Conectar (Connect). - Cambia el nombre de la consulta a
GoldPricesy elige Inicio → Cerrar y cargar (Home → Close & Load). Excel la carga en una hoja nueva como una tabla con el nombre de la consulta.
let
BaseCurrency = "EUR",
MassUnit = "gram",
Symbols = {"XAU", "XAG", "XPT", "XPD"},
Response = Json.Document(
Web.Contents(
"https://metalapi.com/api/v1/latest",
[
Query = [base = BaseCurrency, currencies = Text.Combine(Symbols, ","), unit = MassUnit],
ApiKeyName = "api_key"
]
)
),
Updated = #datetime(1970, 1, 1, 0, 0, 0) + #duration(0, 0, 0, Response[timestamp]),
Prices = Table.FromRecords(
List.Transform(
Symbols,
(symbol) => [
Symbol = symbol,
Price = Record.Field(Response[rates], Response[base] & symbol),
Currency = Response[base],
Unit = MassUnit,
#"Updated (UTC)" = Updated
]
)
),
Typed = Table.TransformColumnTypes(
Prices,
{{"Symbol", type text}, {"Price", type number}, {"Currency", type text},
{"Unit", type text}, {"Updated (UTC)", type datetime}}
)
in
TypedLa consulta lee la clave con el prefijo del base de la respuesta (EURXAU para EUR) y convierte el timestamp Unix a UTC. Cambia BaseCurrency y MassUnit según lo que necesites.
ApiKeyName = "api_key" mantiene la clave fuera del archivo: Power Query la toma de la credencial API web (Web API) y la añade como parámetro de consulta api_key, una de las tres formas en que MetalAPI acepta una clave. La credencial se guarda en la configuración de orígenes de datos de Excel en tu equipo, no en el libro, así que a un compañero que abra el archivo se le pedirá su propia clave. Cámbiala o elimínala en Datos → Obtener datos → Configuración de origen de datos (Data → Get Data → Data Source Settings).
Web.Contents también acepta Headers = [#"X-API-Key" = "..."], pero eso guarda la clave dentro del libro. Úsalo solo con archivos que nunca salgan de tu equipo.
En las fórmulas, busca los precios en la tabla: =XLOOKUP("XAU", GoldPrices[Symbol], GoldPrices[Price]) devuelve el oro en euros por gramo (en Excel en español, la función se llama BUSCARX y, con la coma decimal, los argumentos se separan con punto y coma), y INDEX con MATCH (INDICE y COINCIDIR) hace lo mismo en versiones anteriores.
Actualiza automáticamente los precios del oro en Excel
Una tabla de Power Query no se actualiza sola. Abre Datos → Consultas y conexiones (Data → Queries & Connections), haz clic con el botón derecho en la consulta GoldPrices y elige Propiedades (Properties). En Control de actualización (Refresh control):
- Actualizar cada N minutos (Refresh every N minutes) vuelve a ejecutar la consulta con un temporizador.
- Actualizar datos al abrir el archivo (Refresh data when opening the file) obtiene precios nuevos cada vez que se abre el libro.
- Habilitar actualización en segundo plano (Enable background refresh) permite seguir usando Excel mientras se ejecuta la consulta.
Datos → Actualizar todo (Data → Refresh All; Ctrl+Alt+F5) actualiza a petición. El temporizador solo funciona mientras el libro está abierto.
Cada actualización es una solicitud. Cada hora durante una jornada laboral de ocho horas supone unas 180 al mes, y cada 10 minutos, unas 1050. En Free, donde los precios se actualizan a diario, basta con actualizar al abrir el archivo.
Precios históricos del oro en Sheets y Excel
Los precios de cierre pasados se obtienen de /timeframe: una entrada por día de negociación entre start_date y end_date, hasta 30 días por solicitud en Free y 365 en los planes de pago. En Excel, una segunda consulta proporciona una columna de fecha y una columna por metal:
let
Response = Json.Document(
Web.Contents(
"https://metalapi.com/api/v1/timeframe",
[
Query = [start_date = "2026-09-24", end_date = "2026-10-23", currencies = "XAU,XAG"],
ApiKeyName = "api_key"
]
)
),
Days = Record.ToTable(Response[rates]),
History = Table.FromRecords(
List.Transform(
Table.ToRecords(Days),
(row) => [
Date = Date.FromText(row[Name]),
Gold = Record.FieldOrDefault(row[Value], Response[base] & "XAU", null),
Silver = Record.FieldOrDefault(row[Value], Response[base] & "XAG", null)
]
)
),
Typed = Table.TransformColumnTypes(History, {{"Date", type date}, {"Gold", type number}, {"Silver", type number}})
in
TypedLos fines de semana y los festivos del mercado no aparecen, así que espera menos filas que días naturales. En Apps Script, llama a /timeframe con UrlFetchApp igual que fetchLatest_ llama a /latest y escribe todas las filas con una sola llamada a setValues.
Los cierres pasados nunca cambian, así que carga un rango una vez y consérvalo. Precios históricos del oro y la plata por API explica las cargas de periodos largos, el almacenamiento y los gráficos.
Próximos pasos
Crea una cuenta gratuita, añade la clave como propiedad de la secuencia de comandos o como credencial de API web (Web API) y tendrás el precio del oro en tu hoja de cálculo en unos diez minutos. Los precios diarios del plan Free sirven para una lista de precios diaria o una hoja de cartera; para precios más recientes o más actualizaciones, compara los planes en la página de precios. La documentación de la API enumera todos los endpoints que puedes llamar de la misma forma, incluidos /convert y /carat, este último para precios del oro por quilate en los planes de pago.
Preguntas frecuentes
¿Puedo importar los precios del oro con IMPORTDATA o IMPORTXML?
No desde MetalAPI. Esas funciones leen CSV, TSV, XML o HTML, mientras que la API devuelve JSON, y no pueden enviar una cabecera, así que la clave quedaría en la fórmula a la vista de cualquier lector.
¿Con qué frecuencia se actualiza el precio del oro en mi hoja de cálculo?
Con la frecuencia con la que lo actualices y que permita tu plan: a diario en Free, cada 30 minutos en Lite, cada 10 minutos en Standard y más rápido en los planes superiores. Desde el viernes a las 17:00 hasta el domingo a las 17:00, hora de Nueva York, el mercado al contado está cerrado y el precio se mantiene en el cierre del viernes.
¿Cuántas solicitudes a la API consumirá mi hoja de cálculo?
Una por cada actualización de la hoja Prices o de la tabla de Power Query, más una por divisa y unidad cuando las funciones personalizadas obtienen precios nuevos. Un activador cada hora supone unas 744 solicitudes al mes, y uno diario, unas 31. /usage informa de tu consumo sin contar para la cuota.
¿Es seguro compartir una hoja de cálculo que obtiene precios del oro?
Sí, si la clave se mantiene fuera de las celdas: una propiedad de la secuencia de comandos en Google Sheets, con acceso de edición solo para personas a las que confiarías la clave, y la credencial de API web en Excel. Usa una clave distinta para cada archivo compartido, para poder revocarla por separado.
¿Puedo obtener el precio del oro por gramo o en mi divisa local?
Sí. Pasa un código de divisa y gram o kilogram, como en =GOLDPRICE("INR", "gram"), o cambia BaseCurrency y MassUnit en la consulta de Power Query. La API convierte ambos a partir de la misma instantánea.
Pruébalo con tus propios datos
Crea una cuenta gratuita y haz tu primera solicitud en menos de dos minutos. 100 solicitudes al mes, sin tarjeta de crédito.
Sigue leyendo
Qué significa XAU/USD: los códigos XAU, XAG, XPT y XPD
Qué significa XAU/USD: por qué el oro tiene un código de divisa ISO 4217, qué son XAG, XPT y XPD y cómo leer el sentido de las cotizaciones y datos de API.
API gratuita de precios del oro: qué dan 100 solicitudes al mes
Una API gratuita de precios del oro explicada con honestidad: qué incluye el plan Free de MetalAPI, cómo aprovechar 100 solicitudes al mes y cuándo cambiar.
API de precios del oro en Python: consulta, caché y gráficos
Usa una API de precios del oro en Python: obtén precios en tiempo real con requests, gestiona errores y reintentos, usa caché y grafica una serie con pandas.