
こんにちは、エンジニアのタカです。
突然ですが、Google Apps Script(以下、GAS)を実装していて、もっと効率的に作業したいと思ったことはありませんか?
GASは手軽に業務効率化できる便利なツールですが、コード管理やデプロイの面で課題を感じている方もいるかもしれません。この記事では、GAS開発の課題を解決するツール「clasp」を既存のGASプロジェクトに導入する手順を解説します。
claspとは
GitHub – google/clasp: 🔗 Command Line Apps Script Projects
claspは、Googleが提供するNode.jsのパッケージで、開発者がGASをより効率的に実装、バージョン管理、デプロイができるようにします。
claspを導入することで、具体的には以下のような利点があります。
- ローカル開発環境の構築
claspを使用することで、ローカル環境で任意のエディタやIDEを利用して実装できます。GASはプロジェクトのページに専用のエディタが提供されていますが、このエディタでの開発と比べ、コード補完やリファタクリング機能などが強力になるメリットがあります。
- TypeScriptの利用
claspは実装言語にTypeScriptを選択できます。TypeScriptで実装することで、型安全性の保証や、コードの可読性や保守性が期待できるため、直接GASを実装するよりもバグの発生を減少させることが期待できます。
- バージョン管理の容易さ
ローカル環境で実装したプログラムファイルや設定ファイルは、gitで管理することができます。GASのプロジェクトページでは手動でバージョン管理が必要ですが、gitでの管理のほうが、変更履歴を追跡したり、過去のバージョンに戻したりすることが簡単になります。
- デプロイの簡素化
GASのプロジェクトページではデプロイは手動で行いますが、claspを使用すると、TypeScript等で実装したファイルをコマンドで本来のGASの実行環境にpushしデプロイします。コマンドラインでデプロイができるため、手動でのデプロイと比べて開発の効率が向上します。
既存の運用方法についての悩み
以前、私はGASでシステム仕様を管理する記事を書きましたが、この記事で紹介したGASを本格的にシステムの開発と運用で用いるようになりました。
また、この記事とは別のGASも開発と運用で使い始めており、以下の課題を解決するため、claspを導入することにしました。
clasp導入の背景
- GASのバージョン管理が煩雑
- GASのファイル変更履歴はブラウザ上の専用のエディタでのみ確認でき、かつ以前のバージョンへの復元がプロジェクト全体でしか行えない。
- 回避手段として、GASのファイルをコピー&ペーストしてGitHubにプッシュしているが、手順が煩雑。
- 解決策:webエディタは使わず、最初からローカルで実装とgitでのバージョン管理を行う
- GASのデプロイが手動
- GASプロジェクトのデプロイボタン押下でデプロイを行っており、効率がやや悪い。
- 解決策:claspでコマンドラインからデプロイする
- ローカル開発環境がない
- 実装を専用のブラウザ上のエディタで行っており、コード補完やリファクタリング機能が不足している。
- 解決策:claspで任意のエディタを使用する
claspで管理するGASについて
今回の記事で取り上げるGASですが、前回の記事のコードは若干長いため、簡略化した専用のGASを準備しました。
GASは2ファイルで、処理の内容としては、スプレッドシートから値を読み取り、JSON形式の値に変換のうえ、ドライブに値をテキストファイルとして保存するものです。
なお、テキストファイルを出力するドライブのパス(ID)は、GASのスクリプトプロパティとして登録しておきます。

// JSON生成処理
function generateJson() {
// スプレッドシートのデータを取得する
const sheet =
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("test_sheet");
const data = sheet.getDataRange().getValues();
// JSONを格納するオブジェクトを作成する
const json = {};
// シートの各行を処理する
for (let i = 0; i < data.length; i++) {
json["app_PJ1_" + i] = { number: data[i][0], app: data[i][1] };
}
return json;
}
// メイン関数
function main() {
saveDrive(generateJson());
}
// Google Driveにファイルを保存
function saveDrive(message) {
// Google Driveの特定のフォルダにファイルを作成
const folderId = PropertiesService.getScriptProperties().getProperty(
"DRIVE_FILE_PATH_PJ1"
);
const folder = DriveApp.getFolderById(folderId);
folder.createFile(
"sample.json",
JSON.stringify(message),
MimeType.PLAIN_TEXT
);
}
clasp導入の流れとしては以下の手順で行います。
- リポジトリに元のGASをpushしておく
- 当該リポジトリをcloneしてclaspをインストールし設定を行う
- GASをTypeScriptで書き換え、リポジトリにファイルをpushする
- claspでデプロイする
なお、本来のGASのプロジェクトは2つ存在するため、前述のGASファイルをコピーし、それぞれ別のプロジェクトのGASと仮定して移行を進めます。
以下が、元のGASファイルをpushした状態のリポジトリのディレクトリ構成です。
.
├── README.md
├── project1
│ ├── drive.gs
│ └── main.gs
└── project2
├── drive.gs
└── main.gs
claspのインストールと設定
Node.jsのインストール
claspはNode.jsのパッケージなので、まずはNode.jsのインストールを行い、npmコマンドを使えるようにします。インストールは、下記の記事で解説しているasdfなどで行うのがおすすめです。
claspのインストールと設定
次に、npmコマンドでclaspをインストールし、初期設定を行います。
# package.json作成
npm init -y
# claspをインストール
npm install @google/clasp
# コーディング時に、GASの関数を表示してくれるようになるパッケージ
npm install @types/google-apps-script
# Googleアカウントでログインします (認証画面が表示されるので許可します)
clasp login
続いてclaspのコマンドで設定ファイルを作成します。今回は既存のスプレッドシートを使用するため、IDを指定します。プロジェクト単位で npm initを実行していますが、これは、claspのデプロイ時にプロジェクト単位で package.json
が必要なためです。
# それぞれのプロジェクトで、既存のidを使用してclaspプロジェクトを作成
cd project1
npm init -y
clasp create --title "Project1" --rootDir ./ --parentId "<スプレッドシートのID>"
cd ../
cd project2
npm init -y
clasp create --title "Project2" --rootDir ./ --parentId "<スプレッドシートのID>"
コマンドを実行するとclaspの設定ファイルが生成され、同時にGASのプロジェクトも新規作成されます。
なお、作成後にスプレッドシートからGASのプロジェクトを開こうとすると、スプレッドシートに紐付いているプロジェクトが複数あるため、プロジェクトの選択画面が表示されるようになります。

ここまでのディレクトリ構成
.
├── node_modules
├── README.md
├── package-lock.json
├── package.json
├── project1
│ ├── .clasp.json
│ ├── appsscript.json
│ ├── drive.gs
│ ├── main.gs
│ └── package.json
└── project2
├── .clasp.json
├── appsscript.json
├── drive.gs
├── main.gs
└── package.json
package.jsonの編集
それぞれのprojectディレクトリのpackage.jsonについては、デプロイ用のスクリプトとしてclasp pushコマンドを定義します。
"scripts": {
"deploy": "clasp push"
}
また、ルートディレクトリにあるpackage.jsonには、プロジェクトごとのデプロイ開始スクリプトを定義します。また、GASプロジェクトの画面を開くためのスクリプトも定義しておくと便利です。
"scripts": {
"deploy:project1": "cd project1 && npm run deploy",
"deploy:project2": "cd project2 && npm run deploy",
"open:project1": "cd project1 && clasp open",
"open:project2": "cd project2 && clasp open"
},
設定ファイルの編集
それぞれのprojectディレクトリの設定ファイルについて、appsscript.json(マニュフェストファイル)を編集して、timeZoneを変更しておきます。
{
- "timeZone": "America/New_York",
+ "timeZone": "Asia/Tokyo",
"dependencies": {
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8"
}
(参考) 設定ファイルのドキュメント
各設定ファイルのパラメータについては、公式ドキュメントを参照してください。
マニフェストの構造 | Apps Script | Google for Developers
GitHub – google/clasp: 🔗 Command Line Apps Script Projects
TypeScriptへの書き換え
次は既存のGASファイルの書き換えです。GitHub Copilot Chat や Cursorなどを用いると、比較的楽にGASファイルをTypeScriptに変換できます。
なお、今回はCursorのComposer機能を使用したため、tsconfig.jsonや、必要なディレクトリなどが自動生成されて便利でした。
CursorエディタやComposer機能の基本的な使い方については、2024年10月に公開されたこちらの記事で詳しく解説していますので、併せてご覧ください。
変換後のファイル
// main.ts
declare const saveDrive: (message: JsonData) => void;
export interface JsonData {
[key: string]: {
number: any;
app: any;
};
}
// JSON生成処理
export function generateJson(): JsonData {
// スプレッドシートのデータを取得する
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("test_sheet");
if (!sheet) {
throw new Error("Sheet not found");
}
const data = sheet.getDataRange().getValues();
// JSONを格納するオブジェクトを作成する
const json: JsonData = {};
// シートの各行を処理する
for (let i = 0; i < data.length; i++) {
json[`app_PJ1_${i}`] = { number: data[i][0], app: data[i][1] };
}
return json;
}
// メイン関数
export function main(): void {
saveDrive(generateJson());
}
// drive.ts
import { JsonData } from './main';
// Google Driveにファイルを保存
function saveDrive(message: JsonData): void {
// Google Driveの特定のフォルダにファイルを作成
const folderId = PropertiesService.getScriptProperties().getProperty(
"DRIVE_FILE_PATH_PJ1"
);
if (!folderId) {
throw new Error("Folder ID not found in script properties");
}
const folder = DriveApp.getFolderById(folderId);
folder.createFile(
"sample.json",
JSON.stringify(message),
MimeType.PLAIN_TEXT
);
}
// グローバルスコープに公開(globalの代わりにthisを使用)
// @ts-ignore
this.saveDrive = saveDrive;
書き換え後のディレクトリ構成
変換後のディレクトリ構成は以下のようになります。元の.gsファイルはpushする必要がないため削除します。
.
├── node_modules
├── README.md
├── package-lock.json
├── package.json
├── project1
│ ├── .clasp.json
│ ├── appsscript.json
│ ├── functions
│ │ ├── drive.ts
│ │ └── main.ts
│ └── package.json
├── project2
│ ├── .clasp.json
│ ├── appsscript.json
│ ├── functions
│ │ ├── drive.ts
│ │ └── main.ts
│ └── package.json
└── tsconfig.json
プロジェクトへのデプロイ
定義したスクリプトを使用してデプロイを行います。
$ npm run deploy:project1
Debugger attached.
> gas-management@1.0.0 deploy:project1
> cd project1 && npm run deploy
Debugger attached.
> gas-management-project1@1.0.0 deploy
> clasp push
Debugger attached.
(node:45633) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
└─ appsscript.json
└─ functions/drive.ts
└─ functions/main.ts
Pushed 3 files.
Waiting for the debugger to disconnect...
Waiting for the debugger to disconnect...
Waiting for the debugger to disconnect...
デプロイが完了したら、GASのプロジェクト画面を開き、main関数を手動で実行して動作確認を行います。GASのプロジェクト画面で「実行」ボタンを押し、関数を選択することで実行できます。
$ npm run open:project1
Debugger attached.
> gas-management@1.0.0 open:project1
> cd project1 && clasp open
Debugger attached.
Opening script: <https://script.google.com/d/◯◯◯◯>
Waiting for the debugger to disconnect...
Waiting for the debugger to disconnect...

初回実行時や権限を変更した場合など、データへのアクセス権限の承認が必要になる場合があります。

おわりに
今回は、GAS開発を効率化するためのツール「clasp」の導入から、実際のGASファイルのTypeScriptへの書き換え、そしてデプロイまでを解説しました。
この記事が、GAS開発をより快適に、そして効率的にする一助となれば幸いです。ぜひclaspを活用して、より良いGAS開発体験を実現してください。