ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[分享] UI设计自制日历窗体(无需注册MSCOMCTL.OCX)

  [复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-12-26 21:58 | 显示全部楼层

多谢您的肯定和支持!

后续(根据论坛网友的反馈)可能还会有更新,敬请关注!

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-12-26 22:35 | 显示全部楼层
pao810 发表于 2023-12-26 10:14
导入到系统倒是运行成功了,但是图2里代码这样设置有点麻烦,希望能改一下,
我用的系统是win7,64位,WP ...

可否简要解释一下“代码这样设置有点麻烦”这句话的意思,以及希望如何改进。多说一点,说具体一点。

如果是有依据地觉得麻烦,那必定有更好的想法;如果只是单纯觉得麻烦,那可能是想用一行代码完成这多行代码的功能。如果是后者,请试试用一行代码改写如下代码,完成相同的功能:


  1. Sub 一行秒杀()
  2.     Dim i As Long
  3.     For i = 0 To 100
  4.         Debug.Print i
  5.     Next i
  6. End Sub
复制代码


不过,这写法确实有点不好。首先是,不应把类的私有成员暴露出来,应该调用公开成员(属性或者方法)。比如这里的UserForm的TextBox对象就不应该暴露出来,可以改写成UserForm.OnCalendarSelectionChange(参数1,参数2),然后在UserForm的类模块里面进行Select Case。但不管怎么弄,这个Select Case是免不了的,因为这里有好几个文本框,各自有不同的日历窗体,对Userform来说不做选择的话没法区分。

其次是参数传递问题,和上一个问题有点类似,参数直接穿透两个模块,而非由一个模块传递到另一个模块。日期参数应该在UserForm模块里面处理。

更好的做法是,只用一个日历窗体,对应多个文本框。在不同文本框被激活时,把日历窗体移动到获得焦点的文本框即可。这样,对UserForm来说,不同于之前需要考虑“日期来自哪个日历窗体,它对应的文本框是哪个”这样的问题,而只需要考虑“日期已选,给弹出日历窗体的文本框赋值”就行。


又或者另一种做法,把日期选没选,日期是什么这些信息放到全局变量里面,由调出日历窗体的文本框读取。这样可以省去UserForm纠结于日期来源于哪个日历窗体的问题:因为同一时间只能显示一个日历窗体,且只有一个文本框被激活。这两者只需通过全局变量沟通即可。

TA的精华主题

TA的得分主题

发表于 2023-12-27 11:06 | 显示全部楼层
prome3 发表于 2023-12-25 21:37
感谢反馈!

这条件编译的写法确实是有问题的,现已做更改,请见附件。

我去尝试下,谢谢分析及分享

TA的精华主题

TA的得分主题

发表于 2023-12-27 15:15 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
prome3 发表于 2023-12-25 21:20
感谢评论反馈!

把下图红色框线中的那行代码删掉或者注释掉就行:

发现一个问题,只要前一次选了一个日期,后续再调用日历控件时标颜色的当天日期错误了就自动变为前一次选择的日期

TA的精华主题

TA的得分主题

发表于 2023-12-27 15:21 | 显示全部楼层

楼主发现一个问题,只要前一次选了一个日期,后续再调用日历控件时标颜色的当天日期就错误了就自动变为前一次选择的日期

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-12-27 21:31 | 显示全部楼层
pao810 发表于 2023-12-26 10:14
导入到系统倒是运行成功了,但是图2里代码这样设置有点麻烦,希望能改一下,
我用的系统是win7,64位,WP ...

42楼想表达的意思都在此楼层附件里面了。只有代码,没有工作簿文件,需自行导入工作簿编译运行。

窗体控件共用日历窗体-代码.zip

5.81 KB, 下载次数: 48

TA的精华主题

TA的得分主题

发表于 2023-12-28 17:29 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-12-28 21:21 | 显示全部楼层
jian82372387 发表于 2023-12-27 15:21
楼主发现一个问题,只要前一次选了一个日期,后续再调用日历控件时标颜色的当天日期就错误了就自动变为前 ...

这确实是一个问题,也是一个重大发现。
出现这个问题的原因是:在目前的代码下,从打开工作簿第一次调用日历窗体开始,到关闭工作簿为止,用的都是同一个日历控件,期间对日历的每一次操作都只是显示和隐藏这个日历。所以,每一次调用日历窗体时显示的都是上一次选择的日期。如果是在固定的单元格这样显示,其实是没问题的,能保证单元格值和日历窗体显示的日期一致:

图1 在固定单元格调用日历

图1 在固定单元格调用日历

比如上面图1中,我选择了一个日期,日历窗体自动隐藏起来;如果下一次再在这个单元格调用日历窗体时,弹出来的是下面图2这样的:

图2 同一单元格,第二次调用日历

图2 同一单元格,第二次调用日历

那就会很奇怪。所以在弹出时,就得保证单元格和日历值显示的是一致的。但是在目前的代码下,如果在多个不同的单元格调用这同一个日历控件,就明显的是个问题了。


在提供我的解决办法之前,先说一点,这句话

楼主发现一个问题,只要前一次选了一个日期,后续再调用日历控件时标颜色的当天日期就错误了就自动变为前一次选择的日期
中的“后续再调用日历控件时”,应该是“后续再显示这个日历控件时”;“就错误了”、“自动变为”,其实是压根没变,还是前一次选择的日期,日历只是隐藏了又再次显示而已。这句话是把当前代码的行为和预期的行为混淆在一起了,描述得不太恰当。


上述问题的解决之法如下(诸位或有更好的方法,还请不吝赐教于本作者):

如果要每次显示日历控件时都默认选中“今天”日期(虽然不推荐这种做法,因为违背了上面所追求的一致性),可以每次调用日历控件时都用新建的日历控件,也就是新建日历控件对象,代码做如下图3所示改动:

图3 注释掉这两行代码

图3 注释掉这两行代码

如果要根据不同单元格的值来显示日历控件,则按如下图4-1和图4-2所示改已有代码:

图4-1 窗体模块新增成员

图4-1 窗体模块新增成员

图4-2 向窗体模块新增成员传递活动单元格的值

图4-2 向窗体模块新增成员传递活动单元格的值

(即新增红色方框中的代码)


完整代码和示例工作簿请见附件。后续如有其它问题欢迎继续留言讨论!

日历窗体示例_2023-12-28更新.zip

120.82 KB, 下载次数: 76

根据单元格已有的日期值显示日历窗体

TA的精华主题

TA的得分主题

发表于 2023-12-31 18:03 来自手机 | 显示全部楼层
prome3 发表于 2023-12-27 21:31
42楼想表达的意思都在此楼层附件里面了。只有代码,没有工作簿文件,需自行导入工作簿编译运行。

感谢,完美运行

TA的精华主题

TA的得分主题

发表于 2024-1-2 22:02 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
像我这样不懂WINDOWS API的,就无法理解了。但还是占赞
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-19 05:54 , Processed in 0.046130 second(s), 6 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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