😽

Node.js + TypeScript で Google スプレッドシートの商品情報をCLIから取得してコピーするまで

に公開

はじめに

Google スプレッドシートに商品マスタを管理していて、CLIから商品IDを指定すると
対応する 商品説明 (Z列)を取得し、自動的にクリップボードにコピーできるツールを作りました。
GUIで作業すると、スクロールしたりソートしたり、移動がめんどくさくて時間がかかったので。

今回はその実装手順をまとめます。ほぼAIが書いてくれたんですが、記録として残しておきます…

環境

  • Node.js 18+
  • TypeScript
  • Google Cloud Platform (サービスアカウント利用)
    *3ヶ月間の無料プラン使ってるんで、そのうち使えなくなる…😭 払えばいいんだが

1. Google Cloud 側の準備

  1. Google Cloud Consoleで新しいプロジェクトを作成
  2. API有効化
    • Google Sheets API
  3. サービスアカウント作成
  • Google Cloud Console > IAM & Admin > Service Accounts で鍵を生成
    • 鍵を JSON 形式でダウンロード(credentials.json として保存)
  1. 取得したサービスアカウントの client_email を、対象のスプレッドシートに「閲覧者」として共有

2. プロジェクト作成

mkdir product-tools
cd product-tools
npm init -y

# TypeScript と必要ライブラリを導入
npm install --save-dev typescript ts-node @types/node
npm install googleapis dotenv clipboardy

npx tsc --init

3. .env の設定

SHEET_ID=(スプレッドシートURLの /d/.../edit の部分)
SHEET_NAME=商品リスト

4. ディレクトリ構成

product-tools/
├─ src/
│   ├─ main.ts      # CLIエントリーポイント
│   └─ sheets.ts    # シート操作ロジック
├─ credentials.json # サービスアカウントの鍵
├─ .env
├─ package.json
└─ tsconfig.json

5. sheets.ts 実装

import { google } from "googleapis";

const auth = new google.auth.GoogleAuth({
  keyFile: "credentials.json",
  scopes: ["https://www.googleapis.com/auth/spreadsheets.readonly"],
});

export async function getDescription(productId: string): Promise<string | null> {
  const sheets = google.sheets({ version: "v4", auth });

  const sheetId = process.env.SHEET_ID!;
  const sheetName = process.env.SHEET_NAME!;

  // B列〜Z列をまとめて取得
  const res = await sheets.spreadsheets.values.get({
    spreadsheetId: sheetId,
    range: `${sheetName}!B:Z`,
  });

  const rows = res.data.values;
  if (!rows) return null;

  for (const row of rows) {
    const cellValue = row[0] ? row[0].toString().trim() : "";
    if (cellValue === productId.trim()) {
      return row[24] || null; // Z列(B列が index=0 なので Z列は index=24)
    }
  }

  return null;
}

6. main.ts 実装

import "dotenv/config";
import clipboard from "clipboardy";
import { getDescription } from "./sheets";

async function main() {
  const productId = process.argv[2];
  if (!productId) {
    console.error("Usage: ts-node src/main.ts <商品ID>");
    process.exit(1);
  }

  console.log(`[INFO] 商品ID: ${productId}`);

  const desc = await getDescription(productId);

  if (desc) {
    console.log(`[INFO] ディスクリプション取得: ${desc}`);
    clipboard.writeSync(desc);
    console.log("[INFO] クリップボードにコピーしました");
  } else {
    console.error("[ERROR] 該当する商品IDが見つかりませんでした");
  }
}

main();

7. 実行方法

npx ts-node src/main.ts RLPLSWT1

出力例:

[INFO] 商品ID: RLPLSWT1
[INFO] ディスクリプション取得: Ralph Lauren Polo ラルフローレン ケーブル編み クルーネック セーター XL グレー ...
[INFO] クリップボードにコピーしました

まとめ

ここまでで、

  • 商品IDをCLI引数で指定
  • スプレッドシートから対応する行を検索
  • posting description(Z列)を取得
  • 自動でクリップボードにコピー

まで実装できました。

次のステップとしては、Google Drive と連携して商品画像を自動取得・ZIP化する機能を追加する予定です 🚀

Discussion