Setting timestamp in first empty cell of column - google-apps-script

I have not been able to find this anywhere. I'm guessing I'm searching for the wrong keywords. So far I have been able to use:
function getFirst() {
var spr = SpreadsheetApp.getActiveSpreadsheet();
var column = spr.getRange('F2:F260');
var values = column.getValues(); // get all data in one call
var ct = 0;
while ( values[ct][0] != "" ) {
ct++;
}
return (ct);
}
But I can't quite figure out how to set the return value to (new Date()).
This:
function clockOut() {
SpreadsheetApp.getActiveSheet().getRange('F2').setValue(getFirst(new Date));
}
Sets the time based off of the ct which, because it's zero, looks like: | 12/31/1899 0:00:00 |. Also in the F2 spot not in the ct spot. I think I'm close yet feel like I'm going in the wrong direction. Thanks

You were not too far in the first part... after that it becomes a bit confuse... here is a working example, I changed it to allow for easy customization on choosing the column.
function clockOut() {
var sh = SpreadsheetApp.getActiveSheet();
var col = "F";// choose the column you want
sh.getRange(col+getFirstEmptyCell(col)).setValue(new Date());
}
function getFirstEmptyCell(col) {
var sh = SpreadsheetApp.getActiveSheet();
var values = sh.getRange(col+"1:"+col).getValues()
var ct = 0;
while ( values[ct][0] != "" ) {
ct++;
}
ct++;// because we want to get the row after the last non-empty row
Logger.log(ct);// just to check
return (ct);
}

Related

Google Script for running a function for the most recent row updated by form edit submission

I am using google forms to generate memos for our team. However the work flow is such that they will need to edit their submission to run subsequent form off the same data. (company IT limitations) This works, but I'm having issues isolating the row that was recently edited by the user. Obviously not a coder and I can't find a solution. Any help would be appreciated.
function getFirstEmptyRowByColumnArray() {
var spr = SpreadsheetApp.getActiveSpreadsheet();
var column = spr.getRange('A:A');
var values = column.getValues(); // get all data in one call
var ct = 0;
while ( values[ct] && values[ct][0] != "" ) {
ct++;
}
return (ct);
}
My intent is to revise the getFirstEmptyRowByColumnArray() function. The code as it currently runs finds the last row, I would need it to find the most recent timestamp in column A and run the autofill function on that row.
Figured it out!! Just in case anyone else needs to know.
function getnewupdate() {
var spr = SpreadsheetApp.getActiveSpreadsheet();
var column = spr.getRange('A2:A');
var values = column.getValues(); // get all data in one call
var containingValue = max;
var max = Math.max.apply(null, column.getValues());
var i = [];
for (var y = 0; y < values.length; y++) {
if(values[y] == containingValue){
i.push(y);
}
return (Number(i)+Number(column.getRow()));
}
}

Google Sheets execute script onEdit

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

Google Apps Script - set formula of active cell depending on value of another cell

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.

Count and display how many times values changed in a column

At the start sorry for my poor english, i will try my best to explain everything.
Is there a way to count how many times value in column D has been changed and show it in column E?
In this example in column D person can select two values from list - "☐" and "☑". In column E i would want to see how many times person changed their selection. Lets say for for E3 i want to see how many time D3 was changed, for E4 to show how many times D4 was change and so on.
Thank you for all help!
Example spreadsheet
The only thing i found was somehitng like that:
function onEdit(e) {
if(e.range.getA1Notation() == "D2") {
var sCounter = e.source.getRange("E2");
var counter = sCounter.getValue();
if(counter === 0) {
counter = 1;
} else {
counter ++;
}
sCounter.setValue(counter);
}
}
The problem is that it only counts one cell and i need it to work for the whole column.
This should do it:
function onEdit(e) {
var ss =SpreadsheetApp.getActiveSpreadsheet()
var s=ss.getActiveSheet()
var editColumn=e.range.getColumn()
var editRow = e.range.getRow()
if(editColumn == 4 && editRow >=2) {
var sCounter = s.getRange(editRow,editColumn+1,1,1);
var counter = sCounter.getValue();
if(counter === 0) {
counter = 1;
} else {
counter ++;
}
sCounter.setValue(counter);
}}
Here is my test spreadsheet you can copy and try:
https://docs.google.com/spreadsheets/d/1I5_NVMKPvqN9J2sSlcLRnQbzoVF4iRKOuXJ5mshb-RY/edit?usp=sharing

Google Spreadsheet: Sum values in a set number of sheets

I have a spreadsheet for soccer with an overview sheet (it's the first sheet) and 34 more sheets (for every matchday, called "x. ST") filled with values. In the overview sheet I want to get the sum of specific values from a set number of matchdays. I tried to realize this by an App Script. var start is the value that defines the first matchday, var end the last matchday. I want it as dynamic as possible so I can get values i.e. from Matchday 10 to 20 or 20 to 25 and so on.
Every sheet from start to end has a value in a given cell. This value can be "3" (for win), "1" (for draw) or "0" (for loss). Because this function should display the number of matchdays with wins, every "3" counts as 1, every "1" and "0" as 0. Logically the sum of all 1's is the number of the won matchdays. Here's the code:
function win(cell) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var sum = 0;
var end = ss.getActiveSheet().getRange(21, 2).getValue() + 1;
var start = ss.getActiveSheet().getRange(21, 3).getValue() + 1;
for (var i = start; i < end ; i++ ) {
var sheet = sheets[i];
var val = sheet.getRange(cell).getValue();
if (val == "3") {
val = 1;
} else {
val = 0;
}
sum += val;
}
return sum;
}
Now, my problem is that the code does work, but the sum is always a 0 (zero), regardless of the number of sheets with "3" in the given cell. I really don't see where's the problem. Anyone with an idea?
EDIT: Here's the Spreadsheet. I'm not sure it will help, but whatever:
https://docs.google.com/spreadsheets/d/1SoE4cJVAeeurmB7bvvGENEWvu2Mg1xvA3B3hTobBxW8/edit#gid=0
EDIT2: Ok guys, there were simple errors and the code works now. First I had to change cell in getRange(), and then I had to guarantee every value is an integer. There was also an error with start and end, causing the code searching in the wrong sheets. Because this sheets are currently without any values, there was always the sum of 0. Well, here's the current code:
function win(cell) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var sum = 0;
var end = ss.getActiveSheet().getRange(21, 2).getValue() + 1;
var start = ss.getActiveSheet().getRange(21, 3).getValue();
for (var i = start; i < end ; i++ ) {
var sheet = sheets[i];
var val = sheet.getRange([cell]).getValue();
parseInt(val) * 1;
if (val == 3) {
val = 1;
} else {
val = 0;
}
sum += val;
}
return sum;
}
I cannot be sure without looking at your spreadsheet, but just from looking at your code, I am guessing that you have the "Start" and "end" cells mixed up. The way it is now, both cells are in the same row, but end comes before start, which is not what you seemed to describe above.