How to get url from Google Spreadsheet cell with Google Apps Script? - google-apps-script

I've got a google spreadsheet copied from excel ANd I have some problem with that.
This is my document https://docs.google.com/spreadsheets/d/1Ok_phu5OXtvKHLj3MLa7N3WV2qBdMWRz8dLHnTqjHrc/edit?usp=sharing
This is my code
function myFunction() {
cel = SpreadsheetApp.getActiveSpreadsheet().getActiveCell()
Logger.log(cel.getFormula())
Logger.log(cel.getValue())
}
And this is my log:
[16-10-05 13:39:59:628 EEST]
[16-10-05 13:39:59:629 EEST] RU: VTB Arena - Park and Hotel
And I need to get an URL (https://na3.salesforce.com/0065000000a1b8p) How can I do that?

At this time the Spreadsheet Service of Google Apps Script is not able to get the properties of cells rich text content, just the plain text by using getValue() method. Other methods like getFormula(), getNote() are able to get the corresponding cell property, but none of the them includes the URL of the link.
On Google Sheets the workaround is to get the URL manually. A programmatically alternative is, to use VBA on the Excel file to get the hyperlinks before converting the file to the Google Sheets format. See the answer to Can I use an excel formula to extract the link location of a hyperlink in a cell? for details.

I think it's best to publish the google spreadsheet to the web and then parse the html with BS4 to get the urls.

Here's a workaround I used to get links from cells. Apparently when you use ctrl+K to add links they are added as rich text rather than as formulas. I used the function below in a google sheet to turn these rich text fields with links into html. If there is a link in the field then it returns the html code for the link. If there isn't a link then it simply returns the text passed in. Of course this could be done more elegantly ... I used lots of variables to make it easier to follow what was going on.
//get link from a cell given by A1 notation
function getHtmlfromRichTextRange(theRange){
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var range = sheet.getRange(theRange);
var cell = range;
var cellValue = cell.getRichTextValue();
var cellText = cell.getValue();
var theThing = cellValue.getLinkUrl();
if (theThing == null){
return cellText;
} else {
return ''+cellText+'';
}
}
In a spreadsheet you could do something like (see image 1):
In cell A1, enter "a link to apple"
With cell A1 highlighted, press ctrl+k to add the hyperlink to http://www.apple.com
In cell B1, enter A1
In Cell C1, enter the formula =getHtmlfromRichTextRange(B1)
As a result, you should see the value
a link to apple in cell C1
A couple of things I noticed when working with this example in this way:
If the function in C1 returned just the url and not the url with some String text around it, then Google sheets turned C1 into RichText, too. Since I was using this to create html emails, I had the function return the HTML code for the link.
I could have simplified and passed the String "A1" in quotes the function. I was trying to find a way to have the formula in C1 update when the richtext link in A1 was updated. My thought was that if A1 changed (e.g. the URL changed), then the result of the function in C1 would automatically update. It doesn't. I didn't pursue it. What is written above did the trick for me.
This code worked if the link was all the text in the cell. If the cell had some text in it that had the hyperlink and some text that did not (e.g. the hyperlink was only part of the text in the cell) then this code returned it as plain text and not as a URL.
I used the function as-is in AppScript to loop over a range that contained links. Inside the loop I passed the function the A1 notation of the cells, some of which had links. It worked beautifully and saved me loads of time!
I'm sure there's an easier way. I typically find that after doing it the harder way and thus don't need to do it anymore.

Thanks for asking this question! I've been looking for this myself! I copied a list of Facebook friends into a spreadsheet. They copied as Rich Text, meaning they contained a link, but it wasn't available in =Hypertext format.
I searched forever and it seemed certain there's no easy way around this.
Then I stumbled upon it.
Just select the cell containing the Rich Text (assuming you want to get the link it contains when you hover over it) and hit Command-K to Edit Link.
It will bring up a window where you can enter the Cell Text in the top field, and the URL in the bottom field.
No need to enter anything - it's there by default. So just hit [Enter] and BAM! It's now formatted as =HYPERLINK("URL","Text")
But I had HUNDREDS of these to convert and wanted to find an easier way.
And so I stumbled upon AppleScript (I've never used it til today - even though I'm transitioning away from Apple entirely).
I created a simple AppleScript:
tell application "Google Chrome" to activate
delay 0.5
tell application "System Events"
delay 0.5
tell process "Chrome"
keystroke "k" using command down
delay 0.2
keystroke return
delay 0.2
keystroke return
delay 0.2
keystroke return
delay 0.2
end tell
end tell
Select the cell you want to edit in your spreadsheet (assuming you're using Google Chrome) and then run this AppleScript.
I made several Scripts, all in US Currency amounts. So I have one that runs just once, and then a 5x, a 10x, a 20x, a 50x, and a 100x.
So for my list of 143 names, I just now ran the 100x script, then a 50x script. I sad back and took a sip of coffee while I watched my computer rapidly do the work for me.
Sorry if this is more info than people are looking for -- it's my first time answering a question here (that I recall) and, well, if I had stumbled across the answer I'm writing now -- it would have been a godsend earlier this year!
Happy coding!

This code works to fetch the URL from a column.
function testForUrlGet(){
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName("Zoom");
const range = sheet.getRange('C1:C500');
const values = range.getRichTextValues();
for(i=0; i<=values.length ; i++){
Logger.log(values[i][0].getLinkUrl());
}
}
I hope it helps as I could not find the answer for myself.

Try this:
var url = /"(.*?)"/.exec(cel.getFormulaR1C1())[1];
Logger.log(url);
It pulled the URL when I added it as a link manually.
Note that I used the following i my test:
var dataSheet = CentralSS.getSheetByName(CENTRAL_DATAFILES_SHEETNAME);
var range = dataSheet.getRange("E2");
var url = /"(.*?)"/.exec(range.getFormulaR1C1())[1];

Related

Activating a new cell not working within Google Sheets onSelection(e) execution?

Is there some way to force the selection of another cell (e.g. A1) after someone has selected a different cell (e.g. B2)? If i use a simple ...getRange(1,1).activate() code, it works when I hit "Run" in the script editor, but not when a selection is made in the real spreadsheet. Please help?
I've basically written a long "onSelection" code that allows someone to mark their answers to a trivia game as "Correct" or "Wrong" by clicking on the corresponding cells. (I do this with onSelection(e) because buttons don't work on mobile.)
However, if they get two answers correct in a row, onSelection(e) doesn't work because they've already selected "Correct" the first time. I want the code to select 'A1' automatically so it's ready for their next Correct/Wrong input.
A code as simple as the following works when I select any cell in Google Sheets and then hit "Run" in the script editor, but it doesn't not work when I select a cell with my mouse.
function onSelectionChange(e){
var sheet = SpreadsheetApp.getActiveSheet()
sheet.getRange(1,1).activate();
}

AppsScript with Google Sheets: Conditionally load images based on user interaction/when a range is selected

We've got a google sheet with user editable text that will eventually be used within images. We have a web application that generates the images and serves them, so they can be embedded within the IMAGE function provided within Sheets.
This works fine and ends up being something like:
=IMAGE(CONCAT("PREVIEW_TOOL_URL", "?t=", ENCODEURL(previewText(D2))), 3) where 'previewText' is simply formatting the string to pass to the web tool.
However, to avoid overloading the server and generating a ton of requests every single time someone loads the sheet, I'd like to make it so images only load in some condition (i.e. a user presses a button or they highlight the text), is there some way of doing this?
Add a checkbox to E2:
=IF(E2,IMAGE(CONCAT("PREVIEW_TOOL_URL", "?t=", ENCODEURL(previewText(D2))), 3),"Check to preview")
You can also use Apps Script for this!
You will have to start by:
Go to Tools > Create a new script;
Use the following script:
function loadImages() {
let sheet = SpreadsheetApp.openById("SPREADSHEET_ID").getSheetByName("SHEET_NAME");
sheet.getRange("CELL_YOU_WANT_TO_PLACE_THE_FORMULA").setFormula("YOUR_FORMULA");
}
Do not forget to adjust this script such that it meets your needs accordingly.
Insert a new drawing into the sheet;
Attach a script to it by going to the three dots symbol on the drawing; when asked about the name, input loadImages which is the function which we had created previously.
Press the button on the sheet and that's it!
Reference
setFormula(formula).

Google Sheets - Track Current Cell Selection?

How to Get the currently selected cell/range? was asked 3.5 years ago, but I'm hoping maybe some progress was made since then.
I'd like to make an interactive spreadsheet where there's a boolean grid that will display more information about the status of the currently selected cell in a static location, allowing users to quickly navigate using the arrow keys.
Referencing the previous instance of this question, I tried using the custom function below to get the cell address, although this isn't very dynamic.
function currentCell() {
return SpreadsheetApp.getActive().getActiveRange().getA1Notation();
}
When testing, this function returns the address of the cell the function is called from. I've tried pressing F5 while highlighting another cell and nothing happened. I've also dragged the formula across a selection and each cell only contains its own address (according to the documentation, it should contain the range).
I've also read Henrique's post on caching from 2012, and while I don't completely understand it, I get that we could not get scripts which update without edits being made or manual formula updates.
I would ideally like for the current cell to be tracked without any extra prompts from the user besides arrow key navigation or clicking to select a cell, but if pressing a non-altering key (like Enter) would allow for tracking, that would be fine. I also only need the selected cell, rather than a range, if that makes things easier.
Explicit Question: Is it possible to track the position of the currently selected cell in Google Sheets and store that position in a separate cell? If not, is there a way to do this without altering cell values?
EDIT: Adding an example for clarity. In this conceptual example, A2 =currentCell() as described above. If I were to hit the right arrow key, A2 would update to display I4, since it is now the current selection.
EDIT2: Jason Allshorn's response to Google app script monitor spreadsheet selected ranges appears to give a way of displaying the current selection (range) on the HTML input text. I'd like to do this, but store the value in a static cell on the sheet rather than input text. I'm new to scripting in Sheets and really only know what I've found for resolving this issue, so if I'm overlooking something, please let me know. I did look at Jason's example sheet and it wasn't clear to me what was actually happening there.
You will have to apply the technique suggested on How do I make a Sidebar display values from cells?. This consist on using using client-side code to constantly pulling values from the spreadsheet and then do the corresponding task.
One approach is to use a side-panel with an input field to set the cells to be tracked and another input field to set the destination cell.
You will have to use the onSelectionChange event in the app script to capture any selection change and then get the range name and put it in desired cell.
Something like the below:
function onSelectionChange(e) {
const range = e.range;
//Return in case of multi cell selection
if(range.getNumRows() !== 1 || range.getNumColumns() !== 1) return;
SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange("A2").setValue(range.getA1Notation());
}
You can see the official documentation here

Extracting a url from a HYPERLINK in Google Apps Script for Google Spreadsheet

Say I have =HYPERLINK("http://google.com/abc","Google") in A1 in my spreadsheet and I would like to create a custom Google Apps Script (eg. =GetURL(A1)) to return the url portion of this field. What would I have to do to get that working?
Whenever I create a custom script like so
function GetURL(input) {
return input
}
All I get is the description of the link, in this case "Google".
Is there any way of actually getting this working?
It's an old question, but I had the issue right now.
Turns out that when you add a hyperlink to text in a cell with the spreadsheet web-application, the text gets a rich text value.
(also see here of how to set a richt text value by Apps Script).
Therefore range.getFormula(); would get nothing, as there was no formula in the cell.
You can extract the link that is bound to the rich text with:
var value = range.getRichTextValue().getLinkUrl()
Doc for getRichTextValue and getLinkUrl
function getUrl(input) {
var range = SpreadsheetApp.getActiveSpreadsheet().getRange(input);
var value = range.getFormula();
return value;
}
This gets the raw formula =HYPERLINK("http://google.com/abc","Google" you can then regex or substring the URL out.
I did have to put the ss reference in like =getUrl("A1") with A1 in quotes to make it work.

Add custom Data to Google Sheet once Form is filled

I am using a Goofle form that receives applications from users, once the form is submitted I am using Google form submission trigger to notify. It has some questions like (facebook profile link)
But while sending a notification I don't want those links to be appeared just the same way user enters, instead something like Facebook, twitter (text as hyperlinked.) should appear
I already know about onFormsubmit() function, but not sure how to use, help me out please.
For example:
Cell A2 has user submitted facebook profile link using the form.
I want Column B2 to automatically generated as =hyperlink(A2, "Facebook")
The same thing should happen like A3 to B3 whenever user submits a form.
Ok after a bit of digging and testing, I believe I got a solution for you since you use the "Yet Another Mail Merge" (aka YAMM) add-on. Here it goes:
Firstly make sure your Form is setup properly and linked to a Google Sheet. After all questions have been created, add another column to your sheet, and call it 'Hyperlink' or whatever you please (just remember it for later). We will make use of the form submit trigger in the script editor along with some code.
Here's the code:
function onFormSubmit(e)
{
var r = e.range;
var v = e.namedValues;
var link = v['Link'];
// For testing purposes, this part was apart of my form,
// I'd assume you'd want to change it to something more
// usable in your case. Notice that I refer to the values
// by the name of the question they preside in.
var friendlyName = v['Friendly Name'];
var rngHyper = getCellRngByCol(r, 'Hyperlink');
// See below for the meaning of the boolean
addHyperlink(rngHyper, link, friendlyName, true);
}
// Will only return one cell no matter the range size.
// Perfect for onFormSubmit(e) use case.
function getCellRngByCol(rng, col)
{
var aRng = SpreadsheetApp.getActiveSheet().getDataRange();
var hRng = aRng.offset(0, 0, 1, aRng.getNumColumns()).getValues();
var colIndex = hRng[0].indexOf(col);
return SpreadsheetApp.getActiveSheet().getRange(rng.getRow(), colIndex + 1);
}
// Add some form of hyperlink reference to one particular
// cell, passed as a range object
function addHyperlink(rng, link, name, useFormula)
{
if (useFormula)
{
// If useFormula is TRUE, use Google Sheet HYPERLINK formula,
// only if you are sure all URL's are formated properly,
// and include HTTPS/HTTP/WWW. Also looks more pleasing in Google Sheet.
var formula = '=HYPERLINK("<<URL>>", "<<NAME>>")';
formula = formula.replace('<<URL>>', link).replace('<<NAME>>', name);
rng.setFormula(formula);
}
else
{
// Else use HTML <a> tag with hyperlink referencing, which should transform
// any URL passed as a clickable hyperlink within email. Not very visually
// appealing in Google Sheet.
var value = '<<NAME>>';
value = value.replace('<<URL>>', link).replace('<<NAME>>', name);
rng.setValue(value);
}
}
Then set the trigger, which will probably ask for authorization after saving:
Next, save the script and then put in a test submission through your form to see that the link is created properly, or as desired. Afterwards clear the rows of the spreadsheet (not the header) and remove all responses of the Form itself (not necessary, but keeps things organized for testing purposes).
Now, install the YAMM add-on. It should then add a new column at the end of your sheet called 'Merge satus'. Before setting up the email notification on submit, we need to create your email template. Open up GMAIL, create an email with the desired fields and layout and save it as a draft. Here's what I did as an example:
I'm sure you're familiar with how this add-on, works so I shouldn't need to explain too much here.
After the draft has been created and saved, go back to the Google Sheet attached to the Form. Go to Add-ons > YAMM > Configure form submission notifications. I chose the 'Notify one or more addresses of all responses' option which are tied to the 'To:' emails preset in the draft. Select your draft from the drop down, fill in sender name if needed, AND (very important!!) check the 'Wait until a specific column is filled before sending the email' check box. Make sure to select the Hyperlink column (or whatever you chose to name it earlier). Here's my setup for reference:
Save it, test it, and ta-da. This simple formatting for hyperlinks has been resolved! :D