Script suggestion to insert a timestamp when button is pressed - google-apps-script

I am new to coding and I would like your help in developing a simple script for Google Sheets. What I would like it to do is (see example):
when I press the "START" button the current time automatically gets inserted in the next available empty cell in column A in HH:MM:SS. So every time I press the button a new current time stamp gets added in the next empty cell on column A. The "STOP" button would work exactly the same just that it would and the information in column B.
I have found a code for Visual Basic that does in Excel exactly what I would like to do, I just don't know how to do this is Google Sheets. The code for the "Start" button in Visual Basic for Excel is the following:
Sub StartTime()
nr = ThisWorkbook.Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUP).Row + 1
Cells(nr, 1) = Time
End Sub

This simple solution assumes that the list of start stop times will always be the furthest down of everything in that Sheet (or ideally the only things).
If that is not the case you'll need to change it to find the last row of the range you need when inserting the data..
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
function startTime() {
ss.getRange(ss.getLastRow() + 1, 1).setValue(new Date());
}
function stopTime() {
ss.getRange(ss.getLastRow(), 2).setValue(new Date());
}
The spreadsheet tab Sheet1 will have the same layout as yours with two pictures inserted and Columns A and B formatted as Times.
Now, if you select the picture of the button that you inserted there's a little arrow in the top right hand corner.
Here you click "Assign Script" and type the name of the function (startTime and stopTime respectively).

Related

Google Sheets: Move a cell value to next empty position in Range on sheet

Looking to select multiple choice options from a drop down box.
I have this sample spreadsheet
https://docs.google.com/spreadsheets/d/1BKWZWHRvdLIc8k3MzT4ARENe2s-qD-AW5vegOMs_jqw/edit?usp=sharing
The Clear and Submit buttons should not be a problem.
I am having issues that when I click on "Add another ATA" button, I would like an app script to move the value in D7 to the next available blank cell in the range J2:J13 and then remove the value in D7 to await a new value, then click "Add another ATA" and move the new value to the next available blank cell in the range J2:J13 etc...
I have succeeded in moving the value from D7 to J2 for example.
I cant figure out how to establish via app script how to calculate what cells are blank or not so I know where to insert the code.
I have tried putting the Range J2:13 in an array and cycling through it but I wasn't successful identifying the next available blank cell range.
You can do that with the appendRows_() utility function. Paste it in your script project and call it like this:
const sheet = SpreadsheetApp.getActiveSheet();
const data = sheet.getRange('D7').getValue();
const result = appendRows_(sheet, data, 10);
...where 10 means column J.

Apps Script: How to capture oldValue of a cell after a change made by sheets api?

I am running a python script that updates my google sheet (named 'Notifications') through the sheets api every 5 minutes. The python script first clears and resizes the sheet to only two rows and then adds the new data on top and the sheet's size gets automatically expanded. I've done that not to have empty rows if my new data is smaller in size than the old one.
So the sheet is updated every 5 minutes but if nothing new happened in my data source, the new values are going to be the same as the old. In particular, the value in 'A2' is going to be the same as before the update. If something new has happened, the value in 'A2' is going to be different. I want to track that and get a pop-up message that notifies me that something new has happened after the update.
So as far as I understand I have to use onChange because onEdit only works if the changes are made by a human and cannot track changes made by the api. I'm uncertain how to do that though.
With onEdit I've achieved it and get a pop-up if I modify the content of 'A2' manually but nothing happens when python updates my sheet.
Here's the code with onEdit:
function onEdit(e) {
if (e.range.getA1Notation() === 'A2') {
let oldValue = e.oldValue
let newValue = e.newValue
if (oldValue != newValue) {
Browser.msgBox('The value in A2 changed from ' + oldValue + ' to ' + newValue);
}
}
}
So the end goal is to get a pop-up not every time python updates my sheet, but only if there's a change in the value of 'A2' after the update.
How can I do this?
The only way to get a pop-up when a a change is made through an API is by using polling function from client-side code. One way to do this is by using a sidebar to hold the client-side code.
You should store somewhere the old values then compare with the current values.
Related
How do I make a Sidebar display values from cells?
How to get all old values for a mulitple cell range with onEdit trigger
onEdit(e) not generating trigger event when cell value changes due to inbuilt function
You can use onChange trigger with a "ValueInputOption"="USER_ENTERED" to trigger a function when a script edits a sheet. But you can't show anything in the UI from the triggered context so getting a pop up will be impossible.

Input datetime when double click on a cell

I have 6 columns in google sheet doc.
(A) Date (B)Order (C)ID DEPARTMENT (D)Time sent (E)Time received (F)Delivery time
I want each time I double click column a cell under Time Sent or Time received columns - current date and time is inputted.
Date and time should stay forever (like the time of double click).
Can you please help me to create this code?
Explanation:
There is no doubleClick event in Google Apps Script.
However, you can use onSelectionChange to capture single click events.
The following script will set the value of a cell in column D or E with the current datetime upon a single click.
To prevent a cell from being updated after you selected again, you can add an extra condition to set values only when the selected cell is empty. If the cell has already a date in it, then don't update it. In this way, the original/first datetime will remain intact.
Solution:
function onSelectionChange(e) {
const as = e.source.getActiveSheet();
const row = e.range.getRow();
const col = e.range.getColumn();
if (as.getName() == 'Sheet1' && row>1 && [4,5].includes(col) && e.range.getValue()==''){
e.range.setValue(new Date());
}
}
To use this solution, simply copy & paste it to the script editor and save the changes. After that, it will automatically be used upon single click events. In this solution I used Sheet1 as the sheet name. Feel free to change that according to your specific case.

Trigger for Google Sheets

I have a Google Spreadsheet that will send me an email once a figure in a cell reaches a certain number. I tried setting up triggers, but it doesn't work for what I need.
I need some code to open up the spreadsheet every 2 hours and then check the cell. If the number is greater than what I want, then it emails me.
Does anyone have their own code that I can add to my email function that will do this?
Any help would be appreciated.
The following code will check the value inside a cell and if the number inside the cell is greater than your specified limit, it will send an alert to the given email address.
function sendEmail() {
// get the number in the specified cell. Here I used the cell B2 for reference
var sheet = SpreadsheetApp.getActiveSheet();
var rowNum = sheet.getRange('B2').getValue(); //take the value to rowNum
if(rowNum > your_number_limit ){
var message = 'This is your Alert email!'; // Second column
var subject = 'Your Google Spreadsheet Alert';
MailApp.sendEmail("youremailaddress", subject, message);
}
// Send Alert Email.
}
To check the value every 2 hours do the following
From the Script Editor,
choose Resources > Current project's triggers. You see a panel with the message No triggers set up. Click here to add one now.
Click the link that says No triggers set up. Click here to add one now.
Under Run, select the function you want executed on schedule.
Under Events, select Time-driven.
On the first drop-down list that appears, select Hour timer
set interval of hours for 2 hours.
Click Save.
To ensure that the script runs at the correct time for a particular time zone, click File > Properties, select a time zone and click Save.

How to fix this error in programmatically (with trigger) active() the last occupied row in a Google sheet?

Supose you have a sheet with several hundred rows long. You could to this to go to the last row and start your work:
1) after opening the spreadsheet, do Ctrl End; Ctrl leftArrow; Ctrl
upArrow
this will take you to the last occupied row cell in column A 2) before closing the spreadsheet, select the last occupied cell in
column A and assign it range name endRow then when you open the
spreadsheet do Edit > Named ranges then click on endRow this will take
you to the last occupied row cell in column A;
I just find a way to programmatically implement this, it's really simple, but worked only in the oldspreadsheet. I just put this line inside onOpen() trigger and just works fine: activeSheet.getRange(activeSheet.getLastRow(), 1).activate();.
But it didn't work in the new Google Sheets (a new one with some thousands of rows).
So, I tried the Zig advice, write this function:
function goToLastRow() {
var s = SpreadsheetApp.getActiveSpreadsheet();
var range = s.getRange(s.getLastRow()+1, 1);
range.activate();
}
And set the trigger manually (Script Editor>>Resources>>Triggers from this project>>Ad new trigger). But it still didn't work.
Any suggestion?
I found this way to accomplish what you need:
function onOpen() {
var sheet = SpreadsheetApp.getActiveSheet();
sheet.hideRows(1,sheet.getLastRow());
}
This hides all rows with data from the active sheet, places the cursor on the next (empty) row, so you can start typing away.
when done with the row, simply click the little triangle to the left of the hidden rows, and they will reappear if you need so.
Might cause problems if more than one person enters new rows at the same time.
★ Here is another cool way to accomplish this without any scripting, plus works even with simultaneous users (the script version above could hide a row being entered if another person opens the spreadsheet with edit permissions.)
This 2nd no-script solution will only work if your data has a column with a fixed set of values (¹), for example a column with only the possible values 'pending', 'doing' and 'done'. So find such column, which I assume its on column 'A' in this example.
➮ Lets use "Filter Views" in the "Data" menu (only in the new sheets versions.)This feature allows for personalized filters that only the user applying them sees. Create a filtered view called "Enter new rows mode" with no values checked for column 'A' (click filter:"clear" when you drop-down the column filter menu).
➮ Now, when you enter the spreadsheet, the filtered view is applied automatically and all rows with data will go away.Start typing away. If other users start entering new rows, your row only goes away for them, not for you until you refresh the browser window.
➮ If other users remove the filtered view, its removed only for them, not for you.
You can also do something similar with the "old" filters but it has the same dissadvantage as the script solution regarding multiple users.
*¹ A fixed set of values is needed because the spreadsheet filters automatically add new items as checked in the view. You cant use a date column because you will always get new future values.To configure the filter you need to already have at least one row per possible value, so that you can uncheck them in the column filter.If new values are later entered, you need to edit the view to uncheck it.
I just find the way, it's really very simple, just put this line inside onOpen() trigger and just works fine: activeSheet.getRange(activeSheet.getLastRow(), 1).activate();.
But it didn't work in the new Google Sheets.
So, I tried the Zig advice, write this function:
function goToLastRow() {
var s = SpreadsheetApp.getActiveSpreadsheet();
var range = s.getRange(s.getLastRow()+1, 1);
range.activate();
}
And set the trigger manually (Script Editor>>Resources>>Triggers from this project>>Ad new trigger).
Any suggestion?
Change getActiveSpreadsheet to getActiveSheet. The spreadsheet is all the file, a sheet is just a sheet :P. But you will find that you cant go to any part of a spreadsheet in an onOpen trigger.
The best way is to create a menu for this.
At the end the code goes like this:
function onOpen() //the same to create a onOpen trigger
{
SpreadsheetApp.getUi().createMenu("Go to").addItem("Last Row", "goToLastRow").addToUi();
}
function goToLastRow() {
var s = SpreadsheetApp.getActiveSheet();
Logger.log(s.getLastRow());
var range = s.getRange(s.getLastRow()+1, 1);
range.activate();
}