家計簿のデータをNode.jsでスプレッドシート連携してみた

この記事は[レコチョク Advent Calendar 2021](https://qiita.com/advent-calendar/2021/recochoku)の11日目の記事となります。

# はじめに
はじめまして、最近サウナにどハマりしている株式会社レコチョクの酒見です。
サ活こそ正義ですね。
私も音楽が好きで有名どころしか知らないかもですが、学生時代からいろんな名曲や
アーティストの音楽と共に過ごしてきました。
BUMP OF CHICKEN / ELLEGARDEN / ONE OK ROCK / UVERworldあたりが大好きで、泣かされたり背中を押されたりテンションを上げてもらったりと、思い入れが特に強いです。（世代がわかってしまうかもですね）

そんな私は、普段はサーバサイドエンジニアとしてPHPを触る機会が多いんですが
今回はNode.jsを使用して、Google スプレッドシートへのデータ連携を作ったことを書きたいと思います。


# 前提として
私はスプレッドシートを家計簿代わりに使っています。
PCから入力する分には気にならなかったのですが、スマホからの入力がし辛かったので、
アプリで作ってしまおうと思い、元々使用していたスプレッドシートをDBとして
使いたかったところがあります。
~~ぶっちゃけFirebase Cloud Firestore使うほうが楽でした~~

アプリ側の実装やスプレッドシートのAPI環境準備などは今回は割愛します。

# アプリ構成
簡単に構成を紹介します。

### アプリ
* Flutter( version.2.5.2)

### サーバサイド
* Node.js( version.14 )
    + firebase-functions(実行環境はFirebase Functionsを使用しています。)
    + google-spreadsheet 

今回はJavaScriptで記述します。

### データベース
* スプレッドシート

# Node.jsのプロジェクト作成
環境の構築を始めます。まずはディレクトリの作成からです。

```
$ mkdir sheet-expenses-app
$ cd sheet-expenses-app
```

次にNode.jsのアプリケーションを作成します。

```
$ npm init
```

パッケージ名やいろいろ聞かれますが、全てYESマンで回答しました 。（ここはお好みです）
以下のpackage.jsonが作成されました。

```
{
  "name": "sheet-expenses-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
```

次にFirebase Functionsを使用できるようにします。
今回はJavaScriptでいきます。

```
$ npm install @Google Cloud Monitoring/functions-framework -g
$ firebase init functions
```

これで環境自体はできました。
テンションを上げたいので、一回Hello,Worldで疎通確認してみます。


```JavaScript:index.js
const functions = require("firebase-functions");

exports.helloWorld = functions.https.onRequest(async (request, response) => {
  response.json({result: 'Hello , World!'});
});
```

`/helloWorld`にアクセスしたら`Hello , World!`と返すだけの簡単なメソッドを作りました。
ローカル環境を起動して確認します。

```
$ firebase emulators:start
```


![image-20211122110740696.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486966/75500340-7d0d-5eed-3221-f5d725197596.png)


うん、いいっすね（ニッコリ）

# スプレッドシートへの連携
ではスプレッドシートへの書き込みを作っていきます。
ライブラリを入れておきます。

```
$ npm install google-spreadsheet
```

またGCP側でGoogle Sheets APIを有効化しておき、サービスアカウント・認証キーの準備をしておきます。
ここまでで環境の準備は完了しました。
コードを書いていきます。


```JavaScript:index.js
const functions = require("firebase-functions");
const { GoogleSpreadsheet } = require('google-spreadsheet');

// 認証ファイルパス
const CREDENTIALS_PATH = "./config/sheet_credential.json"; 
// スプレッドシートのIDを指定
const SHEET_KEY = 'XXXXXYYYYYZZZZZ';

exports.addGoogleSheetData = functions.https.onRequest(async (request, response) => {
  // データ連携用にインスタンスを生成
  const doc = new GoogleSpreadsheet(SHEET_KEY);
  const credentials = require(CREDENTIALS_PATH);
  await doc.useServiceAccountAuth(credentials);
  
  // シート情報読み取り
  await doc.loadInfo();
  const sheet = await doc.sheetsById[1491717139];
  // 連携用のデータは配列形式で指定する
  let addData = [
    '=ROW()-1',
    '2021-10-20',
    'CD',
    'YOASOBI THE BOOK',
    '3957',
  ];
  //  書き込み処理
  await sheet.addRow(addData);
  response.json({ resultCode: 200});
});
```

書き込み用の配列にも入れていますが、文字列形式であればスプレッドシートの関数を入れることも可能です。
動作させてみました。

![image-20211122115424530.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486966/facc5f42-73ee-3613-5603-354de685ead3.png)

いいですね、入ってます。

では直書きしている箇所を動的に変更するように変更します。

```JavaScript:index.js
exports.addGoogleSheetData = functions.https.onRequest(async (request, response) => {
  // リクエストパラメータを取得
  let requestData = request.body.data;

  // データ連携用にインスタンスを生成
  const doc = new GoogleSpreadsheet(SHEET_KEY);
  const credentials = require(CREDENTIALS_PATH);
  await doc.useServiceAccountAuth(credentials);
  await doc.loadInfo();
  const sheet = await doc.sheetsById[1491717139];

  // 連携用のデータは配列形式で指定する
  let addData = [
    '=ROW()-1',
    requestData.purchaseDate,
    requestData.category,
    requestData.item,
    requestData.price,
  ];
  await sheet.addRow(addData);
  return response.json({resultCode: 200});
});
```

作ったメソッドをデプロイしていきます。

```
$ firebase deploy
```

Deploy complete! と表示されればOKです。


ではアプリの方からbodyに以下のようなパラメータを設定して
デプロイしたAPIを実行します。

```
{
  "data": {
    "purchaseDate": "2021-11-05",
    "category": "CD",
    "item": "BUMP aurora arc",
    "price": "4653"
  }
}
```
アプリ上はこんな感じです。
![image-20211122115204151.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486966/679ecfe7-def2-45fd-f626-3d36e200f26f.png)


スプレッドシートを確認します。
![image-20211122110941982.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486966/65bbdfcb-0a11-9d4b-9c11-023cf0191c47.png)



うん、アプリで投げたデータが入ってますね。
**よし完成！**

# まとめ
今回はNode.jsからスプレッドシートへ書き込みの処理を作りました。
スプレッドシートは業務でも個人的にも使う機会が多いので、もっと有効活用できればなぁと思いました。
update/deleteも作ってたんですが、長くなるので今回はこれで終わりとします。
お読みいただきありがとうございました。

明日の[レコチョク Advent Calendar 2021](https://qiita.com/advent-calendar/2021/recochoku)は12日目「スライダーって簡単に作れるの知らなかった」です。お楽しみに〜〜。

この記事はレコチョクのエンジニアブログの記事を転載したものとなります。

https://techblog.recochoku.jp/?p=7964