Google Script Editor - script to continuously monitor column - javascript

Thanks in advance for your help, i've been working on this for a long time with no tangible results.
I'm using TypeForm (https://www.typeform.com/) to receive answers to a questionnaire. I'm then using Zapier (zapier.com) to input the responses as a row in a google sheets doc when the form is submitted.
The issue is that there are a few empty columns that i need to fill in once the data is submitted. For example, customer number,as well as Order Date.
I can't get anything to work because the OnEdit function only works for manual edits. I was also thinking about using OnOpen but could get it to work.
What i'm hoping for is a script that runs continuously to check and see if the cells within the column have data in them, and if so, on same row but different column enter in the date (MM dd YYYY) and then in another cell in the same row would be the customer id. The customer id would be generated by sequentially adding a number to that days date. For example. if it was todays date, the customer id would be 063020170001 (there were be 3 extra digits of padding). The next form that came in for the same day would have 063020170002 as a customer Id. Then, the next day, when a form comes in, the customer id would change with day and the sequence would start over, 070120170001. Lastly, once a date has been inputted into a cell, i don't want to allow it be written over, basically don't have the script look at that cell once it's written to.
If you have any advice on how to create this script or even what direction to take, it would be greatly appreciated.
Thanks,

Here's a simple example as a starting point for you.You'll probably have different data so you'll have to change some of the column indexes, Spreadsheet ID and sheetnames. You will also have to hook this up to a time based trigger which you can do from the Script Editor in Edit/Current Project Triggers.
function checkFormResponses()
{
var ss=SpreadsheetApp.openById('SSID');//add spreadsheet id
var sh=ss.getSheetByName('SHEETNAME');
var rg=sh.getDataRange();
var rgA=rg.getValues();
for(var i=0;i<rgA.length;i++)
{
if(!rgA[i][4])//COLUMN INDEXES WILL PROBABLY NEED CHANGING
{
rgA[i][4]=Utilities.formatDate(new Date(), 'GMT-6', 'd/M/yyyy HH:mm:ss');
rgA[i][5]=Utilities.formatDate(new Date(), 'GMT-6', "MMddyyyy") + paddingLeft(String(i),"0",4);
}
}
rg.setValues(rgA);
}
function paddingLeft(padded,padding,length)
{
var s=padded;
for(var i=0;s.length<length;i++)
{
s= padding + s;
}
return s;
}
My Spreadsheet looks like this.
And after being filled in:

Related

Script for last edited/modified time & date

I have been searching around for a script that will give me the time & date that a google sheet was last modified.
I have a list of all the google sheet workbook IDs in column E of a sheet called 'Planner Directory' and I would like it to return the time & date last modified in column F.
This would be really helpful if anyone can assist?
Since you already have all the data in a Google Sheet, I think the easiest way to get this working automatically is using Google Apps Script. I will leave an example of how it would work.
Try this code:
function myFunction() {
var ss = SpreadsheetApp.getActive().getSheetByName("Sheet20"); // Change it to the name
// of the sheet you. are using
var range = ss.getDataRange();
var values = range.getValues();
for(var i=1; i<values.length; i++)
{
values[i][1] = lastModifiedTime(values[i][0]); // 0 is the column number in my testing sheet
// where the IDs are.
// 1 is the column number where the time will be.
}
range.setValues(values);
}
function lastModifiedTime(id)
{
var file = DriveApp.getFileById(id);
return file.getLastUpdated();
}
Input data:
Replace the Sheet ID fields with valid IDs.
Result:
Remember to change the format of the column where you want you have the last modified time to Number > Date time.
Now, in order for you to automate this script you can use a time-driven trigger from Google Apps Script so that the script runs every 5, or 10 minutes for example and so that you can always get the latest time in the results.
Trigger:
References:
Method: getLastUpdated()
Time-driven triggers
I was able to use the suggested script to get the last modified date of a file, which is great but I am having two issues. In the next column of the spreadsheet I had a formula which would tell me if the last modified date is today's date. =if(C2=Today(),"Updated","Not Updated")
The formula doesn't recognize the last modified date that is entered by the script, even though I have that column format set to Date.
When the script suggested in this thread runs, it wipes out the formula entirely and replaces it with static text.

How to make google app script - calendar createEvent() to accept GSheet inputs from cells populated using array formula

A few days ago I got help from Stack Overflow to modify my then Apps Script code used to make calendar events from info on Google sheet, so as to tick a checkbox whenever an entry from the corresponding row is made and subsequently make new events only when the checkbox is unticked.
function addEvent() {
let webinarCalendar = CalendarApp.getCalendarById("blablablablablabla#gmail.com");
let calendarSheet = SpreadsheetApp.getActiveSheet();
let schedule = calendarSheet.getDataRange().getValues();
schedule.splice(0, 1);
const k = 16; // colIndex of checkbok col
const created = schedule.map(e => [e[k]]);
schedule.forEach(function(entry, i) {
if (entry[k] == true) { return; }
webinarCalendar.createEvent(entry[3], entry[14], entry[15], {description: entry[13]});
created[i][0] = true;
});
calendarSheet.getRange(2, k + 1, created.length, 1).setValues(created);
}
This current code worked just fine until 2 days ago when I updated 3 of the 4 cells with the required inputs to work on an array formula so that they get populated automatically whenever a new row entry is made.
The error on the app script console says :
Exception: The parameters (String,String,String,(class)) don't match the method signature for CalendarApp.Calendar.createEvent.
The parameters required for this createEvent() as per documentation are title(string), start time(string), finish time(string) and description(which is inside a javascript object I think and is also a string). To ensure that the datatype did not somehow get changed in the process of creating array formula, I cross checked the cells with an ISTEXT() and all of the inputs returned TRUE.
Second trial that I made was to change the splice() from (0,1) to (0,2) so that it ignores the first row which has the array formula written into the cells, which also did not fix the issue.
I would greatly appreciate if someone could show me what is causing this issue and help me fix it.
I don't know why it worked previously, but startTime and endTime should be Date.
I have checked that you columns are String.
Reference:
createEvent(title, startTime, endTime, options)
The error on the app script console says : Exception: The parameters (String,String,String,(class)) don't match the method signature for CalendarApp.Calendar.createEvent.
This is simply saying it's reading from data that is not in the proper data type. In this case, perhaps, try encasing the entries with 'new Date(entry[x])' for the respective start and end date/time entries.
For people trying to run the scripts, one underlying cause might be the fact that you may be using US locale when the date have been formatted as UK.
(e.g. Date that App Script is looking for is mm/dd/yyyy tt:tt:tt, but if you click in the formula cell it shows as dd/mm/yyyy tt:tt:tt)
What you would do is to go to Files > General > Locale > (Country of Choice) > Save settings.
You would then reload the page and try if the script is working now without that "Cannot find method createEvent(string,string,string)" error.
The line of code to use in your script would be:
SpreadsheetApp.getActive().setSpreadsheetLocale('en_UK');
You could include it in your onOpen trigger function.

Google sheet script to add a week to a date from the sheet

Sorry - I'm a newbie!
I need to use a script to read a date from a Googlesheet, add a week and save the new date back to the sheet.
I've tried various suggestions from various posts without success. The approach I thought should work is failing to get a millisecond value from a date from a cell - subsequent processing appeared OK.
var oldDate = sheet.getRange('oldDateRange').getValue(); // obtains a date object and then...
var oldDateValue = oldDate.getMilliseconds() // I expected to return milliseconds but shows as undefined...
See link to a simplified illustration sheet and script illustrating my problem.
This is my first question on StackOverflow - feedback welcome on how to make it more helpful for others....
In order to convert the date obtained from the sheet to milliseconds, I think you simply need to replace .getMilliseconds() with .getTime()

function recalculates every time i open the sheet, I only want it to recalculate on edit

function timestamp() {
return new Date()
}
The function recalculates every-time i open the sheet. i only want it to recalculate on edit.
I have tried to mess with "onEdit" but i can never get it to work. I have also tried the "current project triggers" but that doesn't seem to fix the problem. I apologize that for the simplicity of the question, I simply can't find or figure out the answer.
Google sheets script
https://docs.google.com/spreadsheets/d/1-Ix9LUmMYNqWnz0mB2PAg9ocJ-TwszqHRbqxAchcxhc/edit#gid=0
It looks (based on your comments on the question), like you've created a custom formula and put it in a cell. If that's the case (meaning that you actually have =timestamp() in a cell), then it will always recalculate both on open and on edit.
That's just how formulas (both the standard ones and custom ones) work. You'll notice this when you have start to have too many formulas in a spreadsheet and it starts to slow down, or even not load correctly.
If you want something that only updates on edit, you'll have to write a function that does exactly that, then set a trigger that calls it on edit.
For example, this function will put the current date in cell A1 of the first sheet of the current spreadsheet:
function setTimestamp()
{
var thisSS = SpreadsheetApp.getActiveSpreadsheet();
var firstSheet = thisSS.getSheets()[0];
var firstCell = firstSheet.getRange(1, 1);
firstCell.setValue(new Date());
}
This kind of function will only run when you call it, so you can set the trigger to whatever you want. Obviously, you'll have to figure out how to select the cell where you want the date to appear.

Get next closest time from a table based on selected hours and minutes

I have a long table with columns of schedule data that I'm loading via a form with jQuery load(). I have access to these html pages with the table data and can add classes/data attributes etc.
My form has select fields for hours and minutes (defaulting to the current time) and I'm trying to get the next closest time plus the four after that.
The time data in my tables are all formatted as <td>H:MM</td>.
Ideally with jQuery, I was wondering how I can strip the table data of everything but those times. Alternatively, since I can reformat this data would I be making my life easier to format it a certain way?
Things I've tried - I am admittedly a novice at js so these things may seem silly:
Reading the first character of each cell and comparing it to the
selected hour. This is obviously a problem with 10, 11, 12 and is
really intensive (this is a mobile site)
Using a single time select field thenCreating an Array of each
column to compare with the selected time. Couldn't get this working
and also creates an issue with having to use a single select for
every time.
Basically looking for a little guidance on how to get this working short of, or maybe including, copying all the html tables into JSON format...
May as well post http://jsbin.com/ozebos/16/edit, though I was beaten to it :)
Basic mode of operation is similar to #nrabinowitz
On load, parse the time strings in some way and add to data on each row
On filter (i.e. user manipulates a form), the chosen time is parsed in the same way. The rows are filtered on row.data('time') >= chosen_time
The resulting array of elements limited to 5 (closest time plus four as OP requested) using .slice(0, 5)
All rows are hidden, these rows are displayed.
Some assumptions have been made, so this code serves only as a pointer to a solution.
I thought this was an interesting question, so I put together a jsFiddle here: http://jsfiddle.net/nrabinowitz/T4ng8/
The basic steps here are:
Parse the time data ahead of time and store using .data(). To facilitate comparison, I'm suggesting storing the time data as a float, using parseFloat(hh + '.' + mm).
In your change handler, use a loop to go through the cells in sequence, stopping when you find the index of the cell with a time value higher than your selected time. Decrement the index, since you've gone one step too far
Use .toggle(i >= index && i < index+4) in an .each() loop to hide and show the appropriate rows.
Here's how to do it on client side. This is just an outline, but should give you an idea.
// Create a sorted array of times from the table
var times = []
$('#mytable td').each(function(cell) {
times.push(cell.innerHTML);
});
times.sort();
// Those times are strings, and they can be compared, e.g. '16.30' > '12.30' returns true.
var currentTime = '12:30' // you probably need to read this from your select
var i = 0;
while (times[i] < currentTime || i=times.length) {
i++;
}
var closestTime = times[i];
var closestTimes = times.slice(i, i+4);
If you want to access not the times, but actually the cells containing the times, you can find them like this:
$('#mytable td').each(function() {
if ($(this).text() in closestTimes) {
// do something to that cell
}
})

Categories