Organizing Spreadsheet Code in several *.gs files - even possible? - google-apps-script

I am trying to organize my code for a Spreadsheet in several script files. Within the script editor I can create as many *.gs files as I want, but I can't figure out how to access code that would be defined in another script.
Simple Example of what I'd like do achieve:
Code.gs:
function onEdit(){
myFunctionFromLibrary_gs();
}
Library.gs:
function myFunctionFromLibrary_gs(){
Browser.msgBox("hi there");
}
The onEdit() is obviously called by a Trigger.
Without modification this will result in a Runtime-Error, stating that
myFunctionFromLibrary_gs TypeError: is not a function, it is undefined.
So how can I make this work, or is this currently not supported?
Thx in advance for your help.

Yes, it's possible.
You are not limited to a single server Code.gs file. You can spread server code across multiple files for ease of development. All of the server files are loaded into the same global namespace, so use JavaScript classes when you want to provide safe encapsulation.
Reference: Google Documentation - features and limitations

I don't know what the _gs suffix means for Google, but without it (see code bellow), the code works.
file1.gs:
function onEdit(){
myFunctionFromLibrary();
}
file2.gs
function myFunctionFromLibrary(){
Browser.msgBox("hi there");
}

I know this is an old question but I found it looking for a similar task and happened to find the answer during my same search.
From the docs at https://developers.google.com/apps-script/guide_libraries#writingLibrary:
If you want one or more methods of your script to not be visible (nor usable) to your library users, you can end the name of the method with an underscore. For example, myPrivateMethod_().
While your function does not END in an underscore, it may have special meaning in other places than just this, or the _gs suffix may also have special meaning (particularly given the same filename suffix).

Related

How to reference an external spreadsheet with Google Apps Scripts

Update: It worked for 5 minutes then stopped working again. Not exactly sure why it's only working part of the time?
This sounds like it's supposed to be simple but I'm only finding information on "getActive" and my function works if I'm using all internal sheets but I tried using openById and nothing happened and openByUrl returns an error. The following is a simplified example of what I'm trying to do:
var store_data_sheet = SpreadsheetApp.openByID('ID here..').getSheetByName('Data');
store_data_sheet.getRange('A1').setValue('testing')
store_data_sheet.insertRows(1);
I'm sure I'm just using the wrong keywords or maybe this isn't even allowed but multiple users will be using their own copy of a specific sheet that runs this function and I'd just like to take certain cell's data and copy it to one external sheet (which is why it also inserts a row so it can push down entries)
Maybe I'm using the wrong "ID"? I assumed the number inside the URL was the ID. If it's something more specific, please let me know.
Like I said, this works flawlessly if I'm referencing an internal sheet. I'd like to be able to do the same exact thing with an external spreadsheet if possible. Thank you!
I found the issue. This function also renames the sheet file so if there is anything in the cell that is used to rename the file, it won't run the storing functions. I either need to run these before the renaming or take out the renaming aspect. ---moving these before the renaming part fixed the problem.

How to share functions in google scripts

Ok. this is simple but I had no success searching in internet.
I want to allow people to use the functions I make in Drive Scripts Editor, so that whoever that wants to use them in their own scripts can.
I want to be clear as I am not a programmer, so here is an example:
I have this script:
function myFunction(a, b) {
return a + b;
}
Then I want other people to just type:
function anothersFunction() {
var x = Titleofproject.myFunction(1, 2);
}
In order to get a 3 for his x (obviously Titleofproject would be much larger).
The idea is to give them the possibility of using it, but not to see the project source code, at least for now.
Thank you!
You can create a Shared Library but note that this is against best practices and the page starts with this:
Warning: A script that uses a library will not run as quickly as it would if all the code were contained within a single script project. Although libraries can make development and maintenance more convenient, you should avoid them in projects where speed is critical. Because of this issue, libraries should not be used in add-ons.

How to include a file into your project

I'm creating a Google Apps Script that's kind of a quiz marker / email merger in one. I've got everything working but my code is pretty long because I find myself having to use procedural coding. This is mostly because I don't know how to use the editor to include a class / library.
I've viewed the Crash Course Video by Kalyan on using the Script Editor, but it didn't answer my question. I've also scoured the internet with no luck.
If you look in the top left of this screenshot, you'll see I have Code.gs and test.gs:
I have all my code in the Code.gs file, but I want to include test.gs in Code.gs. Once I figure out how to do that, I'd like to create a couple of simple classes to organize my functions a bit better (and possibly re-use my classes later).
Thanks in advance!
To clarify Zig Mandel's answer and add to it:
All .gs files that are located in the same Script Project have global access to each other. That is to say that a function that you define in test.gs is accessible by Code.gs if they are in the same Script Project
You can create your own library of code. To do this you would simply create another Script Project, then go to Resources -> Manage libraries..., and add the project key of your original project (that contains the Code.gs and test.gs files). The project key is located in File -> Project properties.
The second bullet point is a good way to organize your code. If you have the same code that you are reusing throughout many Script Projects, then you want to put those functions into one Script Project and create a library out of them, as I explained above.
You already included the code. Should work as is. You can also look at the apps script docummentation and learn to use libraries for code reuse:
https://developers.google.com/apps-script/guide_libraries.
This makes development easier but for best performance you should include them all in your project before publishing like you did this time.
Part of the problem may be the order of execution. The .gs files are executed in order of creation. Copying Code.gs, deleting the original, then running functions from the new copy may fix your problem.
<?!= include('JavaScript.html'); ?>
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}

Best practice for writing equivalent powershell scripts and functions

I have a script that takes in multiple parameters, and that I've documented with proper help comments (e.g. .SYNOPSIS, .DESCRIPTION, .PARAMETER). Several different users in my organization are going to use this powershell script, some who know powershell and will call it from powershell with specific parameter values, and some who don't know powershell and will simply right-click on the script file in Windows Explorer and choose Run with PowerShell (so the parameters will use their default values).
My conundrum is what is the best way to do this in powershell without a bunch of duplicate code. The way I see it, these are my options:
1 - Just write a DoStuff.ps1 script that provides default values for all parameters. This allows it to be ran directly from Windows Explorer, but feels clunky for the powershell users that want to use it as a function from their own scripts, since instead of writing:
Do-Stuff param1 param1
they will be doing:
.\DoStuff.ps1 param1 param2
2 - Within DoStuff.ps1, move the operations it performs into a DoStuff function, and after the function declaration call the DoStuff function with the parameters passed into the script. This would still allow the script to be ran from Windows Explorer, as well as developers to dot source the script into their own scripts so they can access the function. The downside is that when the developers dot source the script, the script is going to call the function with the default parameters (unless I allow them to provide an optional Switch parameter to the script that triggers the function to not be called). Even with this though, it means that I would have to duplicate all of the scripts help text so that it shows for both the script and the function (description, parameter descriptions, etc.).
I can't think of any other options. Ideally I would just be able to write functions in .ps1 file and tag a function with a "default" keyword so that if the script is called, that function is ran by default; but I don't think PowerShell provides anything like this.
What do you think is the best approach in this situation. Is there something I'm overlooking or don't know about? Thanks.
but feels clunky for the powershell users that want to use it as a function from their own scripts
Default parameters would seem, based on your description, to be the best (or, at least, least-worse) approach.
But rather than naming your script DoStuff.ps1 name it and call it so it can be called more like an internal function:
Name it with the dash: Do-Stuff.ps1
Remember you don't need to specify the ps1
If the script is in a folder in $env:Path then you don't need to specify a path.
Also consider a script can load a module from a relative path: you could put most of the code in a script module which the front end (right click on it) script loads and calls into it. Script authors load the module themselves.

Call functions from another "class" / file

Ok, I feel embarrassed that I wasn't able to figure this out on my own, but after a few wasted hours, I figured it would be easier to simply ask over here:
I have a bunch of .gs-files in my Google Apps Script project. Now, I want to call another file's function from a method (something like AnotherClass.awesomeFunction(), which throws a ReferenceError though). Is this possible in Google Apps Script? If so, how?
Files aren't classes. You can call any functions in any file from any other file. Think of your files as if they were just added together before running. If you want class-like scoping you can use the Libraries feature.
The Above replies are correct above file being appended, make sure the order of the files in the file explorer on the app script project page is correct
The Function definition should be in the first file and the function call in the latter.
You change the option of the each file by clicking the 3 dots next to file name and selecting Move file up or Move file down
The following syntax allows you to call any function from within your Google Apps Script project, regardless of whether the function is defined in the same file that is calling it:
myFunction();
The following code is unnecessary and will throw errors:
google.script.run.myFunction();
It can do.
and Corey is right, files is not class.
I'd just like to add that order of files is not important as experienced by me so far. I'm working on a project where all calls are at the start to get a clear tree and all definitions of functions are at the end. Sometimes they're even mixed without any order within files too. So, I guess, it can call function from anywhere regardless of order within file or within project files. It's working in my case though.