How to catch last update in sheet - google-apps-script

I have three Google Forms which submit data to different sheet in Spreadsheet. Google Forms write time stamp in first column when data is submitted. My triggered function send the email notification on submit data to spreadsheet from GForm. I need a different content of notification depending on the sheet of the spreadsheet where data is submitted.
I think about this:
get last update of spreadsheet
switch first sheet to action sheet
find the date equals the last update data in action sheet
if date is not founded, switch to next sheet and find last update date
...
...
if date is founded
get name of action sheet
send content-associated notification
So, think it's too difficult. Of course I can create many spreadsheet with many scripts and each script will send different notification, but it is not ergonomic.
Thank you!

In the event coming from your forms you can get the timeStamp and the row number where the response is recorded. With both criteria I guess it shoudn't be too hard to find the right sheet, just examine this row number in every sheet and compare the time values, if there is a match then you get it !
You can get the values in the eventinfo like this:
Logger.log('row = '+e.range['rowEnd'] + ' timestamp = '+e.namedValues['Timestamp'] )
I didn't test further so please update here is it worked as expected (or not).

Maybe you can add an onEdit trigger:
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
var sheet_name = s.getName();
//you can also add a code to get row and col, timestamp, etc.
}
Note: haven't tested this code. I assume this is what you want.

Related

Google form to generate a unique value for each form submission

On Google form submission, I am trying to get a unique patient id in column A automatically whenever there is a response being submitted. You can also see the formula in the formula bar.
As of now, I am able to do it with the following google script but due to the trigger limit, it is not getting fulfilled as the COVID response is quite higher and requests are keep coming in.
function myFunction1() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var lr=sheet.getLastRow()
sheet.getRange(lr,1).setFormula('="PID"&row()-1');
}
If I add the formula to all cells in column A of this sheet, every time a new row is being inserted on form submission and the formula is NOT available for that row by default.
So, Is there a way that I can automate generating the PID automatically.? or any other smart ideas without the trigger option?
Alternative ARRAYFORMULA in cell A1:
=arrayformula({"Patient Unique ID #";if(B2:B<>"","PID"&row(A2:A)-1,iferror(1/0))})
"Patient Unique ID #" puts the title (Patient Unique ID #) in cell A1, then the ; returns the line.
If B is not empty then generate the unique ID as per "PID" and a unique number based on ROW() less 1. If B is empty, then nothing iferror(1/0).
In Google Sheets, this sort of thing is usually done with an array formula. I would recommend that you leave the 'Form Responses 1' sheet as is and insert the timestamps in a new sheet with something like this:
cell A1:
=arrayformula(
ifs(
row('Form Responses 1'!A1:A)) = 1, "Patient ID",
isnumber('Form Responses 1'!A1:A), row('Form Responses 1'!A1:A) - 1,
true, iferror(1/0)
)
)
cell B1:
={ 'Form Responses 1'!A1:Z }
If you absolutely want to insert the Patient ID column directly in the form responses sheet, you may want to place it on the right after the columns that get updated by the form.
An array formula is more reliable than using a function that runs on a trigger, but do note that the patient IDs will be dynamic and only remain valid as long as no rows are inserted or deleted in the data. The same is true with your current approach.
To get static IDs, use an on form submit trigger that writes an ID on a row when that row is first submitted. See the insertUniqueId_ script for one example — it runs on an on edit trigger, but can be modified to run on an on form submit trigger.

Create a response table with a Google sheet which saves responses in another sheet

I'm trying to create a response table with a Google sheet that lets people enter their responses. Then compile that information into another Google Sheet by specified columns at the bottom of the previous response.
I have tried numerous ways but I cannot seem to get the script to work.
Broken Down, I need the Script/Guide to be able to:
Allow multiple people to record their response individually by the given link of Google sheet Form
Give a dynamic Sum Total in the Total Row
Have an Add row Icon so as to let respondent add rows dynamically and make their own choice of inputs
Create a Submit Icon, which records the response to another google sheet
The intended sheet is below
https://docs.google.com/spreadsheets/d/1cQTBONtpLiMbRmtVgSyOT_mShzzwbrX7-w46zy9w9I4/copy?usp=sharing
This may be a simple question that I didn't sound any solution
Please see if this works for you.
Modified enquiry form
1. Allow multiple people to record their response individually by the given link of Google sheet Form
You need to share a copy of your spreadsheet. Do not share the original. In the URL you have posted, replace 'edit' with 'copy'.
The modified enquiry form
2. Gives a dynamic Sum Total in the Total Row as your user records their inputs by using onEdit function.
3. Has an Add row and Delete row Icon so as to let respondent add and delete rows dynamically and make their own choice of inputs. To add a row, the active row number should be 4 or above
4. Creates a Place Order Image, which appends the response to another google sheet
To achieve point 4, you need to create a separate spreadsheet having 1 row only. This serves as the column heading and can be in a form as shown below. This spreadsheet contains the details of responses from all users.
Note: Updating a spreadsheet automatically when the user clicks the Submit button would require you to make the spreadsheet shareable via email addresses with editor access at a minimum. This is potentially an unsafe way of saving user responses.
function sendData() {
var sprsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = sprsheet.getActiveSheet();
var range = sheet.getRange("A2:G4");
var values = range.getValues();
var mainsprsheet = SpreadsheetApp.openById("main sheet id");
// 1. this "main sheet id" should say something like: "1cQTBONtpLiMbRmtVgSyOT_mShzzwbrX7-w46zy9w9I4", you can xopy/paste the id from your address bar in your browser
// ==> https://docs.google.com/spreadsheets/d/1cQTBONtpLiMbRmtVgSyOT_mShzzwbrX7-w46zy9w9I4/edit?ts=5ed39726#gid=0
var targetSheet = mainsprsheet.getActiveSheet();
targetSheet.appendRow(values);
// 2. appendRow() accepts an array like for example this array with strings ["Fabric Code", "Thickness","Width","Length","Finish","Quality type","Quantity"]
// method getValues() returns an array of arrays (or 2D array) like for example this one[["Fabric Code", "Thickness","Width","Length","Finish","Quality type","Quantity"]]
// Think of the outer [..] as row indicator and the inner [..] as the array that holds the columns(fields) of the record.
// i would change your code to: (remove the //s)
// var lr = targetSheet.getLastRow()
// var lc = targetSheet.getLastColumn()
// targetSheet.getRange(lr+1 , 1, values.length, values[0].length).setValues(values)
//Clear the cells (optional)
range.clearContent();
}

Google Form get Google Sheets Value

I've got a Google Form to enter deposits and withdrawals into a Google Sheet and then the ending balance is calculated so the user can balance their check book.
I'm trying to get the most recent balance to display on the Google Form by finding the last row with a balance that is in the 'Ending Balance' column.
It seems a script may be easiest but nothing seems to so what I need. Any advice or direction is appreciated.
Here's the sheet I have set up, it's connected to my form with the headers in row 2.
Google Sheet Image
You can
create a bound script attached to your destination spreadsheet
set up a installable trigger onFormSubmit that will fire every time a new form is submitted
access the newest form submission data with getLastRow()
Retrieve the values in column 11 (which contains your Ending balance)
Sample script:
function getMyBalance(){
var sheet=SpreadsheetApp.getActive().getActiveSheet();
var row=sheet.getLastRow();
var column=11;
var balance=sheet.getRange(row, column).getValue();
Logger.log(balance);
}

Google Script to force new spreadsheet entries to start at Row 2 after running script to clear the range

I'm an elementary teacher with limited coding experience but I enjoy trying to figure things out if it simplifies my life. :)
I created a Google Form for my students to make their daily lunch choice.
I set up a script that has a trigger to clear the form between midnight and 1 am each night, and it looks like this:
function clearRange() {
//replace 'Sheet1' with your actual sheet name
var sheet = SpreadsheetApp.getActive().getSheetByName('Lunch');
sheet.getRange('A2:G25').clearContent();}
The script itself works - however, now, whenever new entries are added, they are added to the spreadsheet row right below where the old entries were cleared. Thus, if I have twenty students responding on Monday, the spreadsheet has rows 2-21 filled out, which get cleared sometime overnight Monday/Tuesday AM, and the next day, the responses fill rows 22-42, etc. etc.
How can I edit or add something to my script that forces it to put all new entries, after the old ones are cleared, on Row 2 of my spreadsheet?
If this question has already been answered, please point me in that direction as well.
Thank you!
Instead of clearing content from cells, you need to delete rows containing form submission.
Here is the modified code which should work for you. Also, make sure you do not have any frozen row/s.
function clearRange() {
//replace 'Sheet1' with your actual sheet name
var sheet = SpreadsheetApp.getActive().getSheetByName('Lunch');
//get last row, this will be used to count how many rows to delete
var lr = sheet.getLastRow();
//delete row from 2 to last row
sheet.deleteRows(2, lr-1);
}
You're using the .clearContent() method and Google Forms keeps track of the responses based on the row in your spreadsheet, you need to delete the row completely using deleteRows(rowPosition, howMany), like this:
function clearRange() {
//replace 'Sheet1' with your actual sheet name
var sheet = SpreadsheetApp.getActive().getSheetByName('Lunch');
sheet.deleteRows(2, 25);
}
Note: This will not restart the counter you see in the Google Forms user interface:
In order to do that, you will need to use the deleteAllResponses() using the FormApp Class

Spreadsheet Email Trigger

I have Written Script on Google Spreadsheet to send Email when spreadsheet is modified or any Data is added. Email Trigger is working but whenever any data is entered in next Row it send Email to previous email address also.
Please suggest solution
The below is written script :
function onEdit(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 1; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1 , numRows,3) // Fetch the range of cells A2:B3
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[2]; // First column
var message = row[0] + "requested" + row [1]; // Second column
var subject = "Sending emails from a Spreadsheet";
MailApp.sendEmail(emailAddress, subject, message);
}
}
Your question is unclear... nowhere in the script I see something that reads which cell is actually modified... your target range is hardcoded on row 2 so the only row that can be processed is row 2 (and the mail can only be sent once)...
So can you :
explain how it should work
explain how it works now , especially what do you mean by 'previous email'
remove typos in your code (row[2] is not First column)
explain how you trigger this function : the name onEdit(e) suggest an onEdit trigger but simple triggers cannot send mail so I suppose you have set some other trigger.
explain why (e) in your function parameter and not using it ?
EDIT : thanks for the complement of information.
The script you suggest is not sufficient to achieve what you want. The idea here is to check if something in the sheet has been modified either by adding (or inserting) a row of data or (if I understood well) by editing any row in the sheet with a new value.
This is not really as simple as it looks at the first glance ;-)
What I would do it to take a 'snapshot' of the sheet and -based on a timer or onEdit - compare that snapshot to the sheet's current state.
There is more than one way to get that result, you could have a second sheet in your spreadsheet that no one could modify and that is a copy of the main sheet that you update after each modification/mail send. So before updating the script should look for any difference between the sheets and send a report to the corresponding email when a difference is found.
Another way to do that is to store the sheet data converted to a string in the script properties, the principle is the same but it's more 'invisible' for normal users accessing the spreadsheet.
You could also use scriptDb or your userproperties but the script properties is probably better suited (simpler) for this use case.
Tell us what you think/prefer and I (or someone else) could probably give you some code to start with.
It appears that you're using a shared spreadsheet to collect the add-user-requests, and trusting the requesters to fill in the information. In the detail document you shared, it further appears that requests are ADDED, but not EDITED. (That's an important simplifying distinction.)
I suggest that what you really need is to use a form for receiving that input. Using a form will create a "data table" within your spreadsheet, a set of columns that you must not mess with. (You can edit the contents, add and delete rows, but must not add or remove columns.) However, you CAN add columns to the spreadsheet outside of this table, which gives you a handy place to store state information about the status of individual requests.
Further, you can trigger your processing to run on form submit, rather than a simple "onEdit" - this gets away from the problem that ScampMichael pointed out. Alternatively, you can use an installable edit trigger, as described in this answer.
Try this sheet, and this form. Save yourself a copy, go into the script and remove the comments that are stopping emails from being sent, and try it out. There's a menu item in the spreadsheet that can kick off processing; just clear the "Request State" column to re-run it. You can open the form (and find its URL), and add more entries to experiment.
It's the core of a similar system that I've written, and contains a discreet state machine for processing the requests. My system has large amounts of very complex data in multiple spreadsheets, so it often gets pre-empted, then needs to run again. (I use a timed trigger for that.) That's why requests are handled through states. If you find that too complex, pull out only the parts you need.