View Full Version : [SOLVED:] How to create a public array in class module?
alex009988
07-22-2019, 06:30 AM
So that I've tried to use that code in class module
Public sf()
Dim strf(), strf1(), strf2(), strf3()
strf1 = Array(1, 2, 3)
strf2 = Array(4, 5, 6)
strf3 = Array(6, 7, 9)
strf = Array(strf1, strf2, strf3)
End Sub
and code for a module
Sub s()
Debug.Print strf(2)(2)
End Sub
But I get the error "invalid outside procedure".
Bob Phillips
07-22-2019, 07:20 AM
Option Explicit
Public strf As Variant
Dim strf1 As Variant, strf2 As Variant, strf3 As Variant
Public Sub sf()
strf1 = Array(1, 2, 3)
strf2 = Array(4, 5, 6)
strf3 = Array(6, 7, 9)
strf = Array(strf1, strf2, strf3)
End Sub
Sub CallMyClass()
Dim cls As Class1
Set cls = New Class1
cls.sf
Debug.Print cls.strf(2)(2)
End Sub
Paul_Hossler
07-22-2019, 08:01 AM
Probably a matter of personal style, but I wouldn't put public variables in a Class module; I'd use Property Let/Get
Class module Class1
Option Explicit
Dim m_Ary() As Variant
Property Let A(A1 As Variant)
m_Ary = A1
End Property
Property Get A() As Variant
A = m_Ary
End Property
Sub DoubleIt()
Dim i As Long
For i = LBound(m_Ary) To UBound(m_Ary)
m_Ary(i) = 2 * m_Ary(i)
Next I
End Sub
Standard module
Option Explicit
Sub test()
Dim c As Class1
Dim i As Long
Set c = New Class1
With c
.A = Array(1, 2, 3, 4)
.DoubleIt
For i = LBound(.A) To UBound(.A)
Debug.Print .A(i)
Next i
.DoubleIt
For i = LBound(.A) To UBound(.A)
Debug.Print .A(i)
Next i
End With
End Sub
Bob Phillips
07-22-2019, 12:26 PM
Probably a matter of personal style, but I wouldn't put public variables in a Class module; I'd use Property Let/Get
A public variable in a class is the same as Property Let/Get, it is just less coding.
Paul_Hossler
07-22-2019, 02:35 PM
True, but in my example the properties weren't public
Probably no really good reason to make them properties, just the way I did things, since I oft times do things in the property besides just expose the variable, and I find I do better if I'm consistant
Bob Phillips
07-22-2019, 03:17 PM
True, but in my example the properties weren't public
What do you mean, of course they are public, how else do you think you can reference them in the procedure test? Just try explicitly declaring those properties as private and try running test.
Probably no really good reason to make them properties, just the way I did things, since I oft times do things in the property besides just expose the variable, and I find I do better if I'm consistant
I too often do that, but I constantly question myself as to whether I should do that or I should make it a method of the class instead.
Paul_Hossler
07-22-2019, 03:46 PM
What do you mean, of course they are public, how else do you think you can reference them in the procedure test? Just try explicitly declaring those properties as private and try running test.
I too often do that, but I constantly question myself as to whether I should do that or I should make it a method of the class instead.
Yes, you're right -- I just don't think of them as Public in the same way as a Standard Module Public variable since they have to instantiated as part of an object -- just me
Depends on situation -- I think of Methods as the class equivalent of a Sub, and Properties as the class equivalent of a Function
So I might have a property FullName defined as m_Last & " " & m_First
Bob Phillips
07-22-2019, 03:56 PM
Depends on situation -- I think of Methods as the class equivalent of a Sub, and Properties as the class equivalent of a Function
So I might have a property FullName defined as m_Last & " " & m_First
Funny isn't it, I definitely think of Methods as functions, and properties as, well, properties. To be accurate I really think of methods of being the actions of a class, and so can be serviced by a function or a sub (although I tend to use functions), and properties as the attributes of that class (which is why I get myself in knots when I get a property doing something other than just passing the value of that attribute in or out of the class).
In my coding I rarely use subs, except for event code that has sub as part of the signature, on that premise that every procedure should return a result even if it is only success or failure.
alex009988
07-24-2019, 03:12 AM
Thank you both for your help. So I wanted to have huge 99x1001 array(matrix). So I had to divide it into two parts 50x1001. Now I get error "procedure too large".
Now my class module has more then 50000 lines. So I've attached a file of that.
and use this module code
Sub s()
Dim st As Class
Set st = New Class
st.sf
Debug.Print st.strf(2)(2)
End Sub
How to make this code workable?
Bob Phillips
07-24-2019, 04:47 AM
I would put all of those values in a worksheet and load them in the class, fast and space efficient.
I split the values into 50 columns, one for each array, and then used the following code in the class module
Option Explicit
Public strf As Variant
Dim strf1, strf2, strf3, strf4, strf5, strf6, strf7, strf8, strf9, strf10, _
strf11, strf12, strf13, strf14, strf15, strf16, strf17, strf18, strf19, strf20, _
strf21, strf22, strf23, strf24, strf25, strf26, strf27, strf28, strf29, strf30, _
strf31, strf32, strf33, strf34, strf35, strf36, strf37, strf38, strf39, strf40, _
strf41, strf42, strf43, strf44, strf45, strf46, strf47, strf48, strf49, strf50
Public Sub sf()
With ActiveSheet
strf1 = .Range("A2:A1002")
strf2 = .Range("B2:B1002")
strf3 = .Range("C2:C1002")
strf4 = .Range("D2:D1002")
strf5 = .Range("E2:E1002")
strf6 = .Range("F2:F1002")
strf7 = .Range("G2:G1002")
strf8 = .Range("H2:H1002")
strf9 = .Range("I2:I1002")
strf10 = .Range("J2:J1002")
strf11 = .Range("K2:K1002")
strf12 = .Range("L2:L1002")
strf13 = .Range("M2:M1002")
strf14 = .Range("N2:N1002")
strf15 = .Range("O2:O1002")
strf16 = .Range("P2:P1002")
strf17 = .Range("Q2:Q1002")
strf18 = .Range("R2:R1002")
strf19 = .Range("S2:S1002")
strf20 = .Range("T2:T1002")
strf21 = .Range("U2:U1002")
strf22 = .Range("V2:V1002")
strf23 = .Range("W2:W1002")
strf24 = .Range("X2:X1002")
strf25 = .Range("Y2:Y1002")
strf26 = .Range("Z2:Z1002")
strf27 = .Range("AA2:AA1002")
strf28 = .Range("AB2:AB1002")
strf29 = .Range("AC2:AC1002")
strf30 = .Range("AD2:AD1002")
strf31 = .Range("AE2:AE1002")
strf32 = .Range("AF2:AF1002")
strf33 = .Range("AG2:AG1002")
strf34 = .Range("AH2:AH1002")
strf35 = .Range("AI2:AI1002")
strf36 = .Range("AJ2:AJ1002")
strf37 = .Range("AK2:AK1002")
strf38 = .Range("AL2:AL1002")
strf39 = .Range("AM2:AM1002")
strf40 = .Range("AN2:AN1002")
strf41 = .Range("AO2:AO1002")
strf42 = .Range("AP2:AP1002")
strf43 = .Range("AQ2:AQ1002")
strf44 = .Range("AR2:AR1002")
strf45 = .Range("AS2:AS1002")
strf46 = .Range("AT2:AT1002")
strf47 = .Range("AU2:AU1002")
strf48 = .Range("AV2:AV1002")
strf49 = .Range("AW2:AW1002")
strf50 = .Range("AX2:AX1002")
End With
strf = Array(strf1, strf2, strf3, strf4, strf5, strf6, strf7, strf8, strf9, strf10, strf11, strf12, strf13, strf14, strf15, strf16, strf17, strf18, strf19, strf20, strf21, strf22, strf23, strf24, strf25, strf26, strf27, strf28, strf29, strf30, strf31, strf32, strf33, strf34, strf35, strf36, strf37, strf38, strf39, strf40, strf41, strf42, strf43, strf44, strf45, strf46, strf47, strf48, strf49, strf50)
End Sub
I extracted the values by copying all of the strf(x) = values line from your class file into the worksheet, starting at A2, and then running this code on it to setup a grid of values
Sub movem()
Dim targetcol As Long
Dim lastrow As Long
Dim lastcol As Long
Dim i As Long
Application.ScreenUpdating = False
With ActiveSheet
targetcol = 3
lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("B1").Value = "strf1"
.Range("B2").Resize(lastrow - 1).FormulaR1C1 = "=--MID(RC[-1],FIND(""="",RC[-1])+2,99)"
For i = 1003 To lastrow Step 1001
.Cells(i, "A").Resize(1000, 2).Cut .Cells(2, targetcol)
targetcol = targetcol + 2
Next i
lastcol = .Cells(2, .Columns.Count).End(xlToLeft).Column
With .Range("A2").Resize(1001, lastcol)
.Value = .Value
End With
For i = lastcol - 1 To 1 Step -2
.Columns(i).Delete
Next i
lastcol = .Cells(2, .Columns.Count).End(xlToLeft).Column
.Range("A1").AutoFill Destination:=.Range("A1").Resize(1, lastcol), Type:=xlFillDefault
.Rows(1).Font.Bold = True
Debug.Print " With Activesheet"
Debug.Print ""
For i = 1 To lastcol
Debug.Print " " & .Cells(1, i).Value & " = .Range(""" & .Cells(2, i).Resize(1001).Address(False, False) & """)"
Next i
Debug.Print " End With"
End With
Application.ScreenUpdating = True
End Sub
Bob Phillips
07-24-2019, 04:59 AM
Sorry, missed something in the class module, code should be
Option Explicit
Public strf As Variant
Dim strf1, strf2, strf3, strf4, strf5, strf6, strf7, strf8, strf9, strf10, _
strf11, strf12, strf13, strf14, strf15, strf16, strf17, strf18, strf19, strf20, _
strf21, strf22, strf23, strf24, strf25, strf26, strf27, strf28, strf29, strf30, _
strf31, strf32, strf33, strf34, strf35, strf36, strf37, strf38, strf39, strf40, _
strf41, strf42, strf43, strf44, strf45, strf46, strf47, strf48, strf49, strf50
Public Sub sf()
With ActiveSheet
strf1 = Application.Transpose(.Range("A2:A1002"))
strf2 = Application.Transpose(.Range("B2:B1002"))
strf3 = Application.Transpose(.Range("C2:C1002"))
strf4 = Application.Transpose(.Range("D2:D1002"))
strf5 = Application.Transpose(.Range("E2:E1002"))
strf6 = Application.Transpose(.Range("F2:F1002"))
strf7 = Application.Transpose(.Range("G2:G1002"))
strf8 = Application.Transpose(.Range("H2:H1002"))
strf9 = Application.Transpose(.Range("I2:I1002"))
strf10 = Application.Transpose(.Range("J2:J1002"))
strf11 = Application.Transpose(.Range("K2:K1002"))
strf12 = Application.Transpose(.Range("L2:L1002"))
strf13 = Application.Transpose(.Range("M2:M1002"))
strf14 = Application.Transpose(.Range("N2:N1002"))
strf15 = Application.Transpose(.Range("O2:O1002"))
strf16 = Application.Transpose(.Range("P2:P1002"))
strf17 = Application.Transpose(.Range("Q2:Q1002"))
strf18 = Application.Transpose(.Range("R2:R1002"))
strf19 = Application.Transpose(.Range("S2:S1002"))
strf20 = Application.Transpose(.Range("T2:T1002"))
strf21 = Application.Transpose(.Range("U2:U1002"))
strf22 = Application.Transpose(.Range("V2:V1002"))
strf23 = Application.Transpose(.Range("W2:W1002"))
strf24 = Application.Transpose(.Range("X2:X1002"))
strf25 = Application.Transpose(.Range("Y2:Y1002"))
strf26 = Application.Transpose(.Range("Z2:Z1002"))
strf27 = Application.Transpose(.Range("AA2:AA1002"))
strf28 = Application.Transpose(.Range("AB2:AB1002"))
strf29 = Application.Transpose(.Range("AC2:AC1002"))
strf30 = Application.Transpose(.Range("AD2:AD1002"))
strf31 = Application.Transpose(.Range("AE2:AE1002"))
strf32 = Application.Transpose(.Range("AF2:AF1002"))
strf33 = Application.Transpose(.Range("AG2:AG1002"))
strf34 = Application.Transpose(.Range("AH2:AH1002"))
strf35 = Application.Transpose(.Range("AI2:AI1002"))
strf36 = Application.Transpose(.Range("AJ2:AJ1002"))
strf37 = Application.Transpose(.Range("AK2:AK1002"))
strf38 = Application.Transpose(.Range("AL2:AL1002"))
strf39 = Application.Transpose(.Range("AM2:AM1002"))
strf40 = Application.Transpose(.Range("AN2:AN1002"))
strf41 = Application.Transpose(.Range("AO2:AO1002"))
strf42 = Application.Transpose(.Range("AP2:AP1002"))
strf43 = Application.Transpose(.Range("AQ2:AQ1002"))
strf44 = Application.Transpose(.Range("AR2:AR1002"))
strf45 = Application.Transpose(.Range("AS2:AS1002"))
strf46 = Application.Transpose(.Range("AT2:AT1002"))
strf47 = Application.Transpose(.Range("AU2:AU1002"))
strf48 = Application.Transpose(.Range("AV2:AV1002"))
strf49 = Application.Transpose(.Range("AW2:AW1002"))
strf50 = Application.Transpose(.Range("AX2:AX1002"))
End With
strf = Array(strf1, strf2, strf3, strf4, strf5, strf6, strf7, strf8, strf9, strf10, strf11, strf12, strf13, strf14, strf15, strf16, strf17, strf18, strf19, strf20, strf21, strf22, strf23, strf24, strf25, strf26, strf27, strf28, strf29, strf30, strf31, strf32, strf33, strf34, strf35, strf36, strf37, strf38, strf39, strf40, strf41, strf42, strf43, strf44, strf45, strf46, strf47, strf48, strf49, strf50)
End Sub
Paul_Hossler
07-24-2019, 07:25 AM
1. That's a lot of hard coded numbers to have in a Class. Personally, I'd find 100 individually named arrays (srf1 … srf100) cumbersome to work with
I used Bob's movem sub to put into WS and doubled to get 100 cols, since personally I think that's the best place for 100K+ numbers
2. In a standard module
Option Explicit
Sub test()
Dim A As clsArray
Set A = New clsArray
With A
Call .Init(Worksheets("Sheet1").Cells(1, 1).CurrentRegion)
MsgBox .ColVector(2)(2)
MsgBox Application.WorksheetFunction.Max(.ColVector(10))
MsgBox Application.WorksheetFunction.Min(.ColVector(20))
MsgBox Application.WorksheetFunction.Average(.ColVector(30))
End With
Set A = Nothing
End Sub
3. In a class module named clsArray
Option Explicit
Dim m_Array As Range
Private Sub Class_Initialize()
'if always the same data range, could go here
Set m_Array = Nothing
End Sub
Private Sub Class_Terminate()
Set m_Array = Nothing
End Sub
Sub Init(r As Range)
On Error GoTo Err_Handler
Set m_Array = r
Exit Sub
Err_Handler:
End Sub
Property Get ColVector(n As Long) As Variant
ColVector = Empty
On Error GoTo Err_Handler
ColVector = Application.WorksheetFunction.Transpose(m_Array.Columns(n))
Exit Property
Err_Handler:
End Property
Bob Phillips
07-24-2019, 09:05 AM
What you (the OP) have not told us is what you are actually trying to do, and where those numbers come from. I bet we could come up with a better solution if we knew.
Paul_Hossler
07-24-2019, 09:15 AM
+1
alex009988
07-25-2019, 06:54 AM
You're right. I think the best way to work with that stuff is to have a worksheet and custom function
This code works for me
Function fstr(a As Integer, m As Integer)
Sheets("sfactors").Visible = False
Sheets("sfactors").Activate
Set r = Cells(1, 1)
fstr = Range(r(a, m + 1).Address).Value
End Function
But if I want to do it without hiding the list it dosent work
Function fstr(a As Integer, m As Integer)
'Sheets("sfactors").Visible = False
'Sheets("sfactors").Activate
Set r = ThisWorkbook.Sheets("sfactors").Cells(1, 1)
fstr = Range(r(a, m + 1).Address).Value
End Function
What's wrong with the second one? In this case, I had to manually select sfactors list.
Regards, Alex
Paul_Hossler
07-25-2019, 06:59 AM
Not tested
Function fstr(a As Integer, m As Integer) As Double
fstr = ThisWorkbook.Sheets("sfactors").Cells(a, m+1).Value
End Function
If you're reading the WS data from inside a macro, you can use the same method w/o a UDF
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.