Google Sheets - How to jump to today's date when opening a table (via share link) - date

Thank you for your great posts!
I am looking for a code that will cause jumping automatically to the current date after opening a table in Google Sheets (via a share link). Your code (see below) works great if I am signed in. When I create a share link (with or without edit rights), the code does not work. I tried the link with different browsers (Chrome, Edge, Firefox) ... What could be the problem?
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getActiveSheet();
var data = sh.getDataRange().getValues();
var today = new Date().setHours(0,0,0,0);
for(var n=0;n<data[0].length;n++){
var date = new Date(data[0][n]).setHours(0,0,0,0);
if(date==today){break};
}
n++;
sh.getRange(1,n).activate();
}
Kind regards
Here the link to your code:
How to set background color for a row based on current date in Google Docs Spreadsheet?

The onOpen(e) function is a simple trigger that runs only if the user at the keyboard is signed in to their Google account and has edit access to the spreadsheet.
The simple triggers onOpen(e), onEdit(e) and onSelectionChange(e) will not run when a file is opened in read-only mode. The same is true with other kinds of scripts as well. In other words, if you share the file as "can view" or "can comment", no scripts or add-ons will be available.
To make it work, you will have to share the spreadsheet file as "can edit". Note that you you can still protect the spreadsheet through Data > Protected sheets and ranges.
See the jumpToToday_ script for an alternative that supports multiple sheets in the same spreadsheet file.

unfortunately, this won't work for you. by default, all non-signed users (and signed-in users which did not authorize scripts) are protected from "harmful" scripts which may be included with the spreadsheet. all scripts are treated as "harmful" by default including your onOpen script.

Related

How to get the title image using Google Apps Script

Here's a picture of the image which is inserted into MultipleChoiceItem, not an ImageItem. Now I want to get the image url through Google Apps Script. Below is my code.
How to get that?
var form = FormApp.openById('1Y6u01jUdre9ykEEtgmI9eRVo7Clr1GadgdrLyFTVoH1NQ');
var items = form.getItems();
var title = items[0].getTitle();
Unfortunately so far no endpoint has been implemented in Apps Script to get / set neither item images, nor choice images
However, Feature requests have already been filed for both (see here and here).
I recommend you to "star" those feature requests to increase visibility and hope for prompt implementation.

Zapier: from spreadsheet to Facebook Offline events tracking

I've got a database containing offline conversions (email, phone, name, purchase_amount, etc). I can export this database in .csv or .xls and I can also email this file on a daily basis to a Gmail account.
As Zapier has a Google Sheet to "Facebook offline event" API, I tried this workflow with Zapier.com:
Export my database in .xls: OK
Mail it to my Gmail account as an email attachment: OK
Grab the attachment and upload file to Google Drive using Zapier: OK
This is the part where I'm in trouble: I want to copy the content of the .xls file that is on Google Drive to a new Google Sheet. I can't figure out how to do this in Zapier.
Finally, on every new spreadsheet created or new row added (depending on how I configure the Zap) , pushing the data to Facebook API.
I'm not a developer so I want to avoid coding if possible. I tought I could easily do it with zapier but it seems that working with data inside a file is not so easy.
Any help would be much appreciated.
Thank you,
Best regards,
Tim.
If it were me I would look into the scripting capabilities of Google Sheets to try and achieve this, having your code execute from a single place eliminates other possible points of failure. That said, I have put together a somewhat hacky, code free solution that should set you up to do what you are looking to achieve. I break it down step by step below:
Step 1: Export database as .csv file. I could only get this to work with .csv files and not .xlsx files. There may be the ability to do so but it would require further trial and error.
Step 2: Mail it to your Gmail account where I assume there is a Zap which triggers to upload the attachment to your drive account automatically.
Step 3: Setup a second Zap that is connected to your Gmail account
that triggers when you receive an email with an attachment.
Step 4: Isolate the attachment file from the results of the triggered Zap and use it as input for the following formatter action step.
Step 5: Setup your formatter action step using the text option. Within the formatter template select trim white space and use the attachment, isolated from the trigger step, as its input. See example photo here.
Step 6: Setup your final step which is the create Google Sheet function of the Google Sheets Zap. Enter a title for your new sheet, it will probably need to be a unique value I used the attachment ID from step one as my title but you can set it to whatever you would like. In the headers section type =IMPORTDATA("") . Between the two quotation marks place the output of the previous formatter step and then run the Zap. See example photo here.
Explanation: When Zapier catches the attachment file from your inbound email it seems to be stored as raw data. Given this we cannot simply dump this information into a spreadsheet as it would be unreadable. However it seems Zapier has a method for converting this raw data through the endpoint https://zapier.com/engine/hydrate. When we input the raw attachment data into the formatter step Zapier provides a link pointing to the URL for converting the data into its original format. We take this URL and using the Google worksheet function IMPORTDATA() we are able to import the file using Zapier's file conversion engine. Now that the data is in your new sheet you can set up an additional Zap to do something with it. Also note that the Zap to upload the attachment to your Google Drive is not necessary with this setup. That said if you are looking to keep backups of your data then keep it on otherwise you may have the opportunity to save yourself some zaps.
Hope this helps!
Many thanks for your awesome reply. I also tried the "trim whitespace" to get the data back. I only missed the "importdata" function which is super powerful. Indeed it only works with .csv. With .xls file, importdata gives the source code of xls file which is useless.
I ended with 2 zaps:
Grab Gmail attachment, upload to Google Drive (for backup & monitoring) and create new spreadsheet
Send Facebook offline conversion when new spreadsheet is added (filter: only continue when file name is xxxx), lookup spreadsheet row (I took one column that has the same value for each row) and finaly I could match my columns with the Facebook API.

Tracking Clicks in Emails to 3rd Party Websites

A hopefully simple GA newbie question.
I programmatically (in Java) send emails to my clients and I'm trying to track what links in the email they click.
The links in the emails are to third party websites.
Is there a way to setup the href links so that I can track what uid's are clicking and treat clicking those links as an event?
An example link would be to a piece of legislation:
https://www.cga.ct.gov/asp/cgabillstatus/cgabillstatus.asp?selBillType=Bill&which_year=2017&bill_num=5210
how would I add that link in the email HTML?
That does not work, at least not with additional resources.
Google Analytics tracks links by sending a request to the Google servers before the user is redirected to the link href. In web tracking this is usually done via a javascript event handler that is attached to the link. In e-mail javascript is not really an option, so that does not work.
What is usually done instead is that in your emails you link to your own server; there is a script that collects the data from the link, and only then it redirects to the originally requested url. Most commercial newsletter packages integrate a solution like that, but you can set up something yourself with some basic programming skills and the Google Analytics measurement protocol (which would allow you to send tracking calls from a server-side redirection script).
Setup the Redirects Tracking Engine
The Redirects Tracking Engine makes it easy to collect event data where traditional tracking methods may not have been possible. This tracking engine utilizes Google Tag Manager and Google Analytics to capture events and is run on the client side. All events can be seen in Google Analytics (Behavior > Events > Top Events).
Getting Started
Installation
Add the latest JQuery and Redirects Tracking Engine scripts to the header of your site.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script><script type="text/javascript">// Fetches redirects.txt and stores information in the variable data
$.get('redirects.txt', function(data) {
// Fetches the parameters of the query string and stores the path in urlParams
var urlParams = [];
// Sifts through the string and removes unwanted characters
(function () {
var match,
pl = /\+/g, // Regex for replacing addition symbol with a space
search = /([^&=]+)=?([^&]*)/g,
decode = function (s) { return decodeURIComponent(s.replace(pl, '')); },
query = window.location.search.substring(1);
while (match = search.exec(query))
urlParams[decode(match[1])] = decode(match[2]);
})();
// Pulls properties from urlParams and stores them in destination array
var destination = Object.keys(urlParams).map(function(path){return urlParams[path]});
// Assigns the redirects.txt data to the userData array
var userData = data.split('\n');
// Multidimensional array declaration
var redirects = [];
// Fetches the total number of objects in the userData array
var total = userData.length;
// Counter variable
var i = 0;
// Runs through the redirects array to check to see if there is a string match
while (i < total) {
// Places userData into the multidimensional redirects array
redirects[i] = userData[i].split(' => ');
// Checks for a path match in the redirects array
if (redirects[i][0] == destination[1]) {
window.location.href = redirects[i][1];
return;
}
i++;
}
// Redirects to safe page if no match is found
window.location.href = 'https://example.com';
});
Setup Google Tag Manager
Paste this code as high in the <head> of the page as possible. Make sure to substitute the filler GTM-XXXX with your Google Tag Manager Account ID.
<!-- Google Tag Manager --><script>(function(w,d,s,l,i){w[l]=w[l]|| [];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js? id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXX');</script>
<!-- End Google Tag Manager -->
Additionally, paste this code immediately after the opening <body> tag. Make sure to substitute the filler GTM-XXXX with your Google Tag Manager Account ID here as well.
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
NOTE: For more information about installing the Google Tag Manager snippet, check out their Quick Start Guide.
Create Tags/Triggers/Variables
Create a variable — You will need to first create a User-Defined Variable. Go to the Variables page of your Google Tag Manager and in the User-Defined Variables section create a new variable named Tracking ID. Give this variable your Google Analytics Tracking ID in the Value field and SAVE.
Create a tag — You will need to go to the Tags page in Google Tag Manager and click the NEW button. Fill in the fields and click SAVE when finished.
Create a trigger — Finally, you will need to create a trigger. Go to the Triggers page in Google Tag Manager. Once there click on the NEW button and fill in the fields and click SAVE when finished.
After these configurations have been setup in Google Tag Manager you are ready to add your redirects to the redirects.txt file.
Redirects
To add a redirect open the redirects.txt file. The text linkedin is telling the engine what path it needs to look for in the URL. Immediately following is the separator => which shows the engine where the assigned path should direct the user. New redirects can be added on a new line and there are no limits to the number of redirects that can be added to this file.
// Example Redirect
linkedin => https://example.com
Failsafe
In the off-chance that one of the redirects is not working it is good to have a page that the user can be directed to. You can add in your failsafe page by modifying the window.location.href location that comes immediately after the loop.
// Redirects to safe page if no match is found
window.location.href = 'https://example.com';
Browser Support
Supported Browsers : Chrome, Firefox, Safari, Opera, Edge, IE7+.
The source code as well as an example can be found on GitHub.

Custom action button (Junk+)

Is it possible to create custom action button? ["Junk" button with more complex action]
I would like to:
mark the message as junk
copy the message to special folder common to all email accounts
move the message to per account junk folder
AFAIK Current junk button can deliver 1 and 3 without 2.
I need it for custom reporting to external services e.g. spamcop, knujon and other.
If thunderbird can not deliver such functionality then I am willing to accept suggestion of other Linux email clients capable to deliver such functionality.
Obviously this is easy to do with a custom XUL add-on and some basic Thunderbird chrome scripting.
This can also be done with the Custom Buttons Add-on for Thunderbird. Here is the code for the button, you will need to replace with your own folder URI's. The URI's for the folders can be accessed from the right-click content menu Properties .
/* Code */
// 1. mark the message as junk
goDoCommand("cmd_markAsJunk");
// 2. copy the message to special folder common to all email accounts
var copyUri = "imap://{user}#{host}/{path}/{folder}";
var copyFolder = GetMsgFolderFromUri(copyUri);
MsgCopyMessage(copyFolder);
// 3. move the message to per account junk folder
var moveUri = "mailbox://{user}#Local%20Folders/{spam folder}";
var moveFolder = GetMsgFolderFromUri(moveUri);
MsgMoveMessage(moveFolder);
The button script definitions are stored in the file:
{thunderbird profile}/custombuttons/buttonsoverlay.xul
You may be able to update this file automatically to ease deployment.
WARNING: Thunderbird 31 requires different code.
See https://bugzilla.mozilla.org/show_bug.cgi?id=1043819

Google Search autocomplete API?

Does Google provide API access to autocomplete for search like on the actual site? I have not been able to find anything.
I would like to use Google's autocomplete logic for web search on my own site which relies on Google's search API.
The new url is:
http://suggestqueries.google.com/complete/search?client=firefox&q=YOURQUERY
the client part is required; I did't test other clients.
[EDIT]
If you want the callback use this:
http://suggestqueries.google.com/complete/search?client=chrome&q=YOURQUERY&callback=callback
As #Quandary found out; the callback does not work with client "firefox".
[EDIT2]
As indicated by # user2067021 this api will stop working as of 10-08-2015: Update on the Autocomplete API
First, go to google, click Settings (bottom right corner), change Search Settings to "never show instant results. That way, you'll get regular autocomplete instead of a full page of instant results.
After your settings are saved, go back to the Google main home page. Open your browser's developer tools and go to the Network tab. If you're in Firefox, you might have to reload the page.
Type a letter in the search box. A new line should appear in the Network window you just opened. That line is showing where the autocomplete data came from. Copy that url. It should look something like this:
https://www.google.com/complete/search?client=hp&hl=en&sugexp=msedr&gs_rn=62&gs_ri=hp&cp=1&gs_id=9c&q=a&xhr=t&callback=hello
You'll notice your search term right after the part that says q=.
Add &callback=myAmazingFunction to the end of the url. You may replace myAmazingFunction with whatever you want to name your function that will handle the data.
Here's an example of the code required to show the autocomplete data for the search term "a".
<div id="output"></div>
<script>
/* this function shows the raw data */
function myAmazingFunction(data){
document.getElementById('output').innerHTML = data;
}
</script>
<script src="https://www.google.com/complete/search?client=hp&hl=en&sugexp=msedr&gs_rn=62&gs_ri=hp&cp=1&gs_id=9c&q=a&xhr=t&callback=hello&callback=myAmazingFunction"></script>
Now that you know how to get the data, the next step is to automatically change that last script (the one with the autocomplete url). The basic procedure is: each time the user types something in the search box (onkeyup) replace the search term (q=whatever) in the url, and then append to the body a script with that url. Remove the previous script so that the body doesn't get cluttered.
For more info, see http://simplestepscode.com/autocomplete-data-tutorial/
Most of the above mentioned methods works for me, specifically the following serves my purpose.
http://suggestqueries.google.com/complete/search?client=firefox&q=YOURQUERY
Being a newbie in web programming, I'm not much aware of the "Callback" functionality and the format of the file returned by query. I'm little aware of AJAX and JSON.
Could someone provide more details about the format of file returned by the query.
Thanks.
Hi I don't know if this answer is relevant for you anymore or not but google returns JSON data through following get request (although this isn't an official API but many toolbars are using this API so there's no reason why google might discontinue it):
http://google.com/complete/search?q=<Your keywords here>&hl=en
You should use AutocompleteService and pass that text box value into the service.getPlacePredictions function. It send the data in callback function.
let service = new google.maps.places.AutocompleteService();
let displaySuggestions = function(predictions, status) {
}
service.getPlacePredictions({
input: value
}, displaySuggestions);
Base: https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service#AutocompleteService.getPlacePredictions
example: https://dzone.com/articles/implement-and-optimize-autocomplete-with-google-pl
I'm using (( Edrra.com )) API that have google search and suggestions that works with both GET & POST:
Google suggestions:
https://edrra.com/v1/api.php?c=google&f=suggest&k=YOUR_API_KEY&v=YOUR_SEARCH
Google search:
https://edrra.com/v1/api.php?c=google&f=search&k=YOUR_API_KEY&v=YOUR_SEARCH
and more...
What are you trying to use an auto-complete for? More information would help narrow it down.
As far as I know, google does not provide one, but they do exist like jQuery UI's auto-complete.
EDIT:
If you are using their custom search API view here for autocomplete.