Google Scripts For Loop - loops

I'm trying to insert some data from a spreadsheet into a different spreadsheet, the problem is that the loop is not behaving as expected, it only gives me one entry in the target spreadsheet. I've tried using while and no function but it didn't work.
Here is the code:
function move(){
var homeBook = SpreadsheetApp.getActiveSpreadsheet();
var sheet = homeBook.getSheets()[0];
var limit = sheet.getLastRow(); //number of rows in the sheet
var evento = sheet.getRange(2, 1, limit-1).getValues(); //event list
var descript = sheet.getRange(2,2,limit-1).getValues(); //description list
var tags = sheet.getRange(2,3,limit-1).getValues(); //tag list
var sheetsIDHome = sheet.getRange(2,4,limit-1).getValues(); //ID list
var targetBook = SpreadsheetApp.openById("1t3qMTu2opYffLmFfTuIbV6BrwsDe9iLHZJ_ZT89kHr8"); //target workbook
var target = targetBook.getSheets()[0]; //Sheet1
var targetLimit =target.getLastRow(); //Rows with content
var sheetsIDTarget = target.getRange(targetLimit, 4); // ID list
var targetRow = targetLimit+1; //row where content is going to be inserted
for(i = 2;i <= limit;i++){//loop for each value to be inserted in each row of the target sheet
(function(x){
target.getRange(targetRow,1).setValue(x);
target.getRange(targetRow,2).setValue(descript[2]);
target.getRange(targetRow,3).setValue(tags[3]);
target.getRange(targetRow,4).setValue(sheetsIDHome[4]);
targetRow = targetRow++;
})(i);
};

You're trying to access the four arrays created from the values for columns 1-4.
Your for statement needs to match their structure, starting with the first array instance of 0. You can use any of the arrays for the iteration, I've chosen the first.
In addition, I've removed the function and replaced x with the instance from evento.
++ increments the value of the variable, no need for assignment there.
for (var i = 0; i < evento.length; i++) {
target.getRange(targetRow,1).setValue(evento[i]);
target.getRange(targetRow,2).setValue(descript[i]);
target.getRange(targetRow,3).setValue(tags[i]);
target.getRange(targetRow,4).setValue(sheetsIDHome[i]);
targetRow++;
}

there is a code that has been mis-placed, kindly check my code below:
function UpdateBSRSpecial()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var testForm = ss.getSheetByName("ENTRY FORM");
var testTable = ss.getSheetByName("BSR DATA");
var testFormValue = testForm.getRange("G6").getValue();
var rangeData = testTable.getDataRange();
var lastColumn = rangeData.getLastColumn();
var lastRow = rangeData.getLastRow();
for(var i=2;i<=lastRow;i++){
var dataID = testTable.getRange(i,1).getValue();
if(testFormValue == dataID)
{
testTable.getRange(i,6).setValue("new value");
};
};
};
hope this helps

Related

How can I improve speed of for loops in Google Sheets app script?

I know I must use array to improve speed when use for loop but I don't understand how to do that? How can I rewrite this code?
function hiliptk() {
//var I_INDEX = 1;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getDataRange();
var dataValues = dataRange.getValues();
for (var i=3; i<=98; i++) {
var row = sheet.getRange(i, 1, 1,9);
if (sheet.getRange(i,2).getValue()== "PTK") {
row.setBackground("yellow");
} else {row.setBackground("white");}
}
}
This part of your code var dataValues = dataRange.getValues(); will return a 2 dimensional array containing the data in your sheets. You can use the 3rd element of each sub-array to check whether it is "PTK" or not.
Example:
function hiliptk() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getDataRange();
var dataValues = dataRange.getValues();
var rangeListYellowBG = [];
var rangelistWhiteBG = [];
//this loop collects the range by the value of column C
for (var i=2; i<dataValues.length; i++){
if(dataValues[i][2] == 'PTK'){
//push to array rangeListYellowBG if column C is 'PTK'
rangeListYellowBG.push("A"+parseInt(i+1)+":I"+parseInt(i+1));
}else{
//else push to rangelistWhiteBG
rangelistWhiteBG.push("A"+parseInt(i+1)+":I"+parseInt(i+1));
}
}
//this will change the background color of the following range to yellow [A5:I5, A8:I8, A11:I11, A12:I12]
sheet.getRangeList(rangeListYellowBG).setBackground("yellow");
//this will change the background color of the following range to white [A3:I3, A4:I4, A6:I6, A7:I7, A9:I9, A10:I10, A13:I13]
sheet.getRangeList(rangelistWhiteBG).setBackground("white");
}
Sample Data:
Output:
References:
array.push()
getRangeList()

Compare rows in Two Google Sheets, Once a match found Change Font Color

I am trying to create two sheets: Sheet 1: a template into which a student will enter a translation of a word into a cell; Sheet 2: a key which checks it against all possible answers: The two sheets look like this:
Here is a Link To Show the Two Spreadsheets
I am trying to take the provided answer for each column in the template (A:1), and match it against all possible answers listed in the corresponding column in the key (if it matches anything between A:1:A:3 in the key). If there's a match, the font should change to green and it should move to the next column. If there's no match the font turns red before moving to the next column.
I've run the logger, and it seems like it iterates through the data from each sheet correctly. The problem seems to be in comparing the 2 columns.
var ui = SpreadsheetApp.getUi();
var ssA= SpreadsheetApp.getActiveSpreadsheet();
var worksheet = ssA.getSheetByName("Worksheet");
var rangeData = worksheet.getDataRange();
var lastColumn = rangeData.getLastColumn();
var lastRow = rangeData.getLastRow();
var searchRange = worksheet.getRange(2, 2, lastRow-1, lastColumn-1);
var ssB = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1jKuxXo6o5YJjSUrQmaHR0n1ydvw7PgUl29I9mtycF_g/edit#gid=0");
var worksheetB = ssB.getSheetByName("Key");
var rangeDataB = worksheetB.getDataRange();
var lastColumnB = rangeDataB.getLastColumn();
var lastRowB = rangeDataB.getLastRow();
var searchRangeB = worksheetB. getRange(2, 2, lastRowB -1, lastColumnB -1);
function onOpen(){
ui.createMenu("Check My Translation.")
.addItem("Check Set 1", "transcheck")
.addToUi()
function transcheck(){
//iterate through the two corresponding columns in template and reference sheet
for (i = 1; i < lastColumn; i++){
for (j = 1; j < lastRow; j++){
//create the ranges to be compared and store as vars. cell and cellB
var cell = searchRange.getCell(j,i).getValue();
var cellB = searchRangeB.getCell(j,i).getValue();
//check for matches, change font accordingly
if (cell[0] === cellB[0]){
worksheet.getRange(j+1,i+1).setFontColor("green");
}else if(cell[0] =! cellB[0]){
worksheet.getRange(j+1,i+1).setFontColor("red");
I don't get any error messages; it just doesn't match the cells/change colors correctly.
There are several } missing at the end of your code and the correct operator is != instead of =!. Also, as a user mentioned, getValue() function retrieves a single value and not an array as getValues() [1], which is the recommended function to use in this case to avoid hitting the Google quotas [2]:
function onOpen(){
var ui = SpreadsheetApp.getUi();
ui.createMenu("Check My Translation.")
.addItem("Check Set 1", "transcheck")
.addToUi()
}
function transcheck(){
var ssA= SpreadsheetApp.getActiveSpreadsheet();
var worksheet = ssA.getSheetByName("Worksheet");
var rangeData = worksheet.getDataRange();
var lastColumn = rangeData.getLastColumn();
var lastRow = rangeData.getLastRow();
var searchRange = worksheet.getRange(2, 2, lastRow-1, lastColumn-1).getValues();
var worksheetB = ssA.getSheetByName("Key");
var rangeDataB = worksheetB.getDataRange();
var lastColumnB = rangeDataB.getLastColumn();
var lastRowB = rangeDataB.getLastRow();
var searchRangeB = worksheetB. getRange(2, 2, lastRowB -1, lastColumnB -1).getValues();
//iterate through the two corresponding columns in template and reference sheet
for (var i = 0; i < searchRange.length; i++){
for (var j = 0; j < searchRange[0].length; j++){
//create the ranges to be compared and store as vars. cell and cellB
var cell = searchRange[i][j];
var k = 0;
while(k<3) {
var cellB = searchRangeB[k][j];
//check for matches, change font accordingly
if (cell == cellB){
worksheet.getRange(i+2,j+2).setFontColor("green");
break;
}else if(cell != cellB){
worksheet.getRange(i+2,j+2).setFontColor("red");
}
k++
}
}
}
}
[1] https://developers.google.com/apps-script/reference/spreadsheet/range#getValues()
[2] https://developers.google.com/apps-script/guides/services/quotas

Multiple Issues with Google Sheets Scripts (JavaScript)

NEEDLES TO SAY, I am very new to this, but trying my hardest to figure all this out. I have a script right now which actively removes all empty rows from an entire workbook. But I'm hoping someone can assist is narrowing this down to a single sheet within that workbook.
function removeEmptyRows() {
SpreadsheetApp.getActive()
.getSheets()
.forEach(function (s) {
c = 0;
s.getRange(1, 1, s.getMaxRows(), s.getMaxColumns())
.getValues()
.forEach(function (r, j) {
if (r.toString()
.replace(/,/g, "")
.length == 0) {
s.deleteRow((j += 1) - c)
c += 1;
}
})
})
}
Ideally I would like for this to remove only blank rows on one sheet within my workbook called 'Racing Results'. The reason I'm need this, is due to how the spreadsheet is setup and having multiple rows merged together. So when I copy these results over to a different sheet, there are gaps between them and I'd like them removed. Here is the script I'm using to copy the data to another sheet.
function Copy() {
var sss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ss = sss.getSheetByName('Score Card');
var range = ss.getRange('A32:E36');
var data = range.getValues();
var tss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ts = tss.getSheetByName('Race Results');
ts.getRange(ts.getLastRow()+1, 1, data.length, data[0].length).setValues(data);
}
If not to throw one final monkey wrench into this colossal mess, I have been attempting to copy two different cell ranges within the same script and I feel like this isn't possible because only the latter one gets copied and the initial one is discarded. Here is the other copy script I am using which runs before the one above this.
function Copy() {
var sss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ss = sss.getSheetByName('Score Card');
var range = ss.getRange('A1:A1');
var data = range.getValues();
var tss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ts = tss.getSheetByName('Race Results');
ts.getRange(ts.getLastRow()+1, 1, data.length, data[0].length).setValues(data);
}
Score Card Screenshot
In a perfect world, what I'm trying to get setup is the following. Above is a screenshot of the scorecard we are using. I am wanting to copy the Current Date (A1) to the 'Racing Results' sheet, then I want to copy the final score with the team names (A32:E36) and move them to the 'Racing Results' sheet right under it. Once that has been done, I want to remove the empty rows between the results because as of right now this is how it looks when copying over. (see image below)
Race Results Screenshot
Thanks in advance to anyone who is able to assist with any of this in any way shape or form.
Edit:
Removing Empty Rows from a spreadsheet is functioning as intended. Still having issues with Copying multiple times in the same action even when giving them different names. Here is my updated script.
function CopyDate() {
var sss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ss = sss.getSheetByName('Score Card');
var range = ss.getRange('A1:A1');//This range is only one cell
var data = range.getValues();
var tss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ts = tss.getSheetByName('Race Results');
ts.getRange(ts.getLastRow()+1, 1, data.length, data[0].length).setValues(data);
}
function CopyScore() {
var sss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ss = sss.getSheetByName('Score Card');
var range = ss.getRange('A32:E36');
var data = range.getValues();
var tss = SpreadsheetApp.openById('18cl69Id4saI455wk__-PhvfxXZa7iWlQpoiRKqBz6bU');
var ts = tss.getSheetByName('Race Results');
ts.getRange(ts.getLastRow()+1, 1, data.length, data[0].length).setValues(data);
}
function delBlankRows(shtname){
var shtname=shtname || 'Race Results';
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName(shtname);
var rg=sh.getRange(1,1,sh.getMaxRows(),sh.getLastColumn());
var vA=rg.getValues();
var n=0;
for(var i=0;i<vA.length;i++){
if(!vA[i].join("")){
sh.deleteRow(i-n+1);
n++;
}
}
}
function Sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
function SaveRaceResults() {
CopyDate();
Sleep(5000);
CopyScore();
Sleep(5000);
delBlankRows();
}
Deleting All Blank Rows on a Sheet
function delBlankRows(shtname){
var shtname=shtname || 'Sheet1';
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName(shtname);
var rg=sh.getRange(1,1,sh.getMaxRows(),sh.getLastColumn());
var vA=rg.getValues();
var n=0;
for(var i=0;i<vA.length;i++){
if(!vA[i].join("")){
sh.deleteRow(i-n+1);
n++;
}
}
}
Copy function:
function Copy() {
var sss = SpreadsheetApp.getActive();
var ss1 = sss.getSheetByName('Score Card');
var range1 = ss1.getRange('A1');//This range is only one cell
var data1 = range1.getValues();
var ts1 = sss.getSheetByName('Race Results');
ts1.getRange(ts1.getLastRow()+1, 1, data1.length, data1[0].length).setValues(data1);
var ss2 = sss.getSheetByName('Score Card');
var range2 = ss2.getRange('A32:E36');
var data2 = range2.getValues();
var ts2 = sss.getSheetByName('Race Results');
ts2.getRange(ts2.getLastRow()+1, 1, data2.length, data2[0].length).setValues(data2);
}

Cannot convert class to object in spreadsheet

I wish to get a couple of properties of all the folders in my GDrive and write these properties to a spreadsheet. Because of the large number of folders (over 300) I have decided to use Paging and Batch processing. This seems to be working but I can't seem to write the Array[][] I've created in the batch processing to the spreadsheet.
I'm am getting the following error when I try to set the values in my spreadsheet:
Cannot convert (class)#3cc8188e to Object[][].
I did not find any listed questions that were similar to my problem.
The last line of the script is highlighted when the error appears. Code is:
function myFunction() {
var folder = DocsList.getFolder('MyFolder');
var subfolders = null;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = sheet.getRange('a1');
var x = 0;
var pageSize = 250;
var token = null;
var xfolders = new Array(500);
do {
var resultset = folder.getFoldersForPaging(pageSize, token);
subfolders = resultset.getFolders();
token = resultset.getToken();
x = subfolders.length;
for (var a = 0; a < subfolders.length; a++) {
var contents = subfolders[a].getFiles();
xfolders[a] = new Array(6);
if(contents.length>0) {
xfolders[a][0] = subfolders[a].getName();
xfolders[a][1] = subfolders[a].getDateCreated();
xfolders[a][2] = subfolders[a].getLastUpdated();
xfolders[a][3] = contents.length;
xfolders[a][4] = subfolders[a].getSize();
xfolders[a][5] = a;
}
}
} while (subfolders.length > pageSize)
sheet.getRange(1, 1, x, 6).setValues(xfolders);
}
You've started with an array xfolders for which you've initialized a length. There's no need to do this - it's enough to know that it's an array. Later you call getRange() with rows==x, where x = subfolders.length... and if that isn't 500 (the length of xfolders) you will end up with your error. (...because you have undefined array elements.)
What you need to do is make sure that the range you're writing to has the same dimensions as the values you're presenting. One way to do that is to calculate the range dimensions using xfolders itself.
Here's your function, refactored to grow xfolders dynamically, and then to use its dimensions for output to the spreadsheet.
function myFunction() {
var folder = DocsList.getFolder('MyFolder');
var subfolders = null;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = sheet.getRange('a1');
var pageSize = 250;
var token = null;
var xfolders = [];
do {
var resultset = folder.getFoldersForPaging(pageSize, token);
subfolders = resultset.getFolders();
token = resultset.getToken();
for (var a in subfolders) {
var contents = subfolders[a].getFiles();
xfolders[a] = [];
if(contents.length>0) {
xfolders[a][0] = subfolders[a].getName();
xfolders[a][1] = subfolders[a].getDateCreated();
xfolders[a][2] = subfolders[a].getLastUpdated();
xfolders[a][3] = contents.length;
xfolders[a][4] = subfolders[a].getSize();
xfolders[a][5] = a;
}
}
} while (subfolders.length == pageSize) // Quit when we aren't getting enough folders
sheet.getRange(1, 1, xfolders.length, xfolders[0].length).setValues(xfolders);
}

How to loop range of cells and set value in adjacent column

I'm learning Google Apps Scripts for use with Google Spreadsheets.
I have a list of URLs in one column and I want to write a script to get the title element from each URL and write it in the adjacent cell. I have accomplished this for one specific cell as per the following script:
function getTitles() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("url_list");
var range = sheet.getRange("G3");
var url = range.getValue();
var response = UrlFetchApp.fetch(url);
var doc = Xml.parse(response.getContentText(),true);
var title = doc.html.head.title.getText();
var output = sheet.getRange("H3").setValue(title);
Logger.log(title);
return title;
}
This gets the URL in G3, parses it, pulls the element and writes the output in H3.
Now that I have this basic building block I want to loop the entire G column and write the output to the adjacent cell but I'm stuck. Can anyone point me in the right direction?
May look something like this:
function getTitles() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("url_list");
var urls = sheet.getRange("G3:G").getValues();
var titleList = [], newValues = [],
response, doc, title;
for (var row = 0, var len = urls.length; row < len; row++) {
if (urls[row] != '') {
response = UrlFetchApp.fetch(urls[row]);
doc = Xml.parse(response.getContentText(),true);
title = doc.html.head.title.getText();
newValues.push([title]);
titleList.push(title);
Logger.log(title);
} else newValues.push([]);
}
Logger.log('newValues ' + newValues);
Logger.log('titleList ' + titleList);
// SET NEW COLUMN VALUES ALL AT ONCE!
sheet.getRange("H3").offset(0, 0, newValues.length).setValues(newValues);
return titleList;
}

Resources