Несоответствие типа Excel VBA: ожидается массив или пользовательский тип

Я знаю, что многие люди задавали вопросы об этой ошибке, но, судя по ответам на них, я должен все делать правильно.

Я создал класс Variable для хранения нескольких фрагментов информации о переменной. У меня есть еще один класс с именем Equipment, в котором хранится массив этих переменных. Вот соответствующий код в Equipment:

Public name As String
Private variables() As Variable

Public Sub setVariables(vars() As Variable)
    variables = vars
End Sub

У меня также есть модуль, который создает экземпляры Equipment. Вот весь код для этого:

Public Sub fillEquipment()

    'figure out how many units of equipment there are
    numUnits = 0
    atRow = 1
    Do Until Range("A" & atRow).value = ""
        numUnits = numUnits + 1
        atRow = atRow + 1
    Loop

    'create array for equipment units
    Dim units() As Equipment
    ReDim units(0 To numUnits)

    'figure out how many variables there are
    numVars = 0
    For Each col In Range("A1:ZZ1")
        If col.value <> "" Then
            numVars = numVars + 1
        End If
    Next col

    'create an array of equipment one row at a time
    atRow = 1
    Do Until Range("A" & atRow).value = ""
        'create and name equipment
        units(atRow) = New Equipment
        units(atRow).name = Range("A" & atRow).value

        'create an array of vars
        Dim variables() As Variable
        ReDim variables(0 To numVars)
        For atCol = 1 To numVars
            variables(atCol) = New Variable
            variables(atCol).name = Cells(1, atCol).value
            variables(atCol).value = Cells(atRow, atCol).value
        Next atCol

        'add variables to equipment
        units(atRow).setVariables (variables)
        atRow = atRow + 1

    Loop

    'print for testing
    For atRow = 1 To numUnits
        Cells(atRow, 1).value = Equipment(atRow).name
        For atCol = 1 To numCols
            Cells(atRow, atCol + 1).value = Equipment(atRow).getVariables(atCol)
        Next atCol
    Next atRow

End Sub

Вот моя проблема: когда я запускаю программу, она выдает ошибку компилятора «Несоответствие типов: ожидается массив или пользовательский тип» в слове variables в units(atRow).setVariables (variables).

Я не понимаю, что я делаю неправильно. variables определяется как массив типа объекта Variable, который является именно тем, что запрашивает setVariables.

Благодарю вас! Я очень ценю помощь!!


person Ari Levisohn    schedule 07.08.2017    source источник
comment
Это Private variables() As Variable должно быть Private variables() As Variant - и такое же изменение необходимо сделать во всем коде. Не существует такого понятия, как тип Variable, если только вы сами его не определите.   -  person braX    schedule 07.08.2017
comment
Я создал класс под названием Variable. Разве этого недостаточно, чтобы определить его как тип?   -  person Ari Levisohn    schedule 07.08.2017
comment
Ах - и вы просто не показали, что. Я вижу, где вы упоминаете об этом сейчас, хотя. Никто здесь не сможет протестировать какой-либо ваш код без его определения.   -  person braX    schedule 07.08.2017
comment
Прямо сейчас это просто модуль кода с этими объявлениями: Public name As String Public value As Long   -  person Ari Levisohn    schedule 07.08.2017
comment
Что ты пытаешься сделать? С массивом вы не можете просто сделать (AFAIK) Variables. Вам нужно будет перебрать массив переменных и назначать единицы по одной. ...если я правильно понимаю. ...Что вообще такое Units? Вы также должны добавить Option Explicit в самый верх вашего кода, чтобы убедиться, что вы объявили все переменные.   -  person BruceWayne    schedule 07.08.2017
comment
1) Нужно ли объявлять все переменные? Разве это не необходимо? 2) Причина, по которой я хочу передать весь массив сразу, заключается в том, что я заранее не знаю, насколько большим он будет.   -  person Ari Levisohn    schedule 07.08.2017
comment
Также units представляет собой массив Equipment. Я добавил замедление для него выше.   -  person Ari Levisohn    schedule 07.08.2017
comment
Где вы устанавливаете NumVars? Если NumVars равно 0, ReDim ничего не сделает, и цикл for next ничего не сделает.   -  person Rob Anthony    schedule 07.08.2017
comment
Удалите скобки --- Вместо units(atRow).setVariables (variables), units(atRow).setVariables variables. Если это не сработает, попробуйте Public Sub setVariables(vars As Variant)   -  person cxw    schedule 07.08.2017
comment
Я обновляю код выше, чтобы включить все.   -  person Ari Levisohn    schedule 07.08.2017
comment
Лишние скобки все портят. DoSomething (foo) не то же самое, что DoSomething foo. Отбросьте круглые скобки, они заставляют параметр оцениваться как значение и передавать ByVal, что недопустимо для массива.   -  person Mathieu Guindon    schedule 07.08.2017


Ответы (1)


У вас есть лишние скобки. Это компилируется без ошибки:

Sub make(numUnits As Long, numVars As Long)
    Dim units() As Equipment
    ReDim units(0 To numUnits)
    Dim atRow As Long, atCol As Long    ' <-- new Dim, because of Option Explicit

    'create an array of equipment one row at a time
    atRow = 1
    Do Until Range("A" & atRow).value = ""
        'create and name equipment
        units(atRow) = New Equipment
        units(atRow).name = CStr(Range("A" & CStr(atRow)).value)   ' <-- use CStr() anytime you need a string

        'create an array of vars
        Dim variables() As Variable
        ReDim variables(0 To numVars)
        For atCol = 1 To numVars
            variables(atCol) = New Variable
            variables(atCol).name = Cells(1, atCol).value
            variables(atCol).value = Cells(atRow, atCol).value
        Next atCol

        'add variables to equipment
        units(atRow).setVariables variables
        atRow = atRow + 1       ' ^^^^^^^^^ not (variables) - no parens

    Loop
End Sub

Ключевой проблемой были скобки. Однако это также добавляет операторы Dim для ваших переменных. Как сказал @BruceWayne, вы должны всегда использовать Option Explicit. Да, это в каждом модуле и каждом модуле класса. В противном случае можно отказаться от помощи в отладке от компилятора.

На самом деле я также использую Option Base 0 в начале каждого модуля, в основном, чтобы напомнить себе, в какой системе я работаю :).

Изменить Я добавил несколько CStr, которые защитят вас от странных угловых случаев. При дальнейшей разработке этого кода я бы рекомендовал использовать явные переменные рабочего листа, а не полагаться на неявные ActiveSheet. См., например, этот ответ.

person cxw    schedule 07.08.2017
comment
Большое спасибо! - person Ari Levisohn; 08.08.2017