Google Apps Script document not accessible by replaceText() - replace

Here is my code and I can't figure out why replaceText() isn't working.
function createDoc(){
var templateid = "1jM-6Qvy47gQ45u88WfDU_RvfuSTsw27zBP_9MfsUGr8"; // get template file id
var FOLDER_NAME = "Completed Rental Agreements"; // folder name of where to put doc
// get the data from an individual user
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var data = sheet.getRange(2, 1, sheet.getLastRow()-1,sheet.getLastColumn()).getValues();
var lastRow = sheet.getLastRow();
var firstName = sheet.getRange(lastRow, 2, 1,1).getValues();
var lastName = sheet.getRange(lastRow, 3, 1,1).getValues();
var guestEmail = sheet.getRange(lastRow, 7, 1,1).getValues();
var companyEmail = "bearlakeprojectmanagement#yahoo.com";
var companyName = "Bear Lake Project Management";
var username = "jared.hislop.test#gmail.com"; // get their email (from sheet name)
var me = "jared.hislop.test#gmail.com";
//Copy Template
var docid = DocsList.getFileById(templateid).makeCopy("Rental Agreement - "+firstName+""+lastName+"-"+guestEmail).getId();
// var file = DocsList.getFileById(docid).addEditors(me);
// move file to right folder
var file = DocsList.getFileById(docid);
var folder = DocsList.getFolder(FOLDER_NAME);
file.addToFolder(folder);
var doc = DocumentApp.openById(docid);
var body = doc.getActiveSection();
var body_text = doc.addEditor("jared.hislop.test#gmail.com");
// Append Cabin Rules
// doc.appendParagraph("This is a typical paragraph.");
body.replaceText("/^companyEmail$/", "test");
body.replaceText("%companyName%", "test1");
body.replaceText("%todayDate%", "test1");
doc.saveAndClose();
}
I've tried doc.replaceText and body.replaceText along with several other options.
Any ideas why this isn't working?
Thank in advance

Consider this:
body.replaceText("%companyName%", "test1");
That will look for every instance of "companyName" with "%" on either side of it. The "%" in this case is just that, a piece of punctuation in a strange place. This is a convention used to decrease the likelihood of accidentally replacing real text in the document.
Your template document must have that exact pattern for the replacement to work. (Yours doesn't... instead you have just "companyName". Change it to "%companyName%".) Apply that rule for any other replacement you want to make.
You could benefit from some optimization.
...
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
// Next line is hard to maintain - there's a better way.
// var data = sheet.getRange(2, 1, sheet.getLastRow()-1,sheet.getLastColumn()).getValues();
// Read whole spreadsheet, skip headers
var data = sheet.getDataRange().getValues().slice(1);
// Already read in all data, use it instead of reading sheet again.
var firstName = data[data.length-1][2-1]; // (2-1) because array counts from 0
var lastName = data[data.length-1][3-1]; // while spreadsheet columns from 1
var guestEmail = data[data.length-1][7-1]; // Better: put these into variables.
...
While experimenting with your code, I ran into an autocompletion issue with doc.getActiveSection(). It turns out that there has been a recent change, according to the release notes for April 15 2013.
Renamed Document.getActiveSection() to getBody().
You should update your code accordingly.

Related

Simultaneous emails sent to different addresses based on form input

What I have:
A google form with checkbox options so the user can choose ALL that
apply (6 total options)
For each option, there is a specific email associated with each option (6 different emails)
What is occurring:
When a single option is chosen, the email goes out to the correct person
When multiple options are chosen, an email goes out only to the first option
The spreadsheet collects the data correctly, showing all the options chosen, but only one email actually goes out
What I need:
Multiple emails sent to the different specified addresses if their option is one of the selected ones
Current Script:
function sendFormByEmail(e)
{
console.log(JSON.stringify(e))
// Remember to replace XYZ with your own email address
var named_values = e.namedValues
var teachername = named_values["Teacher Name"];
var info = named_values["Your message/announcement"];
var time = named_values["Please include time frame"];
var photos = named_values["Include photos with this form if applicable; you can also create the graphic for social media and include below"];
var announce = e.values[3];
var address = [];
if(announce.match('School Intercom Announcement')){
var address = "mhhsmedia#yanceync.net";
var subject = "School Announcement Request";
}
if(announce.match('MHHS Website')){
var address = "heritagecougars#yanceync.net";
var subject = "Website posting request";
}
if(announce.match('MHHS Social Media')) {
var address = "socialmedia#yanceync.net";
var subject = "Social Media Request";
}
if(announce.match('Week in Pics')) {
var address = "ycspics#yanceync.net";
var subject= "Week in Pics Request";
}
if(announce.match('Remind text message')){
var address = "jstipton#yanceync.net";
var subject = "Remind message request";
}
if(announce.match('Phone call home')){
var address = "blackboardcall#yanceync.net";
var subject = "All-Call Request";
}
// The variable e holds all the form values in an array.
// Loop through the array and append values to the body. ;
var email = address
var message = "";
for(var field in e.namedValues)
message += field + ' :: '
+ e.namedValues[field].toString() + "\n\n";
MailApp.sendEmail(email, subject, message);
}
Things I have tried with no luck:
I attempted to join the addresses with:
var email = address.join(",")
This gave me a script failure that address.join was not a function
I tried including under each if statement:
var email = "jstipton#yanceync.net";
var subject = "All-Call Request";
MailApp.sendEmail(email, subject, message);
This resulted in still only one email being sent to the first option chosen, regardless of how many were chosen after it.
Thank you in advance for your willingness to assist me!
If you have included,under each if statement, theMailApp.sendEmail code and only 1 email is send, that's because your are entering in only one condition.
But why announce match only 1 condition ? I believe there is only one value announce='Week in Pics' (or equivalent) passed into the sendFormByEmail(e) function.
So be sure that announce have a value like "School Intercom Announcement MHHS Website "
Just for you information, there is a lot to say about your code :
The way value is affected into address field (several var address) is not so good. You used array, that's a perfect start, but to add data into an array, it's the push method :
// 🔴 what you use
var address = []; // address = [] an array
var address = "mhhsmedia#yanceync.net"; // address = "mhhsmedia#yanceync.net" a string
var address = "heritagecougars#yanceync.net"; // address = "heritagecougars#yanceync.net" a string
// 🟢 what work
var address = []; // address = [] an array
address.push("mhhsmedia#yanceync.net"); // address = ["mhhsmedia#yanceync.net"] an array of string
address.push("heritagecougars#yanceync.net"); // address = ["mhhsmedia#yanceync.net","heritagecougars#yanceync.net"] an array of string
// So your code can look like as bellow
// ...
var address = [];
if(announce.match('School Intercom Announcement')){
address.push("mhhsmedia#yanceync.net");
subject.push("School Announcement Request");
}
if(announce.match('MHHS Website')){
address.push("heritagecougars#yanceync.net");
subject.push("Website posting request");
}
// ...
for (var email in address){
var subjectToSend = subject.pop()
//...
}
As improvement, you can use switch switch statement, that is far more easier to read than several if.
Finally, match is for regex, if you never heard of such thing have a look, it's a life changer.

script.google.com error: TypeError: Cannot read property 'values' of undefined [duplicate]

This question already has answers here:
How can I test a trigger function in GAS?
(4 answers)
Closed 4 months ago.
I am trying to use a form submit to automatically complete a google doc template I have created. But I keep getting the error TypeError: Cannot read property 'values' of undefined, I am a complete newbie, can someone help me please?
function autoFillGoogleDocFromForm(e) {
//e.values is an array of form values
var timestamp = e.values[0];
var EmailAddress = e.values[1];
var CallReportWriter = e.values[2];
var DateOfMeeting = e.values[3];
var NameOfTheCustomerProspect = e.values[4];
var ContactNameFromClient = e.values[5];
var TitleandContacts = e.values[6];
var PresentfromSesomo = e.values[7];
var MeetingObjectives = e.values[8];
var MeetingResult = e.values[9];
var Background = e.values[10];
var Opportunities = e.values[11];
var Followuprequired = e.values[12];
var Responsible = e.values[13];
var Targetdates = e.values[14];
//file is the template file, and you get it by ID
var file = DriveApp.getFileById('12zJTxLgy_Nmxk1FScyZ3vqHzYnKQ55ckdQ8RsYy-MdA');
//We can make a copy of the template, name it, and optionally tell it what folder to live in
//file.makeCopy will return a Google Drive file object
var folder = DriveApp.getFolderById('1SorfCjOGknFVt1ch39MJ7atBorLf_Sdr')
var copy = file.makeCopy(DateOfMeeting + ',' + NameOfTheCustomer/Prospect, CallReport);
//Once we've got the new file created, we need to open it as a document by using its ID
var doc = DocumentApp.openById(copy.getId());
//Since everything we need to change is in the body, we need to get that
var body = doc.getBody();
//Then we call all of our replaceText methods
body.replaceText('{{MeetingDate}}', DateOfMeeting);
body.replaceText('{{NameOfCustomer}}', NameOfTheCustomer/Prospect);
body.replaceText('{{ReportWriterName}}', CallReportWriter);
body.replaceText('{{ContactNameFromClient}}', ContactNameFromClient);
body.replaceText('{{TitleAndContact}}', TitleandContacts);
body.replaceText('{{PresentFromSesomo}}', PresentfromSesomo);
body.replaceText('{{MeetingObjectives}}', MeetingObjectives);
body.replaceText('{{MeetingResults}}', MeetingResult);
body.replaceText('{{Background}}', Background);
body.replaceText('{{Opportunities}}', Opportunities);
body.replaceText('{{FollowUpRequired}}', Followuprequired);
body.replaceText('{{Responsible}}', Responsible);
body.replaceText('{{TargetDate}}', Targetdates);
//Lastly we save and close the document to persist our changes
doc.saveAndClose();
}
Open the script editor of the sheet where the form response is landing
//
function onFormSubmit(e) {
var resp = e.source.getActiveSheet().getRange(e.range.rowStart,1, e.range.rowStart,14 ).getValues();
var timestamp = resp[0][0];
var EmailAddress = resp[0][1];
var CallReportWriter = resp[0][2];
var DateOfMeeting = resp[0][3];
// continue your code - I have not tested it
}
In script editor, you have to install the on-form-submit trigger
Then as soon as form response lands, your code will run and do whatever you want.

Making a list using api in google sheets

I am attempting to pull faction information from torns api but it puts all data into a single cell rather than listing. heres what ive got so far.
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Faction members')
.addItem('Pulls faction member info','callNumbers')
.addToUi();
}
function callNumbers() {
var response = UrlFetchApp.fetch("https://api.torn.com/faction/42911?selections=basic&key=xFtPCG2ygjbhmKWI");
Logger.log(response.getContentText());
var fact = response.getContentText();
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(1,2).setValue([fact]);
}```
You could try to parse the information using JSON.parse. Something like:
function callNumbers() {
var response = UrlFetchApp.fetch("https://api.torn.com/faction/42911?selections=basic&key=xFtPCG2ygjbhmKWI");
Logger.log(response.getContentText());
var fact = response.getContentText();
var myObject = JSON.parse(fact);
// define an array of all the object keys
var headerRow = Object.keys(myObject);
// define an array of all the object values
var row = headerRow.map(function(key){ return myObject[key]});
// define the contents of the range
var contents = [
headerRow,
row
];
// select the range and set its values
var ss = SpreadsheetApp.getActive();
var rng = ss.getActiveSheet().getRange(1, 1, contents.length, headerRow.length )
rng.setValues(contents)
}

Issues with textfinder and IF

I have a piece of code that was scrounged together from another code that is known working. What it does is searches a column using textfinder for a value, in this case, yesterday's date, if nothing is found, it should send an email.
function findAndSendMail() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('FormResponses');
var ss2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('AlertDate');
var search = ss2.getRange("B2").getValue(); //cell has yesterday's date
var lastRow = ss.getLastRow();
var range = ss.getRange(1,4,lastRow); //define range for column D, column D contains dates
//find all occurrences of search key in column D and push range to array
var ranges = range.createTextFinder(search).findAll();
if (ranges!==null) {
var message = '';
}else {
var message = 'Test';
}
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("EmailGroup").getRange("A1");
var emailAddress = emailRange.getValues();
var subject = 'Subject';
var link = "blahblahblah"
if (message) {
MailApp.sendEmail(emailAddress, subject, '**This is an automated message**\n\n' + message + '\n\n**This is an automated message**\n' + link);
}
}
As you see, it should search column D, then, if it finds something, the message variable will be blank, else if it finds nothing, it will send an email to the email addresses chosen. I'm not sure how the results from a textfinder work with this and I think the way it is written is incorrect. Any help is appreciated, unfortunately, I cannot share the document in question as my company doesn't allow sharing outside of the domain. Thank you!
Try this:
You will need to update the sheet names I moved them to end of the line comments
function findAndSendMail() {
var ss=SpreadsheetApp.getActive()
var sh1=ss.getSheetByName('Sheet1');//FormResponses
var sh2=ss.getSheetByName('Sheet2');//AlertDate
var d1=new Date(sh2.getRange("B2").getValue()); //cell has yesterday's date
var d2=new Date(d1.getFullYear(),d1.getMonth(),d1.getDate()).valueOf();
var rg1 = sh1.getRange(1,4,sh1.getLastRow(),1);
var vA=rg1.getValues().map(function(r){
var dt=new Date(r[0]);
var dtv=new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()).valueOf();
return dtv;
});
if(vA.indexOf(d2)==-1) {
var message='test';
var emailAddress = ss.getSheetByName("Sheet3").getRange("A1").getValue();//EmailGroup
var subject = 'Subject';
var link = "blahblahblah"
}
if (message) {
MailApp.sendEmail(emailAddress, subject, '**This is an automated message**\n\n' + message + '\n\n**This is an automated message**\n' + link);
//SpreadsheetApp.getUi().alert('I found something');//just for testing
}
}
This version sends an email if yesterday is not found.
In answer to you last question:
function findAndSendMail() {
var ss=SpreadsheetApp.getActive()
var sh1=ss.getSheetByName('Sheet1');//FormResponses
var sh2=ss.getSheetByName('Sheet2');//AlertDate
var d1=new Date(sh2.getRange("B2").getValue()); //cell has yesterday's date
if(isDate(d1)) {
var d2=new Date(d1.getFullYear(),d1.getMonth(),d1.getDate()).valueOf();
var rg1 = sh1.getRange(1,4,sh1.getLastRow(),1);
var vA=rg1.getValues().map(function(r){
var dt=new Date(r[0]);
var dtv=new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()).valueOf();
return dtv;
});
if(vA.indexOf(d2)==-1) {
var message='test';
var emailAddress = ss.getSheetByName("Sheet3").getRange("A1").getValue();//EmailGroup
var subject = 'Subject';
var link = "blahblahblah"
}
if (message) {
MailApp.sendEmail(emailAddress, subject, '**This is an automated message**\n\n' + message + '\n\n**This is an automated message**\n' + link);
//SpreadsheetApp.getUi().alert('I found something');//just for testing
}
}else{
SpreadsheetApp.getUi().alert('Data is sheet2!B2 is not a date')
return;
}
}
function isDate(date){
return(Object.prototype.toString.call(date) === '[object Date]');
}

How to find and replace date, on timebased trigger by using ScriptApp Custom function

I have a Google Document with only one date in the body of the document. I am trying to write a script that updates the date every 24 hours.
The date in the document is currently set to "11/01/2016" as text, 1 day less than today (12/01/2016). I assumed using a replaceText() would work.
This is my script at the moment.
ScriptApp.newTrigger("myFunction")
.timeBased()
.atHour(24)
.everyDays(1)
.inTimezone("GMT")
function myFunction()
{
var date = Utilities.formatDate(new Date(), "GMT", "dd/MM/yyy");
var doc = DocumentApp.openById("ID of Document");
doc.replaceText(date-1,date) ;
}
What I am doing wrong here?
You can't replace text on document object, you need to get document body. your date is a string, you can't get yesterday by date-1. refer the date conversion too.
function myFunction()
{
var body = DocumentApp.getActiveDocument().getBody();
var d = new Date();
var yesterdayDate = Utilities.formatDate(new Date(d.getTime()-1*(24*3600*1000)), "GMT", "dd/MM/yyy");
var todayDate = Utilities.formatDate(d, "GMT", "dd/MM/yyy");
body.replaceText(yesterdayDate,todayDate) ;
}