This is the script that I am using currently. I want it to apply to all sheets in my document automatically. Please help. The following is the code.
/**
* Creates a Date Stamp if a column is edited.
*/
//CORE VARIABLES
// The column you want to check if something is entered.
var COLUMNTOCHECK = 1;
// Where you want the date time stamp offset from the input location. [row, column]
var DATETIMELOCATION = [0,1];
// Sheet you are working on
var SHEETNAME = '46'
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//checks that we're on the correct sheet.
if( sheet.getSheetName() == SHEETNAME ) {
var selectedCell = ss.getActiveCell();
//checks the column to ensure it is on the one we want to cause the date to appear.
if( selectedCell.getColumn() == COLUMNTOCHECK) {
var dateTimeCell = selectedCell.offset(DATETIMELOCATION[0],DATETIMELOCATION[1]);
dateTimeCell.setValue(new Date());
}
}
}
I want the script to execute on every sheet so that whenever I add a new sheet the script runs automatically and helps me add a time stamp to column two when I add a value to column 1.
Please help.
I am a complete noob here and as such some detailed explanation will help me immensely.
Basically, just remove the if statement and the code will apply to EVERY sheet.
In the answer given below, I've also used some of the objects returned by the onEdit trigger.
/**
* Creates a Date Stamp if a column is edited.
*/
//CORE VARIABLE
// The column you want to check if something is entered.
var COLUMNTOCHECK = 1;
function onEdit(e) {
var sh = e.range.getSheet();
if (e.range.columnStart == COLUMNTOCHECK){
// edited the right column do something
var targetcell = sh.getRange(e.range.rowStart,2);
targetcell.setValue(new Date());
}
else {
// do nothing
}
}
Related
I have been using a script in my google sheet that I found here:
copy data from one sheet to another in google app script and append a row, one small issue
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Copy");
var pasteSheet = ss.getSheetByName("Paste");
// get source range
var source = copySheet.getRange(2,2,12,2);
// get destination range
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,2,12,2);
// copy values to destination range
source.copyTo(destination);
// clear source values
source.clearContent();
}
When I am running it now it gives me an error:
The coordinates of the target range are outside the dimensions of
the sheet.
which wasn't coming up before. Does anyone have an idea why it is doing this?
Issue:
The error is in this line:
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,2,12,2);
pasteSheet.getLastRow() returns a row number which is at the very bottom of your sheet. Then you consider 12 rows range but the pasteSheet does not have 12 rows after the last row with content.
Solutions:
Add more rows in the pasteSheet:
or you can use insertRowsAfter:
pasteSheet.insertRowsAfter(pasteSheet.getLastRow(), 12)
Code snippet:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Copy");
var pasteSheet = ss.getSheetByName("Paste");
// get source range
var source = copySheet.getRange(2,2,12,2);
// insert rows to make sure you have enough space
pasteSheet.insertRowsAfter(pasteSheet.getLastRow(), 12)
// get destination range
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,2,12,2);
// copy values to destination range
source.copyTo(destination);
// clear source values
source.clearContent();
}
new to using javascript in Google Sheets. I am trying to create a sheet that automatically calculates what business partners will receive based upon their dynamic split percentage and the incoming money. The percentage comes from one cell, but each payment made to the partners will be entered in a column. Here's what I have so far:
/**
* Creates a Date Stamp if a column is edited.
* Also performs dynamic split calculations
*/
//CORE VARIABLES
// The column you want to check if something is entered.
var COLUMNTOCHECK = 13;
// Where you want the date time stamp offset from the input location. [row, column]
var DATETIMELOCATION = [0,-1];
// Where the calculations will be performed for the Partners.
var PARTNERONELOCATION = [0, 1];
var PARTNERTWOLOCATION = [0, 2];
var PARTNERTHREELOCATION = [0, 3];
// Sheet you are working on
var SHEETNAME1 = 'Sheet1'
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var partnerOnePercent = sheet.getRange("G2").getValue();
var partnerOnePaySource = sheet.getRange("M2").getValue();
var partnerTwoPercent = sheet.getRange("G3").getValue();
var partnerTwoPaySource = sheet.getRange("M2").getValue();
var partnerThreePercent = sheet.getRange("G4").getValue();
var partnerThreePaySource = sheet.getRange("M2").getValue();
//checks that we're on the correct sheet.
if(sheet.getSheetName() == SHEETNAME1 ) {
var selectedCell = ss.getActiveCell();
//checks the column to ensure it is on the one we want to cause the date and calculations to appear.
if( selectedCell.getColumn() == COLUMNTOCHECK) {
var dateTimeCell = selectedCell.offset(DATETIMELOCATION[0],DATETIMELOCATION[1]);
dateTimeCell.setValue(new Date());
var partnerOneCell = selectedCell.offset(PARTNERONELOCATION[0],PARTNERONELOCATION[1]);
partnerOneCell.setValue((partnerOnePercent/100)*partnerOnePaySource);
var partnerTwoCell = selectedCell.offset(PARTNERTWOLOCATION[0],PARTNERTWOLOCATION[1]);
partnerTwoCell.setValue((partnerTwoPercent/100)*partnerTwoPaySource);
var partnerThreeCell = selectedCell.offset(PARTNERTHREELOCATION[0],PARTNERTHREELOCATION[1]);
partnerThreeCell.setValue((partnerThreePercent/100)*partnerThreePaySource);
}
}
}
The thing I would like it to do is when I enter a payment into the column (column 13), Is for the payment to be split into the partner location cells (var partnerOneCell, var partnerTwoCell, var partnerThreeCell) that are offset from the cell that the payment amount is typed in, and I only want it to be calculated by the percentages as they are at the moment the payment amount is entered. Any help would be appreciated.
Right now it is only calculating based upon cell M2 (row 2, column 13). I want it to be able to calculate based upon the amount I enter in any cell within that column, and only the cell I am currently updating. I think that this has something to do with getActiveRange or something, but I'm not familiar enough with these methods.
Edit: Upon testing, it also seems that row 3 column 14 is reflecting a calculation of partnerOnePaySource*partnerOnePercent with PaySource coming from row 3 column 13 (M3), though I'm not sure why.
Alright everyone, after reading over my code, I realized how I could use the getActiveCell method within the PaySource variables.
var partnerOnePercent = sheet.getRange("G2").getValue();
var partnerOnePaySource = ss.getActiveCell().getValue();
var partnerTwoPercent = sheet.getRange("G3").getValue();
var partnerTwoPaySource = ss.getActiveCell().getValue();
var partnerThreePercent = sheet.getRange("G4").getValue();
var partnerThreePaySource = ss.getActiveCell().getValue();
With this I was able to fix my problem and it now works.
I have designed a google spreadsheet to help improve efficiency of material flow. I want to automatically sort the data by 2 different columns to prioritize critical parts that need to be received first once the entire row of data is entered. The problem I am having is that the data is sorting as soon as you enter one of the columns I am calling to sort but the columns I want to sort are not the last column of that row of data that needs to be entered. I am trying to use an if statement to not execute the sort until the last column has been entered else throw an error statement that says you must enter data in this column to proceed. Logically, the code makes sense to me but I have only an adequate understanding of computer language. I keep receiving an error in line 10 that the range is not found. I believe my error is the syntax in trying to call the last column. Any help would be greatly appreciated
**function autosort(){
// Variable Declaration
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var NewsheetName = SpreadsheetApp.getActiveSheet().getName();
var sheetName = sheet.getSheetByName(NewsheetName);
var lastCol = sheetName.getLastColumn();
var lastColBlank = SpreadsheetApp.getActiveSheet().getRange(lastCol).isBlank()
// Find range to sort
var range = sheetName.getRange("A2:G");
// Sorting algorithm
if (lastColBlank == false ){
range.sort([6,5]);
}
else {
throw ("error: If trailer # is unavailable, please enter N/A");
}
}**
Try this code:
function onEdit() {
var sh = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var editedCell = sh.getActiveRange().getColumnIndex();
if(editedCell == 2) {
var range = sh.getRange("A2:B10");
var blank = range.isBlank()
var values = range.getValues();
Logger.log(values)
for (var i = 0; i<values.length; i++) {
//values.length returns 11 for eleven items
// values[10][0] would be the 11th row 1st column
Logger.log(values[i][1])
if (values[i][0] == "" || values[i][1] == "") {
//throw new Error("error: If trailer # is unavailable, please enter N/A");
var ui = SpreadsheetApp.getUi();
var response = ui.alert('If trailer # is unavailable, please enter N/A');
}else{
range.sort({column: 2});
}
}
}
}
If you'll look into the code, the sort depends on the second column to be edited. Then, will check the range if the is still a blanked cell.
Just apply your additional code to meet your goal and I think that will work.
Hope this helps.
Goal: I'm trying to create a behavior tracker for four classes in Google Spreadsheets. The tracker has nine sheets: Class7A, Class7B, Class8A, Class8B, and Mon-Fri summary sheets. The goal was for each ClassXX sheet to have behavior tracking information for an entire week, but for the default view to show only the current day's information.
Attempts: During initial workup (with only the Class7A sheet created), I got this to work using a modification of the script found here (Thank you Jacob Jan Tuinstra!): Optimize Google Script for Hiding Columns
I modified it to check the value in the third row of each column (which held a 1 for Monday, 2 for Tuesday, etc), and if it did not match the numerical equivalent for the day of the week (var d = new Date(); var n = d.getDay();), then it would hide that column. This process was somewhat slow - I'm assuming because of the iterating through each column - but it worked.
Quite excited, I went ahead and added the rest of the sheets, and tried again - but the code as written, seems to affect only the current sheet. I tried modifying it by replacing var sheet = ss.getSheets()[0]; with for script that iterated through the columns, until i>4 (I've since lost that piece of code), with no luck.
Deciding to go back and try adapting the original version of the script to instead explicitly run multiple times for each named sheet, I found the that script no longer seems to work at all. I get various version of "cannot find XX function in sheet" or "cannot find XX function in Range."
Source: A shared version (with student info scrubbed) can be found here: https://docs.google.com/spreadsheets/d/1OMq4a4_Gh_xyNk_IRy-mwJn5Hq36RXmdAzTzx7dGii0/edit?usp=sharing (editing is on).
Stretch Goal: Ultimately, I need to get this to reliably show only the current day's columns (either through preset ranges (same for each sheet), or the 1-5 values), and I need it to do so for all four ClassXX sheets, but not the summary pages (and preferably more quickly than the iterations). If necessary, I can remove the summary pages and set them up externally, but that's not my first preference. I would deeply appreciate any help with this; so far my attempts have seemed to only take me backwards.
Thanks!
Current code:
function onOpen() {
// get active spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
// create menu
var menu = [
{name: "Show Today Only", functionName: "hideColumn"},
{name: "Show All Days", functionName: "showColumn"},
{name: "Clear Week - WARNING will delete all data", functionName: "clearWeek"}
];
// add to menu
ss.addMenu("Show Days", menu);
}
var d = new Date();
var n = d.getDay();
function hideColumn() {
// get active spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
// get first sheet
var sheet = ss.getSheets()[0];
// get data
var data = sheet.getDataRange();
// get number of columns
var lastCol = data.getLastColumn()+1;
Logger.log(lastCol);
// itterate through columns
for(var i=1; i<lastCol; i++) {
if(data.getCell(2, i).getValue() != n) {
sheet.hideColumns(i);
}
}
}
function showColumn() {
// get active spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
// get first sheet
var sheet = ss.getSheets()[0];
// get data
var data = sheet.getDataRange();
// get number of columns
var lastCol = data.getLastColumn();
// show all columns
sheet.showColumns(1, lastCol);
}
I cannot recreate the problem of the script not working at all, it's working fine for Class7A so that part is working fine.
So let's look at the two other problems:
Applying this to all Sheets
Speeding up the script
First let's create some globals we use in both functions
var d = new Date();
var n = d.getDay();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetNames = ss.getSheets().map(function(sheet) {return sheet.getName();});
var classSheets = sheetNames.filter(function(sheetName) {return sheetName.match("Class")});
Now we can iterate over classSheets and get the sheet by name and hide columns in each.
However hiding each individual column is very slow.
The sheet is built very structured, every week has 12 columns (except for friday which doesn't have the grey bar), so we can just calculate the ranges we want to hide.
function hideColumn() {
classSheets.map(function(sheetName){
var sheet = ss.getSheetByName(sheetName);
if (n == 1) {
// Hide everything after the first three columns + Monday
sheet.hideColumns(3 + 11, 12 * 4);
} else if (n == 5) {
// Hide everything to the left except the leftmost three columns
sheet.hideColumns(3, 4 * 12);
} else {
// Hide everything left of the current day
sheet.hideColumns(3, (n - 1) * 12);
// Hide everything after the current day
sheet.hideColumns(3 + n * 12, (5 - n) * 12 - 1);
}
});
}
Lastly we can shorten showColumn
function showColumn() {
classSheets.map(function(sheetName){
var sheet = ss.getSheetByName(sheetName);
var lastCol = sheet.getLastColumn();
sheet.showColumns(1, lastCol);
});
}
Currently i have the following google script:
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
var r = s.getActiveCell();
if(s.getName()=='Setup BRF'){
if( r.getColumn() != 2 ) { //checks the column
var row = r.getRow();
var time = new Date();
time = Utilities.formatDate(time, "GMT", "dd-MM-yy' , 'HH:mm:ss");
SpreadsheetApp.getActiveSheet().getRange('J1').setValue(time);
};
};
};
Everytime i edit something on the sheet called Setup BRF it updates the time and date in J1 to show when it was last updated/edited.
My question is if its possible to add a name to lets cell K1 which shows who last updated this sheet. My skill with javascript is nihil so any kind of help is appreciated.
You could use the event object passed to the function
So change the definition to
function onEdit(e) {
and then you can use e.user to get to the user
Something like this
if( r.getColumn() != 2 ) { //checks the column
var row = r.getRow(),
time = new Date(),
user = e.user;
time = Utilities.formatDate(time, "GMT", "dd-MM-yy' , 'HH:mm:ss");
SpreadsheetApp.getActiveSheet().getRange('J1').setValue(time);
SpreadsheetApp.getActiveSheet().getRange('K1').setValue(user);
};