我有一个包含多个工作表的工作簿,每个工作表都有一系列按钮。我想将按钮固定到每个工作表的特定位置,以便每次用户打开工作簿时按钮都会找到正确的位置。问题是所使用的代码仅在置于“ThisWorkbook”中时才有效。我希望能够逐页编码按钮。我已经尝试将代码放入工作表区域,但它不起作用,我无法弄清楚我在这里缺少什么来使其正常工作。
编辑 - 工作簿中的每个工作表都是独一无二的,每个按钮分配不同的宏,每个按钮位于每个工作表的不同位置。工作表本身共享按钮名称("按钮1","按钮2"等),所以我认为按钮需要固定'对于每个单独的工作表,允许这种位置和使用的变化,因为表1上的按钮1与表2上的按钮1完全不同。
下面的代码操作工作簿,而不是我已经被识别为搞砸#1的工作表。
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的建议我试图识别表格中的每个按钮,但我不知道如何使用public property get
并识别机器人"按钮名称"和#34;范围"每个按钮,以便我可以在每张纸上找到多个按钮
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
答案 0 :(得分:2)
迭代工作簿的工作表集合:
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
当然这假设每张纸都有一个名为“按钮1”的按钮
答案 1 :(得分:2)
user3598756有正确答案(正如Mat's Mug指出的那样)。如果您希望在用户打开工作簿时发生某些事情,它将进入workbook_open事件处理程序,该处理程序位于ThisWorkbook代码模块中。这就是Excel VBA的工作方式。如果我想让我的车开始工作,但拒绝将气体放入油箱并要求将气体放入轮胎中,那么猜猜会发生什么?
但是,您仍然可以使用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
这样做的好处是,设置所有按钮位置的所有代码都位于一个不错的位置,因此当您添加或删除工作表时,您只需要到一个位置来更新代码。另一个好处是此代码只执行一次:工作簿打开时。它确实有一个缺点,就是不能满足你的要求,即代码无法循环遍历每个工作表。
另一个(不太有用)选项不涉及在工作表中循环以设置按钮位置是使用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
这个想法太可怕了,它确实有两个好处。首先,如果用户在工作表上移动按钮,则每次他们离开并切换回来时它都会自动重置。另一个好处是它符合您的要求,即代码必须放在单个工作表代码模块中,而不是在工作表中循环。
答案 2 :(得分:2)
在每个工作表上添加一个Property Get
成员,其中包含一个此类按钮;例如,这里将是一个工作表,其按钮位于A1:
Option Explicit
Public Property Get ButtonAnchor() As Range
Set ButtonAnchor = Me.Range("A1")
End Property
这将是按钮在单元格D5中的另一个:
Option Explicit
Public Property Get ButtonAnchor() As Range
Set ButtonAnchor = Me.Range("D5")
End Property
继续为每个有按钮的工作表添加该成员,每次指定Range
对象代表您希望按钮所在的位置。
然后,在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
对于没有anchor
属性的工作表,Nothing
范围为ButtonAnchor
,因此我们通过测试anchor Is Nothing
来跳过这些工作表。另一个假设是,按钮在每个具有该按钮的工作表上都被命名为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")
而不是For Each
中的ThisWorkbook.Workbook_Open
循环内部:
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