I've found a LOT of scripts that will take data from a Google Sheet and create a Google Doc, but I need a paragraph (really just a few sentences) generated into the Sheet itself. We create web pages for people who enter their information into a Google Form (name of their store, location, brands carried, etc.), we do this by exporting the Google Sheet into a .csv file, and uploading the file which generates the pages. So we need the paragraph to be in the Google Sheet.
I need a script that will give me a paragraph that says:
Column D is a "OUR BRAND" dealer located in Column H. Column D also sells Column T.
I've been trying to figure out this script for hours piecing together what I've found elsewhere and it seems like every time I sort out one bit, I screw up another bit. It's a mess:
function onEdit() {
var activeSheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = activeSheet.getSheetByName("All Dealers");
var cell = sheet.getActiveCell();
var row = cell.getRow();
var col = cell.getColumn();
// Fetch the range of cells
var dataRange = sheet.getRange(row, col)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var dealerName = row[0]
var city = row[1]
var brand = row[2];
}
var body = 'dealerName' + "is a OURBRAND located in" + 'city' + 'dealerName' + "also sells" + 'brand';
SpreadsheetApp.getActiveSheet().getRange("AI"+row).setValue('body');
}
Spreadsheet is available here
You don't need a script for this: an arrayformula can do what you want.
Preliminary version: in cell AI2, enter
=arrayformula(D2:D & " is a BRAND dealer located in " & H2:H & ". " & D2:D & " also sells " & T2:T)
(Note that I've put spaces in appropriate places; this is something that requires extra attention when concatenating strings.)
The drawback of the above is that you also get some text in empty rows. To filter them out, replace each column reference by its filtered version: filter( ... , len(D2:D)) keeps only the rows with nonempty column D.
=arrayformula(filter(D2:D, len(D2:D)) & " is a BRAND dealer located in " & filter(H2:H, len(D2:D)) & ". " & filter(D2:D, len(D2:D)) & " also sells " & filter(T2:T, len(D2:D)))
This being in arrayformula means that as new data is added to columnds D,H,T, new text will be created in column AI.
Related
I'm sure that there's not an easy way to do this, but I figured I would ask. I have a sheet that has a decent amount of conditional formatting on it, however, people that I share the sheet with have been copy/pasting and moving rows which aggravatingly disrupts the formatting. I am trying to convert to Scripting for them. The main thing is background colors based on other cell information.
ie: if Any cell from row 4 from column A-D has information in it then the K4 will be red. Once K4 has information inside it then the background will be white.
The conditional formatting I have is: =AND(OR(ISBLANK(A4)=FALSE,ISBLANK(B4)=FALSE,ISBLANK(C4)=FALSE,ISBLANK(D4)=FALSE),ISBLANK(K4)=TRUE).
The other is that when any cell has a certain term "LWOS" then the whole row has a purple background and strikethrough.
Thanks in advance.
I know scripting is hard when you are new to it, so I understand you and decided I'm going to give you a code that should work with yours. And please do follow Endothermic_Dragon's recommendation into studying Apps Script if you want to learn more.
Code:
function onEdit(e) {
// Get active spreadsheet and sheet
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getActiveSheet();
// Get row and column of the current cell edited
var editRow = e.range.getRow();
var editColumn = e.range.getColumn();
// If edited cell is below row 4:
if(editRow > 3) {
// Get row and K cell for checking values later
var rowRange = sheet.getRange("A" + editRow + ":D" + editRow)
var rowValues = rowRange.getValues();
var kCell = sheet.getRange("K" + editRow);
var kValue = kCell.getValue();
var rowHasValue = rowValues[0].some(el => !!el);
var rowHasLWOS = rowValues[0].includes("LWOS");
var kHasValue = kValue != "";
// If edited column is in A-D
if(editColumn < 5) {
// If we see a value on that row and K row doesnt have value
if(rowHasValue && !kHasValue){
// Set K cell to red
kCell.setBackground("red");
}
// If columns A-D of the edited row has LWOS
// (cell value is "LWOS", not cell containing LWOS)
if (rowHasLWOS){
// Set row to purple and strikethrough
sheet.getRange(editRow + ":" + editRow).setBackground("purple").setFontLine("line-through");
}
}
// If edited column is K
if(editColumn == 11) {
// If row doesnt have LWOS, proceed with checking the K value
if(!rowHasLWOS) {
// If edited value of K has value
if(kHasValue) {
// Set K to white
sheet.getRange("K" + editRow).setBackground("white");
}
// If K value was deleted and A-D has values
if(rowHasValue && !kHasValue) {
// Set K back to red
sheet.getRange("K" + editRow).setBackground("red");
}
}
}
}
}
Output:
This has comments on it so hopefully you can at least understand what the code does and how it works.
For more details, check the references you can study below.
References:
Spreadsheet
Spreadsheet tutorials
Beginners guide by Ben Collins
Been building a landing page to start an email list. Decided to use Google Sheets as the backend to store emails & Google Scripts to send the first welcome message.
I hooked up an HTML page to Google Sheets with an API. The user submits their name & email, and then it goes to the Google Sheets. When the document is edited, this function gets triggered which sends a welcome message.
To prevent duplicate messages from going out, I put a simple system in place. When a user has been emailed, the third row (C) is filled in with "EMAIL_SENT" automatically.
When the function is triggered, it should only send the user an email if if there is no "EMAIL_SENT" but every time a new user submits their info, every single email on the list gets another welcome message.
I will attach an image of the spreadsheet
// This constant is written in column C for rows for which an email
// has been sent successfully.
var EMAIL_SENT = 'EMAIL_SENT';
/**
* Sends non-duplicate emails with data from the current spreadsheet.
*/
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = sheet.getLastRow();
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 3);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[0]; // First column
var nameThisMan = row[1]; // Person's name
var emailSent = row[2]; // Third column
if (emailSent !== EMAIL_SENT) { // Prevents sending duplicates
var message = "Hey there " + nameThisMan + "," + "\n \n Thanks for joining the email list! You’re about to be getting some AMAZING programming resources. Here’s the link to the top 10 open source Github repos PDF. \n https://www.dropbox.com/s/wm8ctsdojlsoss6/10%20Most%20Useful%20Open%20Source%20Repos%20for%20Developers.pdf?dl=0\n\n And here’s the link to the archive of all the resources from this email list. These are from all past emails. \n https://docs.google.com/document/d/1hWmGNYkn0czRI29JJu9HgUVC6L4AsNYBxwt45ABnT6w/edit?usp=sharing \n \n Thank you again for joining the list! I will do my best to give you absolutely amazing programming resources. \n \n best, \n Michael Macaulay, Techtime.";
var replyTo = "TechTimeDev#gmail.com";
var subject = "Welcome to TechTime's Email List";
MailApp.sendEmail(emailAddress, replyTo, subject, message);
sheet.getRange(startRow + i, 3).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
function sendEmails2() {
var sheet=SpreadsheetApp.getActiveSheet();
var startRow=2;
var numRows=sheet.getLastRow()-startRow+1;
var dataRange=sheet.getRange(startRow, 1, numRows, 3);
var data=dataRange.getValues();
for (var i=0; i < data.length; ++i) {
var row=data[i];
var emailAddress=row[0];
var nameThisMan=row[1];
var emailSent=row[2];
var replyTo="TechTimeDev#gmail.com";
var subject="Welcome to TechTime's Email List";
if (emailSent!='EMAIL_SENT') {
var message="Hey there " + nameThisMan + "," + "\n \n Thanks for joining the email list! You’re about to be getting some AMAZING programming resources. Here’s the link to the top 10 open source Github repos PDF. \n https://www.dropbox.com/s/wm8ctsdojlsoss6/10%20Most%20Useful%20Open%20Source%20Repos%20for%20Developers.pdf?dl=0\n\n And here’s the link to the archive of all the resources from this email list. These are from all past emails. \n https://docs.google.com/document/d/1hWmGNYkn0czRI29JJu9HgUVC6L4AsNYBxwt45ABnT6w/edit?usp=sharing \n \n Thank you again for joining the list! I will do my best to give you absolutely amazing programming resources. \n \n best, \n Michael Macaulay, Techtime.";
MailApp.sendEmail(emailAddress, replyTo, subject, message);
sheet.getRange(startRow + i, 3).setValue('EMAIL_SENT');
}
}
}
The method getLastRow() will return you the index of the last row with content. In the example you have provided this would be 3. However, what you actually want for performing getRange() is the number of rows you need to take. If you use three you would be taking an extra empty row and therefore, you would be getting the wrong values.
To change this to get the number of rows you need, you can simply do:
var numrows = sheet.getLastRow() - 1; instead of var numRows = sheet.getLastRow();
as you need to subtract from the index the number of rows you are not wanting to get in your range (in your case as you are ignoring the first row only 1 needs to be subtracted).
In using this tutorial script from: https://developers.google.com/apps-script/articles/sending_emails
I am new to apps script and have been searching the forums trying to figure this out...
I'm trying to use another column in the spreadsheet to dynamically enter the salutation in the message. I thought it would be a formula like this:
="Dear "E2, + "Our 2018 Catalog is Coming Soon! Would you like a copy? " But, then I get the error that -ADD parameter1 is text and it is looking for numbers-, (even though I found it in another help area to use the quotes to separate the cell references).
So my questions:
1.Is it possible to make dynamic changes to the message in this script? Or do I need another script in the message column to do this?
2.If I am running more than one script on the spreadsheet and connected form do I need separate script files or just separate blocks on the same file
Thank you!
Adding a separate salutation to an email script
Here's the script for that tutorial:
// This constant is written in column C for rows for which an email
// has been sent successfully.
var EMAIL_SENT = "EMAIL_SENT";
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 3)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var emailSent = row[2]; // Third column
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = "Sending emails from a Spreadsheet";
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 3).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
I believe you wish to have a separate salutation which is at the beginning of the message portion. It appears that you also wish to use column 5 for that data.
So if that's the case then your message would be something like this:
var message = Utilities.formatString('Dear %s\n%s',row[4],row[1]); Reference
This could also be accomplished this way:
var message = 'Dear ' + row[4] + '\n' + row[1];Reference
In either case you would put a name in column 5 and the rest of your message in column2. If you wan't to use html in your email replace the '\n' (line feed) with '<br />' (line break);
The message starts with the saluation in row[4] (column 5) and the rest of the message comes from row[1] according to the tutorial which is column 2.
The data from a getValues() command is returned in an array. Arrays index from zero where as columns in the spreadsheet begin at 1. Reference
If I misinterpreted your question please ask for further assistance in comments below. I'll be glad to help you.
I want to build a custom Google Sheets function via Google Apps Script and I've gotten stuck along the way.
I want to take the text from the first and second column (A1, A2 ...B1, B2 etc..) and return them with custom text, specifically to have them wrapped in tags.
So if in A1 we have "Can of Soda" and in A2 "$0.99", I would like function to return a final string of "Can of Soda " and "$0.99", but individually wrapped into span tags and then concatenated together into one string.
When I look at the Google Scripts log, I can return the the items in each columns as separate logs (although the first column doesn't return the closing tag). The question is how I get them into one string. I also only go through the first row, when I would like that for loop to go through each row.
Here is my log:
[16-05-30 11:32:02:348 EDT] <span>Can of Soda
[16-05-30 11:32:02:349 EDT] <span>0.99</span>
Here's my code as of now:
function weeklyMenu() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
for (var i = 0; i < data.length; i++) {
product = Logger.log("<span>" + data[i][0]) + "</span> ";
price = Logger.log("<span>" + data[i][1] + "</span>");
}
}
\\The end goal is to have a string that says "<span>Can of Soda</span> <span>$0.99</span>"
If you really want to do this with a custom function, in C1 enter:
=weeklyMenu(A1,B1)
The code is:
function weeklyMenu(A,B) {
var sheet = SpreadsheetApp.getActiveSheet();
var con="<span>"+A+"</span> <span>"+B+"</span>";
return con
}
You could also just use a formula (again enter in C1):
="<span>"&A1&"</span> <span>"&B1&"</span>"
Either one can be copied down.
I'm translating VBA into a Google Sheets script, but am a loss on how to get past this loop through all rows in a single column hurdle.
I have a column which contains an #OrdernNumber, a -State code, a First name, and sometimes a Last name, followed by an empty cell. I need to combine the First and Last names into the First name cell, and then clear the Last name cell below. This is illustrated in the screenshot below:
Column C and D in the screenshot reveal the pattern I used to construct my original VBA code:
Sub WorkingCombineAndClearLoop()
Dim Rngcell As Range
For Each Rngcell In Range("B1:B100")
'if first character is #
If left(Rngcell.Value, 1) <> "#" _
'and if first character is -
And left(Rngcell.Value, 1) <> "-" _
'and if cell is not blank then
And Rngcell.Value <> "" Then
'combine left cell
Rngcell.Value = Rngcell.Offset(0, -1).Value _
'with bottom left cell
& " " & Rngcell.Offset(1, -1).Value
'then clear below cell
Rngcell.Offset(1, 0).ClearContents
End If
Next
End Sub
Following is my annotated JavaScript code. Because I can't get the loop working yet, I've had to change the code logic a bit:
function workingCombineAndClearNoLoop() {
//get active spreadsheet, sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
//determine row count
var numRows = SpreadsheetApp.getActiveSheet().getRange("A:A").getLastRow();
//if A1's first character is not # AND
if (s.getRange('A1').getValue().substring(0,1) === "#" &&
//if A2's first character is not ' AND
s.getRange('A1').offset(1, 0).getValue().substring(0,1) === "-" ) {
//Set the value of A2 to...
s.getRange('A1').offset(2, 1).setValue(
//A2 cell content + " " + A2 cell content (concatenate)
s.getRange('A1').offset(2, 1).getValue() + " " +
s.getRange('A1').offset(3, 1).getValue())
//and then clear A2
s.getRange('A1').offset(3, 1).clearContent()
};
}
The following is where everything falls apart - the loop. I've only left the bare bones in this final copy of the code:
function notWorkingCombineAndClearWithLoop() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var numRows = SpreadsheetApp.getActiveSheet().getRange("A:A").getLastRow();
//loop
//how to replace 'A1' with A[i]?, so that it loops through all cells in the column?
for (var i = 0; i < 25; i++) {
if (s.getRange('A1').getValue().substring(0,1) === "#" &&
s.getRange('A1').offset(1, 0).getValue().substring(0,1) === "-" ) {
s.getRange('A1').offset(2, 1).setValue(
s.getRange('A1').offset(2, 1).getValue() + " " +
s.getRange('A1').offset(3, 1).getValue())
s.getRange('A1').offset(3, 1).clearContent()
}
};
}
Note: I've completed Codacademy's JS course and several Google Sheets tutorials, and am pretty good at VBA, but I'm still swimming in circles with this. I've tried to follow many loop examples, using variables in place of A1. Because I can't find any working solution, I've left the non-functioning A1 as a simple placeholder.
Short answer
//how to replace 'A1' with A[i]?, so that it loops through all cells
//in the column?
Use
'A' + i
Explanation
getRange() has several forms, one of them use A1 notation reference. This is used in concordance with the Google Apps Script included in the question.
Example
The main intention of below code is to show how to use the A1 notation to loop through the cells of a column in Google Apps Script.
There was some errors in the indexes. They were corrected.
Also changed the fourth line to reduce the rows to loop through and added a couple of lines.
function editedNotWorkingCombineAndClearWithLoop() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var numRows = SpreadsheetApp.getActiveSheet().getLastRow();
/*
* use variables to reduce number of calls to Apps Script services
* and improve readability
*/
var range, substring1, substring2;
//loop
for (var i = 1; i <= numRows; i++) {
//Here is the magic
range = s.getRange('A' + i );
substring1 = range.getValue().substring(0,1);
substring2 = range.offset(1, 0).getValue().substring(0,1);
if ( substring1 === '#' && substring2 === '-' ) {
range.offset(0, 1).setValue(range.getValue());
range.offset(1, 1).setValue(range.offset(1, 0).getValue());
range.offset(2, 1).setValue(
range.offset(2, 0).getValue()
+ " "
+ range.offset(3, 0).getValue()
)
}
}
}