Can anyone help me writing a function in a range of cells, like:
In the 1st cell of the range: myFunction(A+rowNumber)
Where rowNumber is the number of the respective row, so, for example in cell B2, it should write myFunction(A2), and so on.
var range = ss.getSheetByName('Sheet1').getRange('myRange').getValues();
for (var i = 0; i < range.length; i++) {
// I need to write a function like: '=myFunction('A+rowNumber')'
};
Related
I have a spread sheet with numbers spread around several columns and rows.
I would like to be able to select several cells in the spreadsheet and increment the value for every cell by 1.
I already created a button that calls a function in scripts. I am also able to get my ranges like this:
var sel = SpreadsheetApp.getActive().getSelection().getActiveRangeList().getRanges();
I am able to loop through my ranges, but I cannot get the value of each individual cell and increase it's value. How can this be done?
Inside the loop that goes through the ranges, you can simply get the current value in the cell and set the value again + 1. This is the most basic way to do it but may not be the optimal way.
for(var i in sel){
var range = sel[i].getValue();
sel[i].setValue(range + 1);
}
getRanges() is a function that returns a list of ranges. In order to increment all the values, you have to:
Iterate over the ranges
Iterate over every cell in the range, using either getCell() or getValues() (which is faster).
You can see a code example on how to do it using getValues():
var sel = SpreadsheetApp.getActive().getSelection().getActiveRangeList().getRanges();
for (var i=0; i<sel.length; i++) {
var range = sel[i];
var values = range.getValues();
for (var j=0; j<values.length; j++) {
for (var k=0; k<values[0].length; k++) {
values[j][k] += 1;
}
}
range.setValues(values);
}
I have a sheet that contains hundreds of rows.
The first column includes Reference Number which is unique to each row.
I want to find the row whose Reference Number is a specific number, for example 301, and insert a timestamp (date and time) into the cell of that row which is under column M.
I have the following code, which isn't complete yet and won't work.
var spreadsheet = SpreadsheetApp.getActive();
var RefNumber = 301 //for example
var searchRange = spreadsheet.getSheetByName('Classes').getRange("A:A");
// get the values in an array
var values = searchRange.getValues();
// examine the values in the array
var i = [];
for (var y = 0; y < values.length; y++) {
if(values[y] == RefNumber){
i.push(y);
}
}
// I have no idea how to continue the code! Please include your suggestions here.
You want to search a number from column A, and put the timestamp to the column M with the same row which found the searched number. If my understanding is correct, how about this modification?
Modification points :
Values retrieved by getValues() is 2 dimensional array.
By using getLastRow(), the cost can be lower than that of "A:A".
When RefNumber is found from values, it puts a1Notation to i. By this, the timestamp can be put using getRangeList().
Modified script :
var spreadsheet = SpreadsheetApp.getActive();
var RefNumber = 301 //for example
var sheet = spreadsheet.getSheetByName('Classes'); // Modified
var searchRange = sheet.getRange("A1:A" + sheet.getLastRow()); // Modified
// get the values in an array
var values = searchRange.getValues();
// examine the values in the array
var i = [];
for (var y = 0; y < values.length; y++) {
if(values[y][0] == RefNumber){
i.push("M" + (y + 1)); // Modified
}
}
// I have no idea how to continue the code! Please include your suggestions here.
sheet.getRangeList(i).setValue(new Date()); // Added
References :
getValues()
getLastRow()
getRangeList(a1Notations)
If I misunderstand your question, I'm sorry. At that time, can you provide the sample input and output you want? I would like to modify the script.
Is it possible to make a script returning an array of values that will overwrite non-empty cells?
For example: I have a list of tasks with the following fields: 'task-name, estimated time as in '3w'. The 3rd column is calculated with a custom function that translate the '3w' to 3*5=15 (in days). The custom script takes a range and returns an array of results for the given array of estimated-times from the 2nd column.
All works well until I decide to take a row and move it to re-order the list of tasks. Once I move that row, lets say, one row above, the script complains about an error because the moved row contains a non-empty value where it used be automatically computed by the custom-script. To correct it I need to clear the value of that row at the 3rd column and the script returns to calculate as before.
There should be a way to tell the script to overwrite. Is there?
Thanks,
Erez
Use the isBlank() function to check whether the specified cell in empty and the clear() function in order to clear the value in the cell and provide a new one. Here is a small sample:
function myFunction(){
var ss = SpreadsheetApp.getActiveSheet();
var range = ss.getDataRange();
var maxCol = range.getLastColumn();
var maxRow = range.getLastRow();
for (var i=0; i<maxRow; i++)
{
for (var j=0; j<maxCol; j++)
{
if(!ss.getRange(i+1, j+1).isBlank())
{
ss.getRange(i+1, j+1).clear();
}
}
}
}
i have a spreadsheet that i keep track of tasks i need to do, once complete i enter a date in the last column. What i want is for that completed task to be moved to sheet 2.
At present i have sheet 1 named SUD_schedule and i want the completed row of data to be moved to sheet 2 named SUD_archive. I've looked through the forum posts already and i've tried a variation of scripts but so far no luck. The closest i have come is this script:
function onEdit() {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();//Original sheet
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];//target sheet
// to act on only one sheet, check the sheet name here:
//If it si not first sheet, it will do nothing
if (sheet1.getSheetName() != "SUD_schedule") {
return;
}
//Get Row and column index of active cell.
var rowIndex = sheet1.getActiveRange().getRowIndex();
var colIndex = sheet1.getActiveRange().getColumnIndex();
//If the selected column is 10th and it is not a header row
if (colIndex == 16 && rowIndex > 1) {
//Get the data from the current row
var data = sheet1.getRange(rowIndex,1,1,9).getValues();
var lastRow2;
(sheet2.getLastRow()==0)?lastRow2=1:lastRow2=sheet2.getLastRow()+1;
//Copy the data to the lastRow+1th row in target sheet
sheet2.getRange(lastRow2,1,1,data[0].length).setValues(data);
}
}
Column P (16) is the task complete date, row 1 is frozen and contains column headers.
Can anybody help show where i'm going wrong.
Kind regards
Den
Your code is not generic and you are more complicating your objective. Below will work out your need.
function onEdit(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('SUD_schedule');
var sheet2 = ss.getSheetByName('SUD_archive');
var dateColumn = "16";
var array = []
var range = sheet1.getRange(1, 1, sheet1.getLastRow(), dateColumn);
for (var i = 2; i <= sheet1.getLastRow(); i++) //i iterates from 2 as you say R1 is header
{
if(isValidDate(range.getCell(i, dateColumn).getValue()) == true) //checking if any values on column16 is valid date
{
data = sheet1.getRange(i, 1, 1, dateColumn).getValues(); //Getting the range values of particular row where C16 is date
for (var j = 0; j < dateColumn; j++) //Adding the row in array
{
array.push(data[0][j]);
}
}
if(array.length > 0)
{
sheet2.appendRow(array); //Appending the row in sheet2
array = [];
sheet1.deleteRow(i); //deleting the row in sheet as you said you want to move, if you copy remove this and next line
i=i-1; //managing i value after deleting a row.
}
}
}
//Below function return true if the given String is date, else false
function isValidDate(d) {
if ( Object.prototype.toString.call(d) !== "[object Date]" )
return false;
return !isNaN(d.getTime());
}
I am not sure that the syntax you have as used below is entirely correct.
(sheet2.getLastRow()==0)?lastRow2=1:lastRow2=sheet2.getLastRow()+1;
sheet2.getRange(lastRow2,1,1,data[0].length).setValues(data);
What I know will work for certain is if you omit the variable lastRow2 all together and use this instead.
sheet2.getRange(getLastRow+1,1,1,data[0].length).setValues(data);
To complement Joachin's answer, here is how you can adapt that code if you don't have the date in the last row. In the below shown part of the code replace Lastcolumnumber with your last column.
//Getting the range values of particular row where C16 is date
data = sheet1.getRange(i, 1, 1, LASTCOLUMNNUMBER).getValues();
//Adding the row in array
for (var j = 0; j < LASTCOLUMNNUMBER; j++)
I have data in multiple columns from rows 3-15. I want to find all the unique values in that data set and have it outputted in one column.
The unique function only does one column at a time so it does not work for my purposes.
I am writing a script that will open a new sheet and copy and paste the values into the same column (combines data from multiple columns into one longer column). I will then run the unique function on the single column containing all the data to get an output of all the unique values in my original dataset (Items!B3:Z15)
I have the code written but cannot figure out how to increment a character. If there is a better way to achieve this I am open to suggestions, but I am also curious if it is possible to increment letters.
Thanks for the help, here is my current code:
function uniqueIngredients() {
var book = SpreadsheetApp.getActiveSpreadsheet();
var r=1; // starting with row 1 new sheet
var d='B';
for (i=1; i<4; i++){ //testing by running 3 iterations
var m = 'Ingredients!A'+r; //Intially return Ingredients!A1 then incremented by 11 ex A12
var c = 'Items!'+d+'4:'+d+'15'; // Initially return Items!B3:B15 then incremented by letter ex Items!C3:C15
r = r+12; // add 12 spaces before next copy (max number of ingredients for each item)
d++;
book.getRange(c).copyTo(book.getRange(m), {contentsOnly:true});
}
};
You can use an alternative parameter specification for the getRange() method, which uses column numbers rather than A1 string notation. This would be easier to increment.
That being said, as you are copying values only, it would probably be better (more efficient) to get the source range in a block, and use Javascript to convert into a one-column array, and then set the values:
function uniqueIngredients() {
var ss = SpreadsheetApp.getActive();
var sourceValues = ss.getSheetByName('Items').getRange('A3:D15').getValues();
var target = ss.getSheetByName('Ingredients');
var result = [];
for (var i = 0; i < sourceValues[0].length; i++) {
for (var j = 0; j < sourceValues.length; j++) {
result.push([sourceValues[j][i]]);
}
}
target.getRange(1, 1, result.length, 1).setValues(result);
}
And that being said, you could use a bit of a workaround to provide the end result using spreadsheet functions only:
=ArrayFormula(UNIQUE(TRANSPOSE(SPLIT(CONCATENATE('Items'!A3:D15&CHAR(9));CHAR(9)))))