1

I am aware that this question has been asked in many different forms, but I would like to show my case as I have not found the perfect solution for it.

So, what I need to do is divide every month in 4 or 5 weeks, and type it into the corresponding cells.

Example :

June 2021

enter image description here

I have tried this sample code written by User : danieltakeshi in this thread :

https://stackoverflow.com/a/47393516/11969596

But it has a flaw in it, for example if you type a date from October 2021 the result outputs 6 weeks which is impossible :

Sub WeeksInMonth()
Dim MonthYear As String, txt As String
Dim InputDate As Date, MonthYearDay As Date
Dim i As Long, intDaysInMonth As Long, j As Long
Dim MyArray As Variant
Dim arr As New Collection, a
ReDim MyArray(0 To 31)
j = 0
InputDate = ("1 / 10 / 2021") ' Date from October
MonthYear = Month(InputDate) & "/" & Year(InputDate)
intDaysInMonth = Day(DateSerial(Year(MonthYear), Month(MonthYear) + 1, 0))
For i = 1 To intDaysInMonth
    MonthYearDay = DateSerial(Year(InputDate), Month(InputDate), i)
    MyArray(j) = Application.WorksheetFunction.WeekNum(MonthYearDay)
    j = j + 1
Next i

ReDim Preserve MyArray(0 To j - 1)
On Error Resume Next
For Each a In MyArray
    arr.Add a, CStr(a)
Next

For i = 1 To arr.Count
    Debug.Print arr(i)
Next
End Sub

enter image description here

Please help me find a solution, or tell me how I can adapt it to my current situation.

Cordially,

Rooty
  • 43
  • 11
  • 2
    I don't understand, October 2021 does span 6 weeks. – Warcupine Sep 20 '21 at 14:08
  • 1
    Warcupine is correct. You'll need to define your logic and justify why October is _not_ 6 weeks to get an answer that suits your needs. – Michael Murphy Sep 20 '21 at 14:10
  • Thank you for your inputs, after second thought I did not clarify that I am working with Monday as first day of the week, maybe that is where the confusion lies. With that logic, we have week 40 : 1/10/2021 to 3/10/2021, then week 41 : 4/10/2021 to 10/10/2021 until week 44 : 25/10/2021 to 31/10/2021 with a format (dd/mm/yyyy). Which makes it a total of 5 weeks in the month of October 2021. – Rooty Sep 20 '21 at 14:23
  • 2
    https://learn.microsoft.com/en-us/office/vba/api/excel.worksheetfunction.weeknum there is an implicit Sunday start, change the parameter to a 2 – Warcupine Sep 20 '21 at 14:31
  • 1
    In that case you'll want to provide an additional argument to the `WorksheetFunction.WeekNum` line. Seems like `WeekNum(MonthYearDay, 2)` might do the trick going from the documentation. – Michael Murphy Sep 20 '21 at 14:31
  • It actually does, thank you both for your inputs. I also need to consider only the working days which are Monday to Friday, if you head to January 2022 the output of this is also 6 weeks, but I don't need the Week 1 which is only a week-end. Is there a logic I can add to this sample code? And thank you again for your help. – Rooty Sep 20 '21 at 14:40

2 Answers2

1

This routine checks for the first and last workingday (monday to friday) and then gives the calendar weeks for that date range

Option Explicit

Public Sub test_getWeeknumbersForMonth()

Dim arr As Variant
arr = getWeekNumbersForMonth("1.10.2021")
Debug.Print "1.10.2021: ", Join(arr, " - ")

arr = getWeekNumbersForMonth("1.1.2022")
Debug.Print "1.1.2022: ", Join(arr, " - ")


End Sub


Public Function getWeekNumbersForMonth(inputDate As Date) As Variant

Dim datStart As Date
datStart = getFirstWorkingDayOfMonth(inputDate)

Dim datEnd As Date
datEnd = getLastWorkingDayOfMonth(inputDate)

Dim arrWeekNumbers As Variant
ReDim arrWeekNumbers(1 To 6)    'max 6 weeks can be returned

Dim i As Long: i = 1

Dim dat As Date
dat = datStart

While dat <= datEnd
    arrWeekNumbers(i) = getCalendarWeek(dat)
    i = i + 1
    dat = DateAdd("ww", 1, dat)
Wend
    
ReDim Preserve arrWeekNumbers(i - 1)
getWeekNumbersForMonth = arrWeekNumbers

End Function



Private Function getFirstWorkingDayOfMonth(inputDate As Date) As Date
Dim datToCheck As Date: datToCheck = DateSerial(Year(inputDate), Month(inputDate), 1) - 1

Dim isWorkingday As Boolean
Do
    datToCheck = datToCheck + 1
    isWorkingday = Weekday(datToCheck, vbMonday) <= 5
Loop Until isWorkingday = True

getFirstWorkingDayOfMonth = datToCheck

End Function



Private Function getLastWorkingDayOfMonth(inputDate As Date) As Date
Dim datToCheck As Date: datToCheck = DateSerial(Year(inputDate), Month(inputDate) + 1, 1)

Dim isWorkingday As Boolean
Do
    datToCheck = datToCheck - 1
    isWorkingday = Weekday(datToCheck, vbMonday) <= 5
Loop Until isWorkingday = True

getLastWorkingDayOfMonth = datToCheck

End Function



Private Function getCalendarWeek(inputDate As Date) As Long

'european iso week - CW 1 = week with first thursday
getCalendarWeek = Application.WorksheetFunction.IsoWeekNum(inputDate)

'use weeknum-function -adjust second parameter to your needs
'https://support.microsoft.com/en-us/office/weeknum-function-e5c43a03-b4ab-426c-b411-b18c13c75340
'getCalendarWeek = Application.WorksheetFunction.WeekNum(inputDate, 2)
End Function

Ike
  • 9,580
  • 4
  • 13
  • 29
  • Hello Ike, thank you for your input. Your code is exactly what I needed, except for when I chose the month January 2022, it did count the first week which is only a week-end and does not have weekdays (monday to friday) how can I adjust this code, and make it consider these kind of scenarios ? – Rooty Sep 20 '21 at 15:45
  • 1
    The code is correct - Mo, 3.1.2021 = ISO-Calendarweek 1 (1.1.2021 = Calendarweek 52) Or do you calculate calendarweeks in a different way – Ike Sep 20 '21 at 16:05
  • 1
    I changed getISOWeeknumber to getCalendarweek with both Excel-functions ... adjust to your needs – Ike Sep 20 '21 at 16:14
  • I do calculate calendar weeks with Monday as first day of the week, and the working days are from Monday to Friday. If you head to January 2022 you will notice that the first week is a week-end(Sat-Sun). So I need to omit that and count from S2 as first week of the month. – Rooty Sep 20 '21 at 16:18
  • 1
    Then adjust the new getCalendarweek to use WeekNum instead of IsoWeekNum - then your get the result you want to – Ike Sep 20 '21 at 16:22
  • That's exactly what I did, and your answer was the best one so far! Thank you Ike for your input and efforts, don't forget to upvote my question, so I can upvote your answer. I need minimum 15 reputation for that. Cheers – Rooty Sep 20 '21 at 16:24
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/237293/discussion-between-rooty-and-ike). – Rooty Sep 20 '21 at 16:28
0

First, some months have dates in six weeks.

Next, VBA natively can't return the correct ISO 8601 weeknumbers:

How to get correct week number in Access

Finally, week numbers don't care about workdays or weekends. If you wish to exclude weeks that don't include specific weekdays, filter on the dates of these.

Gustav
  • 53,498
  • 7
  • 29
  • 55
  • 1
    You can use Application.WorksheetFunction.IsoWeekNum() to retrieve the ISO weeknumber in VBA - which is not natively but still VBA ... – Ike Sep 20 '21 at 16:17