Advertisement
jdelano

Rudimentary Calendar

Jan 27th, 2025
827
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ' ***********************  this is the userform code  *********************
  2. Option Explicit
  3.  
  4. ' for sharing 1 click event for each of the command buttons
  5. Private Type TLocals
  6.     AllControls()  As New UsfControlEvents
  7. End Type
  8. Private this As TLocals
  9.  
  10. Dim formIsLoading As Boolean
  11. Public selectedDate As Date
  12.  
  13. Private Sub CreateEventHandlers()
  14.  
  15.     ' date button click event
  16.    Dim ctrl As MSForms.Control, ControlCount As Long
  17.    
  18.     For Each ctrl In Me.Controls
  19.         ' the command button names weren't changed so it was easy to find them on the form
  20.        ' any other command button used will not have command button in it's name
  21.        If InStr(ctrl.Name, "CommandButton") > 0 Then
  22.             ControlCount = ControlCount + 1
  23.             ReDim Preserve this.AllControls(1 To ControlCount)
  24.             With this.AllControls(ControlCount)
  25.                 Set .CmdBttnGroup = ctrl
  26.                 .Init argHostUsf:=Me
  27.             End With
  28.         End If
  29.     Next ctrl
  30.    
  31. End Sub
  32.  
  33.  
  34. Private Function GetButton(buttonName) As MSForms.CommandButton
  35.    
  36.     ' get the button asked for
  37.    Dim ctrl As Control
  38.     Dim foundButton As MSForms.CommandButton
  39.    
  40.     For Each ctrl In frmCalendar.Controls
  41.        
  42.         If ctrl.Name = buttonName Then
  43.             Set foundButton = ctrl
  44.             Exit For
  45.         End If
  46.    
  47.     Next ctrl
  48.    
  49.     Set GetButton = foundButton
  50.    
  51. End Function
  52.  
  53. Private Sub HideButtons()
  54.  
  55.     ' reset the visibility of the buttons used as dates
  56.    Dim ctrl As Control
  57.    
  58.     For Each ctrl In frmCalendar.Controls
  59.         If InStr(ctrl.Name, "Command") > 0 Then ctrl.Visible = False
  60.     Next ctrl
  61.  
  62. End Sub
  63.  
  64. Private Sub SelectMonthYear()
  65.  
  66.     drpMonth.ListIndex = Month(Date) - 1 ' select the current month
  67.    
  68.     ' select the current year
  69.    Dim idx As Integer
  70.     For idx = 0 To drpYear.ListCount - 1
  71.         drpYear.ListIndex = idx
  72.         If drpYear.Text = Year(Date) Then Exit For
  73.    
  74.     Next idx
  75.  
  76. End Sub
  77.  
  78. Private Sub FillCalendar(theMonth As Integer, theYear As Integer)
  79.  
  80.     ' fill the form with the selected month and year
  81.    Dim dayNumber As Integer
  82.     Dim firstDayNextMonth As Date
  83.     Dim firstDayThisMonth As Date
  84.     Dim lastDayThisMonth As Date
  85.     Dim buttonName As String
  86.     Dim buttonNumber As Integer
  87.     Dim dayButton As MSForms.CommandButton
  88.    
  89.     ' calc the first and last days of the month
  90.    firstDayThisMonth = CDate(theMonth & "/1/" & theYear)
  91.    
  92.     firstDayNextMonth = DateAdd("m", 1, firstDayThisMonth)
  93.    
  94.     lastDayThisMonth = firstDayNextMonth - 1
  95.    
  96.     buttonNumber = Weekday(firstDayThisMonth) ' assign the button number to start with
  97.    
  98.     dayNumber = 1
  99.     Do While True
  100.         buttonName = "CommandButton" & buttonNumber
  101.        
  102.         Set dayButton = GetButton(buttonName)
  103.         dayButton.Caption = dayNumber
  104.         dayButton.Visible = True
  105.         dayButton.BackColor = Me.BackColor  ' reset the color of button as "not selected"
  106.        
  107.         ' if true the current days date will have a bold font
  108.        If CDate(drpMonth.Text & " " & dayNumber & ", " & drpYear.Text) = Date Then
  109.             dayButton.ForeColor = vbBlue
  110.         Else
  111.             dayButton.ForeColor = vbBlack
  112.         End If
  113.                
  114.         ' when we reach the last day of the month exit this loop
  115.        If dayNumber = Day(lastDayThisMonth) Then Exit Do
  116.        
  117.         ' increment the day number and the button number it should be placed on
  118.        dayNumber = dayNumber + 1
  119.         buttonNumber = buttonNumber + 1
  120.          
  121.     Loop
  122.    
  123.     ' write the current month year being displayed
  124.    Me.Tag = theMonth & "|" & theYear
  125.    
  126. End Sub
  127.  
  128. Private Sub FillMonthDropDown()
  129.  
  130.     ' fill the month dropdown
  131.    drpMonth.List = Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December")
  132.    
  133. End Sub
  134.  
  135. Private Sub FillYearCombo()
  136.  
  137.     ' fill the year combobox
  138.    drpYear.List = Array(Year(Date) - 1, Year(Date), Year(Date) + 1, Year(Date) + 2, Year(Date) + 3, Year(Date) + 5, Year(Date) + 5)
  139.        
  140. End Sub
  141.  
  142. Private Sub HighlightDateButton(dateToHighlight As Date)
  143.    
  144. End Sub
  145.  
  146. Private Sub btnOK_Click()
  147.     ' close the form
  148.    Me.Hide
  149.    
  150. End Sub
  151.  
  152. Private Sub drpMonth_Click()
  153.     ' update the calendar to display the selected month, there has to be a year
  154.    If Not formIsLoading Then
  155.         HideButtons
  156.         FillCalendar drpMonth.ListIndex + 1, drpYear.Text
  157.     End If
  158.  
  159. End Sub
  160.  
  161. Private Sub drpYear_Click()
  162.         ' update the calendar to display the selected month, there has to be a year
  163.    If Not formIsLoading Then
  164.         HideButtons
  165.         FillCalendar drpMonth.ListIndex + 1, drpYear.Text
  166.     End If
  167.  
  168. End Sub
  169.  
  170. Private Sub UserForm_Initialize()
  171.  
  172.     ' fill the form with the current month and highlight today
  173.    formIsLoading = True
  174.    
  175.     FillMonthDropDown
  176.     FillYearCombo
  177.     SelectMonthYear
  178.    
  179.     FillCalendar Month(Date), Year(Date)
  180.    
  181.     formIsLoading = False
  182.    
  183.     ' assign each of the day buttons the same event handler
  184.    CreateEventHandlers
  185.    
  186. End Sub
  187.  
  188. Private Sub UserForm_Terminate()
  189.    
  190. End Sub
  191.  
  192.  
  193. ' *************************  Module1 UDF
  194. Public Function AskForDate() As Date
  195.    
  196.     Dim dateSelected As Date
  197.    
  198.     frmCalendar.Show vbModal
  199.     dateSelected = frmCalendar.selectedDate
  200.    
  201.     Unload frmCalendar
  202.    
  203.     AskForDate = dateSelected
  204. End Function
  205.  
  206.  
  207. ' ******************** User Class to hold the shared CommandButton click event
  208. ' create an event that all the buttons use
  209. ' from https://www.mrexcel.com/board/threads/how-to-reference-a-userform-command-button-click-event-when-the-button-was-created-dynamically.1189029/
  210.  
  211. Public WithEvents CmdBttnGroup As MSForms.CommandButton
  212.  
  213. Private Type TLocals
  214.     Usf As Object
  215. End Type
  216. Private this As TLocals
  217.  
  218. Public Sub Init(ByVal argHostUsf As Object)
  219.     Set this.Usf = argHostUsf
  220. End Sub
  221.  
  222. Private Sub CmdBttnGroup_Click()
  223.  
  224.     ' indicate the selected date and assign it to the public
  225.    CmdBttnGroup.BackColor = vbYellow
  226.     Dim parentForm As frmCalendar
  227.     Set parentForm = CmdBttnGroup.Parent
  228.    
  229.     parentForm.selectedDate = CDate(parentForm.drpMonth.ListIndex + 1 & "/" & CmdBttnGroup.Caption & "/" & parentForm.drpYear.Text)
  230.     Set parentForm = Nothing
  231.    
  232. End Sub
  233.  
  234.  
  235. ' ******************************  worksheet code
  236. Private Sub CommandButton1_Click()
  237.     ' direct call to a cell
  238.    Sheet1.Cells(2, 2).Value = AskForDate()
  239.    
  240. End Sub
  241.  
  242. Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  243.     ' if the user clicks into a cell on col B allow them to pick a date
  244.    ' ignore the header and the row with a button that lets the user select a date
  245.    If Target.Column = 2 And Target.Row > 2 Then
  246.         ' the user clicked into the column requiring a date
  247.        Sheet1.Cells(Target.Row, 2).Value = AskForDate()
  248.  
  249.     End If
  250.    
  251. End Sub
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement