Google Sheets のデータを JSON 形式で取得する Web API をサクッと作る

（データを追加する Web API は [Google Sheets にデータを追加する Web API をサクッと作る](http://qiita.com/takatama/items/e5cb83012d14c0094a79) をご覧ください）

Google Sheets のデータをJSON 形式で取得する Web API を、10分くらいでサクッと作ります。
レスポンスタイムが長いので、あくまで試作用としてご利用ください。

## シートにある全ての情報を取得する

![seets.png](https://qiita-image-store.s3.amazonaws.com/0/6760/bb6b5817-a124-17ca-10b6-3512b5068a95.png "seets.png")

だったら、

```json
[
  {
    "title": "TechCrunch Japan",
    "feed_url": "http://jp.techcrunch.com/feed/"
  },
  {
    "title": "Engadget Japanese",
    "feed_url": "http://japanese.engadget.com/rss.xml"
  }
]
```

が取得できます。

### 新しいシートを作る

https://docs.google.com/spreadsheets/create で新規のspreadsheetを作ります。

### Script Editor でコードを書く

シート上部のメニュー Tools > Script Editor... を選び、Code.gs に以下のコードを記入します。

getData の引数はシート名(ここでは Sheet1)です。

```javascript
function getData_(sheetName) {
  const sheet = SpreadsheetApp.getActive().getSheetByName(sheetName);
  const rows = sheet.getDataRange().getValues();
  const keys = rows.splice(0, 1)[0];
  return rows.map(row => {
    const obj = {};
    row.map((item, index) => {
      obj[String(keys[index])] = String(item);
    });
    return obj;
  });
}

function doGet() {
  var data = getData_('Sheet1');
  return ContentService.createTextOutput(JSON.stringify(data, null, 2))
  .setMimeType(ContentService.MimeType.JSON);
}
```

### Web app として公開する

まずは作ったコードが正しく動くことを確認します。Script Editor 上部のボタン Deploy（デプロイ）から、Test deployments（デプロイをテスト）を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/847bec5c-669f-ca6d-f3b2-68d3720ea61f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/76a1c471-ae1f-7941-4d45-02ef74710e01.png)

このURLはテスト用になっていて、末尾が```/dev```になっています。
URLをクリックして、WebブラウザーでWeb APIにアクセスし、JSONが表示されればOKです。なお、テスト用のURLは自分からしかアクセスできません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/6507dc39-ea1a-9f90-8187-65d93ca02152.png)

"Authorization is required to perform that action."（承認が必要です）というエラーが出た場合は、スクリプトエディターでRun（実行）してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/d659234a-d636-ed2d-6c58-22ab45f58bc3.png)

Permissionsを設定した後に、もう一度 Web API にアクセスしてみてください。

上手く動作したら、Web APIを公開します。Script Editor 上部のボタン Deploy（デプロイ）から、New deployment（新しいデプロイ）を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/e234a3d6-9992-d66c-6a7e-e15943c8b090.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/8e91326d-d3fd-dd51-bc9e-1a333a1d8320.png)

Deployすると、新しいURLが払い出されます。一般公開されたURLの末尾は```/exec```になっています。

テスト用のURL ```/dev```は、自分からしかアクセスできませんが、エディターで保存されている最新のコードで動作します。一方、管理されたURL ```/exec```は、デプロイ時の設定によって一般公開も可能ですが、デプロイ時のコードでしか動作しません。コードを編集したら忘れずにNew deployment（新しいデプロイ）で登録してください。

#### 古いScript Editorの場合

Script Editor 上部のメニュー Publish > Deploy as web app... を選び、Web app として公開します。

注意：コードを修正した場合、Project version に New を選択し、Web app として公開し直す必要があります。

![webapp.png](https://qiita-image-store.s3.amazonaws.com/0/6760/27566ec6-6655-417f-923e-6d66e98f23a3.png "webapp.png")

- Project version:
 + New を選ぶと、Code.gs を新しいバージョンとして保存した上で公開します。この時、このバージョンのコードを説明するコメントを入力できます(コミットメッセージ)。
- Execute the app as
 + me を選ぶと、自分がこのコードを実行することになります。
- Who has access to the app
 + Anyone, even anonymos を選ぶとあらゆる人がこの Web API を実行できるようになります。

![webapp2.png](https://qiita-image-store.s3.amazonaws.com/0/6760/af8f7ba8-1d3e-a304-04c3-0efa3056ea56.png "webapp2.png")

Deploy ボタンを押した後、Current web app URL にアクセスすると、JSON 形式のデータを取得できます。
cURLで確認するなら -L オプションをつけるといいです ( https://developers.google.com/apps-script/guides/content#redirects ）。

![webapp3.png](https://qiita-image-store.s3.amazonaws.com/0/6760/f94f2ff9-53a2-b9df-cb18-9e3110d35c30.png "webapp3.png")

### コードのポイント

@kazinoue さんに教えていただきました。どうもありがとうございます。
参考: [Google Apps Script で Spreadsheet にアクセスする方法まとめ]
(https://qiita.com/negito6/items/c64a7a8589faaffcfdcf)

上記したように、スプレッドシートのメニューから Script Editor を選んで作ったスクリプトは Container Bound Script と呼ばれます。CBSだと、

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

で、スプレッドシートにアクセスできます。

もし、スプレッドシートと紐づいていない独立したスクリプトを作った場合は、スプレッドシートの id をメモしておき、

```javascript
const spreadsheet = SpreadsheetApp.openById(id);
```

でアクセスする必要があります。スプレッドシートの id は、スプレッドシートの URL (スプレッドシートを開いているWebブラウザーのアドレスバーに書いてある URL) が

```
https://docs.google.com/spreadsheets/d/abc1234567/edit#gid=0
```

だったら、abc1234567 (実際はもっと長い)です。

Class SpreadsheetApp  |  Apps Script  |  Google Developers
https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app#openById(String)

## キーワードを含む行だけを取得する

呼び出す URL に ?q=<キーワード> を与えると、そのキーワードを含む行だけを取得できるようにします。

```javascript
function getData(sheetName, query) {
  var sheet = SpreadsheetApp.getActive().getSheetByName(sheetName);
  var rows = sheet.getDataRange().getValues();
  var keys = rows.splice(0, 1)[0];
  return rows.filter(function(row) {
    if (!query) return true;
    return row.join(':::').toLowerCase().indexOf(query.toLowerCase()) !== -1;
  }).map(function(row) {
    var obj = {};
    row.map(function(item, index) {
      obj[keys[index]] = item;
    });
    return obj;
  });
}

function doGet(e) {
  var data = getData('Sheet1', e.parameter.q);
  return ContentService.createTextOutput(JSON.stringify(data, null, 2))
  .setMimeType(ContentService.MimeType.JSON);
}
```

注意：大事なことなのでもう一度。コードを修正した場合、New deployment（新しいデプロイ）で公開しなおしましょう（古いScript EditorならProject version に New を選択し、Web app として公開し直す）。

## 参考
Web Apps  |  Apps Script  |  Google Developers
https://developers.google.com/apps-script/guides/web#deploying

Content Service  |  Apps Script  |  Google Developers
https://developers.google.com/apps-script/guides/content