Delete Row from all google sheets based on value of a cell - google-apps-script

I am trying to achieve a script that will delete a row based upon a string in a cell within that row,
I can achieve my mission if I want to name each individual sheet, however my sheets are constantly changing names, so this would mean updating the the script daily.
I have tried to create a loop, but that does not seem to work either, any suggestions?
The script I am working on is below.
function RemoveInvoiced() {
var ss = SpreadsheetApp.openById("1pxWr3jOYZbcwlFR7igpSWa9BKCa2tTeliE8FwFCRTcQ").getSheets();
for (var k=0; k<ss.length; k++)
var values = ss[k].getDataRange().getValues();
var rows_deleted = 0;
for (var i = 0; i < values.length; i++) {
for (var j = 0; j < values[i].length; j++) {
var value = values[i][j];
var row = i + 1 - rows_deleted;
if (typeof value === 'string') {
var result = value.search("INVOICED");
if (result !== -1) {
ss.deleteRow(row);
rows_deleted++;
}
}
}
}
};

Instead of using the sheet name to access them, you could access them by Id.
The id will never change as long as you don't delete the sheet, even if you change the name.
You'd first have to get the sheets Id, a simple function could do that for you
function getId(sheet){
Logger.log(sheet.getSheetId());
}
Once you have gotten your sheet ids, you can make a function that will open the right sheet by the ID
function openSheetById(doc, id){
var sheets = doc.getSheets();
for(var i = 0; i< sheets.length ; i++){
if( sheets[i].getSheetId() == id)
return sheets[i];
}
return false;
}
And then you can access the right sheet.
function myFunc(){
var doc = SpreadsheetApp.openById("1pxWr3jOYZbcwlFR7igpSWa9BKCa2tTeliE8FwFCRTcQ");
var id = // your id here
var sheet = openSheetById(doc, id);
if(sheet){
//do other stuffs
}
}

Related

How to change cell values?

I'm using Google app script for sheets and I'm new to it.
I have a column with number and a hyperlink in each cell (each link and number is different).
I want to get the link then make an API request which will return a number which will replace that original number for each cell.
At the moment here is my function:
function getLinkUrls() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("B2:B");
var values = range.getRichTextValues();
for (var i = 0; i < values.length; i++) {
for (var j = 0; j < values[i].length; j++) {
if (values[i][j].getLinkUrl() !== null) {
const val = values[i][j],
url = val.getLinkUrl(),
path = url.split('/')[3];
var response = UrlFetchApp.fetch(`https://decapi.me/twitch/followcount/${path}`),
f = response.getContentText();
}
}
}
}
I want to replace each cell now with f but I'm unsure how.
Table:
Column B should always have hyperlink
I have successful replace the hyperlink with the follower count, you may try if working on your side also, since I did not use getrichtext but getvalue directly:
function getLinkUrls1() {
var sheet = SpreadsheetApp.getActiveSheet();
for (var i = 2; i <= sheet.getLastRow(); i++) {
var url = sheet.getRange(i,2).getRichTextValue().getLinkUrl();
if (url){
var path = url.split('/')[3];
var response = UrlFetchApp.fetch(`https://decapi.me/twitch/followcount/${path}`),
f = response.getContentText();
sheet.getRange(i,2).setRichTextValue(SpreadsheetApp.newRichTextValue()
.setText(f).build());
}
}
}
This is my sample data:

Delete all Sheets except one, loop within a loop

I have a spreadsheet that contains a list of URLS for spreadsheets and the sheet name that I want to keep.
The idea is that I delete all sheets within each of those spreadsheets except the sheet I want to keep.
I have written a script but I can not seem to get it to work, I get an error message of "invalid argument line 20" but I can not figure out why.
I have pasted my code below, any help would be appreciated.
function DeleteImportedData(){
var s3 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("URL's")
var s1 = SpreadsheetApp.getActiveSpreadsheet()
var sh1 = s1.getSheetByName("MasterSheet")
var copy = sh1.getRange(1,1,sh1.getLastRow(),sh1.getLastColumn()).getValues()
var getHeader = sh1.getRange(1,1,1,25).getValues()
for (var j = 1;j<s3.getLastRow(); j++){
var filterName = s3.getRange(j+1, 1).getValue()
var id = s3.getRange(j+1,2).getValue()
var open = SpreadsheetApp.openById(id)
var sheet = open.getSheets()[0];
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var sh3 = open.getSheetByName("STSOR - "+filterName)
}
for (i = 0; i <= sheets.length; i++) {
switch(sheets[i]) {
case sheet.getSheetName() === sh3:
break;
default:
open.setActiveSheet(sheet[i]);
open.deleteActiveSheet;
open.deleteSheet(del)
}
}
}
when you delete the first sheet from the list Sheet1, Sheet2, Sheet3 - Sheet2 changes its index to Sheet1. So it is better to delete sheets from the end
try to use the reverse loop
for (i = sheets.length-1; i >=0 ; i--){
... your code ...
}
There is something wrong between your variable sheet and sheets and your second loop.
Try this way :
for (var j = 1;j<s3.getLastRow(); j++){
// your code
// second loop inside the first loop
for (i = 0; i <= sheets.length; i++) {
switch(sheets[i]) {
case sheets[i].getSheetName() === sh3: //instead of 'sheet'
break;
default:
open.setActiveSheet(sheets[i]); //instead of 'sheet'
open.deleteActiveSheet;
open.deleteSheet(del)
}
} // close first loop
} // close second loop
but I think the second loop would be cleaner that way (IMHO):
for (i = 0; i <= sheets.length; i++) {
if (sheets[i].getSheetName() !== sh3) {
open.deleteSheet(sheets[i].getSheetName());
}
}
If this code doesn't answer your question, please provide more informations about your spreadsheets

Unchecking Checkboxes in Google Sheets

For the life of me I can't figure out how set it up. I would like the function to check the entire sheet... alternatively I do know which specific ranges (B5:B26; G5:G26...AF5:AF26) on a specific sheet, if i can't set it up for the entire sheet...
function setFalse()
{
var sheet = SpreadsheetApp.getSheetByName("Test");
var dataRange = sheet.getRange('A:AN28');
var values = dataRange.getValues();
for (var i = 0; i < values.length; i++)
{
for (var j = 0; j < values[i].length; j++)
{
if (values[i][j] == true)
{
values[i][j] = false; // Modified
}
}
}
dataRange.setValues(values);
};
There's a built-in method to uncheck called uncheck(). You can effectively apply it to the sheet by using getDataRange().
function setFalse() {
SpreadsheetApp.getActive().getSheetByName("Test").getDataRange().uncheck();
};
Lastly, looking at your original code, don't forget to get a spreadsheet file before selecting the sheet.

Google spreadsheets - find all hidden rows - only include rows that are not hidden

The code provided copies data from sheet "Feuille 3" to an another sheet named "INITIALE". Some of the rows in the source sheet tab, "Feuille 3" are hidden.
I hide some rows in "Feuille 3" when col D has a checkbox with a "true" value.
I don't know how I can check the rows hidden in "Feuille 3" and remove these rows in my array "Nouvelleliste."
Here is the code :
function copiertableau() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var orig = ss.getSheetByName("Feuille 3");
var dest = ss.getSheetByName("INITIALE");
var Ancienneliste = orig.getDataRange().getValues();
var Nouvelleliste = new Array();
for (var i = 0; i < Ancienneliste.length; i++) {
var Nouvelleligne = new Array();
for (var j = 0; j < 3; j++) {
Nouvelleligne[j] = Ancienneliste[i][j];
}
Nouvelleliste[i] = Nouvelleligne;
}
ss.getSheetByName("INITIALE").getRange(22, 1, Nouvelleliste.length, 3).setValues(Nouvelleliste);
SpreadsheetApp.flush();
}
The Advanced Sheets API has a way of finding all the rows that were hidden by the user or by code. You must explicitly enable the Advanced Sheets API from the code editor. From the code editor choose, "Resources" and "Advanced Google Services." Scroll down to "Google Sheets API" Turn the button ON. Then click the link to Google API Console. Enable the Google Sheets API in your console.
First get all the rows that are hidden. In the example below, that is done in a separate function. Then compare the current row index to the values in the array. If there is a hidden row, then don't put the row's data into the array.
function copiertableau() {
var arrOfHiddenRows,Nouvelleligne,o,sourceSheetTab,ss;
ss = SpreadsheetApp.getActiveSpreadsheet();
sourceSheetTab = ss.getSheetByName("Feuille 3");
var dest = ss.getSheetByName("INITIALE");
sourceSheetTab = ss.getSheetByName("INITIALE");
var Ancienneliste = sourceSheet.getDataRange().getValues();
var Nouvelleliste = [];
o = {};//Object for arguments to pass to function to get the hidden rows
o.L = sourceSheetTab.getLastRow();
o.ssID = ss.getId();//Put the spreadsheet file ID into the object with key name ssID
o.sheetId = sourceSheetTab.getSheetId();
arrOfHiddenRows = getRowsHiddenByUsr(o);//Get a list of all hidden rows in sheet tab sourceSheet
//Logger.log('arrOfHiddenRows: ' + arrOfHiddenRows)
for (var i = 0; i < Ancienneliste.length; i++) {
if (arrOfHiddenRows.indexOf(i+1) !== -1) {//This row is hidden in the sheet sourceSheet
continue;//continue to loop without putting this rows data into the array
}
Nouvelleligne = [];
for (var j = 0; j < 3; j++) {
Nouvelleligne[j] = Ancienneliste[i][j];
}
Nouvelleliste[i] = Nouvelleligne;
}
ss.getSheetByName("INITIALE").getRange(22, 1, Nouvelleliste.length, 3).setValues(Nouvelleliste);
SpreadsheetApp.flush();
}
function getRowsHiddenByUsr(po) {
try{
var arrHiddenRows,data,fields,i,j,L,L_sh,rows,sheets,sheetId,spreadsheetId,thisSheet,thisShID;
/*
po.L - row length of the sheet tab
po.ssID - the spreadsheet file ID of the spreadsheet
po.sheetID - The ID of the sheet tab
*/
L = po.L;
spreadsheetId = po.ssID;
sheetId = po.sheetID;
//Logger.log(L)
//Logger.log('sheetId: ' + sheetId)
arrHiddenRows = [];
fields = "sheets(data(rowMetadata(hiddenByUser)),properties/sheetId)";//Get only metadata of hidden rows by user
sheets = Sheets.Spreadsheets.get(spreadsheetId, {fields: fields}).sheets;
L_sh = sheets.length;
//Sheets.Spreadsheets.get(spreadsheetId)
//Logger.log('sheets.length: ' + sheets.length)
for (i = 0; i < L_sh; i++) {
thisSheet = sheets[i];
//Logger.log('thisSheet === undefined: ' + thisSheet === undefined)
if (thisSheet === undefined) {
continue;
}
thisShID = thisSheet.properties.sheetId;
//Logger.log('thisShID: ' + thisShID)
if (thisShID === sheetId) {
//Logger.log('they are equal')
data = thisSheet.data;
rows = data[0].rowMetadata;
//Logger.log('thisShID: ' + thisShID)
//Logger.log('rows.length: ' + rows.length)
for (j = 0; j < L; j++) {
//Logger.log(rows[j].hiddenByUser)
if (rows[j].hiddenByUser) arrHiddenRows.push(j+1);
}
}
}
return arrHiddenRows;
}catch(e) {
console.log(e.message);
console.log(e.stack);//log the stack
}
}
thanks #SandyGood It seems it's missing something.
Firstly, i changed
var Ancienneliste = sourceSheet.getDataRange().getValues();
to put "sourceSheetTab" variable; and i delete a line because you put twice "sourceSheetTab" with 2 contents so i keep the first one.
Secondly, your function continue to copy hidden rows in the sourcesheet table.
maybe i can put my other code i did to hide rows in "Feuille 3" to help?
//global variables
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Feuille 3");
function cacherRow() {
for (var i=1; i < 300; i ++){
var nb = sheet.getRange('D'+i).getValue();
if (nb == true){
sheet.hideRows(i);
}
}
}
i enable googlesheets API in the console.
Google Apps Script now offers a new method - isRowHiddenByUser - to determine if a particular row is hidden or not.
for (var i = 0; i < Ancienneliste.length; i++) {
if (sheet.isRowHiddenByUser(i+1)) {
// do something
}
}
Note that you need to specify the row position in the method and it begins from 1, not 0.

Delete Duplicate Row in Google Spreadsheet

I need this script to delete the row (within the Registration sheet) with the matching Registration Code to the Cancel Registration sheet's Registration code. As of now, this script only deletes a row if "sheetR.deleteRow(i);" is not inside "if (regCodeR === regCodeCR) {}". It doesn't delete the correct row either.
function rD() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetR = ss.getSheetByName("Registration");
var sheetCR = ss.getSheetByName("Cancel Registration")
var dataR = sheetR.getDataRange().getValues();
var dataCR = sheetCR.getDataRange().getValues();
var headerRow = 1;
for (var i = 1; i in dataR && i in dataCR; ++i) {
var rowR = dataR[i];
var rowCR = dataCR[i];
var duplicate = false;
var regCodeR = sheetR.getRange(headerRow + i, 10).getValues();
var regCodeCR = sheetCR.getRange(headerRow + i, 9).getValues();
if (rowR[9] === rowCR[8]) {
duplicate = true;
}
}
if (regCodeR === regCodeCR) {
sheetR.deleteRow(i);
}
}
I tried this code with simple data having one column with registration numbers. You can modify the main sheet range according to your data. Also make sure to change the sheet names.
Tried and tested the code below :
function deleteDup(){
var mainSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('regis');
var cancelSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('cancel');
var mainSheetValues = mainSheet.getRange(2, 1, mainSheet.getLastRow(),1).getValues();
var cancelSheetValues = cancelSheet.getRange(2, 1, cancelSheet.getLastRow(),1).getValues();
var k = 0;
var del = [];
// Getting the row index of matching values
for (i = 0; i < cancelSheetValues.length; i++)
{
var cancelValue = cancelSheetValues[i][0];
Logger.log(cancelValue);
for (j = 0; j < mainSheetValues.length; j++)
{
if(mainSheetValues[j][0] == cancelValue){
del[k] = j;
k++;
}
}
}
del.sort();
var count =0;
// deleting the values from the main sheet values array
for (i = 0; i < k; i++ )
{
mainSheetValues.splice((del[i] - count), 1);
count++;
}
var len = mainSheetValues.length;
// Update the sheet with new values
mainSheet.getRange(2, 1, mainSheet.getLastRow(),1).clearContent();
mainSheet.getRange(2, 1, len,1).setValues(mainSheetValues);
}
But instead you can also do this way:
Set a flag value in the registration sheet if it matches with the cancellation sheet.
Then loop through the registration sheet data and delete the matching flag row.
Hope that helps!