List more than 30 students in a class in Google Classroom API query
Asked Answered
T

3

5

At this moment, I have a script that works correctly to list students of a class in Google Classroom, but it does NOT list ALL of the students, only the first 30. I need it to list ALL of the students, no matter how many there are. What I have now is the following:

function listStudents() {
  var s = SpreadsheetApp.getActiveSpreadsheet();
  var sh = s.getSheetByName('CLASS');
  var r = sh.getDataRange();
  var n = r.getNumRows();
  var d = r.getValues();
  for (x = 0; x < n; x++) {
    var i = d[x][0];
    if(i == ''){ continue; } else if (i == 'D') {
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sh = ss.getSheetByName('LISTSTUDENTS');
      var tea = Classroom.Courses.Students.list(d[x][8]);
      var t = tea.students;
      var arr = [];

      try {
        for (i = 0; i < t.length; i++) {
          var c = t[i]; 
          var ids = c.profile;
          var em = ids.emailAddress;
          arr.push([em]);   
        }
      }
      catch (e) { continue; } 

      sh.getRange(d[x][14], d[x][15], arr.length, arr[0].length).setValues(arr);  
    }
  }
}
Tarton answered 17/3, 2018 at 14:39 Comment(0)
E
7

You receive only 30 students in the query because you are only accessing the first page of results. Almost every "advanced service" functions in a similar manner with regards to collections, in that they return a variable number of items in the call (usually up to a size that can be specified in the query, but there are limits). This is to ensure timely service availability for everyone who uses it.

For example, consider Bob (from Accounting). This style of request pagination means he can't request a single response with 20,000 items, during which the service is slower for everyone else. He can, however, request the next 100 items, 200 times. While Bob is consuming those 100 items from his most recent query, others are able to use the service without disruption.

To set this up, you want to use a code loop that is guaranteed to execute at least once, and uses the nextPageToken that is included in the response to the call to .list() to control the loop. In Javascript / Google Apps Script, this can be a do .. while loop:

// Runs once, then again until nextPageToken is missing in the response.
const roster = [],
    // The optional arguments pageToken and pageSize can be independently omitted or included.
    // In general, 'pageToken' is essentially required for large collections.
    options = {pageSize: /* reasonable number */};

do {
  // Get the next page of students for this course.
  var search = Classroom.Courses.Students.list(courseId, options);

  // Add this page's students to the local collection of students.
  // (Could do something else with them now, too.)
  if (search.students)
    Array.prototype.push.apply(roster, search.students);

  // Update the page for the request
  options.pageToken = search.nextPageToken;
} while (options.pageToken);
Logger.log("There are %s students in class # %s", roster.length, courseId);
Everyway answered 17/3, 2018 at 15:23 Comment(1)
This worked when integrated into the original script.Tarton
F
1

for those who struggle with this, here's the code

    function listStudent() {
    var pageSizeValue = 300; /*** change with numbers that you want*/
    var nextPageToken = '';
    var courseID = 1234; /*** change with numbers that you want*/
    var ownerArray = [];

    do {
        var optionalArgs = {
            pageSize: pageSizeValue,
            pageToken: nextPageToken
        };
        var cls = Classroom.Courses.Students.list(courseID, optionalArgs);
        var nextPageToken = cls.nextPageToken;
        
       const ssData = cls.students.map(c => {
       return [c.profile.id,c.profile.name.fullName,c.profile.emailAddress]
              });

        Array.prototype.push.apply(ownerArray, ssData);

       } while (nextPageToken);
         const ss = SpreadsheetApp.openById("1234"); // <<< UPDATE THIS
         const sheet = ss.getSheetByName("Sheet1"); // <<< UPDATE THIS
     sheet.getRange(2,1,ownerArray.length,ownerArray[0].length).setValues(ownerArray); // <<< UPDATE THIS
    }
          
Feminize answered 6/2, 2021 at 3:39 Comment(0)
S
0

I modified the getRoster function in the example provided by Google (https://developers.google.com/apps-script/add-ons/editors/sheets/quickstart/attendance) as follows, and it worked for me.

function getRoster(courseId) {
  var studentNames = []
  var studentEmails = []
  var nextPageToken = ''  

  do {
    var optionalArgs = {
      pageSize: 30,
      pageToken: nextPageToken
    };
    var response = Classroom.Courses.Students.list(courseId, optionalArgs)
    var students = response.students
    nextPageToken = response.nextPageToken    

    for (var i = 0; i <= students.length; i++) {
      try {
        studentNames.push(students[i].profile.name.fullName)
        studentEmails.push(students[i].profile.emailAddress)
      } catch (err) {        
      }
    }
  } while (nextPageToken);
  return { "studentNames":studentNames, "studentEmails":studentEmails }
}
Sciomancy answered 13/1, 2022 at 8:22 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Madwort

© 2022 - 2024 — McMap. All rights reserved.