Using a google sheets apps script, Is it possible to get the X cell in a range of cells as shown below:
var app = SpreadsheetApp;
var ss = app.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cells = sheet.getRange("D6:BF100"); // the range
for (var x = 0; x < 100; i++) {
var cell = cells[row][x]; // this is the line that doesn't work
if (someCondition(x)) {
cell.setBackground("red");
}
}
I don't want to change the colors for every single cell, just the ones that have the correct condition.
I know it is possible to do something like this:
var cell = sheet.getRange(row+i);
But this method takes a very long time to complete the for loop as there are hundreds of cells that need to be scanned. I would rather only use getRange once with the entire range (instead of just one cell at a time) and then from that range (it should make a 2d array right?) set the cell values. I think that would be a lot faster.
Is there a different way to do it faster, or do I just need to do this: var cell = cells[row][x]; a different way.
Thanks!
It looks like your for loop is constructed incorrectly. You increment the variable i that isn't defined or used anywhere. Also, you use the variable row without defining it.
It takes forever because it has to query your sheet each time you call cells.getRange() Instead, you can query once using cells.getValues() to get the whole range, and then change the cells color that meet the condition one at a time.
Try the following;
var app = SpreadsheetApp;
var ss = app.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cells_range = sheet.getRange("D6:BF100");
var cells_values = cells_range.getValues();
for (var col = 1; col <= cells_values[0].length; col++) {
for (var row = 1; row <= cells_values.length; row++) {
if (someCondition(cells_values[row][col])) {
cells_range.getCell(row, col).setBackground("red");
}
}
}
This is just my own answer to help users who might get to this question.
Once you have a range of cells, like this:
var range = sheet.getRange("your range");
You can do this to get a specific cell:
var cell = range.getCell(row, col);
Related
function dataManp() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("My-Sheet-1");
var pasteSheet = ss.getSheetByName("My-Sheet-2");
var clearContentRange = pasteSheet.getRange("A1:Z100");
clearContentRange.clearContent();
var source = copySheet.getRange("a1:f100");
var destination = pasteSheet.getRange("a1:f100");
source.copyTo(destination, {formatOnly:true , contentsOnly:true});
source.copyTo(destination,SpreadsheetApp.CopyPasteType.PASTE_COLUMN_WIDTHS,false);
var rows = pasteSheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var rowsDeleted = 0;
for (var i = 0; i <= numRows - 1; i++) {
var row = values[i];
if (row[3] == '') {
var deleteRowNum = (parseInt(i)+1) - rowsDeleted
pasteSheet.deleteRow(deleteRowNum);
// temp_array[i] = i
rowsDeleted++;
}
}
pasteSheet.deleteColumn(2)
}
Hi,
I have written the following script to perform the following operations,
Copy data from My-Sheet-1 and paste to My-Sheet-2
Deletion of rows that corresponds to empty cells in column 3.
After that deletion of column 2
Rigthnow, the My-Sheet-1 contains only 60 rows and 20, the script is taking approximately 7 secs to complete. However in future the number of rows may extend to some 1000. Is there a way to optimize the above code, so that it takes less time to complete.
My observation is that, copy and pasting the data takes just milli secs. The major time consuming part are the operations, I am performing in the pasteSheet after pasting it. It may be helpful, if we can copy My-Sheet-1 to a temporary variable (copy everything including the formulas, format specifications, values, text etc..) and perform all operations in the temporary variable and then paste everything in the temporary variable to the desired target sheet. But, I don't know, how to copy everything in a sheet to a temporary variable, also, I am not sure, whether this will reduce the time or not. I would be glad, if I can get some help on this as well (i.e. copying everything in a sheet to a temporary variable, perfrom operations on the variables and then paste data in the variable to a new sheet)
Thank you
Edit - 1
Would like to add that, My-Sheet-1 contains mixed data (i.e. numerics, color formatted text, formulas in some cells etc)
Explanation:
deleteRow() takes some time per execution, so it's not recommended to use on hundreds of rows in a loop.
Simple answer would be:
Make a 2D array for Sheet1 using getValues().
Delete / filter out array elements depending if row2 is blank.
Use setValues() to write the filtered array into Sheet2.
Sample Code:
function dataManp() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("My-Sheet-1");
var pasteSheet = ss.getSheetByName("My-Sheet-2");
var lr = copySheet.getLastRow();
var clearContentRange = pasteSheet.getRange(1,1,lr,26);
clearContentRange.clearContent();
var source = copySheet.getRange(1,1,lr,6);
var destination = pasteSheet.getRange(1,1,lr,6);
source.copyTo(destination, {formatOnly:true , contentsOnly:true});
source.copyTo(destination,SpreadsheetApp.CopyPasteType.PASTE_COLUMN_WIDTHS,false);
destination.clearContent();
var values = source.getValues();
var temp_array = [];
for (var i = 0; i < lr; i++) {
var rowValue = values[i];
if (rowValue[2] != '') {
temp_array.push(rowValue);
}
}
var newDest = pasteSheet.getRange(1,1,temp_array.length,6)
newDest.setValues(temp_array);
pasteSheet.deleteColumn(2);
}
One caveat is that you need to have the same format for all rows in a column.
Sample Input:
Sample Output:
The challenge has been getting cell values from the document header together with a range underneath this header to Sheet2, having it as a table, so that later, I can filter, update and delete records via scripts.
So far, I got the below code copying what's within the range underneath the header:
function copyrange() {
var sourceSheet = 'NewItem';
var destinationSheet = 'DW';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sourceSheet);
var LastRowSource = sheet.getLastRow();
var LastColumnSource = sheet.getLastColumn();
var values = sheet.getRange(11,1,LastRowSource,LastColumnSource).getValues();
var csh = ss.getSheetByName(destinationSheet);
var data = [];
var j =[];
//var itemheader = [sheet.getRange("C4:4").getValues(),sheet.getRange("A3:3").getValues(),sheet.getRange("i3:3").getValues(),sheet.getRange("i4:4").getValues(),sheet.getRange("c5:5").getValues(),sheet.getRange("e5:e").getValues(),sheet.getRange("i5:5").getValues(),
// sheet.getRange("C7:7").getValues(),sheet.getRange("c8:8").getValues(),sheet.getRange("c9:9").getValues(),sheet.getRange("e7:7").getValues(),sheet.getRange("e8:8").getValues(),sheet.getRange("i7:7").getValues(),sheet.getRange("i8:8").getValues(),
// sheet.getRange("e9:9").getValues()];
for (var i = 1; i < values.length; i++) {
if ( values[i][0] != '') {
data.push(values[i]);
//sheet.deleteRow(i+1)
}
}
//Copy data array to destination sheet
csh.getRange(csh.getLastRow()+1,17,data.length,data[0].length).setValues(data);
Now, getting different cell values from the header into a row and copying it to Sheet2 as many times/rows as there is in the range copied by the above script seems impossible to me.
Here is a link to a practical example:
https://docs.google.com/spreadsheets/d/1GlD_VIOFHj7PGfCCnfVZqdZbE22aVoUw91BSCZecsRc/edit?usp=sharing
Thanks a lot for your help. Believe me, I've hit my head against the wall enough with this one before I turn to you guys!
Using JavaScript, I want to update a range of cells in Google Sheets.
The code doesn't throw any error, but doesn't work either.
function OnEditDate(e){
var app = SpreadsheetApp;
var ss = app.getActiveSpreadsheet();
var act = ss.getActiveSheet();
var i;
var j;
for(i = 2; i = 30; i++){
for(j = 5; j = 20; j++){
var newVal = act.getRange(i+1,j).getValue();
act.getRange(i,j).setValue(newVal);
}
}
}
This should update all cell in range E2:U30 by moving the contents of all cells to the left one cell.
Let's start off with a few observations...
Your for loops are not specified correctly.
The for loop syntax is for ([initialization]; [condition]; [final-expression]).
Your condition statements are i = 30 and j = 20, which are assignment statements. So in addition to clobbering your intended logic, they also always evaluate to true. You should instead be using a comparison operator, something like i >= 30 and j >= 30.
Furthermore, you shouldn't call API methods such as getRange(), getValue(), setValue() within for loops. These operations are slow and will cause the script to take a long time to complete.
You should use batch operations to get/set the entire range of cells you'd like to update in as few API calls as possible.
In your case, since you're not processing the data, you have no need to actually loop through the data.
Here's an implementation that performs the move you described:
function moveCells() {
var sheet = SpreadsheetApp.getActiveSheet();
var startingColumn = 5; // Column E
var startingRow = 2; // Row 2
var numColumns = 17; // to Column U
var numRows = 29; // to Row 30
// Get the source range which contains the data.
var sourceRange = sheet.getRange(startingRow, startingColumn, numRows, numColumns);
// Get the target range (i.e. same size as sourceRange, but starting one column
// to the left).
var targetRange = sheet.getRange(startingRow, startingColumn - 1, numRows, numColumns);
// Get all of the values from sourceRange into a 2-dimensional array.
var values = sourceRange.getValues();
// Clear all of the cells in sourceRange.
sourceRange.clearContent();
// Set the cell values targetRange, using the values extracted from sourceRange.
targetRange.setValues(values);
}
Note that I'm using the 4 argument version of getRange(), which allows you to work with a grid of cells.
Similarly, I'm using getValues() and setValues(), which allows you to get and set the entire grid of cells in one operation.
I have two sheets, one is a mirror sheet, "Sheet2," that I use to store the values of the other sheet, "Sheet1." My goal is to have a function compare the two sheets for differences. The best way i could think of was by comparing column A from Sheet1 to column A from Sheet2. I found a few functions that compared 2 columns but it did it looking for values from one column and finding it in the other column. Or by returning all the values in those cells that had a matching value, regardless of what row it was in. But I don't want the values in the cells, necessarily. I want to find the first row where the two columns stop matching. I'm fairly new to Javascript so I still can't comprehend the whole for (var j = 0; j < range.length; j++) stuff.
But I'm sure I will need to know how to use it for this function I need. Here's what I tried using but instead of giving me row ranges, it gave me an array of values that were the same, if I changed it to if(lookup[i][0]!==range[j][0]){ it gave me all the possible combinations that weren't matching. This is from stackoverflow.com/questions/42044903
function findDifference() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s=ss.getSheetByName("Sheet1")
var lr=s.getLastRow()
var lookup = s.getRange(2,1,lr-1,2).getValues();
var s1=ss.getSheetByName("Sheet2")
var lr1=s1.getLastRow()
var range = s1.getRange(2,1,lr1-1,2).getValues();
var lookupRange = [];
for (var i = 0; i < lookup.length; i++) {
for (var j = 0; j < range.length; j++) {
var test=lookup[i][0]
if(lookup[i][0]!==range[j][0]){
lookupRange.push([range[j][0],range[j][1],lookup[i][0],lookup[i][1],]);
}}}
s1.getRange(10,1,lookupRange.length,4).setValues(lookupRange);
}
I feel like there's a very similar function for what I'm trying to do that already exists, but I can't seem to find it or come up with how it would work because I'm new and don't know all the tricks.
Something like:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s1=ss.getSheetByName("Sheet1")
var s2=ss.getSheetByName("Sheet2")
var ColumnA1 = s1.getRange('A:A').getValues()
var ColumnA2 = s2.getRange('A:A').getValues()
var Row = Function()
///Some function I can't think of using where
if(ColumnA1 + Row !== ColumnA2 + Row){
???.getRow()
}
The code that you had was "kinda' helpful but it did not solve your particular question. On the other hand, your if(ColumnA1 + Row !== ColumnA2 + Row){ wasn't really helpful either.
Regrettably you DO need to "comprehend the whole for (var j = 0; j < range.length; j++) stuff", though it isn't actually that complicated.
In the following answer, there are basically three elements.
setup sheet1, and get the data
setup sheet2, and get the data
loop through the rows and compare the value on a given line from one sheet to the other.
the for statement signifies the loop
i is simply a counter variable
i=0 means that the starting value is zero. In javascript arrays, zero always the first value set.
i < Sheet1Data.length signifies how many time the loop will run. In this case, it will run while i is less then the number of lines in the array. Remember, i starts with zero, so "less than" the totoal number of lines will be fine.
i++ means that each time the code loops, it increments i by one.. So, i starts with 0, then 1, 2, 3 and so on.
How to find the first row where the two columns stop matching
View the Logs (View > Logs).
You can see on line 32 and 38 of the code Logger.log statements. These record the line number and whether the line values in each sheet match.
function so56195933() {
// setup Spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
// setup Sheet1
var s1 = ss.getSheetByName("Sheet1")
var s1LastRow = s1.getLastRow();
//Logger.log("DEBUG: Sheet 1 Last row = "+s1LastRow);
var Sheet1DataRange = s1.getRange(1,1,s1LastRow);
var Sheet1Data = Sheet1DataRange.getValues();
//Logger.log("DEBUG: Sheet 1 data range = "+Sheet1DataRange.getA1Notation());
var Sheet1length = Sheet1Data.length;
//Logger.log("DEBUG: Sheet1 length = "+Sheet1length);
// setup Sheet2
var s2=ss.getSheetByName("Sheet2")
var s2LastRow=s2.getLastRow();
//Logger.log("DEBUG: Sheet 2 Last row = "+s2LastRow);
var Sheet2DataRange = s2.getRange(1,1,s2LastRow);
var Sheet2Data = Sheet2DataRange.getValues();
//Logger.log("DEBUG: Sheet 2 data range = "+Sheet2DataRange.getA1Notation());
var Sheet2length = Sheet2Data.length;
//Logger.log("DEBUG: Sheet2 length = "+Sheet2length);
// Loop through rows compare value per each sheet
for (var i = 0; i < Sheet1Data.length; i++) {
var s1data = Sheet1Data[i][0];
var s2data = Sheet2Data[i][0];
//Logger.log("DEBUG: Line: "+i+", s1data: "+s1data+" Vs s2data: "+s2data);
if (s1data !=s2data){
// sheets values don't balance
Logger.log("Line: "+i+". Sheets are NOT equal. Sheet1 = "+s1data+", Sheet2 = "+s2data);
return false;
}
else
{
// sheets values balance
Logger.log("Line: "+i+". Sheets are equal, value: "+s1data);
}
}
}
This is my test data
As the title describes I'm trying to update a stock price with a script. I understand that this is likely trivial for most of you, but it's my first time scripting with google sheets.
From what I can see this code should be okay and the code within the loop does work on it's own.
It makes a list for for every time the list has a value it will process the command. Currently the command will only repeat on the same row as I've not figured how to increment the row properly yet.
I want to read from column A and as long as there is a value to increment which A row is read to get the stock symbol, pull the value, and paste it in an incremented E row.
function getData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var symbol = ss.getRange("A2:A").getValues();
for (var row = 2, var count = symbol.length; row < count; row++) {
if (symbol[row] !=''){
ss.getRange('E2').setValue('=GOOGLEFINANCE(A2)');
}
}
}
I think this will get you what you want. The issue with your script was that the E2 was hardcoded in, as was the A2 so it didn't iterate through as needed.
function getData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var symbol = sheet.getRange("A2:A").getValues();
for(i=0; i<symbol.length; i++)
{
if (symbol[i]!=""){
ss.getRange('E'+(i+2)).setValue('=GOOGLEFINANCE(A'+(i+2)+')');
}
}
}