【GAS】【html→GAS 値渡す】④webページでテーブルの行追加→同時にスプレッドシートも同じ行追加、データ挿入

シリーズ④、最終回です。

#####まとめ・完成形・対象者はこちら
[スプレッドシート⇆html 双方向の値受け渡し　CRUD（追加更新・削除）処理　（GAS、javascript、jqueryのみ）](https://qiita.com/forever---beginner/items/2afe3b48202041297e78)

#####過去回
[①スプレッドシート（サーバー）→html（クライアント）へ値受け渡し（ロード、テンプレ読み込み時）](https://qiita.com/forever---beginner/items/8e6f1e9c019070d43954)
[②スプレッドシート→htmlに渡した値をテーブル形式に（jquery）](https://qiita.com/forever---beginner/items/307f7609028fa7852755)
[③webページでテーブルの行削除→同時にスプレッドシートも同じ行削除](https://qiita.com/forever---beginner/items/2afe3b48202041297e78)

###◆今回やること

1. `index.html`のtableに**行追加**ボタン設置
1. クリック　→　webページで行・input・登録ボタンを追加
1. 登録ボタンクリック　→　`index.html`のjavascript関数呼び出し
1. `index.html`3のjs関数　→　`コード.gs`のGAS関数呼び出し、スプシ行・値挿入
1. (3で）登録ボタンを非活性化
<br>

わかりずらかったら、最下層の[完成形（結果・動作）](https://qiita.com/forever---beginner/items/da006c9821de98663322#%E7%B5%90%E6%9E%9C%E5%8B%95%E4%BD%9C)見た方が早いかも?です

ではコードいきましょう

----
###◆コード

`コード.gs`
追加箇所：ssInsvals　
中身：登録ボタンクリック時呼び出し、スプシに行・値挿入

```javascript:コード.js

//htmlテンプレ作成スプシ値取得

function valsget() {
  let ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("テスト");
  let vals = ss.getDataRange().getValues();
  vals.shift();
  return vals;
}

//htmlテンプレ作成

function doGet(){
  let hotpt = HtmlService.createTemplateFromFile('index').evaluate();
  hotpt.setTitle('CRUDテスト');
  return hotpt;
}

//クライアント側で削除ボタンクリック時に呼ばれるGAS関数

function rowdel(rw) {　　//rwで行数$rowIndexを受け取る
  let ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("テスト");
  ss.deleteRows(rw); // ←　rwの行を丸々削除
}

//↓前回から追加箇所
//登録ボタンクリック時呼び出し、スプシに行・値挿入
function ssInsvals(rw,area,district,city){
  let ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("テスト");
  ss.insertRows(rw);
  ss.getRange(rw,1).setValue(area);
  ss.getRange(rw,2).setValue(district);
  ss.getRange(rw,3).setValue(city);

}

```

`index.html`

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>  
    <table id="tbl" border="1">
      <tr>
        <th>地域</th>
        <th>都道府県</th>
　　　　　<th>県庁所在地</th>
        <th>追加ボタン</th>
        <th>削除ボタン</th>
      </tr>
    </table>    
  </body>
</html>

<script
  src="https://code.jquery.com/jquery-3.6.0.slim.min.js"
  integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI="
  crossorigin="anonymous"></script>

<script>

  window.onload = function(){

    google.script.run.withSuccessHandler(dt=>
    {
      for(let i =0;i<dt.length;i++){
        let $tr = $('<tr></tr>');
        $tr.append($('<td></td>').text(dt[i][0])); 
        $tr.append($('<td></td>').text(dt[i][1])); 
        $tr.append($('<td></td>').text(dt[i][2])); 
        $tr.append($('<button></button>').text('下行追加').on('click',add));
        $tr.append($('<button></button>').text('削除').on('click',del));
        $('#tbl').append($tr);       
        }     
    }).valsget();
  }  


//削除ボタンのイベント処理
  function del(){

    var $rowIdx = $(this).parent()[0].rowIndex;
    //削除ボタンの親要素tr取得　→　rowIndexでtrの行取得

    let tru_fal = confirm($rowIdx+"行目を削除しますか");
    //削除のアラート。行数がわかるように一応入れてるだけです。

    //以下、confirmがtrueの処理
    if (tru_fal){
      //一番近いtrを取得　→　削除
      $(this).closest("tr").remove();

      //GAS側のrowdel関数に、行数を引数で渡す　→　rowdelを実行、スプシ行削除
      google.script.run.rowdel($rowIdx+1);

      }
  }


//追加ボタンのイベント処理

  function add(){
    var $cur_row = $(this).closest("tr");
  
    let $tr = $('<tr></tr>');
    $tr.append($('<input></input>').attr('class', 'area')); //input追加、class設定
    $tr.append($('<input></input>').attr('class', 'district'));　//input追加、class設定
    $tr.append($('<input></input>').attr('class', 'city'));　//input追加、class設定
    $tr.append($('<button></button>').text('登録').on('click',ssIns));　
    //登録ボタン追加、clickイベント設定
    $tr.append($('<button></button>').text('削除').on('click',del));

    $cur_row.after($tr);

  }


//登録ボタンのイベント処理

  function ssIns(){
    var $rowIdx = $(this).parent()[0].rowIndex;
    // confirm($rowIdx+"行目を登録しますか");
    
    let $areaInpval = $(this).closest("tr").find('.area').val();
    //ボタンから近いtr取得　→　trの中のclassからinput要素取得　→ inputの値取得
    let $distInpval = $(this).closest("tr").find(".district").val();
    let $cityInpval = $(this).closest("tr").find(".city").val();


    google.script.run.ssInsvals($rowIdx,$areaInpval,$distInpval,$cityInpval);
    alert("登録しました");
    $(this).prop('disabled', true);
    
  }

</script>

```

---
###◆結果、動作

・スプシ

|![スクリーンショット 2021-05-29 22.10.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1563301/e831d601-02c4-497b-b2e4-72c51a83bc6f.png)|
|:--|
<br>
・webページ
行追加ボタン表示が追加されてます

|![スクリーンショット 2021-05-29 22.09.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1563301/cecdc5cb-b390-fe24-d042-81c0b869fe78.png)|
|:--|

・行追加ボタンクリック → 行追加
※css入れてないので、こうなります。ご容赦ください

|![スクリーンショット 2021-05-29 22.10.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1563301/496324f1-805a-f11d-b7fc-3eb08c58e80e.png)--|
|:--|
<br>
・適当にデータ入れて登録ボタンクリック

|![スクリーンショット 2021-05-29 22.11.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1563301/c8f5028d-f850-d0a7-5fa7-1c82029f0997.png)|
|:--|
<br>


・登録ボタンを非活性化

|![スクリーンショット 2021-05-29 22.11.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1563301/121846cf-a5ac-c580-66e3-e245fe4cd65f.png)|
|:--|
<br>


・スプレッドシートにデータ挿入されてます

|![スクリーンショット 2021-05-29 22.11.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1563301/c3a4f0b9-7a52-388c-3c1a-134c7dc16fd0.png)|
|:--|
<br>


・画面リロードしてもちゃんと表示します

|![スクリーンショット 2021-05-29 22.19.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1563301/66ac4946-c1b4-30f6-3bfa-31d05f916536.png)|
|:--|