0

I am trying to find a specific spreadsheet(Target) within each folder (A). These folders are within Folder (B) which are in turn within Folder (C). The current script i have retrieve folder (C), and search through each (B) for folder (A) then spreadsheet. However, because of large numbers of folder (B), i have placed a continuationtoken at the folder (A) level to track which folder (B) have been searched [or at least i believe that's what i am doing]. The issue I have is that the script always resume from the same first folder (B) instead of continuing from the last folder (B) that was searched.

Folder (C) = baseFolder

Folder (B) = studentFolder

Folder (A) = AssessmentFolder

Spreadsheet (Target) = any spreadsheet which includes the given searchkey

Following are snippets of the script that i am using.


        if (continuationToken == null) {
            // firt time execution, get all files from Drive
            var allFolders = baseFolder.getFolders();
            var Tokenalert = ui.alert('There is no token');
          } 

          else {
            // not the first time, pick up where we left off
            var allFolders = DriveApp.continueFolderIterator(continuationToken);
          }

          while (allFolders.hasNext() && end.getTime() - start.getTime() <= maxTime) {
            i++;
            var studentFolder = allFolders.next();
            var AssessmentFolder = studentFolder.getFoldersByName("02 Assessment");
            if (AssessmentFolder.hasNext() == true){
              Logger.log(studentFolder.getName());
              progress.getRange(i,1).setValue(studentFolder.getName());
              AssessmentFolder = AssessmentFolder.next();
              if (AssessmentFolder.searchFiles(checkcode).hasNext() == true){ 

                var filetochange = AssessmentFolder.searchFiles(checkcode); 
                var editfile = filetochange.next();
                progress.getRange(i,2).setValue(editfile);
                Logger.log(editfile);var fileid = editfile.getId();
                var editss = SpreadsheetApp.openById(fileid);

                Logger.log(editss.getName());
                progress.getRange(i,3).setValue(fileid);
                var editsheet = editss.getSheetByName(sheettoedit); 
                // remove protection from the sheet mentioned
                // Protect the active sheet except B2:C5, then remove all other users from the list of editors.
                var protection = editsheet.protect().setDescription('Test');

                if (protectrange != 0) {
                  var unprotected = editsheet.getRange(protectrange);
                }

                if (protectrange2 != 0) {
                var unprotected2 = editsheet.getRange(protectrange2);
                }

                else {
                unprotected2 = unprotected;
                }

                if (protectrange3 != 0) {
                  var unprotected3 = editsheet.getRange(protectrange3);
                }

                else {
                  unprotected3 = unprotected2;
                }

                protection.setUnprotectedRanges([unprotected, unprotected2]);

                // Ensure the current user is an editor before removing others. Otherwise, if the user's edit
                // permission comes from a group, the script throws an exception upon removing the group.
                var me = Session.getEffectiveUser();
                protection.addEditor(me);
                protection.removeEditors(protection.getEditors());

                if (protection.canDomainEdit()) {
                  protection.setDomainEdit(false);
                }

                progress.getRange(i,4).setValue("complete");
              }

              else {
                progress.getRange(i,4).setValue("fail");
              }
            }

            end = new Date()

          }

          // Save your place by setting the token in your user properties
          if(allFolders.hasNext()){
            var continuationToken = allFolders.getContinuationToken();
            userProperties.setProperty('CONTINUATION_TOKEN', continuationToken);
            progress.getRange(1,6).setValue(continuationToken);
          } else {
            i++;
            progress.getRange(i,1).setValue("Completed")
            // Delete the token
            PropertiesService.getUserProperties().deleteProperty('CONTINUATION_TOKEN');
            ss.deleteSheet("Progress");

            var Completionalert = ui.alert('completed');
          }

Pardon my messy code as I am new to coding.

I have checked and the continuation token is stored, and is retrieved. I have also ensured that the script does not end prematurely before the token is stored. The only issue i can think of is that either the way I enter the token again is wrong, or a wrong token is stored. But i am unsure of which. I have tried storing the token at B level and A level, but it doesn't make sense and doesn't work.

Also, I have read the following:

https://developers.google.com/apps-script/reference/drive/folder-iterator Howver it was not very helpful as it only shows how to get a token.

Google Apps Script: How to use ContinuationToken with recursive folder iterator but i do not understand the the term recursive.

It would be great if someone can explain how continuationtoken works. Does it just track the last folder and resume from there? or does it actually take the whole list of folder and gives the position?

To reiterate, the main issue is that the token is created and retrieved, but somehow the script is not resuming from the last folder checked.

Any offhand feedback on other portions of the script is welcomed^^ and thank you in advance!:)

  • You need to call the continue method for the same folder or file search object. So if you generated the original iterator with `DriveApp`, you'd use`DriveApp.continue......`. If you started from some specific folder, you need to get that specific folder, and then call the method from it, not `DriveApp` – tehhowch Jan 27 '20 at 13:14
  • Hi tehhowch, i have tried using that specific folder but i am getting the error of Cannot find function continueFolderIterator in object Student Folders. ? continueFolderIterator are functions only of driveApp class, is that correct? – edmund chan kei yun Jan 29 '20 at 01:56
  • Note that you store a token produced by your "allFolders" variable. To use this token, you need to apply it to the same search that allFolders was - the result of "baseFolder.getFolders()" – tehhowch Jan 29 '20 at 04:46
  • Hi tehhowch, the function continueFolderIterator can only be retrieved from DriveApp. The script is working fine already. Just clarifying in case others read this thread and gets confused. Thank you for your help:) – edmund chan kei yun Feb 05 '20 at 01:35

2 Answers2

0
  1. There are script run-time limitations
    • regular user: 6 minutes
    • Business/Enterprise/Education: 30 mins

Take a brief look for detailed article on Quotas for Google Services


  1. Take a look on Stackoverflow threat Google Apps Script: How to use ContinuationToken with recursive folder iterator, it has similarities to your question

  1. Recursive function is the function which calls itself

Here is the little example of function which returns the base to the exponent power

function pow(a, b) {
  if (b === 1) { return a } 
  else { return a * pow(a, b - 1) }
}
console.log(pow(3, 3)) // same as 3 * 3 * 3 = 27

P.S. This is just an example, use Math.pow() instead


Does it clarify your concerns?

Jeff Rush
  • 874
  • 6
  • 13
  • Hi Jeff, I am aware of the limit and therefore I am utilising the continuationtoken to attempt to work around the limit. As mentioned in my post, I have read the thread that you mentioned, and have taken into account the things noted there. Your explanation on recursive function has helped thank you. But ultimately the issue is not resolved, maybe it wasn't clear, but my issue is that the token is not used, or may be used incorrectly as i have verified that a token is created. I would re-edit my post to re-highlight the main issue, thank you :) – edmund chan kei yun Jan 27 '20 at 10:42
0

After checking through my script, I realized that the error came from me declaring the variable allFolders twice, one more time before this chunk of script and the script is now working as it should after removing the first declaration of allFolders.

Therefore, there was nothing wrong with the script posted here.