Diagonali
Diagonali

Reputation: 109

Where/how to set increment on loop and update array only when condition found?

I'm writing a function to iterate through folders on Google Drive and match files (Google Sheets) with a variable string (a date specified on a table cell). When a matching file is found, the containing folder name string is assigned to folderItems[0] and the file URL to folderItems[1]. Once all matching files within a folder have been found, the next folder is iterated through in the same way. These "folderItems" arrays are stored in a parent array "folderItemsContainer" to create a 2 dimensional array which can then be output to a spreadsheet using .setValues().

I'm having trouble figuring out how or where to put the increment variable so that it will increment only when a filename match is made but not stop a loop when a match isn't found.

I've tried various structures including interchanging for and while loops and inserting if statements where seemingly useful. I've looked at a few different answers on Stackoverflow that come close to making sense but none seem to be applicable here. I'm fairly new to programming. I've got different variations of code I've tried, but this is where I'm up to so far:

function GetFolderData() {
  var currentSheet = SpreadsheetApp.getActiveSpreadsheet();
  var currentYearPeriod = currentSheet.getRange("C1!A4").getValue();
  // Logger.log(currentYearPeriod);

  //Get folder objects from parent folder
  var parentFolderId = "17F0fcBH0jmxsk2sUq723AuIY0E2G_u0m";
  var parentFolder = DriveApp.getFolderById(parentFolderId);

  //Get folders from specified parent folder
  var StaffFolders = parentFolder.getFolders();

  //Create container array
  var folderItemsContainer = [];
  //Create Item Array
  var folderItems = [];
  var i = 0;

  //For every staff folder, regardless of content, do:
  while (StaffFolders.hasNext()) {
    //Get current folder object
    currentFolder = StaffFolders.next();

    //Get files in current folder object as FileIterator
    FolderFiles = currentFolder.getFiles();

    //If folder empty, outer while loop will iterate
    if (FolderFiles !== null) {
      //Iterate through existing files
      while (FolderFiles.hasNext()) {
        //Get file object sequentially
        file = FolderFiles.next();

        //When filename matches currentYearPeriod, store URL next to name in folderItems
        for (i = 0; file.getName().indexOf(currentYearPeriod) !== -1; i++) {
          folderItems[i] = [];

          folderItems[i][0] = currentFolder.getName();
          //  Logger.log(currentFolder.getName());

          folderItems[i][1] = file.getUrl();

          folderItemsContainer[i] = folderItems[i];
        }
      }
    }
  }

  return folderItemsContainer;
}

function InsertFolderData() {
  var sheet = SpreadsheetApp.getActiveSheet();
  sheet.getRange("B4:Z1000").clearContent();
  FolderData = GetFolderData();
  Logger.log(FolderData);
  sheet
    .getRange(4, 2, FolderData.length, FolderData[0].length)
    .setValues(FolderData);
  Logger.log(FolderData);

  /* var str = "";

  for (var i = 0; i < FolderData.length; i++) {
    str += FolderData[i] + "\r\n";
  }
  str = str.substr(0);

  var ui = SpreadsheetApp.getUi();
  ui.alert("DATA IMPORTED: " + "\r\n" + str);

  */
}

With the above code, I'm not entirely sure why but I seem to be getting stuck in an endless loop and the script doesn't finish. What I'm hoping to achieve is the folderItemsContainer array being populated with arrays containing file information (parent folder name[0] and file URL[1]) for files that match the currentYearPeriod variable. I've been refactoring the code and I've learned a lot but unfortunately not how to solve the problem.

Upvotes: 1

Views: 551

Answers (2)

Nelston
Nelston

Reputation: 78

You should check what's the deference between each loop, you are not fully undestending them. If you want to execute the instructions inside the for loop until a certain condition is met, in this case file.getName().indexOf(currentYearPeriod) !== -1, you should use a while loop. The bug is that the previous condition is never met because file never change while running the for loop. Thats why you are having an infinite loop. My solution:

// new variable
var cnt = 0;

while (StaffFolders.hasNext()) {
    currentFolder = StaffFolders.next();
    FolderFiles = currentFolder.getFiles();

    if (FolderFiles !== null) {
      while (FolderFiles.hasNext()) {
        file = FolderFiles.next();

        // You for loop started here
        folderItems[cnt] = [];
        folderItems[cnt][0] = currentFolder.getName();
        folderItems[cnt][1] = file.getUrl();
        folderItemsContainer[cnt] = folderItems[cnt];

        // each time you read a new file you increment by 1
        cnt++;
      }
    }
    // this reset the counter for each new folder
    cnt = 0;
  }

Deferences between loops:

for loops

They are used when you know how many iteration will be needed. For example, if you want to print all the character of a string in the console:

const str = "hello";
for(let i = 0; i < str.length; i++) {
   console.log(str.charAt(i));
}
  • let i = 0 is the starting point
  • i < str.length is when you want to stop. If you have to use a simbol which is not one of the follow <, <=, >, >=, you shouldn't be using a for loop.
  • i++ how you want to reach the stop property.

while loops

If you dont know when your loop is going to end, if it's going to have, 5 iteration, 100 iteration or 0 iteration. You should use while loops.

function getFirstL(str)
   let i = 0;
   while(i < str.length && str.charAt(i) !== "l"){
      i++;
   }
}

Upvotes: 2

tksilicon
tksilicon

Reputation: 4426

Your for loop. Here is syntax of for loop.

for (statement 1; statement 2; statement 3) {
  // code block to be executed
}

Statement 1 is executed (one time) before the execution of the code block.

Statement 2 defines the condition for executing the code block.

Statement 3 is executed (every time) after the code block has been executed.

Your for loop doesn't define a condition for it to exit. A minimum or maximum value. something like

i<file.getName().indexOf(currentYearPeriod); 

So it will check from 0-to that value.

Upvotes: 1

Related Questions