ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 46846|回复: 109

[原创] 自建日历选择窗口取代VBA日历控件mscomct2.ocx解决兼容问题

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2018-8-21 15:18 | 显示全部楼层 |阅读模式
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 向東 于 2018-8-21 15:29 编辑

对于VBA日历控件,之前因为Excel版本兼容问题,
想着自己来写一个程序取代VBA日历控件,
来解决版本不兼容的问题,后来经过研究摸索,
又参考了别人写的代码,终于写成了。

这个完全解决了版本兼容的问题,不管Excel 2003还是2016,
不管32位还是64位,都能正常使用!

因为一直在我写的一个小程序里用着,没有单独拿出来,
今天有空就分离了出来,给大家分享一下!
里面注释很详细,原理说的比较清楚,稍微改造一下就能用了。

另外:
里面的CalendarForm窗口,模块bindBuntonModule,类模块buttonEvent可以导出,
然后在导入到你想使用的VBE中就可以了,窗口的格式及其中的代码都会保留,
这样也方便改造使用。注意,改造的时候CalendarForm窗口,类模块buttonEvent中
含有使用自定义窗口frm_query的代码,需要换成你自己的。

日历控件.JPG

核心代码:
  1. Private Sub bottonDate(sMonth As Date, eMonth As Date)   '42个日期按钮,为每个按钮写上对应的日期值 (此处是代码比较难理解)
  2.     Dim i As Long
  3.     Dim Y As Integer, m As Integer
  4.    
  5.     Y = Year(sMonth)
  6.     m = Month(eMonth)

  7.     For i = 1 To 42   '42个日期按钮,为每个按钮写上对应的日期值
  8.         With Me.Controls("CommandButton" & i)
  9.             If i >= Weekday(sMonth, vbMonday) And i <= Weekday(sMonth, vbMonday) + Day(eMonth) - 1 Then '开始日期和结束日期之间对应的 按钮
  10.                 '选择月1号对应的按钮编号 等于 选择月份的1号对应的星期数;最后一个按钮的编号等于第一个按钮编号 加上 选择月份的总天数(Day(eMonth))减去1
  11.                 .Caption = i - Weekday(sMonth, vbMonday) + 1   '按钮的标题设置为 当前按钮的编号 减去 选择月1号对应的按钮编号 加上 1
  12.                 .ControlTipText = "" '清除按钮上的提示文字
  13.                 .Tag = ""  '清除附加信息
  14.                
  15.                 If (i + 1) Mod 7 = 0 Or i Mod 7 = 0 Then '周六、周日
  16.                     .ForeColor = &HFF& '字体设为红色色
  17.                 Else
  18.                     .ForeColor = &H80000012  '字体设为黑色
  19.                 End If
  20.                
  21.                 If i = Day(Date) + Weekday(sMonth, vbMonday) - 1 And Y = Year(Date) And m = Month(Date) Then '如果某 按钮 上是 今天的日期
  22.                     .BackColor = &HC0FFFF    'vbYellow    '将今日对应的按钮背景色改成 浅黄
  23.                     .ControlTipText = "今日" '设置按钮上的提示文字
  24.                 Else
  25.                     .BackColor = RGB(255, 255, 255)    '其它按钮的背景色显示为活动状态颜色
  26.                 End If
  27.                 If i = Val(TextBoxD.Value) + Weekday(sMonth, vbMonday) - 1 Then .SetFocus '如果某 按钮 上是设置的日期 给按钮设置焦点
  28.                
  29.             ElseIf i < 7 Then '选择月份的上个月的最后几天
  30.                 .Caption = Day(DateSerial(Y, m, 0)) - Weekday(sMonth, vbMonday) + i + 1  '按钮的标题设置为 当前按钮的编号 减去 选择月1号对应的按钮编号 加上 1
  31.                 .ControlTipText = m - 1 & "月" & .Caption & "日" '添加按钮上的提示文字 上月
  32.                 .Tag = m - 1 '附加信息 为上月的月份数
  33.                
  34.                 If (i + 1) Mod 7 = 0 Or i Mod 7 = 0 Then '周六、周日
  35.                     .ForeColor = &HC0C0FF    '字体设为淡红色色
  36.                 Else
  37.                     .ForeColor = &HC0C0C0  ' &H80000011   '字体设为灰色
  38.                 End If
  39.                                 
  40.                 .BackColor = &H8000000F '设置成失活状态颜色
  41.             Else '选择月份的下个月的前几天
  42.                 .Caption = i - Weekday(sMonth, vbMonday) + 1 - Day(eMonth) '按钮的标题设置为 当前按钮的编号 减去 选择月1号对应的按钮编号 加上 1
  43.                 .ControlTipText = m + 1 & "月" & .Caption & "日"  '添加按钮上的提示文字 下月
  44.                 .Tag = m + 1 '附加信息 为下月的月份数
  45.                
  46.                 If (i + 1) Mod 7 = 0 Or i Mod 7 = 0 Then '周六、周日
  47.                     .ForeColor = &HC0C0FF    '字体设为淡红色色
  48.                 Else
  49.                     .ForeColor = &HC0C0C0   '&H80000011   '字体设为灰色
  50.                 End If
  51.                               
  52.                 .BackColor = &H8000000F   '设置成失活状态颜色
  53.             End If
  54.         
  55.         End With
  56.     Next
  57. End Sub
复制代码

要是使用或者代码有任何问题欢迎指正,共同进步。

自建日历选择窗口.rar (37.74 KB, 下载次数: 1825)



补充内容 (2018-11-8 13:24):
打个补丁:
把上面代码中的
.ControlTipText = m - 1 & "月" & .Caption & "日" '添加按钮上的提示文字 上月
修改一下,增加判断当前是不是1月,否则上月提示会显示0月。

补充内容 (2018-11-8 13:24):
If m - 1 = 0 Then
        .ControlTipText = "12月" & .Caption & "日"  '本月是1月,添加按钮上的提示文字 上月
Else
        .ControlTipText = m - 1 & "月" & .Caption & "日" '添加按钮上的提示文字 上月
End If

补充内容 (2018-11-8 13:25):
.ControlTipText = m + 1 & "月" & .Caption & "日"  '添加按钮上的提示文字 下月
修改如下:

补充内容 (2018-11-8 13:25):
If m + 1 = 13 Then
        .ControlTipText = "1月" & .Caption & "日"   '本月是12月,添加按钮上的提示文字 下月
Else
        .ControlTipText = m + 1 & "月" & .Caption & "日"  '添加按钮上的提示文字 下月
End If

补充内容 (2019-12-23 12:18):
针对大家普遍的使用需求,今天有空升级了一下代码,点选指定的单元格就会弹出日历选择窗口,如果要指定一个单元格范围,原理相同,自己酌情修改即可。
代码参见:http://club.excelhome.net/forum. ... 56&pid=10187795

补充内容 (2021-12-19 21:11):
程序再小调整一下,参见102楼:
https://club.excelhome.net/forum ... 56&pid=10856397

评分

16

查看全部评分

TA的精华主题

TA的得分主题

发表于 2018-8-27 01:07 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
   真    棒

TA的精华主题

TA的得分主题

 楼主| 发表于 2018-9-1 07:54 | 显示全部楼层
不满意的地方是类模块buttonEvent中,把自定义窗口写死了,不知道如何写才好,欢迎大家指点、交流!

TA的精华主题

TA的得分主题

发表于 2018-9-6 15:36 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2018-9-6 16:01 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
xu_shiqian 发表于 2018-9-6 15:36
楼主太厉害了,希望能够跳过那该死的兼容性问题。

这个全兼容,我测试过了,Excel2003到2016,32位、64位都没问题,通用。

TA的精华主题

TA的得分主题

发表于 2018-9-9 21:41 | 显示全部楼层
非常感谢楼主,我已经采用你的模块完美的解决了DTPicker不兼容的问题,对你的模块稍作了改动,将年月日从选项卡里面移出来用标签显示了,并且由于我的程序中会很多地方用到时间控件,我将其做成了一个类似独立控件,输出值全送到一个单元格中,然后再通过单元格的变化送到各点击的文本框中,表现的形式与系统的时间控件完全一样。
再也不用因移动到不同电脑上要费很长时间去搞DTPicker的问题了。

应用图片

应用图片

TA的精华主题

TA的得分主题

发表于 2018-9-9 21:53 | 显示全部楼层
主要改了类模块的输出接口
Private Sub buttonGroup_Click() '&Egrave;&Otilde;&AElig;&Uacute;°&acute;&Aring;&yen; &Ecirc;&Acirc;&frac14;&thorn; &Agrave;à
      
    Dim Y, m As Integer
    If Len(buttonGroup.Caption) = 0 Then Exit Sub
   
    With CalendarForm
        Y = Val(.ComboBoxY.Value) '&Egrave;&yen;&micro;&ocirc;&Oacute;&Ograve;±&szlig;&micro;&Auml;"&Auml;ê"
        m = Val(.ComboBoxM.Value)
        
        If Y < 1901 Then
            MsgBox "&Auml;ê·&Yacute;&sup2;&raquo;&Auml;&Uuml;&ETH;&iexcl;&Oacute;&Uacute;1901,&Ccedil;&euml;&Ouml;&Oslash;&ETH;&Acirc;&Ecirc;&auml;&Egrave;&euml;&pound;&iexcl;" 'Excel&frac14;&Ugrave;&para;¨1900&Auml;ê&Ecirc;&Ccedil;&Egrave;ò&Auml;ê&pound;&not;&Otilde;&acirc;&Ecirc;&Ccedil;&acute;í&Icirc;ó&micro;&Auml;&iexcl;&pound;
            .ComboBoxY.SetFocus
            Exit Sub
        End If
        
    End With
   
    On Error Resume Next
   
  
                If Len(buttonGroup.Tag) = 0 Then
                    Thehide.Cells(35, 1).Value = DateSerial(Y, m, buttonGroup.Caption) '&cedil;&sup3;&Ouml;&micro;&cedil;&oslash;&iquest;&ordf;&Ecirc;&frac14;&Egrave;&Otilde;&AElig;&Uacute;&pound;¨&Auml;ê-&Ocirc;&Acirc;-&Egrave;&Otilde;&pound;&copy;  ‘输出到一个单元格
                Else
                    Thehide.Cells(35, 1).Value = DateSerial(Y, Val(buttonGroup.Tag), buttonGroup.Caption) ' &sup2;&raquo;&Ecirc;&Ccedil;±&frac34;&Ocirc;&Acirc; &cedil;&sup3;&Ouml;&micro;&cedil;&oslash;&iquest;&ordf;&Ecirc;&frac14;&Egrave;&Otilde;&AElig;&Uacute;&pound;¨&Auml;ê-&Ocirc;&Acirc;-&Egrave;&Otilde;&pound;&copy;
                End If
            
            
    CalendarForm.Hide
    On Error GoTo 0
End Sub

‘所有结果均输出到同一单元格’
‘然后自己写了一个单元格的变化触发输出到不同的文本框控件的程序’

Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Row = 35 And Target.Column = 1 Then
    If Thehide.Cells(35, 3).Value = "Pg2form" And Thehide.Cells(35, 2).Value = "DTPISL1" Then
        Pg2form.DTPISL1.Value = Target.Value
   
    ElseIf Thehide.Cells(35, 3).Value = "Pg2form" And Thehide.Cells(35, 2).Value = "DTPISL2" Then
        Pg2form.DTPISL2.Value = Target.Value
        
    ElseIf Thehide.Cells(35, 3).Value = "Pg2form" And Thehide.Cells(35, 2).Value = "DTPISL3" Then
        Pg2form.DTPISL3.Value = Target.Value
        
    ElseIf Thehide.Cells(35, 3).Value = "Pg2form" And Thehide.Cells(35, 2).Value = "DTPISL4" Then
        Pg2form.DTPISL4.Value = Target.Value
        
    ElseIf Thehide.Cells(35, 3).Value = "Pg2form" And Thehide.Cells(35, 2).Value = "DTPISL5" Then
        Pg2form.DTPISL5.Value = Target.Value
        
    ElseIf Thehide.Cells(35, 3).Value = "Pg2form" And Thehide.Cells(35, 2).Value = "DTPISL6" Then
        Pg2form.DTPISL6.Value = Target.Value
        
        
    ElseIf Thehide.Cells(35, 3).Value = "Pg6form" And Thehide.Cells(35, 2).Value = "DTPISL2" Then
        Pg6form.DTPISL2.Value = Target.Value
        
    ElseIf Thehide.Cells(35, 3).Value = "Pg7form" And Thehide.Cells(35, 2).Value = "DTPISL1" Then
        Pg7form.DTPISL1.Value = Target.Value
        
    ElseIf Thehide.Cells(35, 3).Value = "Pg7form" And Thehide.Cells(35, 2).Value = "DTPISL2" Then
        Pg7form.DTPISL2.Value = Target.Value
        
    ElseIf Thehide.Cells(35, 3).Value = "Pg7form" And Thehide.Cells(35, 2).Value = "DTPISL3" Then
        Pg7form.DTPISL3.Value = Target.Value
   
    ElseIf Thehide.Cells(35, 3).Value = "Pg7form" And Thehide.Cells(35, 2).Value = "DTPpayment" Then
        Pg7form.DTPpayment.Value = Target.Value
        
   
    End If
   
End If

End Sub

这样就完美的用一个日历窗体解决了很多个日期控件的问题,表现得跟DTPicker一样。

评分

3

查看全部评分

TA的精华主题

TA的得分主题

发表于 2018-9-10 07:34 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
xu_shiqian 发表于 2018-9-9 21:53
主要改了类模块的输出接口
Private Sub buttonGroup_Click() '&Egrave;&Otilde;&AElig;&Uacute;°&acute;& ...

希望楼上老师能上传附件,学习下!谢谢!

TA的精华主题

TA的得分主题

 楼主| 发表于 2018-9-10 08:32 | 显示全部楼层
xu_shiqian 发表于 2018-9-9 21:41
非常感谢楼主,我已经采用你的模块完美的解决了DTPicker不兼容的问题,对你的模块稍作了改动,将年月日从选 ...

我觉得类模块里要改一下,使得更通用。因为我的查询窗口就一个,所以也没花心思,暂时写死了,你这样改一下就解决多窗口查询的问题了。不错,值得借鉴。

TA的精华主题

TA的得分主题

发表于 2018-10-7 20:37 | 显示全部楼层
因为自己的程序比较大,利用放假将模块部分导出,简单作了个示例,供参考。

Calendar.zip

44.34 KB, 下载次数: 1297

日历窗体通用接口

评分

4

查看全部评分

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-12-22 16:48 , Processed in 0.044566 second(s), 10 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表