Google Apps Script Running a Script from Within Another Sheets Code - google-apps-script

I have several sheets set up to do a variety of things. I have a control sheet that looks to do things with these sheets, one of which would be to run a script that is in the target sheet (so not the control sheet). Is there a way in which I can get the control sheet to run the target sheet script?
For example, within Target Sheet "TargetOne", I've got attached code that runs "SubroutineOne".
function SubroutineOne() {
doSomething();
}
And in the Control Sheet I'd want to have something like this.
function ControlCode() {
setSomething();
run TargetSheet.SubroutineOne();
reportSomething();
}
Is there anyway of doing that? Thanks for reading.

There is no direct way to do this. If you want to call other Apps Script projects you should import them as libraries.
To do this, publish the Script on the Target Sheet and use it. Take a look at the documentation for instructions on how to do this.
If you have multiple sheets, this can become a very convoluted solution. You can have a single "master" sheets instead and use the openById(id) function to access the sheets you want to manipulate. That also allows you to modify all the sheets from one script.
Yet another solution is to deploy the Target Sheet as a Web App and add the code you wish to execute on the doPost() or doGet() calls. Be careful with this solution, since you will have to implement controls to avoid duplicate calls or calls by someone else.
Lastly, you could try to use the Apps Script API to directly make the call to execute it.

Related

How can I make an Import function run without opening the sheet?

I have a Google Sheet that uses an IMPORTRANGE query to combine data from multiple other sheets. This combined import sheet is read by Google AppSheet. We have realized that the data AppSheet is reading is always outdated. It only reads the data as of the last time the sheet was manually opened.
I followed the steps in this post to try to fix this issue by creating this function: function refresh() {SpreadsheetApp.flush()}. I then set up a timed trigger to activate it once an hour. Logs show the function is running, but the data is still not updating until I manually open the sheet.
This is my first time using Apps Script. Any tips/ideas? Is there a different or better way to have the formulas update without opening the file?
Thank you for reading.
SpreadsheetApp.flush() only works for the script execution that calls it. If you need to refresh the data results from a formula it's uncertain how exactly the spreadsheet will respond as most of the formula calculations are done on the client side. You could verify this by yourself by using your web browser developer tools.
Anyway, spreadsheet formulas have several caveats so it will not be extrange that at some point you will have to rethink your solution. Assuming that you want to keep using AppSheet:
Use AppSheet for your front end and some no-code / low-code automation. Keep your app small, if you need many forms / views consider to distribute them among several apps.
Use Google Sheets only for data storage for your AppSheet app. Please bear in mind that it has 10 million cells limit for the whole spreadsheet, so you might want to delete the unused sheets and delete the unused columns and rows on each sheet.
You might use Google Apps Script to do the data import and transformation tasks. If you need that something be updated based on actions done on the AppSheet app, you might use an installable change trigger or use webhook from the AppSheet side to and a "simple" web application using Google Apps Script (you could use GET / POST http requests to trigger some Google Apps Script functions).
Also you might use other programming platforms for the data import / transformation tasks and keep using Google Sheets as your AppSheet database by using the Google Sheets API or other automation tools like Zappier, IFTTT, Integromat among many others.
solution #1
You can try this solution :
define a checkbox (for instance in A1 in tab Sheet1)
set this script
function myFunction() {
var chk = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1').getRange('A1')
chk.setValue(false);
SpreadsheetApp.flush();
Utilities.sleep(500);
chk.setValue(true);
}
define a trigger on it
define the formula as follows
=if(A1,importrange("1n-rjSYb63Z2jySS3-M0BQ78vu8DTPOjG-SZM4i8IxXI","A:Z"),"")
when A1 is unchecked, the result will be empty, then check A1 to fill once again the result as expected
solution #2
by script, try for instance
function myFunction() {
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet9')
var data = SpreadsheetApp.openById('1n-rjSYb63Z2jySS3-M0BQ78vu8DTPOjG-SZM4i8IxXI').getSheets()[0].getDataRange().getValues()
sh.getRange(1,1,data.length,data[0].length).setValues(data)
}
put a daily triger as needed

Share a custom google sheet function with another email address without showing the source code

Iv'e written a custom google sheet function using Google Apps Script, and i would like to share it with another spreadsheet user, but i do not want to share the functions source code.
I've converted the Google Apps Script to a project, but now i have no idea how to link the project back to my sheet, so the function will work again.
I also do not want to publish the AddIn to the marketplace.
Test As Addin also doesn't work, the sheet is opened in a new tab, but the cells with the custom function says #NAME?.
What am i missing?
Explanation / issues:
The error #NAME? indicates that you are trying to use a function
that does not exist. As you also mentioned, this function does not
belong to the active spreadsheet but on a different project.
Unfortunately, it is not possible to share a custom function with other spreadsheets directly.
Possible Workarounds:
You can create an add-on.
Another workaround solution would be to create a library. That is a great alternative and the documentation is quite straightforward.
Related:
Creating add ons in Google Apps Script
How to call library function as custom function from spreadsheet formula?

How to change a "bound" Script to a "Standalone" script?

I have a Google Sheets script that's bound to a specific doc. Basically it takes the results of certain cells, then it used these values in doc.
I have multiple Sheets I'd like to "attach" to this script. All the other Sheets have the exact same tabs and cell names, etc.
Is there a way to turn that bound script to a standalone script, then attach them to the other Sheets?
You cannot unbind a bound script:
The file a bound script is attached to is referred to as a "container". Bound scripts generally behave like standalone scripts except that they do not appear in Google Drive, they cannot be detached from the file they are bound to, and they gain a few special privileges over the parent file.
To use the functionality you've created, you'll want to export the bound script as a library and import it in the other spreadsheets' script editors. You may also have to do some tweaks to get any UI alterations
Note that an installed library will not automatically update the used version, so if you make changes to your library source and save a new version, you'll have to go through all the spreadsheets that reference it and update the library version.
The alternative to a library is to go through the process to publish your script as an add-on. This will let you redeploy your changes without needing to go through every single spreadsheet.

Automatically keep one sheet synchronized with another

I have a Google Sheets that I'm working with, and for reasons I'd rather not get into here I need to keep an updated copy of it in a second location. The original spreadsheet has two sheets/pages, I only need to copy from the second sheet/page to the first sheet/page of the new spreadsheet.
I have a server that can accomplish this if an API is necessary. I don't need an exact script to do it, but pointing me in the right direction would be very helpful. I'm most familiar with Python and PHP if they're needed.
I'm sure there is an easier way to do it using Apps Script, but if you want something that works in the short-term while you learn Apps Script, you can use the IMPORTRANGE function and Sheets exclusively.
=IMPORTRANGE("SpreadsheetKey","Sheet!Range")
Example:
I created a sheet called OriginalSheet and in A1:A5 put the numbers 1 through 5.
Next, I created a separate sheet called NewSheet and in cell A1, I put the the following function (with appropriate values for my OriginalSheet filled in):
This method works for me. I'm in the process of learning Apps Script and will post a better method when I learn it :)

How can I invoke my standalone script in my spreadsheet?

I have created a standalone Apps Script from Google Drive, but when I try to access it from a Google Spreadsheet, I don't see a way to access the script (even though when I created the script, I created it as a spreadsheet script).
In the spreadsheet, the "Tools->Script manager..." menu item doesn't show my script, nor does the "Tools->Script editor...". The latter has a section for 'recent projects', but it doesn't list my newly created script, nor its associated project.
If I create a new script from inside the spreadsheet (i.e .Tools->Script editor...) and cut and paste the code from the standalone script, it works fine. However, this can only be used in the single spreadsheet -- to use it from another one, I have to cut and paste / go through auth again.
Is there a way to do this without publishing the script to the gallery, which I assume makes it public (I don't have a problem making it public, but it seems like there must be a better way)? The script is here -- it is world readable with the link. It adds a menu to a google spreadsheet that lets you run a query in BigQuery and dumps the results into your spreadsheet.
The behavior you describe is exactly how it is intended to work... the script you wrote can only work if it is bounded to a spreadsheet.
The fact that you wrote it in an independent script makes it indeed a standalone app but it can only be executed from within the script editor and in this context an onOpen function like the one you wrote doesn't make sense (it runs on opening a document/spreadsheet, not the script).
For now a script can only be bounded to a spreadsheet by copy/pasting the code, at least a script that you want to use as you do (with a menu and direct function calls and activeSheet calls), maybe one day Google will expand the concept of libraries to make your script function available from different document directly (read also the doc about libraries).
There are actually 2 types of standalone Apps Scripts, the one you tried that runs only from within the editor and webapps that are deployed and run in a browser window by themselves. The latter are always build around a doGet function that represents an entry point for the application. You should read the documentation on the subject to get all the details.
To summarize : if you want to access your spreadsheet using getActiveSpreadsheet() and similar methods then you have to write (or paste) the script in the script editor bounded to the spreadsheet.
If you want to have a standalone script you can also interact with spreadsheets (and other document as well) but you have to access them by their ID and the spreadsheet will only be viewable from another browser window, without link between them, and there will be no "active spreadsheet" nor "active sheet"...
A webapp can of course also do that with the advantage of a user interface that you can adapt to your needs but this is becoming a bit too far from the scope of your question.
Hoping I've made it (a bit) more clear, at least I tried to make it simple ;-)
I worked this out with Jordan, following the instructions here:
https://developers.google.com/apps-script/guide_libraries
First, he had to share his standalone script with me, so I had read access to it (probably setting the script as public read would work too).
Then he told me his project key.
I took his project key and inserted it in "Find a Library", in the "Manage Libraries" menu.
For this to work, Jordan had to export "a version" of his library - so third parties can rely on stable code and upgrade at their own rhythm.
As Jordan's script runs automatically on onOpen(), my code had to define a function onOpen() that called his script onOpen(). To do this, the library manager gave me an identifier for the imported library.
Sample code once the library is imported and the library manager gives you an identifier for the library:
function onOpen() {
GivenLibraryIdentifier.onOpen();
}
You can also use installable triggers. If you install an installable trigger (such as onOpen) from your standalone script into the document, it gets similar privileges as if it were a simple trigger.
And better yet, when the installable trigger calls its function from your standalone script, it executes WITHIN your standalone script! So it can call any other function in your standalone script. Its Logger.log() entries can even be viewed from your standalone script, even though it was executed from your sheets document.
So basically, if your script installs an onOpen() trigger tied to one of its functions, it's as good as if your Sheets document had required() your whole standalone script file.
(Assuming the owner of the script has edit privileges to the file.)