I am struggling to understand what is happening within a script I am developing.
The situation is the following: on cell B2 I have inputted 06:45PM, which is automatically taken as time format by GSheets.
On the dummy script, I have the following dummy code:
function whathour() {
var ss=SpreadsheetApp.getActiveSheet();
var t=ss.getRange("B2").getValue();
SpreadsheetApp.getUi().alert(t);
Logger.log(t);
}
(I am using alert as a debug tool, yes).
The amusing result is that the value alerted (or logged) when the function is run is [17-09-14 11:15:25:006 CEST] Sat Dec 30 19:09:05 GMT+00:09 1899. !
I would have focused on the possibility of problematic timezones if I hadnt seen that, well, 18:45 and 19:09 can never be the same time in regards to different timezones!
I am trying to collect just the 18:45 out of the cell in order to do certain time duration operations, but this first step is blocking me. Can anyone help me?
Thanks!
Edit: attached an image of what I described:
How about using getDisplayValue()? This retrieves the displayed value of the cell. The modified script is as follows.
Modified script :
function whathour() {
var ss=SpreadsheetApp.getActiveSheet();
var t=ss.getRange("B2").getDisplayValue();
SpreadsheetApp.getUi().alert(t);
Logger.log(t);
}
Related
I am using the attached to automate a time entry to go along with the date for a calendar import. The entries don't have times, and the staff will not enter them try as I might. I need to automate them to simplify the entry procedure.
The issue I am facing is that the Calendar API needs the data to be in DATE/TIME format. To do this I need to use the =DATE+TIME formula. When I do so and the time reaches 12:00AM, the dates thereafter change to the following day.
Essentially I need to either override the logic that makes it move into the next day after midnight appears, or I need to tell either the function in column B-C that it can never roll to midnight. I am trying to think of perhaps a way that I can tell the function to reset the time if the date in column A changes to a new day, and if it doesn't change to a new day go ahead and use the existing function and add 5 minutes to the time that is shown previously to it.
I am stumped, any help would be greatly appreciated.
Here is a sheet to show you the issue
Here is the formula I tried, which worked to sort out the problem but did not work with the Calendar API requirements to format at DATE/TIME. Even when using the importrange formula to move the data into a new sheet with the cells formatted as DATE/TIME it still recognizes it as TEXT as this is what the formula prescribes.
=IF(A2<>"",(CONCATENATE(TEXT(A2,"MM/DD/YYYY")&" "&TEXT(B2,"HH:MM:SS"))),"")
I need this to work in both the sheet and in the import to Calendar using the Calendar API requirements through APPScript.
If I understood correctly your question, here a suggestion with a custom Apps Script function called like a normal Google Sheet function.
Open Apps Script Editor and paste the function below
Call the function rebuildDateTime(COL1, COL2) inside your spreadsheet
Spreadsheet:
Code:
function rebuildDateTime(arg0, arg1) {
var date = new Date(arg0);
var str = arg1.toString().split(':');
date.setHours(str[0]);
date.setMinutes(str[1]);
return date;
}
Warning :
Your COL2 (which contains only the time), must be forced to TEXT FORMAT
References :
Create a custom function
I'm looking for more of a pointer to some documentation of a method here rather than an exact solution, I'm happy with JavaScript, haven't done much Apps Script and I'm moderate to OK familiar with Google Sheets functions but far from expert.
I have part of a Google Sheet with some date specific data on it like this:
Date
Some-Value
1 Jan 2023
123
15 Jan 2023
456
... etc
In another part of a sheet I have a cell with the current value of Some-Value. This cell in fact contains a formula that totals a column on another sheet for the values. In case it's not blindingly obvious, these dates are in fact sprint end dates and the Some-Value is a count of story points extracted from JIRA. So sort of like this:
Current Value of Some-Value
345
On exactly the date in the Date column I want to copy the value from the "Current Value of Some Value" cell into the cell in the "Some Value" column adjacent to that date. I don't care if that copy happens only once on that day, or several times on that day, or every hour on that day, or whatever. I just want it to happen at least once, automatically.
Should I be looking at an Apps Script function to do this, and roughly how should I do that? Or is there a simpler way of using some Google Sheets function to copy that cell?
You could potentially do this with formulas if you are willing to enable iterative calculation for your sheet. In that case, you could then write something like =if(A2=today(),currentValueCell,B2) (I'm assuming your Date/Some-value table is in A1:Bx of a sheet and you are placing the above in B2). This will return the current value only if the date matches, and then when the dates no longer match will just maintain whatever value is already present in the cell.
EDIT
Ah yes, I forgot that the initial state of a self-referencing IF is zero (rather than null) until a TRUE occurs. Try =if(A2=today(),currentValueCell,if(B2<>0,B2,)) to hide the initial zero generated when the date in A2 is not equal to TODAY().
If you need to copy a value than then it's going to be changed or erased, yes, you'll need an AppScript. If you already know something, you'll more than able to set a simple function to do it.
You can look into Installable Triggers that will help you to set when and how frequently you want your script to be fired; and it will notify you if there are errors in any of that executions.
Sometimes, matching dates can be tricky, more if you have them previously written. If you have to do a timestamp, then you'll probably succeed at first. Just for have it handy: https://developers.google.com/google-ads/scripts/docs/features/dates
Remember to always use Logger.log() to track the progress of your code and what it's returning. Good luck and here you can always ask for specific struggles you may find!
(I'm no expert at programming by far, since it's copying only a value, you may find useful to record macros and watch them to learn how to copy in the formats you need - only values, paste format, etc. - if you don't copy, you can also research in .getValue() and .setValue() )
In case anyone else comes across this in future, here is the somewhat creaky Apps Script function I developed to do this. It's my first Google Apps Script function so feel free to tear it to shreds.
I then added a trigger to run this function weekly, which was easier than I had thought -- a bit of google searching for Apps Script time based triggers found me the answer.
Nonetheless thanks to the people who answered earlier because the clues you gave me helped me find the answer in the end.
function updateUnderTest() {
var activeSheet = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = activeSheet.getSheetByName('Supporting Data');
// I12 is the cell that gets updated daily with the story point count
var value = sourceSheet.getRange('I12').getValue();
// D3:E27 is the range containing date : value pairs
var data = sourceSheet.getRange("D3:E27").getValues();
// epochNow will be the current epoch time, in milliseconds
var epochNow = new Date().valueOf();
// Look through the data range to find a matching date
for (nn=0;nn<data.length;++nn) {
// If a match is found to the nearest day, break the loop
if ((data[nn][0].valueOf() < epochNow) && ((epochNow - data[nn][0].valueOf()) < (24*3600*1000) )) {break};
}
// only update if we found a match
if (nn < 24) {
sourceSheet.getRange(nn+3, 5).setValue(value);
}
}
I spend a lot of time to create and modify calendar-events based on lines in a spreadsheet. The plan was to modify the values in the table and update the calendar automatically. So I use a onEdit-Trigger, what worked well some time long.
But however the script-file lost the authorization now, when I use the script-functions as onEdit-Trigger or as cell-function. It works well, when I'm start that functions out of the script-editor. No authorization problems at all.
Is there a way to set the authorization manually? Without the authorization-dialog, that not appears?
In B42 the date of Easter should be calculated (=Osterdatum(A42;0))
In B43 the Easter date is written by that function, but starter in the script-editor.
The mention line 6 has the following context:
// Kalender in Google eintragen
var test = true; // bei true nix schreiben
// Kalender öffnen, um Termine einzutragen
var kalenderID = "1234567890987654321#group.calendar.google.com"; // Regionalkalender
var meinKalender= CalendarApp.getCalendarById(kalenderID); // Line 6
if (test) {
Logger.log(meinKalender.getName());
}
Can anyone help me to get the authorization back?
I found out, that usage as cell-function works, when I don't use setValue() to other cells.
So the question maybe is:
is it possible to use setValue() to other cells (e.g. C43), when I called the function as cell-function in B42?
Thanks for request.
Udo
Alright, I'm stuck.
I've got a sheet that an entire team of people use to communicate with each other and sign up for timeslots for internal logins.
I've got the sheet formatting performing the way I want to, but, it's too easily edited by people, because they have to be able to edit the values in the cells.
It's currently running Conditional Formatting rules, based upon time/date. Basically, if the cell's timeslot has passed, then it's blacked out. It is also blacked out if the cell isn't associated with the current day.
https://docs.google.com/spreadsheets/d/1TP5iJ9AA_xqDQPiyl89ntZehd7aqDPELcN0bRMGP-SU/edit?usp=sharing
I'm trying to create a script that "onEdit" will restore any formatting (not the value) that had been changed during the edit.
Got it this far, but I'm struggling to make it conditional like the UI rules allow me to do.
function myFunction() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var range1 = sheet.getRange('A1:B10');
range1.mergeAcross()
range1.setBackground('white');
range1.setBorder(true,true,true,true,true,true);
range1.setFontColor('black');
range1.setFontFamily('Arial');
range1.setFontSize(10);
range1.setFontWeight("normal");
range1.setFontStyle("normal");
range1.setHorizontalAlignment("left");
range1.setVerticalAlignment("center");
range1.setWrap(false);
}
Here's where I'm struggling (notes inserted)
function myFunction() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var range1 = sheet.getRange('A1:B10'); // I'd have this repeated for multiple ranges
range1.mergeAcross()
range1.setBackground('white'); // Need an "IF" argument for this, such as if today is Wednesday and time is before 2:30pm, then white, otherwise black. Could probably put this at a different point in the script.
range1.setBorder(true,true,true,true,true,true); // All the following attributes would simply restore defaults
range1.setFontColor('black');
range1.setFontFamily('Arial');
range1.setFontSize(10);
range1.setFontWeight("normal");
range1.setFontStyle("normal");
range1.setHorizontalAlignment("left");
range1.setVerticalAlignment("center");
range1.setWrap(false);
}
Thanks in advance for any help you might offer!
Adam
I've actually been trying to deal with this same problem.
Sadly, google scripts doesn't seem to have a way programmatically set the conditional programming. (Here's a link to the issue. You can cast a vote at the bottom on to get them to implement it)
However, I think you might be able to implement a solution to your problem it by scratch.
The onEdit trigger passes a variable to the function it's assigned to.
function testOnEdit(e) {
Logger.log(JSON.stringify(e));
}
Here is an example of the JSON from the event object for onEdit.
{"range":{"columnStart":3,"rowStart":2,"rowEnd":2,"columnEnd":3},"source":{},"value":"I typed this into B3!","authMode":{},"triggerUid":*********}
You might be able to use this to directly reset the format of the cells they edit. BUT... Unfortunately, onEdit is only fired when a range's values are changed--not when formatting is changed, not when data validation is changed, not when conditional formatting is changed--so to catch the cases that some rouge user decides that purple looks nice, you may want to also make the script run every minute using a timed trigger (but you need to make sure it doesn't take too long to run since it will be going off every minute and google puts a limit on total amount of time triggers can run).
As for comparing dates, these functions may be useful, but be warned that they return the local time (if you have users from multiple time zones you may need to convert to UTC).
function myFunction() {
var date = new Date();
date.getDay(); // the value returned by getDay() is the index of the day of the week, where 0 is Sunday, 1 is Monday...
date.getHours(); // the value returned by getHours() is an integer between 0 and 23
date.getMinutes(); // the value returned by getMinutes() is the current minute in the range 0-60
}
Since I too am dealing with this problem, I plan to add more insight to this solution later. Let me know if you have any insights, Adam.
UPDATE: Based on earlier answers, I joined the chorus of people asking Google to re-enable the ability to do this, and they have apparently complied.
Now to figure out how to implement it since I know nothing about scripting in Google Sheets.
ORIGINAL QUESTION BELOW
I have a spreadsheet with a number of different sheets that require daily entry of data. For example, there's a sheet called US-Sales, with a row for each day of the year. There are also several other identical sheets, like UK-Sales, US-Rentals, etc.
I would like focus to auto-jump to the proper row, based on the current date, whenever one of these sheets is opened.
Possible? If so, how?
This could normally be achieved by a simple script with an onOpen() function (that executes on spreadsheet opening) and activates the desired cell (or sheet)...
but, due to a change in the new version of spreadsheets (that you are most probably using) this is not possible anymore (for now), see this issue (3928) and feel free to star it so that hopefully Google team will change their mind and make it possible again ;-)
edit : this simple code works in old version of spreadsheets, it does not in new version.
function onOpen() {
SpreadsheetApp.getActive().getSheets()[0].getRange('B6').activate();// an arbitrary cell
// not worth trying more complex cell selection (on date or anything else) while this is blocked by design .
}
Details on this change here and below.
EDIT 2 :
On october 16 2014 this issue is now fixed and the code above works also in new version of spreadsheets. details of issue here
to automatically activate the row corresponding to the day of the year you can use a code like below :
function onOpen() {
var day = new Date().getDOY();// this uses a custom date method that returns the day of the year and is defined below
SpreadsheetApp.getActive().getSheets()[0].getRange(day,1).activate();// in cloumn 1 for example. Add an offset if necessary (if headers...)
}
Date.prototype.getDOY = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((this - onejan) / 86400000);
}