Excel VBA-.xlam(加载项)将下标抛出超出范围错误9,但一切都按xlsm运行?

Excel VBA-.xlam(加载项)将下标抛出超出范围错误9,但一切都按xlsm运行?,vba,excel,Vba,Excel,基本上就是罐头上的标签上写的 我有多个用户表单、多个模块、类模块等。我有工作表,其中存储数据并由代码使用。我已将选项卡和按钮添加到功能区 我以.xlsm文件的形式运行并测试了从“过来”到“生病”的所有内容。每种形式的每一个字段、每一个按钮、每一行代码都能完美运行 我将该文件保存为.xlam,在第一个模块中,它挂在这行代码上: Worksheets("All Welders Data").Activate 正如我所说,我得到的下标超出范围错误9 这是我第一次尝试获取VBA项目并将其保存为外接程序

基本上就是罐头上的标签上写的

我有多个用户表单、多个模块、类模块等。我有工作表,其中存储数据并由代码使用。我已将选项卡和按钮添加到功能区

我以.xlsm文件的形式运行并测试了从“过来”到“生病”的所有内容。每种形式的每一个字段、每一个按钮、每一行代码都能完美运行

我将该文件保存为.xlam,在第一个模块中,它挂在这行代码上:

Worksheets("All Welders Data").Activate
正如我所说,我得到的下标超出范围错误9

这是我第一次尝试获取VBA项目并将其保存为外接程序。我一定错过了什么。我读过(John Walkenbach“Excell 2013…”,.xlam文件仍然是一个包含工作表的工作簿,所有内容都应该像.xlsm一样工作

是不是对工作表的引用有误?它是激活的吗?我是否需要在
某物前加前缀。工作表(“blah”)。激活

我累了,完全被难倒了。我希望有人能对我有所帮助。提前谢谢

更新

我想收集每个人的反应和评论。我相信“这本手册”可能会解决这个问题。我现在接近能够测试它了,我将用我的结果再次更新我的问题

然而,由于这篇文章中有很多关于我使用activate的讨论,我想提出一个与所有这些相关的后续问题

这是我的一个模块的示例

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
Private子用户表单_Initialize()
最后一排一样长
将名称单元格设置为范围
调光盒作为控件
'设置窗口大小和位置
应用
.WindowsState=xl最大化
Me.Top=.Top*0.5
Me.Left=.Left*1.0015
缩放=整数((.Width*0.85)/(Width*0.85)*40)
宽度=.Width*0.995
高度=.Height*0.992
以
'关闭除单选按钮和标签以外的所有功能
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
'激活工作表
应用程序。此工作簿。工作表(“所有焊工数据”)。激活
应用程序。此工作簿。工作表(“所有焊工数据”)。范围(“A1”)。激活
'按焊工的姓氏对活动表中的数据进行排序。
使用Application.ThisWorkbook.ActiveSheet.Sort
.SortFields.Clear
.SortFields.Add键:=范围(“B3”),顺序:=xl
.SetRange ActiveCell.CurrentRegion.Offset(1)
.Header=xlYes
.MatchCase=False
.方向=xlTopToBottom
.SortMethod=xl拼音
.申请
以
Application.ScreenUpdating=True
'从激活的工作表中填充combox(在
'第一列,焊工ID号在第二列。
使用Application.ThisWorkbook.ActiveSheet
lastRow=.Cells(.Rows.Count,“A”).End(xlUp).Row
对于.Range(“E3:E”和lastRow)中的每个名称单元格
如果nameCell.Value为“”,则
和我一起。选择EldernamecomboBox
.ColumnCount=2
.AddItem nameCell.Value
.List(.ListCount-1,1)=nameCell.Offset(,-1).Value
'组合框现在显示列“E”中的值和
在coulmn“D”中——按顺序,如在“Name”中——“ID Number”。
'(工作表中列的相反顺序。)
以
如果结束
下一个
以
端接头
你会看到我在一半的时候激活了工作表。然后在下一行我激活了一个范围。我需要激活这个范围,因为我在下面的With块中排序。排序完成了,因为组合框需要按字母顺序排列

如果要激活
范围(“A1”)
我必须确保工作表已激活。如果未激活,则
范围(“A1”).activate
将失败,并出现1004错误,因为除非单元格所在的工作表是活动工作表,否则无法激活单元格

因此,如果我打算坚决不使用activate,那么重构代码的建议是什么,这样我就可以使用excel内置的排序了。我不想做任何循环例程来排序

最后一句话

我只想感谢罗宾·麦肯齐的回答。她走上了正确的道路,给出了一个很好的答案,解决了这个问题


此外,我只想说,我仍然认为有时使用activate并不是一种罪恶!

进一步了解MSDN对该属性的评论:

使用此属性可引用包含宏代码的工作簿。此工作簿是从外接程序本身内部引用外接程序工作簿的唯一方法。ActiveWorkbook属性不返回外接程序工作簿;它返回调用外接程序的工作簿。工作簿属性可能会失败,因为工作簿没有创建外接程序时,ame可能已更改

(我的重点)

您应该这样做(并避免
激活
):


您无法激活隐藏工作簿中的工作表(默认情况下xlam是隐藏的),但-除非确实需要,否则应避免激活工作表-工作表不必处于活动状态才能使用它。请参阅:。默认情况下
工作表(“所有数据”).Activate
将查看ActiveWorkbook,它可能会解释您看到的错误-它会
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
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