Google Script: print school schedule data for each teacher - google-apps-script

This is my first question here. I have searched the site to the best of my knowledge, but haven't found any other examples of my question.
Here is the Google Sheets file
https://docs.google.com/spreadsheets/d/1HxyhoxuPK8H8_vhLg0ZZ-THyOn1cn9nPYRyls8y47iM/edit?usp=sharing
I have 2 sheets in the same Google Sheets document.
The first, "schema" contains a base-school schedule for a teacher, with different classes in different blocks. This needs to be replicated, so that all teachers has this exact setup - so that all unique users have the same 50 lines of schedule data - only with their allocated classes.
The second sheet contains information about the users. Each line contains a UNI-login username and their designated class 1a-1, 4a-1 and 8a-1 for user uni12345 for example. 1a-1 needs to replace 1, in "uni12345"'s schedule data.
I would like all these data (a lot of lines) combined into one sheet, fx. called "combined" - but you get your pick on the name :-)
I have made a Combined Example sheet, that presents how I would like the output for user1+2 in the list.
If the question already is partly answered elsewhere, I'll be happy to look at that also!
Edit:
Since my original question I have made it work - only now I'm hitting the 6min script exectution time limit. Any way around that, eg. optimization?
function merge() {
var CurrentDate = new Date() ;
var CurrentDateString1 = Utilities.formatDate(CurrentDate, "GMT", "MM-dd-yyyy HH:mm:ss") ;
var ss=SpreadsheetApp.getActive();
// var mergeSht=ss.getSheetByName(CurrentDateString1);
var users=ss.getSheetByName('users');
var schema=ss.getSheetByName('schema');
var mergeSht = ss.insertSheet();
mergeSht.setName(CurrentDateString1);
var usersValues = users.getDataRange().getValues();
var schemaValues = schema.getDataRange().getValues();
var counter = 1;
for(var n=1; n < usersValues.length ; n++){
var usersValue = usersValues[n];
var uniName = usersValue[5];
var levelInd = usersValue[2];
var levelMellem = usersValue[3];
var levelUdsk = usersValue[4];
// Logger.log(usersValues[n][5])
for(var i=1; i < schemaValues.length ; i++){
var schemaValue = schemaValues[i];
if (schemaValue != null && schemaValue.length > 0) {
var level = schemaValue[3];
var subject = schemaValue[4];
var room = schemaValue[5];
var day = schemaValue[6];
var position = schemaValue[7];
var levelAfd = getlevel(level,levelInd, levelMellem, levelUdsk);
Logger.log(levelAfd);
// print
var row=[];
row.push(counter++,'','unilogin:'+ uniName, levelAfd, subject, room, day, position);
mergeSht.appendRow(row);
}
}
}
}
function getlevel(level, levelInd, levelMellem, levelUdsk){
switch (level)
{
case 1:
return levelInd;
case 4:
return levelMellem;
case 7:
return levelUdsk;
}
}

Here's something else you could try:
This code creates a new array which avoids having to push each row one by one. Instead, at the end in loads the entire mergeSht all at one time.
function merge()
{
var CurrentDate = new Date() ;
var CurrentDateString1 = Utilities.formatDate(CurrentDate, "GMT", "MM-dd-yyyy HH:mm:ss") ;
var ss=SpreadsheetApp.getActive();
// var mergeSht=ss.getSheetByName(CurrentDateString1);
var users=ss.getSheetByName('users');
var schema=ss.getSheetByName('schema');
var mergeSht = ss.insertSheet();
mergeSht.setName(CurrentDateString1);
var usersValues = users.getDataRange().getValues();
var schemaValues = schema.getDataRange().getValues();
var counter = 1;
var mergeA=[];//Small change
mergeA.push(['H1','H2','H3','H4','H5','H6','H7','H8']); //First row is headers
for(var n=1; n < usersValues.length ; n++)
{
var usersValue = usersValues[n];
var uniName = usersValue[5];
var levelInd = usersValue[2];
var levelMellem = usersValue[3];
var levelUdsk = usersValue[4];
// Logger.log(usersValues[n][5])
for(var i=1; i < schemaValues.length ; i++)
{
var schemaValue = schemaValues[i];
if (schemaValue != null && schemaValue.length > 0)
{
var level = schemaValue[3];
var subject = schemaValue[4];
var room = schemaValue[5];
var day = schemaValue[6];
var position = schemaValue[7];
var levelAfd='';
switch(level)
{
case 1:
levelAfd=levelInd;
break;
case 4:
levelAfd=levelMellem;
break;
case 7:
levelAfd=levelUdsk;
break;
default:
levelAfd='';
break;
}
if(levelAfd)
{
mergeA.push([counter++,'','unilogin:'+ uniName, levelAfd, subject, room, day, position]);
}
}
}
}
mergeSht.getRange(1,1,mergeA.length,mergeA[0].length).setValues(mergeA);
}

Related

I need to split a Google Sheet into multiple tabs (sheets) based on column value

I have searched many possible answers but cannot seem to find one that works. I have a Google Sheet with about 1600 rows that I need to split into about 70 different tabs (with about 20-30 rows in each one) based on the value in the column titled “room”. I have been sorting and then cutting and pasting but for 70+ tabs this is very tedious.
I can use the Query function but I still need to create a new tab, paste the function and update the parameter for that particular tab.
This script seemed pretty close:
ss = SpreadsheetApp.getActiveSpreadsheet();
itemName = 0;
itemDescription = 1;
image = 2;
purchasedBy = 3;
cost = 4;
room = 5;
isSharing = 6;
masterSheetName = "Master";
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Update Purchases')
.addItem('Add All Rows To Sheets', 'addAllRowsToSheets')
.addItem('Add Current Row To Sheet', 'addRowToNewSheet')
.addToUi();
}
function addRowToNewSheet() {
var s = ss.getActiveSheet();
var cell = s.getActiveCell();
var rowId = cell.getRow();
var range = s.getRange(rowId, 1, 1, s.getLastColumn());
var values = range.getValues()[0];
var roomName = values[room];
appendDataToSheet(s, rowId, values, roomName);
}
function addAllRowsToSheets(){
var s = ss.getActiveSheet();
var dataValues = s.getRange(2, 1, s.getLastRow()-1, s.getLastColumn()).getValues();
for(var i = 0; i < dataValues.length; i++){
var values = dataValues[i];
var rowId = 2 + i;
var roomName = values[room];
try{
appendDataToSheet(s, rowId, values, roomName);
}catch(err){};
}
}
function appendDataToSheet(s, rowId, data, roomName){
if(s.getName() != masterSheetName){
throw new Error("Can only add rows from 'Master' sheet - make sure sheet name is 'Master'");
}
var sheetNames = [sheet.getName() for each(sheet in ss.getSheets())];
var roomSheet;
if(sheetNames.indexOf(roomName) > -1){
roomSheet = ss.getSheetByName(roomName);
var rowIdValues = roomSheet.getRange(2, 1, roomSheet.getLastRow()-1, 1).getValues();
for(var i = 0; i < rowIdValues.length; i++){
if(rowIdValues[i] == rowId){
throw new Error( data[itemName] + " from row " + rowId + " already exists in sheet " + roomName + ".");
return;
}
}
}else{
roomSheet = ss.insertSheet(roomName);
var numCols = s.getLastColumn();
roomSheet.getRange(1, 1).setValue("Row Id");
s.getRange(1, 1, 1, numCols).copyValuesToRange(roomSheet, 2, numCols+1, 1, 1);
}
var rowIdArray = [rowId];
var updatedArray = rowIdArray.concat(data);
roomSheet.appendRow(updatedArray);
}
But I always get an unexpected token error on line 51 or 52:
var sheetNames = [sheet.getName() for each(sheet in ss.getSheets())];
(And obviously the column names, etc. are not necessarily correct for my data, I tried changing them to match what I needed. Not sure if that was part of the issue.)
Here is a sample of my data: https://docs.google.com/spreadsheets/d/1kpD88_wEA5YFh5DMMkubsTnFHeNxRQL-njd9Mv-C_lc/edit?usp=sharing
This should return two separate tabs/sheets based on room .
I am obviously not a programmer and do not know Visual Basic or Java or anything. I just know how to google and copy things....amazingly I often get it to work.
Let me know what else you need if you can help.
Try the below code:
'splitSheetIntoTabs' will split your master sheet in to separate sheets of 30 rows each. It will copy only the content not the background colors etc.
'deleteTabsOtherThanMaster' will revert the change done by 'splitSheetIntoTabs'. This function will help to revert the changes done by splitSheetIntoTabs.
function splitSheetIntoTabs() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
var header = rows[0];
var contents = rows.slice(1);
var totalRowsPerSheet = 30; // This value will change no of rows per sheet
//below we are chunking the toltal row we have into 30 rows each
var contentRowsPerSheet = contents.map( function(e,i){
return i%totalRowsPerSheet===0 ? contents.slice(i,i+totalRowsPerSheet) : null;
}).filter(function(e){ return e; });
contentRowsPerSheet.forEach(function(e){
//crate new sheet here
var currSheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet();
//append the header
currSheet.appendRow(header);
//populate the rows
e.forEach(function(val){
currSheet.appendRow(val);
});
});
}
// use this function revert the sheets create by splitSheetIntoTabs()
function deleteTabsOtherThanMaster() {
var sheetNotToDelete ='Master';
var ss = SpreadsheetApp.getActive();
ss.getSheets().forEach(function(sheet){
if(sheet.getSheetName()!== sheetNotToDelete)
{
ss.deleteSheet(sheet);
}
});
}
I was using Kessy's nice script, but started having trouble when the data became very large, where the script timed out. I started looking for ways to reduce the amount of times the script read/wrote to the spreadsheet (rather than read/write one row at a time) and found this post https://stackoverflow.com/a/42633934
Using this principle and changing the loop in the script to have a loop within the loop helped reduce these calls. This means you can also avoid the second call to append rows (the "else"). My script is a little different to the examples, but basically ends something like:
`for (var i = 1; i < theEmails.length; i++) {
//Ignore blank Emails and sheets created
if (theEmails[i][0] !== "" && !completedSheets.includes(theEmails[i][0])) {
//Set the Sheet name = email address. Index the sheets so they appear last.
var currentSheet = theWorkbook.insertSheet(theEmails[i][0],4+i);
//append the header
//To avoid pasting formulas, we have to paste contents
headerFormat.copyTo(currentSheet.getRange(1,1),{contentsOnly:true});
//Now here find all the rows containing the same email address and append them
var theNewRows =[];
var b=0;
for(var j = 1; j < rows.length; j++)
{
if(rows[j][0] == theEmails[i][0]) {
theNewRows[b]=[];//Initial new array
theNewRows[b].push(rows[j][0],rows[j][1],rows[j][2],rows[j][3],rows[j][4],rows[j][5],rows[j][6],rows[j][7]);
b++;
}
}var outrng = currentSheet.getRange(2,1,theNewRows.length,8); //Make the output range the same size as the output array
outrng.setValues(theNewRows);
I found a table of ~1000 rows timed out, but with the new script took 6.5 secs. It might not be very neat, as I only dabble in script, but perhaps it helps.
I have done this script that successfully gets each room and creates a new sheet with the corresponding room name and adding all the rows with the same room.
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
// This var will contain all the values from column C -> Room
var columnRoom = sheet.getRange("C:C").getValues();
// This var will contain all the rows
var rows = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
//Set the first row as the header
var header = rows[0];
//Store the rooms already created
var completedRooms = []
//The last created room
var last = columnRoom[1][0]
for (var i = 1; i < columnRoom.length; i++) {
//Check if the room is already done, if not go in and create the sheet
if(!completedRooms.includes(columnRoom[i][0])) {
//Set the Sheet name = room (except if there is no name, then = No Room)
if (columnRoom[i][0] === "") {
var currentSheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet("No Room");
} else {
var currentSheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet(columnRoom[i][0]);
}
//append the header
currentSheet.appendRow(header);
currentSheet.appendRow(rows[i]);
completedRooms.push(columnRoom[i][0])
last = columnRoom[i][0]
} else if (last == columnRoom[i][0]) {
// If the room's sheet is created append the row to the sheet
var currentSheet = SpreadsheetApp.getActiveSpreadsheet()
currentSheet.appendRow(rows[i]);
}
}
}
Please test it and don't hesitate to comment for improvements.

Script: Transpose, Find and Save

I have some data containing, Dates, Usernames and an average percent that i want to save in a certain way. My problem is that the order of the usernames can change depending on if new ones are added. I therefore need to "find" a specific username and then save the percentage data in the correct column.
I have found some code that partially helps me save the data that i need. But i could use some help in the "find" the corresponding username and save it in a certain Column part.
function save() {
var sss = SpreadsheetApp.getActive();
var ss = sss.getSheetByName('Result');
var range = ss.getRange('B1:B10');
var data = range.getValues();
var tss = SpreadsheetApp.getActive();
var ts = tss.getSheetByName('Archive');
ts.getRange(ts.getLastRow()+1, 1,data[0].length,data.length)
.setValues(Object.keys(data[0]).map ( function (columnNumber) {
return data.map( function (row) {
return row[columnNumber];
});
}));
}
Basically from this:
To a result that looks like this:
Thank you for your assistance.
Alright for anyone out there that may have a similar problem, this is what i ended up with.
function extractAttendance() {
var currentSheet = SpreadsheetApp.getActive();
var attendanceTab = currentSheet.getSheetByName('Data_Filtered');
var userData = attendanceTab.getRange('B1:B').getValues();
var percentageData = attendanceTab.getRange('I1:I').getValues();
var archiveTab = currentSheet.getSheetByName('Archive');
var existingUsersRow = archiveTab.getRange('1:1');
var newRowNumber = archiveTab.getLastRow() + 1;
archiveTab.getRange(newRowNumber, 1).setValue(new Date());
for (var i = 1; i < userData.length; i++) {
var user = userData[i][0];
if (user === '') {
continue;
}
var existingUsers = existingUsersRow.getValues()[0];
var exists = false;
var existingColumnNumber = -1;
for (var j = 0; j < existingUsers.length; j++) {
if (existingUsers[j] === user) {
exists = true;
existingColumnNumber = j + 1;
break;
}
}
if (exists) {
archiveTab.getRange(newRowNumber, existingColumnNumber).setValue(percentageData[i]);
} else {
var newColumnNumber = archiveTab.getLastColumn() + 1;
archiveTab.getRange(1, newColumnNumber).setValue(user);
archiveTab.getRange(newRowNumber, newColumnNumber).setValue(percentageData[i]);
}
}
}
It might be easier to implement your desired functionality through looping rather than through mapping.
The following code retrieves all users ad their percentage data in ‘Result’ and transfers the data (in the format you desire) to "Archive" with the percentages data pasted with the corresponding timestamp into the first empty row.
function save() {
var sss = SpreadsheetApp.getActive();
var ss = sss.getSheetByName('Result');
var range = ss.getRange('B1:B');
var percentageRange = ss.getRange('G1:G');
var userData = range.getValues();
var percentageData = percentageRange.getValues();
var tss = SpreadsheetApp.getActive();
var ts = tss.getSheetByName('Archive');
var userRow=1;
var percentageRow=(ts.getLastRow()+1)
for(var i=0; i<=userData.length; i++)
{
{
var j=(i+2);
ts.getRange(userRow, j).setValue(userData[i])
ts.getRange(percentageRow, 1).setValue(new Date())
ts.getRange(percentageRow, j).setValue(percentageData[i])
}
}
}

using getNotes with blanks inbetween?

I'm trying to use a for loop to change values and to add notes to the ones that I change. since I'm doing it through arrays and not each row individually, my question is, is it possible to get where there isnt a note on the cell to be nothing in the array?
It's through the google scripts system, I've tried looking everywhere but can't find anything on the subject, hoping there's a wizard here.
edit: snippet of script
function CheckHours() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Copy of PNC Roster');
var lastrow = sheet.getLastRow();
var response;
var hoursList = [];
var notesList = [];
var bmidRange = sheet.getRange("L:L").getValues();
var notesRange = sheet.getRange("J:J").getNotes();
for (var i = 0; i < lastrow; i++) {
if (bmidRange[i] > 1) {
//response = UrlFetchApp.fetch('InsertWebsite/?bm=' + bmidRange[i] + '&fr=7');
var seconds = 59378;
var hours = seconds/60/60;
hoursList.push([hours]);
var note = "Activity Check performed: "+ new Date() + "\n\n" + notesRange[i];
notesList.push([note]);
Logger.log(hours);
} else if(bmidRange[i] == "") {
notesList.push('INSERT BATTLEMETRICS ID');
} else {
hoursList.push(bmidRange[i]);
notesList.push(notesRange[i]);
}
}
sheet.getRange("J:J").offset(0, 0, hoursList.length).setNotes(notesList);
sheet.getRange("J:J").offset(0, 0, hoursList.length).setValues(hoursList);
}
What I'm trying to do when I'm pushing the cell values is that they get an appropriate note along with them, but because the variable notesRange is not the same amount as getValues gets, then where there is no notes, instead having a null value in the array basically, is this possible??

Google Sheets Script to Fill Down intermittent blanks in a column

Column C has an ID in it that pertains to several rows, but only the first row has an ID in it.
I need to copy that ID value to the blank cells beneath, until I hit a cell that has another value in it.
I have tried adapting this script but it hits a timeout error.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var last = sheet.getLastRow();//how many times should I do this?
for (i = 5528; i < last; i++) {
var test = sheet.getRange(i, 1,1,1);
//Logger.log(test);
//looks to see if the cell is empty
if (test.isBlank()) {
var rewind = sheet.getRange(i-1, 1, 1, 1).getValues();//gets values from the row above
sheet.getRange(i, 1, 1, 1).setValues(rewind);//sets the current range to the row above
}
}
}
i is set to a big number because every time it times out I have to start over!
I have read that it would be better to bring in the column in an array, work on it, then put it back out to save a lot of time.
I have tried to adapt this but can't get past the variable.
Am I on the right track? I would like to pretty up a solution for the future where I can pass a column or range and do the same thing.
Here is my failing attempt:
function FillDown2() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet2");
var tracts = sheet.getRange("C15:C").getValues();
var allTractList = [];
var title;
for (var row = 0, var len = tracts.length; row < len; row++) {
if (tracts[row][0] != '') {
//response = UrlFetchApp.fetch(tracts[row]);
//doc = Xml.parse(response.getContentText(),true);
title = tracts[row][0];
//newValues.push([title]);
allTractList.push([title]);
Logger.log(title);
} else allTractList.push([title]);
}
//Logger.log('newValues ' + newValues);
Logger.log('allTractList ' + allTractList);
// SET NEW COLUMN VALUES ALL AT ONCE!
sheet.getRange("B15").offset(0, 0, allTractList.length).setValues(allTractList);
return allTractList;
}
Holy Smokes! I did it!
Not sure about why error happened but I had made some changes and got it to work!
Hope this is helpful to others:
function FillDown2() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet2");
var tracts = sheet.getRange("C15:C").getValues();
var allTractList = [];
var title;
var len = tracts.length;
for (var row = 0; row < len; row++) {
if (tracts[row] != '') {
//response = UrlFetchApp.fetch(tracts[row]);
//doc = Xml.parse(response.getContentText(),true);
title = tracts[row];
//newValues.push([title]);
allTractList.push([title]);
Logger.log(title);
} else allTractList.push([title]);
}
//Logger.log('newValues ' + newValues);
Logger.log('allTractList ' + allTractList);
// SET NEW COLUMN VALUES ALL AT ONCE!
sheet.getRange("B15").offset(0, 0, allTractList.length).setValues(allTractList);
return allTractList;
}
Credit to Bryan here:

Google Apps Script: Function to update names from one sheet to another times out. Please refine my loops

I have an app through google docs that I use to record student attendance to my after school tutoring center. I have had higher than usual attendance and my code is not efficient enough to run before timing out. Please assist me in editing my code so that it runs more effectively.
I have to note that I am an absolute beginner, so if this is inappropriately posted, please give me constructive feedback on how to get help with this problem. And I apologize in advance for the (I assume) horrible code you are about to see - it's the best I could do and I worked very hard to create this.
Thank you.
Code:
function updateAttendance(){
var itemSpreadsheetKey = '';
var openedSS = SpreadsheetApp.openById(itemSpreadsheetKey);
var sheetStudentNames = openedSS.getSheetByName("StudentNames");
var sheetDailyData = openedSS.getSheetByName("DailyData");
var app = UiApp.getActiveApplication();
var ss = SpreadsheetApp.openById(itemSpreadsheetKey);
var dailyDataSheet = ss.getSheetByName("DailyData");
var studentNameSheet = ss.getSheetByName("StudentNames");
var dailyData = dailyDataSheet.getDataRange();
var studentNames = studentNameSheet.getDataRange();
var dailyLastRow = dailyData.getLastRow();
var studentNamesLastRow = studentNames.getLastRow();
var studentNamesLastColumn = studentNames.getLastColumn();
var dailyDataNamesArray = sheetDailyData.getRange(2, 1, dailyLastRow).getValues();
for (var i=1; i<=dailyDataNamesArray.length; i++) {
if (i != ""){
var dailyTime = dailyData.getCell(i, 5).getValue();
for (var j=2; j<=studentNamesLastRow; j++) {
var today = dailyData.getCell(1, 8).getValue();
if (dailyData.getCell(i, 1).getValue() == studentNames.getCell(j, 1).getValue()) {
studentNames.getCell(1, studentNamesLastColumn).offset(0, 1).setValue(today);
studentNames.getCell(j, studentNamesLastColumn).offset(0, 1).setValue(dailyTime);
}
}
}
}
return app;
}
If you want your script to go faster you must use array manipulation instead of all these range.setValue() .
Change all the values in a global array (a pair of actually) and when you're done just write these arrays to their respective sheets.
The difference will be enormous ! believe me ;)
All this is pretty well explained in the documentation about best practices.
Here is a "translation" of your code, I'm not sure I didn't make any error in transposition but I have no way to check without knowing what is in your sheets.
Just remember that arrays are 0 indexed while ranges start at 1.
function updateAttendance(){
var itemSpreadsheetKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx';
var openedSS = SpreadsheetApp.openById(itemSpreadsheetKey);
var sheetStudentNames = openedSS.getSheetByName("StudentNames");
var sheetDailyData = openedSS.getSheetByName("DailyData");
var app = UiApp.getActiveApplication();
var ss = SpreadsheetApp.openById(itemSpreadsheetKey);
var dailyDataSheet = ss.getSheetByName("DailyData");
var studentNameSheet = ss.getSheetByName("StudentNames");
var dailyData = dailyDataSheet.getDataRange();
var studentNames = studentNameSheet.getDataRange().getValues();
var dailyLastRow = dailyData.getLastRow();
var studentNamesLastRow = studentNames.getLastRow();
var studentNamesLastColumn = studentNames.getLastColumn();
var dailyDataNamesArray = sheetDailyData.getDataRange().getValues();
for (var i = 1 ; i < dailyDataNamesArray.length; i++) {
if (i != ""){
var dailyTime = dailyDataNamesArray[i][4];
for (var j=1; j<studentNamesLastRow; j++) {
var today = dailyDataNamesArray[0][7];
if (dailyDataNamesArray[i][0] == studentNames[i][0]) {
studentNames[0][studentNamesLastColumn+1] = today;
studentNames[j][studentNamesLastColumn+1] = dailyTime;
}
}
}
}
studentNameSheet.getRange(1,1,studentNames.length,studentNames[0].length).setValues(studentNames):
dailyDataSheet.getRange(1,1,dailyDataNamesArray.length,dailyDataNamesArray[0].length).setValues(dailyDataNamesArray):
return app;
}
Replace the code after the var dailyDataNamesArray line with the following. It's a bit of a guess, so I hope for you that it works:
var todayCell1 = studentNames.getCell(1, studentNamesLastColumn).offset(0, 1);
for (var i=1; i<=dailyDataNamesArray.length; i++) {
if (i != ""){
var dailyTime = dailyData.getCell(i, 5).getValue();
var dailyVar2 = dailyData.getCell(i, 1).getValue();
for (var j=2; j<=studentNamesLastRow; j++) {
var today = dailyData.getCell(1, 8).getValue();
if ( dailyVar2 == studentNames.getCell(j, 1).getValue()) {
todayCell1.setValue(today);
studentNames.getCell(j, studentNamesLastColumn).offset(0, 1).setValue(dailyTime);
}
}
}
}