My script works, for the first sheet of my sample spreadsheet. But it does not work for other sheets in my workbook, even though Logger.log(sheet.getName()) successfully fetches the name of the sheet that is currently being edited. It's a pretty simple problem, I just can't figure out why it only works for one of my sheets.
function onEdit (e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet()
Logger.log(sheet.getName())
if (e.range.getA1Notation() === 'C19' && e.value == 'TRUE') {
sheet.getRange('K2:K89').setNumberFormat("0.00oz")
}
else if (e.range.getA1Notation() === 'C19' && e.value == 'FALSE'){
sheet.getRange('K2:K89').setNumberFormat("0.00g")
}
In 'Loadout Picker' C19 values are TRUE/FALSE
In 'Copy of Loadout Picker 2.0' C19 values are 1/0
In the script in your if loops you have C19 == 'FALSE'/'TRUE'
That's the problem. Just remake a new tickbox at cell C19 in 'Copy of Loadout Picker 2.0' and it will reset the C19 values to TRUE/FALSE from 1/0. (Don't forget to rejoin the spreadsheet or just switch between the sheets so the code starts to work.)
That's also why onEdit() worked for the first sheet and not second.
Related
I am trying to figure out a way to "automate" a task in google sheets. I have a data model that lists all the data on one sheet of all the 'hit percentages' of sports props. The data changes as games complete. I'd like to have check boxes(or something similar) next to the rows that when it's checked it copies that row and then adds it into a sheet called 'Logs" after the last row.
I put this sheet together as an example:
https://docs.google.com/spreadsheets/d/1KocfnKXK1sPmBr3uQfcn8dC6MYV0JUWDz5Ql3AgTMEI/edit?usp=sharing
I believe your goal is as follows.
When you checked the checkbox of column "B" of "Changing Data" sheet, you want to copy the row to the next row of the last row of "Log" sheet.
In this case, how about the following modification? In this modification, in order to check whether the checkbox is checked, the simple trigger of OnEdit is used.
Sample script:
Please copy and paste the following script to the script editor of Spreadsheet and save the script. When you use this script, please check the checkbox of column "B" of "Changing Data" sheet. By this, the script is automatically run by the OnEdit trigger.
function onEdit(e) {
const srcSheetName = "Changing Data"; // This is from your sample Spreadsheet.
const dstSheetName = "Log"; // This is from your sample Spreadsheet.
const { range, source } = e;
const sheet = range.getSheet();
if (sheet.getSheetName() != srcSheetName || range.columnStart != 2 || !range.isChecked()) return;
const dstSheet = source.getSheetByName(dstSheetName);
range.offset(0, -1, 1, 2).copyTo(dstSheet.getRange(dstSheet.getLastRow() + 1, 1));
}
Reference:
Simple Triggers
Copy Row To Log Sheet
function onEdit(e) {
//e.source.toast("Entry");
const sh = e.range.getSheet();
if(sh.getName() == "Sheet0" && e.range.columnStart == 7 && e.range.rowStart > 1 && e.value == "TRUE") {
//e.source.toast("Gate1");
e.source.toast("Gate1");
const lsh = e.source.getSheetByName("Log");
const vs = sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getValues();
lsh.getRange(lsh.getLastRow() + 1, 1,vs.length,vs[0].length).setValues(vs);
}
}
Sheet0:
Alternative Solution
You can try this another implementation using appendRow() & getValue() methods.
This sample will only run the onEdit() function when column B check-boxes are selected on the Changing Data sheet. The function will only copy the text on Column A row that is adjacent to the selected checkbox.
Script
function onEdit(e) {
e.source.getActiveSheet().getName() == 'Changing Data' && e.range.getColumn() == 2 && e.value == "TRUE" ? e.source.getSheetByName('Log').appendRow([e.source.getSheetByName('Changing Data').getRange('A' + e.range.getRow()).getValue()]) : _ ;
}
Alternate Script if you want to include check-boxes to be also copied:
function onEdit(e) {
e.source.getActiveSheet().getName() == 'Changing Data' && e.range.getColumn() == 2 && e.value == "TRUE" ?
(e.source.getSheetByName('Log').appendRow([e.source.getSheetByName('Changing Data').getRange('A' + e.range.getRow()).getValue()]) ?
(e.source.getSheetByName('Changing Data').getRange('B' + e.range.getRow()).copyTo(e.source.getSheetByName('Log').getRange('B' + e.source.getSheetByName('Log').getLastRow()))) : _) : _;
}
Demo
Changing Data sheet
Logs sheet
I have script for Google Sheets that I collected on interwebs and got some help here. No I have 2 onEdit in conflict. I overcome that by creating script Trigger for onEdit2. It works but I don't think it is the best solution. Could you help get those two separated onEdit with if functions into one, please?
//Dependent Dropdown list
function onEdit(e){ // Function that runs when we edit a value in the table.
masterSelector(master1,master2,master3,master4);
var activeCell = e.range; // It returns the coordinate of the cell that we just edited.
var val = activeCell.getValue(); // Returns the value entered in the column we just edited.
var r = activeCell.getRow(); // returns the row number of the cell we edit.
var c = activeCell.getColumn(); // returns the column number of the cell we edit.
var wsName = activeCell.getSheet().getName();
if (wsName === masterWsName && c === firstLevelColumn && r > masterNumberOfHeaderRows) { // the if delimits the section sensitive to modification and action of the onEdit.
applyFirstLevelValidation(val,r);
} else if (wsName === masterWsName && c === secondLevelColumn && r > masterNumberOfHeaderRows){
applySecondLevelValidation(val,r);
}
} // end of onEdit
// addRow by checkboxes
function onEdit2(e) {
masterSelector(master1,master2,master3,master4);
//IF the cell that was edited was in column 4 = D and therefore a checkbox AND if the cell edited was checked (not unchecked):
if (e.range.columnStart === 4 && e.range.getValue() === true) {
var sheet = SpreadsheetApp.getActiveSheet(),
row = sheet.getActiveCell()
.getRow(),
//(active row, from column, numRows, numColumns)
rangeToCopy = sheet.getRange(row, 1, 1, 30);
sheet.insertRowAfter(row);
rangeToCopy.copyTo(sheet.getRange(row + 1, 1));
//Reset checked boxes in column 4
sheet.getRange(row,4,2,1).setValue(false);
}
}
Whole script is here, if needed.
A script cannot contain two functions with the same name. Rename your first onEdit function to onEdit1 (actually it will be better to assign a descriptive name) and the second function as onEdit2, then put them both in one function named onEdit and pass the parameter e to both of them:
function onEdit(e){
onEdit1(e);
onEdit2(e);
}
Related:
Two OnEdit functions not working together
Best Practices for Multiple OnEdit Functions
How to run multiple onEdit functions in the same google script (google sheets)?
Bracketing multiple onEdit functions
In Google Apps Script for Google Sheets, I want to use a barcode scanner to input new data into a cell. If this new data matches what I am expecting, I want another cell to then be activated so I can continue to input data. This is being used to create an inventory, and the initial data being input (and what is being checked by the code) will be the name of the person using the scanner at that time. Here's what I have so far:
var ss = SpreadsheetApp.getActive()
var sheet1 = SpreadsheetApp.getActive().getSheetByName("Sheet1")
//Set active cell to A2 (cell below Name header) when file is opened.
function onOpen() {
sheet1.getRange('A2').activate();
}
function onEdit(e) {
if (e.range.getA1Notation() === 'A2') {
var nameval = sheet1.getActiveCell.getValue();
if (nameval == 'Alpha' || nameval == 'Beta') {
sheet1.getRange('D7').activate();
}
else {
sheet1.getRange('F1').activate();
}}}
Unfortunately this does not seem to do anything - The value in the cell is accepted but the new cell did not activate when either of the activation cases were input.
Modification points:
In your script, sheet1 is not declaread.
getActiveCell of sheet1.getActiveCell.getValue() is not run as the method.
I thought that nameval == 'Alpha' || nameval == 'Beta' might be written by includes.
When these points are reflected in your script, it becomes as follows.
Modified script:
function onEdit(e) {
var range = e.range;
var sheet1 = range.getSheet();
if (range.getA1Notation() === 'A2') {
var active = ['Alpha', 'Beta'].includes(range.getValue()) ? "D7" : "F1";
sheet1.getRange(active).activate();
}
}
In this modified script, when a value of 'Alpha' or 'Beta' is put to the cell "A2", the cell "D7" is activated. When a value except for 'Alpha' and 'Beta' is put to the cell "A2", the cell "F1" is activated.
Note:
This script is automatically run by the OnEdit simple trigger. So, when you directly run this script with the script editor, an error occurs. Please be careful about this.
References:
Simple Triggers
includes()
I want to create a script that will display the cell address of the active cell in A1, however, this is proving difficult because I can't even get the onSelectionChange example on the Google Apps Script guide to work. Whenever I run it, the error I get is TypeError: Cannot read property 'range' of undefined.
This is the code:
/**
* The event handler triggered when the selection changes in the spreadsheet.
* #param {Event} e The onSelectionChange event.
*/
function onSelectionChange(e) {
// Set background to red if a single empty cell is selected.
var range = e.range;
if(range.getNumRows() === 1
&& range.getNumColumns() === 1
&& range.getCell(1, 1).getValue() === "") {
range.setBackground("red");
}
}
About your error message of TypeError: Cannot read property 'range' of undefined, I thought that you might have directly run the function of onSelectionChange with the script editor. If it's so, such error occurs because the event object e is not given.
onSelectionChange is used as the simple trigger. In this case, when you want to retrieve the cell address of the active cell with onSelectionChange trigger, please select the cell on Google Spreadsheet. By this, the script is run by the onSelectionChange trigger.
Sample script:
For example, when the onSelectionChange trigger is run by selecting a cell, the sample script that the cell address is put to the cell as the A1Notation is as follows. When you use this script, please copy and paste the following script to the script editor of Spreadsheet and save it. And, please select a cell on the active Spreadsheet.
function onSelectionChange(e) {
var range = e.range;
range.setValue(range.getA1Notation());
}
Result:
When above script is used, the following result is obtained. You can see that in order to run the script, the cell is selected.
Note:
Even when you selected a cell, when the sample script is not run, please close the Spreadsheet and open the Spreadsheet again. In my environment, I confirmed that by this, the onSelectionChange trigger worked.
Reference:
onSelectionChange(e)
Added 1:
About the following your replying,
Thanks. This works and so did the red cell Google example. Although I did have to close the workbook and reopen it to get it to work. How can I set the range to a fixed cell so the active cell address only appears there?
When you want to run the script for only the specific range, how about the following sample script? From your replying, I used your script for this.
Sample script:
function onSelectionChange(e) {
var ranges = ["A2:B5", "D2:E5"]; // Please set the range you want to run the script.
var range = e.range;
var sheet = range.getSheet();
var check = ranges.some(r => {
var rng = sheet.getRange(r);
var rowStart = rng.getRow();
var rowEnd = rowStart + rng.getNumRows();
var colStart = rng.getColumn();
var colEnd = colStart + rng.getNumColumns();
return (range.rowStart >= rowStart && range.rowEnd < rowEnd && range.columnStart >= colStart && range.columnEnd < colEnd);
});
if (check) {
range.setBackground("red");
}
}
In this script, only when the cell in the range of var ranges = ["A2:B5", "D2:E5"] is selected, range.setBackground("red") is run. So please modify ["A2:B5", "D2:E5"] for your actual situation.
If you want to also check the sheet name, please modify above script as follows. In this case, when the cell in the ranges ["A2:B5", "D2:E5"] of the sheet ["Sheet2", "Sheet3"] is selected, range.setBackground("red") is run.
function onSelectionChange(e) {
var sheetNames = ["Sheet2", "Sheet3"]; // Please set the sheet names.
var ranges = ["A2:B5", "D2:E5"]; // Please set the range you want to run the script.
var range = e.range;
var sheet = range.getSheet();
if (!sheetNames.includes(sheet.getSheetName())) return;
var check = ranges.some(r => {
var rng = sheet.getRange(r);
var rowStart = rng.getRow();
var rowEnd = rowStart + rng.getNumRows();
var colStart = rng.getColumn();
var colEnd = colStart + rng.getNumColumns();
return (range.rowStart >= rowStart && range.rowEnd < rowEnd && range.columnStart >= colStart && range.columnEnd < colEnd);
});
if (check) {
range.setBackground("red");
}
}
Added 2:
About the following your replying,
No, sorry. I meant how can I make the active cell address appear in A1. If I click on cell G5, for example, 'G5' appears in A1.
In that case, how about the following sample script?
Sample script:
function onSelectionChange(e) {
var range = e.range;
range.getSheet().getRange("A1").setValue(range.getA1Notation());
}
I am trying to create a script on Google Sheets to receive a message alert whenever the value of the B10 cell increases. Something like this:
Static oldVal As Variant
oldVal = Me.Range("B10").Value
If Me.Range("B10").Value > oldVal Then
Browser.msgBox('hello world');
End If
There is a way?
Other than your syntax being way off (Apps Script is based on JavaScript), yes, you can do that using a couple different mechanisms.
Use the onEdit(e) simple trigger to watch the sheet.
The e object has an oldValue and a value key you can compare directly. You can also test for a specific cell reference using the range parameter. The following tests for cell B10, specifically:
function onEdit(e) {
if (e.range.getA1Notation() == 'B10' && e.value > e.oldValue) {
Browser.msgBox("you increased the value")
}
}
Taking it even farther, you can specify a sheet within a Spreadsheet to test before the script will run.
function onEdit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
if (e.range.getA1Notation() == 'B10' && e.range.getSheet().getName() == 'Página1' && e.value > e.oldValue) {
Browser.msgBox("you increased the value")
}
}
If the cell is not in the specified sheet or range,, nothing happens.
Watching a formula cell is a little more complex, but it will work. There are two methods in Apps Script. getValue() returns the value displayed in the cell, even if it's calculated by a formula. .getFormula() gets the cell's calculating formula. So, yes, this will work with simply calling .getValue() on the range.
The major difference is that you have to watch the formula cell because it is not directly edited by the user. In other words, the event object will not trigger if the cell value is calculated by a formula. Including it is easy:
function onEdit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var formulaRange = e.range.getSheet().getRange("B4");
if (e.range.getA1Notation() == 'B10' || formulaRange && (e.range.getSheet().getName() == 'Página1' && e.value > e.oldValue) {
Browser.msgBox("you increased the value")
}
}
More on Apps Script event objects in the documentation.