ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[求助] 类模块封装事件

[复制链接]

TA的精华主题

TA的得分主题

发表于 2023-3-1 14:38 | 显示全部楼层 |阅读模式
本人VBA刚入门。现想实现的功能是:对一个工作本(Workbook)中的所有四张工作簿(Worksheet),每当任意一工作簿激活就实现改工作簿A1单元格内容填充成"F4"。


我计划使用类模块的功能,并在建立类模块,命名为"Module1",并写入代码:
  1. Private WithEvents m_Wst As Worksheet

  2. Property Set wst(RHS As Worksheet)
  3.     Set m_Wst = RHS
  4. End Property

  5. Property Get wst() As Worksheet
  6.     Set wst = m_Wst
  7. End Property

  8. Private Sub m_Wst_Activate()
  9.     m_Wst.Cells(1, 1).ClearContents
  10.     m_Wst.Cells(1, 1).Value = "F4"
  11. End Sub
复制代码
同时,在ThisWorkbook中写入代码,将类实例化,同时将四张工作簿赋值给实例:
  1. Sub df()
  2.     Dim n As Integer
  3.     Dim arr(1 To 4) As New Module1
  4.    
  5.     Dim i As Integer
  6.     For i = 1 To 4
  7.         Set arr(i).wst = Me.Sheets(i)
  8.     Next
  9.    
  10. End Sub
复制代码
但是运行过程df后,仍然未能成功实现计划功能。所以想请版友帮忙看一下具体是哪个环节发生了问题。提前感谢大家。

TA的精华主题

TA的得分主题

发表于 2023-3-1 15:09 | 显示全部楼层
刚入门就研究类模块,厉害。
直接用工作簿工作表激活事件来写吧,不用类模块。
Private Sub Workbook_SheetActivate(ByVal Sh As Object)

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-3-1 15:13 | 显示全部楼层
q3698995 发表于 2023-3-1 15:09
刚入门就研究类模块,厉害。
直接用工作簿工作表激活事件来写吧,不用类模块。
Private Sub Workbook_She ...

谢谢您的建议。
由于可能后期考虑程序的拓展性,需要选择一些名称的工作簿的对激活事件进行操作,所以感觉还是用类模块+集合容器的方法比较可行。

TA的精华主题

TA的得分主题

发表于 2023-3-1 15:32 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
peter199083 发表于 2023-3-1 15:13
谢谢您的建议。
由于可能后期考虑程序的拓展性,需要选择一些名称的工作簿的对激活事件进行操作,所以感 ...

还是内置的好用,对选择的部分工作表启用事件,只需要在事件中加一层if判断就行。

当然,你就是非要用类写事件,也没问题,要用公共变量,写在sub内,不执行也没意义,执行完释放变量还是没意义

TA的精华主题

TA的得分主题

发表于 2023-3-1 15:44 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
Dim arr(1 To 4) As New Module1
这句代码声明在过程df中就成了局部变量,当过程df运行结束后,这个数组连同其包含的4个对象都会被销毁,自然也无法响应Activate事件了

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2023-3-1 16:34 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 ykcbf1100 于 2023-3-1 16:35 编辑

workbooks是工作簿,worksheets是工作表。
概念不清。

表循环就可以了,哪用类啊。

TA的精华主题

TA的得分主题

发表于 2023-3-1 16:39 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
直接在Workbook_SheetActivate事件过程里写代码里就可以了
  1. Private Sub Workbook_SheetActivate(ByVal Sh As Object)
  2.     Sh.Cells(1, 1).Value = "F4"
  3. End Sub
复制代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-3-27 16:13 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 peter199083 于 2023-3-27 16:24 编辑
micch 发表于 2023-3-1 15:32
还是内置的好用,对选择的部分工作表启用事件,只需要在事件中加一层if判断就行。

当然,你就是非要用 ...

受您建议思路的启发,我做了两个调整并成功满足需求
1. 放弃数组(array),使用集合(collection);
2. 将集合的作用域从过程中删除,并重新定义在ThisWorkbook中(globally scoped)。

在类模块Module1中写入如下代码:
  1. Private WithEvents m_wst As Worksheet

  2. Property Set Worksheet(o_wst As Worksheet)
  3.     Set m_wst = o_wst
  4. End Property

  5. Private Sub m_wst_Activate()
  6.     m_wst.Cells(1, 1).Value = "F4"
  7. End Sub
复制代码

在ThisWorkbook中写入代码:
  1. Dim col As Collection
  2. Private Sub Workbook_Open()
  3.     Call df
  4. End Sub

  5. Sub df()
  6.     Dim clsWst As Module1
  7.     Dim oWst As Worksheet
  8.     Dim i As Integer
  9.     Set col = New Collection
  10.     For i = 1 To ThisWorkbook.Worksheets.Count
  11.         Set oWst = ThisWorkbook.Worksheets(i)
  12.         Set clsWst = New Module1
  13.         Set clsWst.Worksheet = oWst
  14.         col.Add clsWst
  15.     Next
  16. End Sub
复制代码

解决方案的核心是集合容器作用域的重新定义
wbs.gif
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-9-29 16:30 , Processed in 0.061993 second(s), 10 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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