List of 1st and 3rd Mondays in Excel - excel

In Excel, I'd like a list of the 1st and 3rd Mondays in each month, for say the next six months after today.
Using a formula-based approach, I can find the 1st or 3rd Monday after today. I got stuck when trying to populate the list after that. Particularly, a challenge is to account for months with 5 Mondays in them. The formulas get very complex very quickly!

This is the solution I have so far:
Private Sub Auto_Open()
Dim i, mday As Integer
Dim row, col As Integer
Dim d As Date
Dim min As Integer
min = 14 'Minimum set up period
col = 1 'Column to put results in
row = 2 'Row to start from
d = Date + min + 9 - Weekday(Date) 'Find Monday after Minimum set up period
Worksheets("options").Activate
For i = 1 To 26 'Results up to 26 weeks in future
mday = day(d)
If (mday - 7 <= 0) Then 'First week
Cells(row, col).Value = d
row = row + 1
ElseIf (mday - 14 > 0 And mday - 21 <= 0) Then 'Third week
Cells(row, col).Value = d
row = row + 1
End If
d = d + 7 '+1 week
Next
Worksheets("New Starter").Activate
End Sub

Try this:
On A1 place the first day of one month. On A2 place: =EOMONTH(A1,0)+1
On B1 place =A1+MOD(8-WEEKDAY(A22,2),7).
On C1 place =B1+14
Drag an drop down.
The first column is taking the first day of one month and consecutive month, the column Bis returning the first monday and colunm C is returning the third monday of that month.
If you are looking for the 5th monday:
On D1 place: =IF(A1+MOD(8-WEEKDAY(A22,2),7)+28<EOMONTH(A1,0)+1,A1+MOD(8-WEEKDAY(A22,2),7)+28,"")

Related

Excel formula to assign serial number to duplicates with date criteria

I need excel formula to assign serial number to duplicates but with an added criteria for dates in ascending order.
The Count if formula "=COUNTIF($A$1:A1,A1)" will assign number in ascending order based on the row for the column A data but not based on the date.
I have the below table in Column A and B and the result expected in Column C
Name Date Serial number(Expected Result)
Apple 1/1/2019 1
Orange 2/1/2019 1
Lemon 4/1/2019 2
Banana 5/1/2019 2
Apple 8/1/2019 3
Watermelon 1/1/2019 1
Lemon 1/1/2019 1
Orange 4/1/2019 2
Banana 2/1/2019 1
Apple 5/1/2019 2
If you see first Apple is 1 but next one is not 2 as the date is 8th so its the third date based on ascending order of the date hence its 3 and the last Apple is 2.
Hope I am clear what I am asking. Apologies if any inconvenience in writing as this is my first question here and I am still learning.
If you sort the data, the formula you have will work.
If you're not able to/willing to sort the data then you can use this custom formula ...
Public Function AssignSerialNo(ByVal strName As String, ByVal dtDate As Date, ByVal rngData As Range) As Long
Dim lngRow As Long, lngEmptyCount As Long, strThisName As String, dtThisDate As Date, strThisDate As String
Application.Volatile
AssignSerialNo = 1
' Process each row provided in the 3rd parameter. Give it 10 rows of blanks before exiting out
' and ending the process.
For lngRow = 1 To rngData.Rows.Count
strThisName = Trim(rngData.Cells(lngRow, 1))
strThisDate = rngData.Cells(lngRow, 2)
If strThisName = "" Then
lngEmptyCount = lngEmptyCount + 1
Else
lngEmptyCount = 0
If IsDate(strThisDate) Then
dtThisDate = rngData.Cells(lngRow, 2)
If UCase(strThisName) = UCase(strName) Then
' We have a match, determine if the date value is greater than or less than the parameter.
If dtThisDate < dtDate Then AssignSerialNo = AssignSerialNo + 1
End If
End If
End If
If lngEmptyCount >= 10 Then Exit For
Next
End Function
Add the following formula in the first "Serial Number" cell and fill down ...
=AssignSerialNo(A2,B2,A:B)
... this is all assuming that your example table (with headings) starts from cell A1.
Let me know how you go.

VBA count columns and copy them

Below code hide a certain number of rows(depending on the number of the week we are in) and shows only the cell corresponding to the current week number and cells corresponding to the future week numbers.
Dim test As String
test = Format(Now, "yyyy", vbMonday) & KW(Now)
For k = 3 To lastColumn
ThisWorkbook.Worksheets(PlanningTableNameUG).Columns(k).ColumnWidth = cWidth
If ThisWorkbook.Worksheets(PlanningTableNameUG).Cells(1, k).Value = test Then
today = True
On Error Resume Next
ThisWorkbook.Worksheets(PlanningTableNameUG).Columns(k - 1).Ungroup
On Error GoTo 0
ThisWorkbook.Worksheets(PlanningTableNameUG).Columns(k - 1).Group
End If
If Not today Then
On Error Resume Next
ThisWorkbook.Worksheets(PlanningTableNameUG).Columns(k).Ungroup
On Error GoTo 0
ThisWorkbook.Worksheets(PlanningTableNameUG).Columns(k).Group
ThisWorkbook.Worksheets(PlanningTableNameUG).Columns(k).Hidden = True
If Hidden = True Then
ThisWorkbook.Worksheets(PlanningTableNameUG).Columns(k).Group.Copy
ThisWorkbook.Worksheets(PlanningTableNameUG).Columns(k).Group.Insert Shift:=xlToRight
End If
Else
ThisWorkbook.Worksheets(PlanningTableNameUG).Columns(k).Hidden = False
End If
Next k
' calculate the week number
Function KW(d As Date) As Integer
Dim Tag As Long
Tag = DateSerial(Year(d + (8 - Weekday(d)) Mod 7 - 3), 1, 1)
KW = (d - Tag - 3 + (Weekday(Tag) + 1) Mod 7) \ 7 + 1
End Function
Now, I need to count how many columns were hidden and add the exact numbers of columns, example:
columns:
1,2,3,4,5,6,7,8,9,10 (column 4 is corresponding to today week number)
I hide: 1,2,3 because there are in the past weeks, and want to add 11,12, 13, together with the week number corresponding for them, but not more than 1 year from current date.
Count of the weeks starts at the begging of the current year.
When hiding the columns you could add an integer variable that increases by one then use this variable to add that many new columns.
Then to add the week number, use the last column with the week number on it and add one to it for each of the new columns...
To count hidden columns in used range of ThisWorkbook.Worksheets(PlanningTableNameUG):
Dim col As Range
Dim cnt As Long
For Each col In ThisWorkbook.Worksheets(PlanningTableNameUG).UsedRange
Debug.Print col.EntireColumn.Hidden
cnt = cnt - col.EntireColumn.Hidden
Next col
EntireColumn.Hidden returns True if is hidden. True is -1 in VBA, that is why i deduct it from the counter to get positive value.

Excel VBA macro to count the number of times a specific word appears according to a date (that would be converted to week number)

So I have column A (contains the word) and column C (contains the date) shown below. The columns are occasionally separated by new headers, such as for "Word" and "Date" and a blank space.
Word Date
BV 12/06/2017
BV 12/06/2017
BV 13/06/2017
BV 13/06/2017
BR 17/07/2017
BR 17/07/2017
BR 24/07/2017
Word Date
BT 30/07/2017
BT 30/07/2017
Word Date
BY 05/08/2017
First the date would be converted in terms of week number into a new column D, such as 12/06/2017 to week 24.
Using something like:
Sub TimeConverter()
Dim I as Long, MaxRow as Long
MaxRow = Range("A" & Rows.count).End(xlUp).Row
For I = 2 to MaxRow
Cells(I, "D").Value = DatePart("ww", Cells(I, "C"), 7)
Next
End Sub
Then I would like the VBA macro code to look through column A and find the number of times a word appears and match with a date on the same week number into a new column B.
Using something like:
=COUNTIF(A:A, "BV")
=COUNTIF(A:A, "BR")
Output
# 4
# 3
Now to then combine them together so that the unique word (column A) counts (column B) can be separated into the corresponding week number (column D).
Desired Output:
BV 4 24
BR 2 29
BR 1 30
BT 2 30
BY 1 31
Any suggestion would be great!
Thank you.
Let's say that with your VBA code you have managed to get something like this as an input:
Then, as mentioned in the comments, you need to implement a dictionary to get something like this:
As you see, the keys of the dictionary is the word + the week number together. Thus BR29 is different than BR30.
Copy the sample input, run the code below and you will get the desired output:
Option Explicit
Public Sub TestMe()
Dim myDict As Object
Dim lngCounter As Long
Dim strKey As String
Dim objKey As Object
Set myDict = CreateObject("Scripting.Dictionary")
For lngCounter = 1 To 14
strKey = Cells(lngCounter, 1) & Cells(lngCounter, 3)
If myDict.exists(strKey) Then
myDict(strKey) = myDict(strKey) + 1
Else
myDict(strKey) = 1
End If
Next lngCounter
For lngCounter = 0 To myDict.Count - 1
Cells(lngCounter + 1, 6) = myDict.Items()(lngCounter)
Cells(lngCounter + 1, 7) = myDict.keys()(lngCounter)
Next lngCounter
End Sub
Then you have to work more to find a way to split the keys from BV24 to BV and 24. You need to find a way to eliminate the zero from the results as well.

VBA for week number of a month similar to desktop calendar

Please could you assist me to add Week number for particular months?
This the vba:
With Target
If .Column <> 10 Or .Row < 1 Then Exit Sub
If .Value = "Select" Then
If .Offset(0, 1).Value = "" Then
.Offset(0, 1).NumberFormat = "mm/dd/yy"
.Offset(0, 1).Value = Now - 1
End If
My definition of week number is based on full weeks being Sunday through to Saturday:
If the first of the month does not start on a Sunday then any days up to the first Saturday of the month will be Week 1
The next sets of Sunday through Saturday will be Week 2, Week 3, Week 4 etc. Unless the month started on a Sunday in which case the sets will be Week 1, Week 2, Week 3 etc.
If the month does not end on a Saturday, then the Sunday through to till the end of the month will be Week N+1 where N is the last full week given by step 2.
For example: this month, the 1st of March is on Wednesday. So March 1st-4th (Wed-Sat) will be 1 week and so on.
You can try and see if the WeekNum function suits your purpose.
You can use it in your code like this:
.Offset(0, 2).Value = WorksheetFunction.WeekNum(Now - 1)
The documentation says:
Returns the week number of a specific date. For example, the week containing January 1 is the first week of the year, and is numbered week 1.
There are two systems used for this function:
System 1 The week containing January 1 is the first week of the year, and is numbered week 1.
System 2 The week containing the first Thursday of the year is the first week of the year, and is numbered as week 1. This system is the methodology specified in ISO 8601, which is commonly known as the European week numbering system.
Edit
OP definition of week is per a desktop calendar where each green block is a week - so March 2017 has 5 weeks. Note January 2016 has six weeks under this system!
Therefore, the WeekNum formula will not give the expected result. Instead the following function can be used:
Function GetCalendarTypeMonthWeek(dt As Date) As String
Dim lngDayOfMonth As Long
Dim lngWeekDay As Long
Dim dtFirstDayOfMonth As Date
Dim lngFactor As Long
lngDayOfMonth = Day(dt)
lngWeekDay = Weekday(dt, vbSunday) '<~~ Sunday=1, Monday=2, etc
'does month start on Sunday?
dtFirstDayOfMonth = DateValue("01-" & Month(dt) & "-" & Year(dt))
If Weekday(dtFirstDayOfMonth, vbSunday) = 1 Then
lngFactor = 1
Else
lngFactor = 2
End If
'get calendar week number for date
GetCalendarTypeMonthWeek = "Week " & CStr(Int((lngDayOfMonth - lngWeekDay) / 7) + lngFactor)
End Function
To be used in the sample code like:
.Offset(0, 2).Value = GetMonthWeek(Now - 1)
I think the next function will return the value you want:
Function WeekOfTheMonth(DateRef As Date) As Integer
Dim WeekFirstDayRefMonth As Integer
WeekFirstDayRefMonth = Application.WeekNum(DateSerial(Year(DateRef), Month(DateRef), 1), 2)
Dim WeekLastDayRefMonthB As Integer
WeekLastDayRefMonthB = Application.WeekNum(DateSerial(Year(DateRef), Month(DateRef), 1) - 1, 2)
Select Case WeekFirstDayRefMonth - WeekLastDayRefMonthB
Case 0: WeekOfTheMonth = Application.WeekNum(DateRef, 2) - WeekLastDayRefMonthB + 1
Case 1: WeekOfTheMonth = Application.WeekNum(DateRef, 2) - WeekLastDayRefMonthB
Case Else: WeekOfTheMonth = Application.WeekNum(DateRef, 2)
End Select
End Function
Just write WeekOfTheMonth("place your date here") on your code and you're good to go.
Please note: I didn't check all the scenarios for this code so please let me know if you're getting unexpected results.

Adding up values in columns with conditions

Being beginner and first time on this site, I truly appreciate your help.
WK 1 WK 2 WK 3 WK 4 WK 5 TOTAL HOURS TOTAL OF FIRST 3 WEEKS <> 0
John 10 0 5 6 5 26 21
Smith 4 1 10 3 4 22 15
Peter 0 4 4 4 2 14 12
Susan 5 5 0 5 8 23 15
From my table I want to add only the first three columns that contain no zero. If there's zero on first three, check on next column and add it up to complete three columns again with no zero value. Some function like in Col H TOTAL OF FIRST 3 WEEKS <>0 (where I had to do it manually).
If I can learn set of VB code or any example with formula or macros, thank you so so much. I'm using Excel 2007.
This is the complicated formula Ali M refers to. It's an array formula entered with ctrl-shift-enter:
=IF(COUNTIF(A2:F2,"<>0")=0,0,SUM(A2:INDEX(A2:F2,SMALL(IF(A2:F2<>0,COLUMN(A2:F2),""),MIN(3,COUNTIF(A2:F2,"<>0"))))))
Note that it works if there are less than three non-zero values.
you can use formula but it would be complicated. instead you can use this subroutine that act exactly as you want!
Public Sub y()
Dim i, sum, c As Integer
Dim Rng, Row, cell As Range
Set Rng = Range("B2:F5")
i = 0
For Each Row In Rng.Rows
For Each cell In Row.Cells
If (cell.Value <> 0 And i < 3) Then
sum = sum + cell.Value
i = i + 1
End If
Next cell
Cells(Row.Row, 7).Value = sum
sum = 0
i = 0
Next Row
End Sub
It always put the sum in column H. you can change it by changing this line:
Cells(Row.Row, 7).Value = sum

Resources