スマホで簡単家計簿管理！スプレッドシート入力ツールを作成するまで

## 経緯

社会人になってから、月単位や年単位で何にどれくらいのお金を使っているかを把握したいと思い、ゆるく家計簿をつけていました。
ネットで公開されている家計簿シートを使えば、スプレッドシートを活用して簡単に可視化できるとのことで試してみたのですが、スマホでの入力が面倒……。そこで、スマホ用の家計簿アプリを利用し、記録内容を後日スプレッドシートにまとめていました。

しかし、先日アップデートの関係で私のデータが全て消えてしまいました。半年間スプレッドシートへの入力を怠っていたため、その間の記録もすべて失う結果に……。

この出来事をきっかけに、「スマホからスプレッドシートに簡単に入力できたら便利なのに」と以前から抱いていた願望を、ついに形にすることとしました。

## やりたいこと

以下の機能を実現することを目指します：

- スマホから収支をスプレッドシートに記録
- 記録したデータを閲覧可能にする
- 月や年単位での収支を可視化

## 前提

家計簿管理には、現在も利用している[ロゴログ家計簿](https://rogolog.com/spreadsheet-kakeibo/)のスプレッドシートを使用します。
入力部分は以下の技術を活用して作成します：

- GAS (Google Apps Script)
- HTML と JavaScript

これにより、スマホでも手軽に入力可能なフォームを作成し、スプレッドシートに書き込める仕組みを構築します。

## 実装の流れ

以下の手順で進めていきます：

1. GAS の作成
2. HTML 入力画面の作成
3. JavaScript の作成
4. デプロイとテスト

### 1. GAS の作成

まず、ロゴログ家計簿スプレッドシート「[ロゴログ家計簿](https://rogolog.com/spreadsheet-kakeibo/)」を開きます。画面上部のタブから「拡張機能」→「Apps Script」を選択してスクリプトエディタを開きます。

![スプレッドシート.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980509/2b31f7f1-f1e0-46ec-8ab6-49ed7245ca29.png)

次に、「コード.gs」に doGet 関数を作成します。この関数は、スクリプトのエントリーポイントとして動作します：

```javascript
function doGet() {
  const template = HtmlService.createTemplateFromFile("input");
  return template.evaluate();
}
```
    
### 2. HTML 入力画面の作成
スマホから簡単に入力できるフォームを HTML と JavaScript で作成します。1.で "input.html" を指定してるので、ファイル名は input.html としておきます。入力項目は以下の通りです：
- 日付
- 費目（収入、支出、貯蓄）
- 詳細項目
- メモ
- 決済方法
- 金額

以下はサンプルコードです：
(実際の詳細項目部分はselectタグにしてロゴログ家計簿で定義した項目を選択できるようにしています。)

```html
<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta charset="utf-8">
    <title>家計簿入力</title>
  </head>
  <body>
    <h1>家計簿入力画面</h1>
    <form id="myForm">
      <label for="inputDate">日付:</label>
      <input type="date" id="inputDate"><br>

      <label for="item1">費目:</label>
      <select id="item1">
        <option value="収入">収入</option>
        <option value="支出">支出</option>
        <option value="貯蓄">貯蓄</option>
      </select><br>

      <label for="item2">詳細項目:</label>
      <input type="text" id="item2"><br>

      <label for="payment">決済方法:</label>
      <input type="text" id="payment"><br>

      <label for="total">金額:</label>
      <input type="number" id="total"><br>

      <button type="button" onclick="submitForm()">送信</button>
    </form>

    <script>
      function submitForm() {
        google.script.run.processSubmit(document.getElementById("myForm"));
        alert("記録が完了しました！");
      }
    </script>
  </body>
</html>
```

### 3. JavaScript の作成
- コード.gs でスプレッドシートへの書き込み処理を実装します。
- プロジェクトの設定からスクリプトプロパティを定義することができます。
この値を定義することで、スプレッドシートIDやその他外部公開しない値を安全に取り出すことが可能です。
- ロゴログ家計簿ではD列から入力が可能なので、D列から書き込みを始めるように指定しています。
- ソースコード
    ```javascript
    // スプレッドシートのファイルID
    const SPREADSHEET_FILE_ID = PropertiesService.getScriptProperties().getProperty('SPREADSHEET_FILE_ID');
    // 家計簿シート名
    const SHEET_EXPENSES = '家計簿';
    // 列セル：D列
    const ROW_D = 4;
    
    function processSubmit(form) {
      // スプレッドシートの読み込み
      const spreadsheet = SpreadsheetApp.openById(SPREADSHEET_FILE_ID);
      // シートの選択
      const sheet = spreadsheet.getSheetByName(SHEET_EXPENSES);
      // 日付の形式変更
      const date = form.inputDate.replaceAll("-", "/");
      // 書き込み範囲指定
      const startRow = sheet.getLastRow() + 1;
      const data = [[date, form.item1, form.item2, form.memo, form.payment, form.total]];
      const addRange = sheet.getRange(startRow, ROW_D, 1, data[0].length);
      // シートへ書き込み
      addRange.setValues(data);
    }
    ```

### 4. デプロイとテスト
- デプロイ前に「デプロイをテスト」を指定することで、動作確認が可能です。
- 動作確認後、「新しいデプロイ」を選択すると、実際にデプロイが行われて、他端末からのアクセスも可能となります。

![デプロイ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980509/45c9ab14-7f0c-4435-97ca-cdb37b2813c4.png)

### 完成画面
- chatGPTにデザイン面を助けてもらい、入力画面を作成することができました。
- 実際に入力項目を埋めて「送信」ボタンをクリックするとスプレッドシートに反映されます。

![入力画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980509/2e899125-6e5a-979b-fd24-42784c52f17e.png)

## 今後の展開

今回は、スマホや PC からスプレッドシートへデータを書き込むための基本画面を作成しました。さらに使いやすくするためには、以下の機能も実装予定です：

- 収支の集計結果を閲覧可能にする
- データの編集機能を追加

これらの機能を開発し、今後の記事で詳しく記録していこうと思います！