Delete all empty spaces in specific column in Google Apps Script - google-apps-script

I am trying to delete all empty spaces in a specific column (currency column), because otherwise the imported values don't sum up correctly.
I tried this:
function cleaneuro() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('H2:H996').activate();
spreadsheet.getActiveRangeList().setNumberFormat('#,##0.00\\ [$€-1]');
spreadsheet.getActiveRangeList().replace(/\s/g, "") // here it should happen
spreadsheet.getRange('A2').activate();
};
But as so often, I seem to have a syntax error in the replace line...
any help?

You can't call replace() on a RangeList. You need to loop through the returned ranges instead and use a TextFinder.
function cleaneuro() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('H2:H996').activate();
spreadsheet.getActiveRangeList().setNumberFormat('#,##0.00\\ [$€-1]');
var ranges = spreadsheet.getActiveRangeList().getRanges();
for (var i = 0; i < ranges.length; i++) {
ranges[i].createTextFinder('\\s').useRegularExpression(true).replaceAllWith('');
}
spreadsheet.getRange('A2').activate();
};

The main reason you are not receiving the desired output is because the replace method you have used is typical for an object of type String and not of type RangeList.
Therefore, you can try getting the values from that range and you can also use this formula here in order to remove the empty spaces VALUE.split(' ').join('') instead for example
ranges[i].getValue().split(' ').join('')
Reference
Class Spreadsheet Apps Script - getActiveRangeList();
String.prototype.split().

Related

Google Sheets Apps Script, return random item from named range

I'm trying to create a custom function that I can give a name range as input and have it output a random item from the name range. I have multiple named ranges so it would be convenient to have one function that I could use for all of them. This is what I'm trying to replace =INDEX(named_range,RANDBETWEEN(1,COUNTA(named_range)),1)
This is what I've tried but it doesn't work:
function tfunction(n) {
var randomstuffs = SpreadsheetApp.getActiveSpreadsheet().getRangeByName(n);
var randomstuff = randomstuffs[Math.floor(Math.random()*randomstuffs.length)];
Logger.log(randomstuff);
}
Thanks in advance
You can try this edited script:
function tfunction(n) {
//randomstuffs will only get all cell data that are not empty from a named range
var randomstuffs = [].concat.apply([], SpreadsheetApp.getActiveSpreadsheet().getRangeByName(n).getValues()).filter(String);
var randomstuff = randomstuffs[Math.floor(Math.random()*randomstuffs.length)];
return randomstuff;
}
Sample Result
Created a sample named range TestRange on Column A with 21 cells of data then tried the custom function =tfunction("TestRange") which returned a random cell value.
.getRangeByName() method returns a reference to a range, not the values in the range. You need to add .getValues() to it:
var randomstuffs = SpreadsheetApp.getActiveSpreadsheet().getRangeByName(n).getValues();
Also keep in mind that .getValues() method returns a 2D array of values, indexed by row, then by column. So your var randomstuff declaration will need to be change to account for that, depending on how many rows and columns your range has.

How to use the getRange() method with an array value as one of the parameters

I don't have much experience using Javascript but I'm developing a simple code to filter some information relevant to a professor I'm helping. I am searching the row number of a certain amount of data using a for and then I'm using an array to store all the rows that contain those words. Since I'm using Appscript, I only need to relocate a certain amount of data from the row I'm returning to a final row I've already know. My code is as follows:
if(cell === "Average")
{
index++;
initialcoords[index] = n; // n is the iteration variable in the for
}
I've tested the contents of the array and they are just fine, so I'm storing correctly the rows. The problem is that I'm using a different method to paste the data in a different sheet in Google Spreadhsheets. My code to do so is the following:
function pasteInfo()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getSheetByName("Sheet 1");
var destination = ss.getSheetByName("Sheet 2");
var range = source.getRange(initialcoords[1], 1, 8, 3);
range.copyValuesToRange(destination, 4, 6, 4, 6);
}
My probelm is the getRange() since it prints an error like this:
can't find method getRange((class),number,number,number).
I believe that even if n is declared as an integer, the values that I'm returning are of a different type incompatible with the getRange() method. Could anyone help me to confirm this and to help me convert it to integer? I would really appreciate your help.
You first need to define the Sheet you want to get the data from since a Spreadsheet can have multiple Sheets.
You need to ensure you have appropriate default values defined before using the parameters, otherwise the interpreter will start making guess.
Provide defaults if parameters are empty:
function fillLine(row, column, length, bgcolor)
{
row = row || 0;
column = column || 0;
length = length || 1;
bgcolor = bgcolor || "red";
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(1+row, 1+column, 1, length).setBackground(bgcolor)
}
You may also try the solution offered by community: Can't get Google Scripts working

Google Sheet Custom Function Not Recaculating

Hi I have read about the caching issues with custom functions in Google Sheets, but I'm trying to understand why the following will successfully update if a cell is changed:
function doob(input){
return input * 2;
}
but this will not update:
function doob(input){
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var range = sheet.getRange(input);
var values = range.getValues();
return values[0][0] * 2 ;
}
I need to get the range in order to use the .getBackgroundColor() of each cell.
Probably because in the first function you would pass the cellreference directly,
=doob(A1)
and in the script the value of that cell is used.
In the second, you would probably have to pass the range as string (since you want to get the backgroundcolors, so you are not after the values of that range, right ?)
=doob("A1:B8")
As you know, custom functions suffer from memoization. To work around that you could pass in the range a second time, without the quotation marks.
=doob("A1:B8", A1:B8)
That second paramater is a 'dummy' paramater as the script does nothing with it. BUT: any change in values in that range should make the custom function re-evaluate. However I don't know if that is gonna help you a lot if your final goal is to get the backgroundcolors.

Google App script - setValues() doesn't work

So, I'm trying to write a script using the onEdit() event, which will basically remove links that are duplicates (technically, it removes everything, and only puts back things which aren't duplicates).
My code works fine all the way until it's time to write back non-duplicates. Namely, the line in which I use range.setValues(). I understand that it needs an array of arrays of cells which to edit, and that said array needs to fit in the range.
So far, I have :
if (unique)
{
newData.push(editedRow[0]);
Browser.msgBox(newData);
}
Unique is a variable I use that is false if an exact entry was found. With the msgBox command, I can verify that newData contains what it needs to contain. Further down, I have :
newDataFinal = [newData];
Browser.msgBox('Put values '+newDataFinal+' in range ' +range.getA1Notation());
range.setValues(newDataFinal);
To my knowledge, this should make NewDataFinal an array of arrays, which I can verify if I change setValues() to setValue(), which writes [[22.0, 13.0, 23.0]] (for my example) in the spreadsheet, which looks like an array of arrays to me.
The range should also match, since for this example, I get a prompt along the lines of "Put values 22,13,23 in range B2:B4" from the msgBox, which seems as a fitting range.
So, what am I doing wrong?
Here's the rest of the code (please excuse the abundancy of comments/msgboxes and lack of elegancy, the priority is to get it to work, I can probably optimize it and clean it up a bunch afterwards) :
function onEdit(e)
{
var range = e.range;
var values = range.getValues();
var sheet = SpreadsheetApp.getActiveSheet();
if (sheet.getName() != 'testiranje') return;
newData = new Array();
// Browser.msgBox(range.getA1Notation());
range.clear();
var data = sheet.getDataRange().getValues();
var counter = 0;
for (editedRowIndex in values)
{
unique = true;
editedRow = values[editedRowIndex];
// Browser.msgBox('Edited Row ' +editedRow);
for(i in data)
{
var row = data[i];
// Browser.msgBox('Old Row '+row);
for (j in row)
{
// Browser.msgBox(row[j] + ' vs ' + editedRow[0])
if (editedRow[0] == row[j])
{
Browser.msgBox('Hit! '+editedRow[0]);
unique = false;
}
}
}
if (unique)
{
// Browser.msgBox('Pushing '+editedRow[0]+' in newdata');
newData.push(editedRow[0]);
Browser.msgBox(newData);
}
}
newDataFinal = [newData];
Browser.msgBox('Put values '+newDataFinal+' in range ' +range.getA1Notation());
range.setValues(newDataFinal);
// range.setNote('SCIENCE');
}
I didn't test your code because I didn't feel like creating a sheet for it but what I can suggest (that should solve this issue in any case) is to replace your range.setValues(newDataFinal); with this :
sheet.getRange(range.getRowIndex(),range.getColumnIndex(),newDataFinal.length,newDataFinal[0].length).setValues(newDataFinal);
And if you want to know why the range and array didn't fit you can use this code :
(I used Browser because you seem to like it... I prefer Logger.log)
Browser.msgBox('data height = '+newDataFinal.length+', data width = '+newDataFinal[0].length+' and range height is '+range.getHeight()+', range width is '+range.getWidth()+' ... does it fit ?');
Note : I'm almost sure that your initial range is bigger than the newData array since you remove elements from the initial data... My best guess would be that heights don't fit. (but that's only a guess ;-) since you didn't mention the error message you get...)
the problem is that you cant change cells from an onEdit handler. see the docs. instead install your own onEditCustom handler.

How do I hide rows in a Google spreadsheet using a script based on a character in a column?

I'm using the below script to hide all rows with a value of "1" in column B.
function myfunction () {
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("CSSMaster");
var maxRows = sheet.getMaxRows();
//show all the rows
sheet.showRows(1, maxRows);
//get data from clumn B
var data = sheet.getRange('B:B').getValues();
//iterate over all rows
for(var i=0; i< data.length; i++){
//compare first character, if 1, then hide row
if(data[i][0].charAt(0) == '1'){
sheet.hideRows(i+1);
}
}
}
}
I go to my spreadsheet and enter the following: =myfunction(B:B) , I see "thinking" but nothing happens. What am I doing wrong? (I'm VERY new to Google scripts and am guessing this is a very basic error.)
Your instincts are right - it's a very basic error. First, make sure that you're actually running the code you intend to.
In this example, you've got a function inside a function. When you invoke myFunction() from the spreadsheet, execution will begin but won't find any code to run. Because onOpen() is enclosed in myFunction(), but there is no call in myFunction() to onOpen(), there's nothing to do.
Sort that out - you probably just need to get rid of the declaration and closing brace for onOpen().
Next, you're passing a 2-dimensional array of values when you invoke myFunction(B:B), but you have no parameter handing in the function. (You retrieve the values explicitly with getRange('B:B').getValues().)
General advice: learn some JavaScript (I recommend CodeAcademy), and try your hand at some of the Google Apps Script tutorials. With the competence and confidence from those, you should have no problem getting this working on your own.