Dynamic namedRange, Trying to print only cells with data in them - javascript

function readNamedRange() {
var app = SpreadsheetApp;
var activeSheet = app.getActiveSpreadsheet().getActiveSheet();
var listDown = activeSheet.getRange("listDown");
var result = activeSheet.getRange("listDown").getValues();
}
In the above code, my active sheet contains a namedRange which has the entire B column set to the namedRange called listDown. Cells B1 to B10 have data 1 through 10 in them.
I am trying to print only data cells with values in them using both for loop and an if statement inside it.
I have tried the following logic given below:
for(var i=0; i <result.length; i++){
if(result.length[i] != "" && result.length[i] != undefined ){
console.log(result);
}else{
console.log("namedRange is empty");
}
}
My above logic is not complete and I am unable to understand how to do it.

I believe your goal as follows.
You want to show the values of cells except for the empty cells at the log.
For this, how about this modification?
Modification points:
listDown is not used in your script.
The value retrieved by getValues() is 2 dimensional array. And your range is one column.
In this case, each value can be retrieved by result[i][0].
In your script, result.length[i] always becomes undefined.
At console.log(result), all values of result is shown.
In your case, result[i][0] != "" can be used for the if statement.
When above points are reflected to your script, it becomes as follows.
Modified script:
function readNamedRange() {
var activeSheet = SpreadsheetApp.getActiveSheet();
var result = activeSheet.getRange("listDown").getValues();
for (var i = 0; i < result.length; i++) {
if (result[i][0] != "") { // Modified
console.log(result[i][0]); // Modified
} else {
console.log("namedRange is empty");
}
}
}
References:
getValues()
Array
Added:
You want to show the values of only cells except for the empty cells.
For this, how about the following modified script?
The script in else was removed.
In order to reduce the process cost, var end = activeSheet.getLastRow() is used for the for loop.
Modified script:
function readNamedRange() {
var activeSheet = SpreadsheetApp.getActiveSheet();
var result = activeSheet.getRange("listDown").getValues();
var end = activeSheet.getLastRow();
for (var i = 0; i < end; i++) {
if (result[i][0] != "") {
console.log(result[i][0]);
}
}
}

Related

Google Apps Scripts - Add specific value to each row being processed in a loop

so I want to write a function that takes leads from a source sheet, and then, sends them to another sheet (the destsheet) if they haven't been sent yet. The difference between a lead that has been sent and a lead that hasn't been is that a lead sent should have "yes" in column K (column 10)
I have managed to get the first part working (sending leads from a sheet to another) but for some reason, I can't get the script to add "yes" when a lead is sent to the other sheet. As you can see below, I've tried adding "values[i][tstCol] = "yes";" in several different spots, but it's not working.
Any ideas of what I'm doing wrong? Thanks!
function newLeads() {
var sourceSheet = SpreadsheetApp.openById('ID').getSheetByName('SHEETNAME');
var destSheet = SpreadsheetApp.openById('ID').getSheetByName('SHEETNAME');
var values = sourceSheet.getDataRange().getDisplayValues();
var finalValues=[];
var columns = String("0,1,2,3,4,5,6,7,8").split(','); //only want these columns
var tstCol = 10;
for (var i=0;i<values.length;i++) {
var newValues=[];
//values[i][tstCol] = "yes";
if (values[i][tstCol] != "yes") {
//values[i][tstCol] = "yes";
for (var j=0;j<columns.length;j++) {
//values[i][tstCol] = "yes";
newValues.push(values[i][columns[j]]);
}
finalValues.push(newValues);
}
}
destSheet.getRange(destSheet.getLastRow() + 1, 1, finalValues.length, finalValues[0].length).setValues(finalValues);
}
Take a look at this.
function newLeads() {
try {
var sourceSheet = SpreadsheetApp.openById('ID').getSheetByName('SHEETNAME');
var destSheet = SpreadsheetApp.openById('ID').getSheetByName('SHEETNAME');
var values = sourceSheet.getDataRange().getDisplayValues();
var finalValues=[];
var columns = String("0,1,2,3,4,5,6,7,8").split(','); //only want these columns
var tstCol = 10;
for (var i=0;i<values.length;i++) {
var newValues=[];
if (values[i][tstCol] != "yes") {
values[i][tstCol] = "yes"; // is this where you want to set to yes
for (var j=0;j<columns.length;j++) {
newValues.push(values[i][columns[j]]);
}
finalValues.push(newValues);
}
values[i] = [values[i][tstCol]]; // this would extract column tstCol
}
destSheet.getRange(destSheet.getLastRow() + 1, 1, finalValues.length, finalValues[0].length).setValues(finalValues);
sourceSheet.getRange(1,tstCol+1,values.length,1).setValues(values);
}
catch(err) {
console.log(err);
}
}
Explanation:
The try block is used to see if an error occurs during the block between try and catch; if an error occurs, the catch(err) block is executed and the error is being displayed.
The values array is an array of rows [[1,2,3,4],[5,6,7,8],...] which I converted it to an array [[1],[2],[3]...] of a single column of the spreadsheet type in order to use the setValues(values) method.
Reference link:
Apps Script setValues().

Google Script - Conditionally append rows from sheet to sheet

I'm trying to append rows from one sheet to another sheet based on two conditions. I'm fairly new to google script and coding in general.
You can find a copy of the worksheet here.
I want to extract all rows with a weeknum (column I of MASTER sheet) that matches the previous weeknum (found on the B2 cell of the DASHBOARD sheet) and that also have "Not Coming" (column K of MASTER SHEET).
The goal is to create a call list (on the Call List Cancelled W-1) every week with people that did not honor their appointments the week before. Ideally the rows would be appended on the top of the call list sheet.
I've managed to build this code as for now. But it does not work.
// Creating Call List from cancelled appointments in W-1
var ss = SpreadsheetApp.getActiveSpreadsheet();
//CALL LIST
var sheetCallList = ss.getSheetByName("Call List Cancelled W-1");
var rangeCallList = sheetCallList.getDataRange();
//MASTER
var sheetMaster = ss.getSheets()[0];
var dataRangeMaster = sheetMaster.getDataRange();
var valuesMaster = dataRangeMaster.getValues();
var lastRowMaster = sheetMaster.getLastRow();
var cameOrNot = sheetMaster.getRange("K:K").getValues();
var weekNumColumn = sheetMaster.getRange("I:I").getValues()
//DASHBOARD
var sheetDashboard = ss.getSheets()[1];
var weeknum = sheetDashboard.getRange(2, 2).getValue();
var lastweeknum = weeknum - 1
function appendRowsToCallList() {
for (var i = 2; i < lastRowMaster; i++); {
if ( lastweeknum == weekNumColumn && cameOrNot == "Not Coming") {
sheetCallList.rangeCallList.appendRow(valuesMaster);
}
}
}
Solution:
There is a typo in your for loop:
for (var i = 2; i < lastRowMaster; i++);
Since there's an extra semicolon, this would loop but execute nothing.
Also, to append rows, you need to refer to individual arrays in valuesMaster and check individual values in the other arrays. Also indexes start with 0 so to check from the second value you start the index with 1.
Function code:
function appendRowsToCallList() {
for (var i = 1; i < lastRowMaster; i++) {
if ( lastweeknum == weekNumColumn[i][0] && cameOrNot[i][0] == "Not Coming") {
sheetCallList.appendRow(valuesMaster[i]);
}
}
}
Output:

javascript if function not working properly for index match (apps script)

I'm trying to check whether there are duplicate phone numbers in a column and to then return the first id number associated with the phone match in google apps script.
I created an if statement, according to every reference I've checked I've coded it right. The script runs but nothing populates??
I defined the ranges for the count that has the phone number and id number associated with it. I ensured its in the correct array my using map and used a basic if else statement.
Everything seems to run but the statement doesn't throw out the id numbers. In fact nothing happens.
Please help...
function myFunction() {
var sss = SpreadsheetApp.openById('spreadsheetid'); // sss = source spreadsheet
var ss = sss.getSheetByName('spreadsheetname'); // ss = source sheet
var lr = ss.getLastRow();
for (var i=3;i<lr;i++) {
var phone = ss.getRange(i,4,lr).getValues();
var id = ss.getRange(i,1,lr).getValues();
var phonearray = phone.map(function(r){return r[0]});
if(phonearray == phone[i]){
//emailarray.indexOf(email[i]) &&
ss.getRange(i,30,lr).setValue(id[i]);
} else
ss.getRange(i,30,lr).setValue("");
}
}
There are some things you need to consider
A valuerange is a 2-dimensional array, thus to access the value of an individual cell you need to define phone[i][0] instead of phone[i]
The method getRange requires the syntax getRange(startRow, startColumn, numRows) rather than getRange(startRow, startColumn, lastRow). Keep this in mind when you retrieve your range of interest.
Searching for duplicates will require in your case two (nested) for loops.
Please find below a sample of how you can modify your code to achieve the desired functionality:
function myFunction() {
var sss = SpreadsheetApp.openById('spreadsheetid'); // sss = source spreadsheet
var ss = sss.getSheetByName('spreadsheetname'); // ss = source sheet
var lr = ss.getLastRow();
var phones = ss.getRange(3,4,lr-3+1).getValues();
var ids = ss.getRange(3,1,lr-3+1).getValues();
var phonearray = phones.map(function(r){return r[0]});
for (var i=0;i<=(lr-3);i++) {
var val = phones[i][0];
var duplicates = [];
for(var j = 0; j < phonearray.length; j++){
if (phonearray[j] == val){
duplicates.push(j);
}
}
if(duplicates.length>1){
Logger.log("duplicate");
//emailarray.indexOf(email[i]) &&
ss.getRange((i+3),30).setValue(ids[i]);
} else{
Logger.log("no duplicate");
ss.getRange((i+3),30).setValue("");
}
}
}

How do I make less calls to sheet.getRange and reduce the execution time in a double loop

I want to reduce the calls to sheet.getRange in the following function, because the execution times out.
I've tried re-arranging the loops and parsing the data as a double array, however the size of my spreadsheet changes every day and I need to be able to reference the columns by name only.
function runDuplicateRemover() {
var sheet= SpreadsheetApp.getActive().getSheetByName('Sheet 1');
var rangeData = sheet.getDataRange();
var lastRow = rangeData.getLastRow();
var Cdata = sheet.getDataRange().getValues();
// here I am accessing the column which is used to find duplicates
var colCRM = Cdata[0].indexOf("CRM ID")+1;
var arrayOfDuplicates = [];
for(i=1; i<lastRow; i++){
var cellToCompare = sheet.getRange(i+1,colCRM);
// I am just changing all the colors to see the execution
cellToCompare.setBackground("#88b4fc");
var crmToCompare =cellToCompare.getValue();
//checks to see that this value is not already contained in the rows to delete
if (!cellToCompare.isBlank() && (arrayOfDuplicates.indexOf(i)+1)==0 ){
arrayOfDuplicates.push(i);
cellToCompare.setBackground("#f9d9f9");
for (j = i+1; j<lastRow; j++) {
var cellCurrent = sheet.getRange(j+1,colCRM);
cellCurrent.setBackground("#f2fc88");
var crmCurrent = cellCurrent.getValue();
if (crmToCompare == crmCurrent) {
arrayOfDuplicates.push(j);
cellCurrent.setBackground("#fc92f1");
}
}
//pops last value since that's the only one I want to keep
sheet.getRange(arrayOfDuplicates.pop()+1,colCRM).setBackground("#dbf7d4");
}
}
for (t = arrayOfDuplicates.length-1; t>=0; t--) {
sheet.deleteRow(arrayOfDuplicates[t]+1);
}
}
I'd like to reduce the calls to the sheet.getRange, however I don't know how to delete the rows and then return the data back to the sheet without messing all the column order up.

Data copying with Google Apps Script

I am trying to write a script in Google Apps Script that takes cell information from one sheet and copies it to another sheet, both for just grabbing certain columns to display on the second sheet and also a condition based on the values inside cells in a certain column. Here is what I have so far:
function onMyEdit() {
var myMaster = SpreadsheetApp.openById("xxxxx");
var masterSheet = myMaster.setActiveSheet(myMaster.getSheets()[0]);
var myNames = SpreadsheetApp.openById("xxxxx");
var namesSheet = myNames.setActiveSheet(myNames.getSheets()[0]);
var row1 = masterSheet.getRange(1, 1, masterSheet.getLastRow(), 1);
var rowV = row1.getValues();
var firstArray = masterSheet.getDataRange().getValues();
var dataList = [];
for (var i = 1; i < rowV.length; i++) {
dataList.push(firstArray[i][0]);
dataList.push(firstArray[i][1]);
dataList.push(firstArray[i][2]);
dataList.push(firstArray[i][3]);
}
for (var j = 0; j < rowV.length - 1; j++) {
namesSheet.getRange(2, j + 1, 1, 1).setValue(dataList[j]);
}
}
So as of now it only works on one row, starting from the second row (to allow for column headers). And I suppose when I want to grab rows conditionally based on cell data, I will use an 'if' statement for the condition inside the 'for' loop, but I want the data to copy to the next available row in both sheets. I suppose I'd use something like:
' getLastRow + 1 '
or something like that. I need this code to be as efficient as possible because of the amount of data and its purpose. I am pretty new to programming so please explain in detail, and thanks again.
I'm not sure I understood exactly what you wanted to do but -from what I understood- this code snippet should give you a better way to start with...
(I added a few comments to explain in the code itself)
function onMyEdit() {
var myMaster = SpreadsheetApp.openById("MasterSheet ID");
var masterSheet = myMaster.getSheets()[0]; // get 1rst sheet
var myNames = SpreadsheetApp.openById("NamesSheet ID");
var namesSheet = myNames.getSheets()[0]; // get 1rst sheet
var firstArray = masterSheet.getDataRange().getValues();
var dataList = [];
for ( r = 1; r < firstArray.length; r++) { // iterate the first col of masterSheet
if(firstArray[r][0]=='some condition'){ // if value in the first column == 'some condition get the second column cell in the new array (here you could change what you want to get)
dataList.push([firstArray[r][1]])
}
}
Logger.log(dataList)
if(dataList.length>0){
namesSheet.getRange(1,namesSheet.getLastColumn()+1,dataList.length,1).setValues(dataList);//copy data in a column after last col
}
}

Categories

Resources