I have a spreadsheet with two sheets: Week#, Events.
Sheet "Week#" (calendar week # in Column A and the start day of this week in Column B):
01 January 4, 2016
02 January 11, 2016
03 January 18, 2016
04 January 25, 2016
05 February 1, 2016
and so on till week 52
Sheet "Events" has next columns:
Facility, Repeats, Belongs to week #, Week # starts on, Item, Action, Status.
It's filled with something like this (number of rows varies):
SalonA, monthly, 4, January 25,2016, Floor, to mop the floor, Created
The script is like this:
function createEventmanually (title, date)
{
var sheet = SpreadsheetApp.getActiveSheet();
var row = sheet.getActiveRange().getRowIndex();
var EventStatus = sheet.getRange(row, 7).setValue("Created");
var title = sheet.getRange(row,1).getValue()+" "+"Week "+sheet.getRange(row,3).getValue()+" "+sheet.getRange(row,5).getValue()+":"+" "+sheet.getRange(row,6).getValue();
var cal = CalendarApp.getCalendarsByName('RM') [0];
var date = sheet.getRange(row,4).getValue();
var event = cal.createAllDayEvent(title, date);
}
I manually copy and paste calendar dates from sheet Week# to column "Week # starts on" in sheet Events. And then run the script every time to create event.
How to automatize this process? I understand that it could be done through iteration but I cannot figure it out.
Thank you in advance.
If what you want is 52 calendar events (One every week) for every different
task in the Events sheet, this code is how you would need to do it.
function createAllEventsForTheYear() {
var allRowsOfDataInEventSheet,allDataInWeekSheet,cal,eventSh,i,j,L,Lj,lastRowInEventSheet,lastRowInWeekSheet,
lastColumnInEventSheet,lastColInWeekSh,ss,row,
weekNumberSheet,rowDataBeingProcessedFromEventsSheet,thisEventTitle,thisWeeksDate;
cal = CalendarApp.getCalendarsByName('RM')[0];
ss = SpreadsheetApp.getActiveSpreadsheet();
eventSh = ss.getSheetByName('Events');
weekNumberSheet = ss.getSheetByName('Week#');
lastRowInEventSheet = eventSh.getLastRow();
lastRowInWeekSheet = weekNumberSheet.getLastRow();
lastColumnInEventSheet = eventSh.getLastColumn();
lastColInWeekSh = weekNumberSheet.getLastColumn();
allRowsOfDataInEventSheet = eventSh.getRange(2, 1, lastRowInEventSheet-1, lastColumnInEventSheet).getValues();
allDataInWeekSheet = weekNumberSheet.getRange(2, 1, lastColInWeekSh-1, lastColInWeekSh).getValues();
L = allRowsOfDataInEventSheet.length;
Lj = allDataInWeekSheet.length;
for (i=0;i<L;i+=1) { //Loop through every row of data in the Events sheet
rowDataBeingProcessedFromEventsSheet = allRowsOfDataInEventSheet[i];//Get one row of data
thisEventTitle = rowDataBeingProcessedFromEventsSheet[0] + "Week" + rowDataBeingProcessedFromEventsSheet[2] + " " + rowDataBeingProcessedFromEventsSheet[4] + ": " + rowDataBeingProcessedFromEventsSheet[5];
for (j=0;j<Lj;j+=1) {//For every row in the Events sheet, create an event for every week of the year. 52 events for this event type
thisWeeksDate = allDataInWeekSheet[j][1];//Get the date from the second column of the data in the Weeks# sheet
cal.createAllDayEvent(thisEventTitle, thisWeeksDate);
};
eventSh.getRange(i+2, 7).setValue("Created");//I starts at 0, data starts on row 2
};
};
I have not tested this, or even debugged it, so it may not run perfectly.
Related
I'm trying to write an inputted date from the adjacent cell.
i.e. date entered in A1, B1 = A1 but in word form (in Spanish).
I'm close to a solution but I'm sure making things more complicated than they need to be.
The date column(A) is currently being separated into 3;
day(B), month(D), year(F), using; =LEFT($A1;2), =MID($A1;4;2), =RIGHT($A1;4) accordingly.
In Columns C,E,G I'm using
=INDEX(IMPORTXML("https://www.buscapalabra.com/numeros-a-letras.html?cifra="&B1;"//li[1]//strong");1)
where B1 changes to E1, F1 depending on the column
finally in column H where the date will be written I use:
=trim(LOwer($C2&"de "&TEXT($D2;"mmmm")&" de "&$F2))&If(Value(Right($E2;1))=1;If(Value(MID($E2;4;1))<>1;"o";"");"")
For some reason the text value returned from the site has a space on the end and also does not properly word numbers ending in 1. Hence the use of TRIM() & the nested IF()
It works for now, I haven't tested it exhaustedly but I'd love to hear what people think, I'm new to Sheets but there has to be a cleaner way to do this.
Use custom functions:
You could do this with an Apps Script Custom Function.
First, open a bound script by selecting Tools > Script editor, and copy the following functions to the script (check inline comments for more information):
function DATE_IN_WORDS(date) {
const day = date.getDate(); // Day of the month in numbers
const year = date.getFullYear(); // Year in numbers
const options = { month: 'long'};
const month = new Intl.DateTimeFormat('es-ES', options).format(date); // Month in words
const dayAndYear = [day, year].map(number => { // Retrieve word for day and year
const url = "https://www.buscapalabra.com/numeros-a-letras.html?cifra=" + number
const resp = UrlFetchApp.fetch(url).getContentText();
const first = "<em>Como sustantivo:</em> El <strong>";
const cut = resp.substring(resp.indexOf(first), resp.length);
let word = cut.substring(first.length, cut.indexOf("</strong>")); // Get desired section of HTML
if (number.toString().slice(-1) == "1" && number.toString().slice(-2) != "11") {
word = word.trim() + "o"; // Replace "un" with "uno"
let arrayWord = word.split(" ");
let lastWord = arrayWord.pop();
if (lastWord === "veintiúno") { // If 21, replace "ú" with "u"
lastWord = lastWord.replace("ú", "u");
arrayWord.push(lastWord);
word = arrayWord.join(" ");
}
return word;
} else return word;
});
return dayAndYear.join("de " + month + " de "); // Join day, month and year
}
This function uses:
Intl.DateTimeFormat to retrieve the month in Spanish.
UrlFetchApp to fetch information from https://www.buscapalabra.com/numeros-a-letras.html.
Once it is defined, you can use the function DATE_IN_WORDS the same you would any sheets built-in function. This function would accept the cell with the Date as a parameter.
Example:
Reference:
Custom Functions in Google Sheets
I am trying to query 2 long columns for agents' name, the issue is the names are repeated on 2 tables, one for the total sum of productivity and the other is for total sum of utilization.
The thing is when I query the columns it returns back the numbers for Productivity and Utilization all together.
How can I make the query to search only for Productivity alone and for Utilization alone?
Link is here: https://docs.google.com/spreadsheets/d/12Sydw6ejFobySHUj5JoYkAPbhr0mKoInCWxtHY1W4lk/edit#gid=0
Apps Script would be a better solution in this case. The code below works as follows:
Gets the names from Column D and Column A.
For each name of Column D, it will compare it with each name of Column A (that's the 2 for loops)
If the names coincide (first if), it will check the background color (second if) of the Column A name to accumulate Total Prod and Total Util.
Once it reaches the end of the Column A, writes the values in Total Prod and Total Util (Columns E and F) for each name in D.
function onOpen() { //Will run every time you open the sheet
//Gets the active Spreadsheet and sheet
let sprsheet = SpreadsheetApp.getActiveSpreadsheet();
let sheet = sprsheet.getActiveSheet();
var lastRow = sheet.getLastRow();
var getNames = sheet.getRange(3, 1, lastRow).getValues(); //Names from row 2, col 1, until the last row
var totalNames = sheet.getRange("D4:D5").getValues(); //Change the range for more names
let prodColor = '#f2f4f7'; //hexadecimal codes of the background colors of names in A
let utilColor = '#cfe2f3'; //
for (var i = 0; i < totalNames.length; i++) {
var totalProd = 0, totalUtil = 0; //Starts at 0 for each name in D
for (var j = 0; j < getNames.length; j++) {
if (totalNames[i][0] == getNames[j][0]) {
if (sheet.getRange(j + 3, 1).getBackgroundObject().asRgbColor().asHexString() == prodColor) { //if colors coincide
totalProd += sheet.getRange(j + 3, 2).getValue();
} else if (sheet.getRange(j + 3, 1).getBackgroundObject().asRgbColor().asHexString() == utilColor) {
totalUtil += sheet.getRange(j + 3, 2).getValue();
}
}
}
sheet.getRange(i+4, 5, 1 ,2).setValues([[totalProd, totalUtil]]);
}
}
Note: You will have to run the code manually and accept permissions the first time you run it. After that it will run automatically each time you open the Sheet. It might take a few seconds for the code to run and to reflect changes on the Sheet.
To better understand loops and 2D arrays, I recommend you to take a look at this.
References:
Range Class
Get Values
Get BackgroundObject
Set Values
You can learn more about Apps Script and Sheets by following the Quickstart.
I have a google spreadsheet list, with two columns (200+rows and counting), that looks like this:
Monday 495,636,792
Tuesday 891,243,349
Wednesday 465,844,622
Thursday 425,461,946
Friday 412,401,861
Saturday 424,297,897
Sunday 462,782,430
Monday 454,216,725
Tuesday 1,661,014,800
Wednesday 502,935,706
Thursday 493,009,684
Friday 464,568,911
Saturday 670,963,371
Sunday 491,847,275
(I also have a regular date column, not just the weekdays - if needed)
I would like to count the weekly minimum.
This basically means that I would like an other list that would look like this:
Monday 10
Tuesday 15
Wednesday 20
Thursday 0
Friday 9
Saturday 7
Sunday 25
Monday - 10 would mean, that there were 10 weeks, where Monday had the smallest number during that week.
Sorry I did not understand correctly. This is mot as hard. See corrected code below. The sample sheet is also corrected.
function minDays() {
var s= SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var clr = s.getRange(2,2,7,1).clear()
var lr = ss.getLastRow()-1
var slr = 7
var sr = 2
var weeks = lr/7
for(w=1;w<weeks+1;w++){
if(w==1){sr=sr,slr==slr} else {sr=sr+7,slr=slr+7}
var sVal = ss.getRange(sr,1,slr,2).getValues();
var minVal =sVal[1][1]
var minDay =sVal[0][0]
for (var i = 1; i < 7;i++) {
if(sVal[i-1][1]<=minVal){minVal=sVal[i-1][1],minDay=sVal[i-1][0]} else{minVal=minVal,minDay=minDay}
var fVal=minVal
var fday = minDay
}
var target=s.getRange(2,1,7,2).getValues();
for(var n in target){
var row = target[n][0]
if(row.toString().match(fday)){
var cnt = target[n][1].valueOf()+1
target[n][1]=cnt
}}
var rDay =s.getRange(2, 1,7,2)
var data=rDay.getValues()
rDay.setValues(target)
}}
https://docs.google.com/spreadsheets/d/1AFHeNKeonLDuuOyg7GaTvMB4asvnYHbK2C0WAEbfSsI/edit?usp=sharing
I don't think I'm hallucinating as I've tried it a dozen times. Here's my code:
$('#teo_prep_due').change(function() {
var ber = $('#ber_rcvd');
var tpd = $('#teo_prep_due');
var brDate = ber.datepicker('getDate');
var tpDate = tpd.datepicker('getDate');
var s1Date = new Date();
var s2Date = new Date();
var sdDate = new Date();
s1Date.setDate(brDate.getDate() + 5);
console.log(s1Date);
s2Date.setDate(tpDate.getDate() - 3);
console.log(s2Date);
if (s1Date < s2Date) {
sdDate.setDate(s1Date.getDate());
} else {
sdDate.setDate(s2Date.getDate());
}
$('#survey_due').datepicker('setDate', sdDate);
});
On my date form, I've entered February 28, 2013 for ber_rcvd and March 14, 2013 for teo_prep_due. Following the code, my result should be March 5, 2013. However, s2Date is resulting in February 11, 2013, as if a full month and 3 days are being subtracted instead of just 3 days. Has anyone else run into this?
Using: jquery-1.9.1.min.js, jquery-migrate-1.1.1.js and jquery-ui-1.10.1.min.js.
http://jsfiddle.net/devlshone/veP7b/
The problem is that .setDate() does not set the date, it sets the day of the month. It takes an integer as an argument. When you created s2Date it defaulted to today, which is in February. When you add tpDate.getDate()// equals 14 with -3, you get 11, and therefore February 11th.
I am trying the new Google Dart language and I don't know how to get the last day of the current month?
This gives me current date:
var now = new DateTime.now();
Providing a day value of zero for the next month gives you the previous month's last day
var date = new DateTime(2013,3,0);
print(date.day); // 28 for February
If you want to get the last date of the current month, you need to refer to the 0th day of the next month
Try this in an easy way:
DateTime now = DateTime.now();
int lastday = DateTime(now.year, now.month + 1, 0).day;
Here's one way to find it:
var now = new DateTime.now();
// Find the last day of the month.
var beginningNextMonth = (now.month < 12) ? new DateTime(now.year, now.month + 1, 1) : new DateTime(now.year + 1, 1, 1);
var lastDay = beginningNextMonth.subtract(new Duration(days: 1)).day;
print(lastDay); // 28 for February
I have the current date, so I construct the first day of the next month, and then subtract one day out of it. I'm also taking the change of the year into account.
Update: Here's a little bit shorter code for the same thing, but inspired by Chris's zero-trick:
var now = new DateTime.now();
// Find the last day of the month.
var lastDayDateTime = (now.month < 12) ? new DateTime(now.year, now.month + 1, 0) : new DateTime(now.year + 1, 1, 0);
print(lastDayDateTime.day); // 28 for February
It has the additional check/code, in case you want to do this programmatically (e.g. you have a specific month as an integer).
Here's an extension that might help. (Ref. from Kai's and Chris's answers.)
extension DateTimeExtension on DateTime {
DateTime get firstDayOfWeek => subtract(Duration(days: weekday - 1));
DateTime get lastDayOfWeek =>
add(Duration(days: DateTime.daysPerWeek - weekday));
DateTime get lastDayOfMonth =>
month < 12 ? DateTime(year, month + 1, 0) : DateTime(year + 1, 1, 0);
}
Another way is using Jiffy. It has the endOf method that makes easy to get the last moment of several units, in this case the month:
Jiffy().endOf(Units.MONTH);
While all this answers are correct & do give you the last DAY of the month :
like so : year-month-lastDay 00:00:00.000 -> beginning of the last day of the month
You might need the last bound / DateTime of the month :
like so : year-month-lastDay 23:59:59.999 -> end of the last day of the month
Here is how to get the two bounds within a month with the help of an extension on DateTime :
extension MonthsBounds on DateTime {
DateTime get lastMillisecondOfMonth =>
month < 12 ? DateTime(year, month + 1, 1, 00, 00, 00, -1) : DateTime(year + 1, 1, 1, 00, 00, 00, -1);
DateTime get firstMillisecondOfMonth => DateTime(year, month, 1);
}
print('${DateTime(2022, 12, 14).lastMillisecondOfMonth}'); // 2022-12-31 23:59:59.999
DateTime first = DateTime(month.value.year, month.value.month, 1);
DateTime end = Jiffy(first).add(months: 1, days: -1).dateTime;