最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

excel - Universal change of all existing elements in a VBA nested array - Stack Overflow

programmeradmin0浏览0评论

I have a composite data structure which I have defined using two nested classes. I am presenting a simplified version of the structure here:-

    Routine  Variable  Type
    -------  --------  ----
    Sub_1    l         Long
             y         Class_A
             z         Class_B     

    Class_A  a()       Class_B  
             i         Integer

    Class_B  s         String

So my my first question: Is the above allowable?

Here is the code:

    '1. sub
    Sub NestedArray()

      Const ciNumberToString As Integer = 64

      Dim l As Long
      Dim y As Class_A
      Dim z As Class_B

      Set y = New Class_A
      Set z = New Class_B
  
      For l = 0 To 10
        y.pI = l
        z.pS = Chr(l + ciNumberToString)
        y.pA = z
      Next l

    End Sub

    '2. Class_A
    Option Explicit

      Private a() As Class_B
      Private i As Integer

      Public Property Get pI() As Integer
        pI = i
      End Property

      Public Property Let pI(oI As Integer)
        If Not oI < i Then
          ReDim Preserve a(oI)
        End If
        i = oI
      End Property

      Public Property Get pA() As Class_B
        Set pA = a(i)
      End Property

      Public Property Let pA(oA As Class_B)
        Set a(i) = oA
      End Property


    '3 Class_B
    Option Explicit

      Private i As Integer

      Public Property Get pI() As Integer
        pI = i
      End Property

      Public Property Let pI(oI As Integer)
        i = oI
      End Property`

I put a stop on the 'End Sub' line. This is the expected result (as it appears in the Watches window):-

    Expression    Value    Type
    ----------    -----    ----
    y                      Class_A
      a                    Class_B(0 to 10)
        a(0)               Class_B
          s       "@"      String
          pS      "@"      String
        a(1)               Class_B
          s       "A"      String
          pS      "A"      String
        a(2)               Class_B
          s       "B"      String
          pS      "B"      String
                  
                  .
                  .
                  .

        a(10)              Class_B
          s       "J"      String
          pS      "J"      String
      i           10       Integer
        pA                 Class_B
          s       "J"      String
          pS      "J"      String
        pI        10       Integer

Here is my actual result:-

    Expression    Value    Type
    ----------    -----    ----
    y                      Class_A
      a                    Class_B(0 to 10)
      a(0)                 Class_B
        s         "J"      String
        pS        "J"      String
      a(1)                 Class_B
        s         "J"      String
        pS        "J"      String
      a(2)                 Class_B
        s         "J"      String
        pS        "J"      String

                  .
                  .
                  .

      a(10)                 Class_B
        s         "J"       String
        pS        "J"       String
      i           10        Integer
    pA                      Class_B
      s           "J"       String
      pS          "J"       String
    pI            10        Integer

y.a(0) is set correctly initially, i.e. it has a value of 0. However on the next iteration it is reset to 1. this is done before y.a(1) is set by the code here:-

    For l = 0 To 10
      y.pI = l
      z.pS = Chr(l + ciNumberToString)
      y.pA = z
    Next l

This is the Class_B code which is executed

    Public Property Let pS(oS As Integer)
      s = oS
    End Property

Because z.pS has changed, y.a is altered from:-

    Expression     Value    Type
    ----------     -----    ----
    y                       Class_A
    a                       Class_B(0 to 10)
      a(0)                  Class_B
        pS         "@"      String
        s          "@"      String

to:-

    y                       Class_A
      a                     Class_B(0 to 10)
        a(0)                Class_B
          pS       "A"      String
          s        "A"      String

... and every iteration of an existing element in the array is set to z.pS

I have a composite data structure which I have defined using two nested classes. I am presenting a simplified version of the structure here:-

    Routine  Variable  Type
    -------  --------  ----
    Sub_1    l         Long
             y         Class_A
             z         Class_B     

    Class_A  a()       Class_B  
             i         Integer

    Class_B  s         String

So my my first question: Is the above allowable?

Here is the code:

    '1. sub
    Sub NestedArray()

      Const ciNumberToString As Integer = 64

      Dim l As Long
      Dim y As Class_A
      Dim z As Class_B

      Set y = New Class_A
      Set z = New Class_B
  
      For l = 0 To 10
        y.pI = l
        z.pS = Chr(l + ciNumberToString)
        y.pA = z
      Next l

    End Sub

    '2. Class_A
    Option Explicit

      Private a() As Class_B
      Private i As Integer

      Public Property Get pI() As Integer
        pI = i
      End Property

      Public Property Let pI(oI As Integer)
        If Not oI < i Then
          ReDim Preserve a(oI)
        End If
        i = oI
      End Property

      Public Property Get pA() As Class_B
        Set pA = a(i)
      End Property

      Public Property Let pA(oA As Class_B)
        Set a(i) = oA
      End Property


    '3 Class_B
    Option Explicit

      Private i As Integer

      Public Property Get pI() As Integer
        pI = i
      End Property

      Public Property Let pI(oI As Integer)
        i = oI
      End Property`

I put a stop on the 'End Sub' line. This is the expected result (as it appears in the Watches window):-

    Expression    Value    Type
    ----------    -----    ----
    y                      Class_A
      a                    Class_B(0 to 10)
        a(0)               Class_B
          s       "@"      String
          pS      "@"      String
        a(1)               Class_B
          s       "A"      String
          pS      "A"      String
        a(2)               Class_B
          s       "B"      String
          pS      "B"      String
                  
                  .
                  .
                  .

        a(10)              Class_B
          s       "J"      String
          pS      "J"      String
      i           10       Integer
        pA                 Class_B
          s       "J"      String
          pS      "J"      String
        pI        10       Integer

Here is my actual result:-

    Expression    Value    Type
    ----------    -----    ----
    y                      Class_A
      a                    Class_B(0 to 10)
      a(0)                 Class_B
        s         "J"      String
        pS        "J"      String
      a(1)                 Class_B
        s         "J"      String
        pS        "J"      String
      a(2)                 Class_B
        s         "J"      String
        pS        "J"      String

                  .
                  .
                  .

      a(10)                 Class_B
        s         "J"       String
        pS        "J"       String
      i           10        Integer
    pA                      Class_B
      s           "J"       String
      pS          "J"       String
    pI            10        Integer

y.a(0) is set correctly initially, i.e. it has a value of 0. However on the next iteration it is reset to 1. this is done before y.a(1) is set by the code here:-

    For l = 0 To 10
      y.pI = l
      z.pS = Chr(l + ciNumberToString)
      y.pA = z
    Next l

This is the Class_B code which is executed

    Public Property Let pS(oS As Integer)
      s = oS
    End Property

Because z.pS has changed, y.a is altered from:-

    Expression     Value    Type
    ----------     -----    ----
    y                       Class_A
    a                       Class_B(0 to 10)
      a(0)                  Class_B
        pS         "@"      String
        s          "@"      String

to:-

    y                       Class_A
      a                     Class_B(0 to 10)
        a(0)                Class_B
          pS       "A"      String
          s        "A"      String

... and every iteration of an existing element in the array is set to z.pS

Share Improve this question asked yesterday Steve RobertsSteve Roberts 114 bronze badges 0
Add a comment  | 

1 Answer 1

Reset to default 1

With small modifications, it works:

Sub NestedArray()
  Const ciNumberToString As Integer = 64
  Dim l As Long
  Dim y As Class_A
  Dim z As Class_B
  Set y = New Class_A
  Set z = New Class_B
  For l = 0 To 10
    Debug.Print "l", l
    y.pI = l
    z.pS = Chr(l + ciNumberToString)
    y.pA = z
    Debug.Print "------------- -------------"
  Next l
End Sub

Class_A

Private a() As Class_B
Private i As Integer

Public Property Get pI() As Integer
  pI = i
End Property

Public Property Let pI(oI As Integer)
  If i <= oI Then
    ReDim Preserve a(oI)
    i = oI
  End If
End Property

Public Property Get pA() As Class_B
  Set pA = a(i)
End Property

Public Property Let pA(oA As Class_B)
  Set a(i) = oA
End Property

Class_B

Private i As Integer

Public Property Get pS() As String
End Property

Public Property Let pS(oA As String)
  i = Asc(oA)
  Debug.Print "pS", oA
End Property

-->

l              0 
pS            @
------------- -------------
l              1 
pS            A
------------- -------------
l              2 
pS            B
------------- -------------
l              3 
pS            C
------------- -------------
l              4 
pS            D
------------- -------------
l              5 
pS            E
------------- -------------
l              6 
pS            F
------------- -------------
l              7 
pS            G
------------- -------------
l              8 
pS            H
------------- -------------
l              9 
pS            I
------------- -------------
l              10 
pS            J
------------- -------------

Surely, 'y.a' contains 11 references to a single Class_B object. And, at the end, any 'a(i).i' is the same - 74 (J). To recover it, modify:

Sub NestedArray()
  Const ciNumberToString As Integer = 64
  Dim l As Long
  Dim y As Class_A
  Dim z As Class_B
  Set y = New Class_A
  For l = 0 To 10
    Debug.Print "l", l
    y.pI = l
    Set z = New Class_B
    z.pS = Chr(l + ciNumberToString)
    y.pA = z
    Debug.Print "------------- -------------"
  Next l
End Sub
发布评论

评论列表(0)

  1. 暂无评论