Массив на ThisWorksheet не может использоваться на Sheet1 - PullRequest
0 голосов
/ 07 сентября 2018

У меня есть расписание Excel, которое я настраиваю. Я хочу заполнить код активности в одном столбце, когда я выбираю (из раскрывающегося списка) тип действия в другом столбце.

Я использую vba, чтобы присвоить таблицу кодов и типов массиву, и я сделал это на ThisWorkbook. На странице расписания (Sheet1) я создал код, который на самом деле соответствует типу, и ввел значение в столбец кода (сначала я проверил текущую дату в качестве подтверждения концепции). Но когда я пошел, чтобы соответствовать значениям массива (чтобы я мог назначить код), я получаю несоответствие типов, потому что массив не существует на Sheet1 (но на ThisWorksheet).

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


ThisWorkbook:


Option Explicit
Dim KeyArrTrans As Variant

Sub Workbook_Open()

    Dim LastRow As Integer
    Dim KeyArr As Variant

    With Sheets("Key")
        LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
    End With

    'Debug.Print LastRow

    KeyArr = Sheets("Key").Range("A3:B" & LastRow).Value

    'WriteArrayToImmediateWindow KeyArr
    KeyArrTrans = KeyArr

    'Debug.Print KeyArr(1, 1)

End Sub

Sub WriteArrayToImmediateWindow(arrSubA As Variant)

    Dim rowString As String
    Dim iSubA As Long
    Dim jSubA As Long

    rowString = ""

    Debug.Print
    Debug.Print
    Debug.Print "The array is: "

    For iSubA = 1 To UBound(arrSubA, 1)
        rowString = arrSubA(iSubA, 1)
        For jSubA = 2 To UBound(arrSubA, 2)
            rowString = rowString & "," & arrSubA(iSubA, jSubA)
        Next jSubA
        Debug.Print rowString
    Next iSubA

End Sub

Лист1:


Sub Worksheet_Change(ByVal Target As Range)

    Dim tRowX As Integer
    Dim tColX As Integer
    Dim WorkPerfCol As Integer
    Dim ActivCol As Integer
    Dim WorkValue As String
    Dim curDate As Date
    Dim tArr As Integer
    Dim i As Long
    Dim KeyUBound As Integer

    WorkPerfCol = 3
    ActivCol = 2
    Debug.Print UBound(KeyArrTrans, 1)
    'KeyUBound = UBound(KeyArrTrans, 1)

    If Target.Count = 1 Then
        If Target.Column = WorkPerfCol And Target.Row >= 29 And Target.Row <= 41 Then

            tColX = Target.Column
            tRowX = Target.Row
            WorkValue = Cells(tRowX, tColX).Value

            For i = 1 To KeyUBound
                If KeyArrTrans(i, 2) = WorkValue Then
                    Debug.Print KeyArrTrans(i, 2), KeyArrTrans(i, 1)
                    'ActiveSheet.Cells(tRowX,ActivCol.Value = KeyArrTrans(i,1))
                End If
            Next

            Debug.Print WorkValue, tColX, tRowX
            curDate = Date
            'ActiveSheet.Cells(tRowX, ActivCol).Value = curDate

        End If
    End If


End Sub

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Ключевое слово Dim объявляет локальную переменную . При использовании на уровне модуля он объявляет переменную private с областью действия модуля, т. Е. Точно так же, как если бы она была объявлена ​​с ключевым словом Private. По этой причине предпочитайте использовать Dim для локальных и Private для переменных модуля.

ThisWorkbook - это особый вид модуля - это модуль документа , который является классом , который наследует членов от базового класса - в этом кейс Excel.Workbook класс. ThisWorkbook также является глобальным идентификатором, который ссылается на экземпляр класса ThisWorkbook, который доступен глобально в вашем проекте VBA.

Будучи модулем класса , любые члены Public могут быть доступны извне этого модуля, учитывая экземпляр класса. Поскольку существует глобальная переменная объекта, названная в честь этого класса, ее члены Public могут быть доступны с помощью ThisWorkbook.MemberName.

Таким образом, вы можете объявить KeyArrTrans с помощью ключевого слова Public, фактически сделав его глобальным (т. Е. Фактически объявив его общедоступным в стандартном модуле и получив доступ к нему с именем модуля).

Проблема, которую это создает, заключается в том, что теперь любому коду в любом месте проекта разрешено принимать эту переменную и указывать ее где-то еще .

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

Таким образом, вместо этого вы можете инкапсулировать указатель массива и выставлять его как свойство только для получения , сохраняя объявление закрытым (Dim / Private), и добавление члена Public Property Get к ThisWorkbook:

Public Property Get AllTheKeys() As Variant
    AllTheKeys = KeyArrTrans
End Property

Таким образом (т.е. без предоставления мутатора Public Property Let) другой код может читать массив и записывать его элементы, но они не могут назначаться самому массиву - и эта защита обеспечивается компилятором!

Теперь вы можете получить доступ к массиву через свойство AllTheKeys, доступное для ThisWorkbook:

Debug.Print UBound(ThisWorkbook.AllTheKeys, 1)
0 голосов
/ 07 сентября 2018

ThisWorkbook - это модуль класса. Он представляет собой объект. Вы не можете обратиться к полю, объявленному в этом объекте, без указания имени объекта.

Так что либо объявите KeyArrTrans с ключевым словом Public (вместо Dim) и адресом KeyArrTrans как ThisWorkbook.KeyArrTrans, либо поместите массив в простой модуль. Открытые переменные, объявленные в простом модуле, доступны глобально без указания имени модуля.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...