Google Apps Script でよく使うスニペット集 30 選

この記事は DevFest 2020 の [Google Apps Script 入門 2020](https://youtu.be/aBGnfrfBFEc) で紹介しました。

## はじめに

Google Apps Script では非常に簡単に Google Apps （スプレッドシート、 Google カレンダー、 Gmail、 Google Drive など） 間の連携ができます。例えば Google カレンダーのイベント一覧をスプレッドシートにエクスポートする際には以下のような処理の流れになります。

1. Google カレンダーからイベント一覧を取得
2. スプレッドシートに入力する形式にデータ変換
3. Google スプレッドシートに値を挿入

1, 3 のような Google Apps から取得、挿入する部分はよく使い回す部分となるので、スニペットとして使い回すと便利です。今回は私がよく使うスニペット集を紹介しようと思います。

## スプレッドシート

### スプレッドシートへのアクセス（スタンドアローン型）
https://script.google.com ( or https://script.new ) からスクリプトを作成する場合には以下の形式でシートにアクセスできます。  Spreadsheet ID はスプレッドシート URL の以下の部分を指します。`https://docs.google.com/spreadsheets/d/[ Spreadsheet ID ]/edit`

```JavaScript
const spreadsheet = SpreadsheetApp.openById("Spreadsheet ID")
```

### スプレッドシートへのアクセス（インストール型）
特定のスプレッドシートからスクリプトを作る場合には以下の形式でもシートにアクセスできます。

```JavaScript
const spreadsheet = SpreadsheetApp.getActive()
```

### スプレッドシートから値取得
getDataRange を使うと範囲指定せずに勝手にデータが挿入されている範囲を指定してくれるので便利です。

```JavaScript
const values = spreadsheet
  .getSheetByName('シート名')
  .getDataRange()
  .getValues()
```

### シートへ値挿入
A1 から始まる範囲の時 row, column はともに 1、 values には 2 次元配列が入ります。

```JavaScript
spreadsheet
  .getRange(row, column, numRows, numColumns)
  .setValues(values)
```

### カスタムメニュー追加

```JavaScript
const onOpen = () => {
  SpreadsheetApp
    .getActiveSpreadsheet()
    .addMenu('メニュー名', [
      {name: 'サブメニュー1', functionName: '関数名1'},
      {name: 'サブメニュー2', functionName: '関数名2'},
    ])
}
```

参考記事: [スプレッドシートにカスタムメニューを追加して、拡張機能を実装する方法](https://qiita.com/tanabee/items/dea49d7ab2df17a05b07)

### スプレッドシート編集時に発火

変更のあった Range や値などが取得できる。

```JavaScript
const onEdit = e => {
  const { range, oldValue, value } = e
}
```

### スプレッドシートの選択範囲変更時に発火

選択中の Range やユーザー情報などが取得できる。

```JavaScript
const onSelectionChange = e => {
  const { range, user } = e
}
```


## Google カレンダー

### イベント作成
title は文字列、 start, end は Date 型で指定。

```JavaScript
CalendarApp.getDefaultCalendar().createEvent(title, start, end)
```

### イベント取得
start, end は Date 型で指定。

```JavaScript
const events = CalendarApp
  .getDefaultCalendar()
  .getEvents(start, end)
  .map(event => ({
    title: event.getTitle(),
    description: event.getDescription(),
    start: event.getStartTime(),
    end: event.getEndTime()
  }))
```

上記の値 （title, description など） 以外の取得は CalendarEvent クラスを参照
https://developers.google.com/apps-script/reference/calendar/calendar-event

### 共有カレンダーへのアクセス
実行アカウントのデフォルトカレンダー以外のカレンダーにアクセスする場合には、カレンダー ID を指定してカレンダーにアクセス。

```JavaScript
const calendar = CalendarApp.getCalendarById('Calendar ID')
```

## Gmail

### メール送信

```JavaScript
GmailApp.sendEmail('tanabee@example.com', '件名', '本文')
```

### スレッド検索
最新の 10 件のスレッド取得

```JavaScript
const threads = GmailApp.search('', 0, 10)
```

第一引数に入れる検索演算子は以下を参照
https://support.google.com/mail/answer/7190?hl=ja

### メッセージ一覧取得

```JavaScript
const messages = GmailApp.search('', 0, 10).flatMap(thread => 
  thread.getMessages().map(message => ({
    subject: message.getSubject(),
    body: message.getBody(),
    date: message.getDate(),
    from: message.getFrom(),
    to: message.getTo(),
  }))
)
```

上記の値 （subject, body など） 以外の取得は GmailMessage クラスを参照
https://developers.google.com/apps-script/reference/gmail/gmail-message

## Google ドライブ

### 特定フォルダ配下のフォルダ、ファイル取得

```JavaScript
const folder = DriveApp.getFolderById('Folder ID')

const files = folder.getFiles()
while (files.hasNext()) {
  let file = files.next()
  console.log('file: ', file.getName())
}

const folders = folder.getFolders()
while (folders.hasNext()) {
  let folder = folders.next()
  console.log('folder: ', folder.getName())
}
```

参考記事: [Google Apps Script で Google Drive のフォルダ配下のオーナー権限を一括で譲渡する](https://qiita.com/tanabee/items/da897eee4dac7b90aa24)

## Google フォーム

### フォーム送信内容の取得

```JavaScript
const onSubmit = event => {
  const answer = event.response
    .getItemResponses()
    .map(itemResponse => ({
      item: itemResponse.getItem().getTitle(),
      response: itemResponse.getResponse()
    }))
}
```

フォーム送信時に onSubmit 関数を発火させるために、別途トリガー設定が必要
参考記事: [Google Apps Script ハンズオン資料](https://qiita.com/tanabee/items/4a5056f468ae71d8d648#form-to-slack)

## Google ドキュメント

### ドキュメントへのアクセス（スタンドアローン型）
https://script.google.com からスクリプトを作成する場合には以下の形式でドキュメントにアクセスできます。 Document ID は URL の以下の部分を指します。`https://docs.google.com/document/d/[ Document ID ]/edit`

```JavaScript
const doc = DocumentApp.openById('Document ID')
```

### ドキュメントへのアクセス（インストール型）
特定のドキュメントからスクリプトを作る場合にはこちらの形式でもドキュメントにアクセスできます。

```JavaScript
const doc = DocumentApp.getActiveDocument()
```

### カスタムメニュー追加

```JavaScript
const onOpen = () => {
  DocumentApp
    .getUi()
    .createMenu('メニュー')
    .addItem('アイテム', '関数名')
    .addToUi()
}
```

## Utilities

### 日付のフォーマット指定

```JavaScript
const date = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'YYYY-MM-dd HH:mm:ss')
```

### sleep
1 秒間スリープしたい場合は以下のように書く。

```JavaScript
Utilities.sleep(1000)
```

### UUID 生成

```JavaScript
const uuid = Utilities.getUuid()
```

## トリガー

### 1 分後に特定の関数を実行

6 分の実行時間制限にかかる場合、残り 1 分等のタイミングで次の実行を予約すると便利です。

```JavaScript
const date = new Date()
date.setMinutes(date.getMinutes() + 1);// 1 分後
ScriptApp.newTrigger('関数名').timeBased().at(date).create();
```

参考記事: [GAS ビギナーが GAS を使いこなすために知るべきこと 10 選](https://qiita.com/tanabee/items/2c51681396fe12b6a0e4#6-%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%8B%E3%82%89%E3%83%88%E3%83%AA%E3%82%AC%E3%83%BC%E3%82%92%E3%82%BB%E3%83%83%E3%83%88%E3%81%A7%E3%81%8D%E3%82%8B)

## PropertiesService （プロパティ管理）

### プロパティから値取得

```JavaScript
PropertiesService.getScriptProperties().getProperty('キー名')
```

### プロパティへ値保存

```JavaScript
PropertiesService.getScriptProperties().setProperty('キー名', '値')
```

## LanguageApp （翻訳）

### 翻訳

```JavaScript
const text = LanguageApp.translate('Hello World', 'en', 'ja')
```

参考記事: [3 分で作る無料の翻訳 API with Google Apps Script](https://qiita.com/tanabee/items/c79c5c28ba0537112922)

## Web 公開 （Web サイト、 API 等）

### Web サイト（HTML テンプレートなし）

```JavaScript
const doGet = e => {
  const params = JSON.stringify(e.parameter)
  return HtmlService.createHtmlOutput(params)
}
```

参考記事: [GAS ビギナーが GAS を使いこなすために知るべきこと 10 選](https://qiita.com/tanabee/items/2c51681396fe12b6a0e4#web-%E5%85%AC%E9%96%8B)

### Web サイト（HTML テンプレートあり）

```JavaScript
const doGet = e => {
  return HtmlService.createHtmlOutputFromFile('index')
}
```

別途 index.html を用意する。

### GET API

引数 e の e.parameter にクエリストリングの値が入っている。

```JavaScript
const doGet = e => {
  const params = JSON.stringify(e.parameter)
  return ContentService
    .createTextOutput(params)
    .setMimeType(MimeType.JSON)
}
```

### POST API

引数 e の e.postData.contents に request body のデータが入っている。

```JavaScript
const doPost = e =>  {
  const body = e.postData.contents
  return ContentService
    .createTextOutput(body)
    .setMimeType(ContentService.MimeType.JSON)
}
```

## UrlFetchApp

UrlFetchApp を使うと外部の API にリクエストすることができる。

### GET API リクエスト

```JavaScript
const content = UrlFetchApp.fetch(url).getContentText()
```

### POST API リクエスト

```JavaScript
const res = UrlFetchApp.fetch(url, {
  method: 'POST',
  headers: { "Content-Type": 'application/json' },
  payload: JSON.stringify(data)
})
```

## まとめ

以上個人的によく使う処理をまとめました。厳密には 31 個ありそうですが、今後もちょっとずつ足していくかもしれないのでアバウトに 30 選としました。よかったら Google Apps Script のコードを書く時に参考にしてみてください。

## 関連記事

- [GAS ビギナーが GAS を使いこなすために知るべきこと 10 選](https://qiita.com/tanabee/items/2c51681396fe12b6a0e4)
- [スプレッドシートに OKR を書くとツリー構造で可視化されるツールを作ってみた](https://qiita.com/tanabee/items/3c17dcdbb8efb7afe212)
- [毎月 500 時間の社内ルーティンワークを GAS を使って自動化した話](https://qiita.com/tanabee/items/ce9c3cf9403c4f3f14a9)
- [Top 30 Useful Google Apps Script Snippets](https://medium.com/@tanabee/top-30-useful-google-apps-script-snippets-8ad13077530f) > この記事の英語版