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.
Related
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.
My plan is to calculate how many days between 2 given dates by using function DATEDIF in Google Spreadsheet and the function must be from Google Apps Script. I can get it by below.
sheet.getRange(x,10).setFormula('datedif(K32,L32,"d")');
However, as the row is increasing by AppendRow whenever GAS calls spreadsheet so I tried to use variable x to get the last row. It makes me know where the target row is. My trouble is that I could not let setFormula to use variable as below, where start and due are A1Notation of the 2 given cells with date.
sheet.getRange(x,9).setFormula('datedif([start],[due],"d")');
MY code is as below.
var x = sheet.getLastRow();
sheet.getRange(x,11).setValue("2020/05/20");
sheet.getRange(x,12).setValue("2020/07/21");
start = sheet.getRange(x,11).getA1Notation();
due = sheet.getRange(x,12).getA1Notation();
sheet.getRange(x,9).setFormula('datedif([start],[due],"d")');
sheet.getRange(x,10).setFormula('datedif(K32,L32,"d")');
Answer:
You need to concatenate the cells' A1 notations into your string in setFormula().
Code Modification:
As of V8, you can use template literals inside Google Apps Script. You can do this as below:
start = sheet.getRange(x,11).getA1Notation();
due = sheet.getRange(x,12).getA1Notation();
sheet.getRange(x,9).setFormula(`datedif(${start},${due},"d")`);
References:
Template literals (Template strings) - JavaScript | MDN
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()
Hello Stack Overlords!
I'm currently trying to put together a little coding project. Something simple, but I'm having a rather difficult time.
The objective, clear out three cells once the time of day, based on one of those cells, passes.
Essentially - G9 contains the the time I want the cells to be cleared. Once it has gone past the time of day specified in G9, I'd like cells D6, D9 and G9 cleared.
I've set up a way of doing this using an IF statement, both from the sheets side, and scripts side. On the sheet itself, I have a 1/0 toggle in cell K12. If the value in G9 is greater than the time now (stored in K11), it shouldn't be deleted, so is set as "1". As soon as the value in G9 is greater than the time now stored in K11, it set's the value to "0", meaning it should be deleted.
I've got Google Scripts to check the value of cell K12, and to delete my specified ranges if K12 = 0, as so:
function ClearCells() {
var s = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('AutoDeleteCellsOnTimeExpired');
var Check = s.getRange("K12").getDisplayValue();
if (Check == "0"){
s.getRange('D6').clearContent();
s.getRange('D9:G9').clearContent();}
}
I've then set a toggle on the Scripts function, to run the script once a minute. The issue is, the script will not clear the cells, even after the value in K12 has changed from "1" to "0". The execution transcript shows the code executes fine.
Here's the clinch... If the value is 0, to begin with (I set a value in G9 already later than now), the script runs fine automatically, as expected. After taking a look, it seems that Google Sheets assumes because there hasn't been a USER edit to the sheet (the spreadsheet settings are set to re-calculate NOW formulas once a minute), it thinks the value can't be different and doesn't bother to re-check the value in K12. If I edit another cell on the spreadsheet (even totally unrelated), Google Scripts then checks the cell value again as expected.
This indicates to me it's because it's caching the value of K12, not expecting it to change without user input (which is wrong because it updates itself based on an automatic =NOW update)?
If I'm wrong, please let me know! Otherwise... how can I stop Google Sheets assuming this? I've tried adding a flush() command, but that did nothing.
Link to the spreadsheet can be found here (this is a disposable version, only showing the need-to-see info - edit and tweak away): https://docs.google.com/spreadsheets/d/1AGOLuvGCNWJk1Ft9T2ifjcf9CzCXNHysLiSvsUwxZW4/edit?usp=sharing
Many thanks for your time!
Your assumption
This indicates to me it's because it's caching the value of K12
is correct. The values are cached as to retrieve the data much more efficiently and quickly. The easiest way to refresh the cache is by making a dummy setValue() or clearContent() calls, before you retrieve the value using getValue(). Like so
function ClearCells() {
var s = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('AutoDeleteCellsOnTimeExpired');
s.getRange("A1").setValue("DummyValue") //Dummy Call
Logger.log("SetValue")
s.getRange("A1").clearContent() //Delete Dummy Value
// You can use either just clearContent() or setValue() and clearContent() calls
// To achieve the same result
var Check = s.getRange("K12").getValue();
Logger.log(Check)
if (Check == 0){
s.getRange('D6').clearContent();
s.getRange('D9:G9').clearContent();
}
Logger.log("New Version")
}
Alternatively, you can check the time value to the current time in the google app script directly and perform the required function, like so:
function ClearCells2() {
var s = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName('AutoDeleteCellsOnTimeExpired');
var curTime = new Date()
var expTime = s.getRange("G9").getValue().split(":")
Logger.log(curTime.getHours() +":"+curTime.getMinutes())
Logger.log(expTime[0]+":"+expTime[1])
if (curTime.getHours() >= expTime[0] && curTime.getMinutes() > expTime[1]){
Logger.log("Clear")
s.getRange('D6').clearContent();
s.getRange('D9:G9').clearContent();
}
}
References:
Date(),date.getHours(),date.getMinutes()
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: