将窗体控件button固定到多个工作表

我有一个工作簿,每个工作表都有一系列button。 我想将button固定到每个工作表的特定位置,以便每次用户打开工作簿时,button都会定位到正确的位置。 问题是所使用的代码只能放在“ThisWorkbook”中,而且我希望能够按表单编码button。 我试图将代码放到工作表区域,但它不工作,我不知道我在这里失踪,让它工作。

编辑 – 工作簿中的每个工作表都是独一无二的,每个button都有不同的macros,每个button位于每个工作表的不同位置。 工作表本身共享button名称(“button1”,“button2”等),所以我认为button需要被“固定”到每个单独的工作表上,以允许位置和使用的这种变化,因为button1在工作表1上与第2页上的button1完全不同。

我的代码如下操作工作簿,而不是已经被确定为我的部分#1的工作表。

VBE截图

Private Sub Workbook_Open() Dim rng As Range Set rng = ActiveSheet.Range("D5") With ActiveSheet.Shapes("Button 1") .Top = rng.Top .Left = rng.Left .Width = rng.Width .Height = rng.RowHeight End With End Sub 

编辑#2使用Mat的build议我试图确定工作表内的每个button,但我不知道如何使用public property get和识别每个button的“button名称”和“范围”的bot,以便我可以find更多每张纸一个button

  Option Explicit Public Property Get ButtonName() As String ButtonName = "Button 1" End Property Public Property Get ButtonAnchor() As Range Set ButtonAnchor = Me.Range("B2") End Property 

迭代工作簿的工作表集合:

 Private Sub Workbook_Open() Dim rng As Range Dim sht As Worksheet For Each sht In Worksheets With sht Set rng = .Range("D5") With .Shapes("Button 1") .Top = rng.Top .Left = rng.Left .Width = rng.Width .Height = rng.RowHeight End With End With Next sht End Sub 

当然这假定每张纸都有一个叫做“button1”的button,

user3598756有正确的答案(正如Mat's Mug指出的那样)。 如果您希望在用户打开工作簿时发生某些情况,它将放入位于ThisWorkbook代码模块中的workbook_open事件处理程序中。 这正是Excel VBA的工作方式。 如果我想让我的车上class,但是不要把汽油放进汽油箱,而是要求把汽油放在轮胎上,那么猜猜会发生什么?

但是,您仍然可以使用Thisworkbook代码模块中的单个工作表。 略微调整user3597856的代码:

 Private Sub Workbook_Open() Dim rng As Range Dim sht As Worksheet For Each sht In Worksheets With sht Select Case .Name Case "Sheet 1" Set rng = .Range("D5") With .Shapes("Button 1") .Top = rng.Top .Left = rng.Left .Width = rng.Width .Height = rng.RowHeight End With Case "Sheet 2" Set rng = .Range("G425") With .Shapes("Button 1") .Top = rng.Top .Left = rng.Left .Width = rng.Width .Height = rng.RowHeight End With Case Else 'What to do when its not a sheet we care about? Nothing. End Select End With Next sht End Sub 

这样做的好处是所有的代码都设置在一个不错的位置,所以当你添加或删除表单时,你只需要去一个地方更新代码。 另一个好处是这个代码只能执行一次:工作簿打开时。 它的缺点是不能满足你的要求,即代码不能循环遍历每个表单。

另一个(不太有用)的选项,不涉及循环表单设置button位置是使用Worksheet_Activate事件。 它驻留在每个单独的工作表代码模块中,因此每次更改代码时都可以有无数个子程序。 每次用户点击工作表标签时,都会触发此事件。 调整你的代码有点:

 Private Sub Worksheet_Activate() Dim rng As Range Set rng = ActiveSheet.Range("D5") With ActiveSheet.Shapes("Button 1") .Top = rng.Top .Left = rng.Left .Width = rng.Width .Height = rng.RowHeight End With End Sub 

这个想法太可怕了,它有两个好处。 首先,如果用户在表单上移动button,则每当他们打开并切换回来时,都会自行重置。 另一个好处是它符合您的要求,即代码必须放在单个工作表代码模块中,而不是在工作表中循环。

在每个工作表上添加一个Property Get成员,其中包含一个这样的button; 例如这里将是一个工作表,其中的button在A1:

 Option Explicit Public Property Get ButtonAnchor() As Range Set ButtonAnchor = Me.Range("A1") End Property 

而这将是另一个button在单元格D5中的位置:

 Option Explicit Public Property Get ButtonAnchor() As Range Set ButtonAnchor = Me.Range("D5") End Property 

继续为每个有button的工作表添加该成员,每次指定Range对象代表您想要button的位置。


然后,在ThisWorkbook文档类模块中,您将迭代所有工作表并延迟访问ButtonAnchor成员; 因为这会在没有该属性的工作表中抛出一个错误,所以你会用On Error语句包装它:

 Private Sub Workbook_Open() Dim sheet As Object Dim anchor As Range For Each sheet In ThisWorkbook.Worksheets On Error Resume Next Set anchor = sheet.ButtonAnchor Err.Clear On Error GoTo 0 If Not anchor Is Nothing Then With sheet.Shapes("Button 1") .Top = anchor.Top .Left = anchor.Left .Width = anchor.Width .Height = anchor.RowHeight End With End If Next End Sub 

对于没有ButtonAnchor属性的表单, anchor范围将为Nothing ,因此我们通过testinganchor Is Nothing跳过这些表单。 另一个假设是,该button在每个包含该button的工作表上被命名为Button 1

您可以通过添加其他属性来消除该假设:

 Public Property Get ButtonName() As String ButtonName = "Button 1" End Property 

然后另一张纸可以有:

 Public Property Get ButtonName() As String ButtonName = "Button 42" End Property 

然后,而不是去With sheet.Shapes("Button 1")你会去(在ThisWorkbook.Workbook_Open For Each循环内):

  If Not anchor Is Nothing Then With sheet.Shapes(sheet.ButtonName) .Top = anchor.Top .Left = anchor.Left .Width = anchor.Width .Height = anchor.RowHeight End With End If