Combine multiple Google sheet scripts - google-apps-script

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

Related

Copy Row from one Sheet to another sheet which is linked in the row

I have previously been able to copy rows from one Spreadsheet to another, however what I am trying to do now is copy a row to a specific spreadsheet that is linked on the same row and I can't seem to work it out.
I have around 500 rows of names with data (I cannot share a sheet as my firms Google does not allow for sharing externally but I have a screenshot of dummy data below). I used a formula to find the Unique names and then created a Google Sheet for each person and linked the Sheet back to the master data.
Master Data Sheet (tab is called Sheet1)
I am looking for a script that will work through the sheet, copying the rows to the link that is on the same row but I just can't figure it out - the following script does not work but I am at a loss so any help would be appreciated.
Apologies if I haven't explained myself very well!!
function copyTo(){
var sSheet = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet = sSheet.getSheetByName("Sheet1");
var data = srcSheet.getDataRange().getValues();
for(var i = 1; i < data.length; i++) {
var row = data[i];
var link = row[3];
var id = row[4];
var complete = row[5];
var COMPLETE = "Complete"
if(link !== "" && complete !== "Complete"){
var srcRange = srcSheet.getRange("A" + i + ":C" + i);
var linkID = id.toString()
var tarSS = DriveApp.getFileById(linkID);
var tarSheet = tarSS.getSheetbyName("Sheet1");
var tarRow = tarSheet.getLastRow();
//tarSheet.insertRowAfter(tarRow);
var tarRange = tarSheet.getRange("A" + (tarRow+1) + ":C" + (tarRow+1));
srcRange.copyTo(tarRange);
srcSheet.getRange(i+1,6).setValue(COMPLETE)
}
}};
Try this:
function copyTo() {
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName("Sheet1");
var vs = sh.getDataRange().getValues();
for (var i = 1; i < vs.length; i++) {
var row = vs[i];
var link = row[3];
var id = row[4];
var complete = row[5];
var COMPLETE = "Complete"
if (link !== "" && complete !== "Complete") {
var rg = sh.getRange("A" + i + ":C" + i);
var linkID = id.toString()
var tarSS = SpreadsheetApp.openById(linkID);
var tarSheet = tarSS.getSheetbyName("Sheet1");
var tarRow = tarSheet.getLastRow();
var tarRange = tarSheet.getRange("A" + (tarRow + 1) + ":C" + (tarRow + 1));
rg.copyTo(tarRange);
sh.getRange(i + 1, 6).setValue(COMPLETE)
}
}
};
As much as I understand you question here is the script which will work for you exactly you want .
This will copy data from sheet you want and then create a new spreadsheet and paste into that sheet then link will show of this in same sheet from data copied
Let me know how this worked .
Code.gs
const sendDataToSheet = () => {
const ss = SpreadsheetApp.getActiveSpreadsheet()
const ws = ss.getSheetByName(''paste here your sheet name'')
const newSheet = SpreadsheetApp.create("give new sheet name here")
ws.copyTo(newSheet).setName("Copied Data")
const sheetURL = newSheet.getUrl()
ws.insertRowBefore(1)
ws.getRange(1,1).setValue(sheetURL)
}

Google sheets : remove data from multiple columns

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)?

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

Copy paste if Date = Today Google Sheets API

I am new to google script (and Javascript in general) and am trying to create a "Macro" which loops through a large table of data (Titled "Form response 1"), searches each row to see if the data in the 'To-arrive-date" column matches todays date. If the dates match, I want to copy-paste it into another sheet titled "Email". Below is the script I have written so far, but I keep getting an error stating that an unexpected "Var" is on line 15. However, I thought this var needed to be there for the variable "SrcRange"? Any help would be wonderful, thank you.
var sSheet = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet = sSheet.getSheetByName("Form Responses 1");
var tarSheet = sSheet.getSheetByName("Email");
var lastRow = srcSheet.getLastRow();
var Tsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Form Responses 1");
var date = new Date();
Tsheet.getRange(2, 11).setValue(date);
for (var i = 2; i <= lastRow; i++) {
var cell = srcSheet.getRange("C" + i);
var val = cell.getValue();
if (val == SrcSheet.getRange(2, 11).getValues()
var srcRange = srcSheet.getRange("A" + i + ":F" + i);
var tarRow = tarSheet.getLastRow();
tarSheet.insertRowAfter(tarRow);
var tarRange = tarSheet.getRange("A" + (tarRow+1) + ":F" + (tarRow+1));
srcRange.copyTo(tarRange);
}
}
-Evan
Issue
Your IF statement inside the loop is incomplete. It lacks closing parenthesis as well as opening curly brace. I also noticed and commented out unnecessary codes and corrected a few specifically with regards to new Date() method.
Solution
Please see modified code below. Note that I only modified a few part of the code to make it work. I haven't done any optimization(if applicable). Also, this code is working fully on my end.
function myFunction() {
var sSheet = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet = sSheet.getSheetByName("Form Responses 1");
var tarSheet = sSheet.getSheetByName("Email");
var lastRow = srcSheet.getLastRow();
var tSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Form Responses 1");
var date = new Date().toDateString();
tSheet.getRange(2, 11).setValue(date);
for (var i = 2; i <= lastRow; i++) {
var cell = srcSheet.getRange("C" + i);
var val = new Date(cell.getValue().toString()).toDateString();
Logger.log(val+" "+date)
if (val == date){
Logger.log("test")
var srcRange = srcSheet.getRange("A" + i + ":F" + i);
var tarRow = tarSheet.getLastRow();
// tarSheet.insertRowAfter(tarRow);
var tarRange = tarSheet.getRange("A" + (tarRow+1) + ":F" + (tarRow+1));
srcRange.copyTo(tarRange);
}
}
}

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