How to create a new document from a template with placeholders - google-apps-script

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...
}

Related

Add the time when one google sheets document is modified to another sheets document

I have one sheet for a group of people. I'm trying to make a script so that whenever they edit the sheet, the time that they last edited will show up in a sheet in another document.
A sample row from the group sheet looks like this:
col1|...|col10|person name|...|col17
and the sheet that the time should be going to looks like this:
person name|col2|...|col10|date last edited.
this is the code that I've been trying and it is not working so far:
function onEdit(e) {
var row = e.range.getRow();
var col = e.range.getColumn();
var time = new Date().toLocaleString("en-US", {timeZone: "America/Toronto"})
var ID = "sheet ID"; //The ID for the second sheet goes here
var sheet = SpreadsheetApp.OpenById(ID);
var target = sheet.getSheetByName("Sheet2");
var lastColumn = target.getLastColumn();
var lastRow = target.getLastRow();
var range = target.getRange(1,1,lastRow, lastColumn);
var data = range.getValues();
var userEmail = e.user.getEmail();
var array = userEmail.split(".");
var firstName = array[0];
var secondSheet = e.source.getActiveSheet();
var lastRowSecond = secondSheet.getLastRow();
var lastColumnSecond = secondSheet.getLastColumn();
var secondRange = secondSheet.getRange(1,1,lastRowSecond, lastColumnSecond);
var secondData = secondRange.getValues();
var nameRow = secondData[row-1];
var nameColumn = nameRow[10];
var secondPersonarray = nameColumn.split(" ");
var secondPersonFirstName = secondPersonarray[0];
for (var i=1; i<lastRow; i++) {
var sheetRow = data[i];
var name = sheetRow[0].split(" ");
var firstNameSheet = name[0];
if ((firstName == firstNameSheet) && (firstName == secondPersonFirstName)) {
target.getRange(sheetRow, 10).setValue(time);
}
}
}
I've done something similar, only with one document, so I know the problem isn't with the time.

We're sorry, a server error occurred. Please wait a bit and try again. (line 63, file "Code")

Thank you in advance for helping.
I am trying to convert the most recent submitted data from Google Form/Google sheets to a "template" Google doc. Basically, when a user submit a form, it will convert the data from Google Sheet and create a new Google Doc.
Side note: Im not really a coder.. I found the base script online and tried to modified it accordingly. I would greatly appreciate a step by step if possible?
AGAIN, THANK YOU SO MUCH
function createDocument() {
var headers = Sheets.Spreadsheets.Values.get('SHEET-ID', 'A1:AU1');
var tactics = Sheets.Spreadsheets.Values.get('SHEET-ID', 'A2:AU2');
var templateId = 'DOCTEMPLATE-ID';
for(var i = 0; i < tactics.values.length; i++){
var Fclient = tactics.values[i][0];
var Lclient = tactics.values[i][1];
var birthday = tactics.values[i][2];
var profession = tactics.values[i][3];
var email = tactics.values[i][4];
var phone = tactics.values[i][5];
var whatsapp = tactics.values[i][6];
var preferredcontact = tactics.values[i][7];
var UScitizen = tactics.values[i][8];
var Ocitizen = tactics.values[i][9];
var Tsapre = tactics.values[i][10];
var Pairplane = tactics.values[i][11];
var Photelamen = tactics.values[i][12];
var FFlyer = tactics.values[i][13];
var hotelloy = tactics.values[i][14];
var vistedcountries = tactics.values[i][15];
var smoke = tactics.values[i][16];
var allergies = tactics.values[i][17];
var Othermed = tactics.values[i][18];
var addANOTHER = tactics.values[i][19];
var emergencyname = tactics.values[i][20];
var emergencyphone = tactics.values[i][21];
var emergencyrelation = tactics.values[i][22];
var emergencyname2 = tactics.values[i][23];
var emergencyphone2 = tactics.values[i][24];
var emergencyrelation2 = tactics.values[i][25];
var comptravelmag = tactics.values[i][26];
var secondaryFname = tactics.values[i][27];
var secondaryLname = tactics.values[i][28];
var secondarybirthday = tactics.values[i][29];
var secondaryprofession = tactics.values[i][30];
var secondaryemail = tactics.values[i][31];
var secondaryphone = tactics.values[i][32];
var secondarywhatsapp = tactics.values[i][33];
var secondarypreferredcontact = tactics.values[i][34];
var secondaryUScitizen = tactics.values[i][35];
var secondaryOcitizen = tactics.values[i][36];
var secondaryTsapre = tactics.values[i][37];
var secondaryPairplane = tactics.values[i][38];
var secondaryPhotelamen = tactics.values[i][39];
var secondaryFFlyer = tactics.values[i][40];
var secondaryhotelloy = tactics.values[i][41];
var secondaryvistedcountries = tactics.values[i][42];
var secondarysmoke = tactics.values[i][43];
var secondaryallergies = tactics.values[i][44];
var secondaryOthermed = tactics.values[i][45];
var timestamp = tactics.values[i][46];
//Make a copy of the template file
var documentId = DriveApp.getFileById(templateId).makeCopy().getId();
//Rename the copied file
DriveApp.getFileById(documentId).setName('Basic Information: ' + Lclient + 'test');
//Get the document body as a variable.
var body = DocumentApp.openById(documentId).getBody(); **ERROR HERE**
//Insert the supplier name
body.replaceText('{{Fcilent}}', Fclient);
body.replaceText('{{Lcilent}}', Lclient);
body.replaceText('{{birthday}}', birthday);
body.replaceText('{{profession}}', profession);
body.replaceText('{{email}}', email);
body.replaceText('{{phone}}', phone);
body.replaceText('{{whatsapp}}', whatsapp);
body.replaceText('{{preferredcontact}}', preferredcontact);
body.replaceText('{{UScitizen}}', UScitizen);
body.replaceText('{{Ocitizen}}', Ocitizen);
body.replaceText('{{Tsapre}}', Tsapre);
body.replaceText('{{Pairplane}}', Pairplane);
body.replaceText('{{Photelamen}}', Photelamen);
body.replaceText('{{FFlyer}}', FFlyer);
body.replaceText('{{hotelloy}}', hotelloy);
body.replaceText('{{vistedcountries}}', vistedcountries);
body.replaceText('{{smoke}}', smoke);
body.replaceText('{{allergies}}', allergies);
body.replaceText('{{Othermed}}', Othermed);
body.replaceText('{{addANOTHER}}', addANOTHER);
body.replaceText('{{emergencyname}}', emergencyname);
body.replaceText('{{emergencyphone}}', emergencyphone);
body.replaceText('{{emergencyrelation}}', emergencyrelation);
body.replaceText('{{emergencyname2}}', emergencyname2);
body.replaceText('{{emergencyphone2}}', emergencyphone2);
body.replaceText('{{emergencyrelation2}}', emergencyrelation2);
body.replaceText('{{comptravelmag}}', comptravelmag);
body.replaceText('{{secondaryFname}}', secondaryFname);
body.replaceText('{{secondaryLname}}', secondaryLname);
body.replaceText('{{secondarybirthday}}', secondarybirthday);
body.replaceText('{{secondaryprofession}}', secondaryprofession);
body.replaceText('{{secondaryemail}}', secondaryemail);
body.replaceText('{{secondaryphone}}', secondaryphone);
body.replaceText('{{secondarywhatsapp}}', secondarywhatsapp);
body.replaceText('{{secondarypreferredcontact}}', secondarypreferredcontact);
body.replaceText('{{secondaryUScitizen}}', secondaryUScitizen);
body.replaceText('{{secondaryOcitizen}}', secondaryOcitizen);
body.replaceText('{{secondaryTsapre}}', secondaryTsapre);
body.replaceText('{{secondaryPairplane}}', secondaryPairplane);
body.replaceText('{{secondaryPhotelamen}}', secondaryPhotelamen);
body.replaceText('{{secondaryFFlyer}}', secondaryFFlyer);
body.replaceText('{{secondaryhotelloy}}', secondaryhotelloy);
body.replaceText('{{secondaryvistedcountries}}', secondaryvistedcountries);
body.replaceText('{{secondarysmoke}}', secondarysmoke);
body.replaceText('{{secondaryallergies}}', secondaryallergies);
body.replaceText('{{secondaryOthermed}}', secondaryOthermed);
body.replaceText('{{timestamp}}', timestamp);
//Append tactics
parseTactics(headers.values[0], tactics.values[i], body);
}
}
function parseTactics(headers, tactics, body){
for(var i = 1; i < tactics.length; i++){
{tactics[i] != '' &&
body.appendListItem(headers[i] + ' | ' + tactics[i] + ' OTHER').setGlyphType(DocumentApp.GlyphType.BULLET);
}
}
}
Error: "We're sorry, a server error occurred. Please wait a bit and try again. (line 63, file "Code")"
I expected the script to generate a new google doc from the data sheet as it is being submitted on google form.
I think your pretty close. Here's an example I did.
First, I created a function to generate some data for myself.
function testData() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
sh.clearContents();
var rg=sh.getRange(1,1,10,10);
var vA=rg.getValues();
for(var i=0;i<vA.length;i++) {
for(var j=0;j<vA[i].length;j++) {
vA[i][j]=Utilities.formatString('row: %s - col: %s',i+1,j+1);
}
}
rg.setValues(vA);
}
The above function creates a sheet that looks like this:
The Template File Looks like this:
And after running this code:
function createDoc(){
var spreadsheetId='spreadsheet Id';
var templateId='template Id';
var data=Sheets.Spreadsheets.Values.get(spreadsheetId,'Sheet177!A1:J2');//range include sheet name
var docId=DriveApp.getFileById(templateId).makeCopy('Test').getId();
var body=DocumentApp.openById(docId).getBody();
for(var i=0;i<data.values.length;i++) {
for(var j=0;j<data.values[i].length;j++) {
var s=Utilities.formatString('{{col%s-%s}}',i+1,j+1);
body.replaceText(s,data.values[i][j]);
}
}
}
There appears in the same folder another file named test that looks like this:
I must say that sure is a simple way to get data.
I'm kind of wondering if perhaps you simply didn't authenticate the program in the script editor.

Google Docs Script: appendText/insertText Formatting

How do I use appendText() or insertText() for a Google Doc script and maintain formatting?
I want to format the middle portion (group2) of appended strings with italics, while leaving the other parts (group1, group3) as normal text. For example: Hi my name is Nate.
I can bring in "Hi" and append "my name is" and it formats correctly. When I try to append (or insert) "Nate," "Nate" is italicized as well.Between operators +, appendText(), and insertText(), I'm not having much luck.
Below is the relevant portion of the script. Below that, is the entire thing.
How can I append 3 strings together, and only format the middle portion?
NOTE: I commented-out the things I tried (trial1, trial2, etc.). I also started HERE and used it as a guide.
Thanks for any help you can offer!
RELEVANT PART:
if (author1 != "") {
var group1 = author1+author2+author3;
var group2 = title2Italics+containerItalics;
var group3 = contribution1+contribution2+contribution3+version+number+publisher+pubDate+location;
//Only using the calculations below to determine the offset for insertText
var group1Length = group1.length;
var group2Length = group2.length;
var offset = group1Length+group2Length
Logger.log(group1Length);
Logger.log(group2Length);
Logger.log(offset);
//Determines if italicizing is necessary
if (group2.length > 0) {
var addG1 = body.insertParagraph(0,group1)
var addG2 = addG1.appendText(group2);
var formatItalics = addG2.editAsText().setItalic(true);
//var trial1 = addG2.editAsText().setItalic(true) + group3; //does not return the contents of "group3"
//var trial2 = formatItalics + group3; //does not return the contents of "group3"
//var trial3 = formatItalics.insertText(offset,group3); //Error: "Index (18) must be less than or equal to the content length (6)."
//var trial4 = formatItalics.insertText(group2Length, group3); //formats "group3" as well
//var trial5 = formatItalics.appendText(group3); //formats "group3" as well
}
//If italicizing is NOT necessary
else {
var cite = body.insertParagraph(0,group1 + group3);
} //ELSE STATEMENT ENDS HERE
} //FIRST IF STATEMENT ENDS HERE
ENTIRE SCRIPT:
function mlaBibTest() {
// Sheet Information
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.setActiveSheet(ss.getSheetByName('test'));
var startRow = 3;
var startCol = 21;
var numRows = sheet.getLastRow()-1;
var numCols = 14;
var dataRange = sheet.getRange(startRow, startCol, numRows, numCols);
// Document information
var doc = DocumentApp.openById('13MlHq_uoO1rUF0RfdF_kBlLJjbGt4aDoOcSWef0V4zM');
var body = doc.getBody();
// Fetch values for each row in the SS Range.
var cells = dataRange.getValues();
for (var i = 0; i < cells.length; ++i) {
var column = cells[i];
var colU = column[0];
var colV = column[1];
var colW = column[2];
var colX = column[3];
var colY = column[4];
var colZ = column[5];
var colAA = column[6];
var colAB = column[7];
var colAC = column[8];
var colAD = column[9];
var colAE = column[10];
var colAF = column[11];
var colAG = column[12];
var colAH = column[13];
var author1 = colU;
var author2 = colV;
var author3 = colW;
var title1Quotes = colX;
var title2Italics = colY;
var containerItalics = colZ;
var contribution1 = colAA;
var contribution2 = colAB;
var contribution3 = colAC;
var version = colAD;
var number = colAE;
var publisher = colAF;
var pubDate = colAG;
var location = colAH;
if (author1 != "") {
var group1 = author1+author2+author3;
var group2 = title2Italics+containerItalics;
var group3 = contribution1+contribution2+contribution3+version+number+publisher+pubDate+location;
//Only using the calculations below to determine the offset for insertText
var group1Length = group1.length;
var group2Length = group2.length;
var offset = group1Length+group2Length
Logger.log(group1Length);
Logger.log(group2Length);
Logger.log(offset);
//Determines if italicizing is necessary
if (group2.length > 0) {
var addG1 = body.insertParagraph(0,group1)
var addG2 = addG1.appendText(group2);
var formatItalics = addG2.editAsText().setItalic(true);
//var trial1 = addG2.editAsText().setItalic(true) + group3; //does not return the contents of "group3"
//var trial2 = formatItalics + group3; //does not return the contents of "group3"
//var trial3 = formatItalics.insertText(offset,group3); //Error: "Index (18) must be less than or equal to the content length (6)."
//var trial4 = formatItalics.insertText(group2Length, group3); //formats "group3" as well
//var trial5 = formatItalics.appendText(group3); //formats "group3" as well
}
//If italicizing is NOT necessary
else {
var cite = body.insertParagraph(0,group1 + group3);
} //ELSE STATEMENT ENDS HERE
} //FIRST IF STATEMENT ENDS HERE
} //FOR LOOP ENDS HERE
SpreadsheetApp.flush();
} // FUNCTION ENDS HERE
This is a simple example of doing what you asked. It's important to remember that setItalics(true) sets a persistent setting for all new text to be italic, so we have to set it back to false after.
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var paragraph = body.insertParagraph(0, ""); //add paragparh at top of body.
var text1 = paragraph.appendText("Not Italics ");
var text2 = paragraph.appendText("Italics ");
text2.setItalic(true); //Everything after and including this will be italics
var text3 = paragraph.appendText("Not Italics");
text3.setItalic(false); //Everything after and including this will not be italics
>Not Italics Italics Not Italics
So it's easier if you set italics as you build the paragraph.

How to fix the issue mail merge issue

I am trying to create an approval flow using sheet mail merge with approval buttons in the mail . Mail could generate when the user submits the HTML form.
Below script is not working I have attached the script with sample sheet.
I am not able to identify the exact issue, please help me to fix or identify
Sample Sheet
var REQUESTS_STATE_COLUMN = 32;
var STATE_APPROVERS_EMAILED = "EMAILED_Response Pending";
var STATE_APPROVED = "Approved";
var STATE_DENIED = "Rejected";
function sendEmail(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange("A2:AH2");
var data = dataRange.getValues();
for (i in data) {
var rowData = data[i];
var email = e.namedValues["Email Address"];
var emailAddress = rowData[30];
var submiterEmail = rowData[1];
var ProjectName = rowData[2];
var SrDesign = "Sr. Design Architect Services";
var PerHourRate = rowData[6];
var NumberOfHours = rowData[7];
var TotalRate = rowData[8];
var Contact = "Contact Centre Expert";
var PerHourRate2 = rowData[10];
var NumberOfHours2 = rowData[11];
var NTotalRate2 = rowData[12];
var NJrDesign = "Jr. Design Architect";
var PerHourRate3 = rowData[14];
var NumberOfHours3 = rowData[15];
var TotalRate3 = rowData[16];
var Outsourced = "Outsourced Technical Support Resource";
var PerHourRate4 = rowData[18];
var NumberOfHours4 = rowData[19];
var TotalRate4 = rowData[20];
var Supplier = "Supplier Management";
var PerHourRate5 = rowData[22];
var NumberOfHours5 = rowData[23];
var TotalRate5 = rowData[24];
var Project = "Project Management & Execution";
var PerHourRate6 = rowData[26];
var NumberOfHours6 = rowData[27];
var TotalRate6 = rowData[28];
var UserAccount = rowData[28];
var GrandTotalRate = rowData[29];
var seq = e.values[1];
var url = ScriptApp.getService().getUrl();
var sheet = SpreadsheetApp.openById('1i5x0oqpCDgOZO2Nbly4SpNkWpLbTXJhT6pPOfQ7NuEc').getSheetByName("Sheet1");
var cellval = range.getCell(row,1).getValue();
var options = '?approval=%APPROVE%&reply=%EMAIL%'
.replace("%EMAIL%",e.namedValues["User Email Address"])
var approve = url+options.replace("%APPROVE%","Approved")+'&row='+data+'&cellval='+cellval;
var reject = url+options.replace("%APPROVE%","Rejected")+'&row='+data+'&cellval='+cellval;
var subject = 'Technology Charges for '+ProjectName+'';
var html = '<p style="font-family:Verdana; fontsize=9px">Hello Recipient,<br/><br/><br/><br/>Referance No: '+cellval+'<br/><a href='+ approve +'> <b>approve </b></a><a href='+ reject +'> <b>Reject</b></a><br/>'
MailApp.sendEmail({
to: emailAddress,
subject: subject,
htmlBody: html,
});
//Add a state in the form spreadsheet with APPROVERS_EMAILED state
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow = sheet.getLastRow();
sheet.getRange(lastRow, REQUESTS_STATE_COLUMN+1).setValue(STATE_APPROVERS_EMAILED);
}
}
function doGet(e){
var answer = (e.parameter.approval === 'Approved') ? 'Yes -Approved!' : 'No-Rejected ';
var cellval = e.parameter.cellval;
var email = e.parameter.reply;
var sheet = SpreadsheetApp.openById("1i5x0oqpCDgOZO2Nbly4SpNkWpLbTXJhT6pPOfQ7NuEc").getSheetByName("Sheet1");
var data = sheet.getDataRange().getValues();
var headers = data[0];
var approvalCol = headers.indexOf("Approval") + 1;
if (0 === approvalCol) throw new Error ("Must add Approval column.");
// Record approval or rejection in spreadsheet
var row = ArrayLib.indexOf(data, 0, cellval);
if (row < 0) throw new Error ("Request not available."); // Throw error if request was not found
sheet.getRange(row+1, approvalCol).setValue(e.parameter.approval);
// Display response to approver
var app = UiApp.createApplication();
app.add(app.createHTML('<h2>Thank you..! Your response has been recorded'+' saying: '+ answer + '</h2>'))
return app
}
The getCell requires integer value for row and column but instead you are passing the entire row (rowData). You need to replace the line 45 to the below line.
var cellval = dataRange.getCell(i+1, 1).getValue()

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.