I have a Google Form attached to a spreadsheet. Everytime the data is submitted via the form into the spreadsheet. Then the spreadsheet should automatically send an email to several individuals but, it's not working.
Here is my code:
function myFunction(row) {
var sheets = SpreadsheetApp.getActiveSpreadsheet();
var sheet = sheets.getSheets()[0]; // Form Responses 1
var columnName = sheet.getRange("A1:S1").getValues();
var dataRange = sheet.getRange(row);
var data = dataRange.getValues();
var responseObj = {};
var carId = "";
for (var i = 2; i < columnName[0].length; i++) {
var key = columnName[0][i];
var value = dateFormat(data[0][i],key);
responseObj[key] = value;
if(key === "Car ID"){
carId = value;
}
}
var htmlBodyLoc = doGet(responseObj);
MailApp.sendEmail({
to: 'person.one#gmail.com,person.two#gmail.com,person.three#gmail.com',
subject:'Car Inspection - ' + outletId + ' ' + new Date(),
htmlBody: htmlBodyLoc,
});
}
I am actually getting an error on this line: var dataRange = sheet.getRange(row);
Thanks.
You have 4 ways to call sheet.getRange()
getRange(row, column)
It is for single cells ranges.
If you are from VBA, this is the most approximate to worksheet.Cells
getRange(row, column, numRows)
This way you can make a range of singles columns and multiple rows, useful sometimes
getRange(row, column, numRows, numColumns)
This is the way to go, programmatically.
E.g sheet.getRange(1,1,2,2) will get you the range A1:B2
And finally there is getRange(a1notation) which you can use like sheet.getRange("A1:B2")
If you are trying to get a single cell of data, maybe you can just change
var dataRange = sheet.getRange(row);
To
var dataRange = sheet.getRange(row, yourFixedColumn);
yourFixedColumn being an Integral with index 1 for the column E.g column A = 1
Otherwise you must change the passed argument row to something that complies with the methods listed above.
Related
I am having problems with a script that I wrote. It isn't throwing any errors however I am not receiving the emails. The goal of this script is to send an email if column G has value Y.
Column A = Organization Name
Column C= Days Aging
Column F= Email (where the email should be sent)
Column G= Status (where the Y will be)
function CheckPastDueAccounting() {
//Fetch Accounting Spreadsheet with past due accounts
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var lrow= ss.getLastRow();
for(var i=2;i<=lrow;i++);
var Status =ss.getRange(i,7);
var value = Status.getValue();
if (value == 'Y') {
var DaysAgingColumn = ss.getRange(i,3);
var DaysAging = DaysAgingColumn.getValue();
// Fetch Organization Name
var Organizations = ss.getRange(i,1);
var org = Organizations.getValue();
// Fetch the email address
var emailRange = ss.getRange(i,6);
var emailAddress = emailRange.getValue();
// Send Alert Email.
var message = 'Hi. Your account is past due ' + DaysAging + ' days.'; // Second column
var subject = 'Past Due Accounting Alert: ' + org;
GmailApp.sendEmail(emailAddress, subject, message);
}
}
Issue:
You should be enclosing the statements you want to run in loop between { }. Otherwise, the for loop is just incrementing the variable i and not running any of your desired code.
Moreover, after the for loop ends, the variable i is higher than the last row with content (lrow) which means that all calls to .getRange(i, columnIndex) refer to empty cells. Because of this, no email is sent, and no error is shown.
Solution:
function CheckPastDueAccounting() {
// Code before for loop starts
for(var i=2; i<=lrow; i++) {
// Code to run in loop (iterate through all rows with content)
}
// Code to run after for loop ends
}
Improving code:
Calling getRange(row, column) for individual cells, for each row in a for loop, is not the best way to iterate through rows with data.
It's much better to first (1) get all the values in the desired range, with getRange(row, column, numRows, numColumns) and getValues(), and then (2) iterate through the resulting 2D array, like this:
function CheckPastDueAccounting() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var lrow= ss.getLastRow();
var firstRow = 2;
var values = ss.getRange(firstRow, 1, lrow - firstRow + 1, 7).getValues();
for (var i = 0; i < values.length; i++) {
var row = values[i];
var value = row[6];
if (value == 'Y') {
var DaysAging = row[2];
var org = row[0]; // Fetch Organization Name
var emailAddress = row[5]; // Fetch the email address
var message = 'Hi. Your account is past due ' + DaysAging + ' days.';
var subject = 'Past Due Accounting Alert: ' + org;
GmailApp.sendEmail(emailAddress, subject, message); // Send Alert Email.
}
}
}
Reference:
for loop
getRange(row, column, numRows, numColumns)
I'm learning Google script as I go along and came across an issue that I could not find a solution for.
I have a function that takes in several several strings and one cell as params.
I assume passing a cell is not same as passing its value (string too btw)
Please find attached code:
//return id assigned to data(cell) sheetname
function findInColumn(column, data, colName, sheetname) {
/*
data = cell (cell value is 'bag_backpack.png') does not work
var range = SpreadsheetApp.getActiveRange();
var col = range.getColumn();
var row = range.getRow();
var range2 = SpreadsheetApp.getActiveSheet().getRange(row,col+1);
data = range2.getValue(); (cell value is 'bag_backpack.png') <---fail too
data = 'bag_backpack.png'; <---works
*/
var sheet = SpreadsheetApp.getActive().getSheetByName(sheetname);
var column = sheet.getRange(column + ":" + column); // like A:A
var values = [];
for (var index = 0; index < column.getValues().length; index++) {
values.push(column.getValues()[index][0])
}
var colIndex = getByName(colName, sheetname);
var rowIndex = values.indexOf(data);
//grab id value of data
var range = sheet.getRange(rowIndex+1,colIndex+1);
var data = range.getValue();
return data
}
While I value and need your feedback I kindly request your bear in mind I'm a novice at best and I've spend several hours searching before asking here.
Thank you for your help.
Edit: bag_backpack.png is the content of a cell I'm searching in a column to get the row number of said cell.
var rowIndex = values.indexOf(data);
Returns the index I need.
However... if I feed a cell to the function instead of a string like a cell elsewhere with bag_backpack.png as its content or even derive said value from it:
var range = SpreadsheetApp.getActiveRange();
var col = range.getColumn();
var row = range.getRow();
var range2 = SpreadsheetApp.getActiveSheet().getRange(row,col+1);
data = range2.getValue(); (cell value is 'bag_backpack.png') <---fail too
In said case:
var rowIndex = values.indexOf(data);
gives out -1 instead of index desired.
Most of what you have doesn't make sense to me. I'm guessing that this is what you want. Since I can't figure out what you want, perhaps you can tell me what I missed.
function findInColumn(column,sheetname) {
var sh=SpreadsheetApp.getActive().getSheetByName(sheetname);
var rg=sh.getRange(column + ":" + column); /
var vA=rg.getValues();
var values = [];
for (var i=0;i<vA.length; i++) {
values.push(vA[i][0]);
}
return values
}
I want to thank everyone for taking the time to reply.
the issue was NOT with the code but with some of the first filename having uppercase in the id,name sheet while the binder sheet it did not.(at least 5 hours on Tent.png/tent.png)
I'm attaching a link to my finished work in hopes it benefits anyone.
https://docs.google.com/spreadsheets/d/1jCy1I4r6PeY3kUWrhNno2XO18Jghq6_b1kyN3AflidM/edit?usp=sharing
Hi could someone help me with this script im trying to insert a formula in all the blank cell from (J15) to (J38) here is what ive got but I just cant seem to get it the proper way any help would be greatly appreciated.
function test() {
var ssA = SpreadsheetApp.getActive(); //changed from openById() for my convenience
var ss = ssA.getActiveSheet(); //change from getSheetByName() for my convenience
var range = ss.getRange(15,10,24,1); //row 2 column 7 (G) lastRow 1 column
var data = range.getValues(); //Gets all data
for(var i=0;i<data.length;i++) //this runs over entire selected range
{
if(!data[i][0]) //If true then it's blank
{
data[i](('=Iferror(If(G15="",, if($B$5 = Iferror(query(\'Client
List\'!$A$2:$A, "select A where A =\'"&$B$5&"\'"),""),VLOOKUP($B$5,Client_Rate,2,False),VLOOKUP(D15,Config_Rate_List
,2,False))),"")');)
}
}
range.setFormula(data); //Sets all data.
}
You want to put the formula to "J15:J38". If my understanding is correct, how about this modification?
I thought that it is possible that the cells of "J15:J38" have the values and formulas. So in this modified script, the formula is put to the empty cells which don't have both. The flow of script is as follows.
Retrieve values and formulas from "J15:J38".
Create range list.
Put the formula using setFormula().
I think that there are several solutions for your situation. So please think of this as one of them.
Modified script :
function test() {
var ssA = SpreadsheetApp.getActive(); //changed from openById() for my convenience
var ss = ssA.getActiveSheet(); //change from getSheetByName() for my convenience
var range = ss.getRange(15,10,24,1); //row 2 column 7 (G) lastRow 1 column
var data = range.getValues(); //Gets all data
// The following script was modified.
var formulas = range.getFormulas();
var rangeList = [];
var offset = 15;
for(var i=0;i<data.length;i++) {
if(!data[i][0] && !formulas[i][0]) {
rangeList.push("J" + (offset + i));
}
}
var formula = '=Iferror(If(G15="",, if($B$5 = Iferror(query(\'Client List\'!$A$2:$A, "select A where A =\'"&$B$5&"\'"),""),VLOOKUP($B$5,Client_Rate,2,False),VLOOKUP(D15,Config_Rate_List,2,False))),"")';
ss.getRangeList(rangeList).setFormula(formula);
}
Note :
I was not sure whether the sheet name is Client List or ClientList, because of the line break in your script.
I'm not sure about the formula which was put to cells.
About your title, "black" of "Google Script insert formula in 1 column where cell are black" is "blank"?
Reference :
getRangeList(a1Notations)
If this was not what you want, I'm sorry.
Edit :
Unfortunately, the formulas in an array cannot be put the cells using the range list yet. I think that Sheets API can put various formulas once. But as a simple way, here, I would like to propose the following script.
function test() {
var ssA = SpreadsheetApp.getActive(); //changed from openById() for my convenience
var ss = ssA.getActiveSheet(); //change from getSheetByName() for my convenience
var range = ss.getRange(15,10,24,1); //row 2 column 7 (G) lastRow 1 column
var data = range.getValues(); //Gets all data
// The following script was modified.
var formulas = range.getFormulas();
var val = [];
var offset = 15;
for(var i=0;i<data.length;i++) {
if(!data[i][0] && !formulas[i][0]) {
ss.getRange("J" + (offset + i)).setFormula('=Iferror(If(G' + (offset + i) + '="",, if($B$5 = Iferror(query(\'Client List\'!$A$2:$A, "select A where A =\'"&$B$5&"\'"),""),VLOOKUP($B$5,Client_Rate,2,False),VLOOKUP(D' + (offset + i) + ',Config_Rate_List,2,False))),"")');
}
}
}
I wrote a Google Script for my spreadsheet (a lot of copy/paste online) that is intended to transfer a row of data from one sheet to another sheet if a date matches to the current date (it runs once per day). The code works, with one exception of row 24 where I get an error of "Cannot conver XXX to (class)" with XXX representing the data in that row. It seems it may be something with how I'm defining the variable source_range but I just can't get it to work! Any help is much appreciated. The goal is that within the for loop it copies the "current" row of data based on variable i. If I change the source_range parameters to something static (like row 3, for example) it works perfectly.... but of course then it only pastes row 3 every time which is not what I desire. Any suggestions help!
function AutomationEnroll() {
try{
var spreadsheet = SpreadsheetApp.openById("XXXHIDDENXXX");
var source_sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheets() [2]);
var target_sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[3]);
var startRow = 2; // First row of data to process
var numRows = source_sheet.getLastRow()-1; // Number of rows to process
var dataRange = source_sheet.getRange(startRow, 1, numRows, source_sheet.getLastColumn());
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
//Logger.log(sheetDate);
var TodayDate = Utilities.formatDate(new Date(),'GMT','EEE, d MMM yyyy')
var SurgeryDate = Utilities.formatDate(new Date(row[1]),'GMT', 'EEE, d MMM yyyy')
if (TodayDate == SurgeryDate){
//I now need it to copy row[i] in sheet[2] over to the last_row in sheet[3] ;
var source_range = source_sheet.getRange(data[i], 1, 1, 12) //error converting to (class)
var last_row = target_sheet.getLastRow();
target_sheet.insertRowAfter(last_row);
var target_range = target_sheet.getRange("A"+(last_row+1)+":L"+(last_row+1));
source_range.copyTo(target_range);
}
}
}catch(err){
Logger.log(err.lineNumber + ' - ' + err);
}
}`
I am trying to write a script that will take a list of expenses from a google sheet and append them to a already existing table in a google docs template. At the moment I have this (the reason it says names is because I am testing with dummy data of names and ages):
function myFunction() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet()
var numRows = sheet.getLastRow()
var numColumns = sheet.getLastColumn()
var data = sheet.getRange(1, 1, numRows, numColumns).getValues()
var doc = DocumentApp.openById('13l6O8nmEZgJiZnzumWihsRVOZiq_8vUj6PtBtb9My_0')
var body = doc.getBody()
var tables = body.getTables()
var table = tables[1]
for (var i = 1; i < data.length; i++){
var row = data[i]
var name = row[0]
var age = row[1]
var state = row[2]
var done = 'Done'
//Check to see if line has already been processed or not
if (!state){
sheet.getRange(i + 1, 3).setValue(done)
//Slices out the blank state value
var slice = row.slice(0, numColumns-1)
table.appendTableRow(slice)
}
}
}
This just adds a new table to the document but I can't find way to add rows to an existing table of the data I can add indvidual cells one per row but that isn't useful and can't seem to/don't understand how the appendtoRow instruction works. Any thoughts on how best to do this?
To add a row to an existing table you need to use appendTableRow() and then add cells to this newly added row.
Change the last part of your script like below (make sure that your table is indeed the second table in the document since you used var table = tables[1])
...
if (!state){
sheet.getRange(i + 1, 3).setValue(done);
//Slices out the blank state value
var slice = row.slice(0, numColumns-1);
Logger.log(slice);
var tableRow = table.appendTableRow();
for(var n in slice){
tableRow.appendTableCell(slice[n]);
}
}
...