I have a Gsheet where if I need to delete a row that contains the text 'none' on Sheet1, it will also delete the same row (or range of rows) on Sheet2.
I've tried the following code which will delete the row on Sheet1, but I can't get it to delete the corresponding row on Sheet2
function sort() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1')
SpreadsheetApp.getActive().getSheetByName('Sheet2')
var rows = sheet.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[9] == 'none') {
sheet.deleteRow((parseInt(i)+1) - rowsDeleted); rowsDeleted++;
}
}
};
The expected result is to delete the same row on both sheets, but at the moment it is only deleting on Sheet1.
Thanks!
And if the 'none' text was in a different column on Sheet1 than Sheet2, what would I do? I tried this but it doesn't seem to work:
function sort() {
var sheet1 = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var sheet2 = SpreadsheetApp.getActive().getSheetByName('Sheet2');
var rows = sheet1.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[9] == 'none') {
sheet1.deleteRow((parseInt(i)+1) - rowsDeleted);
if (row[10] == 'none') {
sheet2.deleteRow((parseInt(i)+1) - rowsDeleted);
rowsDeleted++;
}
}
};}
I would create two seperate variables for the two seperate sheets:
function sort() {
var sheet1 = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var sheet2 = SpreadsheetApp.getActive().getSheetByName('Sheet2');
var rows = sheet1.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[9] == 'none') {
sheet1.deleteRow((parseInt(i)+1) - rowsDeleted);
sheet2.deleteRow((parseInt(i)+1) - rowsDeleted);
rowsDeleted++;
}
}
};
Related
I have this script working well, but I'm uncertain how to make it run on every tab not labeled "Main". Thanks in advance!
function hideRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Dude"); // Enter sheet name
var row = s.getRange('A2:A').getValues(); // Enter column letter that has the text "hide" and "unhide"
var cell = s.getRange('A1').getValue();
s.showRows(1, s.getMaxRows());
for(var i=0; i < row.length; i++){ if(row[i] != cell) { s.hideRows(i+2, 1); } // Value to hide
}
}
Jerome
Run on every sheet except Main
I assume that you are running the onEdit trigger.
function hideRows(e) {
const s = e.range.getSheet();
if(s.getName() == "Main") return;
var row = s.getRange(2,1,s.getLastRow() -1 ).getValues().flat();
var cell = s.getRange('A1').getValue();
s.showRows(1, s.getLastRow());
for (var i = 0; i < row.length; i++) {
if (row[i] != cell) { s.hideRows(i + 2, 1); }
}
}
Want to exclude more sheets
function hideRows(e) {
const s = e.range.getSheet();
const ex = ['Main','Sheetx'];//excluded sheet names
const idx = ex.indexOf(s.getName());
if(~idx) return;
var row = s.getRange(2,1,s.getLastRow() -1 ).getValues().flat();
var cell = s.getRange('A1').getValue();
s.showRows(1, s.getLastRow());
for (var i = 0; i < row.length; i++) {
if (row[i] != cell) { s.hideRows(i + 2, 1); }
}
}
Basically, the user will input data on a new item on sheet NovoItem. When the Save Button (to be added) is pressed, the code is supposed to check on sheet2 (ArquivoItens) if the item is already there. If so, then it should break.
The code is not breaking if value is found on sheet2 (ArquivoItens):
function copyrange() {
var sourceSheet = 'Novo Item';
var destinationSheet = 'ArquivoItens';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sourceSheet);
var ActiveUser = Session.getActiveUser();
//it add current user and a timestamp to the last 2 columns on sheet1.
var val = sheet.getRange("Q12:Q")
.getValues();
for (var i = 0; i < val.length; i++) {
if (val[i] > 0) {
sheet.getRange(12, 34, i + 1, 1)
.setValue(new Date());
sheet.getRange(12, 35, i + 1, 1)
.setValue(ActiveUser)
}
}
var LastRowSource = sheet.getLastRow();
var LastColumnSource = sheet.getLastColumn();
var values = sheet.getRange(11,1,LastRowSource,LastColumnSource).getValues();
var csh = ss.getSheetByName(destinationSheet);
var data = [];
for (var i = 1; i < values.length; i++) {
if ( values[i][0] != '') {
data.push(values[i]);
//sheet.deleteRow(i+1)
}
}
var dataNovoItem = sheet.getRange("B12:B").getValues(); // gets data (item number) in the sheet where data is input
var dataArquivoItens = csh.getRange("B2:B").getValues(); //gets the item number on the datawarehouse sheet
for(var n=1; n < dataNovoItem.length ; n++){
for(var j=1; j< dataArquivoItens.length ; j++){
if (dataNovoItem[n] != 0 && dataArquivoItens[j] != 0) {
if(dataNovoItem[n] == dataArquivoItens[j]) {
break;
}
}
}
}
Logger.log("Novo Item" + dataNovoItem);
Logger.log("ArquivoItens" + dataArquivoItens);
//Copy data array to destination sheet
csh.getRange(csh.getLastRow()+1,1,data.length,data[0].length).setValues(data);
}
Here's the log I'm getting:
Any help is appreiated.
You aren't using the iterator to access the index that you're iterating through.
It should be
for(var n=1; n < dataNovoItem.length ; n++){
for(var j=1; j< dataArquivoItens.length ; j++){
if (dataNovoItem[n] != 0 && dataArquivoItens[j] != 0) { // this is where I try to eliminate blank rows in both ranges. I've tried != '', but it gets me the same result on the print below.
if(dataNovoItem[n] == dataArquivoItens[j]) {
break; //not working
}
}
}
}
Logger.log("Novo Item" + dataNovoItem);
Logger.log("ArquivoItens" + dataArquivoItens);
I ended up solving this by iterating only through the existing list and comparing each row with the value I had set on the current sheet. This is probably too logic to yur programmers, but for a beginner like me, this can be a pain.
This is how the working is now:
var newItemID = sheet.getRange("W5").getValue(); //get the destination cell, where the item will be set
var itemIDArquivoItens = csh.getRange(2, 1, csh.getLastRow(),1).getValues(); //gets the data range where the existing ID's to be compared against are
var message = "Item já cadastrado!"; //Message to be displayed in case the ID already exists in the list;
for(j = 1; j < itemIDArquivoItens.length; j++) { //loops through existing ID
if(itemIDArquivoItens[j][0] == newItemID) { //if the ID already exists, pop up a message and stop the code from running
Browser.msgBox(message)
return;
}
}
I have a script that deletes empty rows in Google Sheets. Currently it only runs on the sheet I have open; I want it to run on all worksheets in the document.
After a long time trying to apply code from other peoples questions, I just cannot seem to get it to work with my existing code.
Any answers are appreciated.
This is one snippet of code I tried to use but it would not run
function saveRange(){
var tabs = [
'Sample_tab_1',
'Sample_tab_2',
'Sample_tab_3',
'Sample_tab_4'
];
var ss=SpreadsheetApp.getActiveSpreadsheet();
for (var i = 0; i < tabs.length; i++) {
var sheet=ss.getSheetByName(tabs[i]);
var range=sheet.getRange('A8:AE47').getValues();
sheet.getRange(sheet.getLastRow()+1, 1, range.length, range[0].length).setValues(range);
}
}
This is what I have that works but only on the current sheet
function readRows() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.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[2] == 0 || row[2] == '') {
sheet.deleteRow((parseInt(i)+1) - rowsDeleted);
rowsDeleted++;
}
}
};
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Remove rows where column C is 0 or blank",
functionName : "readRows"
}];
sheet.addMenu("Script Center Menu", entries);
};
You can try this code snippet, but be careful, this will clear EVERY sheet in your current google Spreadsheet:
function readRows()
{
var spreadsheet = SpreadsheetApp.getActive();
var ttl = spreadsheet.getSheets().length;
for (var a=0; a<ttl; a++)
{
spreadsheet.getSheets()[a].clear()
//if you prefer to delete, please replace the above
}
}
Combined with your script, it may look like this below:
function readRows()
{
var spreadsheet = SpreadsheetApp.getActive();
var ttl = spreadsheet.getSheets().length;
for (var a=0; a<ttl; a++)
{
var sheet = spreadsheet.getSheets()[a];
var rows = sheet.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[2] == 0 || row[2] == '')
{
sheet.deleteRow((parseInt(i)+1) - rowsDeleted);
rowsDeleted++;
}
}
}
};
Here I would like to give a modification:
function readRowsModify()
{
var spreadsheet = SpreadsheetApp.getActive();
var ttl = spreadsheet.getSheets().length;
for (var a=0; a<ttl; a++)
{
var sheet = spreadsheet.getSheets()[a];
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
//if row 1 is header change i>0 to i>1
for (var i = numRows; i>0; i--)
{
var row = values[i-1];
//if in this row, column c is 0 or column c is '' or column c is undifined,
//please correct define in this filter to delete row
if (row[2] == 0 || row[2] == '' || row[2] == undefined)
{
sheet.deleteRow(i);
}
}
}
};
I am combining tables from different sheets into one on google sheets. What I am trying to do is set up a function onedit(e) may be combined with a loop function to run this
=index($G$2:$G$8,match($A10&$I$1,arrayformula($B$2:$B$8&$E2:$E8),0),"").
I am new to google script so I have just tried using formulas but the formula updates all cells next to it and what I want is that it matches and stays so that next time column G gets updated then the result be added to B10 instead of rewriting A10. (I1 has formula =today() so that it has a place of reference but if the code can just match with the date then that would be great!)
Here is the link to the sheet if you would like to see what I am talking about. https://docs.google.com/spreadsheets/d/1jviYYhI1V_bL8TMVvijR9vo_7sBFfktbhgblGNcYfrQ/edit?usp=sharing
Column B2:B8 are drop-downs that are based on the list from A10:A18 if that makes any difference.
Any help would be greatly appreciated I've been looking for 3 days and can't find something that would do this.
try this:
function autoload() {
var ss = SpreadsheetApp.getActiveSheet();
var meeting = ss.getRange("B2:F8").getValues();
var targetNames = ss.getRange("A10:A18").getValues();
var writtingRange = ss.getRange("B10:F18").getValues();
var updatedUser = targetNames;
var writtingColumn = -1;
var coolMatrix;
for (var i = 0; i < meeting.length; i++) {
var name = meeting[i][0]
for (var j = 0; j < targetNames.length; j++) {
if (targetNames[j][0] == name) {
for (var z = 0; z < writtingRange[0].length; z++) {
if (writtingRange[j][z] == '' && writtingColumn < 0) {
writtingColumn = z;
break;
}
}
writtingRange[j][writtingColumn] = meeting[i][4];
updatedUser[j] = true;
}
}
}
whiteSpaceRemover(writtingRange);
ss.getRange("B10:F18").setValues(writtingRange);
}
function whiteSpaceRemover(multidimensionalArray) {
for (var i = 0; i < multidimensionalArray.length; i++) {
for (var j = 0; j < multidimensionalArray[0].length; j++) {
if (multidimensionalArray[i][j] == '') {
multidimensionalArray[i].splice(j, 1);
multidimensionalArray[i].push('');
}
}
}
for (var i = 0; i < multidimensionalArray.length; i++) {
if (multidimensionalArray[i][0] == '') {
for (var j = 0; j < multidimensionalArray[i].length; j++) {
if (multidimensionalArray[i][j] != '') {
whiteSpaceRemover(multidimensionalArray);
}
}
}
}
return multidimensionalArray;
}
Tested this with a copy of your sheet, and it was working well, it sets the correct note next to the name and a '-' if they were not in the meeting, you have to run it manually for now, but it can be assigned to an onEdit() if you'd like.
function onEdit(event)
{ var timezone = "GMT-5"; var timestamp_format = "MM/dd/yyyy"; // Timestamp Format.
var updateColName = "Student Name";
var timeStampColName = "Date";
var sheet, ss;
ss = SpreadsheetApp.getActiveSpreadsheet();
sheet = ss.getActiveSheet();//Get the active sheet
var actRng = event.source.getActiveRange();
var editColumn = actRng.getColumn();
var index = actRng.getRowIndex();
var headers = sh
eet.getRange(4, 1, 1, sheet.getLastColumn()).getValues();
var dateCol = headers[0].indexOf(timeStampColName);
var updateCol = headers[0].indexOf(updateColName); updateCol = updateCol+1;
if (dateCol > -1 && index >=5 && index <= 36 && editColumn == updateCol) { // only timestamp if 'Last Updated' header exists, but not in the header row itself!
var cell = sheet.getRange(index, dateCol + 1);
var date = Utilities.formatDate(new Date(), timezone, timestamp_format); cell.setValue(date); }
function onEdit(){
var ss = SpreadsheetApp.getActiveSheet();
var meeting = ss.getRange("B2:F37").getValues();
var targetNames = ss.getRange("A38:A90").getValues();
var writtingRange = ss.getRange("B38:F90").getValues();
var updatedUser = targetNames;
var writtingColumn = -1;
var coolMatrix;
for(var i = 0; i < meeting.length; i++){
var name = meeting[i][0]
for (var j = 0; j < targetNames.length; j++) {
if (targetNames[j][0] == name){
for (var z = 0; z < writtingRange[0].length; z++) {
if (writtingRange[j][z] == '' && writtingColumn < 0) {
writtingColumn = z;
break;
}
}
writtingRange[j][writtingColumn] = meeting[i][4];
updatedUser[j] = true;
}
}
}
for (var w = 0; enter code here w < writtingRange.length; w++){
if (writtingRange[w][writtingColumn] == ''){
writtingRange[w][writtingColumn] = '-';
}
}
ss.getRange("B38:F90").setValues(writtingRange);
}}
I am trying to highlight duplicate rows in my sheet by checking for the same email address entered under the 'Email Address' column.
I have some code (below) that does this - it looks for duplicate rows based on repeated values under 'Email Address' and highlights them red. However, once I revisit the sheet, manually remove the duplicate row and rerun the script, the same row is highlighted again. Why is this happening and what can I do to ensure that when I update the sheet, the (now) unique row is not highlighted again?
function findDupes() {
var CHECK_COLUMNS = [3];
var sourceSheet = SpreadsheetApp.getActiveSheet();
var numRows = sourceSheet.getLastRow();
var numCols = sourceSheet.getLastColumn();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var newSheet = ss.insertSheet("FindDupes");
for (var i = 0; i < CHECK_COLUMNS.length; i++) {
var sourceRange = sourceSheet.getRange(1,CHECK_COLUMNS[i],numRows);
var nextCol = newSheet.getLastColumn() + 1;
sourceRange.copyTo(newSheet.getRange(1,nextCol,numRows));
}
var dupes = false;
var data = newSheet.getDataRange().getValues();
for (i = 1; i < data.length - 1; i++) {
for (j = i+1; j < data.length; j++) {
if (data[i].join() == data[j].join()) {
dupes = true;
sourceSheet.getRange(i+1,1,1,numCols).setBackground("crimson");
sourceSheet.getRange(j+1,1,1,numCols).setBackground("crimson");
}
}
}
ss.deleteSheet(newSheet);
if (dupes) {
Browser.msgBox("Possible duplicate(s) found. Please check for repeat attendees.");
} else {
Browser.msgBox("No duplicates found.");
}
};
I want to be able to run the script again once I have manually removed the rows and have it reflect the updated nature of the sheet.
Try this:
Sorry, but there were so many things I couldn't understand why you were doing them that I find it easier just to show you how I'd do it.
function findAndHighlightDupesInColumn(col) {
var col=col||3;//I think you wanted to check column 3
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rg=sh.getDataRange();
var vA=rg.getValues();//gets all data
var uA=[];//this is the array that hold all unique values
for(var i=1;i<vA.length;i++) {//assumes one header row
if(uA.indexOf(vA[i][col-1])==-1) {//if it's unique then put it in uA
uA.push(vA[i][col-1]);
}else{//if it's not unique then set background color
sh.getRange(i+1,1,1,sh.getLastColumn()).setBackground('crimson');
}
}
}
The following code will remove duplicates in column 3:
This method assumes that the first occurrence of any row is the row that you wish to keep. All other duplicate rows are deleted.
function removeColumnDupes(col) {
var col=col||3
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rg=sh.getDataRange();
var vA=rg.getValues();
var uA=[];
var d=0;
for(var i=1;i<vA.length;i++) {
if(uA.indexOf(vA[i][col-1])==-1) {
uA.push(vA[i][col-1]);
}else{
sh.deleteRow(i+1-d++);
}
}
}
Try adding this before the for loops. It will turn all the rows into white, and then the rest of your code will turn the duplicates red:
sourceSheet.getRange(2,1,numRows,numCols).setBackground("white");
Also, you can add an onEdit() function to check for duplicates in real time, when you add or edit an email address:
function onEdit(e){
if (e.range.getColumn() == 3){
var sourceSheet = SpreadsheetApp.getActiveSheet();
var numRows = sourceSheet.getLastRow();
var numCols = sourceSheet.getLastColumn();
var data = sourceSheet.getRange("C2:C"+numRows).getValues();
var editedCell = e.value;
for (var i = 0; i < data.length;i++){
if (editedCell == data[i] && (i + 2) != e.range.getRow()){
sourceSheet.getRange(e.range.getRow(),1,1,numCols).setBackground("crimson");
sourceSheet.getRange(i+2,1,1,numCols).setBackground("crimson");
}
}
}
}