ss.getSheetByName() not a function errlr [duplicate] - javascript

My code is meant to take data from a user input form and insert a new row to a spreadsheet:
function addNewRow(rowData) {
const currentDate = new Date();
const ss = SpreadsheetApp.getActiveSheet;
const ws = ss.getSheetByName('DataTable');
ws.appendRow(rowData.userName,rowData.userProject, rowData.workDate, rowData.timeSpent, currentDate);
}
Yet when I run the code it returns
TypeError: ss.getSheetByName is not a function

Use const ss = SpreadsheetApp.getActive() to get the spreadsheet. Note the parentheses. The function will not get called if you omit them.

The error "getSheetByName is not a function" occurs when running a function in Google Apps Script when this method is called upon a variable that wasn't assigned a Class Spreadsheet object.
In this case, the OP forgot to include the parenthesis at the end of SpreadsheetApp.getActiveSheet causing Spreadsheet.getActiveSheet method to be assigned to the variable instead of executing this method to return a Class Sheet object. This also happens when chaining another method that doesn't return a Class Spreadsheet Object, i.e. Spreadsheet.getActiveSheet().getName() returns a string.
In the OP case the solution is straightforward as already was show in the previous answer. Other cases having the same error might require a different solution, to find it,
Check the correct spelling and syntax. For this it's very helpful to understand the pretty basics of JavaScript, i.e, JavaScript is case sensitive. This means that getActiveSheet is not the same as getactivesheet.
Check the official guides in https://developers.google.com/apps-script/overview, more specifically https://developers.google.com/apps-script/guides/sheets.
Check the official reference in https://developers.google.com/apps-script/reference. In this specific case you might search for getSheetByName directly in this link. In this case this method is used in several examples that might be helpful to understand it.
Going deep in the Google Apps Script editor, use the autocomplete feature to have instant feedback about it the method is available for the object assigned to the variable: Type a dot after the variable name, this will show a list of the available methods, continue typing the method name to filter the list suggestions, if there isn't any suggestion, then there is very likely that there is a problem on the variable declaration. Ref. https://developers.google.com/apps-script/guides/services/#using_autocomplete
Use the Google Apps Script debugger. Ref. https://developers.google.com/apps-script/guides/support/troubleshooting#debugging
Go deep in learning JavaScript. There a lot of resources to start learning JavaScript. By default Google Apps Script use V8 to execute scripts. Please bear in mind that Web APIs like the DOM API aren't available in V8. It's worthy to note that there are some JavaScript functions that aren't supported in Google Apps Script like async as well some Global Objects like Promise
Related
How do I check if an object has a specific property in JavaScript?
Accessing spreadsheet in Google Script (this question is about a similar TypeError message)
Automatically replace dots with commas in a Google Sheets Column with Google Script (this question is about a similar TypeError message)

Related

Google Script API understanding

This is a two part question, regarding the Google Script API.
First, I can read the SDK/API reference, and execute examples successfully, via the "try now" feature. But, what I am missing a step in understanding when trying to build webApps (with limited javascript knowledge - admittedly). Namely, the SDK shows the syntax for many things but not in the way I would expect to use it within Javascript.
A concrete example of my problem: I am trying to create a simple function to return verification Codes (8-digit codes) from the Admin API. Here is an example function.
function getCodes(){
var userEmail = 'testuser#exampl.com';
var user = AdminDirectory.Users.list({userKey: userEmail}).verificationCodes;
Logger.log('User data:\n %s', JSON.stringify(user, null, 2));
}
naturally, the syntax for the AdminDirectory call is wrong, I get errors. I have tried many different variation, but without a proper understanding of the reference, I feel like I am just guessing (and I have guessed a lot).
Can someone throw me a bone? Thanks
Have a look at the Users resource
You will see that verificationCodes is not part of this resource
However, there is a way to retrieve verification codes: with VerificationCodes: list
To usew the latter, you need to provide the userEmail as parameter
So modify your request to:
AdminDirectory.VerificationCodes.list(userEmail).items.forEach(function(item){Logger.log('Code: ' + item.verificationCode)});

Instantiating a class dynamically from a string

Good afternoon fellow developers,
I am currently trying to develop a function that instantiates business objects dynamically based on the value of the string it receives as a parameter. I know this can be done in JavaScript as I have done it before and, just to be sure, I even tested it again in Visual Studio Code after having encountered this issue in my SAPUI5 app. My function's code looks somewhat like this:
createObject: function (sObject) {
var newObject = new this[sObject]();
// var newObject = new [sObject](); I also tried this way.
};
For the sake of testing this function, the sObject string currently contains the hardcoded value "Order" and I am importing my Order.js object into the file where i'm trying to instantiate this objects dynamically. No matter what I try I keep getting this error when debugging my code:
TypeError: this[sObject] is not a constructor
I was wondering if some of you might have tried something similar before and might be able to point me in the right direction. Even if there are ways for me to work around this issue, it would be really nice if I learnt how to do this dynamically since I was planning on using this approach on several different scenarios. I look forward to reading from you!
It is a really unsafe practice to instantiate objects from a string and an ATROCIOUS one to do it from a parameter a user can supply. If you have a limited set of objects its much safer to have a big switch statement.
switch(name) {
"objA": return new ObjA();
}

Is there a Google app scripts function reference?

I was trying to create a function that takes a number of minutes and outputs it in a nice readable format. For instance, FORMATMINUTES(1570) would output 1d2h10m, but I got hung up trying to find a truncate function. I also had to change my lets to vars. Is there a reference that tells you what javascript features are available when writing custom functions?
To simplify I created two functions. First, the Math.trunc() function doesn't seem to exist as it doesn't show up as a suggestion and throws an error when used:
function MYTRUNC(input) {
return Math.trunc(input);
}
Second I thought that maybe I could use sheets's built-in TRUNC function, but that isn't defined either:
function MYTRUNC2(input) {
return TRUNC(input)
}
I read google's guide but it says "Custom functions are created using standard JavaScript" but not what version of javascript. Apparently it doesn't support let.
Their app scripts reference has a lot of information on interacting with sheets, but not a basic or complete reference. I realize that in this situation I can use Math.floor which is available or subtract input % 1, but I'd like to know what other idiosyncrasies there might be, and if I can use newer javascript features. Template literals give an error as well, so maybe it's based on an earlier javascript version?
The best reference I have found is from within the online Script Editor's debugger.
Make a breakpoint anywhere in any function. Then run that function with the bug button to start debugging. Next, click on the two buttons at the end of the tool bar: "Show inheritance" and "Show all data".
In the debugger, you should see a this with a "+" to expand it. Expand it and then expand [[prototype]] to see all the builtin App Script objects (GmailApp, etc), then find the next [[prototype]] below those to see the standard JavaScript objects such as Array, Math, Date, etc and you can inspect all of the functions that are available from there.

What's the best way to handle Eclipse errors on CouchDB Map/Reduce JavaScript functions?

As noted in Where to write and store mongoDB map/reduce functions in java project - Eclipse doesn't like a JavaScript (.js) file to only contain the following:
function(doc) {
if(doc.somekey) emit(doc._id, doc);
}
The keyword function is marked with an error:
Syntax error on token "function", Identifier expected after this token
This form is used in MapReduce, but perhaps it's not exactly valid JavaScript (I'm not a lawyer). Is there any way to allow this form?
edit it looks like it's a function expression instead of a function statement. ( MDN, ECMA-262 )
Non-solution: "Just add a function name" according to https://stackoverflow.com/a/11258388/185799 it seems that it's not important to economize on the size of these functions. However, adding a function name results in: {"error":"compilation_error","reason":"Compilation of the map function in the 'myView' view failed: Expression does not eval to a function."}
Possible solution? Add a function name or "module.exports = " at the top, and then remove it during a build phase, using grunt/gulp/yeoman or something related.
For now, what I am actually doing is using the literal form function anonymous(... and then doing a string replace just before calling synchronizeWithDb() to replace function anonymous( with function(. This doesn't answer my question, but works around it.
You have three bad options:
You can ignore the error since CouchDB can process this file (it will wrap it later to make it valid).
You can change the file extension but then you lose syntax highlight, code completion and error checks.
You can delete the error in the error view. It will stay deleted until you change the file the next time or you do a full build.
You may be able to configure Eclipse to stop validating the file.
There are two ways to implement #4:
You can ignore the resource. That makes this file invisible to Eclipse and all plugins. Which means you can't edit it anymore inside of Eclipse. Use Resource Filters for that.
You can check the per-project preferences for Validation rules for JavaScript. Maybe you can exclude the file.

Calling COM methods from unreferenced assemblies

I'm migrating an install script from js to vb.net and I'm facing the following problem.
I'm having issues as JS is late-binded so I need to research the datatype returned by each method in order to make the strong typed counterpart in vb.net (or C# for the matter)
In the original js install script, I'm getting to a point where I don't know how to port this 2 calls:
var objWMIService = GetObject("winmgmts:\\\\.\\root\\cimv2");
var objAccount = objWMIService.Get("Win32_SID.SID='S-1-1-0'");
If I leave data type inference, I get COMType, so I can't call the Get method from the generated object.
I think I could solve this by using IDispatch, but It's been like 10 years since I used IDispatch and I can't rememeber exactly how to do it.
Also, after further research, I've seen that the internal COM is actually a SWBemServicesEX object, which I don't know what to reference in order to generate a COM interop system.
I would appreciate it a lot, if anyone can provide any ideas or solutions to this issue.
Current vb.NET code is just:
Dim objWMIService = GetObject("winmgmts:\\.\root\cimv2")
not sure how to be able to call the Get method from objWMIService, and how to determine what this method actually returns!
I ended doing what Steve says in his answer and it solved the issue for me. I'm not very happy with runtime late binding, but it gets the job done!
for reference:
Try using Dim objWMIService as Object = GetObject("winmgmts:\.\root\cimv2") instead. Then you can use Dim objAccount as Object = objWMIService.Get("Win32_SID.SID='S-1-1-0'"). When doing late-binding, declare everything as an object. You can then step through the code in debug and sometimes see what the return is. Then search for the methods/properties/etc for that type and write your next line. Takes a little work but you don't need references to any dlls. Theres just an assumption that the dll are registered (COM) or in your path that .Net follows (CLR)

Categories

Resources