google apps map get geocode from address in sheet - google-apps-script

Not sure why this stopped working. I'm trying to get the latitude & longitude from an address. Was working at one point. Not sure what happened. I'm listing the address in column U.
function geocode(){
var tkhCopy = SpreadsheetApp.openById('xxx').getSheetByName('tkhCopy');
var range = tkhCopy.getRange('U2:U');
var addresses = range.getValues();
// Determine the first row and column to geocode
var row = range.getRow();
var column = range.getColumn();
// Set default destination columns
var destination = new Array();
destination[0] = 22; // column + 1;
destination[1] = 23; // column + 2;
// tkhCopy.insertColumnsAfter(column, 2);
var geocoder = Maps.newGeocoder();
var count = range.getHeight();
// Iterate through addresses and geocode
for(i in addresses) {
var location = geocoder.geocode(
addresses[i]).results[0].geometry.location);
tkhCopy.getRange(row, destination[0]).setValue(location.lat);
tkhCopy.getRange(row++, destination[1]).setValue(location.lng);
Utilities.sleep(200);
}
}

You could have hit a quota on the number of times you can use the Geocoder service. Wait a day and try again.

Related

How to transfer one column of google sheet into google docs on particular places?

I have cities of London on google sheet and I want to take one column which named cities with postcodes to the google doc on particular places. I want that data to put into google doc that is shared in picture 2
That cities with postcode whole data into city name in google docs one by one
It could be something like this:
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = 'D5:D9'; // <--- set your range
var cities = sheet.getRange(range).getValues().flat();
var placeholder = '\\[bold\\]city name\\[/bold\\]';
var doc_ID = '###'; // <--- set ID of your document
var doc = DocumentApp.openById(doc_ID);
var body = doc.getBody();
while (cities.length) {
var find = body.findText(placeholder);
if (!find) break;
var city = '[bold]' + cities.shift() + '[/bold]';
find.getElement().asText().replaceText(placeholder, city);
}
}
This function takes list of city names form the range D5:D9 of current sheet, opens a document with given ID and changes the placeholders [bold]city name[/bold] with the city names.
It works fine if there is only one placeholder per paragraph. If a paragraph can contain two or more placeholders (for different cities) it needs another implementation.
Here is the variant that handles several placeholders within a paragraph:
function myFunction2() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = 'D5:D9'; // <--- set your range
var cities = sheet.getRange(range).getValues().flat();
var placeholder = '\\[bold\\]city name\\[/bold\\]';
var doc_ID = '###'; // set ID of your document
var doc = DocumentApp.openById(doc_ID);
var body = doc.getBody();
// based on https://stackoverflow.com/questions/51783382
var found = body.findText(placeholder);
while (found) {
if (cities.length == 0) break;
var city = '[bold]' + cities.shift() + '[/bold]';
var start = found.getStartOffset();
var end = found.getEndOffsetInclusive();
var text = found.getElement().asText();
text.insertText(end + 1, city);
text.deleteText(start, end);
found = body.findText(placeholder, found);
}
}
It should keep all font styles but it doesn't sometimes.

getting lat/long from address with geocode in google apps script

I've got this working code that gets the lat/long combo from an address.
function testgeocode(){
var responses = SpreadsheetApp.openById('###').getSheetByName('Form Responses');
var range = responses.getRange('AD2:AD');
var addresses = range.getValues();
var row = range.getRow();
var column = range.getColumn();
var destination = new Array();
destination[0] = 31; // column + 1;
destination[1] = 32; // column + 2;
var geocoder = Maps.newGeocoder();
var count = range.getHeight();
for(i in addresses) {
var location = geocoder.geocode(addresses[i]).results[0].geometry.location;
responses.getRange(row, destination[0]).setValue(location.lat);
responses.getRange(row++, destination[1]).setValue(location.lng);
Utilities.sleep(200);
}
}
I'm having difficulty modifying it so that the lat/long combo is outputted into one column with the format 'lat,long'.
Explanation / Issues:
First of all, your code is quite inefficient. The reason for that is because you are using getRange and setValue inside a for loop but also two times per iteration. As it is explained in the best practices, the proper way to achieve your goal is to store the values into an empty array and then use setValues outside the for loop to set them to your sheet.
The other modification is already mentioned in the other answer. You want to concatenate location.lat, location.lng separated by a comma.
Solution:
function testgeocode(){
var responses = SpreadsheetApp.openById('###').getSheetByName('Form Responses');
var range = responses.getRange('AD2:AD');
var addresses = range.getValues();
var row = range.getRow();
var column = range.getColumn();
var destination = new Array();
destination[0] = 31; // column + 1;
destination[1] = 32; // column + 2;
var geocoder = Maps.newGeocoder();
var count = range.getHeight();
var data = [];
for(i in addresses) {
var location = geocoder.geocode(addresses[i]).results[0].geometry.location;
data.push([location.lat + ',' + location.lng]) // new code
Utilities.sleep(200);
}
responses.getRange(2,destination[0],data.length,1).setValues(data); // new code
}
From what I understood, currently you're getting the latitude and longitude values and writing them to different cells, but you want to have them both in a single cell, separated by a comma.
If that's the case, then you can make the following changes.
From:
var location = geocoder.geocode(addresses[i]).results[0].geometry.location;
responses.getRange(row, destination[0]).setValue(location.lat);
responses.getRange(row++, destination[1]).setValue(location.lng);
To:
var location = geocoder.geocode(addresses[i]).results[0].geometry.location;
responses.getRange(row, destination[0]).setValue(location.lat + ',' + location.lng);
You can adjust the parameters of getRange() if you want to write it to a different cell.

Extract Google Analytics Data into Google Sheets

I have set up the Google analytics API on Google sheets for reporting purposes, however have had some issues:
How to add titles to the table?
function myFunction() {
var tableId = 'ga:*******' // Your Google Analytics view ID
var startDate = '2daysAgo';
var endDate = '1daysAgo';
var metric = 'ga:pageviews';
var options = {
'dimensions': 'ga:pageTitle, ga:date',
'sort': '-ga:date',
'filters': 'ga:pageTitle==(EN) SignUp Page'
};
var result = Analytics.Data.Ga.get(tableId, startDate, endDate, metric, options); // Make the request
var total_sessions = result.totalsForAllResults['ga:sessions'];
var total_transactions = result.totalsForAllResults['ga:transactions'];
var doc = SpreadsheetApp.getActiveSpreadsheet(); // Current document
var sheet = doc.getSheetByName('Sheet1'); // Current sheet
//sheet.getRange('B3').setValue(total_sessions); // Write total sessions
//sheet.getRange('B4').setValue(total_transactions); // Write toal transactions
var rows = result.rows;
for (var k = 0; k < rows.length; k++) {
var pagetitle= rows[k][0];
var date= rows[k][1];
var pageviews= rows[k][2];
var result_row = [pagetitle, date, pageviews]; // Single row of results
sheet.appendRow(result_row); // Print single row of results
}
}
use sheet.appendRow to add desired header row before looping through report rows.

More Efficient way to get and compare non-concurrent fields Google Sheets (Google App Script)

I am working on a solution that is essentially a change log, I am using the edit event trigger to capture the data that is being changed. After that I need to create a separate sheet that essentially shows a singular row for each person that had data changed but the data presented is the most current data. So if the unique id already exists on the sheet it is first deleted and then the new data is moved into the sheet.
The script i have is working but as it is not efficient it is possible for the users doing the input to "beat" the program run time.
The only solution I can think of is to read the values into an array but as i am new to the programing world and app script so i'm positive there is a solution that i am just not aware of yet.
Open to any ideas!
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sName = e.source.getActiveSheet().getSheetName();
var sNameActive = SpreadsheetApp.getActiveSheet();
if(sName == "D_Comp") { // enter the if statement only if changes we made on a sheet not named logging
var value;
var mA1 = e.range.getA1Notation().split(":")[0]; //range of change in A1 notation.
var col = e.range.getColumn(); // column number of where change occured
var row = e.range.getRow(); // row number of where the change occured
var time = new Date().toTimeString(); // time the change was made
var user = e.user;
var oldvalue; // defining the variable that will store the old value within the sheet
oldvalue = e.oldValue; // old value that was in the cell before hand
var aCell = e.source.getRange(mA1);
value = aCell.getValue();
var colhdr = ss.getActiveSheet().getRange(1, col).getValue(); // getting the header value
var Emplid = ss.getActiveSheet().getRange(row, 1).getValue(); // getting the emplid
var GUID = ss.getActiveSheet().getRange(row, 2).getValue(); // getting the GUID
var effdate= ss.getActiveSheet().getRange(row, 28).getValue(); // getting the change date
var Salary = ss.getActiveSheet().getRange(row, 44).getValue(); // get base salary value for workers row
var Location = ss.getActiveSheet().getRange(row, 36).getValue(); // get location value for workers row
var Department = ss.getActiveSheet().getRange(row, 16).getValue(); // get department numerical value for workes row
var DepName = ss.getActiveSheet().getRange(row, 17).getValue(); // get departmner name for workers row
var SOB = ss.getActiveSheet().getRange(row, 48).getValue(); // get phone stipend value for workers row
var Stp_phone = ss.getActiveSheet().getRange(row, 50).getValue(); // get phone stipend value for workers row
var Stp_home = ss.getActiveSheet().getRange(row, 51).getValue(); // get home stipend for workers home
var Chng_rsn = ss.getActiveSheet().getRange(row, 29).getValue();
if(oldvalue == undefined) { // we are replacing any underfined old value with a blank
oldvalue = '';
}
var data = [GUID, time, oldvalue, value, colhdr, user]; // output into table on Logging sheet
e.source.getSheetByName("Logging").appendRow(data);
var comp_sheet = ss.getSheetByName("Comp_Changes") //setting the variable of comp_sheet to the comp_Change_full_rows
var data2 = [Emplid, GUID, Chng_rsn, effdate, Salary, Location, Department, DepName, SOB, Stp_phone, Stp_home]; // populating the array data2
var lastrow = comp_sheet.getLastRow();
//loop to check if the emplid already exists on the comp final change sheet or not
for (var x = 1; x <= lastrow; x++){
var eval_emplid = comp_sheet.getRange(x, 1).getValue();
//if a match is found, delete the old row
if (eval_emplid == Emplid) {
comp_sheet.deleteRow(x);
}
}
comp_sheet.appendRow(data2); // appending the comp full rows sheet with the data in data2
}
}

Concatenate a few cells and creating a link from concatenation

I am trying to create a script where by assume
Column I contains Address
Column J contains City
Column K contains Zip code
Assume the there are thousands of entries
I wanted a script that would concatenate these values and create a google maps link on column I itself.
I did manage to get the link part working partly but could not get it to concatenate it before creating the link.
function googlemaps() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var r = ss.getActiveRange() + ss.getActiveRange().offset(0, 0, 1, 2);
// var t = r.offset(1, 0, 2);
var v = r.getValues();
for(var i=0;i<v.length;i++) {
for(var j=0;j<v[0].length;j++) {
v[i][j] = '=HYPERLINK("http://google.com/maps/places/'+v[i][j]+'","'+v[i][j]+'")'
}
}
r.setValues(v);
};
It keeps giving me this error
// typeError: Cannot find function getValues in object RangeRange
I know it's the offset thing but I can't get it to work.
An example of what i want would be
I3 = 1515 SW 2 CT
J3 = Miami
K3 = 33196
And with this script run, it would change I in
=hyperlink("http://google.com/maps/places/1515 SW 2 CT Miami 33196", "1515 SW 2 CT")
should be able to work across a range.
Anyone please help.
I tried this as well:
function googlemaps() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var r = ss.getActiveRange();
var r2 = ss.getActiveRange().offset(0, 1);
var r3 = ss.getActiveRange().offset(0, 2);
var v = r.getValues();
var v1= r2.getValues();
var v2= r3.getValues();
var vf= v + v1 + v2;
for(var i=0;i<vf.length;i++) {
for(var j=0;j<vf[0].length;j++) {
vf[i][j] = '=HYPERLINK("http://google.com/maps/places/'+vf[i][j]+'","'+vf[i][j]+'")'
}
}
r.setValues(vf);
};
and that does not work as well, gives me the error Cannot find method setValues(string)
You can also do this with just a formula.
I3 = 1515 SW 2 CT
J3 = Miami
K3 = 33196
L3 = =HYPERLINK(CONCATENATE("http://maps.google.com/maps? f=q&source=s_q&hl=en&geocode=&q=",I3," ",J3," ",K3),"Google Map")
Sorry I did not understand your requirement. Try this.
function googlemaps() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow()
var r = ss.getSheetValues(3,9,lr-2,3);//Assunes address data starts on row 3
for(var i=0;i<lr-2;i++) {
var addr = r[i][0]+' ' +r[i][1]+' ' +r[i][2] // Concatenates address data
r[i][9] = '=HYPERLINK("http://maps.google.com/maps? f=q&source=s_q&hl=en&geocode=&q='+addr+'","'+addr+'")'
ss.getRange(i+3,9).setFormula(r[i][9]);
ss.getRange(i+3,10).clear(); //Clears City
ss.getRange(i+3,11).clear(); //Clears Zip
}
};
Here is another version than creates an array of the hyperlinks and writes them back once instead of a row at a time. It is much faster. I tested it with 4000 addresses. Also, I changed it to start on row 2 (assuming a header row). If you need to adjust where it starts, Google setRange(1,1,1,1) notation for an explaination of what each number means. It controls the start row. Also the lr-1 would need to be changed if you change the start row so the total number of rows will be correct.
function googlemaps1() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow()
var r = ss.getSheetValues(2,9,lr-1,3);//Assunes address data starts on row 2
var arr = []
for(var i=0;i<lr-1;i++) {
var addr = r[i][0]+' ' +r[i][1]+' ' +r[i][2] // Concatenates address data
r[i][9] = '=HYPERLINK("http://maps.google.com/maps? f=q&source=s_q&hl=en&geocode=&q='+addr+'","'+addr+'")'
arr.push([r[i][9]])
}
var clr = ss.getRange(2,10,arr.length,2).clear();//clear state and zip
var destrange = ss.getRange(2,9,arr.length,1);
destrange.setFormulas(arr);// set all hyperlinks
};