锡上的标签基本上是什么。
我有多个用户表单,多个模块,类模块等。我有工作表,其中数据由代码存储和使用。我在功能区上添加了一个标签和按钮。
我运行并测试了从“Come Here”到“Sick'Em”的所有内容,作为.xlsm文件。每种形式,每个按钮,每行代码的每个字段都运行得很好。
我将文件保存为.xlam,并且在第一个模块中,这个代码就挂起了这个代码:
Worksheets("All Welders Data").Activate
正如我所说,我得到下标超出范围错误9。
这是我第一次尝试接受VBA项目并将其另存为加载项。我肯定错过了什么。我读过(John Walkenbach“Excell 2013 ...”).xlam文件仍然是带有工作表的工作簿,一切都应该像.xlsm一样工作。
是否错误表格是对工作表的引用?它是激活吗?我需要加前缀Something.Worksheets("blah").Activate
吗?
我很累,而且我很难过。我希望有人对我有一些意见。提前谢谢!
更新
我想让所有人回答他们的回复和评论。我相信“ThisWorkbook”可能会解决这个问题。我现在很接近能够测试它,我将用我的结果再次更新我的问题。
但是,由于关于我使用激活的这篇文章有很多讨论,我想提出一个与所有这些相关的后续问题。
以下是我的某个模块的示例。
Private Sub UserForm_Initialize()
Dim lastRow As Long
Dim nameCell As Range
Dim box As control
'Set Window size and position
With Application
.WindowState = xlMaximized
Me.Top = .Top * 0.5
Me.Left = .Left * 1.0015
Zoom = Int((.Width * 0.85) / (Width * 0.85) * 40)
Width = .Width * 0.995
Height = .Height * 0.992
End With
'Turn off everything except the radio Buttons and thier labels
Me.submitButton.Visible = False
Me.submitButton.Enabled = False
Me.chooseWelderLabel.Visible = False
Me.chooseWelderNameComboBox.Visible = False
Me.chooseWelderNameComboBox.Enabled = False
Me.welderNameLabel.Visible = False
Me.welderNameText.Visible = False
Me.welderNameText.Enabled = False
Me.checkNameButton.Visible = False
Me.checkNameButton.Enabled = False
Application.ScreenUpdating = False
'Activate the worksheet
Application.ThisWorkbook.Worksheets("All Welders Data").Activate
Application.ThisWorkbook.Worksheets("All Welders Data").Range("A1").Activate
'sort the data in the active sheet by the welder's last name.
With Application.ThisWorkbook.ActiveSheet.Sort
.SortFields.Clear
.SortFields.Add Key:=Range("B3"), Order:=xlAscending
.SetRange ActiveCell.CurrentRegion.Offset(1)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Application.ScreenUpdating = True
'populate the combox from the active sheet (welder name in the
'first column, welder ID number in the second column.
With Application.ThisWorkbook.ActiveSheet
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For Each nameCell In .Range("E3:E" & lastRow)
If nameCell.Value <> "" Then
With Me.chooseWelderNameComboBox
.ColumnCount = 2
.AddItem nameCell.Value
.List(.ListCount - 1, 1) = nameCell.Offset(, -1).Value
'ComboBox now shows the values in column "E" and the values
'in coulmn "D" - in that order, as in "Name" - "ID Number".
'(the reverse order of the columns in the worksheet.)
End With
End If
Next
End With
End Sub
你会看到大约一半我激活了工作表。然后在下一行我激活一个范围。我需要激活范围,因为我随后在随后的With块中进行排序。排序已完成,因为ComboBox需要按字母顺序排列。
如果我要激活Range ("A1")
,我必须确保工作表已激活。如果没有,那么Range("A1").Activate
将失败并出现1004错误,因为除非单元所在的工作表是活动工作表,否则无法激活单元格。
因此,如果我将成为永远不会使用激活的核心,那么重构此代码的建议是什么,以便我可以使用excel的内置排序。我对做任何类型的循环例程不感兴趣。
最后的词
我只想感谢Robin MacKenzie的回答。她走在正确的轨道上并给出了解决问题的良好答案。
另外,我只是想说,我仍然认为有时使用激活并不是一种罪恶!
答案 0 :(得分:1)
此MSDN上关于ThisWorkbook
属性的评论:
使用此属性引用包含宏代码的工作簿。 ThisWorkbook是从加载项本身引用加载项工作簿的唯一方法。 ActiveWorkbook属性不会返回加载项工作簿;它返回调用加载项的工作簿.Workbooks属性可能会失败,因为在创建加载项时工作簿名称可能已更改。
(我的重点)
您应该这样做(并避免Activate
):
Dim wsData As Worksheet
Set wsData = ThisWorkbook.Worksheets("All Welders Data") '<-- use ThisWorkbook
' no need to Activate - just use the data
Dim rngStuff As Range
Set rngStuff = wsData.Range("A1:G5") '<-- change hardcoded range to whatever you need
' now work with the range
关于更新后的问题,我建议使用类似于下面的代码来填充ComboBox
上的UserForm
而不使用Activate
。它除了处理加载ComboBox
的部分之外进行了测试,主要是你的工作代码。
Option Explicit
Sub UserForm_Initialize()
Dim wsData As Worksheet
Dim rngToSortFirstCell As Range
Dim lngLastRow As Long
Dim rngNameCell As Range
' set a reference to the sheet
Set wsData = ThisWorkbook.Worksheets("All Welders Data")
' clear existing sort fields
wsData.Sort.SortFields.Clear
' set a reference to the header of range to sort
Set rngToSortFirstCell = wsData.Range("B3")
' sort it by CurrentRegion of first cell
rngToSortFirstCell.Sort Key1:=Range("B3").CurrentRegion, _
Order1:=xlAscending, _
Header:=xlYes, _
MatchCase:=False, _
SortMethod:=xlPinYin
' put welder names to combo box
With wsData
lngLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For Each rngNameCell In .Range("E3:E" & lngLastRow)
If rngNameCell.Value <> "" Then
With Me.chooseWelderNameComboBox
.ColumnCount = 2
.AddItem rngNameCell.Value
.List(.ListCount - 1, 1) = rngNameCell.Offset(, -1).Value
'ComboBox now shows the values in column "E" and the values
'in coulmn "D" - in that order, as in "Name" - "ID Number".
'(the reverse order of the columns in the worksheet.)
End With
End If
Next
End With
End Sub