Gg / Google Drive 移動副本文件到特定資料夾 2

延續「Gg / Google Drive 移動副本文件到特定資料夾 1

處理如何把上傳的檔案分門別類放在各自的資料夾內

這當然就需要用Google Apps Script來達成,為了避免動到表單資料

所以將資料複製到另一個工作表,並增加會用到的欄位

A至H欄是原本的表單資料

I欄是紀錄是否已經處理過,避免重覆複製檔案

J欄是新的個別作業資料夾的連結

K欄是用來記錄如果錯誤時的訊息


回過頭來說程式的構想

如果透過表單上傳,G欄會是每一個檔案的連結路徑

如果直接提供雲端資料夾,H欄會是一個雲端資料夾的連結路徑

主程式要先處理表單上的資料

再透過兩個子程式處理G欄或H欄的連結

主程式 getDatafromSheet()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
function getDatafromSheet() {
  //https://docs.google.com/spreadsheets/d/***************************************/
  //113-修訂版學習扶助師資研習課程講師培訓課程-課後作業 (回覆)
  var ss = SpreadsheetApp.openById("***************************************");

  var sOne = ss.getSheets()[2];//工作表-作業處理
  //Logger.log(sOne.getName());

  var r = sOne.getLastRow();
  //var r = 3
  //Logger.log(r);

  for (var i = 2; i <= r; i++) {
    //Logger.log(i);
    var checkDo = sOne.getRange(i, 9).getValue();
    if (checkDo === "") {
      var rName = sOne.getRange(i, 3).getValue();//姓名
      //Logger.log(rName);
      var rCity = sOne.getRange(i, 5).getValue();//服務縣市
      //Logger.log(rCity);
      var rSub = sOne.getRange(i, 6).getValue();//繳交作業科目
      //Logger.log(rSub);
      var rFiles = sOne.getRange(i, 7).getValue();//課後作業上傳
      var rFilesArr = rFiles.toString().split(",");
      //Logger.log(rFilesArr.length);
      var rDriUrl = sOne.getRange(i, 8).getValue();//雲端資料夾網址
      //Logger.log(rDriUrl);

      //var resultMoveFile = test();
      //Logger.log(resultMoveFile);
      if (rFiles == "" && rDriUrl != "") {
        var reustMg = copyDriUrl(i, rName, rCity, rSub, rDriUrl);
      } else {
        var reustMg = copyFileToFolder(i, rName, rCity, rSub, rFilesArr);
      }

      //Logger.log(reustMg);

      if (reustMg[0] === "good") {
        sOne.getRange(i, 9).setValue("◎");
        sOne.getRange(i, 10).setValue("https://drive.google.com/drive/folders/" + reustMg[1]);
      } else if (reustMg[0] === "bad") {
        sOne.getRange(i, 11).setValue(reustMg[1]);
      } 
      //if reustMg
    } else {
      Logger.log("已執行過");
    }
    // if checkDo
  }
  //for i
}

 

處理G欄的子程式 copyFileToFolder(n, n1, n2, n3, n4)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//*******************************************************************************************************************
//
//n,序號
//n1,姓名 rName
//n2,服務縣市 rCity
//n3,繳交作業科目 rSub
//n4,課後作業上傳 rFilesArr

function copyFileToFolder(n, n1, n2, n3, n4) {
  //Logger.log(n1);
  //Logger.log(n2);
  //Logger.log(n3);
  //Logger.log(n4);

  //主資料夾  課後作業/表單上傳
  //var mainFolder = DriveApp.getFolderById("10BOUbWUaVzPrxu1MbeXiDuAJmQ1tIGan");

  var subName = n3;//繳交作業科目

  //繳交作業科目的資料夾
  var arr1 = ["國中國語文(繳交期限10/14)", "國小國語文(繳交期限10/14)", "國中英語文(繳交期限10/13)", "國小英語文(繳交期限10/6)", "國中數學(繳交期限10/13)", "國小數學(繳交期限10/13)-01-國小學生數學學習發展與實務", "國小數學(繳交期限10/13)-02-國小數學補救教學課程規劃", "共同課程二-國中(繳交期限10/31)", "共同課程二-國小(繳交期限10/18)"];

  //對應繳交作業科目的資料夾的資料夾ID
  var arr2 = ["******************", "******************", "******************", "******************", "******************", "******************", "******************", "******************", "******************"];

  //取得繳交作業科目在arr1的位置
  var subIndex = arr1.indexOf(subName);
  //ogger.log(subIndex);
  //Logger.log(arr2[subIndex]);

  //透過arr1的相對位置取得arr2的對應值
  var subId = arr2[subIndex];//繳交作業科目的資料夾 folderID
  var subFolder = DriveApp.getFolderById(subId);

  //判斷是否已經有相同名稱的資料夾在科目資料夾內
  var folderName = n + n3 + "-" + n1;
  /*
  var folders = subFolder.getFolders();
  while (folders.hasNext()) {
    folder = folders.next();
    if (folder.getName() === folderName) {
      i=2;
      folder.setName(folderName +"-"+ i);
      i=i+1;
      break;
    };
  }*/
  var workFolder = DriveApp.createFolder(folderName);
  workFolder.moveTo(subFolder);//將學員的作業資料夾移動到對應的科目資料夾
  var workFolderId = workFolder.getId();
  //Logger.log(n4);
  //移動作業檔案
  for (var r = 0; r < n4.length; r++) {
    //https://stackoverflow.com/questions/50051358/trim-and-clean-google-script
    //https://stackoverflow.com/questions/5964373/is-there-a-difference-between-s-g-and-s-g
    var dUrl = n4[r].toString().trim().replace(/\s(?=\s)/g, '');
    //Logger.log(dUrl);

    var dId = dUrl.split("=")[1];
    //Logger.log(dId);

    var fOne = DriveApp.getFileById(dId);
    var new_fOne = fOne.makeCopy(workFolder);
  }
  var msg = [];
  msg.push("good");
  msg.push(workFolderId);
  return msg;
}

 

處理H欄的子程式 copyDriUrl(e, e1, e2, e3, e4)

#40-54

程式碼參考了#65-81的copy(fromFolder, toFolder)

因為Google Drive 無法直接透過程式複製整個資料夾

要先創建資料夾,再複製檔案

由於資料夾可能會有好幾層

這個程式先複製第一層的所有檔案到指定的資料夾

然後再尋找第一層是否有資料夾

如果有資料夾,就在指定的資料夾內創建相同名稱的資料夾

再把資料夾內的檔案複製到這個資料夾

遍歷到所有的資料夾跟檔案

這個設計概念在之前的VBA遍歷FTP內的所有資料夾跟檔案很類似

在程式內呼叫自己的遞迴程式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//*******************************************************************************************************************
//
//e,序號
//e1,姓名 rName
//e2,服務縣市 rCity
//e3,繳交作業科目 rSub
//e4,雲端資料夾網址 rDriUrl

function copyDriUrl(e, e1, e2, e3, e4) {
  var msg = [];//記錄錯誤訊息
  try {
    var fromFolderId = e4.toString().split("https://drive.google.com/drive/folders/")[1].split("?")[0];
    var fromFolder = DriveApp.getFolderById(fromFolderId);
  } catch (error) {
    msg.push("bad");
    msg.push(error);
    return msg;
  }

  var subName = e3;//繳交作業科目

  //繳交作業科目的資料夾
  var arr1 = ["國中國語文(繳交期限10/14)", "國小國語文(繳交期限10/14)", "國中英語文(繳交期限10/13)", "國小英語文(繳交期限10/6)", "國中數學(繳交期限10/13)", "國小數學(繳交期限10/13)-01-國小學生數學學習發展與實務", "國小數學(繳交期限10/13)-02-國小數學補救教學課程規劃", "共同課程二-國中(繳交期限10/31)", "共同課程二-國小(繳交期限10/18)"];

  //對應繳交作業科目的資料夾的資料夾ID
  var arr2 = ["******************", "******************", "******************", "******************", "******************", "******************", "******************", "******************", "******************"];

  //取得繳交作業科目在arr1的位置
  var subIndex = arr1.indexOf(subName);
  //ogger.log(subIndex);
  //Logger.log(arr2[subIndex]);

  //透過arr1的相對位置取得arr2的對應值
  var subId = arr2[subIndex];//繳交作業科目的資料夾 folderID
  var subFolder = DriveApp.getFolderById(subId);
  var folderName = e + e3 + "-" + e1;
  var workFolder = DriveApp.createFolder(folderName);
  workFolder.moveTo(subFolder);//將學員的作業資料夾移動到對應的科目資料夾

  // copy files
  var fromFiles = fromFolder.getFiles();
  while (fromFiles.hasNext()) {
    var fOne = fromFiles.next();
    var newFile = fOne.makeCopy(workFolder);
    newFile.setName(fOne.getName());
  }

  // copy folders
  var folders = fromFolder.getFolders();
  while (folders.hasNext()) {
    var folder = folders.next();
    var newFolder = workFolder.createFolder(folder.getName());
    copy(folder, newFolder);
  }

  var workFolderId = workFolder.getId();

  msg.push("good");
  msg.push(workFolderId);
  return msg;
}
//
//參考 https://gist.github.com/KenjiOhtsuka/d4432b6d80ad2b81ab7c965de2a8a00d
//
function copy(fromFolder, toFolder) {
  // copy files
  var files = fromFolder.getFiles();
  while (files.hasNext()) {
    var file = files.next();
    var newFile = file.makeCopy(toFolder);
    newFile.setName(file.getName());
  }

  // copy folders
  var folders = fromFolder.getFolders();
  while (folders.hasNext()) {
    var folder = folders.next();
    var newFolder = toFolder.createFolder(folder.getName());
    copy(folder, newFolder);
  }
}

 

接下來再來說明程式內容