GoogleスプレッドシートとExcelで金価格をリアルタイム取得:API活用ガイド
Apps Scriptのカスタム関数でGoogleスプレッドシートに、Power QueryでExcelに金価格をリアルタイムで取り込む方法。定期的な自動更新とAPIキーの安全な管理まで解説します。
スプレッドシートで金価格をリアルタイムに表示する
金価格の計算の多くは、今もスプレッドシートで行われています。宝石店の価格表、地金の在庫表、スクラップ金の見積もりシート、ポートフォリオの管理表などです。GoogleスプレッドシートやExcelで金価格をリアルタイムに取得すれば、ウェブサイトから数値をコピーしなくても自動で更新されます。このガイドでは、その両方を構築します。Apps Scriptを使ったGoogleスプレッドシートの=GOLDPRICE("EUR", "gram")カスタム関数と、ExcelのPower Queryテーブルです。どちらも自動で更新され、APIキーはセルに含まれません。
どちらにも少しだけコードが必要です。MetalAPIはJSONを返しますが、どちらのスプレッドシートにも、URLから取得したJSONを解析し、APIキーをヘッダーで送信できるワークシート関数はありません。Apps ScriptとPower Queryなら、その両方ができます。
MetalAPIのキーが必要です。無料アカウントを作成してください。クレジットカードは不要で、月100リクエストと毎日の価格更新が含まれています。Excelの場合は、Microsoft 365のExcelやWindows版のExcel 2016以降など、Power Query(取得と変換/Get & Transform)を使えるバージョンも必要です。価格の鮮度はプランによって決まります。Freeでは毎日、Liteでは30分ごと、Standardでは10分ごと、Enterpriseでは最短5秒ごとです。
どのレスポンスにも、各シンボルが2回ずつ含まれます。USDXAU(base=EURならEURXAU)は金1トロイオンスの価格で、接頭辞のないXAUキーはその逆数です。ここで紹介するコードは、常に接頭辞付きのキーを読み取ります。
Googleスプレッドシートで金価格をリアルタイムに取得する方法
仕組みは、スプレッドシートにバインドされた小さなApps Scriptプロジェクトです。スクリプトプロパティからキーを読み込み、UrlFetchAppで価格を取得し、CacheServiceでキャッシュして、セルで使えるカスタム関数を提供します。時間主導型のトリガーで価格を最新の状態に保ちます。
- スプレッドシートを開き、拡張機能 → Apps Script(Extensions → Apps Script)を選びます。そのファイルにバインドされたスクリプトプロジェクトが作成されます。
- Apps Scriptエディタでプロジェクトの設定(Project Settings、歯車アイコン)を開き、スクリプト プロパティ(Script Properties)までスクロールして、スクリプト プロパティを追加(Add script property)をクリックします。プロパティに
METALAPI_KEYと入力し、値にキーを貼り付けて、スクリプト プロパティを保存(Save script properties)をクリックします。 - エディタ(Editor)に戻り、
Code.gsの内容を下の2つのコードブロックに置き換えて保存します。 - 関数メニューで
refreshPricesを選び、実行(Run)をクリックします。最初の1回だけ、外部サービスへの接続とスプレッドシートの編集をスクリプトに許可するよう求められます。
APIキーをセルに入れない
キーをセルに貼り付けて、数式でURLを組み立てるのはやめましょう。セル内のキーは、スプレッドシートを開けるすべての人に見え、コピーやエクスポートのたびに一緒に渡り、削除した後も変更履歴に残ります。キーを手に入れた人は誰でも、あなたのクォータを消費できます。
より適した保存場所はスクリプトプロパティです。グリッドの一部ではないため、セル、エクスポート、変更履歴には現れません。ただし、金庫ではありません。スプレッドシートの編集権限を持つ人なら誰でも、拡張機能 → Apps Scriptを開いて読み取れます。そのため、次の点に注意してください:
- スプレッドシートごとに別のキーを使う。 そうすれば、他の連携を壊さずにキーを無効化できます。キーの作成とローテーションについては、認証ガイドをご覧ください。
- 編集権限は、キーを渡してもよい人にだけ付与する。 閲覧者やコメント可能なユーザーはスクリプトエディタを開けませんが、スプレッドシートをコピーすると、バインドされたスクリプトもコピーされます。広く共有するファイルでは、共有設定で閲覧者とコメント可能なユーザーによるコピーを無効にしてください。
- キーはヘッダーで送信する。 スクリプトは
api_keyパラメーターではなくX-API-Keyを使うため、記録されたURLにキーが残りません。 - 疑わしいときはローテーションする: 新しいキーを作成してスクリプトプロパティを更新し、ダッシュボードで古いキーを無効化します。
Googleスプレッドシート用のGOLDPRICEカスタム関数
次のコードをCode.gsに貼り付けます。METALPRICEは4種類の貴金属に対応し、GOLDPRICEは金用のショートカットです。1回のリクエストで4種類の金属がすべて返されるため、同じ通貨と単位の金と銀は、キャッシュされた1つのレスポンスを共有します。
// Googleスプレッドシート用のMetalAPI価格。APIキーはセルからではなく、
// スクリプトプロパティMETALAPI_KEY(プロジェクトの設定)から読み込む。
const API = "https://metalapi.com/api/v1";
const SYMBOLS = ["XAU", "XAG", "XPT", "XPD"];
const CACHE_SECONDS = 3600; // 1時間。Apps Scriptでは最大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, // 例外を送出せずにエラーレスポンスを返す
});
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;
}
/**
* MetalAPIから取得した貴金属の最新価格。
*
* @param {string} symbol XAU(金)、XAG(銀)、XPT(プラチナ)、XPD(パラジウム)のいずれか。
* @param {string} currency USD、EUR、GBPなどの通貨コード。デフォルトはUSD。
* @param {string} unit troy_oz(デフォルト)、gram、kilogramのいずれか。
* @param {any} refresh 任意。Prices!B1などのセル。値が変わると価格を再取得する。
* @return 金属1単位あたりの、指定した通貨での価格。
* @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;
}
/**
* MetalAPIから取得した金の最新価格。例:=GOLDPRICE("EUR", "gram")
*
* @param {string} currency USD、EUR、GBPなどの通貨コード。デフォルトはUSD。
* @param {string} unit troy_oz(デフォルト)、gram、kilogramのいずれか。
* @param {any} refresh 任意。Prices!B1などのセル。値が変わると価格を再取得する。
* @return 指定した通貨・単位あたりの金価格。
* @customfunction
*/
function GOLDPRICE(currency, unit, refresh) {
return METALPRICE("XAU", currency, unit, refresh);
}あとは、任意のセルに数式を入力します:
| 数式 | 返される値 |
|---|---|
=GOLDPRICE() | 1トロイオンスあたりの米ドル建て金価格 |
=GOLDPRICE("EUR", "gram") | 1グラムあたりのユーロ建て金価格 |
=GOLDPRICE("GBP", "kilogram") | 1キログラムあたりの英ポンド建て金価格 |
=METALPRICE("XAG", "USD", "troy_oz") | 1トロイオンスあたりの米ドル建て銀価格 |
内部の仕組みは次のとおりです:
@customfunctionを付けると、関数が数式のオートコンプリートに追加され、コメントがヘルプテキストとして表示されます。muteHttpExceptions: trueにより、例外を送出せずにエラーレスポンスが返されます。そのため、セルには#ERROR!が表示され、カーソルを合わせるとMetalAPIのコードとメッセージを確認できます。たとえば、不明な通貨なら201(invalid_base)です。CacheServiceは、各レスポンスをCACHE_SECONDSの間(最大6時間)保持します。通貨、単位、refreshの値が同じセルは、このキャッシュを共有します。- キャッシュされていない通貨と単位の組み合わせごとに1リクエストかかります。 また、数式のセルはそれぞれ個別にGoogleのサーバーを呼び出します。数百の価格セルがあるシートでは、代わりに後述の
Pricesシートを参照してください。
不明な通貨などのバリデーションエラーは課金されるため、壊れた数式は早めに修正してください。何がカウントされるかは、レート制限ガイドに掲載されています。
時間主導型トリガーでGoogleスプレッドシートの金価格を更新する
Googleスプレッドシートがカスタム関数を再実行するのは引数が変わったときで、時刻によって再実行されるわけではありません。ファイル → 設定 → 計算(File → Settings → Calculation)の再計算の設定が影響するのは、NOWやRANDなどの関数だけです。定期的に更新するには、時間主導型のトリガーで価格をシートに書き込みます。パート1の下に次のコードを追加します:
/** 最新価格を「Prices」という名前のシートに書き込む。時間主導型トリガーから実行する。 */
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);
}
/** エディタから1回実行する。refreshPricesの既存のスケジュールは置き換えられる。 */
function installTrigger() {
ScriptApp.getProjectTriggers().forEach(function (t) {
if (t.getHandlerFunction() === "refreshPrices") ScriptApp.deleteTrigger(t);
});
ScriptApp.newTrigger("refreshPrices").timeBased().everyHours(1).create();
}エディタからinstallTriggerを1回実行するか、トリガー(Triggers、時計アイコン)→ トリガーを追加(Add Trigger)で、refreshPrices、時間主導型(Time-driven)、間隔を指定して手動でトリガーを追加します。
実行のたびに1リクエストを消費し、データの時刻をPrices!B1に、その下に金属ごとに1行ずつ価格を書き込みます。Prices!B3が1トロイオンスあたりの米ドル建て金価格です。これらのセルを直接参照するか、Prices!B1をrefresh引数として渡してください。=GOLDPRICE("EUR", "gram", Prices!B1)は、トリガーが新しいデータ時刻を書き込むたびに、通貨と単位の組み合わせごとに1回だけ再取得します。時刻が変わらない週末には、まったく再取得しません。Pricesシートを別の通貨や単位にするには、refreshPrices内のfetchLatest_の引数を変更します。
間隔はプランに合わせてください。価格の更新より頻繁に更新しても、同じ値が繰り返されるだけです:
| プラン | 価格の更新 | トリガー | トリガーによる月間リクエスト数 |
|---|---|---|---|
| Free(100リクエスト) | 毎日 | .everyDays(1).atHour(6) | 約31 |
| Lite(1,000リクエスト) | 30分ごと | .everyHours(1) | 約744 |
| Standard(10,000リクエスト) | 10分ごと | .everyMinutes(10) | 約4,500 |
refresh引数付きのカスタム関数は、更新のたびに通貨と単位の組み合わせごとに1リクエストを追加で消費します。Liteで1時間ごとのトリガーにGOLDPRICE("EUR", "gram", Prices!B1)を組み合わせると月に約1,500リクエストに達し、プランの1,000を超えることがあります。.everyHours(2)を使うか、Pricesシートだけを使ってください。トリガーは予定時刻ちょうどではなくその前後に実行され、atHourはスクリプトのタイムゾーンを使います。
Power QueryでExcelに金価格を取り込む
Excelでは、Power QueryがAPIを呼び出してJSONを解析し、定期的に更新されるテーブルとして読み込みます:
- データ(Data)タブで、データの取得 → その他のデータソースから → 空のクエリ(Get Data → From Other Sources → Blank Query)を選びます。
- Power Queryエディターでホーム → 詳細エディター(Home → Advanced Editor)を選び、下のクエリを貼り付けて完了(Done)をクリックします。
https://metalapi.com/への接続方法を尋ねられたら、資格情報の編集(Edit Credentials)をクリックし、Web APIを選んでキー(Key)にキーを貼り付け、接続(Connect)をクリックします。- クエリの名前を
GoldPricesに変更し、ホーム → 閉じて読み込む(Home → Close & Load)を選びます。Excelは、クエリと同じ名前のテーブルとして新しいシートに読み込みます。
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
Typedこのクエリは、レスポンスのbaseを接頭辞にしたキー(EURならEURXAU)を読み取り、UnixのtimestampをUTCに変換します。BaseCurrencyとMassUnitは必要に応じて変更してください。
ApiKeyName = "api_key"により、キーはファイルに保存されません。Power QueryはWeb APIの資格情報からキーを取得し、api_keyクエリパラメーターとして付加します。これは、MetalAPIがキーを受け付ける3つの方法の1つです。資格情報はブックではなく、自分のコンピューター上のExcelのデータソース設定に保存されるため、ファイルを開いた同僚には、その人自身のキーの入力が求められます。資格情報の変更や削除は、データ → データの取得 → データソース設定(Data → Get Data → Data Source Settings)で行います。
Web.ContentsはHeaders = [#"X-API-Key" = "..."]も受け付けますが、その場合はキーがブック内に保存されます。自分のコンピューターから外に出ないファイルでのみ使ってください。
数式では、テーブルから価格を検索します。=XLOOKUP("XAU", GoldPrices[Symbol], GoldPrices[Price])は1グラムあたりのユーロ建て金価格を返します。古いバージョンでは、INDEXとMATCHで同じことができます。
Excelの金価格を自動で更新する
Power Queryのテーブルは自動では更新されません。データ → クエリと接続(Data → Queries & Connections)を開き、GoldPricesクエリを右クリックしてプロパティ(Properties)を選びます。更新コントロール(Refresh control)で、次の設定ができます:
- 定期的に更新する(Refresh every N minutes):タイマーでクエリを再実行します。
- ファイルを開くときにデータを更新する(Refresh data when opening the file):ブックを開くたびに最新の価格を取得します。
- バックグラウンドで更新する(Enable background refresh):クエリの実行中もExcelを操作できます。
データ → すべて更新(Data → Refresh All、Ctrl+Alt+F5)で、必要なときに更新できます。タイマーが動くのは、ブックを開いている間だけです。
1回の更新は1リクエストです。1日8時間の勤務時間中に1時間ごとに更新すると月に約180リクエスト、10分ごとなら約1,050リクエストになります。価格が毎日更新されるFreeプランでは、ファイルを開いたときの更新で十分です。
スプレッドシートとExcelで金の過去価格を扱う
過去の終値は/timeframeから取得します。start_dateからend_dateまでの取引日ごとに1件のデータが返され、1リクエストあたりFreeでは最大30日、有料プランでは最大365日分です。Excelでは、2つ目のクエリで、日付の列と金属ごとの列を持つテーブルを作成できます:
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
Typed週末や市場の休日は含まれないため、行数は暦日数より少なくなります。Apps Scriptでは、fetchLatest_が/latestを呼び出すのと同じようにUrlFetchAppで/timeframeを呼び出し、1回のsetValues呼び出しですべての行を書き込みます。
過去の終値は変わらないため、一度読み込んだ期間はそのまま保存しておきましょう。長期間のデータの一括取得、保存、グラフ化については、APIで金・銀の過去価格を取得するをご覧ください。
次のステップ
無料アカウントを作成し、キーをスクリプトプロパティまたはWeb APIの資格情報として追加すれば、10分ほどでスプレッドシートに金価格を表示できます。Freeプランの毎日の価格は、日次の価格表やポートフォリオのシートに適しています。より新しい価格やより多くの更新が必要な場合は、料金ページでプランを比較してください。APIドキュメントには、同じ方法で呼び出せるすべてのエンドポイントが掲載されています。/convertや、有料プランで利用できるカラット別金価格の/caratも含まれます。
よくある質問
代わりにIMPORTDATAやIMPORTXMLで金価格を取り込めますか?
MetalAPIからはできません。これらの関数が読み込めるのはCSV、TSV、XML、HTMLですが、APIが返すのはJSONです。また、これらの関数はヘッダーを送信できないため、キーが数式に含まれ、すべての閲覧者に見えてしまいます。
スプレッドシートの金価格はどのくらいの頻度で更新されますか?
更新を実行した頻度で、プランが許す範囲まで更新されます。Freeでは毎日、Liteでは30分ごと、Standardでは10分ごとで、上位プランではさらに頻繁です。ニューヨーク時間の金曜17:00から日曜17:00まではスポット市場が閉まっており、価格は金曜日の終値のままです。
スプレッドシートはAPIリクエストをどれくらい使いますか?
PricesシートまたはPower Queryテーブルの更新1回につき1リクエストです。これに加えて、カスタム関数が新しい価格を取得するときに、通貨と単位の組み合わせごとに1リクエストかかります。1時間ごとのトリガーなら月に約744リクエスト、1日1回なら約31リクエストです。/usageを使えば、クォータを消費せずに使用量を確認できます。
金価格を取得するスプレッドシートを共有しても安全ですか?
キーをセルに入れなければ安全です。Googleスプレッドシートではスクリプトプロパティを使い、編集権限はキーを任せられる人だけに限定します。ExcelではWeb APIの資格情報を使います。共有するファイルごとに別のキーを使えば、個別に無効化できます。
1グラムあたりや自国通貨建ての金価格を取得できますか?
はい。=GOLDPRICE("INR", "gram")のように、通貨コードとgramまたはkilogramを渡すか、Power QueryのBaseCurrencyとMassUnitを変更してください。APIはどちらも同じスナップショットから換算します。
関連記事
XAU/USDの意味:XAU・XAG・XPT・XPDが表すもの
XAU/USDの意味を解説します。金にISO 4217の通貨コードがある理由、XAG・XPT・XPDの意味、価格やAPIデータでの表示方向の読み方までわかります。
無料の金価格API:月100リクエストでできること
無料の金価格APIを正直に解説します。MetalAPIのFreeプランの内容、キャッシュとまとめ取得で月100リクエストを有効に使う方法、アップグレードの目安を紹介します。
Pythonで金価格APIを使う:価格の取得、キャッシュ、グラフ化
Pythonで金価格APIを使う方法を解説します。requestsでの最新価格の取得、エラー処理とリトライ、レスポンスのキャッシュ、pandasの時系列とmatplotlibによるグラフ化まで紹介します。