Capture values and send email trigger - google-apps-script

I managed to collect data of user typing in and by using onChange trigger, I did meet my requirements for my task. However, I realized that for example I am filling up Column A1:A4. If my A1:A3 is out of range, it will trigger the email. But if my A4 is within range, the values of A1:A3 will still trigger the email eventhough it has trigger it before. How do I make sure that the values that have been capture do not trigger the email again?
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
currentsheet = ss.getSheetName();
//var values = ss.getRange(a1Notation)
//console.log(values);
var lastcol = ss.getLastColumn();
var vibrationtemplate = HtmlService.createTemplateFromFile("vibration");
var temperaturetemplate = HtmlService.createTemplateFromFile("temperature");
//console.log(lastcol);
if((currentsheet == 'A Vibration') || (currentsheet == 'B Vibration')){
console.log(currentsheet);
for(var i =2; i<=lastcol; i++){
var cell = ss.getRange(i,lastcol).getValues();
console.log(""+cell);
if(cell > 8){
console.log("Value is more than 8 and current value is "+cell);
vibrationtemplate.vibrate = cell;
MailApp.sendEmail("someone#gmail.com",
"Parameter Out of Range Notification",
"",{htmlBody: vibrationtemplate.evaluate().getContent()});
}
}
}
if((currentsheet == 'A Temperature') || (currentsheet == 'B Temperature')){
console.log(currentsheet);
for(var i =2; i<=lastcol; i++){
var cell = ss.getRange(i,lastcol).getValues();
console.log(""+cell);
if(cell > 80){
console.log("Value is more than 80 and current value is "+cell);
temperaturetemplate.temp = cell;
MailApp.sendEmail("someone#gmail.com",
"Parameter Out of Range Notification",
"",{htmlBody: temperaturetemplate.evaluate().getContent()});
}
}
}
}
EDIT: Latest code - Using a daily trigger and only checks at the end of the day.
function myFunction() {
const ss = SpreadsheetApp.getActiveSheet();
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var sheetNumber = sheets.length; //Get number of sheets within Spreadsheet
var currentSheet = ss.getIndex()-1; //Get index of current sheet with 0 indexing
var vibrationtemplate = HtmlService.createTemplateFromFile("vibration"); //Create HTML for email by grabbing template from vibration.html
var temperaturetemplate = HtmlService.createTemplateFromFile("temperature"); //Create HTML for email by grabbing template from temperature.html
const vibrationlimit = 8; //Set vibrationlimit as constant equals to 8
const temperaturelimit = 80; //Set temperaturelimit as constant equals to 80
var currentDate = new Date(); //Get system Date and Time
var currentDay = currentDate.getDate(); //Extract Date from Full Date(currentDate)
var currentMonth = currentDate.getMonth() +1; //Extract Month from Full Date(currentDate), add +1 as month index start from 0.
for (var z = currentSheet ; z<sheetNumber ; ++z ){
SpreadsheetApp.setActiveSheet(sheets[z])
var lastcol = sheets[z].getLastColumn();
var lastrow= sheets[z].getLastRow();
var cellDate = sheets[z].getRange(1,lastcol).getValues();
var formattedCellDate = new Date(cellDate);
var cellDay = formattedCellDate.getDate();
var cellMonth = formattedCellDate.getMonth() + 1;
if((z==0) || (z==2)){
if((cellDay == currentDay) && (cellMonth == currentMonth)){
for(var i = 2; i<=lastrow; i++){
var scxvibrationname = sheets[z].getRange(i,1).getValues();
var vibration = sheets[z].getRange(i,lastcol).getValues();
if(vibration > vibrationlimit){
Logger.log("Vibration over 8 - Current Value is "+vibration);
vibrationtemplate.vibrate = vibration;
vibrationtemplate.scxvibration = scxvibrationname;
}
}
}
}
}

You can use PropertiesService to store the last row of the previous script run
The following code sets the start row for the for loop to the (last row+1) of the previous script run, so that only e-mails from newly added rows will be sent:
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
currentsheet = ss.getSheetName();
//var values = ss.getRange(a1Notation)
//console.log(values);
var lastcol = ss.getLastColumn();
var lastrow=ss.getLastRow();
var vibrationtemplate = HtmlService.createTemplateFromFile("vibration");
var temperaturetemplate = HtmlService.createTemplateFromFile("temperature");
//console.log(lastcol);
if(PropertiesService.getScriptProperties().getKeys().length==0){
PropertiesService.getScriptProperties().setProperty('startRow', lastrow+1);
}
var startRow=PropertiesService.getScriptProperties().getProperty('startRow');
if((currentsheet == 'A Vibration') || (currentsheet == 'B Vibration')){
console.log(currentsheet);
//I ASSUME THAT YOU WANT TO LOOP THROUGH ALL ROWS AND NOT COLUMNS
for(var i =startRow; i<=lastrow; i++){
var cell = ss.getRange(i,lastcol).getValues();
console.log(""+cell);
if(cell > 8){
console.log("Value is more than 8 and current value is "+cell);
vibrationtemplate.vibrate = cell;
MailApp.sendEmail("someone#gmail.com",
"Parameter Out of Range Notification",
"",{htmlBody: vibrationtemplate.evaluate().getContent()});
}
}
}
...
PropertiesService.getScriptProperties().setProperty('startRow', lastrow+1);
}

function myFunction() {
const ss = SpreadsheetApp.getActiveSheet();
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var sheetNumber = sheets.length; //Get number of sheets within Spreadsheet
var currentSheet = ss.getIndex()-1; //Get index of current sheet with 0 indexing
var vibrationtemplate = HtmlService.createTemplateFromFile("vibration"); //Create HTML for email by grabbing template from vibration.html
var temperaturetemplate = HtmlService.createTemplateFromFile("temperature"); //Create HTML for email by grabbing template from temperature.html
const vibrationlimit = 8; //Set vibrationlimit as constant equals to 8
const temperaturelimit = 80; //Set temperaturelimit as constant equals to 80
var currentDate = new Date(); //Get system Date and Time
var currentDay = currentDate.getDate(); //Extract Date from Full Date(currentDate)
var currentMonth = currentDate.getMonth() +1; //Extract Month from Full Date(currentDate), add +1 as month index start from 0.
for (var z = currentSheet ; z<sheetNumber ; ++z ){
SpreadsheetApp.setActiveSheet(sheets[z])
var lastcol = sheets[z].getLastColumn();
var lastrow= sheets[z].getLastRow();
var cellDate = sheets[z].getRange(1,lastcol).getValues();
var formattedCellDate = new Date(cellDate);
var cellDay = formattedCellDate.getDate();
var cellMonth = formattedCellDate.getMonth() + 1;
if((z==0) || (z==2)){
if((cellDay == currentDay) && (cellMonth == currentMonth)){
for(var i = 2; i<=lastrow; i++){
var scxvibrationname = sheets[z].getRange(i,1).getValues();
var vibration = sheets[z].getRange(i,lastcol).getValues();
if(vibration > vibrationlimit){
Logger.log("Vibration over 8 - Current Value is "+vibration);
vibrationtemplate.vibrate = vibration;
vibrationtemplate.scxvibration = scxvibrationname;
}
}
}
}
}
I manipulated by using daily time-driven trigger.

Related

cannot target specific cell in a sheet (google app script)

I currently have a script that takes the selected option in column F and updates a different sheet with the selected value. The first sheet is set up like this
A
B
C
D
E
F
Date
Names of other sheets
Month
Day
Weekday
Options
The other sheets are set to start on the 16th of the month and finish on the 15th of the following month. So the sheet labeled (2023/01) has dates starting from row 7. The dates are in column A and the value to be updated is in column D.
The problem
In the script, the dates are all offset by one. So if you select 23/01/16 it actually matches 23/01/17. This doesn't seem to be a problem except when the 15th of every month is selected. Since the sheets end on the 15th and the dates are offset it matches the 16th but the 16th does not exist on the sheet so the cell is not updated.
MY solution
To fix this issue I created a condition to check if the selected date includes '/16' then run some code. I then created a variable to get the previous sheet and got the last row and set the value that way. I used toast() to check if the values I am selecting are correct and they seem to be. The sheet name is correct and the last row is correct but I am not actually seeing the cell being updated. I am not sure what I am doing wrong so any help would be greatly appreciated.
/* 休日入力イベント
--------------------------------------*/
function changeHoliday(ss) {
var sheet = ss.getActiveSheet(); //アクティブなシート
var sheetName = sheet.getSheetName();
var atvc = sheet.getActiveCell(); //アクティブセル
//休日シートの休日を変更した時だけ
if(sheetName=='休日' || sheetName && atvc.getColumn() == 6){
var flag = atvc.getValue(); //休日かどうか
var targetSheetName = String(atvc.offset(1, -4).getValue()); //対応するシート名
//Get previous sheet name
var prevSheetName = String(atvc.offset(-1,-4).getValue());
var targetDate = Utilities.formatDate(atvc.offset(1, -5).getValue(),"JST", "yyyy/MM/dd"); //対応する日付
// var targetDateEndofSheet = Utilities.formatDate(atvc.offset(0, -5).getValue(),"JST", "yyyy/MM/dd");
var targetSheet = ss.getSheetByName(targetSheetName);
var lastRow = targetSheet.getLastRow();
var values = targetSheet.getRange(1,1,lastRow,1).getValues();
// 取得したデータから一致する日付を探す
//original i=7
for (var i=7; i<lastRow; i++){
var d = Utilities.formatDate(values[i][0],"JST", "yyyy/MM/dd");
//My if statement
if(targetDate.includes("/16")) {
var targetS = ss.getSheetByName(prevSheetName); //get the pervious sheet
var lastR = targetS.getLastRow(); //get the last row of the previous sheet
//check the values
ss.toast( "prev sheet name " + prevSheetName +"last r: " + lastR + "flag" + flag + "td " + targetDate)
//select the cell 4 of the last row
var r = prevSheetName.getRange(lastR,4);
r.setValue(flag); //set the select value
}
if(d == targetDate){
var range = targetSheet.getRange(i,4);
// データ追加
range.setValue(flag);
}
}
}
//一度に1つの日付を入力してください
}
/* 休日の保護の解除
--------------------------------------*/
function protectionRemove_(targetDate){
var ss = SpreadsheetApp.getActive();
var protections = ss.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var i = 0; i < protections.length; i++) {
var protection = protections[i];
// 説明文が一致したら削除
if (protection.getDescription() == targetDate) {
protection.remove();
}
}
}
I was able to solve it with some of the suggestions made in the comments
I added this to my code
if(d.includes("/16") && targetDate.includes("/16")) {
var prevSheetName = String(atvc.offset(-1, -4).getValue()); //get target page
var targetSheet = ss.getSheetByName(prevSheetName);
var lr= targetSheet.getLastRow(); //select the last of the target page
var r = targetSheet.getRange(lr,4); //set the range
r.setValue(flag);
}
Please find my explanation in the comments:
function changeHoliday(ss) {
var sheet = ss.getActiveSheet(); //アクティブなシート
var sheetName = sheet.getSheetName();
var atvc = sheet.getActiveCell(); //アクティブセル
//休日シートの休日を変更した時だけ
/* Should be AND OPERATOR */
if(sheetName=='休日' && sheetName && atvc.getColumn() == 6){
var flag = atvc.getValue(); //休日かどうか
/* Should check the value */
if (flag == '休日') {
/* Row offset should be 0 */
var targetSheetName = String(atvc.offset(0, -4).getValue()); //対応するシート名
//Get previous sheet name
/* Not needed */
// var prevSheetName = String(atvc.offset(-1,-4).getValue());
/* Row offset should be 0 */
var targetDate = Utilities.formatDate(atvc.offset(0, -5).getValue(),"JST", "yyyy/MM/dd"); //対応する日付
// var targetDateEndofSheet = Utilities.formatDate(atvc.offset(0, -5).getValue(),"JST", "yyyy/MM/dd");
var targetSheet = ss.getSheetByName(targetSheetName);
var lastRow = targetSheet.getLastRow();
var values = targetSheet.getRange(1,1,lastRow,1).getValues();
// 取得したデータから一致する日付を探す
//original i=7
/* i should starts from 6 */
for (var i=6; i<lastRow; i++){
var d = Utilities.formatDate(values[i][0],"JST", "yyyy/MM/dd");
//My if statement
/* Not needed */
/*
if(targetDate.includes("/16")) {
var targetS = ss.getSheetByName(prevSheetName); //get the pervious sheet
var lastR = targetS.getLastRow(); //get the last row of the previous sheet
//check the values
ss.toast( "prev sheet name " + prevSheetName +"last r: " + lastR + "flag" + flag + "td " + targetDate)
//select the cell 4 of the last row
var r = prevSheetName.getRange(lastR,4);
r.setValue(flag); //set the select value
}
*/
if(d == targetDate){
/* Row should be i + 1 */
var range = targetSheet.getRange(i + 1,4);
// データ追加
range.setValue(flag);
/* Better to break */
break;
}
}
}
}
//一度に1つの日付を入力してください
}
To simplify:
function changeHoliday(ss) {
var sheet = ss.getActiveSheet();
var sheetName = sheet.getSheetName();
var atvc = sheet.getActiveCell();
if(sheetName=='休日' && sheetName && atvc.getColumn() == 6){
var flag = atvc.getValue();
if (flag == '休日') {
var targetSheetName = String(atvc.offset(0, -4).getValue());
var targetDate = Utilities.formatDate(atvc.offset(0, -5).getValue(),"JST", "yyyy/MM/dd"); //対応する日付
var targetSheet = ss.getSheetByName(targetSheetName);
var lastRow = targetSheet.getLastRow();
var values = targetSheet.getRange(1,1,lastRow,1).getValues();
for (var i=6; i<lastRow; i++){
var d = Utilities.formatDate(values[i][0],"JST", "yyyy/MM/dd");
if(d == targetDate){
var range = targetSheet.getRange(i + 1,4);
range.setValue(flag);
break;
}
}
}
}
}

How to create a new document from a template with placeholders

I'm trying to create a script that will create new documents from a template-document. Replace placeholders in the documents with data from the sheet based on a keyword search in a specific column. And then change the row's value in the specific column so that the row will not process when the script runs again.
I think I've got it right with the first keyword search, and the loop through the rows. But the last part to get the data to 'merge' to the placeholders I can't figure out how to. I just get the value "object Object" and other values in the document.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var lastColumn = s.getLastColumn();
function createDocFromSheet() {
var headers = getUpsertHeaders(s);//function is defined outside of this function
var statusColNum = headers.indexOf('Status')+1;
var row = getRowsData(s); //The function is defined outside this function.
for (var i=0; i<row.length; i++) {
var jobStatus = '';
if (row[i]['Status'] === '') {
//New: write the status to the correct row and column - this will be moved to the end when I get the rest right
var jobStatus = "Created";
s.getRange(i+2, statusColNum).setValue(jobStatus);
//Find the template and make a copy. Activate the body of the new file.
var templateFile = DriveApp.getFileById('1lkfmqsJMjjPujHqDqKtcDmL-5GMIxpOWTyCOaK29d2A');
var copyFile = templateFile.makeCopy()
var copyId = copyFile.getId()
var copyDoc = DocumentApp.openById(copyId)
var copyBody = copyDoc.getActiveSection()
//Find the rows Values as an object.
var rows = s.getRange(i+2,1,1,lastColumn)
var rowsValues = rows.getValues();
Logger.log(rowsValues)
//Until here I think it's okay but the last part?
//HOW TO replace the text???
for (var columnIndex = 0; columnIndex < lastColumn; columnIndex++) {
var headerValue = headerRow[columnIndex]
var rowValues = s.getActiveRange(i,columnIndex).getValues()
var activeCell = rowsValues[columnIndex]
//var activeCell = formatCell(activeCell);
Logger.log(columnIndex);
copyBody.replaceText('<<' + headerValue + '>>', activeCell)
}
Template doc : Link
Template sheet: Link
You can use the following GAS code to accomplish your goals:
var DESTINATION_FOLDER_ID = 'YOUR_DESTINATION_FOLDER_ID';
var TEMPLATE_FILE_ID = 'YOUR_TEMPLATE_FILE_ID';
function fillTemplates() {
var sheet = SpreadsheetApp.getActiveSheet();
var templateFile = DriveApp.getFileById(TEMPLATE_FILE_ID);
var values = sheet.getDataRange().getDisplayValues();
var destinationFolder = DriveApp.getFolderById(DESTINATION_FOLDER_ID);
for (var i=1; i<values.length; i++) {
var rowElements = values[i].length;
var fileStatus = values[i][rowElements-1];
if (fileStatus == 'Created') continue;
var fileName = values[i][0];
var newFile = templateFile.makeCopy(fileName, destinationFolder);
var fileToEdit = DocumentApp.openById(newFile.getId());
for (var j=1; j<rowElements-1; j++) {
var header = values[0][j];
var docBody = fileToEdit.getBody();
var patternToFind = Utilities.formatString('<<%s>>', header);
docBody.replaceText(patternToFind, values[i][j]);
}
sheet.getRange(i+1, rowElements).setValue('Created');
}
}
You only have to replace the 1st and 2nd lines as appropriate. Please do consider as well that the code will assume that the first column is the file name, and the last one the status. You can insert as many columns as you wish in between.
After some coding I ended up with this code to process everything automatic.
Again thanks to #carlesgg97.
The only thing I simply can't figure out now is how to generate the emailbody from the template with dynamic placeholders like in the document. How to generate the var patternToFind - but for the emailbody?
I've tried a for(var.... like in the document but the output doesn't replace the placeholders.
var DESTINATION_FOLDER_ID = '1inwFQPmUu1ekGGSB5OnWLc_8Ac80igK0';
var TEMPLATE_FILE_ID = '1lkfmqsJMjjPujHqDqKtcDmL-5GMIxpOWTyCOaK29d2A';
function fillTemplates() {
//Sheet variables
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data');
var values = sheet.getDataRange().getDisplayValues();
//Header variables
var headers = sheet.getDataRange().getValues().shift();
var idIndex = headers.indexOf('ID');
var nameIndex = headers.indexOf('Name');
var emailIndex = headers.indexOf('Email');
var subjectIndex = headers.indexOf('Subject');
var statusIndex = headers.indexOf('Status');
var fileNameIndex = headers.indexOf('File Name');
var filerIndex = headers.indexOf('Filer');
var birthIndex = headers.indexOf('Date of birth');
//Logger.log(statusIndex)
//Document Templates ID
var templateFile = DriveApp.getFileById(TEMPLATE_FILE_ID);
//Destination
var destinationFolder = DriveApp.getFolderById(DESTINATION_FOLDER_ID);
var templateTextHtml = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Email').getRange('D11').getValue();
//Run through the variables
for (var i=1; i<values.length; i++) {
//If first column is empty then stop
var index0 = values[i][0];
if(index0 == "") continue;
var rowElements = values[i].length;
var fileStatus = values[i][statusIndex];
//If the row already processed then stop
if (fileStatus == "Created") continue;
//If the row is not processed continue
//Define the new filename by the relevant Column
var fileName = values[i][fileNameIndex];
var newFile = templateFile.makeCopy(fileName, destinationFolder);
var fileToEdit = DocumentApp.openById(newFile.getId());
//Replace placeholders in the new document
for (var j=1; j<rowElements-1; j++) {
var header = values[0][j];
var docBody = fileToEdit.getBody();
var patternToFind = Utilities.formatString('{{%s}}', header);
docBody.replaceText(patternToFind, values[i][j]);
}
//Create the PDF file
fileToEdit.saveAndClose();
var newPdf = DriveApp.createFile(fileToEdit.getAs('application/pdf'));
DriveApp.getFolderById(DESTINATION_FOLDER_ID).addFile(newPdf);
DriveApp.getRootFolder().removeFile(newPdf);
newFile.setTrashed(true);
var newPdfUrl = newPdf.getUrl();
//Create the emailbody
var textBodyHtml = templateTextHtml.replace("{{Name}}",values[i][nameIndex]).replace("{{Date of birth}}",values[i][birthIndex]);
var textBodyPlain = textBodyHtml.replace(/\<br>/mg,"");
//Will send email to email Column
var email = values[i][emailIndex];
var emailSubject = values[i][idIndex]+" - "+values[i][fileNameIndex]+" - "+values[i][nameIndex];
MailApp.sendEmail(email,emailSubject,textBodyPlain,
{
htmlBody: textBodyHtml+
"<p>Automatic generated email</p>",
attachments: [newPdf],
});
sheet.getRange(i+1, filerIndex+1).setValue(newPdfUrl);
sheet.getRange(i+1, statusIndex+1).setValue('Created');
}//Close for (var i=1...
}

How do I get my google spreadsheet to open to today's date?

Here is a link to my document:
https://docs.google.com/spreadsheets/d/1wBpeCUTmePD3N5CDz57LeBBWZHnSwrX-5b6XscdbB4s/edit?usp=sharing
I want the document to open to today's date or to the Monday of each week.
Please help.
Thanks in advance.
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getRange("A:A");
var values = range.getValues();
var day = 24*3600*1000;
var today = parseInt((new Date().setHours(0,0,0,0))/day);
var ssdate;
for (var i=0; i<values.length; i++) {
try {
ssdate = values[i][0].getTime()/day;
} catch(e) { }
if (ssdate && Math.floor(ssdate) == today) {
sheet.setActiveRange(range.offset(i,0,1,1));
break;
}
}
}
The main issue in your attempt is that you grabbed column A, but your dates exist in row 2. Try this:
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("2018"); // Specifiy the sheet
var range = sheet.getRange("2:2"); // Row 2
var values = range.getValues()[0]; // This is a 2-dimensional array in the form [[row1-col1, row1-col2],[row2-col1,row2-col2]].
// Because we only pulled one row (Row 2), we can immediately select just that row by appending the [0]
var today = new Date();
var todayDate = today.getDate();
var todayMonth = today.getMonth();
var todayYear = today.getFullYear();
for (var i=0; i<values.length; i++) {
var columnDate = new Date(values[i]);
if (columnDate.getDate() === todayDate && columnDate.getMonth() === todayMonth && columnDate.getFullYear() === todayYear) {
sheet.getRange(1, i+1).activate();
break;
}
}
}

GetCell -> GetValue -> SetValue fails

I want to make the below mentioned code working but it doesn't - nothing happens when I run it (also no error), that means the username (sUserName) doesn't get saved in the spreadsheet... And also I don't understand why the columns cant start with 2, 3, 4 (then the timestamp can stay in column #1) instead 1, 2, 3 - if so I get an error.
Here is the code:
var userNameColumn = 1; //Column where the user name is written
var subTypeColumn = 2; //Column where the submitter type is written ex. "Requester"
var sUserNameColumn = 3; //Column where the user name is saved
function saveUserName() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
for (var i = 1; i <= numRows; i++) {
var userNameCell = rows.getCell(i, userNameColumn);
var subTypeCell = rows.getCell(i, subTypeColumn);
var sUserNameCell = rows.getCell(i, sUserNameColumn);
if(sUserNameCell.isBlank() && subTypeCell.getValue() === 'Requester') {
sUserNameCell.setValue(userNameCell)
};
}
}
Here is the link for my spreadsheet and code:
Google Spreadsheet
See if this helps
function saveUserName() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var rows = sheet.getDataRange().getValues();
for (var i = 1; i < rows.length; i++) {
var userNameCell = rows[i][1];
var subTypeCell = rows[i][2];
var sUserNameCell = rows[i][3];
if (!sUserNameCell && subTypeCell === 'Requester') sheet.getRange(i+1,4).setValue(userNameCell)
}
}

How to loop command using the .getRowIndex() in Google Sheets?

function getColIndexByName(colName) {
var sheet = SpreadsheetApp.getActiveSheet();
var numColumns = sheet.getLastColumn();
var row = sheet.getRange(1, 1, 1, numColumns).getValues();
for (i in row[0]) {
var name = row[0][i];
if (name == colName) {
return parseInt(i) + 1;
}
}
return -1;
}
function sendtoContacts () {
var source = SpreadsheetApp.getActiveSpreadsheet();
var ss = source.getActiveSheet();
var row = ss.getActiveRange().getRowIndex();
var group = ContactsApp.getContactGroup('From Googlesheet');
var givenName = ss.getRange(row, getColIndexByName("First")).getValue();
var familyName = ss.getRange(row, getColIndexByName("Last")).getValue();
var email = ss.getRange(row, getColIndexByName("Work Gmail")).getValue();
var Homeemail = ss.getRange(row, getColIndexByName("Personal Email")).getValue();
var company = ss.getRange(row, getColIndexByName("Company")).getValue();
var title = ss.getRange(row, getColIndexByName("Title")).getValue();
var phone = ss.getRange(row, getColIndexByName("Phone")).getValue();
var mobile = ss.getRange(row, getColIndexByName("Mobile")).getValue();
var newContact = ContactsApp.createContact(givenName, familyName, email);
var contactid = newContact.getId();
var addy = ss.getRange(row, getColIndexByName("Address")).getValue();
var city = ss.getRange(row, getColIndexByName("City")).getValue();
var prov = ss.getRange(row, getColIndexByName("Prov")).getValue();
var pc = ss.getRange(row, getColIndexByName("Postal Code")).getValue();
var address = addy + ", " + city + ", " + prov + ", " + pc
var AltContact = ss.getRange(row, getColIndexByName("Alt Contact Name")).getValue();
var AltRelation = ss.getRange(row, getColIndexByName("Alt ContactRelation")).getValue();
var AltPhone = ss.getRange(row, getColIndexByName("Alt Contact Phone")).getValue();
var AltWork = ss.getRange(row, getColIndexByName("Alt Contact Wk No")).getValue();
var AltMobile = ss.getRange(row, getColIndexByName("Alt Contact Mobile")).getValue();
newContact.addToGroup(group);
newContact.addAddress("Home", address);
newContact.addCompany(company, title);
newContact.addEmail("Home", Homeemail);
newContact.addCustomField("Emergency Contact", AltContact);
newContact.addCustomField("Emergency Contact Relation", AltRelation);
newContact.addCustomField("Emergency Contact Work", AltWork);
newContact.addCustomField("Emergency Contact Mobile", AltMobile);
for ( var i = 0; i < phone.length ; i++){
if (phone[i][3] != ''){ newContact.addPhone("HOME", phone); return}};
for ( var i = 0; i < mobile.length ; i++){
if (mobile[i][44] != ''){ newContact.addPhone("Mobile", mobile); return}};
}
function MakeAllContacts() {
var source = SpreadsheetApp.getActiveSpreadsheet();
var ss = source.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 100; // Number of rows to process
for (row = 2; row < 6; row++)
{
sendtoContacts();
}
return
}
Here I am duplicating the entries with MakeAllContacts() but I want to make the RowIndex change to every row in the sheet so it add all the contacts in the sheet. Here is at Video I made explaining it Video and here is a link to my actual sheet Google Sheet. I have a fair bit of code I would like to start sharing if I could just get my head are around looping instead of the one row to be All the rows in the sheet. Thanks for any help is appreciated.
Your sendtoContacts () function is using ss.getActiveRange().getRowIndex(); to determine which row to use but nowhere in your script you set any row to active so you keep using the same data all the way through the main loop in MakeAllContacts().
There are 2 possible solutions :
use activate() in the MakeAllContacts() function loop so that the active row changes for each iteration (ss.getRange(row,1).activate())
use a rowIndex parameter in the sendtoContacts () function like below :
function MakeAllContacts() {
var source = SpreadsheetApp.getActiveSpreadsheet();
var ss = source.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 100; // Number of rows to process
for (row = 2; row < numRows; row++){
sendtoContacts(row);
}
}
and then change the function sendtoContacts () function like this:
function sendtoContacts (row) { // row as parameter
var source = SpreadsheetApp.getActiveSpreadsheet();
var ss = source.getActiveSheet();
...
That said, this approach is not very efficient since each data is read in the spreadsheet using a single getRange/getValue which is particularly slow... please read the best practice to get inspiration on how to handle your data more efficiently using a single getValues() and iterate the array content instead.