実現したいこと
お世話になります。
GASで別共有ドライブ間で指定フォルダのコピーをするスクリプトを作成しようとしています。
ネットの情報やChatGTPのアドバイスを参考に作成を進めてきたのですが、
どうしてもうまくいかない部分があったのでここで質問しようと思います。
前提
下記のようなGASを作成中です。
スプレットシートで指定されたコピー元とコピー先のアイテムID間でサブフォルダも含んだコピー
をします。無料版だと6分、有料版だと30分で処理がタイムアウトしてしまうので、
指定時間でコピー処理を自動終了し、トリガーで再実行された時にコピー処理を再開させるようにしたいです。
スクリプトの説明
1.コピー元のsourceFolderIdとコピー先のtargetFolderIdを指定するとサブフォルダ以下も含めてコピーする。
2.コピー元のsourceFolderIdはActiveSpreadsheetの'フォルダコピー'シートの'B3'セルを読み込んで指定する。
3.コピー先のtargetFolderIdはActiveSpreadsheetの'フォルダコピー'シートの'B6'セルを読み込んで指定する。
4.初回の処理開始日時をActiveSpreadsheetの'フォルダコピー'シートの'E3'セルに設定する。
5.全ての処理が完了したら処理完了日時をActiveSpreadsheetの'フォルダコピー'シートの'E4'セルに設定する。
6.コピー処理中にGASを実行しても処理が実行できないようにLockService.getScriptLock()でロックを掛ける。
7.処理時間が指定時間(デフォルト5分)を経過すると処理を中断してコピーの処理状態をPropertiesService.getScriptProperties().setPropertyで保存してロックを解放して終了する。
8.GASを再実行するとPropertiesService.getScriptProperties().getPropertyで中断していたコピー処理を再開する。
9.実行が初回の場合はコンソールログに"Starting new session."と表示するようにする。
10.実行が2回目以降の場合はコンソールログに"Resuming session."と表示するようにする。
1回目の実行では、無事にコピーがされるのですが、
2回目の実行で処理を再開させた時に
nextFile.makeCopy(nextFile.getName(), currentIteration.targetFolder);
の部分で下記エラーが出てしまいます。
発生している問題・エラーメッセージ
Exception: The parameters (String,(class)) don't match the method signature for DriveApp.File.makeCopy. nextIteration @ コード.gs:180 copyFolderRecursively @ コード.gs:131 executeCopyProcess @ コード.gs:74
該当のソースコード
GAS(Google
1 var LOCK_KEY = "COPY_PROCESS_LOCK"; 2 var MAX_RUNNING_TIME_MS = 5 * 60 * 1000; //処理時間はデフォルト5分 3 var RECURSIVE_ITERATOR_KEY = "RECURSIVE_ITERATOR_KEY"; 4 5function startTrigger() { 6 //この関数を1日一回のクーロンなどで登録しておく 7 8 // ステータスクリア 9 StatusClear(); 10 11 // 開始日時をセルに記録 12 getStartDateTime(); 13 14 // 終了日時のセルをクリアー 15 ENDDateTimeClear(); 16 17 18 // セッション情報を削除して新しいセッションを開始 19 PropertiesService.getScriptProperties().deleteProperty(RECURSIVE_ITERATOR_KEY); 20 21 //バックアップトリガーを設定 22 ScriptApp.newTrigger("executeCopyProcess").timeBased().everyMinutes(5).create(); 23} 24 25function executeCopyProcess() { 26 27 var lock = LockService.getScriptLock(); 28 29 // スプレッドシートの読み込み 30 const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); 31 // シートの選択 32 const sheet = spreadsheet.getSheetByName('フォルダコピー'); 33 // セルの選択 34 const range1 = sheet.getRange('B3'); 35 // セルの値を取得する 36 const sourceFolderId = range1.getValue(); 37 // セルの選択 38 const range2 = sheet.getRange('B6'); 39 // セルの値を取得する 40 const targetFolderId = range2.getValue(); 41 42 var range3 = sheet.getRange('E6'); 43 // セルの値を取得する 44 var runStatus = range3.getValue(); 45 46 47 try { 48 // Try to acquire the lock and proceed if successful 49 if (lock.tryLock(5000)) { 50 console.info("Lock acquired, starting copy process."); 51 52 copyFolderRecursively(sourceFolderId, targetFolderId, runStatus); 53 } else { 54 console.info("Lock is already taken, skipping this run."); 55 } 56 } finally { 57 58 //ステータスをRunningにセットする 59 StatusRUN(); 60 // Release the lock when done 61 lock.releaseLock(); 62 } 63} 64 65function endTrigger() { 66 //executeCopyProcessトリガーを削除 67 68 var triggers = ScriptApp.getProjectTriggers(); 69 70 for (var i = 0; i < triggers.length; i++) { 71 var trigger = triggers[i]; 72 73 if (trigger.getHandlerFunction() == "executeCopyProcess") { 74 ScriptApp.deleteTrigger(trigger); 75 } 76 } 77} 78 79function copyFolderRecursively(sourceFolderId, targetFolderId,runStatus) { 80 81 var sourceFolder = DriveApp.getFolderById(sourceFolderId); 82 var targetFolder = DriveApp.getFolderById(targetFolderId); 83 84 var startTime = new Date().getTime(); 85 86 var recursiveIterator; 87 88 89// [{folderName: String, fileIteratorContinuationToken: String?, folderIteratorContinuationToken: String}] 90 var recursiveIterator = JSON.parse(PropertiesService.getScriptProperties().getProperty(RECURSIVE_ITERATOR_KEY)); 91 if (recursiveIterator !== null) { 92 // verify that it's actually for the same folder 93 if (sourceFolder.getName() !== recursiveIterator[0].folderName) { 94 console.warn("Looks like this is a new folder. Clearing out the old iterator."); 95 recursiveIterator = null; 96 } else { 97 console.info("Resuming session."); 98 } 99 } 100 101 if (recursiveIterator === null) { 102 console.info("Starting new session."); 103 recursiveIterator = []; 104 recursiveIterator.push(makeIterationFromFolders(sourceFolder, targetFolder)); 105 PropertiesService.getScriptProperties().setProperty(RECURSIVE_ITERATOR_KEY, JSON.stringify(recursiveIterator)); 106 } 107 108 while (recursiveIterator.length > 0) { 109 recursiveIterator = nextIteration(recursiveIterator, startTime); 110 111 var currTime = new Date().getTime(); 112 var elapsedTimeInMS = currTime - startTime; 113 var timeLimitExceeded = elapsedTimeInMS >= MAX_RUNNING_TIME_MS; 114 if (timeLimitExceeded) { 115 PropertiesService.getScriptProperties().setProperty(RECURSIVE_ITERATOR_KEY, JSON.stringify(recursiveIterator)); 116 console.info("Stopping loop after '%d' milliseconds. Please continue running.", elapsedTimeInMS); 117 return; 118 } 119 } 120 121 console.info("Done copying"); 122 getENDDateTime(); 123 StatusClear(); 124 PropertiesService.getScriptProperties().deleteProperty(RECURSIVE_ITERATOR_KEY); 125 126 // executeCopyProcessのトリガーを削除 127 endTrigger(); 128} 129 130function makeIterationFromFolders(sourceFolder, targetFolder) { 131 132// if (!targetFolder) { 133// targetFolder = DriveApp.createFolder("New Target Folder"); // 適切なフォルダ名を設定してください 134// } 135 136 return { 137 folderName: sourceFolder.getName(), 138 targetFolderName: targetFolder.getName(), 139 fileIteratorContinuationToken: sourceFolder.getFiles().getContinuationToken(), 140 folderIteratorContinuationToken: sourceFolder.getFolders().getContinuationToken(), 141 sourceFolder: sourceFolder, 142 targetFolder: targetFolder, 143 144 }; 145} 146 147function nextIteration(recursiveIterator, startTime) { 148 149 var currentIteration = recursiveIterator[recursiveIterator.length -1]; //配列の最後の要素(現在のイテレーション)を取得 150 if (currentIteration.fileIteratorContinuationToken !== null) { 151 var fileIterator = DriveApp.continueFileIterator(currentIteration.fileIteratorContinuationToken); 152 if (fileIterator.hasNext()) { 153 // process the next file 154 var path = recursiveIterator.map(function(iteration) { return iteration.folderName; }).join("/"); 155 var nextFile = fileIterator.next(); 156 processFile(nextFile, path); 157 158 nextFile.makeCopy(nextFile.getName(), currentIteration.targetFolder); 159 160 currentIteration.fileIteratorContinuationToken = fileIterator.getContinuationToken(); 161 recursiveIterator[recursiveIterator.length -1] = currentIteration; 162 return recursiveIterator; 163 } else { 164 // done processing files 165 currentIteration.fileIteratorContinuationToken = null; 166 recursiveIterator[recursiveIterator.length- 1] = currentIteration; 167 return recursiveIterator; 168 } 169 } 170 171 if (currentIteration.folderIteratorContinuationToken !== null) { 172 var folderIterator = DriveApp.continueFolderIterator(currentIteration.folderIteratorContinuationToken); 173 if (folderIterator.hasNext()) { 174 // process the next folder 175 var folder = folderIterator.next(); 176 recursiveIterator[recursiveIterator.length-1].folderIteratorContinuationToken = folderIterator.getContinuationToken(); 177 var newTargetSubfolder = currentIteration.targetFolder.createFolder(folder.getName()); // 新しいサブフォルダを作成 178 recursiveIterator.push(makeIterationFromFolders(folder, newTargetSubfolder)); // ターゲットフォルダを更新した新しいイテレーションを追加 179 180 return recursiveIterator; 181 } else { 182 // done processing subfolders 183 recursiveIterator.pop(); 184 return recursiveIterator; 185 } 186 } 187throw "should never get here"; 188} 189 190 191function processFile(file, path) { 192 console.log(path + "/" + file.getName()); 193} 194 195 196 197function getStartDateTime() { 198//現在時刻を取得 199 var now = new Date(); 200 var year = now.getFullYear(); 201 var month = now.getMonth()+1; 202 var date = now.getDate(); 203 var hour = now.getHours(); 204 var minute = now.getMinutes(); 205 var second = now.getSeconds(); 206 //入力したい文字列に整形する 207 var nowDate = year + "年" + month + "月" + date + "日" + hour + "時" + minute + "分" + second + "秒"; 208// スプレッドシートの読み込み 209 const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); 210 // シートの選択 211 const sheet = spreadsheet.getSheetByName('フォルダコピー'); 212 //E3セルに時刻を入力 213 sheet.getRange('E3').setValue(nowDate); 214 215} 216 217function getENDDateTime() { 218//現在時刻を取得 219 var nowE = new Date(); 220 var yearE = nowE.getFullYear(); 221 var monthE = nowE.getMonth()+1; 222 var dateE = nowE.getDate(); 223 var hourE = nowE.getHours(); 224 var minuteE = nowE.getMinutes(); 225 var secondE = nowE.getSeconds(); 226 //入力したい文字列に整形する 227 var nowEDate = yearE + "年" + monthE + "月" + dateE + "日" + hourE + "時" + minuteE + "分" + secondE + "秒"; 228 // スプレッドシートの読み込み 229 const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); 230 // シートの選択 231 const sheet = spreadsheet.getSheetByName('フォルダコピー'); 232 //E4セルに時刻を入力 233 sheet.getRange('E4').setValue(nowEDate); 234} 235 236function ENDDateTimeClear() { 237 // スプレッドシートの読み込み 238 const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); 239 // シートの選択 240 const sheet = spreadsheet.getSheetByName('フォルダコピー'); 241 //E4セルに時刻を入力 242 sheet.getRange('E4').clearContent(); 243} 244 245function StatusClear() { 246 // スプレッドシートの読み込み 247 const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); 248 // シートの選択 249 const sheet = spreadsheet.getSheetByName('フォルダコピー'); 250 //E4セルに時刻を入力 251 sheet.getRange('E6').clearContent(); 252} 253 254function StatusRUN() { 255 // スプレッドシートの読み込み 256 const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); 257 // シートの選択 258 const sheet = spreadsheet.getSheetByName('フォルダコピー'); 259 //E4セルに時刻を入力 260 sheet.getRange('E6').setValue("Running"); 261} 262
試したこと
自分でネットで調べたりChatGPTにアドバイスを貰ったりしながらエラー修正を
繰り返してここまで来ましたが行きづまってしまいました。
補足情報(FW/ツールのバージョンなど)
Google Apps Script
回答1件
あなたの回答
tips
プレビュー