Problem
I'm trying to using twitter intent to tweet out a pre-written, custom tweet. But when I click fa-twitter the box appears blank. I think the problem may be how I'm encoding the URL?
scripts.js
function shareTeam(){
$(".fa-twitter").click(function(){
// Create an empty array
var teasers = [];
// Grabs the names of all the players in the span
// Sets a variable marking the indexOf each of the names
// If the index doesn't find a space, it returns -1, which returns the full name
// Otherwise it will return only what follows the space
var lastNames = $("li span").map(function() {
var name = $(this).text();
var index = name.indexOf(" ");
return index == -1 ? name : name.substring(index + 1);
}).get();
// console.log(lastNames);
// var regularNames = lastNames.slice(0, 3); // Same as below, but no shuffling
var regularNames = lastNames;
regularName1 = regularNames[0]; // Forward
regularName2 = regularNames[1]; // Forward
regularName3 = regularNames[2]; // Defenseman
regularName4 = regularNames[3]; // Defenseman
regularName5 = regularNames[4]; // Defenseman
regularName6 = regularNames[5]; // Goalie
// Find me a random number between 1 and 3
// Where 1 is the start number and 3 is the number of possible results
// This is zero-indexed? So the numbers will be one lower than the actual teaser #
var teaser = "teaser";
var rand = Math.floor(Math.random() * 6);
console.log(rand);
// Concatenate the two strings together
teaseRand = teaser.concat(rand);
// These are the components that make up that fullURL
var baseURI = "https://twitter.com/intent/tweet?";
var twitterUsername = "#stltoday";
var interactiveURL = "http://staging.stltoday.com/STLblues";
// Randomly generate one of three teasers
var teaser1 = regularName3 + " to " + regularName2 + " back to " + regularName1 + " — GOAL! Create your own all-team #STLBlues team: ";
var teaser2 = "My #STLBlues dream team has " + regularName3 + " and " + regularName4 + ". Build your own: ";
var teaser3 = "My #STLBlues dream team has " + regularName4 + " and " + regularName5 + ". Build your own: ";
var teaser4 = "My #STLBlues team will skate circles around yours! Pick your team: ";
var teaser5 = regularName6 + " with the glove save! ";
var teaser6 = "Pick your #STLBlues dream team from 50 of the best #StLouisBlues to hit the ice: ";
// Push teasers into array
teasers.push(teaser1);
teasers.push(teaser2);
teasers.push(teaser3);
teasers.push(teaser4);
teasers.push(teaser5);
teasers.push(teaser6);
// This is the full url that will be switched in and out
var fullURL = "text="+teasers[rand]+"&url="+interactiveURL+"&via=("+twitterUsername+")";
// var fullURL = interactiveURL+"&via="+twitterUsername+"&text="+teasers[rand];
console.log(fullURL);
// It needs to be encoded properly as well
var encodedURL = baseURI+encodeURIComponent(fullURL);
// Change the href to the link every time the Twitter button is clicked
$(".link--twitter").attr("href", encodedURL);
console.log(encodedURL);
// if (lastNames.length === 6) {
// } else {
// var encodedURLGeneric = baseURI+encodeURIComponent(fullURL);
// $(".link--twitter").attr("href", encodedURLGeneric);
// }
});
}
The solution was to encode each part individually
function shareTeam(){
$(".fa-twitter").click(function(){
// Create an empty array
var teasers = [];
// Grabs the names of all the players in the span
// Sets a variable marking the indexOf each of the names
// If the index doesn't find a space, it returns -1, which returns the full name
// Otherwise it will return only what follows the space
var lastNames = $("li span").map(function() {
var name = $(this).text();
var index = name.indexOf(" ");
return index == -1 ? name : name.substring(index + 1);
}).get();
var regularNames = lastNames.slice(0, 4); // Same as below, but no shuffling
regularName1 = regularNames[0]; // Forward
regularName2 = regularNames[1]; // Forward
regularName3 = regularNames[2]; // Defenseman
regularName4 = regularNames[3]; // Defenseman
// Find me a random number between 1 and 3
// Where 1 is the start number and 3 is the number of possible results
// This is zero-indexed? So the numbers will be one lower than the actual teaser #
var teaser = "teaser";
var rand = Math.floor(Math.random() * 3);
console.log(rand);
// Concatenate the two strings together
teaseRand = teaser.concat(rand);
// These are the components that make up that fullURL
var baseURI = "https://twitter.com/intent/tweet?text=";
var twitterUsername = "stltoday";
var interactiveURL = "http://staging.stltoday.com/STLblues";
// Randomly generate one of three teasers
var teaser1 = regularName3 + " to " + regularName2 + " back to " + regularName1 + " — GOAL! Create your #STLBlues team:";
var teaser2 = "My #STLBlues dream team has " + regularName3 + " and " + regularName4 + ". Build your own:";
var teaser3 = regularName4 + " to " + regularName3 + " back to " + regularName2 + " — GOAL! Create your #STLBlues team:";
var teaser4 = "Pick your #STLBlues dream team from 50 of the best #StLouisBlues to hit the ice:";
// Push teasers into array
teasers.push(teaser1);
teasers.push(teaser2);
teasers.push(teaser3);
teasers.push(teaser4);
// This is the full url that will be switched in and out
// It needs to be encoded properly as well
var fullURL = baseURI+encodeURIComponent(teasers[rand])+"&url="+encodeURIComponent(interactiveURL)+"&via="+encodeURIComponent(twitterUsername);
var genericURL = baseURI+encodeURIComponent(teasers[3])+"&url="+encodeURIComponent(interactiveURL)+"&via="+encodeURIComponent(twitterUsername);
console.log(fullURL);
console.log(genericURL);
// Change the href to the link every time the Twitter button is clicked
$(".link--twitter").attr("href", fullURL);
console.log(fullURL);
if (lastNames.length === 6) {
console.log("Yeah, yeah, yeah");
} else {
$(".link--twitter").attr("href", genericURL);
}
});
}
Related
I'm new to Google Apps Script so I'm looking for some advice. There's multiple parts and I managed to do some of it but I'm stuck on others. Any help would be much appreciated.
I'm trying to make a script that:
drafts a reply to emails that contain specific keywords (found in the body or the subject line).
I also want it to include a template with data inputted from a Google Sheets file.
It would be preferable if the draft can be updated without making a duplicate whenever the Sheet is modified.
I plan on also including a row of values (the first one) that correspond to the Subject columns in the second row the but I haven't gotten to it yet.
Some details about the Google Sheet:
Each row corresponds to a different person and email address that regularly emails me.
The first three columns are details about the person which I include in the body of my draft.
Each column after that represents a different string or keyword I expect to find in the subject of the emails sent to me.
The rows underneath contain two patterned code-words separated by a space in one cell that I want to be able to choose from. Such as:
3 letters that can contain permutations of the letters m, g, r (for ex: mmg, rgm, rgg, gmg)
and 0-3 letters with just p's (for ex: p, pp, ppp, or blank)
I want to be able to detect the different codes and assign it to a variable I can input into my draft.
What I have so far:
I'm able to draft replies for emails within my specified filter. However, I only have it set up to reply to the person's most recent message. I want to be able for sort through the filter for specific emails that contain a keyword in the subject line when it loops through the columns.
I'm able to input static strings from the Sheet into the body of my email but I'm still having trouble with the patterned codewords.
I was able to loop through more than one row in earlier version but now it's not. I'll look over it again later.
Here's my code:
function draftEmail() {
var sheet = SpreadsheetApp.getActiveSheet(); // Use data from the active sheet
var startRow = 1; // First row of data to process
var numRows = sheet.getLastRow() - 1; // Number of rows to process
var lastColumn = sheet.getLastColumn(); // Last column
var dataRange = sheet.getRange(startRow, 1, numRows, lastColumn) // Fetch the data range of the active sheet
var data = dataRange.getValues(); // Fetch values for each row in the range
// Work through each row in the spreadsheet
for (var i = 2; i < data.length; ++i) {
var row = data[i];
// Assign each row a variable
var grader = row[0]; // Col A: Grader's name
var firstName = row[1]; // Col B: Student's first name
var studentEmail = row[2]; // Col C: Student's email
var grade = row[3].split(' '); // Col D: Grade
var pgrade = grade[1];
var hgrade = grade[0];
for (var n = 1; n < data.length; ++n) {
var srow = data[n];
var subjectCol = srow[3];
var threads = GmailApp.getUserLabelByName('testLabel').getThreads();
for (i=0; i < threads.length; i++)
{
var thread = threads[i];
var messages = thread.getMessages(); // get all messages in thread i
var lastmsg = messages.length - 1; // get last message in thread i
var emailTo = WebSafe(messages[lastmsg].getTo()); // get only email id from To field of last message
var emailFrom = WebSafe(messages[lastmsg].getFrom()); // get only email id from FROM field of last message
var emailCC = WebSafe(messages[lastmsg].getCc()); // get only email id from CC field of last message
// form a new CC header for draft email
if (emailTo == "")
{
var emailCcHdr = emailCC.toString();
} else
{
if (emailCC == "")
{
var emailCcHdr = emailTo.toString();
} else
{
var emailCcHdr = emailTo.toString() + "," + emailCC.toString();
}
}
var subject = messages[lastmsg].getSubject().replace(/([\[\(] *)?(RE|FWD?) *([-:;)\]][ :;\])-]*|$)|\]+ *$/igm,"");
// the above line remove REs and FWDs etc from subject line
var emailmsg = messages[lastmsg].getBody(); // get html content of last message
var emaildate = messages[lastmsg].getDate(); // get DATE field of last message
var attachments = messages[lastmsg].getAttachments(); // get all attachments of last message
var edate = Utilities.formatDate(emaildate, "IST", "EEE, MMM d, yyyy"); // get date component from emaildate
var etime = Utilities.formatDate(emaildate, "IST", "h:mm a"); // get time component from emaildate
if (emailFrom.length == 0)
{
// if emailFrom is empty, it probably means that you may have written the last message in the thread. Hence 'you'.
var emailheader = '<html><body>' +
'On' + ' ' +
edate + ' ' +
'at' + ' ' +
etime + ',' + ' ' + 'you' + ' ' + 'wrote:' + '</body></html>';
} else
{
var emailheader = '<html><body>' +
'On' + ' ' +
edate + ' ' +
'at' + ' ' +
etime + ',' + ' ' + emailFrom + ' ' + 'wrote:' + '</body></html>';
}
var emailsig = '<html>' +
'<div>your email signature,</div>' +
'</html>'; // your email signature i.e. common for all emails.
// Build the email message
var emailBody = '<p>Hi ' + firstName + ',<p>';
emailBody += '<p>For ' + subjectCol + ', you will be graded on #1, 2, and 3: <p>';
emailBody += '<p>Participation: ' + pgrade + '</p>';
emailBody += '<p>HW grade: ' + hgrade + '</p>';
emailBody += '<p>If you have any questions, you can email me at ' + grader + '#email.com.<p>';
emailBody += '<p>- ' + grader;
var draftmsg = emailBody + '<br>' + emailsig + '<br>' + emailheader + '<br>' + emailmsg + '\n'; // message content of draft
// Create the email draft
messages[lastmsg].createDraftReply(
" ", // Body (plain text)
{
htmlBody: emailBody // Options: Body (HTML)
}
);
}
}
}
function WebSafe(fullstring)
{
var splitString = fullstring.split(",");
var finalarray = [];
for (u=0; u < splitString.length; u++)
{
var start_pos = splitString[u].indexOf("<") + 1;
var end_pos = splitString[u].indexOf(">",start_pos);
if (!(splitString[u].indexOf("<") === -1 && splitString[u].indexOf(">",start_pos) === -1)) // if < and > do exist in string
{
finalarray.push(splitString[u].substring(start_pos, end_pos));
} else if (!(splitString[u].indexOf("#") === -1))
{
finalarray.push(splitString[u]);
}
}
var index = finalarray.indexOf(grader + "#email.com"); // use your email id. if the array contains your email id, it is removed.
if (index > -1) {finalarray.splice(index, 1);}
return finalarray
}
}
I've never coded in JavaScript before or used Google Scripts so I mostly looked at similar examples.
Thank you for any feedback.
I prefer reading code that isn't too nested. So I took the liberty to re-write your code and make it easier to read.
Your main function:
function mainFunction(){
// Use data from the active sheet
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var threads = GmailApp.getUserLabelByName('<YOUR-LABEL-HERE>').getThreads();
var subject1 = data[1][3];
// Work through each row in the spreadsheet omit headers
for (var i = 2; i < data.length; ++i) {
// Get grader's data
var grader = getGrader(data[i]);
console.log(grader);
// Loop through threads
for (j=0; j < threads.length; j++){
var thread = threads[j];
// Get last message in thread
var messages = thread.getMessages();
var lastMsg = messages[messages.length - 1];
var email = new Email(grader, lastMsg, subject1);
// Create the draft reply.
var draftMessageBody = createDraftMessage(email);
lastMsg.createDraftReply(draftMessageBody);
}
}
}
Support functions:
Function getGrader:
function getGrader(array){
var row = array
var grader = {}
grader.grader = row[0];
grader.firstName = row[1];
grader.studentEmail = row[2];
var grade = row[3].split(' ');
grader.pgrade = grade[1];
grader.hgrade = grade[0];
return grader
}
Function webSafe:
function webSafe(fullstring, grader){
var splitString = fullstring.split(",");
var finalarray = [];
for (u=0; u < splitString.length; u++){
var start_pos = splitString[u].indexOf("<") + 1;
var end_pos = splitString[u].indexOf(">",start_pos);
// if < and > do exist in string
if (!(splitString[u].indexOf("<") === -1 && splitString[u].indexOf(">",start_pos) === -1)){
finalarray.push(splitString[u].substring(start_pos, end_pos));
} else if (!(splitString[u].indexOf("#") === -1)){
finalarray.push(splitString[u]);
}
}
// use your email id. if the array contains your email id, it is removed.
var index = finalarray.indexOf(grader.grader + "#mangoroot.com");
if (index > -1) {
finalarray.splice(index, 1);
}
return finalarray
}
Function Email: Behaves like a class
var Email = function(grader, lastMsg, subject){
this.signature = "your_email_signature,";
this.grader = grader;
this.to = webSafe(lastMsg.getTo(), this.grader);
this.from = webSafe(lastMsg.getFrom(), this.grader);
this.cc = webSafe(lastMsg.getCc(), this.grader);
this.subject = lastMsg.getSubject().replace(/([\[\(] *)?(RE|FWD?) *([-:;)\]][ :;\])-]*|$)|\]+ *$/igm,"");
this.message = lastMsg.getBody();
this.date = lastMsg.getDate();
this.attachments = lastMsg.getAttachments();
this.subject1 = subject;
this.ccHeader = function() {
var ccHeader = "";
if (this.to == "" || this.cc == ""){
ccHeader = this.cc.toString();
}
else {
ccHeader = this.to.toString() + "," + this.cc.toString();
}
return ccHeader
}
this.eDate = function() {
return Utilities.formatDate(this.date, "IST", "EEE, MMM d, yyyy");
}
this.eTime = function() {
return Utilities.formatDate(this.date, "IST", "h:mm a");
}
this.header = function() {
var header = ''.concat('On ');
if (this.from.length == 0){
header += this.eDate().concat(' at ',this.eTime(),', you wrote: ');
}
else {
header += this.eDate().concat(' at ',this.eTime(),', ',this.from,' wrote: ');
}
return header
}
this.body = function(){
var grader = this.grader;
var body = '<div>'.concat('<p>Hi ',grader.firstName,',</p>');
body += '<p>For '.concat(this.subject1,', you will be graded on #1, 2, and 3: </p>');
body += '<p>Participation: '.concat(grader.pgrade,'</p>');
body += '<p>HW grade: '.concat(grader.hgrade,'</p>');
body += '<p>If you have any questions, you can email me at '.concat(grader.grader,'#mangoroot.com.</p>');
body += '<p>- '.concat(grader.grader,'</p>','</div>');
return body;
}
}
Function createDraftMessage:
function createDraftMessage(email){
var draft = '<html><body>'.concat(email.body);
draft += '<br>'.concat(email.signature);
draft += '<br>'.concat(email.header);
draft += '<br>'.concat(email.message);
draft += '<br>'.concat('</body></html>');
return draft;
}
Now when you run mainFunction() you should get your expected drafts.
Notes:
It is good practice to keep functions flat, flat is better than nested. Makes the code more readable and maintainable.
Also be consistent in your variable naming style.
var emailMsg = ''; // Good.
var emailmsg = ''; // Hard to read.
Have a read about classes
My program is currently supposed to take the HTML input, put it into an object array, sort it using orderBy, then output it to the p2 textContent. I tested all of the aspects of this program before adding orderBy, and then the program stopped working.
var p1 = document.getElementById("p1");
var p2 = document.getElementById("p2");
var enterName = document.getElementById("name");
var enterRating = document.getElementById("rating");
var button = document.getElementById("button");
var players = [];
button.addEventListener("click", addPlayer);
function addPlayer() {
p1.innerText += enterName.value + " - " + enterRating.value + " " + "| ";
players.push({ player: enterName.value, rating: enterRating.value });
var sortedPlayers = _.orderBy(players, [rating, player], [desc, desc]);
console.log(players);
console.log(sortedPlayers);
p2.innerText = "";
for (i = 0; i < players.length; i++) {
p2.innerText += players[i].player + " - " + players[i].rating + " | ";
}
}
p1 exists and is used for testing purposes, just to make sure that my browser isn't lagging. After I added the orderBy, neither array logged to the console. Before, the players array logged with every run of the addPlayer() function.
I'm using codepen to write this program, and I am pretty sure lodash is installed if that is relevant.
I am trying to write code that will output something like the following for example:
Dog 1 Name: Neo Toys: 3
Dog 2 Name: Henry Toys: 2
However, I will only get the results from the last inputs. So if I were to input the data above, I get this with my code.
Dog 1 Name: Henry Toys: 2
How do I make it so that every time I put in an input, it doesn't replace the previous one?
var garrDog = [];
function start() {
var valueToPush = {};
var vName = '';
var vToys = '';
vName = prompt("Enter the dog's name (leave blank to stop)");
vToys = prompt("Enter number of toys " + vName + " has (leave blank to stop)");
valueToPush['dogName'] = vName;
valueToPush['dogToys'] = vToys;
while (vName.length > 0) {
vName = prompt("Enter the dog's name (leave blank to stop)");
if (vName.length > 0) {
vToys = prompt("Enter number of toys " + vName + " has (leave blank to stop)");
valueToPush['dogName'] = vName;
valueToPush['dogToys'] = vToys;
}
}
garrDog.push(valueToPush);
listDogs();
}
function listDogs() {
var i = 0;
while (i < garrDog.length) {
document.getElementById('output').innerHTML += ('Dog ' + (i+1) + ' Name: ' + garrDog[i].dogName + ' No. of toys: ' + garrDog[i].dogToys + '<br />');
i++;
}
}
You only execute push once; it should be in the loop. Also, make sure you define a new object in each iteration, or you will mutate the same object, resulting in an array of repetitions of the same object.
Here is a corrected version of the start function (the rest can stay as it is):
function start() {
garrDog = []; // Add this when you want to start from scratch each time
vName = prompt("Enter the dog's name (leave blank to stop)");
while (vName.length > 0) {
var valueToPush = {};
vToys = prompt("Enter number of toys " + vName + " has");
valueToPush['dogName'] = vName;
valueToPush['dogToys'] = vToys;
garrDog.push(valueToPush);
vName = prompt("Enter the dog's name (leave blank to stop)");
}
listDogs();
}
NB: I would not tell the user that they can stop by entering nothing for the secondary question. That would leave one entry incomplete. Only leave that option for the first question.
Also, consider making garrDog a local variable and passing it to the listDogs function. It depends on whether you want to maintain the list and extend it at each call of start.
EDIT#2:
I've decided to try and batch the copy-paste operations that run after all the emails are fired. In previous posted code, in the last lines of every loop, I copied and pasted the items from each purchase order ("Email" sheet) to another ("AsignRec"). Now, what I want to do is store the items from "Email" sheet in every loop to a Javascript array, and paste all together into "AsignRec" at the end, just once.
However, I'm still not doing it right. I'm stuck at the final pasting/setValues(). I believe the array is correctly formed, as it has a length of 49, which is the number of unique SKUs to be sent out to suppliers. Still, at the setValues([OCitems]) line 185, I get the error "Incorrect range height, was 1 but should be 49 (line 185, file "TestArrayMultiple4")".
I assume this means the destination/output range is not the same size as array/input (called OCitems). I don't see why though, since I defined the length of the output range using OCitems.length. I am missing something, and not sure what.
This is the important bit of the code, and full code below. Same GDocs link as before, script file TestArrayMultiple4, lines 160-185.
https://docs.google.com/spreadsheets/d/1yzvMTh0VYhRhiexNzQPIjTwz1FCMq4XnbpGvCF1FYu8/edit#gid=436022027
/// Get Range we want to change to creating Javascript array and paste at end only
var OcNoHeader = sheet.getRange("B9:J" + MaxTableRow).getValues(); // get items to send to supplier from "Email Sheet"
// if supplier number is 1, create array "OCitems" by storing OcNoHeader. If not supplier #1, then append to existing array "OCitems"
if(y == 1){
var OCitems = OcNoHeader}
else
{for(j=0;j<OcNoHeader.length;j++){
OCitems.push(OcNoHeader[j]);
}}
Logger.log(OCitems);
Logger.log("OCitems length = " + OCitems.length)
debugger;
i++; // after firing email, y+1 to go to next supplier
Logger.log("i++ IF =" + 1);
Logger.log("new i ELSE =" + 1)
debugger;
} // only do while x = max number of suppliers reached
while (i < x);
sheet3.getRange(3, 3, OCitems.length, 9).setValues([OCitems]); // paste operation, NumRows set equal to length of array
=========================
EDIT#1: Worked on improving performance using getValues of several cells instead of doing individual getValue() several times over. Unfortunately, this hasn't reduced the execution time in a stable or noticeable manner (sometimes it finished before 6min, sometimes not).
Posting code below (you can access it in script file "TestArrayMultiple2" in new Sheet shared below):
Using Execution transcript, I see that although the execution time of the getValue() lines that were previously taking very long has basically been reduced to zero, other lines of code are now taking more time and killing the gain achieved from the batching other getValue().
There are still 4-5 "individual" getValue() on specific cells (much less than before), but I don't understand why they would take so long. So it seems even if I removed the remaining "individual" getValue(), if only one remained, it would take even longer.
Seems to me it has something to do with caching (and I'm sure I don't fully understand this concept), for the following reasons:
1) It is always the first getValue() in the loop which takes the longest.
2) I tried to go down a different route, by changing the code for the copy/paste operation which occurrs after all emails are sent (line 150 in "TestArrayMultiple2" script file). I basically try to create an array which gets fed with more data at every loop (append/push method) but doesn't paste within every loop - the idea is to paste all the data at the end, after finishing looping. I still don't have it right (this second script file is the last one, "TestArrayMultiple3"), but I can see the emails get fired off much faster.
Once again, your help would be much appreciated.
> // version with 1 getDataRange array which stores for supplier ID, name, email, MaxTableRow for PO email, email subject all from Dashboard sheet
function TestArrayMultiple2() {
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var sheet = ss.getSheetByName("Email");
var sheet1 = ss.getSheetByName("Pedido email");
var sheet2 = ss.getSheetByName("Dashboard");
var sheet3 = ss.getSheetByName("AsignRec");
var sheet4 = ss.getSheetByName("ListadoProductos");
var sheet5 = ss.getSheetByName("Registro-Consolid");
var sheet6 = ss.getSheetByName("Registro-Unico");
var x = ss.getSheetByName("Dashboard").getRange("C4").getValue();
Logger.log("x = " + x)
var offsetV = 4; // number of rows of offset for email status to be inserted in Dashboard sheet
var OffSetColProv = 1; // column in Dashboard sheet with supplier name
var OffsetColMaxPOrows = 3; // Number of unique SKUs or rows in PO. Replace MaxTableRow formula in Email Sheet
var OffSetColPzas = 4; // column in Dashboard sheet with number of items in supplier purchase order.
var OffSetColEmail = 5; // column in Dashboard sheet with supplier email
var OffSetColCC = 13; // column in Dashboard sheet with supplier email CC
var OffSetColSubject = 14; // column in Dashboard sheet with supplier email Subject
var colStatus = 11; // column in Dashboard sheet where send status of email inserted -----> LEAVE AS IS FOR NOW, not an offset, is fixed, col. K = 11
var OffsetEmailRows = 8 // number of rows in Email sheet before the items in PO are shown
var ProvNumEmail = sheet.getRange(1,2); // Supplier number in email sheet used to refresh products in purchase order email via FILTER formula
var StatusRange = sheet2.getRange("K5:K100");
Logger.log("StatusRange = " + StatusRange)
var currentTime = new Date();
var timestamp = Utilities.formatDate(currentTime,'GMT-0600','dd/MM/yyyy HH:mm:ss');
Logger.log("timestamp = " + timestamp);
var ProvArray = sheet2.getRange("E5:S100");
var DashValues = ProvArray.getValues();
i = 0;
do {
var y = DashValues[i][0];
Logger.log("y = " + y)
ProvNumEmail.setValue(y); // set value of next supplier in Email sheet to load next purchase order products
// emails var here in order to update email value in IF email = ERROR condition and skip to else
var Prov = DashValues[i][OffSetColProv];
Logger.log("Prov = " + Prov);
var EmailSubject = DashValues[i][OffSetColSubject];
Logger.log("EmailSubject = " + EmailSubject)
var MaxTableRow = DashValues[i][OffsetColMaxPOrows] + OffsetEmailRows;
Logger.log("MaxTableRow = " + MaxTableRow)
var EmailTo = DashValues[i][OffSetColEmail];
Logger.log("EmailTo = " + EmailTo)
var EmailCC = DashValues[i][OffSetColCC];
Logger.log("EmailCC = " + EmailCC)
var Piezas = DashValues[i][OffSetColPzas];
Logger.log("Piezas = " + Piezas)
SpreadsheetApp.flush();
var name = "Petsy Compras - Juan Carlos León";
var ReplyToEmail = "compras#petsy.mx";
var email = EmailTo;
var subject = EmailSubject;
var name = name;
var replyTo = ReplyToEmail;
var Emailcc = EmailCC;
var schedRange = sheet.getRange("B7:J"+MaxTableRow);
var body = '<div>';
body += "Estimados," +'<br>' + '<br>';
body += "Envío la orden de compra, por un total de " + '<b>' + Piezas + " piezas." + '</b>' +'<br>' + '<br>';
body += "Favor de confirmar las existencias lo más rápidamente posible, dentro del mismo correo y"+ '<b><a style="color:#FF0000">'+ " enviar factura a: "+ '</a></b>' + "facturasproveedores#petsy.mx." +'<br>' + '<br>';
body += "Al dar " +'<b><a style="color:#FF0000"> '+ "RESPONDER A TODOS" + '</a></b>' +" la tabla con los productos pedidos se hace editable: favor de marcar por cada item si será faltante." +'<br>' + '<br>';
body += "Cualquier duda avísenme por favor." +'<br>' + '<br>';
body += "Un saludo" +'<br>' + '<br>';
body += '<b>' + "Juan Carlos León" + '<b>' + '<br>';
body += "Petsy Compras"+'<br>';
body += "Mapa aquí: "+'<br>';
body += "Fijo directo 1: (55) 68 12 07 97 / Fijo directo 2: (55) 68 12 07 99 / Cel y Whatsapp: 55 32 23 57 17"+'<br>' + '<br>';
body += "" +'<br>' + '<br>';
body += getHtmlTable(schedRange);
body += '</div>';
// variables for error email
var emailERR = 'oscialom#petsy.mx'
var subjectERR = 'ERROR ENVIO OC' + ' // ' + Prov + ' ' + timestamp
if(email == 'ERROR' || MaxTableRow == 0) // skip condition to go begin loop with y+1
{
// if above skip condition is true, y+1 to move to next purchase order
Logger.log("y = " + y);
Logger.log("IF");
sheet2.getRange(y + offsetV,colStatus).setValue('NOT_SENT'); // set email send status next to supplier in Dashboard sheet
{
GmailApp.sendEmail(emailERR, subjectERR, "Requires HTML",
{
'name':name,
'replyTo':replyTo,
'htmlBody':'',
'cc':''});
}
i++;
Logger.log("new i IF =" + 1);
continue
}
else
{
// if skip condition is false, fire current supplier purchase order email email
Logger.log("i = " + i);
Logger.log("y = " + y);
Logger.log("ELSE");
GmailApp.sendEmail(email, subject, "Requires HTML",
{
'name':name,
'replyTo':replyTo,
'htmlBody':body,
'cc':EmailCC});
}
sheet2.getRange(y + offsetV,colStatus).setValue('OK'); // set email send status next to supplier in Dashboard sheet
// START copy-paste Asign-Rec
var MaxTableRowASIGN = sheet3.getRange("A1").getValue();
Logger.log("MaxTableRowASIGN = " + MaxTableRowASIGN)
/// Get Range we want to change to creating Javascript array and paste at end only
debugger; // stop debugger at this point !! REMOVE OR PLACE AT CORRECT LINE IF USING DEBUGGER
var OcNoHeader = sheet.getRange("B9:J" + MaxTableRow);
var ConsolAsignRec = sheet3.getRange("B3:K" + MaxTableRow);
var ProvOC = sheet.getRange("B2").getValue();
Logger.log("ProvOC = " + ProvOC)
var MaxRowB = sheet3.getRange("C1").getValue() + 1;
Logger.log("MaxRowB = " + MaxRowB);
var NextRowB = MaxRowB + 1;
Logger.log("NextRowB = " + NextRowB);
OcNoHeader.copyTo(sheet3.getRange(MaxTableRowASIGN + 1,3),{contentsOnly:true});
var NumRowsProv = OcNoHeader.getNumRows();
var ProvOCcolumn = sheet3.getRange(MaxRowB, 2, NumRowsProv)
Logger.log("ProvOCcolumn = " + ProvOCcolumn);
ProvOCcolumn.setValue(ProvOC);
// END copy-paste Asign-Rec
i++; // after firing email, y+1 to go to next supplier
Logger.log("i++ IF =" + 1);
Logger.log("new i ELSE =" + 1)
} // only do while x = max number of suppliers reached
while (y<x);
// set y = 1 to reset value again after finishing loop
sheet.getRange(1,2).setValue(1); // reset ProvNumber = 1 to start again next time script is fired.
var EmailsSent = sheet2.getRange("C10").getValue(); // set values
Logger.log("EmailsSent = " + EmailsSent)
var EmailErrors = sheet2.getRange("C11").getValue();
Logger.log("EmailErrors = " + EmailErrors)
var MaxTableRowEND = sheet2.getRange("C9").getValue();
var schedRange = sheet2.getRange("E4:K" + MaxTableRowEND);
var emailEND = "oscialom#petsy.mx";
var subjectEND = 'OCs Inbound enviadas' + ' ' + timestamp + " (errores " + EmailErrors + " / enviados " + EmailsSent + ")";
var EmailCCEND = "";
var bodyEND = getHtmlTable(schedRange);
GmailApp.sendEmail(emailEND, subjectEND, "Requires HTML",
{
'name':name,
'replyTo':replyTo,
'htmlBody':bodyEND,
'cc':EmailCCEND});
StatusRange.clearContent();
/// START RecordTimestamp code
var Avals = sheet4.getRange("A1:A").getValues();
var lastrow1 = Avals.filter(String).length;
Logger.log('lastrow1 =' + lastrow1)
var Avals2 = sheet5.getRange("A1:A").getValues();
var lastrow2 = Avals2.filter(String).length;
Logger.log('lastrow2 =' + lastrow2)
sheet4.getRange("B2:B" + lastrow1).copyTo(sheet5.getRange(lastrow2 + 1, 1)) // copy order-items to Registro sheet, after last filled row
sheet4.getRange("K2:K" + lastrow1).copyTo(sheet5.getRange(lastrow2 + 1, 2)) // copy Prov1 to Registro sheet, after last filled row
var Avals3 = sheet5.getRange("C1:C").getValues();
var lastrow2c = Avals3.filter(String).length;
Logger.log('lastrow2c =' + lastrow2c);
if(lastrow2 == 1)
{ sheet5.getRange(lastrow2c + 1, 3, lastrow1 - 1).setValue(timestamp)
Logger.log('IF')
}
else
{
sheet5.getRange(lastrow2c + 1, 3, lastrow1 - 1).setValue(timestamp)
Logger.log('ELSE')
}
var MaxTableRowEMAIL = sheet6.getRange("G5").getValue()
var subject = "Items pedidos en OC automatizada " + timestamp
var email = "oscialom#petsy.mx";
var EmailCC = "";
var EmailBCC;
var name = "Petsy Compras";
var ReplyToEmail = "compras#petsy.mx"
var schedRange = sheet6.getRange("A1:C" + MaxTableRowEMAIL);
var body = getHtmlTable(schedRange);
{
GmailApp.sendEmail(email, subject, "Requires HTML",
{
'name':name,
'replyTo':ReplyToEmail,
'htmlBody':body,
'cc':''});
}
/// END RecordTimestamp code
Logger.log("MaxTableRowASIGN " + MaxTableRowASIGN);
var endtime = new Date();
Logger.log("timestamp end " + timestamp);
Logger.log("endtime " + Utilities.formatDate(endtime,'GMT-0600','dd/MM/yyyy HH:mm:ss'));
var scripttime = (endtime - currentTime);
Logger.log("scripttime original" + scripttime);
// strip the ms
scripttime /= 1000;
Logger.log("scripttime / 1000" + scripttime);
// get seconds (Original had 'round' which incorrectly counts 0:28, 0:29, 1:30 ... 1:59, 1:0)
var seconds = Math.round(scripttime % 60);
Logger.log("scripttime % 60" + scripttime);
// remove seconds from the date
scripttime = Math.floor(scripttime / 60);
Logger.log("scripttime / 60" + scripttime);
// Browser.msgBox("Script completado en " + seconds + " segundos",Browser.Buttons.OK_CANCEL); // removed MsgBox to measure real execution time
Logger.log("seconds " + seconds)
}
=====================
ORIGINAL POST
I wrote a Google script to automate the purchase order process to several suppliers. The process takes a list of products (from sheet ListaProductos), formats the product info into an email format (sheet "Email"), sends the emails, and does some copy/pasting into other sheets of the same spreadsheet. However, I always run into the execution time at around 75% of the script. I'm fairly new to this, have been reading up but frankly don't know what to try next.
I see the problem in this part of code:
do {
// read info from the sheet
range.getValue();
// more code here...
} // only do while x = max number of suppliers reached
while (y<x)
Operation getValue takes much time to run. Best practice is to use the whole range:
var data = sheet.getDataRange().getValuses();
and then use data as source for further calculations.
See more info here:
https://developers.google.com/apps-script/best_practices
Hi everybody this code is used to have a list name and id of facebook friends or invited friends if executed on friend list page. I'm trying to count the character of a string in javascript but .length method return always 1. I don't understand why cause I'm counting on a string not an array.
this is my code:
var name_list;
var id_list;
var count_letter_l;
var count_name = 0;
var count_id = 0;
var inputs = document.getElementsByClassName('_2akq _1box');
for(var i=0;i<inputs.length;i++){
var name = inputs[i].getElementsByTagName('span')[0].childNodes[0].nodeValue;
var full_id = inputs[i].getAttribute("data-reactid");
var split_id = full_id.split(':');
var split_two = split_id[1].split('.');
var split_final = split_two[0];
var count_letter = split_final.length;
//console.log(count_letter);
if(name != 'null'){
name_list+= ',' + '"' + name + '"';
id_list += ',' + '"' + split_final + '"';
count_letter_l += ',' + '"' + count_letter + '"';
count_name++;
count_id++;
}
}
console.log(name_list);
console.log('------!!!!!!!!------');
console.log(id_list);
console.log('names = ' + count_name);
console.log('id = ' + count_id);
console.log('letters for esch field = ' + count_letter_l);
I wish to count the character of every id cause in my case when I grab the ids I have some "0" and "1" in the and of the list. I don't know why and I wish to cut them out of the list.
This is an element of _2akq _1box class. you can see it if open firefox firbug and look at facebook front-end html code while you are displaying the friends list
<span class="_2akq _1box" data-reactid=".5q.2.0.0.0.0:0:1:$1543522353.0.0.$2.$text.0.0">
<span data-reactid=".5q.2.0.0.0.0:0:1:$1543522353.0.0.$2.$text.0.0.0">Laura Casali</span>
</span>
the console tell me:
letters for esch field = undefined,"1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1".....
tnx for help