Keep getting 'Null' when pulling data from google sheets - google-apps-script

Whenever I try to pull data from 2 of 3 sheets from using the 'google.script.run' function call from Javascript, I keep getting an error saying the array I am returning is Null, but when I just change the exact same function call to work on another sheet, it returns the data perfectly
I have tried deleting the sheets and giving it the same names, I have tried using 'openWithURL' instead of 'getActive' to access the spreadsheet, I have tried rewriting the code, I have tried the same code in a different project, and checking the documentation to make sure I am not missing any detail. I have tried changing the references to the sheets, some work and some dont.
var SS = SpreadsheetApp.getActive();
var DB_BOOKINGS = SS.getSheetByName("BookingDatabase");
var DB_VEHICLES = SS.getSheetByName("VehicleDatabase");
var DB_REQUESTS = SS.getSheetByName("RequestDatabase");
function getRequestData(){
return DB_REQUESTS.getDataRange().getValues();
}
<script>
function getRequestData(callingFunction) {
google.script.run
.withSuccessHandler(callingFunction)
.withFailureHandler(CustomAlert)
.getRequestData();
}
</script>
I want to retrieve the sheet data but keep getting a null value

Since this is an issue with formatting as you said, try using getDisplayValues() rather than getValues(), this will pull the data as you see it in the sheet (as a string), rather than the unformatted data itself.
Reference:
getDisplayValues

I was having a similar problem. This was exactly the solution I needed. For my situation, I was able to use getValues() successfully on the initial page load, but when I tried to run it again as a sort of 'refresh' to update the values without reloading the entire page, it would return null.
My data did indeed contain dates, so after changing it to getDisplayValues(), it worked perfectly.

Related

Range.SetValues() does not insert data on one sheet, on the other works. What is the reason?

I have a GoogleSheet with basically two sheets, which are very similar in terms of data collected.
I need to calculate same values for both sheets, but source data is in different columns.
Therefore I created three files in AppsScript:
Common.gs - with common function definitions
sheet1.gs
sheet2.gs - both sheet1 and sheet2 have only definitions of proper ranges in particular columns and one function to run script, which essentially calls functions defined in Common.gs, like so in sheet1.gs:
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheet1")
var createdColumn = sheet.getRange("E2:E").getValues()
var ackColumn = sheet.getRange("G2:G").getValues()
var resColumn = sheet.getRange("I2:I").getValues()
var timeToAckColumn = sheet.getRange(2,14,ackColumn.length,1)
var timeToResColumn = sheet.getRange(2,15,resColumn.length,1)
var yearAndWeekRange = sheet.getRange(2,16,createdColumn.length,2)
function calculateMetricsSheet1() {
calculateTimeDiff(createdColumn, ackColumn, timeToAckColumn)
calculateTimeDiff(ackColumn, resColumn, timeToResColumn)
calculateWeek(createdColumn, yearAndWeekRange)
}
example function implementation (they are basically very similar with minor differences):
function calculateWeek(createdColumn, yearAndWeekRange) {
var arrData = []
for(var i=0;i<createdColumn.length;i++) {
if(createdColumn[i][0].toString()=="") {
arrData.push(["",""])
continue
}
var createdDate = new Date(createdColumn[i][0])
var year = createdDate.getFullYear()
var week = Utilities.formatDate(createdDate, "GMT+1", "w")
arrData.push([year, week])
}
yearAndWeekRange.setValues(arrData)
}
the sheet2.gs is basically different column definitions, the functions called within calculateMetricsSheet2() are the same.
So what is the problem?
The script works perfectly fine for sheet2.gs, but for sheet1.gs it does collect proper data, calculates proper data, but the data does not appear in proper columns after Range.setValues() call.
No exceptions or errors appear in the console.
Documentation does not provide any kind of information what could be the problem.
I have really ran out of ideas what could be the cause of the issue.
Does anyone have any idea what is going on?
edit: It may be useful to put emphasis on the fact that each script runs function calling 3 other functions -> all of them end with Range.setValues({values}). And for one sheet all of them work, and for the other - none.
That's the reason I assume there is something wrong with the sheet itself, maybe some permissions/protection? But I couldn't find anything :(
edit2: I modified my code to iterate through the sheet 10 rows at a time, because I thought maybe when I get a whole column, something bad happens with data and breaks setValues() function.
Unfortunately - even if my code iterated 1 row at a time, it still did not work on sheet1, but worked on sheet2. So not a data problem.
The code you show always puts values in yearAndWeekRange which is always in the 'sheet1' sheet. To put the data into another sheet, you need to change the target range appropriately.
The dimensions of the range must match the dimensions of the array you put there. Use this pattern:
yearAndWeekRange.offset(0, 0, arrData.length, arrData[0].length).setValues(arrData);
I found out what is the problem.
Two scripts were pretty identical, even with naming of variables - ie ackColumn, resColumn etc.
Those were stored as a global variables, so even if I was running script1.gs, it used global variables from script2.gs, effectively writing proper data to wrong sheet.
separating global variables names fixed the issue.
Perhaps a rookie mistake, but I missed the fact, that if I have a variable defined outside any function, it becomes global and could be overwritten from other file

How to fix error in google sheet custom script [duplicate]

I have a .tsv file from a tool and I have to import it the Google Sheet (nearly) real-time for reports. This is my code for importing:
function importBigTSV(url) {return Utilities.parseCsv(UrlFetchApp.fetch(url).getContentText(),'\t');}
It worked till some days ago when Error messages keep saying "Exceeded maximum execution time (line 0)."
Could anyone help? Thank you a lot!
Issue:
As #TheMaster said, custom functions have a hard limit of 30 seconds, which your function is most probably reaching. Regular Apps Script executions have a much more generous time limit (6 or 30 minutes, depending on your account), so you should modify your function accordingly.
Differences between functions:
In order to transform your function, you have to take into account these basic differences:
You cannot pass parameters to a function called by a Menu or a button. Because of this, you have to find another way to specify the URL to fetch.
Values returned by a regular function don't get automatically written to the sheet. You have to use a writing method (like setValues, or appendRow) to do that.
A non-custom function is not called in any particular cell, so you have to specify where do you want to write the values to.
Since, from what I understand, you are always fetching the same URL, you can specify that URL just by hardcoding it into your function.
Solution:
The function below, for example, will write the parsed output to the range that is currently selected (at the moment of triggering the function). You could as well provide a default range to write the output to, using getRange:
function importBigTSV() {
var url = "{url-to-fetch}";
var range = SpreadsheetApp.getActiveRange();
try {
var output = Utilities.parseCsv(UrlFetchApp.fetch(url).getContentText(),'\t');
var outputRange = range.offset(0, 0, output.length, output[0].length);
outputRange.setValues(output);
} catch(err) {
console.log(err);
}
}
If the URL can change, I'd suggest you to have a list of URLs to fetch, and, before triggering the function, select the desired URL, and use getActiveRange in order to get this URL.
Attaching function to Menu:
In any case, once you have written your function, you have to attach this function somehow, so that it can be trigged from the sheet itself. You can either create a custom menu, or insert and image or drawing, and attach the script to it. The referenced links provide clear and concise steps to achieve this.
Reference:
Custom Functions > Return values
Custom Menus in G Suite

Google spreadsheet - #N/A error when imported range has a custom function

In my Google spreadsheet (the newest version, as of August 2014) I'm using =IMPORTRANGE(P5,"Tasks!b6:o7") where P5 cell contains another spreadhsheet's key. One of the cells in the other spreadsheet contains my custom function, that sometimes takes time to calculate (there are dozens of cells using that function). The problem is that in the first spr. that cell's value is not displayed properly, the #N/A error message is displayed instead.
The function is defined as follows:
// global variable
var ONEDAY = 24*60*60*1000; // hours*minutes*seconds*milliseconds
function _mySimpleCalculateDaysDifference(DateToBeChecked)
{
var todaysDate = new Date();
var todaysDayModifier = todaysDate.getHours()<6?-1:0;
var daysDiff = (todaysDate.getTime() - DateToBeChecked.getTime())/ONEDAY;
return Math.floor(daysDiff) + todaysDayModifier;
}
It's being called the following way:
=if((H18>0),(H18-F18),if((F18>0),_mySimpleCalculateDaysDifference(F18),""))
where F and H columns contain date values.
Is there any way to solve that problem?
Edit:
I mentioned that the main spreadhsheet is the newest Google spreadsheet, but those being pulled in were 'old'.
This answer relates to a situation when the importing spreadsheet is the 'new' one, and imported - the 'old' (as of September 2014):
Make sure that both spreadsheets are of the same version, i.e. old<-old or new<-new (although as #eddieparkinson commented, in his case similar issue existed for an old<-old situation).
In my case converting the imported spreadsheet to the new helped and I cannot observe the issue now.
PS
Probably the easiest way to convert is to save it as an Excel file, then import it back into Google Drive and convert into Google spreadsheet. I found it the easiest and most reliable way, although I lost my charts and scripts. There were also problems with validations, so I had to recreate them. If you're not using any of these - it should be OK.

Google Apps Script in Spreadsheet storing decimal values instead of Integer in Project Properties

This is my first post. I tried searching via Google and this site but really couldn't find any info about typecasting or converting numerical values within GAS specifically in this scenario. So here the problem:
I have a very basic script attached to a Google Spreadsheet. The script simply keeps track of the last row that was populated, increments the value by one, so that the next row can be populated. I'm storing the "last row used" as a Project Property. For some reason, the script keeps writing the value back into Project Properties as a decimal value, which throws off the whole script since it seems I can't use a decimal value to reference a cell location.
Here is the code snippet:
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var value = ss.getSheetByName("Sheet1").getRange("D13").getValue().toString();
var last = ScriptProperties.getProperty("last");
var therowx = parseInt(ScriptProperties.getProperty("therow"));
Browser.msgBox("The last row is: " + therowx);
if( value != last ) {
ScriptProperties.setProperty("last", value);
ScriptProperties.setProperty("therow", therowx + 1);
}
}
Assuming that I've pre-set the Property to 1 before running the script, once this method fires, it sets it to 2.0 instead of just 2. I've tried wrapping the method call with the Number() and parseInt() functions but they don't seem to make a difference.
I'm open to suggestions, as I'm sure I'm doing something wrong but just not quite sure what.
It would appear that you are using a value from the spreadsheet with var value = ss.getSheetByName("Sheet1").getRange("D13").getValue().toString();
This is were you are getting the decimal as Google spreadsheets will default to one decimal place. You will need to highlight the column or cell and change the format to Number>Rounded to get rid of it.
I am sure i am missing some components of your full script here, however have you tried the "getLastRow" function? There are some scripts in the tutorials that use it and it is a tried tested and true method of finding the last row of the sheet.

ABOUT: Tutorial: Sending emails from a Spreadsheet

Is it possible to get this script updated? In 2009 it may have worked, but it doesn't now.
Tutorial: Sending emails from a Spreadsheet -
Quick link to Google Developers Tutorial
I can't for the life of me get my own script to work. Having a problem incrementing the rows correctly when it checks before sending, which is either leaving me sending a dozen e-mails of a single row of data or if I try to implement a while loop, I've ended up sending myself over hundreds of e-mails and google then stops me from using the function any further until the next day.
My specific script question is HERE, except I don't think I worded it correctly because no one is replying.
It seems that you forgot a couple of things in your script :
1° : var dataRange = sheet.getRange(sRow,1,1,cols); // this gets only 1 row in your sheet so it is normal that the loop doesn't work (length=1).
I'd suggest to replace the height value by the last row value (see docs to get that value) to make the loop iterate through every rows.
2° when you use .setValue(EMAIL_SENT); the value of EMAIL_SENT is not defined in your code (it is defined outside the function in the tutorial).
I'd suggest to add a statement like this : var EMAIL_SENT="EMAIL_SENT" or, more simply use the string value in your 'setValue' statement like this : .setValue("EMAIL_SENT");