Getting an error parsing data in google sheet custom script function - google-apps-script

I created a simple custom function to test in google sheets script functions. The function definition is :
/**
* convert duration such as 1:30 to 1.5
*
* #customfunction
*/
function SIMPLETEST(input) {
// simply return the input for now to test.
return input;
}
and in my spread sheet I have a cell A2 that have value 3:30:00. when I apply this function on B2 for example set b2 to: =DURATION_DECIMAL(A2) it returns 12/30/1899 which I believe is base date.
Why is this happening?

It's because you must have the data type for that cell set to "automatic" or "duration", and Google Sheets will guess that "3:30:00" is a type of date/time for automatic, and for duration it converts it to date/time for passing to your function. It lets you keep it in your format (#:##:##), but when you pass it to your custom formula, Sheets first converts it to a Javascript Date object, which your function then returns, and sheets automatically displays as a regular date (12/30/1899). See Google's warning about Date conversions with custom functions here.
The easiest solution is to just explicitly set your input format to "plain text" using the format selection dropdown, and then in your custom function code, you can parse it as you see fit.
For example, I used this StackOverflow answer to write your custom function:
function DURATION_DECIMALS(input){
// https://stackoverflow.com/a/22820471/11447682
var arr = input.split(':');
var dec = parseInt((arr[1]/6)*10, 10);
return parseFloat(parseInt(arr[0], 10) + '.' + (dec<10?'0':'') + dec);
}
And here it is working with format set to plain text:

This works for me:
function durdechrs(dt) {
return Number((dt.valueOf()-new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()).valueOf())/3600000).toFixed(2);
}

Related

Google Apps Script - force setValue to text

I am using setValue() to put values from an array into spreadsheet cells. Some array elements contain data that is text, but is being parsed as numeric, eg: "6E5", and setValue() converts them (in that case the cell gets the numeric value 600000). Is there any way to force the cell to be a text value?
I think you're looking to set the number format. Do this before you setValue. See example below. You could also create all of your array values to be a formula. Example ="6E5" see an answer I posted here related to forms.
Something like this....
/** #OnlyCurrentDoc*/
function setRangeToBeText() {
var newValue = [["6E5","7d","99"]];
//test on first cell
var theRange = SpreadsheetApp.getActiveSheet().getRange(1,1,newValue.length,newValue[0].length);
//sets format first
theRange.setNumberFormat('#');
theRange.setValues(newValue);
}
Example setting Format:
Example WITHOUT setting format:
]

How do I get the current cell in a Google Apps Script function?

I have a Google Sheet. In that sheet, I have a readonly cell that calls a custom function called formatCell. In that function, I need to dynamically set the number format. I know I can set the number format using the setNumberFormat function. To demonstrate, here is where I'm at:
function formatCell(p) {
var cell = null; // TODO: Get the cell that calls `formatCell`
if (p === 1) {
cell.setNumberFormat("0.000");
} else if (p === 2) {
cell.setNumberFormat("# ?/?");
}
}
What I don't know is how to get the cell that calls formatCell. I know there is a getCurrentCell function. However, that function gets the cell with the current focus. I need to get the cell that is calling formatCell. How do I do that?
To get the cell containing the formula use SpreadsheetApp.getActiveRange().
Please bear in mind that custom functions can't change cells characteristics, they can only return a value or an array of values.
Reference
https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app#getActiveRange()
https://developers.google.com/apps-script/guides/sheets/functions

How to get fixed cell value, not formula?

I have a cell in Google Sheets, with =NOW() formula in it. All I need - to get the value, generated by formula (22.01.2014 15:23:51), not the formula by itself.
If I try: var nowtime = SpreadsheetApp.getActiveSheet().getRange('A1').getValues();,
I get ={DATE(2014\1\22)+TIME(15\19\13)}, but not the numbers.
How to do it with Google Script syntax?
I know I'm a little late to the party here, but you could try .getDisplayValue() instead of .getValue() or .getDisplayValues() instead of .getValues() That will give you the result of the formula instead of the formula itself.
I just had the same problem and the above solution worked for me.
Use this little snippet to do that.
Code
function getCell(startcol, startrow) {
// prepare string
var str = String.fromCharCode(64 + startcol) + startrow;
// retrieve value
var vCell = SpreadsheetApp.getActive().getRange(str).getValue();
// return content cell
return vCell;
}
Screenshot
Explained
The first parameter of the custom function passes on the column index, as an integer. The var str creates from the column integer and the row index a string (A1 notation). Then the value is retrieved and returned to the spreadsheet.
This piece of code will retrieve any value.
Add the script under Tools>Script editor. Press the "bug" button to validate the script and you're on the go !!

Using built-in spreadsheet functions in a script

I'm using Google App Script for the first time.
I'm using it on a Google Doc spreadsheet.
I'm trying very simple functions, just to learn the basics. For example this works:
function test_hello() {
return 'hello';
}
But I'm puzzled by this simple one :
function test_today() {
return today();
}
It makes an #ERROR! wherever I use it.
And when I put my cursor on it, it says :
error : ReferenceError: "today" is not defined.
While the today() function works when used directly in the spreadsheet.
Does this mean that in scripts, I cannot use spreadsheet built-in functions?
Is there any elegant way around this?
Some spreadsheet functions are quite useful to me (I like weekday() for example).
A non-elegant way could be to create columns to calculate intermediate values that I need, and that can be calculated with spreadsheet functions. But I'd rather avoid something this dirty and cumbersome.
Google Apps Script is a subset of JavaScript, spreadsheet functions are currently not supported.
For example, if you want to create a function that returns today's date you should write :
function test_today(){
return new Date()
}// note that this will eventually return a value in milliseconds , you'll have to set the cell format to 'date' or 'time' or both ;-)
syntax is the same as with sheet functions : =test_today() see tutorial
There are many internet ressources on javascript, one of the most useful I found is w3school
Google Apps Script still does not (1/7/20) include an API to Google Sheets native functions.
But you can set the formula (native functions) of a cell named as a named range in a spreadsheet.
Then in the GAS:
var nativeOutput = spreadsheet.getRangeByName("outputCell").getValue();
Voila! Your GAS is calling the native function in the cell.
You can send data from the GAS to the native function in the cell, by naming another cell in the sheet (or in any sheet) referred to by the formula in the other cell:
spreadsheet.getRangeByName("inputCell").setValue(inputData);
Your GAS can dynamically create these cells, rather than hardcoding them, eg:
// Create native function, its input and output cells; set input value; use native function's output value:
// Use active spreadsheet.
var spreadsheet = SpreadsheetApp.getActive();
// Name input, output cells as ranges.
spreadsheet.setNamedRange("inputCell", spreadsheet.getRange("tuples!F1"));
spreadsheet.setNamedRange("outputCell", spreadsheet.getRange("tuples!F2"));
var outputCell = spreadsheet.getRangeByName("outputCell");
var inputCell = spreadsheet.getRangeByName("inputCell");
// Set native formula that consumes input cell's value, outputting in formula's cell.
outputCell.setFormula("=WEEKNUM(inputCell)");
// Call native function by setting input cell's value for formula to consume.
// Formula sets its cell's value to formula's output value.
inputCell.setValue(15);
// Consume native function output.
var nativeOutput = outputCell.getValue();
Logger.log("nativeOutput: "+ JSON.stringify(nativeOutput)); // Logs "nativeOutput: 3"
Beware: this technique exposes the code in cells that a spreadsheet user can access/change, and other spreadsheet operations could overwrite these cells.
What the spreadsheet functions can do, Javascript can do. I just have to replace var day_num = weekday() by var day_num = new Date(date).getDay()
Here is the result :
/**
* Writes the day of the week (Monday, Tuesday, etc), based on a date
*/
function day_name(date) {
// calculate day number (between 1 and 7)
var day_num = new Date(date).getDay();
// return the corresponding day name
switch(day_num) {
case 0: return 'Sunday'; break;
case 1: return 'Monday'; break;
case 2: return 'Tuesday'; break;
case 3: return 'Wednesday'; break;
case 4: return 'Thursday'; break;
case 5: return 'Friday'; break;
case 6: return 'Saturday'; break;
}
return 'DEFECT - not a valid day number';
};

google apps script: built-in spreadsheet functions fail in script - wrong syntax?

I am learning GAS and want to use spreadsheet functions within my script. As a test I did a simple case but on save it threw "reference Error: 'Left' is not defined." I've looked through examples of code and can't see an alternate syntax.
function testLeft(){
return LEFT("abcdef",3);
}
A second simple test, same result
function testNow(){
return Now()
}
Any suggestions? My wild guess is that there is a special syntax within scripts for using a built-in spreadsheet function. Or maybe not all functions available directly in spreadsheets are available for use in GAS?
Thanks.
Unfortunately spreadsheet functions are not available in Google Apps Script. In this case you can use JavaScript's substring() method to get the portion of the string you desire.
I am from a VBA background and I have found this site
http://excelramblings.blogspot.co.uk/2012/05/google-apps-script-equivalents-for.html
provided by Bruce Mcpherson very helpful lots of ready made functions for copying and pasting into your Google App Script especially if you are converting from an Excel spreadsheet to a Google spreadsheet.
Bruces Code for LEFT:
function Left(str,optLen) {
return Mid( str, 1 , optLen);
}
And to use the above LEFT function you will also need Bruces Mid function:
function Mid (str,optStart,optLen) {
var start = IsMissing (optStart) ? 0 : optStart - 1;
var length = IsMissing (optLen) ? Len(str) - start + 1 : optLen ;
DebugAssert( str.slice, str + ' is not a valid string for Mid function');
return str.slice ( start, start + length);
This is my attempt at simulating the mid Function
function fMid(varInStr, intPlace) {
//GAS does not have a Mid Function so I have made this one for now
//varInStr is the input string and you want a character returned from it at a given position
//intPlace is the position of the character you want
//Example
//=fMid("123456789", 9) returns "9"
var P
var N
P = intPlace -1
N = intPlace
return varInStr.substring(P,N)
};