我也以一种或另一种方式偶然发现了同样的困境,为什么 Excel VBA 没有Date Picker
. 感谢 Sid,他出色地完成了为我们所有人创造一些东西的工作。
尽管如此,我还是到了需要自己创作的地步。我把它贴在这里是因为我确信很多人都会登陆这篇文章并从中受益。
我所做的和 Sid 所做的一样简单,只是我不使用临时工作表。我认为计算非常简单直接,因此无需将其转储到其他地方。这是日历的最终输出:
如何设置:
- 创建 42 个
Label
控件并按顺序命名并从左到右、从上到下排列(此标签包含上面的灰色25
到灰色5
)。Label
将控件的名称更改为Label_01、Label_02等。将所有 42 个标签Tag
属性设置为dts
.
Label
为标题创建另外 7 个控件(这将包含Su、Mo、Tu...)
- 再创建 2 个
Label
控件,一个用于水平线(高度设置为 1),一个用于月和年显示。Label
将用于显示月份和年份的名称命名为Label_MthYr
- 插入 2 个
Image
控件,一个包含左侧图标以滚动上个月,一个包含滚动下个月(我更喜欢简单的左右箭头图标)。命名它Image_Left
并Image_Right
布局应该或多或少像这样(我将创造力留给任何使用它的人)。
声明:
我们需要在最顶部声明一个变量来保存当前选择的月份。
Option Explicit
Private curMonth As Date
私有过程和函数:
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
图像事件:
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
我添加了这个以使它看起来像用户正在单击标签并且也应该在Image_Right
控件上完成。
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
标签事件: 所有 42 个标签 ( to )
都应完成所有这些操作提示:构建前 10 个标签,然后对剩余的标签使用查找和替换。Label_01
Lable_42
Private Sub Label_01_Click()
select_label Me.Label_01
End Sub
这是为了悬停在日期和点击效果。
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
用户窗体事件:
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
同样,只是为了悬停日期效果。
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
就是这样。这是原始的,您可以在其中添加自己的扭曲。
我已经使用了一段时间,并且没有任何问题(性能和功能方面)。
还没有Error Handling
,但我想可以很容易地管理。
实际上,没有效果,代码太短了。
您可以管理您的日期在select_label
程序中的去向。HTH。