Copy and pasting data between cells with Google Scripts - google-apps-script

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

Related

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

onEdit: How to reference cell from another sheet and write a cell value offset from that cell?

I am trying to use another sheet as reference to trigger an onEdit script. There is a cell in Sheet2 that changes to "Y" but is based on a reference equation. So I am trying to use Sheet 1 as the basis for onEdit. My question is, am I specifying the reference cell from the non active sheet, and then writing a status "Y" on an offset cell?
if( s.getName() !== "Sheet1" ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
var col = r.getColumn();
var col2 = col.offset(0,-5);
var target = SpreadsheetApp.setActiveSheet(s.getSheetByName('Sheet2')).setActiveRange(col2,10);
var stat = target.offset(-6,0);
var status = stat.getValue();
var time = new Date();
time = Utilities.formatDate(time, "GMT", "dd-MM-yyyy HH:mm:ss");
switch(status) {
case (status !== "Y"):
target.setValue(time);
break;
}
Ok, your code has a few inherent problems right off the bat.
var col2 = col.offset(0,-5); should not work, because of var col = r.getColumn(); You are trying to use the .offset() method that has to be used on a range, however based on your code, col is an integer.
If you want to offset the active cell that is selected, then you would do r.offset(0, -5). For example, we are on Sheet2 and have Row 20, Column 10 active. Let's go over your code and see what you would get:
r = Range J20 on _Sheet2_ (specifically that sheet)
col = 20
Immediately we see that col2 will throw an exception. Going onwards, currently I see no reason to set the active sheet to another one. You can have range1 and range2 that you aquire by sheet1.getRange(20,10) and shee2.getRange(20,10). Doing range1.setValue("A") and range2.setValue("B") will write A and B in J20 on different sheets.
Using the same scenario, of us being on J10 (once everything is fixed) target.setValue(time); will set the value in J10 (because you took the column number and set it as the row number). stat will be J4, because you offset the row by -6 on Sheet2 range target

How to Insert Result of SUM from Two Date in the spreadsheet

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);
...

Automatically move data from one sheet to another in google docs

i have a spreadsheet that i keep track of tasks i need to do, once complete i enter a date in the last column. What i want is for that completed task to be moved to sheet 2.
At present i have sheet 1 named SUD_schedule and i want the completed row of data to be moved to sheet 2 named SUD_archive. I've looked through the forum posts already and i've tried a variation of scripts but so far no luck. The closest i have come is this script:
function onEdit() {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();//Original sheet
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];//target sheet
// to act on only one sheet, check the sheet name here:
//If it si not first sheet, it will do nothing
if (sheet1.getSheetName() != "SUD_schedule") {
return;
}
//Get Row and column index of active cell.
var rowIndex = sheet1.getActiveRange().getRowIndex();
var colIndex = sheet1.getActiveRange().getColumnIndex();
//If the selected column is 10th and it is not a header row
if (colIndex == 16 && rowIndex > 1) {
//Get the data from the current row
var data = sheet1.getRange(rowIndex,1,1,9).getValues();
var lastRow2;
(sheet2.getLastRow()==0)?lastRow2=1:lastRow2=sheet2.getLastRow()+1;
//Copy the data to the lastRow+1th row in target sheet
sheet2.getRange(lastRow2,1,1,data[0].length).setValues(data);
}
}
Column P (16) is the task complete date, row 1 is frozen and contains column headers.
Can anybody help show where i'm going wrong.
Kind regards
Den
Your code is not generic and you are more complicating your objective. Below will work out your need.
function onEdit(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('SUD_schedule');
var sheet2 = ss.getSheetByName('SUD_archive');
var dateColumn = "16";
var array = []
var range = sheet1.getRange(1, 1, sheet1.getLastRow(), dateColumn);
for (var i = 2; i <= sheet1.getLastRow(); i++) //i iterates from 2 as you say R1 is header
{
if(isValidDate(range.getCell(i, dateColumn).getValue()) == true) //checking if any values on column16 is valid date
{
data = sheet1.getRange(i, 1, 1, dateColumn).getValues(); //Getting the range values of particular row where C16 is date
for (var j = 0; j < dateColumn; j++) //Adding the row in array
{
array.push(data[0][j]);
}
}
if(array.length > 0)
{
sheet2.appendRow(array); //Appending the row in sheet2
array = [];
sheet1.deleteRow(i); //deleting the row in sheet as you said you want to move, if you copy remove this and next line
i=i-1; //managing i value after deleting a row.
}
}
}
//Below function return true if the given String is date, else false
function isValidDate(d) {
if ( Object.prototype.toString.call(d) !== "[object Date]" )
return false;
return !isNaN(d.getTime());
}
I am not sure that the syntax you have as used below is entirely correct.
(sheet2.getLastRow()==0)?lastRow2=1:lastRow2=sheet2.getLastRow()+1;
sheet2.getRange(lastRow2,1,1,data[0].length).setValues(data);
What I know will work for certain is if you omit the variable lastRow2 all together and use this instead.
sheet2.getRange(getLastRow+1,1,1,data[0].length).setValues(data);
To complement Joachin's answer, here is how you can adapt that code if you don't have the date in the last row. In the below shown part of the code replace Lastcolumnumber with your last column.
//Getting the range values of particular row where C16 is date
data = sheet1.getRange(i, 1, 1, LASTCOLUMNNUMBER).getValues();
//Adding the row in array
for (var j = 0; j < LASTCOLUMNNUMBER; j++)