I am trying to create a script to automatically take information from a google sheet and put each row of data into individual, formatted docs. However when I run the script it either populates the data as "DOB" (in the date of birth spot) or as a different value. I am not a very good programmer and any help is appreciated. Thanks,
function createDocument() {
var headers =Sheets.Spreadsheets.Values.get('1oycOOxDIAhbAI6Yq54KF4GAnjfVcttywYXOpKDBLHag', ('A1', 'B1', 'C1', 'D1', 'H1', 'I1', 'N1', 'O1'));
var tactics = Sheets.Spreadsheets.Values.get('1oycOOxDIAhbAI6Yq54KF4GAnjfVcttywYXOpKDBLHag', ('A4:O14'));
var templateId = '1NJQHx4TWRQ3EQle5aLr-QV4uqD-tSR8TMP2-f6QjPmY';
for(var i = 0; i < tactics.values.length; i++){
var Patient_name = tactics.values[i][0];
var Date_Scheduled = tactics.values[i][0];
var Surgery_Posting = tactics.values[i][0];
var Start_Time = tactics.values[i][0];
var Hospital = tactics.values[i][0];
//Make a copy of the template file
var documentId = DriveApp.getFileById(templateId).makeCopy().getId();
//Rename the copied file
DriveApp.getFileById(documentId).setName(Patient_name + ' Surgery Posting');
//Get the document body as a variable
var body = DocumentApp.openById(documentId).getBody();
//Insert the Patient_name
body.replaceText('##Patient_name##', Patient_name)
//Insert the Date_Scheduled
body.replaceText('##Date_Scheduled##', Date_Scheduled)
//Insert the Surgery_Posting
body.replaceText('##Surgery_Posting##', Surgery_Posting)
//Insert the Start_Time
body.replaceText('##Start_Time##', Start_Time)
//Insert the Hospital
body.replaceText('##Hospital##', Hospital)
//Append tactics
parseTactics(headers.values[0], tactics.values[i], body);
}
}
function parseTactics(headers, tactics, body){
for(var i = 0; i < tactics.length; i++){
{tactics[i] != '' &&
body.appendListItem(headers[i] + ' | ' + tactics[i] + ' net').setGlyphType(DocumentApp.GlyphType.BULLET);
}
}
}
The column position after the iterator was not changed to the next column.
var Patient_name = tactics.values[i][0];
var Date_Scheduled = tactics.values[i][1]; //this last part the 0 to 1
Related
Reference to the previous question to Filter Gmail body and paste in Spreadsheet
I had created below a google app script and set a trigger for after every 5 minutes:
function GetEmailsData(){
// SKIP TO OUT OF OFFICE HOURS AND DAYS
var nowH=new Date().getHours();
var nowD=new Date().getDay();
if (nowH>19||nowH<8||nowD==0) { return }
// START OPERATION
var Gmail = GmailApp;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var MasterSheet = ss.getSheetByName("Master");
var index = 2;
var aa = 0; // count already update entries
var na = 0; // count not update entries
var lasttime = MasterSheet.getRange("Z1").getValue(); // in spreadsheet i record the last time of email scanned, so next trigger will search after that
Logger.log(lasttime);
var cdate = new Date();
var ctime = cdate.getTime();
var qDate = MasterSheet.getRange("Z1").getValue();
Logger.log("QDATE IS " + qDate);
//problem # 1: from filter is not working.
// SEARCH EMAIL
var query = 'from: email id, subject: email subject, after:' + Math.floor((qDate.getTime()) /1000);
var threadsNew = Gmail.search(query);
Logger.log(threadsNew.length);
//loop all emails
for(var n in threadsNew){
var thdNew = threadsNew[n];
var msgsNew = thdNew.getMessages();
var msgNew = msgsNew[msgsNew.length-1];
// GET ATTACHMENT
//var bodyNew = msgNew.getBody();
var plainbody = msgNew.getPlainBody();
var subject = msgNew.getSubject();
var Etime = msgNew.getDate();
//var attachments = msgNew.getAttachments();
//var attachment = attachments[0];
Logger.log(Etime);
Logger.log(subject);
//Logger.log(plainbody);
var tdata = plainbody.trim();
var data = parseEmail001(tdata);
//Logger.log(data);
// First Check Email Date
var newdate = new Date();
var dd = newdate.getDate();
var mm = newdate.getMonth() + 1;
var yyyy = newdate.getFullYear();
var cd = dd + "-" + mm + "-" + yyyy
//Logger.log(new Date());
//Logger.log(cd);
if (Etime.getDate() != dd) {return}
// first check current sheet exist or not
// DATE DECLARATION IS ABOVE
var itt = ss.getSheetByName(cd);
if (!itt) {
ss.insertSheet(cd);
var itt = ss.getSheetByName(cd);
var ms = ss.getSheetByName("Master");
var hlc = ms.getLastColumn();
var headings = ms.getRange(1,1,1,hlc).getValues();
itt.getRange(1,1,1,hlc).setValues(headings);
}
var MasterSheet = ss.getSheetByName(cd);
var mlr = MasterSheet.getLastRow();
var mlc = MasterSheet.getLastColumn();
//check data already updated or not
var NewDepositSlipNumber = Number(data[2]).toFixed(0);
//Logger.log(Number(data[2]).toFixed(0));
var olddata = MasterSheet.getDataRange().getValues();
//Logger.log(olddata[1][2]);
for(var i = 0; i<olddata.length;i++){
if(olddata[i][2] == NewDepositSlipNumber){
//Logger.log(i + 1);
var status = 'Already Update'
Logger.log(status);
break;
}
else{
var status = 'Not Update'
//Logger.log(status);
}
}
// count how many updated and how many not.
if(status == 'Not Update'){
na = na + 1;
}
else{
aa = aa + 1;
}
if(status == 'Not Update'){
MasterSheet.appendRow(data);
Logger.log("Data Updated");
}
}
//problem # 2: if conversation length are long, it is not reaching there
var lastscantime = threadsNew[0].getLastMessageDate();
var master = ss.getSheetByName("Master");
master.getRange("Z1").setValue(lastscantime);
Logger.log(lastscantime);
master.getRange("Z2").setValue(new Date());
Logger.log(new Date());
Logger.log("Total " + threadsNew.length + " found, out of which " + aa + " are already updated, while " + na + " are updated.");
}
function parseEmail001(message) {
var replaces = [
'Branch Code',
'Branch Name',
'Slip No',
'BL Number',
'Type Of Payment',
'Customer Name',
'Payer Bank',
'Payer Bank Branch',
'Transaction Type',
'Amount',
'Posting Date',
'Value Date'
];
return message.split('\n').slice(0, replaces.length)
.map((c,i) => c.replace(replaces[i], '').trim());
}
This script is working fine but I have two problems:
I placed three filters in query 1) from 2) subject 3) after
but sometimes it gives me emails that are from the same ID but different subject.
as per my observation, and I verified it by using debug mode if the conversation length is long I guess more than 30 it will not reach the end part of the script. it skipping my last step as I also marked it in the above script. and if conversation length is less it works smoothly.
explanation: in other words, from morning to evening it's working fine after every five minutes, but the next day it gets the problem, then I manually update my spreadsheet master sheet Z1 value as of today's date and time, then it works fine till tonight.
You might be reaching a script limitation. Possibly the custom function runtime.But it can be any, you should see an error if it didn't finish.
As part of a student attendance system, I would like to add a color stripe to every last row of a class for attendance using App Scripts. My columns of Google Sheets are: (i) Date, (ii) Email, (iii) Latitude, (iv) Longitude, and (v) Subject-code. Tried many ways but did not find the solution.
var sss = SpreadsheetApp.getActiveSpreadsheet();
var ssID = sss.getId();
var sheetName = sss.getName();
var sheet = sss.getSheetByName("TempDataSet");
var sheet1 = sss.insertSheet('TempDataSet_temp');
sheet.getDataRange().copyTo(sheet1.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
sheet.getDataRange().copyTo(sheet1.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_FORMAT, false);
var shID = sheet1.getSheetId().toString();
sheet1.getRange(2, 1, sheet.getLastRow() -1, sheet.getLastColumn()).sort({column: 1, ascending: false});
var columns_delete = [7,2]; //[7,5,4,2];
columns_delete.forEach(col=>sheet1.deleteColumn(col));
//const sss = SpreadsheetApp.getActiveSpreadsheet();
//const sheet = sss.getSheetByName("TempDataSet");
const subs = sheet.getRange('F2:F'+sheet.getLastRow()).getValues().flat();
const usubs = subs.filter((value, index, self)=>self.indexOf(value) === index);
const dts = sheet.getRange('A2:A'+sheet.getLastRow()).getDisplayValues().flat();
const udts = dts.filter((value, index, self)=>self.indexOf(value) === index);
if(usubs.length>1){
subs.forEach((s,i)=>{
if(i>1){
if(subs[i]!=subs[i-1]){
sheet.getRange(i+1,1,1,5).setBackground('yellow');
}}});
}
else if (udts.length>1){
dts.forEach((d,i)=>{
if(i>1){
if(dts[i]!=dts[i-1]){
sheet.getRange(i+1,1,1,5).setBackground('yellow');
}}});
}
var from = Session.getActiveUser().getEmail();
var subject = 'Batch Attendance Record for Your Reference';
var body = 'Dear Student,'+ '\n\n' + 'Greetings! Please find the batch attendance record attached. Stay safe and blessed.' + '\n\n' + 'Thank you.';
var requestData = {"method": "GET", "headers":{"Authorization":"Bearer "+ScriptApp.getOAuthToken()}};
var url = "https://docs.google.com/spreadsheets/d/"+ ssID + "/export?format=xlsx&id="+ssID+"&gid="+shID;
var result = UrlFetchApp.fetch(url , requestData);
var contents = result.getContent();
sss.deleteSheet(sss.getSheetByName('TempDataSet_temp'));
var sheet2 = sss.getSheetByName('StudentList');
var data = sheet2.getLastRow();
var students = [];
var students = sheet2.getRange(2, 6, data).getValues();
//MailApp.sendEmail(students.toString(), subject ,body, {attachments:[{fileName:sheetName+".xlsx", content:contents, mimeType:"MICROSOFT_EXCEL"}]});
for (var i=0; i<students.length; i++){ // you are looping through rows and selecting the 1st and only column index
if (students[i][0] !== ''){
MailApp.sendEmail(students[i][0].toString(), subject ,body, {attachments:[{fileName:sheetName+".xlsx", content:contents, mimeType:"MICROSOFT_EXCEL"}]});
//MailApp.sendEmail(students[i][0].toString(), subject ,body, {from: from, attachments:[{fileName:"YourAttendaceRecord.xlsx", content:contents, mimeType:"MICROSOFT_EXCEL"}]});
}
}
Explanation:
Based on your question, I understand the following steps:
Check if you have at least two unique subjects in column E. One way to do that is to find the unique list of subjects. If the length of that list is 2 or more it means that you have different subjects. In that case, the first block of the if statement evaluates to true and you add a yellow line in the row before the subject is changed.
If you have only one subject, namely the length of the unique list of subjects is 1 the first block of the if statement will evaluate to false. In that case, the script will check whether column A has 2 or more unique dates. If it does, the second block of the if statement will be executed and the script will add a yellow line in the row before the date is changed. Otherwise, it won't do anything.
Solution:
You can execute color() as a standalone script. I would advice you to save this function in a new .gs file and then simply call it within your current script. Namely, put color() anywhere you want in the code snippet you provided.
function color() {
const sss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = sss.getSheetByName("TempDataSet");
const subs = sheet.getRange('E2:E'+sheet.getLastRow()).getValues().flat();
const usubs = subs.filter((value, index, self)=>self.indexOf(value) === index);
const dts = sheet.getRange('A2:A'+sheet.getLastRow()).getDisplayValues().flat();
const udts = dts.filter((value, index, self)=>self.indexOf(value) === index);
if(usubs.length>1){
subs.forEach((s,i)=>{
if(i>1){
if(subs[i]!=subs[i-1]){
sheet.getRange(i+1,1,1,5).setBackground('yellow');
}}});
}
else if (udts.length>1){
dts.forEach((d,i)=>{
if(i>1){
if(dts[i]!=dts[i-1]){
sheet.getRange(i+1,1,1,5).setBackground('yellow');
}}});
}
}
Complete Solution:
function sendEmails(){
var sss = SpreadsheetApp.getActiveSpreadsheet();
var ssID = sss.getId();
var sheetName = sss.getName();
var sheet = sss.getSheetByName("TempDataSet");
var sheet1 = sss.insertSheet('TempDataSet_temp');
sheet.getDataRange().copyTo(sheet1.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
sheet.getDataRange().copyTo(sheet1.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_FORMAT, false);
var shID = sheet1.getSheetId().toString();
sheet1.getRange(2, 1, sheet.getLastRow() -1, sheet.getLastColumn()).sort({column: 1, ascending: true});
var columns_delete = [7,2]; //[7,5,4,2];
columns_delete.forEach(col=>sheet1.deleteColumn(col));
SpreadsheetApp.flush();
const subs = sheet1.getRange('E2:E'+sheet1.getLastRow()).getValues().flat();
const usubs = subs.filter((value, index, self)=>self.indexOf(value) === index);
const dts = sheet1.getRange('A2:A'+sheet1.getLastRow()).getDisplayValues().flat();
const udts = dts.filter((value, index, self)=>self.indexOf(value) === index);
if(usubs.length>1){
subs.forEach((s,i)=>{
if(i>1){
if(subs[i]!=subs[i-1]){
sheet1.getRange(i+1,1,1,5).setBackground('yellow');
}}});
}
else if (udts.length>1){
dts.forEach((d,i)=>{
if(i>1){
if(dts[i]!=dts[i-1]){
sheet1.getRange(i+1,1,1,5).setBackground('yellow');
}}});
}
SpreadsheetApp.flush();
var from = Session.getActiveUser().getEmail();
var subject = 'Batch Attendance Record for Your Reference';
var body = 'Dear Student,'+ '\n\n' + 'Greetings! Please find the batch attendance record attached. Stay safe and blessed.' + '\n\n' + 'Thank you.';
var requestData = {"method": "GET", "headers":{"Authorization":"Bearer "+ScriptApp.getOAuthToken()}};
var url = "https://docs.google.com/spreadsheets/d/"+ ssID + "/export?format=xlsx&id="+ssID+"&gid="+shID;
var result = UrlFetchApp.fetch(url , requestData);
var contents = result.getContent();
sss.deleteSheet(sss.getSheetByName('TempDataSet_temp'));
var sheet2 = sss.getSheetByName('StudentList');
var data = sheet2.getLastRow();
var students = [];
var students = sheet2.getRange(2, 6, data).getValues();
//MailApp.sendEmail(students.toString(), subject ,body, {attachments:[{fileName:sheetName+".xlsx", content:contents, mimeType:"MICROSOFT_EXCEL"}]});
for (var i=0; i<students.length; i++){ // you are looping through rows and selecting the 1st and only column index
if (students[i][0] !== ''){
MailApp.sendEmail(students[i][0].toString(), subject ,body, {attachments:[{fileName:sheetName+".xlsx", content:contents, mimeType:"MICROSOFT_EXCEL"}]});
//MailApp.sendEmail(students[i][0].toString(), subject ,body, {from: from, attachments:[{fileName:"YourAttendaceRecord.xlsx", content:contents, mimeType:"MICROSOFT_EXCEL"}]});
}
}
}
I have a simple app in which users complete some basic details of a meeting in a google sheet and then export these to their google calendar. Script as follows:
function exportEvents() {
var sheet = SpreadsheetApp.getActiveSheet();
var headerRows = 1;
var range = sheet.getDataRange();
var data = range.getValues();
// var calId = sheet.getRange("H2:H2").getValue();
var calId = "xxxxxxxxxxxx";
var cal = CalendarApp.getCalendarById(calId);
for (i=0; i<data.length; i++) {
if (i < headerRows) continue;
var row = data[i];
var date = new Date(row[1]);
var title = row[2];
var initial = row[0];
var concatTitle = initial + " - " + title;
var tstart = new Date(row[3]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
// var tstop = new Date(row[4]);
var tstop = new Date(tstart + row[4]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var loc = row[5];
var desc = row[6];
var id = row[7];
try {
var event = cal.getEventSeriesById(id);
}
catch (e) {
// do nothing - we just want to avoid the exception when event doesn't exist
}
if (!event) {
var newEvent = cal.createEvent(concatTitle, tstart, tstop, {description:desc,location:loc}).getId();
row[7] = newEvent;
}
else {
event.setTitle(concatTitle);
event.setDescription(desc);
event.setLocation(loc);
var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1);
event.setRecurrence(recurrence, tstart, tstop);
}
debugger;
}
range.setValues(data);
}
The whole thing works great, except for when the user puts more than 60 mins as the length of the meeting in column 4. Anything up to 59 mins works great and the event is logged with the correct start and end time. However, when I enter 60 or more mins, the error reads 'Event start time must be before event end time."
I'm sure I'm doing something very simple very wrong, but any help would be greatly appreciated.
I've been searching for the answer to this question but have so far been unable to piece together the answer. Please explain any answer you have in really simple terms as I'm fairly new to GAS and RegEx. I've got most of the syntax down but the execution of it in GAS is giving me a hard time.
Basically, I want to write a script that, when the spreadsheet is edited, checks which rows have yet to be merged. Then, on those rows, creates a copy of a template Google Doc and names the document based on the spreadsheet data. From there (this is the hard part), I need it to replace merge tags in the template with the data from the spreadsheet.
The tags in the templates I'll be using look like this: <<mergeTag>>
My idea was to match the whole tag, and replace it with data from the spreadsheet that exists in the column with the same name as what's inside the "<<>>". Ex: <<FooBar>> would be replaced with the data from the column named FooBar. It would obviously be from the current row that needs the merging.
After that, all that's left is to send an email (a few more row-specific personalization) with that document attached (sometimes as a PDF) with the body of the message coming from an HTML file elsewhere in the project.
This is the whole thing I have so far (notice the placeholders here and there that I can personalize for each spreadsheet I use this for):
function onEdit() {
//SPREADSHEET GLOBAL VARIABLES
var ss = SpreadsheetApp.getActiveSpreadsheet();
//get only the merge sheet
var sheet = ss.getSheetByName("Merge Data");
//get all values for later reference
var range = sheet.getActiveRange();
var values = range.getValues();
var lastRow = range.getLastRow();
var lastColumn = range.getLastColumn();
//get merge checker ranges
var urlColumn = range.getLastColumn();
var checkColumn = (urlColumn - 1);
var checkRow = range.getLastRow();
var checkRange = sheet.getRange(2, checkColumn, checkRow);
var check = checkRange.getBackgrounds();
//get template determination range (unique to each project)
var tempConditionRange = sheet.getRange(row, column);
var tempConditionCheck = tempConditionRange.getValues();
//set color variables for status cell
var red = "#FF0000";
var yellow = "#FFCC00";
var green = "#33CC33";
//////////////////////////////////////////////////////////
//DOC GLOBAL VARIABLES
var docTemplate1 = DriveApp.getFileById(id);
var docTemplate2 = DriveApp.getFileById(id);
var docTemplate3 = DriveApp.getFileById(id);
var folderDestination = DriveApp.getFolderById(id);
//////////////////////////////////////////////////////////
//EMAIL GLOBAL VARIABLES
var emailTag = ss.getRangeByName("Merge Data!EmailTag");
var personalizers = "";
var subject = "" + personalizers;
var emailBody = HtmlService.createHtmlOutputFromFile("Email Template");
//////////////////////////////////////////////////////////
// MERGE CODE
for (i = 0; i < check.length; i++) {
//for rows with data, check if they have already been merged
if (check[i] == green) {
continue;
} else {
var statusCell = sheet.getRange((i+2), checkColumn, 1, 1);
var urlCell = sheet.getRange((i+2), urlColumn, 1, 1);
var dataRow = sheet.getRange((i+2), 1, lastRow, (lastColumn - 2))
statusCell.setBackground(red);
//for rows with data, but not yet merged, perform the merge code
//////////////////////////////////////////////////////////
//DOC CREATION
//Determine which template to use
if (tempConditionCheck[i] == "") {
var docToUse = docTemplate1;
}
if (tempConditionCheck[i] == "") {
var docToUse = docTemplate2;
}
if (tempConditionCheck[i] == "") {
var docToUse = docTemplate3;
}
//Create a copy of the template
//Rename the document using data from specific columns, at specific rows
//Move the doc to the correct folder
var docName = "";
var docCopy = docToUse.makeCopy(docName, folderDestination);
var docId = docCopy.getId();
var docURL = docCopy.getUrl();
var docToSend = DriveApp.getFileById(docId);
var docBody = DocumentApp.openById(docId).getBody();
Here's where I need the help
//Locate the Merge Tags
//Match Merge Tags to the column headers of the same name
//Replace the Merge Tags with the data from the matched column, from the correct row
function tagReplace() {
var tagMatch = "/(<{2}(\w+)>{2})/g";
}
statusCell.setBackground(yellow);
urlCell.setValue(docURL);
The rest is just finishing up the process
//////////////////////////////////////////////////////////
//EMAIL CREATION
//Create an email using an HTML template
//Use Merge Tags to personalize email
//Attach the doc we created to the email
//Send email to recipients based on data in the sheet
MailApp.sendEmail(emailTag, subject, emailBody, {
name: "Person McPerson",
attachments: [docToSend], //[docToSend.getAs(MIME.PDF)],
html: emailBody,
});
//////////////////////////////////////////////////////////
//CHECK ROW UPDATE
statusCell.setBackground(green);
}
}
}
My sheets all have a frozen first row that acts as the header row. All my columns will be consistently named the exact same thing as the tags (minus the <<>>).
How do I match the tags to the data?
EDIT
```````````````````
The solution did not work as described when I inserted it into my code as follows:
function formMerge() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Merge Data");
var urlColumn = sheet.getMaxColumns();
var checkColumn = urlColumn - 1;
var lastRow = ss.getSheetByName("Form Responses").getLastRow();
var values = sheet.getDataRange().getValues();
var headers = values[0];
var urlRange = sheet.getRange(2, urlColumn, lastRow);
var checkRange = sheet.getRange(2, checkColumn, lastRow);
var check = checkRange.getBackgrounds();
var red = "#ff0404";
var yellow = "#ffec0a";
var green = "#3bec3b";
var docTemplate = DriveApp.getFileById(id);
var folderDestination = DriveApp.getFolderById(id);
// MERGE CODE
for (i = 0; i < check.length; i++) {
if (check[i] == green) {
continue;
} else {
var statusCell = sheet.getRange((i+2), checkColumn, 1, 1);
var urlCell = sheet.getRange((i+2), urlColumn, 1, 1);
var dataRow = sheet.getRange((i+2), 1, 1, (urlColumn - 2)).getValues();
var clientNameRange = sheet.getRange((i+2), 3);
var clientName = clientNameRange.getValue();
var dateRange = sheet.getRange((i+2), 2);
var datePreFormat = dateRange.getValue();
var timeZone = CalendarApp.getTimeZone();
var date = Utilities.formatDate(new Date(datePreFormat), timeZone, "MM/dd/yyyy");
statusCell.setBackground(red);
//EMAIL VARIABLES
var personalizers = clientName;
var subject = "Post Intake Report for " + personalizers;
var emailBody = "Please see the attached Google Doc for the Post Intake Report for " + clientName + ". The intake was performed on " + date + ".";
var emailTagRange = sheet.getRange((i+2), 24);
var emailTagValue = emailTagRange.getValue();
var emailTag = emailTagValue.split(", ");
//DOC CREATION
var docToUse = docTemplate;
var docName = "Post Intake Report - " + clientName + " [" + date + "]";
var docCopy = docToUse.makeCopy(docName, folderDestination);
var docId = docCopy.getId();
var docURL = docCopy.getUrl();
var docBody = DocumentApp.openById(docId).getBody().editAsText();
for (var j=0; j<headers.length; j++) {
var re = new RegExp("(<<"+headers[j]+">>)","g");
docBody.replaceText(re, dataRow[j]);
}
statusCell.setBackground(yellow);
urlCell.setValue(docURL);
//EMAIL CREATION
MailApp.sendEmail(emailTag, subject, emailBody, {
name: "Christopher Anderson",
attachments: [docCopy],
html: emailBody
});
statusCell.setBackground(green);
}
}
}
Build the RegExp for each tag on the fly, using the header values from your spreadsheet.
Use Body.replaceText() to perform the replacements.
var values = sheet.getDataRange().getValues();
var headers = values[0];
...
// Loop over all columns. Use header names to search for tags.
for (var col=0; col<headers.length; col++) {
// Build RegExp using column header
var re = new RegExp("(<{2}"+headers[col]+">{2})","g");
// Replace tags with data from this column in dataRow
body.replaceText(re, dataRow[col]);
}
This snippet will operate on a single row; the first couple of declarations should appear outside of your row loop. The column looping is then done after you've created and opened the new document, and obtained the body object.
It loops over all the columns in the spreadsheet, using the header names to find the tags you've defined, and replaces them with the corresponding cell contents for the current row.
I am reading JSON from a Google Spreadsheet and need help getting to the text within entry.content.$t. The text is a column named "description" in the spreadsheet. The feed for the spreadsheet is (removed)
So far, my script is
function listChapters(root) {
var feed = root.feed;
var entries = feed.entry || [];
var html = ['<ul>'];
for (var i = 0; i < entries.length; ++i) {
var chlist = entries[i];
var title = (chlist.title.type == 'html') ? chlist.title.$t : escape(chlist.title.$t);
var chapters = chlist.content.$t;
html.push('<li>', chapters, '</li>');
}
html.push('</ul>');
document.getElementById("chapterlist").innerHTML = html.join("");
}
The question is - How do I read "description" from $t to place in the var chapters?
The text within chlist.content.$t is almost, but not quite, properly formatted JSON. Since it's not properly formatted, you cannot use JSON.parse() to create an object that you could then get a description property from.
Here's a brute-force approach that will extract the description, used in place of the original html.push('<li>', chapters, '</li>');:
// Get the text between 'description: ' and 'Chapter website:'
var descStart = chapters.indexOf('description:')+13; //+length of 'description: '
var descEnd = chapters.indexOf('Chapter website:');
var description = chapters.substring(descStart,descEnd);
html.push('<li>', description, '</li>');
Tested with this, checking results in debugger:
function test() {
var url = '---URL---';
var result = UrlFetchApp.fetch(url);
var text = result.getContentText();
var bodytext = Xml.parse(text,true).html.body.getText();
var root = JSON.parse(bodytext);
listChapters(root);
}