Google sheets : remove data from multiple columns - google-apps-script

I have been trying to clean a file by removing specific values from different columns.
I have no problems doing it from one column but if I add the same script with a different column and run the two script the values are not removed correctly.
I am pretty new to this so my scripting might be wrong. Is there a better way to do this? Or a mistake I made?
function clean() {
var startTime = new Date().getTime();
var deleteSelectedRows = removeThenSetNewVals();
var runTime = (new Date().getTime() - startTime) / 1000;
Logger.log("Runtime is: " + runTime + " seconds");
};
function removeThenSetNewVals(){
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var range = sheet.getDataRange();
var pattern = new RegExp("value1|value2");
var columnToSearch = 5;
var newRangeVals = range.getValues().filter(r => r[0] && !pattern.exec(r[columnToSearch]))
range.clearContent();
var numRows = newRangeVals.length;
var newRange = sheet.getRange(1,1, numRows, newRangeVals[0].length).setValues(newRangeVals);
var maxRows = sheet.getMaxRows();
sheet.deleteRows(numRows + 1, maxRows - numRows);
};
function clean2() {
var startTime = new Date().getTime();
var deleteSelectedRows = removeThenSetNewVals2();
var runTime = (new Date().getTime() - startTime) / 1000;
Logger.log("Runtime is: " + runTime + " seconds");
};
function removeThenSetNewVals2(){
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var range = sheet.getDataRange();
var pattern = new RegExp("Value1|Value3");
var columnToSearch = 2;
var newRangeVals = range.getValues().filter(r => r[0] && !pattern.exec(r[columnToSearch]))
range.clearContent();
var numRows = newRangeVals.length;
var newRange = sheet.getRange(1,1, numRows, newRangeVals[0].length).setValues(newRangeVals);
var maxRows = sheet.getMaxRows();
sheet.deleteRows(numRows + 1, maxRows - numRows);
};

You can do all the checks in one .filter() method
function removeThenSetNewVals(){
let sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1'),
range = sheet.getDataRange(),
maxRows = sheet.getMaxRows(),
srchCol_1 = 2,
srchPatt_1 = new RegExp("Value1|Value2"),
srchCol_2 = 5,
srchPatt_2 = new RegExp("Value1|Value3"),
newRangeVals = range.getValues().filter(r => r[0] && !srchPatt_1.exec(r[srchCol_1]) && !srchPatt_2.exec(r[srchCol_2])),
numRows = newRangeVals.length;
range.clearContent();
sheet.getRange(1,1, numRows, newRangeVals[0].length).setValues(newRangeVals);
sheet.deleteRows(numRows + 1, maxRows - numRows);
}
and it might be better to replace pattern.exec(string) with pattern.test(string)?

Related

Iterate through column A and do until empty cell

My script is working but it times out. I am unsure as to what I can do to keep it from doing this.
function archived(e) {
var sheet = SpreadsheetApp.getActive().getSheetByName('IVA');
const targetSheet = e.source.getSheetByName('Archived Videos');
const numColumnsToMove = 20;
var sheetTo = SpreadsheetApp.getActive().getSheetByName('IVA');
var myValues = sheetTo.getRange('A:A').getValues();
var i;
for (i = 0; i < myValues.length; i++) {
if (myValues[i][0] === '')
return i + 1;
const rangeToMove = sheet.getRange(e.range.rowStart, 1, 1, numColumnsToMove);
const values = rangeToMove.getValues();
appendRowsV(targetSheet, values, 1);
sheet.deleteRows(e.range.rowStart, 1);
var lRow = sheet.getLastRow();
var lCol = sheet.getLastColumn(), range = sheet.getRange(lRow,1,1,lCol);
sheet.insertRowsAfter(lRow, 1);
range.copyTo(sheet.getRange(lRow+1, 1, 1, lCol), {contentsOnly:false});
}
}
As an FYI my sheet has 1500 rows and 15 columns. don't know if that is important or not.
Just in case. As far as I can tell from your code you're trying to append all data from the sheet 'IVA' at the bottom of the sheet 'Archived Videos'. It can be done this way:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var src_range = ss.getSheetByName('IVA').getDataRange();
var dest_sheet = ss.getSheetByName('Archived Videos');
var last_row = dest_sheet.getLastRow() + 1;
var dest_range = dest_sheet.getRange('A' + last_row);
src_range.copyTo(dest_range);
}

get active sheet email, and a small problem on my code

I have two issues on my code, due to my luck of experience in coding, the code that I have is made to copy rows with a specific cell value, in my case it's 'commande confirmer', the first problem that I have is the first line of my values even if it has the specific value it's not copying but on other lines it's working perfectly.
And for the 2nd issue I want to get also when the data copied it transfer with it to the active sheet email, I found how to get it, but how to include it and being transferred I couldn't make it.
Here is my code
and thanks in advance.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Sheet1");
var url = "https://docs.google.com/spreadsheets/d/15nIAXcP0a14OvvBr5lww4tO23stQD4PEu0QDAcgaFyE/edit?ouid=112360896426304156672&usp=sheets_home&ths=true";
var ss2 = SpreadsheetApp.openByUrl(url);
var pasteSheet = ss2.getSheetByName("Sheet2");
// get source range
var max = copySheet.getMaxRows().toString();
var email= Logger.log(Session.getActiveUser().getEmail());
var range = copySheet.getRange(2, 1, max, 10);
var dataValues = range.getValues();
for (i = 1; i < dataValues.length; i++) {
if (dataValues[i][9] === 'COMMANDE CONFIRMER') {
pasteSheet.appendRow([dataValues[i][0],
dataValues[i][email],
dataValues[i][1],
dataValues[i][2],
dataValues[i][3],
dataValues[i][4],
dataValues[i][5],
dataValues[i][6],
dataValues[i][7],
dataValues[i][8],
dataValues[i][9]]);
var clearRow = i + 2;
copySheet.getRange('A' + clearRow + ':J' + clearRow).clear();
}
}
// get destination range
var destination = pasteSheet.getRange(pasteSheet.getLastRow() + 1, 1, max, 1);
// clear source values
Browser.msgBox('Commande Confirmer');
}
Try it this way:
function funko() {
var ss = SpreadsheetApp.getActive();
var csh = ss.getSheetByName("Sheet1");
var ss2 = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/15nIAXcP0a14OvvBr5lww4tO23stQD4PEu0QDAcgaFyE/edit?ouid=112360896426304156672&usp=sheets_home&ths=true");
var psh = ss2.getSheetByName("Sheet2");
var email = Session.getActiveUser().getEmail();
var range = csh.getRange(2, 1, csh.getLastRow() - 1, 10);
var cvs = range.getValues();
let oA = [];
cvs.forEach((r, i) => {
if (r[9] == 'COMMANDE CONFIRMER') {
let t = r.slice();
t.splice(1, 0, email);
oA.push(t);
csh.getRange(i + 1, 1, 1, csh.getLastColumn()).clearContent();
}
});
psh.getRange(psh.getLastRow() + 1, 1, oA.length, oA[0].length).setValues(oA);
Browser.msgBox('Commande Confirmer');
}

Combine multiple Google sheet scripts

I have been trying for weeks now to solve this issue but did not have any luck (I am pretty new to Google Scripting). So I am posting here hoping some of you managed to solve this before me !
I have multiple scripts in Google sheets and I would like to put them all together to run everything on a schedule.
The scripts are running well separately but not together. I see mostly conflict between script 2 and 3
Basically this is to get datas from an URL, and clean them. Here is a description of the script :
1 - Get the data from an URL
2 - Clean column 6
3 - Clean column 3
4 - Change number format
Here is the script :
function importCSVFromWeb() {
// Provide the full URL of the CSV file.
var csvUrl = "https://mycsvdata.testsite";
var csvContent = UrlFetchApp.fetch(csvUrl).getContentText();
var csvData = Utilities.parseCsv(csvContent);
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
}
// 2 - CLEAN CATEGORIES
function clean() {
var startTime = new Date().getTime();
var deleteSelectedRows = removeThenSetNewVals();
var runTime = (new Date().getTime() - startTime) / 1000;
Logger.log("Runtime is: " + runTime + " seconds");
};
function removeThenSetNewVals(){
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var range = sheet.getDataRange();
var pattern = new RegExp("Accessories|case|pouch...");
var columnToSearch = 5;
var newRangeVals = range.getValues().filter(r => r[0] && !pattern.exec(r[columnToSearch]))
range.clearContent();
var numRows = newRangeVals.length;
var newRange = sheet.getRange(1,1, numRows, newRangeVals[0].length).setValues(newRangeVals);
var maxRows = sheet.getMaxRows();
sheet.deleteRows(numRows + 1, maxRows - numRows);
};
// 3 - CLEAN NAME
function clean2() {
var startTime = new Date().getTime();
var deleteSelectedRows = removeThenSetNewVals2();
var runTime = (new Date().getTime() - startTime) / 1000;
Logger.log("Runtime is: " + runTime + " seconds");
};
function removeThenSetNewVals2(){
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var range = sheet.getDataRange();
var pattern = new var pattern = new RegExp("Accessories|case|pouch...");
var columnToSearch = 2;
var newRangeVals = range.getValues().filter(r => r[0] && !pattern.exec(r[columnToSearch]))
range.clearContent();
var numRows = newRangeVals.length;
var newRange = sheet.getRange(1,1, numRows, newRangeVals[0].length).setValues(newRangeVals);
var maxRows = sheet.getMaxRows();
sheet.deleteRows(numRows + 1, maxRows - numRows);
};
// 4 - CLEAN PRICE
function decimal(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var cell = sheet.getRange("D1:D");
// Always show 3 decimal points
cell.setNumberFormat("00");
}
Thank you very much for any help !
There are two methods that might help you - Spreadsheet.flush() and Lockservice. I cannot tell for sure if it will work without having the insight into your code, but you can try. Wrap each of your method calls into:
const lock = LockService.getScriptLock()
try{
lock.waitLock(30000)
method() // run your method here
SpreadsheetApp.flush()
} finally{
lock.releaseLock()
}
I am curious what you mean by run them together. But it is easy enough to have one function call the other functions and then using a trigger, set sheets to run the main function on the schedule you want
function daily() {
importCSVFromWeb();
clean();
removeThenSetNewVals();
clean2();
removeThenSetNewVals2();
decimal();
}

Google Sheets function runs but does not affect sheet content

I'm working on a Google Sheets script to perform the following:
iterate through a specified sheet, finding rows that do not contain a specified value within a specified column
store these rows as a range in a variable
remove all other rows
replace the sheet content with the stored rows
The script runs without error, but does not affect sheet content. I'm not sure what the issue is - any feedback is appreciated.
Here's the script:
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('Clear OI')
.addItem('Clear OI', 'removeZeroOI')
.addToUi();
}
function removeZeroOI() {
// Deleting Rows Based on Cell Values
//GLOBALS
var SS = SpreadsheetApp.openById("mySheetID");
var SHEET = SS.getSheetByName("mySheetName");
var RANGE = SHEET.getDataRange();
var DELETE_VAL = 0;
var COL_TO_SEARCH = 13; //column N
function main() {
var startTime = new Date().getTime();
var deleteSelectedRows = removeFilterSetVals();
var runTime = (new Date().getTime() - startTime)/1000;
Logger.log("Runtime is: "+runTime + " seconds");
};
function removeFilterSetVals(){
var rangeVals = RANGE.getValues();
var filteredRange = rangeVals.filter(function(val){
return val[COL_TO_SEARCH] != DELETE_VAL ;
});
RANGE.clearContent();
var newRange = SHEET.getRange(1,1,filteredRange.length, filteredRange[0].length);
newRange.setValues(filteredRange);
};
}
If you are actually using your showing script, I think that in your script, when the function of removeZeroOI() is run, main() and removeFilterSetVals() are not run. By this, the script doesn't work while no error occurs.
When you want to run main() and removeFilterSetVals(), how about the following modifications?
Modified script:
function removeZeroOI() {
var SS = SpreadsheetApp.openById("mySheetID");
var SHEET = SS.getSheetByName("mySheetName");
var RANGE = SHEET.getDataRange();
var DELETE_VAL = 0;
var COL_TO_SEARCH = 13; //column N
main(); // Added
function main() {
var startTime = new Date().getTime();
var deleteSelectedRows = removeFilterSetVals();
var runTime = (new Date().getTime() - startTime) / 1000;
Logger.log("Runtime is: " + runTime + " seconds");
};
function removeFilterSetVals() {
var rangeVals = RANGE.getValues();
var filteredRange = rangeVals.filter(function(val) {
return val[COL_TO_SEARCH] != DELETE_VAL;
});
RANGE.clearContent();
var newRange = SHEET.getRange(1, 1, filteredRange.length, filteredRange[0]
.length);
newRange.setValues(filteredRange);
};
}
And,
function removeZeroOI() {
var SS = SpreadsheetApp.openById("mySheetID");
var SHEET = SS.getSheetByName("mySheetName");
var RANGE = SHEET.getDataRange();
var DELETE_VAL = 0;
var COL_TO_SEARCH = 13; //column N
var startTime = new Date().getTime();
// Script of "removeFilterSetVals()" is put here.
var rangeVals = RANGE.getValues();
var filteredRange = rangeVals.filter(function(val) {
return val[COL_TO_SEARCH] != DELETE_VAL;
});
RANGE.clearContent();
var newRange = SHEET.getRange(1, 1, filteredRange.length, filteredRange[0]
.length);
newRange.setValues(filteredRange);
var runTime = (new Date().getTime() - startTime) / 1000;
Logger.log("Runtime is: " + runTime + " seconds");
}

How to show spreadsheet name in Logger

I am trying to get a chart from spreadsheet A. I take this into a Chart object, and try to put it back in spreadsheet B.
I always get an 'unknown sheetname' error. I have been trying to put new ranges in the new chart, as you can see in the code. When I do a Logger.log(newrange.getSheet()) I indeed get Sheet instead of SHEETNAME, like the chart builder messes with the sheetnames.
What is happening?
function updateCharts() {
var ss = SpreadsheetApp.openById("ID");
var sheet = ss.getSheetByName("SHEETNAME");
var charts = sheet.getCharts();
var ss2 = SpreadsheetApp.openById("NEW ID");
var sheet2 = ss2.getSheetByName("SHEETNAME");
for (var c=0; c<charts.length; c++) {
var chart = charts[c];
var ranges = chart.getRanges();
var type = chart.getType();
var info = chart.getOptions();
var builder = chart.modify();
var range = ranges[0];
builder.removeRange(range);
var startRow = range.getRow();
var startCol = range.getColumn();
var numRows = range.getNumRows();
var numCols = range.getNumColumns();
var newrange = ss2.getSheetByName("statistiek").getRange(startRow, startCol, numRows, numCols);
Logger.log(newrange.getSheet());
builder.addRange(newrange);
var title = chart.getOptions().get('title')
builder.setOption('title', title + " " + p);
var newchart = builder.build();
ss2.getSheetByName("statistiek").insertChart(newchart);
}
}
Logger.log() requires a string, but you're feeding it an object with newrange.getSheet(). Try this instead, if you want the sheet's name:
Logger.log(newrange.getSheet().getName())
To see the names of all sheets in a spreadsheet, try:
var ss = SpreadsheetApp.openById("ID");
var allSheets = ss.getSheets();
for (i in allSheets) {
Logger.log("Sheet " + i + " is named " + allSheets[i].getName());
}