Installable OnEdit not being called in Stock spreadsheet - google-apps-script

I have a function (in a Google Apps Script), not called onEdit(), but something else and this has been set up to be called from any on edit events via in the Installable onEdit on a Google Spreadsheet.
The spreadsheet is around stocks and monitors a portfolio and the purpose of the function is to send an email as soon as a stop loss is hit on a stock, i.e. the price of a stock falls to a certain price. The price of the stock is retrieved and updated via the Google Finance API in a column in the spreadsheet.
Now, when running the function from the script or locally editing the spreadsheet, the function is called successfully. However, I am finding that as the stock price is updating automatically throughout the day on Google Drive and falling to the stop loss price, the on edit function is not being called. I read somewhere about it not being called by an "anonymous" user? I know it's not being called as I have an "email counter" column, which decreases every time the function is called, and once at 0 no more mails will be sent to avoid spamming. This not decreasing via the Google Finance API automatic price updates.
Can someone advise what is causing this and if this there is any workaround?

A list of things-that-don't-trigger-onEdit, along with their issue tracking ids, were provided in a previous answer.
Content of a spreadsheet changed by scripts does not trigger onEdit.
A work-around might be to use a time-based trigger, and in the call-back scan for and react ti changes. (Could the updater set a trigger to fire in the near future, perhaps?) Challenges for this will be around balancing responsiveness vs trigger limits.

Related

How to implement? Spreadsheet with link - Go To Link Grab Data - Update Spreadsheet Row

I am looking for technology suggestions. Or if this can be done in native google sheets (note the site I am looking to access is behind a username and password).
I have a google sheet that looks like this
birth date
link
data_element_from_website
12/31
https://something.com/3920230
1/31
https://something.com/1920238
lets say on https://something.com/3920230 there is a HTML element 123
Twice a day I want to be able to refresh the data, this could be done by going into the spreadsheet and clicking/doing something.
Can this be done?
What if https://something.com/3920230 is behind a login (authentication). Note: I could be logged in to the website in a different tab... I don't think that would make a difference though...
Assuming you have a script that you would like to run twice a day, you can use Apps Script Time-driven triggers:
A time-driven trigger (also called a clock trigger) is similar to a cron job in Unix. Time-driven triggers let scripts execute at a particular time or on a recurring interval, as frequently as every minute or as infrequently as once per month. (Note that an add-on can use a time-driven trigger once per hour at most.)
If it's just some formulae, you can change the recalculation settings to be either On change, On change and every minute or On change and every hour under the File > Spreadsheet settings menu item and clicking on the Calculation tab.
If you want to get data from public site(no login) you can use ImportXML. You can google a lot about it, for example
https://answerbun.com/personal-finance-money/get-revenue-details-in-google-sheets-using-google-finance/
If the page you want can only be accessed using login, this becomes a rather complicated task, especially using only apps script libraries (not much scraping lib support here)

Google Calendar Trigger Does Not Fire

The objective is to transfer data from Google Calendar to a Google Sheet whenever the calendar is edited. For this we need a script that transfers the data, and need to set up the Calendar trigger.
Thanks to Oleg Valter and his excellent and exhaustive explanation how to create the script on this page:
Google calendar events to Google spreadsheet automatic refresh onEdit
the data transfer already works fine when the script is started from the Google sheets. I use a modified version of Oleg's script, which works well, and I am not sure if it would make sense to re-post it here (since that is not the problem).
I have tried to create the trigger with Oleg's funtion first:
/**
* Installs Calendar trigger;
*/
function calendarTrigger() {
var trigger = ScriptApp.newTrigger('callback name here')
.forUserCalendar('calendar owners email here')
.onEventUpdated()
.create();
}
but the trigger did not fire when I have added a new event on the calendar. Checked the triggers connected to the project, and the trigger created by the above function was there. Checked the Executions and nothing showed up.
Then I have manually deleted the trigger, and manually crated a new one following the instructions under "Managing triggers manually" section of this page:
https://developers.google.com/apps-script/guides/triggers/installable#google_apps_triggers
The trigger was created again, which basically looked the same as the one created by the above function, but it still did not fire when tested.
Now I am stuck and have no idea what else to try. It supposed to work, but it is possible that I have missed setting up something else that might be required for this to work.
I am using a simple Google account connected to a single email address (not a business suite). Never had any problems with the other triggers related to the sheets before that I could not resolve (sometimes the platform refuses to work as it should, but then later things get back to normal).
I would highly appreciate any advice about what else to try, or if you know what the problem is, even better.
Thanks in advance,
Zoltan
Well, after some trial and error based on ziganotschka's kind answer (thanks again) found the problem. It is caused by a bit of confusion about what the
.forUserCalendar('calendar owners email here') and the
Calendar ID supposed to be.
On my Calendar account there are several calendars, but two are of interest for us here:
"Main Calendar" which is the default calendar associated with the account. If everything else is deleted, then this will remain.
another calendar that I have added for the very purpose to be connected to the spreadsheet, and named it "Auto Billing" (only this is checked and displayed).
The Main Calendar has this on the Settings page (changed my email address):
Integrate calendar
Calendar ID
myAddress#yahoo.com
The Auto Billing calendar has this on the
Settings page (changed the ID):
Integrate calendar
Calendar ID
svj8tu1o458a9s1488xxxxxxxx#group.calendar.google.com
My intent was to use a custom created calendar for this purpose instead of using the default Main Calendar, because this might be full with all kinds of events.
Therefore when the trigger is created manually
svj8tu1o458a9s1488xxxxxxxx#group.calendar.google.com
should be added in the field "Calendar owner email" instead of the calendar owner's email address.
When the trigger is created from script using the above snippet, then
.forUserCalendar("svj8tu1o458a9s1488xxxxxxxx#group.calendar.google.com")
should be used.
In the script that transfers the data from the Calendar to the sheet the
var Calendar = CalendarApp.getCalendarById("svj8tu1o458a9s1488xxxxxxxx#group.calendar.google.com");
should be used. This way the trigger will work when events are edited on the Auto Billing calendar.
Thanks for the guidance Ziganotschka, and also big thanks to Oleg for the original script. Hope this debugging will help others as well.
Google Calendar trigger is a feature for the Google Calendar
It does not work for "myaddress#yahoo.com" calendars

Having trouble with Google script authorizations, need help remotely updating many (dozens of) Google Forms

I'm setting up an event to encourage people to stay physically active. Once someone registers, they are sent a copy of a Google Form/Sheet template that they will use to create their team. Each member of the team will enter their name, select the activity that they performed and record how long they performed it. The log Form should automatically update to list these names and activities so that the users can select from this list later rather than enter them again. The linked Response spreadsheet has charts comparing the team members activities to each other. I have a 'master' spreadsheet that imports the data from all of the team's response sheets and compares and displays them (on Google Slides) for the participants to view.
The problem that I'm having is that I would like to be able to programmatically authorize the Log Form auto update so that I don't need to do it manually every time a new Log Form is generated.
Things tried:
1) Form ranger - the Form ranger configuration can be setup in the form template, but is lost once the template is copied, requiring me to reconfigure (and authorize) the Form Ranger each new form as it's generated.
2) Use Google script to update the form with an onFormSubmit trigger. Process is working but I need to manually setup the onFormSubmit trigger, the first time, in each new Form/Spreadsheet in order for it to continue automatically afterward.
3) Updated the manifest file to include: "oauthScopes": ["https://www.googleapis.com/auth/spreadsheets.currentonly"] When I tried this, the script generated an error indicating 'You do not have permission to call SpreadsheetApp.openById'. It began working again after removing the '.currentonly' but still required me to manual authorize it for each new Form/SS.
4) Added
/**
* #OnlyCurrentDoc
*/
to the script. This added several seconds to the script runtime but, other than that, I didn't notice any change. Still required me to manually authorize.
5) I've tried using simple triggers (onOpen and onEdit) to detect changes in the Form's linked Response sheet, but found that these triggers are not activated with the form's automated sending of data to the spreadsheet but rather when the USER manually performs the operations on the spreadsheet. So still no automated updating.
Do you have any other ideas? I appreciate any assistance that you can provide.
Thanks,
David

How to get around time trigger limitations for Add-Ons in Google App Script?

I want to develop an Add-On to Google Sheets that gets statistics from multiple APIs every 15 minutes (at least).
I use time triggers for this in my script (which I want to make into an add-on) and that is fine.
However, I read that an Add-On can only have a time trigger with a frequence of 1 hour. This would make it impossible to make the Add-On as I need more frequent data than that.
Are there any workarounds around this issue?
Would it be feasible to have a script start and then continously add and delete a time trigger in some other way, like "run in 15 minutes again"?
As it's stated in the documentation for the Add-ons triggers, you can't set it for less than an hour [1]:
Time-driven triggers cannot run more frequently than once per hour.
Also, they can't have more than one type of trigger at the same time, meaning you could only have one time-driven trigger [1]:
Each add-on can only have one trigger of each type, per user, per
document. For instance, in a given spreadsheet, a given user can only
have one edit trigger, although the user could also have a form-submit
trigger or a time-driven trigger in the same spreadsheet. A different
user with access to the same spreadsheet could have their own separate
set of triggers.
Conclusion: I don't see any workaround possible for this.
[1] https://developers.google.com/gsuite/add-ons/concepts/triggers

Are there any Non-User Modified Google App Script Triggers

Is there anyway to fire an onChange trigger on a Google spreadsheet when the change was made by an App Script?
For context, I've got an app that pulls metrics from Google Analytics for individual blog posts. My challenge is when there are more than 50 blog posts (each on its own row) in a spreadsheet, or if the data is slow coming back from Google Analytics API for any reason, the application exceeds the time limit. I'd like to configure the sheet so the app runs once for each blog post, and then once the data is changed on the spreadsheet, the app is triggered to run again.
Thanks!
its not possible to trigger the onChange/onEdit etc from script.
however you can do this:
use an extra column to store the last processed date per row.
from your time trigger check if the last modified date of the spreadsheet (from DriveApp) is after the date stored per row.
this allows the trigger to run even once a minute while consuming little quota on the simple checks.