0

I am stuck at this point. How to get such construction:

 "<b>"+gradesNameArray+":</b> "+studentsGradeArray+"\n"
 "<b>"+gradesNameArray+":</b> "+studentsGradeArray+"\n"
 "<b>"+gradesNameArray+":</b> "+studentsGradeArray+"\n"
 "<b>"+gradesNameArray+":</b> "+studentsGradeArray+"\n"
 "<b>"+gradesNameArray+":</b> "+studentsGradeArray+"\n"
 "<b>"+gradesNameArray+":</b> "+studentsGradeArray+"\n"

And put it here:

sendText(id_callback,!!!HERE!!!,keyBoard );

Full code:

for(var i=1; i < 100; i++){
  if (expenseSheet.getRange(i, 27).getValue() == id_callback) { 
    var studentsGrade = expenseSheet.getRange(i, 1, 1, 25).getValues(); 
    var gradesName = expenseSheet.getRange(1, 1, 1, 25).getValues();
    for(var q=1; q < 10; q++){
      if (studentsGrade[0][3+q] !== "") {
      var gradesNameArray = [gradesName[0][3+q],];
      var studentsGradeArray = [studentsGrade[0][3+q],];
      var gradesMessageText = "<b>"+gradesNameArray+":</b> "+studentsGradeArray+"\n";
    } 
  }            
}
}         
sendText(id_callback,gradesMessageText,keyBoard );

Also I need to check if each [studentsGrade[0][3+q],] is not empty.

Web Page
  • 9
  • 1

2 Answers2

2

Problem

Generating and concatenating strings via looping over a collection of data.

Explanation

The reason why strings are not concatenated is that at each iteration of the loop you redeclare the gradesMessageText variable and, more importantly, initialize it again, until during last iteration the variable gets assigned the data from last entry in the collection.

If you used cost or let, this will not even work, but due to a peculiar behaviour of var, so called hoisting bumps it to the top of the scope (top of the function scope in your case), making it available to be referenced later in sendText.

Optimizations

As it stands now, you script is bound to be slow (the more records, the worse it will get), because you use input / output (I/O) operations in a loop (getRange() -> getValue() chain, getValues() used for extracting a single row). It is best practice to do such operations in batch (i.e. use getValues() once and work on an in-memory array the rest of the time).

Runnable test version:

const id_callback = 26;

const testGrades = [
 "abcdefghijklmnopqrstuvwxyz".split(""),
 [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]
];
const [names] = testGrades.slice(0);

const parsed = testGrades
  .filter(gradeRow => gradeRow[26] === id_callback && gradeRow.slice(4,12).every(Boolean))
  .map(gradeRow => {
    const name = names.slice(4,12);

    return gradeRow.slice(4,12).reduce((acc,cur,i) => acc += `<b>${name[i]}:</b> ${cur}\n`, "");
  });
       
console.log(parsed.join(""));

Sample with services:

const grades = expenseSheet.getRange(1, 1, 99, 25).getValues();
const [ names ] = grades.slice(0);

const parsed = grades
  .filter(gradeRow => gradeRow[26] === id_callback && gradeRow.slice(4,12).every(Boolean))
  .map(gradeRow => {
    const name = names.slice(4,12);

    return gradeRow.slice(4,12).reduce((acc,cur,i) => acc += `<b>${names[i]}:</b> ${cur}\n`, "");
  });

sendText(id_callback, parsed.join("") , keyBoard);

References

  1. map() method
  2. filter() method
  3. slice() method
  4. String concatenation in JavaScript
1

Try this:

var gradesMessageText=""
for(var i=1;i<100;i++){
  if (expenseSheet.getRange(i, 27).getValue() == id_callback) { 
    var studentsGrade = expenseSheet.getRange(i, 1, 1, 25).getValues(); 
    var gradesName = expenseSheet.getRange(1, 1, 1, 25).getValues();
    for(var q=1; q < 10; q++){
      if (studentsGrade[0][3+q] !== "") {
      var gradesNameArray = [gradesName[0][3+q]];
      var studentsGradeArray = [studentsGrade[0][3+q]];
      gradesMessageText+="<b>"+gradesNameArray+":</b> "+studentsGradeArray+"<br />";
    } 
  }            
}
}         
sendText(id_callback,gradesMessageText,keyBoard );
Cooper
  • 59,616
  • 6
  • 23
  • 54