How to Insert Result of SUM from Two Date in the spreadsheet - google-apps-script

How to Insert Result of SUM from Two Date in the spreadsheet
Data:
H3: 27/11/2013 1:31:00
F3: 00:15
I3: Should be appear the result of SUM (H3+F3) using this formula =SUM(H3+F3). The Result is 27/11/2013 1:49:00 (24hs Formatting)
Action:
Should be executed only when some insert a value in the column F starting 3rd row.
Only should be executed for the row where was modify.
Should be insert the result in column I, the sum of H+F
Here I have the starting script for the 1 & 2.
function CreationDate(event){
//Script Sume Date
var actSht = event.source.getActiveSheet();
if (actSht.getName() == "sheet1"){
var activeCell = actSht.getActiveCell(); //Detec the ActiveCell
var column = activeCell.getColumn(); // Detect the Column of the ActiveCell
var colNums = [6]; //Coulmns, whose edit is considered
if(colNums.indexOf(column) == -1) return; //If column other than considered then return
var row = activeCell.getRow(); //Detect the ActiveRow
if(row < 3) return; //If header row then return
TEST:
I try to formatting this script Clic Here to sum the data and back the result in dd/mm/yyyy hh:mm:ss but I didn't have lucky.
Why is needed?:
Is very important have this formula run asap because I use is to scheduling a critical call to many ISP around the country.
I try to use =arrayformula(sum(h3+f3)) but didn't work. I needs a script because I add new rows all the time.
I will appreciate your help.
Best Regards,

The single-row version of Adam's formula, in row 3 for example, is:
=IF(ISNUMBER(H3)*ISNUMBER(F3);H3+F3;IFERROR(1/0))
Since you're worried that users may damage the formula, you can use an onEdit() trigger function to ensure the formula is updated in Column I anytime the data in Column F is edited.
// When a value is entered in column F, set I = H + F, for rows >= 3.
function onEdit(e) {
if (!e) { // This block is for testing in debugger; always uses row 3
e = {};
e.range = SpreadsheetApp.getActiveSheet().getRange('F3');
e.value = e.range.getValue();
}
var row = e.range.getRow();
var col = e.range.getColumn();
if (col == 6 && row >= 3) {
// Insert single-cell version of Adam's formula into I
e.range.getSheet().getRange(row,9)
.setFormula('=IF(ISNUMBER(H'+row+')*ISNUMBER(F'+row+');H'+row+'+F'+row+';IFERROR(1/0))');
}
}
An alternative way to insert the correct row number into the formula is to use Regular Expression replacement:
...
// Insert single-cell version of Adam's formula into I
var rowTag = new RegExp('%ROW%','g');
var formula = '=IF(ISNUMBER(H%ROW%)*ISNUMBER(F%ROW%);H%ROW%+F%ROW%;IFERROR(1/0))'
.replace(rowTag,row);
e.range.getSheet().getRange(row,9).setFormula(formula);
...

Related

Google app script for loop is extremely slow

I have a pivot table set up in a google sheet file where I've labeled the sheet pivot table 1. I want to get each value of the first column of the pivot, duplicate each values 12 times in an array and paste these values in the 3rd column of sheet 5. However, it seems extremely slow to do with the script never really completing (just takes 10+ minutes before I've cancelled it).
The pivot has approximately 3000 lines, which would result in a 3000 * 12 = 36000 array.
Any thoughts on how I can optimize this?
function test2() {
// activating current spreadsheet for use
var spreadsheet = SpreadsheetApp.getActive();
//empty array
var array_dept = []
// returns (integer #) the last row of the pivot table 1 sheet that has content
var last_row = spreadsheet.getSheetByName("Pivot Table 1").getLastRow();
// Get value in pivot table 1 from range of row 1 (dept name), column 1, all the way to last row
// Then paste it in sheet5 from row 1, column 3, all the way to the last row defined above
for (var i = 1; i < last_row; i++ )
{
//get value and then paste it in a destination
var value_dept = spreadsheet.getSheetByName("Pivot Table 1").getRange(i,1).getValue();
array_dept.fill(value_dept, -12 + (12*i) , 12*i)
}
destination_dept = spreadsheet.getSheetByName("Sheet5").getRange(1,3, last_row);
destination_dept.setValues(array_dept);
}
You don't need use a loop if you know the first row and the last row on the source column. You can just define the range:
var pivotRange = pivot.getRange(1,1,last_row)
var targetRange = target.getRange(1,3,last_row)
doc ref; this is just one of five methods to define a range.
In the OP script, there would be 3000xgetRange + 3000xgetValue. In this answer there are: 2xgetRange and 1 x getValue. This should account for a substantial amount of script processing. Of course, we know nothing of the rest of the spreadsheet (its size, formula, functions, triggers, etc). But all other things being equal, this should improve the performance of the script.
function test2() {
// activating current spreadsheet for use
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
var pivotSheetName = "Pivot Table 1"
var pivot = spreadsheet.getSheetByName(pivotSheetName)
//temporary array
var array_dept = []
// returns (integer #) the last row of the pivot table 1 sheet that has content
var last_row = pivot.getLastRow();
//Logger.log("DEBUG: last row in the pivot table:"+last_row)
var pivotRange = pivot.getRange(1,1,last_row)
// Logger.log("DEBUG: the range for the pivot range = "+pivotRange.getA1Notation())
var pivotData = pivotRange.getValues()
//Then paste it in sheet5 from row 1, column 3, all the way to the last row defined above
var targetSheetName = "Sheet5"
var target = spreadsheet.getSheetByName(targetSheetName)
var targetRange = target.getRange(1,3,last_row)
// Logger.log("DEBUG: the range for the target range = "+targetRange.getA1Notation())
targetRange.setValues(pivotData)
Logger.log("Done")
}

Copy and pasting data between cells with Google Scripts

Photo of Spreadsheet
Newbie Question
I am guessing this is any easy question for most people here but I can't figure out what I am missing and I've spent quite a while trying to figure it out.
I have a script that is supposed to time stamp different columns. All the if functions work correctly for stamping columns A, E, and F by placing input in columns in B, C, and G respectively.
The one issue I having is getting column E to show input when column d is checked. I've tried a number of different ways(which are commented out in the code.)
I am not sure what I am missing but the difference between the code that is working and the code that isn't is that code that is working uses an offset function to place a date stamp of the current time while the code that isn't working is supposed to copy the data from one row up and two columns over. Essentially this means in an example that when column D10 is checked it should copy the time value in F9 to E10(I have corrected this example since my original post. I was a bit tired when I first wrote it)
Here is the example of my code. I have also attached a picture of the spreadsheet for clarity. I suspect the issue that I using a function wrong but I don't have enough experience to understand why.
function onEdit(e){
//CORE VARIABLES
// The columns that trigger datestamps in other columns
var COLUMNB = 2;
var COLUMNC = 3;
var COLUMND = 4;
var COLUMNG = 7;
// Where you want the date time stamp offset from the input location. [row, column]
// DTL = Date Time Location
//Intiates a series of variables to hold the offset values for datestamping the row entry
//Instiates a variable which controls the offset values for column B name entry
//The date stamp currently corresponds to column A and is triggered by selecting a client in column B
var DTLColB = [0,-1];
//Intiates a variable to hold the offset values for datestamping the start time column with the current time
//The date stamp currently corresponds to the time value in column E and the trigger is in column C
var DTLColCCTstart = [0, 2];
//Intiates a variable to hold the offset values for datestamping the start time column with the previous row entry time
//The date stamp currently corresponds to the time value in column E(offset(-1,2))and the trigger is in column D,-,-
//It copies the previous end time into the current start time
var DTLColDLTstart = [0, 1];
//Intiates a variable to hold the offset values for datestamping the current time in the end time col for for a row
//The date stamp currently corresponds to the time value in column F and the trigger is in column G
var DTLColGCTend = [0, -1];
var LastStampCoord = [-1, 2];
//Intiates a variable that controls which sheets this function is active on
var SHEETNAME = 'Cont Log'
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() == COLUMNB) {
var dateTimeCellB = selectedCell.offset(DTLColB[0],DTLColB[1]);
dateTimeCellB.setValue(new Date());
}
if( selectedCell.getColumn() == COLUMNC || selectedCell.getColumn == true ) {
var dateTimeCellC = selectedCell.offset(DTLColCCTstart[0],DTLColCCTstart[1]);
dateTimeCellC.setValue(new Date());
}
if( selectedCell.getColumn() == COLUMND || selectedCell.getColumn == true) {
var dateTimeCellD = selectedCell.offset(DTLColDLTstart[0],DTLColDLTstart[1]);
// var oldtimevalue = selectedCell.offset(LastStampCoord[0],LastStampCoord[1]);
// var oldtimevalue = range.selectedCell.offset(LastStampCoord[0],LastStampCoord[1]));
//var oldtimevalue = selectedCell.offset(LastStampCoord[0],LastStampCoord[1]);
//var oldtimevalue = selectedCell.getrange(selectedCell.offset(LastStampCoord[0], LastStampCoord[1])).getvalues;
//var oldtimerecord = sheet.getrange(selectedCell.offset(LastStampCoord[0],LastStampCoord[1])).getvalue();
//var oldtimevalue = oldtimerecord.getvalue();
// var LastStampLookup = selectedCell.offset(LastStampCoord[0],LastStampCoord[1]).getvalue();
// var LastStampTime = LastStampLookup.getvalue()
// range1.offset(2, 0).setValue("Order complete");
// dateTimeCellD.offset(LastStampCoord[0], LastStampCoord[1]).setvalue(timelocation);
//dateTimeCellD.setValue(new oldtimevalue.getvalue());
dateTimeCellD.setValue(new date());
}
if( selectedCell.getColumn() == COLUMNG || selectedCell.getColumn == true) {
var dateTimeCellG = selectedCell.offset(DTLColGCTend[0],DTLColGCTend[1]);
dateTimeCellG.setValue(new Date());
}
}
}
[1]: https://i.stack.imgur.com/85DwP.png
I am not sure what I am missing but the difference between the code
that is working and the code that isn't
You have a small typing mistake - change
dateTimeCellD.setValue(new date());
to
dateTimeCellD.setValue(new Date());
However, if your goal is to set the value of dateTimeCellD to the one of the cell 1 to the right, one to the top - you can do it with
dateTimeCellD.setValue(dateTimeCellD.offset(-1,1).getValue());
See the method descriptions here and here.
Try this:
function onEdit(e){
var sh=e.range.getSheet();
if( sh.getName()=="Cont Log" ) {
var ts=Utilities.formatDate(new Date(),Session.getScriptTimeZone(),"E MM/dd/yyyy HH:mm:ss");
if(e.range.columnStart==2) {e.range.offset(0,-1).setValue(ts);}
if(e.range.columnStart==3) {e.range.offset(0,2).setValue(ts);}
if(e.range.columnStart==4) {e.range.offset(0,1).setValue(ts);}
if(e.range.columnStart==7) {e.range.offset(0,-1).setValue(ts);}
}
}

Auto insert row above, based on single cell value

I am trying to auto-insert a row above the current top row (row 2) based on a cell's value.
I cannot figure out the variables I need to put into the script editor.
I tried googling for help and modified other peoples script to see if I could do it, and the answer is no, no I do not possess the knowledge/skill.
function conditionalNewRow() {
var ss = SpreadsheetApp.getActive().getSheetByName('NEW INV');
var sh = ss.getActiveSheet();
var headerRow = 1;
var firstRow = headerRow + 1;
var range = sh.getRange("A2"); // Get range of row 2.
var futureRange = sh.getRange("A3"); // Get range of row 3.
var numCols = range.getNumColumns(); // Get the number of columns for row 2.
var contentVal = false;
for (i = 1; i <= numCols; i++) {
var currentValue = range.getCell(1,i).getValue();
if (currentValue == "NO"){
contentVal = true;
break;
}
}
if (contentVal == true) {
sh.insertRowBefore(firstRow); // Insert an empty row into row 2.
futureRange.copyTo(sh.getRange(firstRow, 1, firstRow, numCols), {contentsOnly:false}); // Copy row 3 to row 2.
}
}
All I want is a blank row above the previous row when a cell meets certain criteria;
e.g. Cell A2 contains any of the following; YES, NO, LOADED, UNLOADED
If it contains any of those values, it will auto-insert a row above.
I am a little unclear on your intent and what issues you are having.
A few things I see:
1) Since your range is a single cell, var numCols = range.getNumColumns(); should always return 1, so your loop, for (i = 1; i <= numCols; i++), should run exactly once. It feels like there is a lot of redundant code here.
To get the value of cell A2, you could just write:
var range = sh.getRange("A2");
var currentValue = range.getValue();
2) From the if statements, it looks like you only want to add a new row if the value of A2 is something other than "NO". Is that correct? (This is not what your question states). If so, I think you're pretty close with the sh.insertRowBefore(firstRow); statement, it just might be getting lost in some convoluted logic.
3) Do you really want to copy everything from row 3 into row 2? In the question you state "All I want is a blank row above the previous row when a cell meets certain criteria".
Perhaps something like this is closer to what you want?
function conditionalNewRow() {
var ss = SpreadsheetApp.getActive().getSheetByName("NEW INV");
var sh = ss.getActiveSheet();
var range = sh.getRange("A2"); // Get range of row 2.
var currentValue = range.getValue();
if (currentValue !== "NO") {
sh.insertRowBefore(firstRow); // Insert an empty row into row 2.
}
}
Edit
From your comment, sounds like you want to insert a new row whenever A2 is edited to one of the selectable values. You may want to check out simple triggers, such as onEdit, which runs whenever a cell is edited. For instance, something like this:
/**
* The event handler triggered when editing the spreadsheet.
* #param {Event} e The onEdit event.
*/
function onEdit(e) {
// get sheet
var sheet = SpreadsheetApp.getActive().getSheetByName("NEW INV");
// Get the edited range
var editedRange = e.range;
// check if cell A2 was edited
if (editedRange.getA1Notation() === "A2") {
// check if value is a desired value
if (editedRange.getValue() === "YES" || "NO" || "LOADED" || "UNLOADED") {
// if yes to both, insert new row
sheet.insertRowBefore(2);
}
}
}

Script - Add a row beneath, based on conditional criteria

Dear Oracles of the script,
I have been trying to get some script to automatically add a row beneath the one I have inputted on, but only if the Balance is anything BUT zero. If it's zero, I don't want another row adding.
I've tried a few scripts and looked around the site, and tried them with triggers with on edit, but they just seem to add a row, despite me trying to state a condition for them to trigger.
function onEdit(event) {
var eventRange = event.range;
if (eventRange.getColumn() == 12) { // 12 = column of input that triggers it
var columnXRange =
SpreadsheetApp.getActiveSheet().getRange(eventRange.getRow(), 13,
eventRange.getNumRows(), 12); /// column number it affects
var values = columnXRange.getValues();
for (var i = 0; i < values.length; i++) {
if (!values[i][0]) { // If cell isn't empty
values[i][0] = '0';
}
}
columnXRange.setValues(values);
}
}
function Clear(e){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('AGL');
sheet.getRange('N4:N').clearContent();
}
function AddRow() {
var sheet = SpreadsheetApp.getActiveSheet();
if (sheet.getName() == "AGL") {
var activeCell = sheet.getActiveCell();
if (activeCell.getColumn() == 13) {
var Balance = sheet.getRange('N:N');
if (Balance != '0'); {
sheet.insertRowAfter(activeCell.getRow());
}
}
}
}
In column N, I have an array formula working out the balance of stock in, against stock out.
In column M, I have a script running that will add a 0 when something is put into column L. I also have a script that erases the output of the array formula, so they don't get tangled up with each other.
I would like, when editing a row, when I place a figure in column L or M, and if the balance in Column N is greater than 0, I would like a new row adding underneath. (If you can get it to add the values from A & B, that'd be a bonus, but not fussy.) If the balance is 0, I don't want a row adding.
Currently, I have mixed results with it just adding a row every time I edit column N.
Requirement:
Add a row when columns L or M are edited and the value in column N is greater than 0 (& if possible, add values from columns A & B to the new row).
Solution:
This is pretty much all you need for your script. I've added comments to explain what each part is doing so it should be pretty easy to follow.
function onEdit(e) {
//define edited sheet, row number and column number
var sh = e.source.getActiveSheet();
var row = e.range.getRow();
var col = e.range.getColumn();
//get value of column N for edited row
var val = sh.getRange(row, 14).getValue();
//if columns L or M are edited and column N is greater than 0
if ((col === 12 || col === 13) === true && val > 0) {
//insert row below edited row
sh.insertRowAfter(row);
//get values of columns A and B of edited row
var vals = sh.getRange(row, 1, 1, 2).getValues();
//set values in columns A and B
sh.getRange(row+1, 1, 1, 2).setValues(vals);
}
}
Notes:
I haven't included any of your other functions, only adding a row, you can incorporate these in this function if you desire.
You won't be able to run this script manually at all (it'll fail on the first line), it'll just run automatically when the sheet is edited.
References:
Event Objects
Class Sheet

Delete Row If Two Corresponding Cells Match

In my google sheet file, sheet2 is being used as a blacklist wherein colA = a name, colB = date they were blacklisted, colC = date they will be removed from the blacklist (3 months after value in colB). Sheet1 records the responses of a signup form.
I would like a script that will automatically remove the names after their colC date. Perhaps a script that can delete an entire row if two cells match. An example would be if B2 and C2 are equal then delete row 2. This would have to apply to every row.
Any help would be greatly appreciated. Thank you very much.
It wasn't immediately clear which sheet you wanted to remove the name from. My answer assumes that you are removing the name from the blacklist sheet, sheet2.
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var sheet2 = ss.getSheetByName ("sheet2");
var values = sheet2.getDataRange ().getValues ();
var day = 24*3600*1000;
var today = parseInt ((new Date ().setHours (0,0,0,0))/day);
var ssdate; // Date to check, spreadsheet date
// Start at the bottom and move up the file, since all rows will shit up when deleted
for (var i = values.length; i >= 0; i--)
{
try
{
ssdate = values[i][2].getTime () / day; // 2 is for the C column (0 is for the A column)
}
catch (e) {ssdate = null;}
// Testing that the date is today or later to remove from file
if (ssdate && Math.floor (ssdate) >= today)
{
sheet2.deleteRow (i + 1); // Removes name from blacklist.
// i + 1, because it is the row number, which starts at 1
// where arrays start index at 0.
}
}