Google Sheets function runs but does not affect sheet content - google-apps-script

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");
}

Related

Google script function works when it runs separately, but when I run all the functions together it doesn't work

I've got a question about my script. I've got a script where when running together only 2 out of 3 functions run, the other function does not run. The one function that does not work when running together is the "medewerkerLijst" function. When I run that function on it's own it works perfectly as it should, when running it together with the other 2 functions it does not work. I can't figure out why it's not working.
The functions "nieuwDossier" & "sorteerDossiers" do work when running together. Sorry if my code is a mess, I'm still learning how to code.
function Aanmaken(){
medewerkerLijst();
nieuwDossier();
sorteerDossiers();
}
function medewerkerLijst() {
var ss5 = SpreadsheetApp.getActiveSpreadsheet();
var copySheet2 = ss5.getSheetByName("-Dossier");
var pasteSheet2 = ss5.getSheetByName("-Medewerkers");
// get source range
var source2 = copySheet2.getRange(2,7,1,1);
// get destination range
var destination2 = pasteSheet2.getRange(pasteSheet.getLastRow()+1,1,1,1);
// copy values to destination range
source2.copyTo(destination2, {contentsOnly:true});
}
function nieuwDossier() {
var source = SpreadsheetApp.getActiveSpreadsheet();
var sheet = source.getSheetByName('-Template');
sheet.copyTo(source).setName('Nieuw');
var sheet2 = source.getSheetByName('-Dossier');
var cell = sheet2.getRange("G2");
var value = cell.getValue();
var sheet3 = source.getSheetByName('Nieuw');
sheet3.setName(value);
sheet3.setTabColor(null);
}
function sorteerDossiers () {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetNameArray = [];
var sheets = ss.getSheets();
for (var i = 0; i < sheets.length; i++) {
sheetNameArray.push(sheets[i].getName());
}
sheetNameArray.sort();
for( var j = 0; j < sheets.length; j++ ) {
ss.setActiveSheet(ss.getSheetByName(sheetNameArray[j]));
ss.moveActiveSheet(j + 1);
}
}
This runs just fine
function main() {
var ss = SpreadsheetApp.getActive();
var sh1 = ss.getSheetByName("Sheet1");
var sh2 = ss.getSheetByName("Sheet2");
var rg1 = sh1.getRange(2, 7, 1, 1);
var rg2 = sh2.getRange(sh2.getLastRow() + 1, 1, 1, 1);
rg1.copyTo(rg2, { contentsOnly: true });
var sh3 = ss.getSheetByName('Sheet3');
var sh4 = sh3.copyTo(ss).setName('Sheet4');
var cell = sh1.getRange("G2");
var v1G2 = cell.getValue();
sh4.setName(v1G2);
sh4.setTabColor(null);
var shts = ss.getSheets().map(sh => sh.getName()).sort().forEach((n, i) => {
ss.setActiveSheet(ss.getSheetByName(n));
ss.moveActiveSheet(i + 1)
});
}

RefreshImport function not working in Google Sheets

I tried to fill it with my sheet data, but that
var dataRange = sheet.getDataRange();
get an error. What should I do?
function RefreshImports() {
var lock = LockService.getScriptLock();
if (!lock.tryLock(5000)) return; // Wait up to 5s for previous refresh to end.
var id = "1r7TgCWXfjmcjufT0yz9qcFDlr482SdHDHlZYblXyAt0"; // [YOUR SPREADSHEET ID]
var ss = SpreadsheetApp.openById(id);
var sheet = ss.getSheetByName("crypto"); // sheet name
var dataRange = sheet.getDataRange();
var formulas = dataRange.getFormulas();
var content = "";
var now = new Date();
var time = now.getTime();
var re = /.*[^a-z0-9]import(?:xml|data|feed|html|range)\(.*/gi;
var re2 = /((\?|&)(update=[0-9]*))/gi;
var re3 = /(",)/gi;
for (var row=0; row<formulas.length; row++) {
for (var col=0; col<formulas[0].length; col++) {
content = formulas[row][col];
if (content != "") {
var match = content.search(re);
if (match !== -1 ) {
// import function is used in this cell
var updatedContent = content.toString().replace(re2,"$2update=" + time);
if (updatedContent == content) {
// No querystring exists yet in url
updatedContent = content.toString().replace(re3,"?update=" + time + "$1");
}
// Update url in formula with querystring param
sheet.getRange(row+1, col+1).setFormula(updatedContent);
}
}
}
}
// Done refresh; release the lock.
lock.releaseLock();
// Show last updated time on sheet somewhere
sheet.getRange(7,2).setValue("Rates were last updated at " + now.toLocaleTimeString())
}
I set up the trigger.
Not sure what you trying to do and you explanation leaves a lot to be desired.
So this is a simple way to put your formulas into a sheet named "Destination".
function RefreshImports() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("crypto");
const rg = sh.getDataRange();
const formulas = rg.getFormulas();
sh.getRange(1,1,formulas.length,formulas[0].length).setFormulas(formulas);
}

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 App Scripts: How do you copy a row to the next available row in a new tab depending on the value in a cell

I am trying to transfer a row (range A:AE) from sheet NSI to the next available row in Sheet1 if cell AE= 1.
My code doesn't seem to work, please could somebody help me?
Thank you!!
function myFunction() {
function copyRows() {
var sSheet = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet = sSheet.getSheetByName("NSI");
var lastRow = srcSheet.getLastRow();
for (var i = 2; i <= lastRow; i++) {
var srcRange = srcSheet.getRange("A" + i + ":AE" + i);
var cell = srcSheet.getRange("AE" + i);
var val = cell.getValue();
//sets the target sheet depending on the exam in column AE
if (val == "1") {
var tarSheet = sSheet.getSheetByName("Sheet1");
}
//insets the row in the correct target worksheet
var tarRow = tarSheet.getLastRow()+1;
tarSheet.insertRows(tarRow);
var tarRange = tarSheet.getRange("A" + (tarRow) + ":AE" + (tarRow));
srcRange.copyTo(tarRange);
}
};
}
function copyRows() {
var sSheet = SpreadsheetApp.getActive();
var srcSheet = sSheet.getSheetByName("NSI");
const vs = srcSheet.getRange(2, 1, srcSheet.getLastRow() - 1, 31).getDisplayValues();
var tarSheet = sSheet.getSheetByName("Sheet1");
vs.forEach(r => {
if (r[30] == "1") {
tarSheet.appendRow(r);
}
});
}

How to check particular value in google spreadsheet

I picked this code online and I am trying to check if the value in the column B is 'Done' then the value will be be copied otherwise not. Here is the code I am using:
copy sheet function below will copy the datat from source sheet to destination sheet but what I want that it will only pick the row if the col B value contains Done
function copySheet() {
var sourceSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Source");
var destSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Destination");
var columns_to_be_copied =['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U'];
var columns_to_be_pasted =['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U'];
for (column in columns_to_be_copied) {
var copy_range_string = columns_to_be_copied[column] + ':' + columns_to_be_copied[column];
var paste_range_string = columns_to_be_pasted[column] + ':' + columns_to_be_pasted[column];
var source = sourceSheet.getRange(copy_range_string);
var destination = destSheet.getRange(paste_range_string);
if(findInColumn('A','Done') !== -1) {
copyTo(source,destination );
}
}
}
function copyTo(source,destination) {
var sourceSheet = source.getSheet();
var destSheet = destination.getSheet();
var sourceData = source.getValues();
var dest = destSheet.getRange(
destination.getRow(), // Top row of destination
destination.getColumn(), // left col of destination
sourceData.length, // # rows in source
sourceData[0].length); // # cols in source (elements in first row)
dest.setValues(sourceData);
SpreadsheetApp.flush();
}
function findInColumn(column, data) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sprint");
var column = sheet.getRange(column + ":" + column); // like A:A
var values = column.getValues();
var row = 0;
while (values[row] && values[row][0] !== data) {
row++;
}
if (values[row][0] === data)
return row+1;
else
return -1;
}
As I am a fan of simple and easy to read (even after long time) solutions I would suggest the following script:
function main() {
var sourceSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Source');
var destinationSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Destination');
copyFromTo(sourceSheet, destinationSheet);
}
function copyFromTo(sourceSheet, destinationSheet) {
const ColumnB = 1; //Array indexing starts from 0
const FilterValue = 'Done';
var sourceValues = sourceSheet.getSheetValues(1, 1, 100, 28); //startRow, startColumn, numRows, numColumns
var filteredValues = sourceValues.filter(function(row) {
return row[ColumnB] === FilterValue;
});
destinationSheet.getRange(1, 1, filteredValues.length, filteredValues[0].length).setValues(filteredValues);
}
It's about the same function. I just modified it to facilitate my debugging process. It copies the columns from source to destination if Sprint has "Done" in that column.
function copySheet() {
var srcsh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Source");
var dessh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Destination");
var from = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U'];
var to = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U'];
for(var i=0;i<from.length;i++) {
var fromrg = from[i] + ':' + from[i];
var torg = to[i] + ':' + to[i];
var src = srcsh.getRange(fromrg);
var des = dessh.getRange(torg);
if(findInColumn(from[i],'Done')!== -1){
src.copyTo(des);
}
}
}
function findInColumn(col, data) {
var col=col || 'A';//This is here for initial testing so I could run the function without parameters.
var data=data || 'Done';
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sprint");
var rg = sh.getRange(col + "1:" + col + sh.getMaxRows());//MaxRows is kind of big but I was not sure what else you'd like to do and I dont know what your Sprint sheet looks like.
var vA = rg.getValues();
var rv=-1;
for(var i=0;i<vA.length;i++){
if(vA[i][0]==data){
rv=i+1;
break;
}
}
return rv;
}
I see that you changed the question a bit. This function looks in your sprint sheet as you show in your answer and copies from source to destination only those columns that have the word "Done" on any row of that column. But it checks every column in your "columns_to_be_copied" which I called "from". Originally, that's what your function was trying to do. So I just wanted to be clear what this function is doing. If it's not what you want then leave a comment and I'll delete it.