Turning an email address in a cell into a clickable link - google-apps-script

I have a column of email addresses and would really like to turn them into clickable links. I am a rookie coder still and trying to figure this out. So the code below is from trying to record a macro in google app script. I need it to reference the current cell, turn that cells email address into a link to it, then move down the column.
Should be super simple, take cell A1's contents, turn into link of the contents in the cell, then move down the list and do it again until it completes the entire column.
function emailing() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getActiveRangeList().setShowHyperlink(true);
spreadsheet.getCurrentCell().setFormulaR1C1('=HYPERLINK("mailto:test#emailaddress.com","test#emailaddress.com")');
};
Each email will be turned into a link to that email address.

I have tested the following code and worked successfully converting each email to a hyperlink. Assuming you want to convert all of them when you use the macro, this code works for you:
function emailing() {
var sheet = SpreadsheetApp.getActiveSheet();
for(i=0; i<1048576; i++) {
var gcells = sheet.getRange(6 + i, 6); //In my test i put the emails in the F column starting from the 6th row.
var email = gcells.getValue();
if (gcells.isBlank()) {
break
}
gcells.setFormulaR1C1('=HYPERLINK("mailto:' + email + '","' + email + '")');
}
}
I used the number 1048576 as the limit on the for because that's the maximum number of rows you can have, although it'll break when it takes a blank cell.
If what you want is to convert to a hyperlink only the cell you have selected and then change the selected cell, you should use the getActiveCell function [1] to set only that value and then the activate() function [2] to change the selection to the next cell.
[1] https://developers.google.com/apps-script/reference/spreadsheet/sheet#getactivecell
[2] https://developers.google.com/apps-script/reference/spreadsheet/range#activate()

Related

Google sheet script to search and retrieve Gmail data

I've started a script that matches an email address in Col D with Gmail and writes the last message date in Col E. I'd like that script to repeat row by row - now it only writes to Row 2 (newbie question - sorry).
I'd also like to search for data in addition to "from". I'd like to also search "to" and other variables.
Lastly, I'd like this to have a trigger that is time-based (daily or weekly) and I'm still getting my head wrapped around triggers, so any help is really appreciated.
function myFunction() {
// Get the value in the cell D2 (which will have the email to check the latest interaction)
var ss =
SpreadsheetApp.getActive().getSheetByName('Sheet1').getRange('D2').getValue();
// Search the date of the last message of the search from the email in cell D1 and log it
var latestEmail = GmailApp.search('from:"'+ss+'"')[0].getLastMessageDate();
Logger.log(latestEmail);
// Print the date on the cell to the right
SpreadsheetApp.getActive().getSheetByName('Sheet1').getRange('E2').setValue(latestEmail);
}
I'd like that script to repeat row by row - now it only writes to Row 2
You will need to iterate ("loop") through your sheet's rows.
Try this:
function myFunction() {
const sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1')
const addresses = sheet.getRange(2, 4, sheet.getLastRow()-1).getValues().flat().filter(Boolean)
for (let [index, address] of addresses.entries()) {
const latestEmail = GmailApp.search(`from: ${address}`)[0].getLastMessageDate()
sheet.getRange(index+2, 5).setValue(latestEmail);
}
}
Commented:
function myFunction() {
// Your sheet.
const sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1')
// All cells in Column D (Column 4).
const addresses = sheet.getRange(2, 4, sheet.getLastRow()-1).getValues().flat().filter(Boolean)
// For each address in Column D... (While keeping track of the index)
for (let [index, address] of addresses.entries()) {
// Get the last message date from this address...
const latestEmail = GmailApp.search(`from: ${address}`)[0].getLastMessageDate()
// And set the adjacent cell to that date.
sheet.getRange(index+2, 5).setValue(latestEmail);
// "Index+2" because index starts at 0 and we started our range at row 2.
}
}
I'd also like to search for data in addition to "from". I'd like to also search "to" and other variables.
That can all be done using GmailApp.search()
Lastly, I'd like this to have a trigger that is time-based (daily or weekly) and I'm still getting my head wrapped around triggers, so any help is really appreciated.
Couldn't be easier, see here:
Managing triggers manually
In your Script Editor, click the Triggers icon and then click the Add Trigger button.
You will be looking to choose this function, from event source: "Time-driven", and select when you would like it to run.

getlastrow, then last column, and then populate based on that information

Recently, there was a program by the name of Eddienuput that allows you to properly train against basically anything in training mode. One issue is that you have to make a text file with all the button presses, as well as the timing for each. Once this text file is made, the inputs are added into a virtual controller.
The working sheet can be seen here.
The idea here is that you put the data of the character on the second sheet, then on the generator sheet you select the buttons you want, then press the [>] to put it to the right of the current buttons stored, and you use the [v] button.
When I hit the down arrow (I've assigned the script to the buttons), the three entries needed for the program to register the input are inserted one row below the active row.
The problem is the Right arrow. I sort of have it right (it puts the three inputs needed to the right.. but it isn't finding the bottom-right entry and putting it to the right of it, but instead it looks for the furthest right column and puts it to the right of everything instead of next to the last cell on the last row.
here is the code as I have it now:
function addbuttontoString()
{
//DEFINE ALL ACTIVE SHEETS
var ss = SpreadsheetApp.getActiveSpreadsheet();
var eddGenSheet = ss.getSheetByName("Eddie Input Generator");
var lrwithcontentofEddGenSheet = eddGenSheet.getLastRow()+1;
var lcwithcontentofEddGenSheet = eddGenSheet.getLastColumn();
var CharacterFrameDataSheet = ss.getSheetByName("CharacterFrameData");
//Current string Variables
var totalcurrentstringRows = lrwithcontentofEddGenSheet-4;
var fullcurrentString = eddGenSheet.getRange(5,1,totalcurrentstringRows, lcwithcontentofEddGenSheet);
var cslastRow = fullcurrentString.getLastRow();
var bottomrightcolumnNumber = eddGenSheet.getRange(lrwithcontentofEddGenSheet,1,1,lcwithcontentofEddGenSheet).getLastColumn();
Logger.log(bottomrightcolumnNumber)
//GET LAST ROW #OF ITEM SHEET
var lastrowItem = CharacterFrameDataSheet.getLastRow();
// Get the perfect Eddie value from Character Frame Data you are grabbing data for
var button = eddGenSheet.getRange('B4').getValue();
// Set up the Perfect Frame Variable
for(var i = 2; i <= lastrowItem; i++)
{
if(button == CharacterFrameDataSheet.getRange(i, 1).getValue())
{
var Perfectframe = CharacterFrameDataSheet.getRange(i, 4).getValue();
}
}
Logger.log(fullcurrentString.isBlank());
if(fullcurrentString.isBlank()){
// POPULATE eddGen SHEET Same Line
eddGenSheet.getRange("A5").setValue(button);
eddGenSheet.getRange("B5").setValue("F");
eddGenSheet.getRange("C5" ).setValue(Perfectframe);
} else {
eddGenSheet.getRange(lrwithcontentofEddGenSheet-1, bottomrightcolumnNumber +1).setValue(button);
eddGenSheet.getRange(lrwithcontentofEddGenSheet-1, bottomrightcolumnNumber +2).setValue("W");
eddGenSheet.getRange(lrwithcontentofEddGenSheet-1, bottomrightcolumnNumber +3).setValue(Perfectframe);
}
}
I believe your goal as follows.
When you click the right arrow button, you want to add the values from the 1st empty column of the row.
In your script, in order to retrieve the coordinate of the column for putting values, getLastColumn() is used as follows. In this case, the 1st empty column of the row is not retrieved. The last column of the sheet is retrieved. So, how about the following modification?
From:
var bottomrightcolumnNumber = eddGenSheet.getRange(lrwithcontentofEddGenSheet,1,1,lcwithcontentofEddGenSheet).getLastColumn();
To:
var bottomrightcolumnNumber = eddGenSheet.getRange(lrwithcontentofEddGenSheet - 1, 1).getNextDataCell(SpreadsheetApp.Direction.NEXT).getColumn();
In this modification, the 1st empty column is retrieved using getNextDataCell().
Note:
I'm not sure about your actual situation. So when above modification was not useful for your situation, can you provide the detail information about your actual situation? By this, I would like to modify it.
References:
getLastColumn()
getNextDataCell(direction)

How do I use a dropdown menu to change the cell contents of a range?

So I have a file on Sheets, and in the file is a section of cells that are formatted so when you enter "0", they are empty circles, and when you enter any other number (I just go with "1" to make it easy), the circles are filled. I know I could probably use the formulas in the actual sheet, but I'd like the option to edit the cells individually. I really only need the dropdown to fill them all at once or clear them all to save time. And the dropdown has options "Clear" and "Fill".
I have the dropdown menu in grouped cells AG97:AN97 and I'd like to be able to change the cells in W100:W103 (there are more ranges, but one step at a time.)
I've tried using previous questions to help me, but I can't seem to grasp the code.
function addValidation() {
var range = SpreadsheetApp.openById('(SHEETID)');
var sheet = ss.getSheets()[0];
var values = range.getValues();
var data = sheet.getDataRange().getValues();
var rule = SpreadsheetApp.newDataValidation().requireValueInList(["Clear", "Fill"]).build();
for(var i=0; i<data.length; i++) {
if(data[i][22] == "Clear") {
sheet.getRange(i+100, 7).clear().setDataValidation(rule);
}
}
}
I replaced the sheet idea just for the purpose of showing code. I tried to get the clear function to work before I tried working on fill, but no luck. I keep getting "Bad value (line 2, file "Code")"
"Bad value (line 2, file "Code")" means that you inserted your SpreadsheetID incorrectly.
If your Spreadsheet URl is something like
https://docs.google.com/spreadsheets/d/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/edit#gid=0, then the ID is the part designated with X - usualy 44 characters long.
Yuo need to pass it to the method openById() in quotes (or double quotes), but without brackets:
SpreadsheetApp.openById('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
Also, probably you want to assign it to a variable called ss rather than range, given your next line is var sheet = ss.getSheets()[0];.

Google Apps Scripts Send automated email with trigger (not repetitively)

I'm attempting to set up automated emails through google sheets using scripts and a trigger.
How do I define only new additions to the spreadsheet should trigger an email? The spreadsheet is constantly added to.
function sendloggeremails() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow()
for (var i = 72; i <= lr; i++) {
var currentEmail = ss.getRange(i, 7).getValue();
var currentClassTitle = ss.getRange(i, 3).getValue();
MailApp.sendEmail(currentEmail, "complaint: customer number " + currentClassTitle , "Please check through the log as you have a new assigned to you");
}
}
var i = 72 plainly because this is the last row, I don't want to have to manually change this constantly. Added triggers but at the moment I still need to go into the code to change var i.
Any chance anyone can help with this?
Sending Emails only Once with a Loop
You could use something like this. To get started you would want to put something in the sent column so that old lines would not resend their emails and you'd still maintain a record of past emails. I suggested putting the string "SENT". But the test just ask the question is that column empty so anything will work.
Obviously, I haven't seen you spreadsheet so I don't know where to put the sentColumn so you can change the var sentColumn = 75 to anything you wish and all of the other places it's used will change accordingly.
function sendloggeremails() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sh=ss.getActiveSheet();//You should probably change this to getSheetByName() and then put in the correct name of the sheet
var sentColumn=75;//If this column is not empty then don't send emails. If you send any email then also put "SENT" into this column so you wont resend it next time you run the loop.
sh.getRange(1,sentColumn).setValue("Sent");//I'm assuming a header row and I'm putting a Header Title there you can pick any open column you want
var rg=sh.getDataRange();//This gets all of the sheets data into one one range
var vA=rg.getValues();//This gets all of the values in above range in a two dimension object we often refer to as a two dimensional array.
//If you have header row you can start at i=1
for(var i=1;i<vA.length; i++) {//This will loop over all of the rows on the sheet.
if(!vA[i][sentColumn-1]){//Heres the test to see if theres something in sentColumn. If sentColumn is empty meaning truthy is false then it send the email
var currentEmail=vA[i][6];//this replaces the getValue from column7 *1
var currentClassTitle=vA[i][2];//this replaces the getValue from column3 *1
MailApp.sendEmail(currentEmail, "complaint: customer number " + currentClassTitle , "Please check through the log as you have a new assigned to you");
sh.getRange(i+1,sentColumn).setValue("SENT");//After sending email we put something. In this case "SENT" into the sentColumn so that next through the loop we won send another email because its truthy will be true.
}
}
}
//*1 Array indices are 1 less that column numbers because arrays start counting from zero.
If you wish we could also delete the rows as we send them. All you have to do is keep track of how many rows you have deleted each time the loop is run with say a variable like var n=0 to start with and then the row number that gets deleted will be i-n+1. And right after the deletion you increment n by one.
You can setup the trigger using this function.
function setupEmailTrigger() {
if(ScriptApp.getProjectTriggers().indexOf('sendloggeremails')==-1){
ScriptApp.newTrigger('sendloggeremails').timeBased().everyDays(1).atHour(17).create();
}
}
It checks to see if the trigger already exists and if the trigger already exists it does nothing.

Append data on Google Sheets script editor

I have a script where a user inputs some information on the user tab. Then, they hit a button which triggers a script to dump the information they input into a separate tab which I'm calling the repository. This code is working flawlessly:
function dumpInputsToRepository(button) {
var userSheet = SpreadsheetApp.getActiveSpreadsheet();
var userTab = userSheet.getSheetByName('PhoneSelect');
var firstRow = 6;
var range = userTab.getRange(firstRow, 1, userTab.getLastRow() - firstRow +1, 10);
var data = range.getValues();
var repTab = userSheet.getSheetByName('Rep');
repTab.getRange(repTab.getLastRow() + 1, 1, data.length, 10).setValues(data);
In the repository list, I want to add two columns of data on the right side of what is being input. Specifically, I want a column which produces the timestamp of when the button was pushed, and I want another column which produces the email address of the person who pushed the button.
For the timestamp, I had the idea to add an extra column in the user tab with =Now() function, and then just extend the inputs to 11 columns of data being moved to the repository. That works, but I figure there is a more elegant solution which I could input.
Getting the email to be produced in the final column has eluded me. I've tried to rework some code from here: https://developers.google.com/apps-script/reference/base/session#getActiveUser()
But I can't get my email address to appear anywhere let alone appended to to the data that is being sent from the user sheet to repository sheet. Any help is greatly appreciated!