Using the code below, the google sheet enters the Date in column 6 when a cell in column 1 is edited. It also includes the timestamp.
How can this code be altered so that just the date (day-month-year) is entered? This would allow searches by date on the sheet.
function onEdit(e) {
var sheetName = 'Cases Allocation'; //name of the sheet the script should work on
var colToWatch = 1
var colToStamp = 6 //timestamp in col A
if (e.range.columnStart !== 1 || e.source.getActiveSheet()
.getName() !== sheetName || e.value == '') return;
var writeVal = e.value !== "" ? new Date(),: '';
e.source.getActiveSheet()
.getRange(e.range.rowStart, colToStamp)
.setValue(writeVal);
}
You can try using Utilities.formatDate. This method formats date according to specification described in Java SE SimpleDateFormat class. You can visit the date and time patterns here. An example of usage is:
// This formats the date as Greenwich Mean Time in the format
// year-month-dateThour-minute-second.
var formattedDate = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd'T'HH:mm:ss'Z'");
Logger.log(formattedDate);
Do take note that using Utilities.formatDate has the following effects as noted in this post:
Utilities.formatDate does not change the cell format; it converts
its content to text. If you are going to use the date value in
computations, you don't want it to be converted to text.
Utilities.formatDate requires one to specify a timezone. If you put
something like "GMT+1" and your country observes Daylight Saving
Time, you can expect hard-to-track bugs to come up a few months
later. With setNumberFormat, the date value remains consistent with
all other date values in the spreadsheet, governed by its timezone
setting.
To avoid these, you can also use setNumberFormat(numberFormat) to set the date or number format. The accepted format patterns are described in the Sheets API documentation. And an example usage is:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var cell = sheet.getRange("B2");
// Always show 3 decimal points
cell.setNumberFormat("0.000");
Thanks all - tried format etc, but then just decided to add a column and split the date and time, with just the date going into a new column.
function onEdit(e) {
var sheetName = 'Cases Allocation'; //name of the sheet the script should work on
var colToWatch = 1
var colToStamp = 6 //timestamp in col A
if (e.range.columnStart !== 1 || e.source.getActiveSheet()
.getName() !== sheetName || e.value == '') return;
//var writeVal = e.value !== "" ? new Date(),: '';
e.source.getActiveSheet()
.getRange(e.range.rowStart, colToStamp)
.setValue(new Date(new Date().setHours(0,0,0,0))).setNumberFormat('MM/dd/yyyy');
}
The below code will save the date without time. You can change the format as required. The field remains a date which can be used as required.
setValue(new Date(new Date().setHours(0,0,0,0))).setNumberFormat('MM/dd/yyyy');
Related
I am having issues making this work. I want to insert todays date in colum 4 upon making checkbox true in colum 1. There are multiple rows. I am not seeing the error of my ways. Any suggestions would be appreciated.
Thanks,
function onEdit(e) {
var ss = e.source.getActiveSheet();
var date = new Date();
if (e.range.columnStart != 1 || e.value != "TRUE") return;
ss.getRange(e.range.rowStart,4).setValue(date);
}
Instead of:
E.value != "TRUE"
Simply use:
!e.value
And then instead of:
ss.getRange(e.range.rowStart,4).setValue(date)
You can simply use:
e.range.offset(0,3).setValue(date)
That allows you to eliminate the need for the ss variable as well.
I'm new to App Script, please be gentle!
I have a table with a start date and a number of months, I need to list each recurring month from the start date to the number of months.
I'm struggling with 2 issues:
The first date placed in the array seems to be updating as I cycle the dates
The formats are in UNIX and I can't get them to be useful despite an awful lot of reading!
Thank you so much for any help!
Input file (https://i.stack.imgur.com/2EJ65.png)
Output file(https://i.stack.imgur.com/0DH5R.png)
Console log (https://i.stack.imgur.com/NVqck.png)
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Get Data sheet
var rawData = ss.getSheetByName('Sheet3');
// Get a date and set it as a date format
var start = new Date(rawData.getRange("B2").getValues());
console.log(start);
// Get Months
var months = rawData.getRange("C2").getValues();
// Define dates array
var dates = [];
// Add first date
const startDate = start
dates.push([startDate]);
//Add rest of dates dates in a loop
for (var run = 1;run < months;run++) {
//get the last pasted month name
var lastMonth = start.getMonth();
//push next month
dates.push([start.setMonth(lastMonth+1)]);
}
// Get processedData sheet
var processedData = ss.getSheetByName('sheet2');
// Post the outputArray to the sheet in a single call
console.log(start);
console.log(startDate);
console.log(dates);
console.log(dates.length);
console.log(dates[0].length);
processedData.getRange(1,1,6,1).setValues(dates);
}
Incrementing Dates by month and setting format
function lfunko() {
const ss = SpreadsheetApp.getActive();
let dt = new Date();
let start = new Date(dt.getFullYear(),dt.getMonth(),dt.getDate());//need to change back to your value
const months = 10;//need to change back to your value
let dates = [];
dates.push([start]);
for (let run = 1; run < months; run++) {
dates.push([new Date(start.getFullYear(),start.getMonth() + run, start.getDate())])
}
ss.getSheetByName('Sheet0').getRange(1, 1, dates.length).setValues(dates).setNumberFormat("mm/dd/yyyy");//changed sheet name
Logger.log(dates);
}
I want to add some quick filters using the ui of google sheets. Currently I want to allow the user to click "show last month" to only see the data of the last month. The dates are written in the first column.
Now I prefer to use the filter of google sheets before just printing the values into the sheet, to allow the user to further modify that filter.
Thus I am trying to build filterCriteria using SpreadsheetApp.newFilterCriteria().whenDateEqualToAny(dates) and I am parsing an array of valid dates. In the documentation it says I have to put a "Date[]" - doesn't that mean an array of dates?
Below the error message and my code:
Error message (linked to the line "var filterCriteria..."):
"Exception: The boolean condition can not have multiple values for equality checks for non-data source objects"
My code:
function showLastMonth() {
var ss = SpreadsheetApp.getActive()
var sheet = ss.getSheetByName('evaluation')
var now = new Date()
var thisYear = now.getFullYear()
var thisMonth = now.getMonth()
if(thisMonth == 0){var startMonth = 11; var startYear = thisYear - 1}
else{var startMonth = thisMonth - 1; var startYear = thisYear}
var startDate = new Date(startYear, startMonth, 1)
var endDate = new Date(thisYear, thisMonth, 0)
var dates = getDateArray(startDate, endDate)
var filter = sheet.getFilter()
if(filter == null ){
var range = sheet.getDataRange()
var filter = range.createFilter()
}
var filterCriteria = SpreadsheetApp.newFilterCriteria().whenDateEqualToAny(dates)
filter.setColumnFilterCriteria(1, filterCriteria)
}
getDateArray = function(startDate, endDate){
var startYear = startDate.getFullYear()
var startMonth = startDate.getMonth()
var dateArray = []; dateArray.push(startDate)
var date = startDate; var day = date.getDay()-1
while(date<endDate){
day++
date = new Date(startYear, startMonth, day)
if(date<=endDate){dateArray.push(date)}
}
return dateArray;
}
I believe your goal as follows.
You want to hide the rows of the values except for dates using the basic filter.
You want to achieve this using Google Apps Script.
Issue and workaround:
In the current stage, it seems that array of whenDateEqualToAny(array) is required to be the length of 1. I think that this is the reason of your issue. So for example, when var filterCriteria = SpreadsheetApp.newFilterCriteria().whenDateEqualToAny([dates[0]]) is used, no error occurs. This situation is the same with the setBasicFilter request of Sheets API. Unfortunately, it seems that this is the current specification. But, the official document says The acceptable values. which uses the plural form. Ref So I also think that this is not correct for the actual situation as mentioned by TheMaster's comment.
In order to achieve your goal, in this case, I would like to propose the following 2 patterns.
Pattern 1:
In this pattern, using setHiddenValues(), the values except for the values of dates in your script are set as the hidden values.
Modified script:
When your script is modified, please modify as follows.
From:
var filterCriteria = SpreadsheetApp.newFilterCriteria().whenDateEqualToAny(dates)
To:
var obj = dates.reduce((o, e) => Object.assign(o, {[`${e.getFullYear()}\/${e.getMonth() + 1}\/${e.getDate()}`]: true}), {});
var range = sheet.getRange("A1:A");
var dispValues = range.getDisplayValues();
var hiddenValues = range.getValues().reduce((ar, [a], i) => {
if (a instanceof Date && !obj[`${a.getFullYear()}\/${a.getMonth() + 1}\/${a.getDate()}`]) {
ar.push(dispValues[i][0]);
}
return ar;
}, []);
var filterCriteria = SpreadsheetApp.newFilterCriteria().setHiddenValues(hiddenValues).build();
Pattern 2:
In this pattern, using whenNumberBetween(), the values of dates in your script are shown. In this case, it is required to convert the date object to the serial number.
Modified script:
When your script is modified, please modify as follows.
From:
var filterCriteria = SpreadsheetApp.newFilterCriteria().whenDateEqualToAny(dates)
To:
var filterCriteria = SpreadsheetApp.newFilterCriteria().whenNumberBetween(
(dates[0].getTime() / 1000 / 86400) + 25569,
(dates.pop().getTime() / 1000 / 86400) + 25569
).build();
The conversion from the date object to the serial number was referred from this thread.
References:
setHiddenValues(values)
whenNumberBetween(start, end)
I have created a google spreadsheet. On the column A in row 1 I have used "vastzetten" (that's in dutch). The first column and row I have blocked. When I go with the cursor I can change the date and the rest of the sheet dissapeared after the block. (Look the images). Is there a way when I start the sheet it selects the date of the day then moves the rest of the sheet after the titleblock? I hope that somebody knows what I mean.
You could use an installable trigger to hide columns and/or to activate the range corresponding to the current date.
For instructions on how to set an installable trigger see https://developers.google.com/apps-script/guides/triggers/installable
The following code assumes that the column headers are values of date type. If the current date is found, then the columns at the left will be hidden and the the cell below the corresponding header will be activated.
function myFunction(){
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheets()[0];
var tz = ss.getSpreadsheetTimeZone();
var today = Utilities.formatDate(new Date(), tz, 'YYYY-MM-dd')
var data = sheet.getDataRange().getValues();
var headers = data[0];
for(var i = 0;i<= headers.length;i++){
if(headers[i] instanceof Date){
if(today == Utilities.formatDate(headers[i], tz, 'YYYY-MM-dd')){
sheet.hideColumns(2,i-1);
sheet.getRange(2, i+1).activate();
break;
}
}
}
}
I'm new to Protractor and here I'm trying to test an angularjs date picker from Protractor.
I tried to find a way to do this and this article was the only thing I found and It is not very clear to use
If someone know how to test please help.
What I need is to select today's date.
Thanks in advance :)
edit -
alecxe, here is the screen shot of my date picker. Unfortunately cannot provide the link of the page. :(
<input
class="form-control ng-pristine ng-valid ng-not-empty ng-touched"
ng-model="invoice.fromdate"
data-date-format="yyyy-MM-dd"
data-date-type="string"
data-max-="" data-autoclose="1"
bs-datepicker=""
ng-change="dateRange()"
type="text">
I think you can avoid manipulating the datepicker manually and instead set the date either by just sending the keys with a today's date value:
var picker = element(by.model("invoice.fromdate"));
// get today's date
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1; //January is 0!
var yyyy = today.getFullYear();
if(dd<10) {
dd='0'+dd
}
if(mm<10) {
mm='0'+mm
}
today = mm+'/'+dd+'/'+yyyy;
picker.clear();
picker.sendKeys(today);
Or, by setting the associated model's value directly:
picker.evaluate("invoice.fromdate= '" + today + "'");
Two methods have been suggested so far: 1. sendKeys() 2. evaluate()
I'm a bit new to protractor but I think both of these have issues in the case of not having an input element that spawns the calendar, i.e.:
Sendkeys() works only if date is on an element and the uib-datepicker is a dropdown sort of deal. This didn't help me because my datepicker element is a standalone and isn't paired with an input element.
evaluate() doesn't update angular's actual model in the browser (which begs the question of how useful evaluate actually is...). According protractor docs, evaluate, "Evaluates the input as if it were on the scope of the current underlying elements." In my case I want to test whether the date generated by the datepicker gets to my enpdpoint via a post request and then back again (hence e2e) without getting effed (corrupted), therefore, I need my date to be on my angular model in the browser instance, not just in the browser-driver environment or whatever the runtime environment of the protractor test is. I could be wrong about this.
This expect() passes but the ng-form is invalid (i'm assuming b/c model in browser wan't actually updated to receive the date I'm trying to pass in.):
function convertToPickerDate(date) {
var date = new Date(date);
var dd = date.getDate();
var mm = date.getMonth() + 1; //January is 0!
var yyyy = date.getFullYear();
var yy = yyyy.toString().slice(2);
return mm + '/' + dd + '/' + yy;
}
// expect passes, but form is invalid - DON'T USE for standalone cal
it('should enter start date in date picker', function () {
offerStart = convertToPickerDate(myData.startDate);
var offerStartPicker = element(by.model('current.startDate'));
offerStartPicker.evaluate("current.startDate = '" + offerStart + "'");
offerStartPicker.evaluate("current.startDate").then(function (value) {
expect(value).toBe(offerStart);
});
})
but the ng-form that the element is on is invalid...
My solution uses css selection and arrow keys to select a date relative to today:
Shipment Start Date: <em id="offerStartPrint">{{current.startDate | date:'shortDate' }}</em>
<div id="offerStart"
name="offerStart"
uib-datepicker
ng-model="current.startDate"
class=""
ng-change="setStartDate()"
datepicker-options="startDateOptions"
required></div>
</div>
function convertToPickerDate(date) {
var date = new Date(date);
var dd = date.getDate();
var mm = date.getMonth() + 1; //January is 0!
var yyyy = date.getFullYear();
var yy = yyyy.toString().slice(2);
return mm + '/' + dd + '/' + yy;
}
it('should enter expiration date in date picker using tabs and arrows :)', function () {
// select today element on uib-datepicker calendar
// div#offerStart elem has date model
var calToday = element(by.css('div#offerStart table td button.active'));
calToday.sendKeys(protractor.Key.ARROW_DOWN); // one week away
calToday.sendKeys(protractor.Key.ARROW_DOWN); // two weeks away
calToday.click(); // if you remove this click no date is entered
var fortnightAway = new Date(Date.now() + 12096e5);
fortnightAwayString = convertToPickerDate(fortnightAway);
expect(element(by.id('offerStartPrint')).getText()).toBe(fortnightAwayString);
})
Left and right arrows can be used to increment/decrement date by one day at a time.
up/down arrows can be used to inc/dec one week at a time.
One could probably figure out how to arrow through months and years as well.
var data_picker = element(by.model("invoice.fromdate"));
// select current date with date function
var current_date = new Date();
var day = today.getDate();
var month = today.getMonth()+1; //By default January count as 0
var year = today.getFullYear();
if(day<10) {
day='0'+day
}
if(month<10) {
month='0'+month
}
current_date = month+'/'+day+'/'+year;
data_picker.clear(); // Note if you are facing error message related to clear. Comment this line
data_picker.sendKeys(today);
Hope this will work