I am trying to get an expense approval sheet working, most of it now works, but when I submit the script to send the approval results to the user and the sheet. I get following error:
TypeError: Cannot read property "approveExpenseReport" from undefined. (line 64)
The error is referencing the below line.
var approvedOrRejected = (approval.approveExpenseReport == "Yes") ? "approved" : "rejected";
Are you using this tutorial on Expense Approvals verbatim?
If not, please share more of the code or point to which sample/tutorial you are operating off. Basically, the error message means that the "approval" object instance is not set to a value.
Otherwise, looking at the code from the tutorial, my guess is that you have not properly created the "Approvals Spreadsheet". Perhaps, it doesn't have the right headers and row formats? Make sure to follow the steps in Section #2 in the tutorial.
Related
Someone on stack overflow from 2016 reported this issue happening in debug mode only but this isn't debug mode, it is happening in my live code (run from webapp) running in backend AND debug mode.
The frustrating thing is that this isn't every call to setValues. There is one array call to setvalues that does work (writes to the spreadsheet) higher in the script.
This code has not been modified in more than a month and was working until at least 10-26 (first failure reported 11-2).
Here is a small example:
function setValuesIsFailing(sheet, array, row, column){
//newIDR_SHEET.getRange(3, 9, formulaColumns.length, 2).setValues(formulaColumns);//old command this function replaces
const targetRange = sheet.getRange(row,column,array.length,array[0].length);
console.log(139,targetRange.getA1Notation());
sheet.getRange("C5").setValue("UGH");
targetRange.setValues(array);
console.log(sheet.getRange("C5").getValue());
}
The result of this code is the expected console log of :
10:46:10 AM Info 139 'I3:J49'
10:46:11 AM Error
Exception: Service Spreadsheets failed while accessing document with id 12shsTE-Mxxx
setValuesIsFailing # Code.gs:143
So line 139 implies that it does have the sheet it is writing to and then it
doesn't throw an error when told to write to those two locations (but it does
not succeed in writing to them) and after that it throws an error when asked
to read from one of the locations.
To recap:
code was working just fine. Had not been modified for a month and was working correctly most of that month.
setValue / setValues commands fail silently without throwing an error (nothing is written to target)
service spreadsheet error occurs later when trying to read from places that should have been modified by the script but were not
Moving the problem to a new function obviously didn't fix it.
Other things I tried, logging the sheet name, reassigning a new variable to the sheet (originalyl concerned that somehow the function was losing the sheet but debugging shows that isn't the case), moving the failing piece of code to a new function for easier logging, waiting for the problem to resolve itself.
Any ideas?
=====
Solved:
It turned out that the weird behavior was caused by a failed attempt to apply data validation to the sheet.
Unlikely that anyone else will have this behavior, but I was pulling my data validations down from a sheet a single column at a time.
Either it was accepting a 2d array of one column as acceptable to the data validation setup command OR it was automatically flattening the array since it was only one column. This has changed. Manually flattening my column data with a .flat() fixed the issue. I would really have expected the bad validation setting call to throw an error though.
I discovered that a bad validation application was causing the spreadsheet to basically stop being able to be updated.
It was reading a 2d array (one column) and applying that as a validation list. When I flattened the validation list it worked.
I hope you're well.
I'm using google sheets to help manage some data for my work. One of our programmers wrote a google apps script for me to log into our website, pull the data I need, and then dump it into google sheets. It works well, however sometimes it encounters and error and it fails to log in to our website. (please see the photo below)
Error I encounter
To fix the error, I need to delete the cell's contents, and then enter the function in that cell again. This forces the function to try again from scratch and it will load successfully.
What I cut and paste to fix it
What I need a way to automatically run all the functions again (something functionally the same as deleting it and entering it again manually).
I'm hoping for someway to create a button that I could press which would delete and re-enter the text in the relevant cells, or something like that. However, I would appreciate any solution that anyone can suggest.
I really appreciate it!
-edit: I should also mention that I'm using this function a lot in a large range of spreadsheets and they're all interconnected so when one gets an error, it kills the entire web of documents and I need to root around for which one failed and then copy its contents, delete it, then enter it again.
edit 2: Thank you fir your first response and sorry about posting images of the error I received. You've set me down the right path and I've combined this onEdit function for when I edit single sell to directly replace the text in that cell. When I use "foo" or something like that, it works and replaces the text in that sell with "foo". However, what I really need to replace it with is =ImportJSON("expertList", 1) but when I try i get an error:
Syntax error: SyntaxError: Unexpected identifier line: 341 file: Code.gs
Here's the code in question:
function onEdit(e) {
if (e.range.getA1Notation() === 'A1') {
refresher()
}
}
function refresher() {
var newValue = '=yourfunction()';
var sheetName = "sheet name";
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
var range = sheet.getRange("this is the cell you want to re-write");
range.clearContent();
SpreadsheetApp.flush();
range.setValue(newValue);
}
Last Edit:
Thanks for the help! If anyone stumbles on this post in the future, the above code works to delete what's in cell, then enter it again into that same cell (thereby resetting the function)
I am unable to change grades using the Google Classroom API. When I run the code below, lines 2 and 3 run fine. However, line 4 fails with the following message: #ProjectPermissionDenied The Developer Console project is not permitted to make this request.
1) var studentSubmission = {'assignedGrade':'1'};
2) var studentSubmissions = Classroom.Courses.CourseWork.StudentSubmissions.list(courseId, courseWorkId, {userId:'studentEmail#apps.matsuk12.us'});
3) var studentAssignmentId = studentSubmissions['studentSubmissions'][0].id;
4) Classroom.Courses.CourseWork.StudentSubmissions.patch(studentSubmission, courseId, courseWorkId, studentAssignmentId,{'updateMask':'assignedGrade'});
When I go to Project Properties and look at the scopes, here is what I see:
https://www.googleapis.com/auth/classroom.courses
https://www.googleapis.com/auth/classroom.coursework.students
https://www.googleapis.com/auth/classroom.profile.emails
https://www.googleapis.com/auth/classroom.profile.photos
https://www.googleapis.com/auth/classroom.rosters
https://www.googleapis.com/auth/spreadsheets
I am trying to access my own Google Classroom using a container bound script (spreadsheet). Seems like if I have access to the assignments, I should have access to add a grade. Not sure why I can't add the grade. Is there anything I can do to get this code working? The end goal is to be able to grade assignments using a form (not a google form) and have the score automatically pushed to Google Classroom.
I saw a related post that mentions a solution, but it is not clear how to implement it: Permission denied using Classroom.Courses.CourseWork.StudentSubmissions.list(4140802199, 4801051201);
I also see a related bug report here: https://issuetracker.google.com/issues/67748271 (I'm not sure though if this really is a bug, or if this is just how the Google Classroom API works, or if I'm just doing something wrong)
From the posts you linked someone posted this code:
function createCoursework (id) {
Classroom.Courses.CourseWork
.create(id, {
// doesn't work but triggers permissions correctly "courseId": id, "title": 'foo', "description": 'desc', });
}
Essentially you need to put this code somewhere in your projects code. Then, using the, Run menu, execute that function. It won't do anything, but it will initialize the authorization request from google; by means of a popup. After that you should be good to delete that function and use that scope.
I am trying to connect a Google Spreadsheet with Google BigQuery for that I created a Google Apps Script but when I try to run it I get the following error:
Cannot call method "setSchema" of undefined.
The code calling setSchema is the following
var loadJob = BigQuery.newJob()
.setConfiguration(
BigQuery.newJobConfiguration()
.setLoad(
BigQuery.newJobConfigurationLoad()
.setSourceFormat("NEWLINE_DELIMITED_JSON")
.setSchema(sshema)
.setDestinationTable(json_table.getTableReference())
)
);
When I view the log for sshema I get a correct JSON like
{fields=[{name=first, type=STRING}, {name=last, type=STRING}]}
I am not sure how to solve the error, when I comment out the SetSchema line the error goes away...but obviously the script does not do what its suppose to.
Any tip in the right direction will be appreciated. Thanks!
UPDATE: I tried debugging the script and the line that is suppose to create the newJob() simply inserts the {} value into the loadJob variable. I am not sure why this is not working but at least it seems to be the problem.
This is a temporary bug, should be fixed in a week. You can track it at:
https://code.google.com/p/google-apps-script-issues/issues/detail?id=2906
In the meantime, you can bypass it by not chaining the sets(): https://stackoverflow.com/a/17420247/132438
I'm looking for examples of a pattern where a demon script running within a GoogleAppsForBusiness domain can parse incoming email messages. Some messages will will contain a call to yet a different GAScript that could, for example, change the ACL setting of a specific document.
I'm assuming someone else has already implemented this pattern but not sure how I go about finding examples.
thx
You can find script examples in the Apps Script user guide and tutorials. You may also search for related discussions on the forum. But I don't think there's one that fits you exactly, all code is out there for sure, but not on a single script.
It's possible that someone wrote such script and never published it. Since it's somewhat straightforward to do and everyone's usage is different. For instance, how do you plan on marking your emails (the ones you've already read, executed, etc)? It may be nice to use a gmail filter to help you out, putting the "command" emails in a label right away, and the script just remove the label (and possibly set another one). Point is, see how it can differ a lot.
Also, I think it's easier if you can keep all functions in the same script project. Possibly just on different files. As calling different scripts is way more complicated.
Anyway, he's how I'd start it:
//set a time-driven trigger to run this function on the desired frequency
function monitorEmails() {
var label = GmailApp.getUserLabelByName('command');
var doneLabel = GmailApp.getUserLabelByName('executed');
var cmds = label.getThreads();
var max = Math.min(cmds.length,5);
for( var i = 0; i < max; ++i ) {
var email = cmds[i].getMessages()[0];
var functionName = email.getBody();
//you may need to do extra parsing here, depending on your usage
var ret = undefined;
try {
ret = this[functionName]();
} catch(err) {
ret = err;
}
//replying the function return value to the email
//this may make sense or not
if( ret !== undefined )
email.reply(ret);
cmds[i].removeLabel(label).addLabel(doneLabel);
}
}
ps: I have not tested this code
You can create a google app that will be triggered by an incoming email message sent to a special address for the app. The message is converted to an HTTP POST which your app receives.
More details here:
https://developers.google.com/appengine/docs/python/mail/receivingmail
I havn't tried this myself yet but will be doing so in the next few days.
There are two ways. First you can use Google pub/sub and handle incomming notifications in your AppScrit endpoint. The second is to use the googleapis npm package inside your AppScript code an example here. Hope it helps.
These are the steps:
made a project on https://console.cloud.google.com/cloudpubsub/topicList?project=testmabs thing?
made a pubsub topic
made a subscription to the webhook url
added that url to the sites i own, i guess? I think I had to do DNS things to confirm i own it, and the error was super vague to figure out that was what i had to do, when trying to add the subscription
added permission to the topic for "gmail-api-push#system.gserviceaccount.com" as publisher (I also added ....apps.googleusercontent.com and youtrackapiuser.caps#gmail.com but i dont think I needed them)
created oauth client info and downloaded it in the credentials section of the google console. (oauthtrash.json)