アプリを開発していて、そのデータをGoogleスプレッドシートで管理したいと思うことが多々あります。表計算ではありますが、データベースのように使っている方も多いでしょう。

そこで、本記事ではGoogleスプレッドシートをAPI化する2つの方法をご紹介します。

GoogleスプレッドシートをAPI化する2つのアプローチ

手軽に始めたい人向け:GASで簡易的にAPI化する方法

GoogleスプレッドシートをAPI化する簡易的な方法として、GAS(Google Apps Script)を使う方法があります。GASはGoogleが提供するJavaScriptベースのスクリプト環境で、Googleスプレッドシートを操作するためのAPIが用意されています。

以前、Google スプレッドシートを データベース代わりに使うには? 初心者でもできるAPI連携の始め方 – モナカプレスの記事で紹介したSheetToRESTというライブラリを使った場合、以下のようなコードでWebアプリを作成できます。

const sheetName = 'YOUR_SHEET_NAME';

// 取得系処理用
function doGet(e) {
  const sheet = SpreadsheetApp.getActive().getSheetByName(sheetName);
  const { action, limit, skip, term, id } = e.parameter;
  switch ((action || '').toUpperCase()) {
    case 'ONE': // 1件取得
      return SheetToRest.get(sheet, id);
    case 'FIND': // 検索
      return SheetToRest.find(sheet, term);
    case 'COUNT': // カウント
      return SheetToRest.count(sheet);
    default: // 一覧取得
      return SheetToRest.list(sheet, limit, skip);
  }
}

function doPost(e) {
  const sheet = SpreadsheetApp.getActive().getSheetByName(sheetName);
  const { action, id } = e.parameter;
  switch ((action || '').toUpperCase()) {
    case 'UPDATE': { // データ更新
      const params = JSON.parse(e.postData.getDataAsString());
      return SheetToRest.update(sheet, id, params);
    }
    case 'DELETE': // データ削除
      return SheetToRest.remove(sheet, id);
    default: { // データ登録
      const params = JSON.parse(e.postData.getDataAsString());
      return SheetToRest.create(sheet, params);
    }
  }
}

このコードの中では認証は行っていませんので、独自の仕組みが必要です。ただし、Google Apps Scriptではヘッダー情報は受け取れないので、クエリパラメータでトークンを渡すなどの工夫が必要です。

本番利用・拡張性重視:Google Sheets APIを使った本格的な方法

より本格的に使う場合には、Googe Sheets APIを使う方法がおすすめです。Googe Sheets APIを使う場合には、Google Cloud Platformでプロジェクトを作成し、APIを有効化する必要があります。

あらかじめ固定のシートIDを使う場合には、Sheets APIを有効にしてください。シートIDが不定、たとえばユーザーにファイル一覧から選択させる場合には、Drive APIも有効にする必要があります。

プロジェクトのクライアントキーやシークレットキーをアプリの中に組み込むのはセキュリティ的に問題があるので、別途Webアプリケーションを用意し、そこからGoogle Sheets APIを呼び出すのが良いでしょう。例えばGoogle Cloud Runや、Cloudflare Workers、AWS Lambdaなどを使う方法があります。

もしCloudflareを使う場合には、実行エンジンがNode.jsではないので下記の googleapis は利用できないので注意してください。

スプレッドシート一覧を取得する方法

以下は、Node.jsでGoogle Sheets APIを使って、シート一覧を取得するサンプルコードです(Expressを利用)。まず、認証を行ってアクセストークンとリフレッシュトークンを取得します。その後、Drive APIを使ってスプレッドシートの一覧を取得します。

import express from "express";
import { google } from "googleapis";

// Google OAuth2 クライアントの設定
const oauth2Client = new google.auth.OAuth2(
  process.env.GOOGLE_CLIENT_ID,
  process.env.GOOGLE_CLIENT_SECRET,
  process.env.GOOGLE_REDIRECT_URI
);

// スコープ(Google Sheets と Drive)
const SCOPES = [
  "https://www.googleapis.com/auth/spreadsheets",
  "https://www.googleapis.com/auth/drive",
];

// 認証URLへリダイレクト
app.get("/auth", (req, res) => {
  const url = oauth2Client.generateAuthUrl({
    access_type: "offline",
    scope: SCOPES,
    prompt: "consent",
  });
  res.redirect(url);
});

// 認証後のコールバック処理
app.get("/oauth2callback", async (req, res) => {
  const code = req.query.code;
  if (!code) {
    return res.status(400).send("Authorization code missing.");
  }

  try {
    // トークンを取得
    const { tokens } = await oauth2Client.getToken(code);
    oauth2Client.setCredentials(tokens);    
    const drive = google.drive({ version: "v3", auth: oauth2Client });
    // Google スプレッドシートのみ取得するクエリ
    const query = "mimeType='application/vnd.google-apps.spreadsheet' and trashed=false";
    const response = await drive.files.list({
      q: query,
      fields: "files(id, name, modifiedTime, owners)",
      pageSize: 20, // 最大取得件数(必要に応じて調整)
    });

    const files = response.data.files || [];
    if (files.length === 0) return res.send("<p>スプレッドシートが見つかりませんでした。</p>");

    // 結果をHTMLで表示
    const html = `
      <h2>スプレッドシート一覧</h2>
      <ul>
        ${files
          .map(
            (f) =>
              `<li>
                <b>${f.name}</b>(ID: ${f.id})<br>
                更新日: ${f.modifiedTime}<br>
                所有者: ${f.owners?.[0]?.emailAddress || "不明"}
              </li>`
          )
          .join("")}
      </ul>
    `;
    res.send(html);
  } catch (err) {
    console.error(err);
    res.status(500).send("Error retrieving access token");
  }
});

// 起動
app.listen(port, () => {
  console.log(Server running at http://localhost:${port});
});

スプレッドシートのデータを取得・更新する方法

その後、指定したシートIDの情報を取得するには、以下のようなコードを追加します。以下の場合は、A1セルの値を取得しています。

const sheets = google.sheets({ version: "v4", auth: oauth2Client });
const response = await sheets.spreadsheets.values.get({
  spreadsheetId, // 取得したいスプレッドシートのID
  range: 'A1', // 最初のシートのA1セルを取得
});
const value = response.data.values?.[0]?.[0];
console.log('A1セルの値:', value);

更新する場合には、以下のようなコードを使います。

// A1セルを更新
const response = await sheets.spreadsheets.values.update({
  spreadsheetId,
  range: "A1",
  valueInputOption: "USER_ENTERED", // ユーザーが入力した形式で反映(数式などもOK)
  requestBody: {
    values: [['Hello, World!']],
  },
});

GoogleスプレッドシートをAPI公開する際の注意点

Googleスプレッドシートを外部公開する上で懸念すべき点は以下の通りです。

  • 不特定多数からアクセスさせても問題ないか?
  • 読み取り専用か、更新・削除・追加まで許可するか?

不特定多数からアクセスさせても問題ないか?

Google Sheet APIを使う場合、APIキー(プロジェクト)ごとにレートリミットがあります。使用制限  |  Google Sheets  |  Google for Developersによれば、1分あたり300件のリクエストが上限です。さらに1ユーザーあたり、60回/分という制限があります。

リクエストサイズについてはハードリミットはありませんが、Googleの推奨として最大ペイロードは2MBまでにするのが良いとされています。

読み取り専用か、更新・削除・追加まで許可するか?

データ公開のみとする場合には、SSSAPIのようなサービスを使うのが手軽です。読み取り専用なので、セキュリティ面でも安心です。

他の操作(更新、削除、作成)も可能にする場合には、Google Sheets APIまたはApps Scriptを使う必要があります。いずれの場合においても、セキュリティが重要になります。Google Sheets APIを使う場合には、サービスアカウントを使ってアクセス制御を行います。Apps Scriptの場合には、独自の認証を実装する必要があります。

Googleスプレッドシートはデータベースではないので、型が指定できるわけではありません。同じ列の値でも、数字や文字列、日付が混在することがあります。取得した値の検証を行わないと、意図しない動作をする可能性があります。

また、同時操作の競合が発生する可能性があります。複数のユーザーが同じシートを同時に更新する場合、最後に更新した内容が反映されるため、データの整合性が保たれないことがあります。必要に応じてロック機構を実装するなどの対策が必要です。

最後にデータの削除です。行のデータを削除すると、以降の行が繰り上がるため、IDなどで特定して削除する場合には注意が必要です。そのため、行の削除ではなく、論理削除(削除フラグを立てるなど)や行の内容をクリアする(空文字にする)方法を検討してください。

何よりレートリミットがありますので、データの取得はキャッシュ(加えて定期的な更新)するなどの工夫が必要です。もしキャッシュを行う場合には、スプレッドシート側での更新はデータの不整合につながるので、アプリケーションを介してのみ更新するなど運用ルールが必要でしょう。

まとめ:用途に応じたGoogleスプレッドシートAPI化の選び方

今回はGoogleスプレッドシートをAPI化する2つの方法をご紹介しました。簡易的に使う場合にはGASを使う方法が手軽ですが、セキュリティ面での工夫が必要です。より本格的に使う場合にはGoogle Sheets APIを使う方法がおすすめです。

展示会などのデモでは、GAS版を使うことで、手早くAPI化できるので便利です。ぜひ試してみてください。