gas（Google Apps Script）でgoogle formsを使わずに家計簿アプリを作る

エンジニアでもなく理系でもないですが、フリーターからIT企業に入りプログラミングに触れて面白さを知りました。
独学でgasについて学び、ネット上の先輩方のコードを参考にしながら、自分の家計のやりくりに使えないかと家計簿を作りました。
-


# 前提条件
1. google formは使わない
1. UIはgasで表現
1. シンプルにその月のカード利用額と無駄遣い額を入力するだけ
1. なんとかレスポンシブ対応（だけどほぼスマホで入力することを考えたUI）

基本的には上記の通り、シンプルにgasだけで家計簿アプリを作りました。
cssなども独学で調べながら作ったため、ところどころ変な記述してるかもしれません・・・
（brを多用していたりとか）

# 画面構成
基本的には下記の通り2画面構成
1. トップページ
1. 入力ページ

## トップページ
誰が使ったか（リーマン、リーマン妻）、カード利用金額、無駄遣い額（カード利用額の中で無駄遣い額がいくらかを視覚的に出したい）だけをトップページに表示

その他についてはトップページの最初に家計簿アプリというアプリ名を書くくらいで他はなし

## 入力ページ
入力ページも基本的にシンプルに、日付、使用者、カード利用金額、無駄遣い額の入力欄を用意
日付、使用者については選択式

## 準備
二枚のシートを新規で作成
1. 家計簿（アプリトップページに表示
1. ▲家計簿データ（こちらにアプリからのデータが入る

家計簿シートの方で、▲家計簿データを集計するように関数を入れる
▲家計簿データのA列にB列に入力された日付を1日に固定するように関数を入れる
（2022年5月27日なら2022年5月1日）

# 具体的なコード

アプリの裏側

```コード.gs
function doGet(e) {
  var page=e.parameter["p"];
 
  if(page == "index" || page== null){
    
  var htmlOutput = HtmlService.createTemplateFromFile("index").evaluate();
  htmlOutput
    .addMetaTag('viewport', 'width=device-width, initial-scale=1,maximum-scale=1')
  return htmlOutput;
  return HtmlService.createTemplateFromFile('index').evaluate();
}
  
  else if(page =="index2"){
  var htmlOutput = HtmlService.createTemplateFromFile("index2").evaluate();
  htmlOutput
    .addMetaTag('viewport', 'width=device-width, initial-scale=1,maximum-scale=1')
  return htmlOutput;
  return HtmlService.createTemplateFromFile('index2').evaluate();
  }
}


function processForm(formObject) {
  var val1 = formObject.date;
  var val2 = formObject.user;
  var val3 = formObject.card;
  var val4 = formObject.gluttony;
  var ss = SpreadsheetApp.openById("自分のスプレッドシートのID");
  var sh = ss.getSheetByName("▲家計簿データ");
  var lr = sh.getLastRow();
  var arrdata = [[val1,val2,val3,val4]];
  sh.getRange(lr+1,2,1,arrdata[0].length).setValues(arrdata);
  Logger.log(arrdata)
 }
 
```
```index.html
<!DOCTYPE html>
<html>
  <head>
  <title>家計簿</title>
    <base target="_top">
    
    <script>
    function resizeHtml(){
  var w = document.body.clientWidth;
  var h = document.body.clientHeight;
  var scale = 980 / w;
  var transX = (scale - 1) * w / 2 / scale;
  var transY = (scale - 1) * h / 2 / scale;
  document.body.style.webkitTransform = "scale("+scale+") translate("+transX+"px, "+transY+"px)";
}
    </script> 
    <style>
h1{
background: linear-gradient(#0000cc,#0099ff);
color: #fff;
}

h2{
background: linear-gradient(#0099ff,#0099ff);
color: #fff;
}

font1{
color: #000000;
}

font2{
color: red;
}

.square_btn2{
  height: 10rem;
    text-align: center;
    padding: 0.5em 3em;
    text-decoration: none;
    background: #265ab9;/*ボタン色*/
    color: #FFF;
    border-bottom: solid 4px #0B2161;
    border-radius: 3px;
}
.square_btn2:active {/*ボタンを押したとき*/
    -ms-transform: translateY(4px);
    -webkit-transform: translateY(4px);
    transform: translateY(4px);/*下に動く*/
    box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.2);/*影を小さく*/
    border-bottom: none;
} 

body{
  margin: 8px;
  background-size: cover;
  background-position:50% 50%; 
  border: solid 1px gray;
  }
  
 table {
    display: table;
    border-collapse: separate;
    border-spacing: 2px;
    border-color: #000000;
}
 
  </style> 
  </head>
  <body>
  
   <div style="text-align:center;">
  <h1>家計簿アプリ</h1>
  
<a href="ウェブアプリケーションとして公開した際の「入力ページ」のURL" class="square_btn2">家計簿入力</a>
<br>
<br>  

<table align=center border=”2”>
        <h2>家計簿サマリ</h2>
        <tr>
         <th><font1>使用者</font1></th>
         <th><font1>カード使用額</font1></th>
          <th><font1>無駄遣い額</font1></th>
        </tr><p>
          <?
          var ss = SpreadsheetApp.getActiveSpreadsheet();
          var sheet = ss.getSheetByName('家計簿');
          var range = sheet.getRange(2,2,2,3).getDisplayValues();
          for(var i = 0, l = range.length; i < l; i++) {
              output.append('<tr>');
              output.append('<td>' + range[i][0] + '</td>');
              output.append('<td>' + range[i][1] + '</td>');
              output.append('<td>' + range[i][2] + '</td>');
              output.append('</tr>');
            }
          ?>
      </table>  
</div>
</body>
</html>
```
```index2.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
     <script>
      window.onload = function () {
        var date = new Date();
        var yyyy = date.getFullYear();
        var mm = ("0"+(date.getMonth()+1)).slice(-2);
        var dd = ("0"+date.getDate()).slice(-2);

        document.getElementById("today").value=yyyy+'-'+mm+'-'+dd;
        }
 
    function preventFormSubmit() {
      var forms = document.querySelectorAll('form');
      for (var i = 0; i < forms.length; i++) {
        forms[i].addEventListener('submit', function(event) {
          event.preventDefault();
        });
      }
    }
    window.addEventListener('load', preventFormSubmit);

    function handleFormSubmit(formObject) {
      google.script.run.withSuccessHandler().processForm(formObject);
    }
   
   function OnButtonClick() {
     target = document.getElementById("output");
     target.innerHTML = "complete!";
     target.style.color = '#000000';   
   }

    </script>

<style>


font1{
color: #000000;
}

font2{
color: red;
}


p.border {
border-bottom: solid 1px #000000;
}

form {
  /* フォームをページの中央に置く */
  margin: 0 auto
  width: 250px;
  /* フォームの範囲がわかるようにする */
  padding: 0.5em;
  border: 1px solid #CCC;
 
}

form div + div {
  margin-top: 1em;
}

label {
  /* すべてのラベルを同じサイズにして、きちんと揃える */
  display: inline-block;
  width: 100%;
  text-align: left;
  color:#000000;
}

select {
/* すべてのラベルを同じサイズにして、きちんと揃える */
  display: inline-block;
  width: 100%;
  height: 28px;
}

input, textarea {
  /* すべてのテキストフィールドのフォント設定を一致させる
     デフォルトで、textarea は等幅フォントが設定されている */
  font: 0.9em sans-serif;
  color:#663399;
  background: linear-gradient(#f5f5f5,#cbcbcb);

  /* すべてのテキストフィールドを同じサイズにする */
  width: 100%;
  box-sizing: border-box;

  /* テキストフィールドのボーダーの外見を同一にする */
  border: 1px solid #999;
  
  height: 28px;
  
  text-decoration:underline;
}

input:focus, textarea:focus {
  /* アクティブな要素を少し強調する */
  border-color: #000;
}

textarea {
  /* 複数行のテキストフィールドをラベルにきちんと揃える */
  vertical-align: top;

  /* テキスト入力に十分な領域を与える */
  height: 1em;
}

.button {
  /* ボタンを他のテキストフィールドと同じ場所に置く */
  text-align: center;

}

button {
  /* このマージンは、ラベルとテキストフィールドの間のスペースと
     おおよそ同じスペースを表す */
  margin-left: .5em;
  height: 28px;
  color:#663399;
  background: linear-gradient(#f5f5f5,#cbcbcb);
  box-sizing: border-box;

  /* テキストフィールドのボーダーの外見を同一にする */
  border: 1px solid #999;
}

body{
  margin: 8px;
  background-size: cover;
  background-position:50% 50%; 
  }

h1{
background: linear-gradient(#0000cc,#0099ff);
color: #fff;
}

</style>

  </head>
  <body>

    <h1 align="center">家計簿入力</h1>

  <form onsubmit="handleFormSubmit(this)" align="center">
      <table>  
        <tbody> 
        
        <div>
        <label for="date">日付:</label>
        <input type="date" id="today" name="date">
        </div>
        <p class="border"></p>      
              
        <div>    
       <label for="user">使用者:</label>
       <select name="user">
       <option value="リーマン" selected>リーマン</option>
       <option value="リーマン妻">リーマン妻</option>              
       </select>
        </div>
        <p class="border"></p>        
               
       <div>
       <label for="card">カード使用額:</label>
       <input type="text" name="card" >
       </div>
       <p class="border"></p>
       
       <div>
       <label for="gluttony">無駄遣い額:</label>
       <input type="text" name="gluttony" >
       </div>
       <p class="border"></p>
 
       <div class="button">
   <input type="submit" style="width: 100px" value="入力" onclick="OnButtonClick();">
   <button><a href="ウェブアプリケーションとして公開した際の「入力ページ」のURL">再入力</a></button> 
   <button type="return"><a href="ウェブアプリケーションとして公開した際の「トップページ」のURL">戻る</a></button>
           <div id="output"></div>
           <br>
            </div>
         </tbody>  
      </table><!-- end table -->  
       
    </form>  
  </body>
</html>
```
# できた画面紹介
### トップページ
![20220527_1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2694062/c34ea63b-65c5-3824-9561-589377d1668c.png)

### 入力ページ
![20220527_2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2694062/a8a344a7-5285-8db4-bf01-6e3d07a96d88.png)

### 動作
1. トップページにて家計簿入力
1. 入力画面に移動
1. 入力画面にて、使用者、カード使用額、無駄遣い額を入力
1. 入力を押す
※再入力ボタンは入力ページをリロードする
※戻るボタンはトップページに戻る



# まとめ
とりあえず形にはなった気がする
コードについての簡単な解説は下記のページでやってみたので、もし見たいかたはどうぞ

## 
解説ページ: [スプレッドシートのGoogle Apps Script（GAS）で家計簿アプリ5_「サラリーマンがプログラミングしてみた」](https://minrich.net/programming/google-apps-script_kakeibo_5/)