Google Script setValue results in [[value]] - google-apps-script

I am trying to come up with a script that will simply capture the value of a cell and paste that value in another cell. The cell value it is capturing is a simple, unformatted cell containing the number 32. My code below works but the result is not 32 in the target cell. Instead, the result is [[32.0]]. Can someone help me understand what it is adding the brackets and the .0?
function test(row) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();// Define active sheet
var amountdue = sheet.getRange("A30").getValues();// Capture amount due
sheet.getRange("B30").setValue(amountdue);// Paste amount due
}

The function that you are using "getValues()" is intended to capture more than one cell. As this function is designed to capture a table it give in output a result that is not the value of one cell but the value of several cells. to display them we need to store them in something that it's easily accessible and structured : an array.
The array is represented as: [cell1Value, cell2Value, cell3Value, ...] .
As there may have more than one row we store each row in an other array: [row1, row2, row3, ...]. so in the end it's something like that:
[ [row1Cell1, row1Cell2, ...], [row2Cell1, row2Cell2, ...] ]
You don't want these brackets, change "getValues()" for "getValue()" without "s".
Or when you set the value use:
amoutdue[0][0]
the first [0] is to say I want the first row (we start at 0) and the second [0]... you already guessed is for the first cell.
I suppose that you are getting the ".0" after "32" because as you are trying to set the array of array in a cell. Javascript don't know how to handle that and try to transform the array of array in full text.

Related

I need to clean up and split words from a mess of data into their own cells in a row. How can I accomplish this?

I am attempting to create documentation from an export of data that gives me a jumbled mess all in one cell that I need to clean up and extract certain bits from.
Here is an example:
[{"label":"Native Invoice","value":"native_invoice","displayOrder":0,"hidden":false,"readOnly":false},{"label":"Data Sync","value":"data_sync","displayOrder":1,"hidden":false,"readOnly":false}]
All of this is in one cell, and I need to have only the following information in their own individual rows:
Native Invoice
Data Sync
This example only has 2 values, but some that I am working on have hundreds, and it is taking far too long to manually copy and paste the values I need into their own cells.
Note: I am working in Google Sheets exclusively.
If I'm understanding you correctly, you want to pull anything after "label": without quotes. If that's the case, and if you are open to a formula instead of a script, supposing that your raw-data block were in A1, place this in B1:
=ArrayFormula(IFERROR(QUERY(FLATTEN(REGEXREPLACE(IF(NOT(REGEXMATCH(SPLIT(REGEXREPLACE(A1,"label.:.([^"&CHAR(34)&"]+)","~|$1~"),"~"),"\|")),,SPLIT(REGEXREPLACE(A1,"label.:.([^"&CHAR(34)&"]+)","~|$1~"),"~")),"\|","")),"WHERE Col1 Is Not Null")))
Here is how a custom function can look like:
function parse(txt) {
var jsn = JSON.parse(txt);
return [jsn[0].label, jsn[1].label];
}
Here is how it works:
You put the data into cell A1, put the formula =parse(A1) into the cell B1, and get the results in cells B1 and B2.
Update
If you want to get labels from all objects of the data, here is another variant of the function:
function get_labels(txt) {
return JSON.parse(txt).map(x => x.label); // get 'label' from all the objects
}
It works about the same way:

Format a Google Sheets cell in numerical formatting 000 via Apps Script

I'm looking to set a column to format 000, which will display the zeros at begenning.
So, if a cell displays "3", I want that the script will set it to display "003".
This column is located in BDD tab, 13th column starting from the second row.
function FormattingGpeTrait() {
const sheet = SpreadsheetApp.getActiveSheet().getSheetByName("BDD").getRange(2,13)
sheet.setNumberFormat('000')
Modification points:
The method of "getSheetByName" is for Class Spreadsheet. In your showing script, you try to use it to Class Sheet. By this, an error occurs. This has already been mentioned in the comment. Ref
From 13th column starting from the second row., I thought that you might have wanted to set the number format of 000 to "M2:M". In your showing script, the number format is set to only a cell "M2".
If you want to set the number format to the cells "M2:M" of the sheet name of "BDD", how about the following modification?
Modified script:
function FormattingGpeTrait() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("BDD");
sheet.getRange("M2:M" + sheet.getLastRow()).setNumberFormat('000');
}
When you run this script, the number format of "000" is set to the cells "M2:M" of "BDD" sheet.
If you want to set the number format to the "M2:M", please modify getRange("M2:M" + sheet.getLastRow()) to getRange("M2:M").
References:
getActiveSpreadsheet()
getSheetByName(name)
The easiest way to get a range on a named sheet is to include the sheet name in the range reference, like this:
function formattingGpeTrait() {
SpreadsheetApp.getActive().getRange('BDD!M3:M').setNumberFormat('000');
}
I think that you can't use the standard number formats as they all will only evaluate your value to a real number value where '003' in reality is equal to '3' from a numeric sense.
You have two real options which is to either store the value in a Text column as "003" or prepend the value with an apostrophe "'003" which is basically the same as storing it as Text but the column can remain numeric.
You can create a custom number format for a cell/column to also do this but I am not certain how to accomplish this programatically. Basically, this is still going to end up like the Text variations I mention above, only you have a named format you can call. The data will still be stored as Text.

Ability to Edit Google Sheets' Custom Function Result

I'm wondering if it is possible to edit the result of a custom function in Google Sheets when returning a 2-dimensional array.
If I try to delete a cell that is part of the returned array, it blinks but stays there.
If I enter something in a cell that is part of the returned 2-dimensional array, it works, but the function then does not return because the value is blocking the display of the 2-dimensional array (Array result was not expanded because it would overwrite data in A3.)
It's the same as for built-in functions returning an array (split, importrange, query, etc): output cannot be edited. But there is a workaround described below.
Suppose the output range is A1:B6. Elsewhere in a sheet, enter =A1 and copy this formula to a 2 by 6 range. This creates a range that is visually identical to the function output, but editable cell-by-cell. If you edit a cell in this new range, it will cease to depend on the function, but the rest will still be updated if the function input changes.

Changing data in a Google spreadsheet

I am changing a few cells of data in a Google spreadsheet. I would like to write back the data into the spreadsheet. The problem i have is that the sheet has say 5 columns, when i add new data into one of the cells i would like to backup the old data in the next free cell in that row. When i do this i am not able to write back the data. This is my code.
var sheet = SpreadsheetApp.openByUrl("URL");
var d = sheet.getSheetByName('Form Responses').getDataRange().getValues();
var head = sheet.getSheetByName('Form Responses').getRange(1,1,1,sheet.getLastColumn()).getValues()[0];
d[29][2] = "A";
d[29][3] = "B";
d[29][4] = "C";
d[29][5] = "D";
sheet.getSheetByName('Form Responses').getRange(1,1,d.length,d[0].length).setValues(d);
This is the error i get. Incorrect range width, was 6 but should be 5
I have also tried modifying the the write back statement as
sheet.getSheetByName('Form Responses').getRange(29,1,1,d[29].length).setValues(d[29]);
In this case i get Cannot convert Array to Object[][].
What is the correct way to write back the data. Preferably i would like to write back data of that particular row only, instead of the whole sheet data.
The issue here is that you modify only one "row" in the array so that in the end it is not "symetric" anymore (ie every rows don't have the same length) and that causes the error you get.
possible solutions :
There are probably more than one good way to avoid that error, you could create a second array with new data (same height) and join the arrays before writing back to the sheet or, as in the example below, add a cell (or many cells) to every row in the array in a loop before assigning them a new value. Depending on the size of the array one could be better and/or easier than the other to implement... here is a simplified example that should work :
for(var n=0;n<d.length;n++){
d[n].push('');
Logger.log('row '+n+' = '+d[n]+'\n');// see the result
}
EDIT following comment :
OR you can write a single row if you change only one, just change the code to
sheet.getSheetByName('Form Responses').getRange(29,1,1,d[29].length).setValues([d[29]])
which is not far from what you tried but you were simply missing the pair of brackets to get a 2D array as required by setValues()

Is it possible to define a new function in Google-docs spreadsheet?

Is it possible to define a function in Google Spreadsheets that can be used in any cell?
It would be helpful if I could define and use functions that refer to other cells in the same way that I can use native functions, e.g. by entering =myfunction(C1, C2, C3)
Yes - there's a tutorial. Just use javascript functions by name in your spreadsheet. Define them using Tools > Script editor.
Watch out for name restrictions; I was confused by the behavior of functions that I created with names like "function x10() {}" not being found. Renaming to a longer name fixed it. There are probably documented rules for what isn't allowed, but I don't know where they are.
I am a "newbee". But is is my experience that you can only access a "cell"
via the "range" object. You must define the range as a single cell.
For example "A1:A1", will give you access the the cell at "A1".
A RANGE is an object associated to a "SHEET".
A SHEET is an object associated to a "SPREADSHEET".
Here is some sample code to access cell A1 in the current active sheet:
var cell_A1 = SpreadsheetApp.getActiveSheet().getRange("A1:A1");
From here you can pass the object like any other parameter.
myFunction(cell_A1);
The receiving function must "know" that it is dealing with a "range".
It can only access its values by calling "methods" associated to the
"range" object.
Be careful! A "range" can consist of more than one cell. Your called
function should test to see that it is working with a single cell.
If you pass a range of more than one cell, your function might not
act in the way you expect.
The two methods of a range object: "getNumRows()" and "getNumColumns()"
returns the numbers of Rows and Columns in a range object.
In general, if you use methods that are limited to changing or accessing
a single cell, and operate on a larger range set, the function will only be
performed on the upper-left cell member. But be careful. While you
might assume a method will only change a single cell, it may actually
affect all cells in the range. Read the documentation closely.
There is another method to obtain a range of a single cell. Its instruction
looks like this:
var cell_B2 = SpreadsheetApp.getActiveSheet().getRange(2, 2, 1, 1).
The first two parameters tell the "getRange" function the location of the
cell (in row, column format). The second two parameters define the number of
"rows" and "columns" to associated with the range. By setting them both to
"1", you access a single cell.
Hope this helps.