６．Googleドライブのフォルダを自動作成する

# 今日の目標：新規作成時にGoogleDriveのフォルダを作成する

## 0．前回の振り返り
https://qiita.com/LoAMiat/items/694bf0353c30a0fb1185

スプレッドシートの内容を保存できるようになりました。


## 1. 排他制御で同時更新を制御
保存後の処理がどんどん複雑化していくので、現在の更新人数は少ないので問題はなさそうですが、念のため排他制御を組み込んでおきます。

``` javascript:handler.gs
/**
 * 保存系ハンドリング
 */
function doPost(e) {

  // パラメータ取得
  const type = e.parameter.type;
  const catId = e.parameter.catId;
  const personId = e.parameter.personId;

  let htmlOutput;

  // スクリプトロック
  const lock = LockService.getScriptLock();

  // ロックされている場合、ロック解除されるまで最大10秒待機
  for(let i=0; i<10; i++){
    if(!lock.hasLock()){
      break;
    }else{
      // 1秒（1,000ミリ秒）処理を待機
      Utilities.sleep(1000);
    }
  }

  // 最大10秒（10,000ミリ秒）ロックを取得する
  if ( lock.tryLock(10000) ) {
    // 猫追加
    if( type === 'New' ){
      htmlOutput = doNew(e);
    }
    // 猫編集
    else if( type === 'Edit' ){
      htmlOutput = doEdit(e, catId);
    }
    // 猫体重追加 OR 猫写真追加
    else if( type === 'Add-Weight' ||  type === 'Add-Photo' ){
      htmlOutput = doAdd(e, type, catId);
    }else{
      console.log(type);
      htmlOutput = doEdit(e, catId);
    }

    // ロック開放
    lock.releaseLock();
  }

  return htmlOutput;
}
```

## 2．Googleドライブのフォルダを新規作成する
フォルダは指定フォルダ配下に作成します。作成後はフォルダIDを返却して、スプレッドシートに更新します。
``` javascript:edit.gs
/**
 * 猫写真用フォルダ作成
 */
function createFolder(catId, catName){
  // 親フォルダ取得
  const parentFolder = DriveApp.getFolderById(CatFolder);
  const folderName = catId + '：' + catName;
  // 個別猫フォルダ作成
  const newFolder = parentFolder.createFolder(folderName);
  // フォルダID返却
  const folderurl = newFolder.getId();
  return folderurl;
}
```
## 3．作成したフォルダに画像ファイルを保存する
先ほど作成したフォルダに画像を保存していきます。保存後にパラメータを付与した状態で画面遷移したいので、`google.script.run`を利用する方式にします。
こちらを利用する場合、以下３点にはまりましたので共有です。
- 呼び出すgsファイル内へ渡せる**パラメータは1つ**のみ
- パラメータには`<form>`の中身のみが正しく値が受け渡しできる
- success系のメソッドを記述できるが、その中で画面遷移はできない

上記に反してしまう場合、`google.script.run`自体が実行されないのでエラーにもならず、ログからも状況を確認することができずで分析に手間取ってしまいました。

```javascript:Add.gs
/**
 * 猫画像保存
 */
function createFile(form){
  // フォルダ取得
  const catFolderId = form.url.toString().split("/").pop();
  const parentFolder = DriveApp.getFolderById(catFolderId);
  // ファイル作成
  parentFolder.createFile(form.file);
}
```
```html:Add.html
    <script>
      function onClickBtn() {
        // loadingアニメーション表示
        let loadingDiv = document.getElementById('loading');
        loadingDiv.style.display = 'block';
        // 保存処理の実行
        onSubmit();
      }

      function onSubmit() {
        const form = document.getElementById("myForm");

        if(type === 'Add-Weight'){
          google.script.run.doAdd(form);
        }else{
          google.script.run.createFile(form);
        }
        const url = '<?= deployURL ?>?type=detail&catId=<?= catId ?>';
        window.top.location.href = url;
      }
    </script>
  </head>
  <body>
    <div id="loading" class="loading">
      <div class="ring">
        loading
        <span></span>
      </div>
    </div>

    <header>
      <a href="<?= deployURL ?>">
        <!-- <img src="https://lh3.googleusercontent.com/d/19JNci3LGLdVVjCzCJh5LrIHU2L5ObroA"/> -->
        <?= header ?>
      </a>
    </header>
    <div class="cat-profile">
      <form id="myForm">
        <h2 class="text-center m-4">情報追加
          <button type="button" class="catBtn btn btn-outline-primary" onclick="onClickBtn();">保存</button>
```
## 4．保存処理をPOSTを利用しない形にすべて書き換える
eを使っていた部分をformを利用する形に書き換えるだけです。
画面生成をgs内で行っていたものを、画面遷移に書き換えると処理が早く感じるようになりました。
``` javascript:handler.gs
/**
 * 保存系ハンドリング
 */
function doUpdate(form) {

  // パラメータ取得
  const type = form.type;
  const catId = form.catId;

  let htmlOutput;

  // スクリプトロック
  const lock = LockService.getScriptLock();

  // ロックされている場合、ロック解除されるまで最大10秒待機
  for(let i=0; i<10; i++){
    if(!lock.hasLock()){
      break;
    }else{
      // 1秒（1,000ミリ秒）処理を待機
      Utilities.sleep(1000);
    }
  }

  // 最大10秒（10,000ミリ秒）ロックを取得する
  if ( lock.tryLock(10000) ) {
    // 猫追加
    if( type === 'New' ){
      htmlOutput = doNew(form);
    }
    // 猫編集
    else if( type === 'Edit' ){
      htmlOutput = doEdit(form, catId);
    }
    // 猫体重追加 OR 猫写真追加
    else if( type === 'Add-Weight' ){
      htmlOutput = addWeight(form);
    }
    // 猫体重追加 OR 猫写真追加
    else if( type === 'Add-Photo' ){
      htmlOutput = createFile(form);
    }

    // ロック開放
    lock.releaseLock();
  }
}
```
---
もうちょっとで、ver1として利用開始できそうです。
今日はここまで