Calling show() method in spreadsheet by trigger / doPost - google-apps-script

I would like to have a spreadsheet respond to incoming doPost(e) request, by presenting a user interface.
I do get a server error when I do that with the published script. (call ss.show(userinterface)
Is this possible to do anyway?
I just want to get a notification when data us pushed to the spreadsheet using an external applicatoin. Adding a row is okay, but I would like to trigger the Htmlservice popup to give information about that data.

No its not possible to show ui from there, only from an interface created from doGet and responding to browser events from the user that created it.
You have some options:
1 keep open a sidebar that regularly polls the status (from a script property for example every 10s).
2 i havent tried this from a post, but try doing ss.toast("cheers"). Doubt would work thou

Related

how to know if a Google Form has been submitted by the user in a web app

I would like to use Google Forms in my webapp to run quizzes.
The Google Form is created.
I use the pre-fill option to get a URL.
From my web app I create an iframe and pass the URL (different for each user) by passing the user-id to the form.
User now fills the form and submits.
The data is stored in a spreadsheet.
Earlier I publish the spreadsheet (thereby making it public).
I can now access the spreadsheet data and update my local database.
So currently, when the user submits (from within Google Form) there is no way my web app knows about it. (I have browsed the internet for solutions but did not find any).
Is there a way to get around this?
Currently, at some "stage" in the web app, I check if the user form data is available in the database. If not, I check the spreadsheet for that user data. If found, update the webapp database. So in that sense the webapp uses a pull-feature to check for updates.
Thanks
I see that you want to know when a new Form response has been uploaded. If my understanding of the question is correct, then you could use a simple .onEdit() trigger in the response Sheet. As an alternative, you could use a FormResponse.submit() installable trigger that fires at each response. Please keep in mind that triggers are limited to form uploads that don't fire from API requests and script executions, as detailed here. Please, don't hesitate to ask for further clarification.
UPDATE
Based on your last comment I get that your priority is to see the response Sheet updated in real time. If my understanding of the issue is correct, then you can show the responses Sheet directly in a webapp inside an iframe. Please, ask me any question if you have doubts about this approach.

Why Isn't My Spreadsheet Changing From Input Values of An Outside Source?

So I am trying to use an outside source (Zapier) to input values into my spreadsheet. These input values are then "transposed (formula wise)" into my spreadsheet to fit the cell coordinates with which they are to align.
I have the spreadsheet set to run 'onEdit' and when these incoming values arrive, it is supposed to cause the rest of the spreadsheet to change, but the function is not running.
However, if I were to edit the spreadsheet 'manually,' the onEdit function runs perfectly.
So why then would the spreadsheet not be running the function, when the outside source brings its input values?
UPDATE:
So I discovered that if I manually authorize an 'onChange' installable trigger, it will work. But if I create a copy of the same exact spreadsheet, the installable trigger will not exist in the copy. The copy needs to have the trigger without me having to do it manually. So I am trying to create a code inside of Google Script Editor that will either allow me to use the onChange function or install the onChange function in the Developer Hub. Any thoughts? Here is the code I tried but did not work:
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("My
Sheet")
var ssid = "My SpreadSheet ID";
ScriptApp.newTrigger('My Sheet)
.forSpreadsheet(ss.getId())
.onChange()
.create();
myFunction()
{
If there is an alternative for the onChange function, then I'm all ears. I just need a function that can run itself in my copies.
As a part of a collaborative effort, let me clarify the Zapier part (this answer does not concern the copy part).
Part 1. Zapier setup
Assuming you have a third-party application that you pull data from (btw, since you decided to use apps script, isn't it easier to drop the middleman like Zapier and connect to the 3P app API – if it has one, ofc – directly?), you created a Catch Hook and a POST Action.
The POST Action setup contains several fields:
URL field - this is where your /exec URL goes (WebApp is deployed via Publish->Deploy as a WebApp). After you deploy your script as a WebApp, you will get a URL that users and scripts can make requests to (it is always of this format https://script.google.com/macros/s/{yourProjectId}/exec - with some slight diff. due to access permissions). To avoid permissions issue, set the Who has access to the app option to anyone or anyone, even anonymous (otherwise, you'll have to devise auth handling).
Payload Type field is irrelevant here, but I suggest using JSON.
Data field is required if you chose the POST Action and should contain key-value pairs of data you would like to transmit via Zapier (the data will be available in parameter/parameters property of the event object).
Part 2. WebApp setup
Published WebApps should have either a doGet() or doPost() function to be able to receive and process requests (or both). Each of them accepts one special argument, which is constructed each time a request to the WebApp is made – an event object.
The event object will contain all the data that you sent from Zapier. You can then use this data to conditionally trigger different functions, pass data to handlers, etc. So, instead of relying on triggers, you can create a function that is called inside the doGet / doPost that will a) populate your target sheet with new values; b) do anything else after that, thus acting as an analogue of onEdit / onChange.
Useful links
Event object structure;
Passing event objects around;
Creating triggers on other documents;

running onload function in Google Form app script

I have a Google Form and a script and a script bound to the form.
I'm trying to get a function to run when a user fill in the form.
But the only function I get to run is when a hook it to the OnFormSubmit trigger.
No other function is running, no matter what I try.
Can I run a function i Google App Script on initial load when a user is filling the form? Is this possible?
Thanks
More details (I'll accept some other way to accomplish the task):
the function should capture some url parameters I pass to the form, and send it over to Google Analytics... I believe that part is solved here: Google Forms & The Measurement Protocol
As the form has several pages, the parameters I pass to the first page gets lost when the user goes to next pages, so I cannot capture them when submitting the form - therefore I'm trying to do it whenever the users first edits the form.
I tried to add the params as prefilled fields on a hidden page, but if it is hidden then it too gets lost on submitting...
Since Sandy did not write out an answer, I will.
You cannot execute Apps Script as part of a form when the user visits it. You can't modify a form as the user is filling it out (Dynamic form...etc). If you need this type of behavior, you will need to create your own form as part of a Apps Script Web App.
Web App information: https://developers.google.com/apps-script/guides/web

HTML Loading Messages

Is there a way to pass a value back to a HTML page while a server side function is running?
In the past when I was using the UI service, early in the function I would just create a label in the UI like:
app.createLabel('Working, hang on!');
And it would appear while the script was running, letting them know the script was running. When it got to certain parts of the script I would then be able to update/create a new message like:
app.createLabel('Halfway there, hold on.');
Or
app.createLabel('Fetched values, processing them');
etc., to tell them where we are if the script was running for a long time. An added bonus was that it could also update them on what direction the script was taking, so for example if a room booking script found that the first room was unavailable, it could pass a message back such as:
app.createLabel('First room was busy, checking other rooms');
And so on, and so forth.
Is there a way to do this with the HTML service? It seems my only options are success and failure handlers updating the HTML page when the function is complete, which don't seem to be what I want, as it's not a 'Real Time' message.
You can still use ui.alert() in sheets and docs, and sheets also has toast().
To keep the message within a sidebar or dialog that you've created using the HTML Service, you can set up a separate poller function on the client, to retrieve messages from the server every once in a while. Your long-running function could queue up a message via a function call on the server, which would be picked up by the poller on its next cycle, and displayed to the user.
See How to poll a Google Doc from an add-on for an example of a poller.

Google Apps Script - communication between script

HiMy problem is following: I would like to create small web page, on which it will be possible to create event in Google Calendar, but with some restrictions. In my case this calendar could be edited by my flatmates to reserve washing machine. This reservation cannot overlap and also all of us has limited number of days when we can use it. I have created private calendar, and I have created script which validate requests, and if everything is ok add event to calendar. This script is executed as me (because only I have permission to edit this calendar).
But I have problem with fetching information which user execute this script (me or one of my flatmate). Class Session contains 2 methods getActiveUser() and getEffectiveUser() but active user does not work (I guess because privacy protection policy). But if I create another script which is executed as user accessing the web I can get active user.
Does anybody know if is it possible to communicate somehow between this 2 scripts embedeed on the same site? I want to pass email of active user from one script to another. Or maybe do you know better solution how to solve this problem?
Regards
Adam
As you noticed, you need to set the script to run as the user accessing it to get his email. Then, instead of accessing the calendar directly (which you obviously can't) you can call another script published, but running as yourself allowing anonymous access that will receive this request from the "viewing" script and create the calendar events for it.
After you publish this "background" script, get its url and use it on a UrlfetchApp.fetch call to it. Then pass the parameters as url paremeters (or on payload if you prefer to use post instead of get).
The background script may even use ContentService to give nice return values to the calling script.
Sure, you can do so, but it's not as simple as you'd like. Make your admin level script run a web service that responds to the other script. It can probably be hacked as you can't authenticate the users, but comon, this is a washing macine!