Time Stamp Script not working on Pasting/Dragging Cell Values - excel

I have a script which records the time stamp on which an entry is made in a specific cell. It uses a onEdit trigger.
PROBLEM STATEMENT:
When I'm dragging/copy-pasting the data over a range of adjacent cells(in the same column), only the first entry is producing a time-stamp output.
CODE:
var s = SpreadsheetApp.getActiveSheet();
var sName = s.getName();
var r = s.getActiveCell();
if( r.getColumn() == 8 && sName == 'Processing') { //which column to watch on which sheet
var row = r.getRow();
var time = new Date();
SpreadsheetApp.getActiveSheet().getRange('CU' + row.toString()).setValue(time); //which column to put timestamp in
};
};

You are using onEdit to insert a timestamp when a field is edited. But when an edit is done by copy/paste or dragging a cell/range, the timestamp is applied only for the first cell in the new target range.
The reason that this is happening is that your script output recognises only the activecell and does not recognise the rest of the activerange
var r = s.getActiveCell();
var row = r.getRow();
There are several solutions to your problem.
ActiveRange:
Enable the script to process the number of rows in the active range.
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
var sName = s.getName();
var r = s.getActiveCell();
var row = r.getRow();
var ar = s.getActiveRange();
var arRows = ar.getNumRows()
// Logger.log("DEBUG: the active range = "+ar.getA1Notation()+", the number of rows = "+ar.getNumRows());
var time = new Date();
if( r.getColumn() == 8 && sName == 'Processing') { //which column to watch on which sheet
// loop through the number of rows
for (var i = 0;i<arRows;i++){
var rowstamp = row+i;
SpreadsheetApp.getActiveSheet().getRange('CU' + rowstamp.toString()).setValue(time); //which column to put timestamp in
}
}
}
Event Objects: Enable the script to take advantage of the event Objects generated by OnEdit.
In the following script, the edited range, the column, sheet name, the starting and ending row numbers are all obtained/determined by using Event Objects available to onEdit.
function onEdit(event) {
var s = SpreadsheetApp.getActiveSheet();
// Logger.log(JSON.stringify(event)); //DEBUG
var ecolumnStart = event.range.columnStart;
var erowStart = event.range.rowStart;
var erowEnd = event.range.rowEnd;
var ecolumnEnd = event.range.columnEnd;
// Logger.log("DEBUG: Range details - Column Start:"+ecolumnStart+", Column End:"+ecolumnEnd+", Row start:"+erowStart+", and Row End:"+erowEnd);
// Logger.log("DEBUG: the sheet is "+event.source.getName()+", the range = "+event.range.getA1Notation());
var sName = event.range.getSheet().getName();
// Logger.log("DEBUG: the sheet name is "+sName)
var time = new Date();
var numRows = event.range.rowEnd -event.range.rowStart+1;
if( event.range.columnStart == 8 && sName == 'Processing') { //which column to watch on which sheet
// loop though the number of rows
for (var i = 0;i<numRows;i++){
var row = event.range.rowStart+i;
SpreadsheetApp.getActiveSheet().getRange('B' + row.toString()).setValue(time); //which column to put timestamp in
}
}
}

Related

Delete rows after certain time

you see, I have this code, it works in the next way, after a form submit, the data goes to a sheet called Responses, that data is sent to another sheet in the same spreadsheet, this one is called Store, i'm using another coz as you know, once you delete for example the answer set on row 1 by the form, the next value is put on row two, but i need to read the first row, so in my code whenever the data is on responses, is sent to Store's first row, after that is compared in another sheet calleh Termo, then all the data that is filtered in thermo that exist on Store, is used to create a Slides presentation.
The problem is the next, i need to delete the row on Store after the slide is created, so when the next form is submited, the Store's first row is empty and can ''store'' the new value, my problem is that in some way, it deletes the data on Store first, and then when it creates the presentation slide, is empty, all this using on form submi trigger, but when i execute in the editor both separately, it works...
const PRESENTATION_ID = '1Xkbhk5UvEeCqu6NsBdRD41ysvxv4aW2-upKyVKYJboA'; //hacer variable para redireccionar al slides correcto
//Para generar historial
var SOURCE_SPREADSHEET_ID;
const TARGET_SPREADSHEET_ID = "1VELwR-qZMbUSsK3_VUmz8x2FRULSiOy0UvAMMHdhPE4";
const SOURCE_SHEET_NAME = "Responses";
const TARGET_SHEET_NAME = "HISTORIAL";
var Comparador;
//Fin de variables pala generar historial
function moveData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Responses"); // Nombre de la hoja
Absoluto = "1";
Comparador = "1";
SOURCE_SPREADSHEET_ID = "1VELwR-qZMbUSsK3_VUmz8x2FRULSiOy0UvAMMHdhPE4"
//NAME_COL_INDEX = 6;
//NAME_COL_INDEX2 = 12;
var cell1 = s.getRange('AU1');
var value1 = cell1.getValue();
var value2 = Absoluto;
var cell2 = s.getRange('B1');
//VAriables para el segundo manejo
//fin
if (value1==value2){
var ss = SpreadsheetApp.getActive();
var dailySheet = ss.getSheetByName('Responses');
var appendSheet = ss.getSheetByName('Store');
var values = dailySheet.getRange("Responses!2:" + dailySheet.getLastRow()).getValues();
values = values.filter(e=>e[0]); //gets rid of blank rows. filters based on the first column (index 0).
appendSheet.getRange(appendSheet.getLastRow()+1,1,values.length,values[0].length).setValues(values);
Utilities.sleep(8000);
}
}
function generatePresentationData(){
//let sheet = SpreadsheetApp.getActiveSheet();
let sheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1VELwR-qZMbUSsK3_VUmz8x2FRULSiOy0UvAMMHdhPE4/edit?resourcekey&pli=1#gid=1218501416").getSheetByName("Termo");
let marketData = getDataFromSheet_(sheet);
let chartFromSheet = getChartsFromSheet_(sheet);
let slides = getSlides_();
let masterSlide = slides[1];
masterSlide.duplicate();
writeDataToMinutaSlide_(slides, marketData);
function getDataFromSheet_(sheet){
let dataRange = sheet.getDataRange();
let data = dataRange.getValues();
data.shift();
return data;
}
function getChartsFromSheet_(sheet){
let charts = sheet.getCharts();
let chart = charts[0];
return chart;
}
function getSlides_(){
let presentation = SlidesApp.openById(PRESENTATION_ID);
let slides = presentation.getSlides();
return slides;
}
function writeDataToMinutaSlide_(slides, marketData){
let slideMinuta = slides[1];
let moveSlide = slides[1];
moveSlide.move(3);
for (let index = 0; index < marketData.length;index++){
slideMinuta.replaceAllText(`{{Accion${index}}}`,marketData[index][56]);
slideMinuta.replaceAllText(`{{Respo${index}}}`,marketData[index][57]);
slideMinuta.replaceAllText(`{{Date${index}}}`,marketData[index][61]);
slideMinuta.replaceAllText(`{{Area}}`,marketData[index][4]);
slideMinuta.replaceAllText(`{{Estacion${index}}}`,marketData[index][74]);
slideMinuta.replaceAllText(`{{Fecha${index}}}`,marketData[index][62]);
slideMinuta.replaceAllText(`{{Responsable${index}}}`,marketData[index][2]);
slideMinuta.replaceAllText(`{{Problema${index}}}`,marketData[index][9]);
slideMinuta.replaceAllText(`{{Duracion${index}}}`,marketData[index][10]);
slideMinuta.replaceAllText(`{{A${index}}}`,marketData[index][39]);
slideMinuta.replaceAllText(`{{N${index}}}`,marketData[index][40]);
slideMinuta.replaceAllText(`{{M${index}}}`,marketData[index][41]);
slideMinuta.replaceAllText(`{{E${index}}}`,marketData[index][42]);
slideMinuta.replaceAllText(`{{L${index}}}`,marketData[index][43]);
slideMinuta.replaceAllText(`{{I${index}}}`,marketData[index][44]);
slideMinuta.replaceAllText(`{{É${index}}}`,marketData[index][45]);
slideMinuta.replaceAllText(`{{Image${index}}}`,marketData[index][19]);
slideMinuta.replaceAllText(`{{Causa${index}}}`,marketData[index][11]);
slideMinuta.replaceAllText(`{{Motivo${index}}}`,marketData[index][12]);
slideMinuta.replaceAllText(`{{Raiz${index}}}`,marketData[index][69]);
slideMinuta.replaceAllText(`{{Subcausa${index}}}`,marketData[index][67]);
slideMinuta.replaceAllText(`{{Pilar${index}}}`,marketData[index][68]);
}
}
}
var ss = SpreadsheetApp.getActive();
var dailySheet = ss.getSheetByName('Store');
var values = dailySheet.getRange("Store!1:" + dailySheet.getLastRow()).getValues();
values.reverse().forEach((r,i)=>{
if (r=='del'){
sheet.deleteRow(values.length-i+1);
}
});
var source = ss.getRange("Store!A1:AT");
source.clear();
Does anyone know a way to make the clear rows function after the generate presentationslide? This is the Slide I'm generating whitin the data on Store

How to return each individual row in the results?

I have created an API that searches sheet 2 in a spreadsheet for a keyword and returns the number of the row of the cell that the key word was found in. I want to copy and paste all the rows from sheet 2 on to sheet 1. I can't get the script to copy and paste them all.
function executeSearch() {
//establishing search sheet
var SSS = SpreadsheetApp.openById('ID');
var SS = SSS.getSheetByName('Sheet1');
var searchTerm = SS.getRange('B3').getValue();
//establishing the data sheet
var DS = SSS.getSheetByName('Sheet2');
var completeSearch = DS.createTextFinder(searchTerm).findAll();
for (var i = 0; i < completeSearch.length; i++) {
var range = completeSearch[i];
var resultsCells = range.getA1Notation(); //get the cell location of the search data cell
var row = range.getRow(); //get the rows that the search data is in
DS.getRange(row, 1, 1, DS.getMaxColumns()).copyTo(SS.getRange(8, 1, 1, DS.getMaxColumns()));
}
Your code is copying the data to the same row each time:
DS.getRange(row, 1, 1, DS.getMaxColumns()).copyTo(SS.getRange(8, 1, 1, DS.getMaxColumns()));
To get the code to write the data to new rows, you can change it to:
DS.getRange(row, 1, 1, DS.getMaxColumns()).copyTo(SS.getRange(8 + i, 1, 1, DS.getMaxColumns()));
But this isn't efficient when you have a large number of results. You are repeatedly calling the sheet for writing each row.
It would be more efficient to first write all the search results to an array. And then to call the sheet just once to write all the data to the rows in one go.
function executeSearch() {
//establishing search sheet
var SSS = SpreadsheetApp.openById('ID');
var SS = SSS.getSheetByName('Sheet1');
var searchTerm = SS.getRange('B3').getValue();
//establishing the data sheet
var DS = SSS.getSheetByName('Sheet2');
var completeSearch = DS.createTextFinder(searchTerm).findAll();
var searchResults = []; // Create an array to store the values of the search results
for (var i = 0; i < completeSearch.length; i++) {
var range = completeSearch[i];
var row = range.getRow(); //get the rows that the search data is in
var values = DS.getRange(row, 1, 1, DS.getMaxColumns()).getValues();
searchResults.push(values[0]);
}
SS.getRange(8, 1, searchResults.length, searchResults[0].length).setValues(searchResults);
}
The only thing to watch out for in this script is that it will write values to the sheet and not formulas.

programmatically print out cell and comments contents from spreadsheet

I have a spreadsheet with worksheets (originally in Google Sheets, but I can export to .xlsx or .ods) and I would like to programmatically print out the cell values of the first line along with the comments in each cell. E.g. see screenshot below of worksheet (https://docs.google.com/spreadsheets/d/1DGsrEKrxfQm8sRzfLyqu4z6Hx8eDdkVDiYlN3Rwve6A/edit?usp=sharing):
There are 3 cells in row1 each with a comment in them.
I would like to programmatically print out the contents of this worksheet so that they look something like:
Cell:"field1",Comment:"key=foobar"
Cell:"field2",Comment:"key=bar"
Cell:"field3",Comment:"key=foobar"
Any ideas?
google-spreadsheets
function getNotes_(fileId, sheetName, rangeA1)
{
var data = [];
var file = SpreadsheetApp.openById(fileId);
var sheet = file.getSheetByName(sheetName);
var range = sheet.getRange(rangeA1);
var values = range.getValues();
var notes = range.getNotes();
var getResult_ = function(value, i) { data.push( 'Cell:"' + value + '",Comment:"' + rowNotes[i] +'"') };
var rowNotes = [];
for (var i = 0, l = values.length; i < l; i++)
{
rowNotes = notes[i];
values[i].forEach(getResult_);
}
return data;
}

auto copy value of cell from sheet 2 to sheet 1 using google apps script

I’m trying to get the value of column Notes in Sheet 2 and put it to column Notes of Sheet 1. To do that, they should have the same column Company value. When I enter a value in Company (Sheet 2), the code will find if it has the same value in Company (Sheet 1). If the code finds the same value of Company, the value in Notes (Sheet 2) that I enter will automatically put in Notes (Sheet 1). I used the if/else statement in my code but it is not running.
Any help would be greatly appreciated.
Ex:
Sheet 1
enter image description here
Sheet 2
enter image description here
Here's my code :)
function onEdit() {
var sheetId = SpreadsheetApp.openById('1fx59GrC_8WEU5DCM5y2N8YR3PK936RLqZVknQ66WWUA'); //replace with source ID
var sourceSheet = sheetId.getSheetByName('Notes'); //replace with source Sheet tab name
var notesActiveCell = sourceSheet.getActiveCell();
var notesRow = notesActiveCell.getRow();
var notesComp = SpreadsheetApp.getActiveSheet().getRange('B' + notesRow.toString());
var destSheet = sheetId.getSheetByName('Companies'); //replace with destination Sheet tab name
var compActiveCell = destSheet.getActiveCell();
var compRow = compActiveCell.getRow();
var companies = SpreadsheetApp.getActiveSheet().getRange('B' + compRow.toString());
if (notesComp.getValues() == companies.getValues()) {
Logger.log(notesComp.getValues());
var sourceRange = SpreadsheetApp.getActiveSheet().getRange('C' + notesRow.toString()); //assign the range you want to copy
var notesData = sourceRange.getValues();
destSheet.getRange('F' + compRow.toString()).setValues(notesData);
}
}
There are a lot of errors in your code. I'm not a very experienced programmer, but form what you have said I think the script below should give you a good starting point.
Don't forget, you also need to add an onEdit trigger to run the script when you enter a value.
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getActiveSheet();
var sourceCellRow = sourceSheet.getActiveCell().getRowIndex();
var sourceData = sourceSheet.getRange(sourceCellRow, 1, 1, 2).getValues();
var destSS = SpreadsheetApp.openById('Paste destination Spreadsheet ID here');
var destSheet = destSS.getSheetByName('Companies');
var searchData = destSheet.getRange(1, 1, destSheet.getLastRow()).getValues();
for (var i = 0; i < searchData.length; i ++){
if(searchData[i][0] == sourceData[0][0]){
destSheet.getRange(i + 1, 2).setValue(sourceData[0][1]);
break;
}
}
}
Try using the copyTo(destination)
Copies the data from a range of cells to another range of cells. Both the values and formatting are copied.
// The code below will copy the first 5 columns over to the 6th column.
var sheet = SpreadsheetApp.getActiveSheet();
var rangeToCopy = sheet.getRange(1, 1, sheet.getMaxRows(), 5);
rangeToCopy.copyTo(sheet.getRange(1, 6));
}
I think that will be invaluable inside your onEdit() function.\
You might also want to check this sample from this google forum
function Copy() {
var sss = SpreadsheetApp.openById('spreadsheet_key'); //replace with source ID
var ss = sss.getSheetByName('Source'); //replace with source Sheet tab name
var range = ss.getRange('A2:E6'); //assign the range you want to copy
var data = range.getValues();
var tss = SpreadsheetApp.openById('spreadsheet_key'); //replace with destination ID
var ts = tss.getSheetByName('SavedData'); //replace with destination Sheet tab name
ts.getRange(ts.getLastRow()+1, 1,5,5).setValues(data); //you will need to define the size of the copied data see getRange()
}

How to make Google form submission sort into separate sheets?

I can only get this to sort automatically when I input the text manually into the cell. I've tried changing to OnFormSubmit but no luck. How can I rewrite this to have Google Docs automatically sort the form-submitted answers to separate tabs?
function onEdit(event) {
// assumes source data in sheet named Needed
// target sheet of move to named Acquired
// test column with yes/no is col 4 or D
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = SpreadsheetApp.getActiveSheet();
var r = SpreadsheetApp.getActiveRange();
if(s.getName() == "Inbox" && r.getColumn() == 6 && r.getValue() == "Los Angeles") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Los Angeles");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row)
}
}
Dont write the sorted sheet data manually. Instead use a single QUERY formula per sheet. With it you can filter sort grouo and pivot your data as you like.

Resources