Formatting MM/DD/YYYY dates in textbox in VBA

前端 未结 9 1745
故里飘歌
故里飘歌 2020-11-22 10:47

I\'m looking for a way to automatically format the date in a VBA text box to a MM/DD/YYYY format, and I want it to format as the user is typing it in. For instance, once the

9条回答
  •  轮回少年
    2020-11-22 11:11

    I too, one way or another stumbled on the same dilemma, why the heck Excel VBA doesn't have a Date Picker. Thanks to Sid, who made an awesome job to create something for all of us.

    Nonetheless, I came to a point where I need to create my own. And I am posting it here since a lot of people I'm sure lands on this post and benefit from it.

    What I did was very simple as what Sid does except that I do not use a temporary worksheet. I thought the calculations are very simple and straight forward so there's no need to dump it somewhere else. Here's the final output of the calendar:

    enter image description here

    How to set it up:

    • Create 42 Label controls and name it sequentially and arranged left to right, top to bottom (This labels contains greyed 25 up to greyed 5 above). Change the name of the Label controls to Label_01,Label_02 and so on. Set all 42 labels Tag property to dts.
    • Create 7 more Label controls for the header (this will contain Su,Mo,Tu...)
    • Create 2 more Label control, one for the horizontal line (height set to 1) and one for the Month and Year display. Name the Label used for displaying month and year Label_MthYr
    • Insert 2 Image controls, one to contain the left icon to scroll previous months and one to scroll next month (I prefer simple left and right arrow head icon). Name it Image_Left and Image_Right

    The layout should be more or less like this (I leave the creativity to anyone who'll use this).

    enter image description here

    Declaration:
    We need one variable declared at the very top to hold the current month selected.

    Option Explicit
    Private curMonth As Date
    

    Private Procedure and Functions:

    Private Function FirstCalSun(ref_date As Date) As Date
        '/* returns the first Calendar sunday */
        FirstCalSun = DateSerial(Year(ref_date), _
                      Month(ref_date), 1) - (Weekday(ref_date) - 1)
    End Function
    

    Private Sub Build_Calendar(first_sunday As Date)
        '/* This builds the calendar and adds formatting to it */
        Dim lDate As MSForms.Label
        Dim i As Integer, a_date As Date
    
        For i = 1 To 42
            a_date = first_sunday + (i - 1)
            Set lDate = Me.Controls("Label_" & Format(i, "00"))
            lDate.Caption = Day(a_date)
            If Month(a_date) <> Month(curMonth) Then
                lDate.ForeColor = &H80000011
            Else
                If Weekday(a_date) = 1 Then
                    lDate.ForeColor = &HC0&
                Else
                    lDate.ForeColor = &H80000012
                End If
            End If
        Next
    End Sub
    

    Private Sub select_label(msForm_C As MSForms.Control)
        '/* Capture the selected date */
        Dim i As Integer, sel_date As Date
        i = Split(msForm_C.Name, "_")(1) - 1
        sel_date = FirstCalSun(curMonth) + i
    
        '/* Transfer the date where you want it to go */
        MsgBox sel_date
    
    End Sub
    

    Image Events:

    Private Sub Image_Left_Click()
    
        If Month(curMonth) = 1 Then
            curMonth = DateSerial(Year(curMonth) - 1, 12, 1)
        Else
            curMonth = DateSerial(Year(curMonth), Month(curMonth) - 1, 1)
        End If
    
        With Me
            .Label_MthYr.Caption = Format(curMonth, "mmmm, yyyy")
            Build_Calendar FirstCalSun(curMonth)
        End With
    
    End Sub
    

    Private Sub Image_Right_Click()
    
        If Month(curMonth) = 12 Then
            curMonth = DateSerial(Year(curMonth) + 1, 1, 1)
        Else
            curMonth = DateSerial(Year(curMonth), Month(curMonth) + 1, 1)
        End If
    
        With Me
            .Label_MthYr.Caption = Format(curMonth, "mmmm, yyyy")
            Build_Calendar FirstCalSun(curMonth)
        End With
    
    End Sub
    

    I added this to make it look like the user is clicking the label and should be done on the Image_Right control too.

    Private Sub Image_Left_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, _
                                     ByVal X As Single, ByVal Y As Single)
        Me.Image_Left.BorderStyle = fmBorderStyleSingle
    End Sub
    
    Private Sub Image_Left_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, _
                                   ByVal X As Single, ByVal Y As Single)
        Me.Image_Left.BorderStyle = fmBorderStyleNone
    End Sub
    

    Label Events:
    All of this should be done for all 42 labels (Label_01 to Lable_42)
    Tip: Build the first 10 and just use find and replace for the remaining.

    Private Sub Label_01_Click()
        select_label Me.Label_01
    End Sub
    

    This is for hovering over dates and clicking effect.

    Private Sub Label_01_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, _
                                   ByVal X As Single, ByVal Y As Single)
        Me.Label_01.BorderStyle = fmBorderStyleSingle
    End Sub
    
    Private Sub Label_01_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, _
                                   ByVal X As Single, ByVal Y As Single)
        Me.Label_01.BackColor = &H8000000B
    End Sub
    
    Private Sub Label_01_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, _
                                 ByVal X As Single, ByVal Y As Single)
        Me.Label_01.BorderStyle = fmBorderStyleNone
    End Sub
    

    UserForm Events:

    Private Sub UserForm_Initialize()
        '/* This is to initialize everything */
        With Me
            curMonth = DateSerial(Year(Date), Month(Date), 1)
            .Label_MthYr = Format(curMonth, "mmmm, yyyy")
            Build_Calendar FirstCalSun(curMonth)
        End With
    
    End Sub
    

    Again, just for the hovering over dates effect.

    Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, _
                                   ByVal X As Single, ByVal Y As Single)
    
        With Me
            Dim ctl As MSForms.Control, lb As MSForms.Label
    
            For Each ctl In .Controls
                If ctl.Tag = "dts" Then
                    Set lb = ctl: lb.BackColor = &H80000005
                End If
            Next
        End With
    
    End Sub
    

    And that's it. This is raw and you can add your own twist to it.
    I've been using this for awhile and I have no issues (performance and functionality wise).
    No Error Handling yet but can be easily managed I guess.
    Actually, without the effects, the code is too short.
    You can manage where your dates go in the select_label procedure. HTH.

提交回复
热议问题