I have a Google Sheets file with 3 spreadsheets. Each of the first 2 contains numerous number data entries. All I want to do is change one cell value on the third (tt) if any data is changed on a different sheet. Looking at my incomplete onEdit() script, you will see I obviously don’t know what I’m doing. How to I change the value of cell ‘a5’ on third spreadsheet (tt) for any changes made anywhere on only the first two?
function onEdit(event)
{
var aa = event.SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Input-Expenses");
var ss = event.SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Input-Income-n-Assets");
var tt = event.SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Run Program");
var r = event.aa.getActiveRange('a1:r105');
var s = event.ss.getActiveRange('d1:q94');
var g = 0
tt.getRange('a5').setValue(g);
}
You need to refer to this article:
https://developers.google.com/apps-script/guides/triggers/
Find Edit trigger.
range A Range object, representing the cell or range of cells that
were edited.
Usage:
var editedRange = event.range;
var editedSheet = editedRange.getSheet();
if (editedSheet.getName() === 'Sheet1')
{
var targetSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2");
// do smth
}
This should do what you want
function onEdit(event) {
try {
var aName = event.range.getSheet().getName(); // Active sheet
if( ( aName === "Input-Expenses" ) || ( aName === "Input-Income-n-Assets" ) ) {
// You said anywhere on these 2 sheets and put in Run Program:A5
event.source.getSheetByName("Run Program").getRange("A5").setValue(0);
}
}
catch(err) {
SpreadsheetApp.getUi().alert(err);
}
}
Related
I am trying to accomplish 2 things with Google Sheets. I have a Main sheet with data and I would like to:
Create new sheet with the name based on a cell value in Column B (accomplished)
Copy the rows containing those values in B in that new sheet
Part 1 works fine with this script:
function onOpen() {
var menu = [{
name : "Add",
functionName : "newSheet"
}
];
SpreadsheetApp.getActiveSpreadsheet().addMenu("Sheet", menu);
}
function newSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var templateSheet = ss.getActiveSheet();
var sheet1 = ss.getSheetByName("Sheet1")
var getNames = sheet1.getRange("B2:B").getValues().filter(String).toString().split(",");
for (var i = 0; i < getNames.length; i++) {
var copy = ss.getSheetByName(getNames[i]);
if (copy) {
Logger.log("Sheet already exists");
} else {
templateSheet.copyTo(ss).setName(getNames[i]);
ss.setActiveSheet(ss.getSheetByName(getNames[i]));
ss.moveActiveSheet(ss.getNumSheets());
}
}
}
The problem is when new sheets are created it copies the content of the main sheet. I would like to have only the rows containing the value in Column B copied into the new sheet.
Instead of using copyTo you might use one of the insertSheet methods of Class Spreadsheet, then copy rows having the required value in column B into the new sheet.
The specific code to copy the rows depends on what really need to copy (values, displayed values, formulas, cells formatting, rich text cell content formatting, notes, data validation, conditional formatting)
Let say that you are only interested in passing the values, you could use something like the following in the getNames for loop:
var data = sheet1.getDataRange().getValues().filter(row => row[1] === getNames[i])
var newSheet = ss.insertSheet(getNames[i]);
if( data.length > 0 ) newSheet.getRange(1,1,data.length,data[0].length).setValues(data);
Related
insertSheet advanced options
check for existence of a sheet in google spreadsheets
You can just add one more function to remove redundant rows from any sheet. Something like this:
function main() {
var sheet = SpreadsheetApp.getActiveSheet()
remove_rows("aaa", sheet); // remove all rows, that contain 'aaa' in first column
}
function remove_rows(value, sheet) {
var data = sheet.getDataRange().getValues();
var new_data = data.filter(x => x[0].indexOf(value)>=0)
sheet.getDataRange().clearContent();
sheet.getRange(1,1,new_data.length,new_data[0].length).setValues(new_data);
}
I have the below spreadsheet that I would like to AutoFill the persons name. the issue is that there are blank rows between the names. Each name is in line with a sku2 and needs to be inline with all locations. there can be up to 10 blank rows (due to how many locations).
if I could loop this maybe
function LoopTillLr() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('A2').activate();
spreadsheet.getActiveRange().autoFillToNeighbor(SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);
spreadsheet.getCurrentCell().getNextDataCell(SpreadsheetApp.Direction.DOWN).activate();
};
Appreciate any help
If you only want to replicate the NAME values against variable LOCATION values then use this script:
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
var lastRow = ss.getDataRange().getLastRow();
for (var i = 1; i < lastRow+1; i++) {
if (ss.getRange(i,1).getValue() == "") {
var value = ss.getRange(i-1,1).getValue();
ss.getRange(i,1).setValue(value);
}
}
}
Ensure that A2 is not empty else the script will fail.
If it is a lot of records, you can create a function and run it. The following does this until the end of the sheet, so make sure to delete all the rows towards the end which you do not need or adjust the range in the 2nd row.
function autoFillDown(){
const range = SpreadsheetApp.getActiveSheet().getRange("A:A");
const rows = range.getValues();
let outputArray = [];
rows.forEach( row => {
// if it contains a name, leave it
if( row[0].length > 1){
outputArray.push( [row[0]] )
// otherwise replace it with the value above it
} else {
outputArray.push( [outputArray[outputArray.length-1]] );
}
});
range.setValues( outputArray );
}
Good morning everyone :),
I'm struggling withe a problem for some time and I was wondering that anyone can help me here.
I wrote some script that is copying and pasting rows from one sheet to another when Q column checkbox is TRUE. Please see code below :
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
if(ss.getActiveCell().getColumn() == 16 && ss.getActiveCell().getRow() > 1 && ss.getActiveCell().isChecked()) {
var source = ss.getRange("TRACKER!B2:N2");
var destSheet = ss.getSheetByName("ARCHIVE");
var destRange = destSheet.getRange(destSheet.getLastRow()+1,2);
source.copyTo(destRange,{contentsOnly: true});
source.clear();
}
}
My QQ is how to change last script input :
source.clear();
That instead of clearing it just delete whole row, and also how to change
var source = ss.getRange("TRACKER!B2:N2");
That B2:N2 will be change into B?:N? where "?" depending which row in column Q was selected.
Thank You in advance
Have a good day
Mariusz
When the onEdit() trigger fires,
Apps Script passes the function an event object as an argument,
typically called e. The event object contains information about the
context that caused the trigger to fire.
So you could change your script to:
function onEdit(e) {
var activeSheet = e.source.getActiveSheet(); // Assumes the active sheet is called 'TRACKER'
var activeCell = e.source.getActiveCell();
if ( activeCell.getColumn() == 17 && activeCell.getRow() > 1 && activeCell.isChecked() ) {
var source = activeSheet.getRange(activeCell.getRow(), 2, 1, 13); // Columns B through N
var destSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ARCHIVE");
var destRange = destSheet.getRange(destSheet.getLastRow() + 1, 2);
source.copyTo(destRange,{contentsOnly: true});
source.clearContent(); // To clear just the contents and not delete the row
}
}
Column Q = column 17.
This script assumes that the active sheet with the checkboxes is called 'TRACKER'
Ref docs for onEdit()
Ref docs for getting cells, ranges in spreadsheets and copying and clearing them.
Hello ADW and thank you for quick reply,
I have update the code like this :
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
if(ss.getActiveCell().getColumn() == 16 && ss.getActiveCell().getRow() > 1 && ss.getActiveCell().isChecked()) {
var source = ss.getRange("TRACKER!B" + ss.getActiveCell().getRow()+ ":N"+ss.getActiveCell().getRow());
var destSheet = ss.getSheetByName("ARCHIVE");
var destRange = destSheet.getRange(destSheet.getLastRow()+1,2);
source.copyTo(destRange,{contentsOnly: true});
ss.deleteRow(ss.getActiveCell().getRow());
}
}
and it seems to work fine now but nevertheless once again thank you for the code it surly help me to solve this query.
I'm new to Google Sheets Script and got stuck trying to do the following. I have 2 columns: C containing start timecode and D containing end timecode. A third column (F) contains the length of a film cue resulting from start timecode and end timecode. Since the timecode results from a script, the cells containing the result cannot be exported to another format. So I am trying to create a 4th column that will print the results from column F as values. I managed to write a little script that can do it. It looks like this:
function getRangeValuesEP01() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var range = ss.getSheetByName("EP01").getRange('F3:F100').activate();
var values = range.getValues();
return values;
};
The thing is, it does not execute automatically, when I edit any of the timecodes in C or D.
So I tried this:
function onEdit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet()
var sheetName = sheet.getName();
if ( sheetName == "EP02" || sheetName == "EP01" ) {
var range = sheetName.getRange('F3:F100').activate();
var r = sheetName.getActiveRange();
if (r.getColumn() == 4 ) {
var col = r.getColumn();
if ( col >= 3 && col <= 100 ) {
sheetName.getRange(r.getRow(),5);
var values = range.getValues();
}
}
}
}
It does not give me any errors, but it does not do anything either. It probably does not really make sense. As I said, I am new to those scripts. And it does not take into account that is has to look for editing in both columns C and D. Oh, or would it be enough to look at F, since that already updates its results when C or D are changed?
Maybe someone can push me into the right direction here?
Read comments:
function myonEdit(e)
{
var sheet=e.source.getActiveSpreadsheet();
var sheetName=sheet.getName();
if(sheetName=="EP02" || sheetName=="EP01")
{
var r=sheet.getRange('F3:F100');//I made changes up to this point but the next line makes no sense so rethink it in light of changes
if (r.getColumn()==4)//This line doesn't make any sense because you set range to F3:F100 F is column 6 so it will never be 4
{
var col= r.getColumn();
if ( col >= 3 && col <= 100 )
{
sheetName.getRange(r.getRow(),5);
var values = range.getValues();
}
}
}
}
I’m writing a custom function in Google Apps Script that, if a certain other cell contains a number, uses the value of that cell and several other cells to calculate a result. Otherwise, if that certain other cell does not contain a number, the function should just return an empty string so that the active cell appears blank.
I was able to come up with a working function to do this, but in order to protect sensitive information, I’m not going to copy it here. Instead, here’s an example function that accomplishes the same thing:
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
var rowNum = sheet.getActiveCell().getRow();
var rowVals = sheet.getRange(rowNum, 1, 1, 15).getValues();
var fVal = rowVals[0][5];
if (fVal == "" || isNaN(fVal)) {
return ""; //leave cell blank if column F doesn't contain a number
}
var aVal = rowVals[0][0];
var bVal = rowVals[0][1];
var cVal = rowVals[0][2];
var gVal = rowVals[0][6];
return ((gVal * fVal) + aVal + bVal + cVal);
}
However, in an effort to speed it up (and also some other reasons that would be complicated to try to explain here, so you'll have to just trust me), I want to have the custom function set the value of the cell to be a formula instead of doing the calculating itself. It doesn’t work to just put the formula in the cell in the first place because then it still calculates/shows a result even if column F doesn’t contain a number.
Here’s what I’ve tried so far:
function myFunction2() {
var sheet = SpreadsheetApp.getActiveSheet();
var rowNum = sheet.getActiveCell().getRow();
var fVal = sheet.getRange(rowNum, 6).getValue();
if (fVal == "" || isNaN(fVal)) {
return ""; //leave cell blank if column F doesn't contain a number
}
var formula = '=SUM((G2*F2)+A2+B2+C2)';
return formula;
}
^This just makes the cell display the string “=SUM((G2*F2)+A2+B2+C2)”.
So I then tried using setFormula on the active cell:
function myFunction3() {
var sheet = SpreadsheetApp.getActiveSheet();
var cell = sheet.getActiveCell();
var rowNum = cell.getRow();
var fVal = sheet.getRange(rowNum, 6).getValue();
if (fVal == "" || isNaN(fVal)) {
return ""; //leave cell blank if column F doesn't contain a number
}
cell.setFormula('=SUM((G2*F2)+A2+B2+C2)');
}
^which, when I called the function in a cell, returned an error saying “You do not have permission to call setFormula”. The same thing happened when I tried getting the a1 notation of the active cell and then using getRange(a1Notation).setFormula('=SUM((G2*F2)+A2+B2+C2)') instead of calling setFormula directly on the active cell.
Anybody know if there's a way around that permission error? or have any other ideas for how to accomplish this?
The permission error is because of restrictions on what user defined functions can do. You can, however, do this with onEdit like this:
function onEdit(e) {
var ss=SpreadsheetApp.getActiveSpreadsheet()
var s=ss.getActiveSheet();
var col = e.range.getColumn();
var rowNum = e.range.getRow();
if(col==6){
var fVal = s.getRange(rowNum,col,1, 1).getValue()
}
if (fVal == "" || isNaN(fVal)) {
return
}
else{
s.getRange(rowNum,col,1, 1).setFormula('=SUM((G2*F2)+A2+B2+C2)');
}}
I actually ended up figuring out a way to accomplish what I wanted using the built-in IF function, so that's what I did.