Generate Google Map from Addresses in Google Sheet - google-maps

I'd like to create a Google Map that pulls addresses from a google sheet. I've figured out how to generate a map search of a single address (see below), but can't figure out how to get my map to plot multiple addresses.
function sendMap2() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Summary');
var address = sheet.getRange('C15:C17').getValue();
var mapUrl = "https://www.google.com/maps/search/?api=1&query=";
var mapQuery = encodeURIComponent(address);
GmailApp.sendEmail('emailaddress#gmail.com', 'Map', 'Map Link: '+mapUrl+mapQuery );
}

Problem:
You are using getValue, which will only return the top-left cell in the range you specify (that is, C15).
Solution:
If you want to get all the addresses in the range, you have to use getValues instead. This will return a two-dimensional array of values, which I'd suggest you to transform to a simple array of addresses. You can then iterate through each address in this array, appending each array to the body of the email message with concat().
It could be something along the following lines:
function sendMap2() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Summary');
var values = sheet.getRange('C15:C17').getValues();
var addresses = [];
for (var i = 0; i < values.length; i++) {
addresses = addresses.concat(values[i]);
}
var body = "";
for (var j = 0; j < addresses.length; j++) {
var mapUrl = "https://www.google.com/maps/search/?api=1&query=";
var mapQuery = encodeURIComponent(addresses[j]);
body = body.concat('Map Link: ' + mapUrl + mapQuery + '\n');
}
GmailApp.sendEmail('your-email', 'Map', body);
}
UPDATE:
If you want to point to several addresses in a single URL, you can use this instead:
var mapUrl = "https://www.google.com/maps/dir/";
var body = 'Map Link: ' + mapUrl;
for (var j = 0; j < addresses.length; j++) {
var mapQuery = encodeURIComponent(addresses[j]);
body = body.concat(mapQuery + '/');
}
GmailApp.sendEmail('your-email', 'Map', body);
}
Reference:
Range.getValue
Range.getValues
String.prototype.concat()

Related

How to add hyperlink in table (or array) in a Google Doc using Google DOC API Script?

I am having the following code for appending table in Google Docs.
var sss = SpreadsheetApp.openById('id of spreadsheet');
var rawData = sss.getDataRange().getValues()
var data = []
for (var i = 0; i< rawData.length; i++){
tempData=[]
tempData=[rawData[i][1],rawData[i][2],rawData[i][3]]
data.push(tempData)
}
var someDoc = DocumentApp.openById(someId);
var body = someDoc.getBody();
body.appendTable(data).editAsText().setBold(false);
This code works fine. The problem is that there is url in rawdata[i][3]. It gets displayed in Google doc as plain text. How can I convert it into hyperlink? It would be even better if it is possible to write it as body.appendParagraph("my link").setLinkUrl("http://www.google.com"). The problem is that it is in an array, not in paragraph.
I believe your goal is as follows.
You want to put a table to Google Document by retrieving the values from Google Spreadsheet.
In your Spreadsheet, the column "D" has the hyperlinks. And, you want to set the value as the hyperlink.
In this case, how about the following modification?
Modified script:
var sss = SpreadsheetApp.openById('id of spreadsheet');
var rawData = sss.getDataRange().getValues();
var data = []
for (var i = 0; i < rawData.length; i++) {
tempData = []
tempData = [rawData[i][1], rawData[i][2], rawData[i][3]]
data.push(tempData)
}
var someDoc = DocumentApp.openById(someId);
var body = someDoc.getBody();
// I modified below script.
var table = body.appendTable(data);
for (var r = 0; r < table.getNumRows(); r++) {
var obj = table.getCell(r, 2).editAsText();
var text = obj.getText();
if (/^https?:\/\//.test(text)) obj.setLinkUrl(text);
}
table.editAsText().setBold(false);
When this script is run, a table is put using the values retrieved from Spreadsheet. And, about the column "C" of the table, the text is changed to the hyperlink.
Note:
This modified script supposes that your values of column "D" are like https://### and http://###. Please be careful about this.
If you want to give the specific text (for example, click here) with the hyperlink, please modify as follows.
From
if (/^https?:\/\//.test(text)) obj.setLinkUrl(text);
To
if (/^https?:\/\//.test(text)) obj.setText("click here").setLinkUrl(text);
References:
getCell(rowIndex, cellIndex) of Class Table
setLinkUrl(url)
You can try the following to make all URLs in a Google Doc clickable:
function urlClickable() {
var urlRegex = 'http[s]?:\/\/[^ ]+';
var doc = DocumentApp.openById('yourDocId');
var body = doc.getBody();
var urlElement = body.findText(urlRegex);
while (urlElement != null) {
var text = urlElement.getElement().asText();
var startOffset = urlElement.getStartOffset();
var endOffset = urlElement.getEndOffsetInclusive();
text.setLinkUrl(startOffset, endOffset, getUrl(text.getText()));
urlElement = body.findText(urlRegex, urlElement);
}
}
function getUrl(text) {
var startOffset = text.indexOf('http');
var endOffset = text.indexOf(' ', startOffset);
if (endOffset === -1) {
endOffset = text.length;
}
return text.substring(startOffset, endOffset);
}

How to change cell values?

I'm using Google app script for sheets and I'm new to it.
I have a column with number and a hyperlink in each cell (each link and number is different).
I want to get the link then make an API request which will return a number which will replace that original number for each cell.
At the moment here is my function:
function getLinkUrls() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("B2:B");
var values = range.getRichTextValues();
for (var i = 0; i < values.length; i++) {
for (var j = 0; j < values[i].length; j++) {
if (values[i][j].getLinkUrl() !== null) {
const val = values[i][j],
url = val.getLinkUrl(),
path = url.split('/')[3];
var response = UrlFetchApp.fetch(`https://decapi.me/twitch/followcount/${path}`),
f = response.getContentText();
}
}
}
}
I want to replace each cell now with f but I'm unsure how.
Table:
Column B should always have hyperlink
I have successful replace the hyperlink with the follower count, you may try if working on your side also, since I did not use getrichtext but getvalue directly:
function getLinkUrls1() {
var sheet = SpreadsheetApp.getActiveSheet();
for (var i = 2; i <= sheet.getLastRow(); i++) {
var url = sheet.getRange(i,2).getRichTextValue().getLinkUrl();
if (url){
var path = url.split('/')[3];
var response = UrlFetchApp.fetch(`https://decapi.me/twitch/followcount/${path}`),
f = response.getContentText();
sheet.getRange(i,2).setRichTextValue(SpreadsheetApp.newRichTextValue()
.setText(f).build());
}
}
}
This is my sample data:

Displaying array data in Google sheets vertically

This is probably an easy fix but I'm not sure why the array of matching emails are being outputted horizontally and not vertically in Google Sheets. I want all the emails to be in a specific column so the must be outputted vertically with each email being in an individual cell. I tried using the split method to separate the array into individual cells but only the first email is displayed.
function getTheDesiredContacts() {
var SS =SpreadsheetApp.getActiveSpreadsheet();
var EmailSheet = SS.getSheetByName("Threads");
var Contacts = ContactsApp.getContactGroup("Employees").getContacts();
var EmailsArray = [];
var label = GmailApp.getUserLabelByName(LABEL);
var MaxColumnCount = 30;
var threads = label.getThreads();
for(var i = 0, n = Contacts.length, x = 0; i < n; i++){
if(i < MaxColumnCount){
EmailsArray.push([]);
}
EmailsArray[x] = Contacts[i].getEmailAddresses()[0];
x++;
}
if (threads.length > 0) {
for (var t=threads.length-1; t>=0; t-- ){
var labels = threads[t].getLabels();
}
for (var i in labels) {
var z= labels[i].getName();
}
if(z==LABEL){
var EMails = GmailApp.getMessagesForThreads(
GmailApp.search("label:" + labels[i].getName())).reduce(function(a, b){
return a.concat(b);}).map(function(EMails){
return EMails.getFrom();
});
var AEmail = EMails.sort().filter(function(el,j,a){
if(j==a.indexOf(el))
return 1;return 0
});
var deDup = new Array();
for(var k in AEmail) {
var str = AEmail[k].split("<").pop();
str=str.replace(">",'');
deDup.push(str);
}
}
}
var matchingEM = new Array();
for(var m in EmailsArray){
for(var o in deDup){
if(EmailsArray[m]==deDup[o]){
matchingEM.push(deDup);
}
}
}
var unq = matchingEM.filter((item, i, ar) => ar.indexOf(item) === i);
var unique = unq.join();
var uniqueOff = unique.split(',');
var uniqueemails= new Array;
uniqueemails.push([unique]);
Logger.log("These are the matching emails: " + uniqueemails);
EmailSheet.getRange(2,4, uniqueemails.length,1).setValues([uniqueemails]);
return uniqueOff
}
Modification points:
When I saw your script, it seems that uniqueemails of EmailSheet.getRange(2,4, uniqueemails.length,1).setValues([uniqueemails]); is [["value1,value2,,,"]] that value1,value2,,, is a string value. In this case, the values are put to a cell. This is due to var unique = unq.join();. In order to put the values to the row direction, the array is required to be like [["value1"],["value2"],,,].
For this, how about the following modification?
Modified script:
Please modify your script as follows.
From:
var unq = matchingEM.filter((item, i, ar) => ar.indexOf(item) === i);
var unique = unq.join();
var uniqueOff = unique.split(',');
var uniqueemails= new Array;
uniqueemails.push([unique]);
Logger.log("These are the matching emails: " + uniqueemails);
EmailSheet.getRange(2,4, uniqueemails.length,1).setValues([uniqueemails]);
To:
var uniqueemails = matchingEM.filter((item, i, ar) => ar.indexOf(item) === i)[0].map(e => [e]);
EmailSheet.getRange(2, 4, uniqueemails.length, 1).setValues(uniqueemails);
In above modified script, the values are put from the cell "D2" to the row direction. This is from your script. If you want to put the values to other rows, please modify above script.
Note:
In this modified script, it supposes that your script currently works with no errors. Please be careful this.
References:
map()
setValues(values)

Google Sheets Apps Script RichTextValueBuilder Parameters Don't Match method Signature

I am working to programmatically display a list of residents for a "know your neighbors map" community project. I want to take any number of first & last names for a residence and list them with last names in bold and leading any first names & numbers. The kludge code below or from the link is my first pass. I have tried various iterations to get the exception to go away, but I have been unsuccessful and I can't find anything concrete in the documentation or on the Googles.
Make a copy and run it yourself with this link: https://docs.google.com/spreadsheets/d/1rWHG5CKHvFzohTq9fSl8p8AjNcFjX0Tatior_hvOncE/copy
I'm getting the following error: "Exception: The parameters (SpreadsheetApp.RichTextValueBuilder) don't match the method signature for SpreadsheetApp.Range.setRichTextValue. (line 49, file "Code")"
Any ideas?
Kludge down here!
function main() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheetByName('Data');
var address_array = dataSheet.getRange('AddressData').getValues();
var bold = SpreadsheetApp.newTextStyle().setBold(true).build();
var resident_count = 1;
for (var i = 0; i < address_array.length; i++) {
var resident_array = address_array[i];
var resident_cell_range_name = 'Resident' + resident_count.toString();
var resident_cell = dataSheet.getRange(resident_cell_range_name);
var resident_text_array = [];
var resident_bold = [];
for (var j = 0; j < resident_array.length; j += 3) {
var last = resident_array[j];
var first = resident_array[j + 1];
var number = resident_array[j + 2];
if (last) {
var bold_start_stop = [];
var total = length_all(resident_text_array);
bold_start_stop.push(total);
bold_start_stop.push(total + last.length);
resident_bold.push(bold_start_stop);
resident_text_array.push(last)
}
if (first) {
if (number) {
var name_num = first + ' - ' + number;
resident_text_array.push(name_num)
}
else {
resident_text_array.push(first)
}
} else {
if (number) {
resident_text_array.push(number)
}
}
}
var value = SpreadsheetApp.newRichTextValue();
var resident_text = 'Some text';
// var resident_text = resident_text_array.join(String.fromCharCode(10));
// var resident_text = resident_text_array.join(' ');
value.setText(resident_text);
// for (start_stop of resident_bold) {
// value.setTextStyle(start_stop[0], start_stop[1], bold);
// }
value.build();
// resident_cell.setValue('text');
resident_cell.setRichTextValue(value);
Logger.log(resident_text_array);
resident_count += 1;
}
Logger.log(address_array);
}
function length_all(resident_text_array){
var total = 0;
for (each of resident_text_array) {
total = total + each.length;
}
return total;
}
The issue was using the build() command outside of the setRichTextValue() function.
Original that led to the exception:
value.build();
resident_cell.setRichTextValue(value);
Fixed:
resident_cell.setRichTextValue(value.build());
I'm not sure why, but that did it!

Get data from array in nested json using Google Script

I need to fix a Google Script I've been working on. Basically, I have a json https://www.instagram.com/nike/?__a=1 that returns basic info about Nike's account on instagram. I have no problem retrieving data from objects such as "biography". But, when I try to retrieve nested objects (arrays) I'm doing something wrong because the results arrive duplicated (see attachment). Can anyone help me figure out what I'm doing wrong?
// the name of the sheet within your document
var sheetName = "Sheet1";
// the name of the Instagram account you want the follower count for
var instagramAccountName = "nike";
function insert() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(this.sheetName);
var followers = [];
var followers = captionArray(this.instagramAccountName);
for(var i = 0 ; i < 3; i++) {
sheet.appendRow([Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd"), followers]);
};
}
function captionArray(username) {
var i = 0;
for(var i = 0; i < 3; i++) {
var url = "https://www.instagram.com/" + username + "/?__a=1";
var response = UrlFetchApp.fetch(url).getContentText();
var caption = [];
var caption = JSON.parse(response).graphql.user.edge_owner_to_timeline_media.edges[i].node.edge_media_to_caption.edges[i].node.text;
return caption;
};
}
I think this is causing problems:
You're using the same index (i) for both arrays, but the second have only one element.
You just need to do one request.
This code works for me:
function captionArray(username) {
var captions = [];
var url = "https://www.instagram.com/nike/?__a=1";
var response = UrlFetchApp.fetch(url).getContentText();
var edges = JSON.parse(response).graphql.user.edge_owner_to_timeline_media.edges;
for(var i = 0, limit = edges.length; i < limit; i++) {
captions.push(edges[i].node.edge_media_to_caption.edges[0].node.text);
}
return captions;
}