1
votes

I'm still fairly new with Google Scripts. I have a student roster Google Sheet with demographic information, including ID numbers. I also have a responses Sheet that automatically collects email addresses on Column B (email addresses are created by the ID number plus "@foo.org"). I'm trying to get my script to parse through auto-collected emails, map the ID portion of the email onto column C. Then I'm using for loops to check the extracted ID number against my main roster, and map the remaining information for the same student on the responses sheet.

As of now, I'm only able to correctly map the first row in the responses sheet; As of the second row I only see the numeric IDs but it doesn't map the other relevant columns. This is what I currently have:

function extractId() {
  var responsesSheet = SpreadsheetApp.openById('XXXXXXX').getSheetByName('Sheet1');
  var rosterSheet = SpreadsheetApp.openById('XXXXXXX').getSheetByName('Sheet1');

  var responsesHighestEntry = responsesSheet.getLastRow();

  var email;
  var idNumber;

  var rosterLastRow = rosterSheet.getLastRow();
  var rosterArray = rosterSheet.getRange(2, 1, (rosterLastRow - 1)).getValues();
  var studentResponsesRow;

  var i;
  var x;
  var y = 2;
  var fullName;
  var grade;
  var advisoryTeacher;
  var advisoryRoom;


  for (i = 2; i < responsesHighestEntry; i++) {
    email = responsesSheet.getRange(i, 2).getValue();
    idNumber = email.replace(/\@(.*)/i,"");
    responsesSheet.getRange(i, 3).setValue(idNumber);

    for (x = 0; x < rosterLastRow; x++) { 
      if (rosterArray[x] == idNumber) {
        studentResponsesRow = y;

        fullName = rosterSheet.getRange(y, 2).getValue(); 
        responsesSheet.getRange(y, 4).setValue(fullName);

        grade = rosterSheet.getRange(x + 2, 6).getValue(); 
        responsesSheet.getRange(studentResponsesRow, 5).setValue(grade);

        advisoryTeacher = rosterSheet.getRange(x + 2, 7).getValue(); 
        responsesSheet.getRange(studentResponsesRow, 6).setValue(advisoryTeacher);

        advisoryRoom = rosterSheet.getRange(x + 2, 8).getValue(); 
        responsesSheet.getRange(studentResponsesRow, 7).setValue(advisoryRoom);
      } 

      y++;

    }
  }
}

Sample roster Sample roster sheet with demographic data.

Sample end-result responses sheetSample end-result responses sheet. In this case, the email addresses are auto-collected. Columns C-G would be the result of running the script.

1
Can you provide a sample Spreadsheet including the script for replicating the situation of I'm only able to correctly map the first row in the responses sheet; As of the second row I only see the numeric IDs but it doesn't map the other relevant columns.? Of course, please remove your personal information. By the way, in your script, it seems that the ID is retrieved from email. But how about directly retrieving it from the column "C"? - Tanaike
The second image is the one that would execute the script. The first part of the first for-loop extracts the ID from the email, and sets the value on Column C. Then, in the second for-loop, I'm trying to cross check that ID against the roster sheet (first image), and then map the data onto the relevant columns in the response row. The script includes mapping the full name onto column D of the second image. For work confidentiality reasons I cannot provide a sample sheet other than the pictures. - gonzalo2000
Thank you for replying. I understood that you cannot provide a sample Spreadsheet. Can you provide the method for replicating about I'm only able to correctly map the first row in the responses sheet...? Because although I prepared the sample sheet of the images, I cannot replicate your situation using your updated script. So I thought that the sample of images might be the different from the actual format. By the way, in your script, it seems that the ID is retrieved from email. But how about directly retrieving it from the column "C"? If I misunderstood your situation, I apologize. - Tanaike
Thanks for replying. Lines 29-42 of the above script is what's mapping the content on my original file. In my original setup, the second image would only have Column B. The intention is that the second for-loop checks the ID extracted from the email against the roster and maps the data onto the responses sheet. (he general idea is to have a Google Form set to auto-collect email. The responses sheet (i.e. the second image) would have Column B, and then the script produces columns C-G based on accurate data. I'm running into problems after the first iteration of the loop. - gonzalo2000
Thank you for replying. I thought that I could understand about your goal. So I proposed a modified script as an answer. Could you please confirm it? If I misunderstood your question and that was not the result you want, I apologize. - Tanaike

1 Answers

2
votes
  • You want to achieve "Sample end-result responses sheet" from the values of "roster sheet" in the images in your question.
    • In your situation, "responses sheet" has only the column "B" which has the email addresses.
    • You want to put the values that the ID from the email address is the same with the column "A" in "roster sheet".
  • You want to achieve this using Google Apps Script.

If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.

The flow of this modified script is as follows.

  1. Retrieve the values of the column "B" from "responses sheet".
  2. Retrieve the values from "roster sheet".
  3. Create an object for searching IDs.
  4. Create the result values as an array.
  5. Put the values to "responses sheet".

Modified script:

function extractId() {
  var responsesSheet = SpreadsheetApp.openById('XXXXXXX').getSheetByName('Sheet1');
  var rosterSheet = SpreadsheetApp.openById('XXXXXXX').getSheetByName('Sheet1');
  var valuesOfresponsesSheet = responsesSheet.getRange(2, 2, responsesSheet.getLastRow() - 1, 1).getValues();
  var valuesOfrosterSheet = rosterSheet.getRange(2, 1, rosterSheet.getLastRow() - 1, 8).getValues();
  var obj = valuesOfrosterSheet.reduce(function(o, e) {
    o[e[0]] = [e[0], e[1], e[5], e[6], e[7]];
    return o;
  }, {});

  // var resultValues = valuesOfresponsesSheet.map(function(e) {return obj[e[0].replace(/\@(.*)/i,"")]});
  var resultValues = valuesOfresponsesSheet.map(function(e) {return obj[e[0].toString().replace(/\@(.*)/i,"")] || ["","","","",""]}); // Modified

  responsesSheet.getRange(2, 3, resultValues.length, resultValues[0].length).setValues(resultValues);
}

Reference: