【GAS】GoogleFormの回答者ごとにGoogleDriveにフォルダを自動作成するためのGoogleAppScriptをかいてみた

![video.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377231/49df3725-be5b-f179-5c6e-dcd4fb8fc69b.gif)

Google**Form**  x  Google**Spreadsheet**  x  Google**Drive**

# 内容
Googleフォームのアンケートに顧客が回答したら、スプレッドシートに用意してある固有IDを付与させる。付与した固有IDをフォルダ名として、Googleドライブにフォルダを作らせる。個人的にフォルダというワードを使うのが抵抗あるのでこれより先フォルダのことをディレクトリと書かせていただきます。

# 目的
ディレクトリ作成の自動化
Googleフォームの回答がある度に手動でディレクトリを作るのが面倒

# 要件

- **固有ID**は事前に別シートに用意したものを用いたい
- 回答結果がスプレッドシートにリアルタイムで反映されるタイミングで、**付与した固有IDも隣に表示**させたい
- **コピー元のディレクトリ**をあらかじめ用意しておくのでそれを名前を変えて固有ID名でコピーさせたい
- コピー元のディレクトリにはファイルが入っているので、そのファイルも含め**再帰的**にコピーさせたい
- アンケートの返答があり次第、**逐一**ディレクトリを作らせたい（まとめてドンではない）

# システム
以下のようなシステムを考えました

1. フォームの回答結果がスプレッドシートに即時反映される
1. 設定したトリガーの条件にマッチして***formsFunction***が実行される
1. 別シートに用意した固有IDの**リスト**を取得
1. フォームの最後の行番号とそれに紐づくA列の**セル**を取得
1. 該当セルの行番号を**インデックス**にして、固有IDのリストの中から固有IDを付与
1. 付与した固有IDを該当セルの**値**に設定することで、固有IDが回答結果の隣（A列）に表示される
1. 付与した固有IDを**引数**にディレクトリをコピーする関数を呼び出す
1. **GoogleDrive**にあるコピー元のディレクトリを引数（固有ID）名でコピー構築する

# 手順
上記システムを実現するための手順です

## コピー元ディレクトリの準備
以下のようにコピーさせたいディレクトリとその中身のファイルをGoogleDrive上に準備してください
私の場合、**COPYME**というディレクトリの中に**税務書類等.txt**ファイルを配置してあります
この**COPYME**がコピー元ディレクトリになります
![スクリーンショット 2023-06-22 0.37.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377231/d8f0f063-cd34-a6e2-e033-cfcc81a39fec.png)

## Googleフォームの作成

Googleフォームを作成します
回答タブ、**スプレッドシートにリンク**をクリックすることで回答結果をスプレッドシートに連携させます

![スクリーンショット 2023-06-21 23.37.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377231/c5092fb5-963c-93eb-bca6-cfa066e92424.png)


## スプレッドシートの準備
**シートを追加**をクリックして、写真のようにあらかじめ用意した顧客の固有IDリストを別シートに準備しておきます
![スクリーンショット 2023-06-21 23.45.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377231/c4e9a2c1-0d00-9fc0-9540-0c760a28bc9d.png)

また、フォームの回答シートのA列が回答結果のタイムスタンプになってると思うので、左に列を追加してください。この追加したA列に固有IDを付与します。また、タイムスタンプが邪魔なので私はB列を非表示に設定しました。

## Google App Scriptの作成

**Google App Script**を以下のコードに差し替えてください

```javascript
function formsFunction() {
  // 固有IDのリストを取得します
  var values　= getValues();

  var spreadsheet = SpreadsheetApp.openById('ここにスプレッドシートのIDを代入してください');
  var sheet = spreadsheet.getSheets()[0];
   
  // GF最後の行&&A列
  var range = sheet.getRange(sheet.getLastRow(),1);

  // 空だったら固有IDを追加
  if(range.isBlank() == true){
    range.setValue(values[sheet.getLastRow()-2]);

    // 固有IDを引数にして関数呼び出し
    copyFolder(values[sheet.getLastRow()-2]);
  }
}


function getValues() {
  // スプレッドシート＆シートオブジェクトを取得
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName('ID_list');

  // A列の範囲を取得　（全範囲になってるので必要最低限な行に絞った方がスマート）
  var range = sheet.getRange('A:A');
  // セルの値を取得
  var values = range.getValues();

  // 取得したデータを実行ログに表示
  console.log(values);

  return values;
}


function copyFolder(cliantName) {
  // コピー元のフォルダID
  var folderId = "ここにあなたのフォルダIDを代入してください";
  
  // 新しいフォルダ名
  var newFolderName = cliantName;
  
  // コピー元のフォルダを取得
  var sourceFolder = DriveApp.getFolderById(folderId);
  
  // 新しいフォルダを作成
  var newFolder = sourceFolder.getParents().next().createFolder(newFolderName);
  
  // サブフォルダを再帰的にコピー
  copySubFolders(sourceFolder, newFolder);
  
  // フォルダ内のファイルをコピー
  copyFiles(sourceFolder, newFolder);
  
  Logger.log("フォルダをコピーしました。");
}

// サブフォルダを再帰的にコピーする関数
function copySubFolders(sourceFolder, newFolder) {
  var subFolders = sourceFolder.getFolders();
  
  while (subFolders.hasNext()) {
    var subFolder = subFolders.next();
    var newSubFolder = newFolder.createFolder(subFolder.getName());
    copySubFolders(subFolder, newSubFolder);
    copyFiles(subFolder, newSubFolder);
  }
}

// フォルダ内のファイルをコピーする関数
function copyFiles(sourceFolder, newFolder) {
  var files = sourceFolder.getFiles();
  
  while (files.hasNext()) {
    var file = files.next();
    file.makeCopy(file.getName(), newFolder);
  }
}

```
ちなみにスプレッドシートののIDは`https://docs.google.com/spreadsheets/d/xxxx/`の`xxxx`の部分です。

## トリガーの設定

以下トリガーの設定です

![スクリーンショット 2023-06-22 0.10.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377231/e6537178-2a8e-73ae-b21a-03f1c1aadaa7.png)


これで準備は以上です


# テスト

Googleフォームを回答してみてください

- スプレッドシートへの回答結果の反映
- 固有IDの付与と表示
- Googleドライブへのディレクトリ作成

が同時に行われるのを確認できます

![スクリーンショット 2023-06-22 1.35.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377231/9ab0928f-c424-cee8-bdac-9809dc1c9427.png)


以上

はじめてのGAS体験でした