I'm trying to add x blank rows after every no blank cells in a range.
I use a loop but with my loop, only the first cell is affected.
Here, my code :
I think I know where I'm wrong (I need to loop in sheet.insertRowsAfter(i, 5); but I can not do it...)
Thank you !
function insertRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("test");
var sourceRange = sheet.getRange(10, 1, sheet.getLastRow());
var sheetData = sourceRange.getValues();
var numRows = sourceRange.getNumRows();
Logger.log(numRows);
for (var i=10; i < numRows; i++) {
sheet.insertRowsAfter(i, 5);
}
}
In your case we need to start at the end of the range and work our way up, adding rows where appropriate. The code below will do this and add a 5 rows below any row which has data, even adding rows if there is a blank row following the one with data. You could pass startRow to the function if you wish for more flexibility
function insertRows() {
var startRow = 10;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("test");
var sourceRange = sheet.getRange(startRow, 1, sheet.getLastRow());
var sheetData = sourceRange.getValues();
var numRows = sourceRange.getNumRows() - startRow;
// Logger.log(numRows);
for (var i=numRows; i > -1; i--) {
if (sheetData[i].join("")) {
sheet.insertRowsAfter(i + startRow, 5);
}
}
}
As a general comment: You are retrieving more rows as necessary as sheet.getLastRow() gets the last row number with data and the use in getRange() is telling the app to pull that number of rows as opposed to that number minus the starting position.
Try the below. This will add 3 rows when there is a no blank cell.
function insertRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("test");
var sourceRange = sheet.getRange(1, 1, sheet.getLastRow());
var sheetData = sourceRange.getValues();
for (var i=0; i < sheetData.length; i++) {
if(sheetData[i][0]!=""){
sheet.insertRowsAfter(i+1, 3);
sheetData = sheet.getRange(1, 1, sheet.getLastRow()).getValues();
}
}
}
Related
I'm new to javascript and a novice coder. I have been trying to write a simple script for a Google Sheet to concatenate two columns of data into another column:
My script below runs fine but only produces Aaron Ward as line 1 of Desired Column C. I'm sure it is really simple what I am missing, but if anyone has a minute to help a rookie, I'd really appreciate it.
function concatenate() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var lr = sheet.getLastRow()
var values1 = sheet.getSheetValues(1, 1, lr, 1);
var values2 = sheet.getSheetValues(1, 2, lr, 1);
var results = [];
for (var i = 0; i < lr; i++) {
results = [values1[i] + " " + values2[i]];
Logger.log(results);
sheet.getRange(1, 3, results.length).setValues([results]);
}
}
Why not using a formula? In C1 place the formula =JOIN(“ “,A1:B1) and drag it to the last row.
You're very close. In your for-loop, you need to push() the concatenated string into your results array. Then you can setValues(results) after the for-loop.
function concatenate() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var lr = sheet.getLastRow()
var values1 = sheet.getSheetValues(1, 1, lr, 1);
var values2 = sheet.getSheetValues(1, 2, lr, 1);
var results = [];
for (var i = 0; i < lr; i++) {
results.push([values1[i] + " " + values2[i]]);
}
sheet.getRange(1, 3, results.length).setValues(results);
}
You can either use this
function conCat(){
var ss = SpreadsheetApp.getActiveSpreadsheet()
var ws = ss.getSheetByName("your sheet name")
var data = ws.getDataRange().getValues()
for(var k = 1;k<data.length;k++){
var row = data[k]
var merge = row[0]+" "+row[1]
ws.getRange(k+1,3).setValue(merge)
}
}
This code will simply take values from first and second column and concatenate result will show in third column
I've written script to sort a google sheet by column A, and then take you to the cell next to the one you just edited, and I have it working perfectly for me the owner, but for editors, nothing seems to work starting from the "sort" function.
I assume this means some part of it is an installable trigger? but as far as I can tell I've made it all with simple triggers.
function onEdit(e) {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
var cell = sheet.getActiveCell();
var NEXTcell = sheet.getActiveRange().offset(0,1);
var range = e.range;
var columnOfCellEdited = range.getColumn();
var sheet = spreadsheet.getActiveSheet();
// When Column A edited
if (columnOfCellEdited === 1) {// Column 1 is Column A
//Set marker
NEXTcell.setValue('sorting');
// Sort whole sheet excluding first 2 rows by Column A.
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).activate();
spreadsheet.getActiveRange().offset(2, 0, spreadsheet.getActiveRange().getNumRows() - 2).sort({column: 1, ascending: true});
// Find original cell after sorting
var rowoffset = 3;
var rng = sheet.getRange(rowoffset, 2, 600);
var data = rng.getValues();
var search = "sorting";
for (var i=0; i < data.length; i++) {
if (data[i][0] == search) {
data[i][0] = "";
rng.setValues(data);
var foundcell = sheet.getRange((i+rowoffset), 2);
foundcell.activate();
break;
}
}
}
}
So Stackdriver logs for-the-win.
Turns out protections I hadn't considered are the culprit.
I need a little assistance writing a google script function.
I have a Google Sheet where each individual row may have a different color assigned to it.
I need a script that can note the html color code found in the first cell of each row, in that cell.
So for example lets say row 1 is a green row and row 2 is a blue row, the cell A1 should say #00ff00 and A2 should say #0000ff after running the script. Below is what I have so far.
function colorDetector() {
var startRow = 1; // First row of data to process
var numRows = 3; // Number of rows to process
var currentsheet = 'Production' // What sheet you would like to process (must be within ' ')
//This section prepares the document to be read
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(currentsheet);
var dataRange = sheet.getRange(startRow, 1, numRows, 15) // Fetch values for each row in the Range (row, column, numRows, numColumns)
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
//this is the section i cant seem to get working correctly
var color = row[0].getbackground(); //should set the variable "color" to the html color found in the first cell of the current row.
sheet.getRange(startRow + i, 1).setValue(color); // notes the variable found
SpreadsheetApp.flush();
}
}
Here is what I ended up figuring out on my own. It works perfectly.
function colorDetector2() {
var startRow = 1; // First row of data to process
var currentsheet = 'sheet 4' // What sheet you would like to process (must be within ' ')
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(currentsheet);
var numRows = 10; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 20) // Fetch values for each row in the Range (row, column, numRows, numColumns)
var colordata = dataRange.getBackgrounds();
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var color = colordata[i]
var colorconv = String(color[1]);
if (colorconv == "#00ff00") {
//do something here;
} else {
//do something else here;
}
}
}
I want a Google Script which checks once a day on my spreadsheet and copies the values to another sheet and than deletes all the rows if the date in that cell is small than the current.
The file looks like this:
And this is what I wrote so far:
function DeleteIfDateIsToSmall(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
var today = new Date();
var today2 = Utilities.formatDate(today,'GMT+0200','dd.MM.yyyy');
var startRow = 2; // First row of data to process
var numRows = sheet.getLastRow()-1
for (var i=2; i < numRows; i++) {
var DateCell = s.getRange(i, 13);
var sheetDate = DateCell.getValue()
var sheetDate2 = Utilities.formatDate(sheetDate,'GMT+0200','dd.MM.yyyy');
var row = i;
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Ended or Deleted");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
if (s.getName() == "Start" && sheetDate != 0 && sheetDate != "" && today2.valueOf() > sheetDate2.valueOf()){
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
}
It doesn't seem to work, please help.
A few things are wrong or suboptimal here.
For a timed trigger, the event object does not have any range/source data; it only has time data. You need to pick a sheet by name (or loop through all sheets obtained by getSheets, if this is what you want).
Utilities.formatDate returns a string, which is not the best way to compare dates; in any case calling valueOf on it seems pointless.
Instead of using getValue in a loop, it is more efficient to obtain values before entering the loop, with getValues. There are some other things you do in the loop that should be outside.
Deleting rows when moving top to bottom in a sheet is tricky, because rows shift, messing up their indexing. For this reason, I collect the rows to be deleted in an array, and then delete them in bottom-to-top order.
function DeleteIfDateIsTooSmall() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Start");
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Ended or Deleted");
var today = new Date();
var dates = s.getRange(2, 13, s.getLastRow()-1, 1).getValues();
var rowsToDelete = [];
for (var i = 0; i < dates.length; i++) {
if (dates[i][0] && dates[i][0] < today) {
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(i + 2, 1, 1, numColumns).moveTo(target);
rowsToDelete.push(i + 2);
}
}
for (i = rowsToDelete.length - 1; i >= 0; i--) {
s.deleteRow(rowsToDelete[i]);
}
}
I am trying to get the source rows that match my conditions to move to a target sheet. Then delete the source rows in the source sheet. Please see below code. Any help would be much appreciated.
function moveDeleteRow() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s1 = ss.getSheets()[0];
var values = s1.getDataRange().getValues();
var activeUser = Session.getActiveUser().getEmail();
var userFullName = ContactsApp.getContact(activeUser).getFullName();
Logger.log(userFullName);
var deleted = 0; // Counter
var cell = s1.getActiveCell();
for (var i = 0; i < values.length; i++) {
if (values[i][0] == userFullName && values[i][2] == 'Shipped') {
var rowdata = values[i];
Logger.log(rowdata);
var targetSheet = ss.getSheets()[2];
var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s1.getRange(1, 1, 1, s1.getLastColumn()).moveTo(targetRange);
s1.deleteRow(i + 1 - deleted);
deleted++;
}
}
SpreadsheetApp.flush();
};
This is a general code for moving range to range
function moveRange() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheets()[0];
var sourceRange = sourceSheet.getDataRange();
var targetSheet = ss.getSheets()[1];
var targetRange = targetSheet.getRange(1, 1, sourceSheet.getLastRow(), sourceSheet.getLastColumn());
sourceRange.moveTo(targetRange) ;
}
https://developers.google.com/apps-script/reference/spreadsheet/range#movetotarget
You just need to select the source and target properly.
Edit: If you're moving specific rows and want to delete the rows as well then it would be better to push the target values into an array (set them all at once later using range.setValues(array[][])) and also the indexes for the rows to be deleted and then delete the rows using sheet.deleteRow(position) using another loop. While using this, you'll have to keep in mind the offset for the next row being deleted because the ones that were deleted will cause the rest to shift up.