Google Sheets API:在表格中使用 Narwhal API

你可以通过 Narwhal API 把节假日、发布日期、经济数据、大宗商品现货价格、汇率和预测市场概率拉取到 Google 表格。用 Apps Script 把数据写入不同的标签页,再添加基于时间的触发器,就能按计划刷新。

你将完成的设置

Apps Script 通过 UrlFetchApp 把你的表格连接到 API。你会得到每个数据领域各一个标签页,以及用同一个 API 密钥填充它们的 pullAll 函数。密钥保存在脚本属性中,脚本发出请求时读取它。REST 和 MCP 在各个数据 API 中共用该密钥。基础 URL 为 https://api.narwhalapi.com,每个数据调用都使用 GET。

设置你的 API 密钥

  1. 创建免费密钥 获取一个免费的 Narwhal API 密钥。请保留好这个密钥,用于稍后在编辑器中添加的脚本属性;切勿把它写进表格单元格。
  2. 打开 Apps Script 在 Google 表格中打开“扩展程序”菜单,选择 Apps Script。你将在这里添加脚本,并设置它对密钥的访问。
  3. 把密钥存入脚本属性 在“项目设置”中,添加一个名为 NARWHAL_API_KEY 的脚本属性,并把值设为你的密钥。脚本通过 PropertiesService.getScriptProperties() 读取它,并放在 Authorization 请求头中发送,格式为 Bearer YOUR_KEY。

用 Apps Script 获取数据

  1. 创建数据标签页 创建名为 Holidays、Releases、CPI、Brent、FX 和 Fed 的标签页。脚本靠这些名称找到每个响应的写入位置,所以请完全按原样命名。
  2. 添加脚本 把这段代码粘贴到 Apps Script 中。共用的 pull 辅助函数会读取每次调用指定的响应字段,并把行写入对应的标签页。Brent 的价格不在列表里,所以直接使用响应对象。
    Apps Script:六个领域
    const API = "https://api.narwhalapi.com";
    
    function pull(sheetName, path, listKey) {
      const key = PropertiesService.getScriptProperties().getProperty("NARWHAL_API_KEY");
      const res = UrlFetchApp.fetch(API + path, {
        headers: { Authorization: "Bearer " + key },
      });
      const body = JSON.parse(res.getContentText());
      const rows = listKey ? body[listKey] : [body];
      if (!rows || rows.length === 0) return; // an empty list writes nothing
      const columns = [];
      rows.forEach((row) =>
        Object.keys(row).forEach((name) => {
          // every row, so a null first value cannot hide a column
          if (
            !columns.includes(name) &&
            (row[name] === null || typeof row[name] !== "object")
          )
            columns.push(name);
        }),
      );
      const values = [columns].concat(
        rows.map((row) =>
          columns.map((name) =>
            row[name] === undefined || row[name] === null ? "" : row[name],
          ),
        ),
      );
      const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
      sheet.clear();
      // Text columns (dates, periods like 2026-09) stay plain text so Sheets does not
      // turn them into dates.
      // Decimal strings such as "1.0823" stay numbers.
      columns.forEach((name, index) => {
        const sample = rows.find(
          (row) => typeof row[name] === "string" && row[name] !== "",
        );
        if (sample && !/^-?\d+(\.\d+)?$/.test(sample[name]))
          sheet.getRange(1, index + 1, values.length, 1).setNumberFormat("@");
      });
      sheet.getRange(1, 1, values.length, columns.length).setValues(values);
    }
    
    function pullAll() {
      pull("Holidays", "/v1/calendars/holidays/USA/2026", "holidays");
      pull(
        "Releases",
        "/v1/economics/calendar?countries=USA&start_date=2026-11-01" +
          "&end_date=2026-11-30&limit=100",
        "releases",
      );
      pull("CPI", "/v1/economics/USA/cpi/observations?start=2025-09", "observations");
      pull("Brent", "/v1/commodities/spot/BRENT/USD", null);
      pull("FX", "/v1/fx/rates/USD?currencies=EUR,IDR", "rates");
      pull("Fed", "/v1/predictions/policy-paths/federal-reserve", "meetings");
    }
  3. 运行 pullAll 在编辑器中运行 pullAll 来填充各标签页。对于非空响应,辅助函数会先清空目标标签页,再写入标题行和其后的数据,所以请把公式放在这些标签页之外。空列表不会写入任何内容。它会从每一行中读取列名,因此第一个值为 null 也不会让某一列消失。

包含日期以及 2026-09 这类期间的文本列会保持为纯文本,这样表格就不会把它们转成日期。以字符串形式传来的小数,如 1.0823,则保持为数字。下面的调用使用同样的辅助函数、API 基础 URL 和脚本属性,各自指定目标标签页、请求路径和响应字段。

按计划定时运行

  1. 打开触发器 使用 Apps Script 编辑器中的时钟图标打开触发器。
  2. 添加基于时间的触发器 为 pullAll 添加一个基于时间的触发器,例如每天运行一次。它调用的函数,与你在编辑器中填充数据标签页时调用的是同一个。

自定义函数也可以调用 URL Fetch,但每次表格重新计算时它们都会重新运行,每次都会消耗一次请求;通过菜单项或基于时间的触发器运行的函数,则只写入一次值。

在 Google 表格中查询节假日

把美国 2026 年的节假日拉取到 Holidays。响应列表是 holidays,每个条目都有 date 和 name。辅助函数把这两个字段写成列,并保持日期文本不变。如果想让假日行单独放在一个标签页,就把这个调用和共用脚本一起使用。

节假日拉取
pull(
  "Holidays", "/v1/calendars/holidays/USA/2026", "holidays"
);
// Read date and name in the Holidays tab.

在 Google 表格中查询发布日期

把美国 2026 年 11 月的经济数据发布日历拉取到 Releases。从响应中读取 releases,每个条目都有 at、period、topic 和 status。这个请求针对的是发布日期;要获取各期间对应的经济数值,请使用 CPI 观测值的调用。

发布日期拉取
pull(
  "Releases",
  "/v1/economics/calendar?countries=USA&start_date=2026-11-01" +
    "&end_date=2026-11-30&limit=100",
  "releases",
);
// Read at, period, topic and status in the Releases tab.

在 Google 表格中查询经济数据

把请求起点设为 2025 年 9 月,将美国 CPI 观测值拉取到 CPI。响应列表是 observations,标签页的列是 period 和 value。第一次拉取后,请查看标题行。做环比计算时,按期间文本查找每个月,这样缺了某个月也不会让公式错位。

CPI 拉取
pull(
  "CPI", "/v1/economics/USA/cpi/observations?start=2025-09", "observations"
);
// Read period and value in the CPI tab.

要比较 2026 年 9 月与 2026 年 8 月,请在 CPI 标签页之外使用下面的公式。每个 VLOOKUP 在 CPI!A:B 中查找指定的月份;计算是用 9 月的值除以 8 月的值,再减去 1。

CPI 环比
=VLOOKUP("2026-09",CPI!A:B,2,FALSE)/VLOOKUP("2026-08",CPI!A:B,2,FALSE)-1

在 Google 表格中查询大宗商品现货价格

把以 USD 计价的 Brent 现货价格拉取到 Brent。price 字段从响应对象中读取。这个调用给列表键传入 null,所以辅助函数把整个对象当作一行,并把各字段写在对应的列名下。

Brent 拉取
pull(
  "Brent", "/v1/commodities/spot/BRENT/USD", null
);
// Read price in the Brent tab.

在 Google 表格中查询汇率

把以 USD 为基础的 EUR 和 IDR 汇率拉取到 FX。rates 列表的每个条目都有 currency 和 rate。读取该标签页时,请把这两列放在一起,让每个汇率都对应着它的货币。

汇率拉取
pull(
  "FX", "/v1/fx/rates/USD?currencies=EUR,IDR", "rates"
);
// Read currency and rate in the FX tab.

在 Google 表格中查询预测市场概率

把美联储政策路径拉取到 Fed。响应列表是 meetings,每个条目都有 resolves_at、p_cut、p_hold 和 p_hike。请把结算时间和概率一起读取,让降息、维持不变和加息的概率都对应着各自的会议。

Fed 拉取
pull(
  "Fed", "/v1/predictions/policy-paths/federal-reserve", "meetings"
);
// Read resolves_at, p_cut, p_hold and p_hike in the Fed tab.

为什么不用 IMPORTDATA 或 IMPORTXML?

IMPORTDATA 和 IMPORTXML 无法发送 Authorization 请求头。Narwhal API 请求需要 Bearer 请求头,所以要用带 UrlFetchApp 的 Apps Script 来发请求。辅助函数从脚本属性中读取密钥,并在获取响应之前加上请求头。

可以把节假日数据用于 NETWORKDAYS 吗?

可以。把 Holidays 标签页的 date 列用作 NETWORKDAYS 的假日参数。请使用该列的日期,而不是假日名称。此脚本中的假日请求提供的是美国 2026 年的假日日期。

为什么 CPI 响应的起始期间可能晚于请求的期间?

所有账户都可读取完整历史。如果序列在请求的开始日期之后才开始,响应将从其第一个观测值开始。

发布于。

后续步骤