I want to use a global array of objects of my own class (Markers class), which have data loaded in from a recordset. I can load the data from the recordset into the objects in the array just fine it seems, but when I try to access the values in the one of the objects in the array, it gives an "Object Required" error. I don't understand why my Markers() array of Marker class objects is getting destroyed or going out of scope.
Dim Markers(6)
Public Function GetItemSet(ByVal item)
'gets user input and returns a recordset object (just 1 record/row) from a SQL database
'working properly
End Function
Public Sub LoadMarkers(ByVal rs)
For i = 0 to 6
Set Markers(i) = New Marker
Next
MsgBox rs.Fields.Item("TextLine1").Value
Markers(0).TextLine(0) = rs.Fields.Item("TextLine1").Value
Markers(0).TextLine(1) = rs.Fields.Item("TextLine2").Value
'the above is just what I'm using to test functionality, no errors so far
End Sub
Public Function GetMarkerText(ByVal mrkr, ByVal line)
GetMarkerText = Markers(mrkr).TextLine(line)
End Function
In the other script I've tried both using Markers(0).TextLine(0) directly as well as calling GetMarkerText(0,0) to get the value... both methods result in object required error either on the line I directly try to access it or in the one line of code for GetMarkerText. LoadMarkers sub seems to have no issues accessing the Markers() array of Marker class objects, but then it seems to get destroyed after that sub ends? I'm new to VBScript so maybe I just don't quite understand how the scope is working but I can't see why this shouldn't work. Any ideas?
EDIT: Am I just a noob with Classes? Here's the relevant portion of the Markers class definition:
Class Marker
Private m_Name
Private m_TxtLines(6)
Private m_ItemNum
Private m_FontSize
Private m_FontType
Private m_Length
Private Sub Class_Initialize( )
m_Name = "Unnamed"
m_ItemNum = 0
m_Length = 1
For i = 0 To 6
m_TxtLines(i) = ""
Next
m_FontSize = 8
m_FontType = "Arial"
End Sub
'Name Property
Public Property Get Name
Name = m_Name
End Property
Public Property Let Name(marker)
m_Name = marker
End Property
'TextLine Property for holding up to 7 lines of marker text
Public Property Get TextLine(index)
TextLine(index) = m_TxtLines(index)
End Property
Public Property Let TextLine(index, txt)
m_TxtLines(index) = txt
End Property
'ItemNum Property
Public Property Get ItemNum
ItemNum = m_ItemNum
End Property
Public Property Let ItemNum(num)
m_ItemNum = num
End Property
'Length Property
Public Property Get Length
Length = m_Length
End Property
Public Property Let Length(len)
m_Length = len
End Property
'FontSize Property
Public Property Get FontSize
FontSize = m_FontSize
End Property
Public Property Let FontSize(pts)
m_FontSize = pts
End Property
'FontType Property
Public Property Get FontType
FontType = m_FontType
End Property
Public Property Let FontType(font)
m_FontType = font
End Property
'Haven't added my methods in yet
End Class
After staring at the class definition for a while think I may have spotted the culprit.
The assignment in...
Public Property Get TextLine(index)
is not correct. It should just point to...
TextLine = m_TxtLine(index)
not
TextLine(index) = m_TxtLine(index)
Related
I'm new to Microsoft Office Professional Plus 2013 Access.
I am developing an application using:
-Microsoft Office Professional Plus 2013 Access
I my VBA Editor, I have the following Class Module:
Option Explicit
Option Compare Database
Private cntrollingPersonFullNameProp As String
Private cntrollingPersonIsNameAddressProvidedProp As String
Private cntrollingPersonIsDOBProvidedProp As String
Private cntrollingPersonIsTaxResidenceProvidedProp As String
Private cntrollingPersonIsControllingPersonTypeProvidedProp As String
Private cntrollingPersonIsSignedAndDatedProp As String
Public Property Get CntrollingPersonFullName() As String
CntrollingPersonFullName = cntrollingPersonFullNameProp
End Property
Public Property Let CntrollingPersonFullName(lCntrollingPersonFullName As String)
cntrollingPersonFullNameProp = lCntrollingPersonFullName
End Property
Public Property Get CntrollingPersonIsNameAddressProvided() As String
CntrollingPersonIsNameAddressProvided = cntrollingPersonIsNameAddressProvidedProp
End Property
Public Property Let CntrollingPersonIsNameAddressProvided(lCntrollingPersonIsNameAddressProvided As String)
cntrollingPersonIsNameAddressProvidedProp = lCntrollingPersonIsNameAddressProvided
End Property
Public Property Get CntrollingPersonIsDOBProvided() As String
CntrollingPersonIsDOBProvided = cntrollingPersonIsDOBProvidedProp
End Property
Public Property Let CntrollingPersonIsDOBProvided(lCntrollingPersonIsDOBProvided As String)
cntrollingPersonIsDOBProvidedProp = lCntrollingPersonIsDOBProvided
End Property
Public Property Get CntrollingPersonIsTaxResidenceProvided() As String
CntrollingPersonIsTaxResidenceProvided = cntrollingPersonIsTaxResidenceProvidedProp
End Property
Public Property Let CntrollingPersonIsTaxResidenceProvided(lCntrollingPersonIsTaxResidenceProvided As String)
cntrollingPersonIsTaxResidenceProvidedProp = lCntrollingPersonIsTaxResidenceProvided
End Property
Public Property Get CntrollingPersonIsControllingPersonTypeProvided() As String
CntrollingPersonIsControllingPersonTypeProvided = cntrollingPersonIsControllingPersonTypeProvidedProp
End Property
Public Property Let CntrollingPersonIsControllingPersonTypeProvided(lCntrollingPersonIsControllingPersonTypeProvided As String)
cntrollingPersonIsControllingPersonTypeProvidedProp = lCntrollingPersonIsControllingPersonTypeProvided
End Property
Public Property Get CntrollingPersonIsSignedAndDated() As String
CntrollingPersonIsSignedAndDated = cntrollingPersonIsSignedAndDatedProp
End Property
Public Property Let CntrollingPersonIsSignedAndDated(lCntrollingPersonIsSignedAndDated As String)
cntrollingPersonIsSignedAndDatedProp = lCntrollingPersonIsSignedAndDated
End Property
In the Form code file,
Dim cntrollingPersonsArray() As CntrollingPerson
Private Sub AddControllingPersonBtn_Click()
Dim cntrlPerson As New CntrollingPerson
cntrlPerson.CntrollingPersonFullName = …….
cntrlPerson.CntrollingPersonIsNameAddressProvided = …..
ReDim Preserve cntrollingPersonsArray(UBound(cntrollingPersonsArray)+ 1)
cntrollingPersonsArray(UBound(cntrollingPersonsArray)) = cntrlPerson
End Sub
The application throws the:
'91' Object variable or With block variable not set
at the following line
cntrollingPersonsArray(UBound(cntrollingPersonsArray)) = cntrlPerson
I've tried a bunch of different code modifications
ReDim Preserve cntrollingPersonsArray(UBound(cntrollingPersonsArray))
or
ReDim Preserve cntrollingPersonsArray(0 to UBound(cntrollingPersonsArray))
or
ReDim Preserve cntrollingPersonsArray(1 to UBound(cntrollingPersonsArray))
Could someone please show me what steps to take in order to correct the aforementioned problem?
Use a collection object instead of an array. All your problems are solved!
EXAMPLE:
Option Explicit
Private cntrollingPersons As New Collection
Private Sub AddControllingPersonBtn_Click()
Dim cntrlPerson As New CntrollingPerson
cntrlPerson.CntrollingPersonFullName = ""
cntrlPerson.CntrollingPersonIsNameAddressProvided = ""
cntrollingPersons.Add cntrlPerson
End Sub
RELATED READING: https://excelmacromastery.com/excel-vba-collections/
Hi I have the following code
Partial Public Class DT_AnalyseDetail
Private componentField As String
Private contentField As String
Public Property Component() As String
Get
Return Me.componentField
End Get
Set(value As String)
Me.componentField = Value
End Set
End Property
Public Property Content() As String
Get
Return Me.contentField
End Get
Set(value As String)
Me.contentField = Value
End Set
End Property
End Class
Partial Public Class DT_Analyse
Private detailField() As DT_AnalyseDetail
Private batchField As String
Public Property Detail() As DT_AnalyseDetail()
Get
Return Me.detailField
End Get
Set(value As DT_AnalyseDetail())
Me.detailField = value
End Set
End Property
Public Property Batch() As String
Get
Return Me.batchField
End Get
Set(value As String)
Me.batchNoField = Value
End Set
End Property
End Class
Sub()
Dim a_Myana(1) As DT_Analyse
Dim a_Mydet(1) As DT_AnalyseDetail
a_Mydet(0) = New DT_AnalyseDetail
a_Mydet(0).Component = "TEST"
a_Mydet(0).Content= "YES"
a_Myana(0) = New DT_Analyse
a_Myana(0).Batch= "123"
a_Myana(0).Detail(0) = New DT_AnalyseDetail
a_Myana(0).Detail(0) = a_Mydet(0)
End Sub
The Error happens when I want to fill a_Myana(0).Detail(0) = a_Mydet(0)
I guess that my Class / array defintions are not correct. But I am not sure how to handle it. Does "Detail" need to have more dimensions?
The class defintion was written by visual studios xsd.exe from an xesd file.
This line does not do everything you think it does:
Dim a_Mydet(1) As DT_AnalyseDetail
You believe it creates an array of DT_AnalyseDetail objects, but this does not happen. Instead, it creates an array of DT_AnalyseDetail object references. At this point, each of those references has a value of Nothing (the references don't refer to any object). These Nothing references do not have space allocated for the Component property yet, so the line with the assignment fails.
BTW, there are two references here, not one, as VB.Net arrays are 0-indexed by default.
To fix the code, you need to do this:
Sub()
Dim a_Mydet(1) As DT_AnalyseDetail
a_Mydet(1) = New DT_AnalyseDetail()
a_Mydet(1).Component = "TEST"
End Sub
.
Looking now at the updated question.
You have these lines:
a_Myana(0) = New DT_Analyse
a_Myana(0).Batch= "123"
a_Myana(0).Detail(0) = New DT_AnalyseDetail
a_Myana(0).Detail(0) = a_Mydet(0)
Here, you are expecting the New DT_Analyse expression to create a new array for the Detail property. This does not happen. Arrays are objects. Properties are object references. Just like with the previous issue, you must first make sure the object reference refers to something other than Nothing. You need to do this:
a_Myana(0) = New DT_Analyse
a_Myana(0).Batch= "123"
a_Myana(0).Detail = New DT_AnDT_AnalyseDetail(0)
a_Myana(0).Detail(0) = New DT_AnalyseDetail
a_Myana(0).Detail(0) = a_Mydet(0)
Instead of
a_Myana(0).Detail(0) = New DT_AnalyseDetail
a_Myana(0).Detail(0) = a_Mydet(0)
I set
a_Myana(0).Detail() = a_Mydet
and it works :)
I've been searching all over but nothing seems to do the trick for me. Here is the problem:
I want to store an array of "keys"
Here is my simple class:
Private pkeys_length As Integer
Private pkeys() As String
Public Property Get keys_length() As Integer
keys_length = pkeys_length
End Property
Public Property Let keys_length(arg As Integer)
pkeys_length = arg
End Property
Public Property Get Keys() As String
Keys = pkeys()
End Property
Public Property Let Keys(ByVal arg As String)
ReDim pkeys(0 To pkeys_length) As String
pkeys = arg
End Property
And here is what I am trying to store:
Dim str_pkeys() As String
Dim pkey_count As Integer
pkey_count = CountPrimaryKeys(stbl)
'Store the keys of that table
ReDim str_pkeys(pkey_count) As String
keyset_1.keys_length = pkey_count
str_pkeys = FindPrimaryKeys(keyset_1.Table)
keyset_1.Keys = str_pkeys
As it stands, it Gives the error Compile Error: Type mismatch
I have had several problems while storing the array, I'm not sure if I am actually getting anywhere. This is the only error I haven't been able to fix. All I need to be able to do is store the array of strings in the class.
Anyone familiar with how to go about this?
I think you need to use String() in your Get property and remove the ByVal in the Let:
Private pkeys_length As Integer
Private pkeys() As String
Public Property Get keys_length() As Integer
keys_length = pkeys_length
End Property
Public Property Let keys_length(arg As Integer)
pkeys_length = arg
End Property
Public Property Get Keys() As String()
Keys = pkeys
End Property
Public Property Let Keys(arg() As String)
ReDim pkeys(0 To pkeys_length) As String
pkeys = arg
End Property
Apart from this a small design suggestion: do you really need a Set for the array length? Why not include this in the set of the array - and only provide the Get instead?
I have a Class ABC. And i want to write two properties for
it. One i have already mentioned in the code. The other one will be a single dimensional array.
Public Class ABC
Private m_Type As String
Private SomeArray........need to write a property for array which will be of type `int`
Public Property Type() As String
Get
Return m_Type
End Get
Set(ByVal value As String)
m_Type = value
End Set
End Property
End Class
I am not sure how to define a property for array which can be used in a List(Of ABC). The property for array can be a read only array as i will be
hard coding the data for it.
So basically when i do this,
Dim SomeList As New List(Of ABC)
And inside a for loop i need something like this,
SomeList.Item(index).SomeArray......this will give me all the items inside the array
You can declare an array property the same way as you declare a different property type:
Public Class ABC
Private _Type As String
Private _SomeArray As Int32()
Public Property SomeArray As Int32()
Get
Return _SomeArray
End Get
Set(ByVal value As Int32())
_SomeArray = value
End Set
End Property
Public Property Type() As String
Get
Return _Type
End Get
Set(ByVal value As String)
_Type = value
End Set
End Property
End Class
for example, if you want to loop all Integers in one array of the list:
Dim index As Int32 = 0
Dim someList As New List(Of ABC)
For Each i As Int32 In someList(index).SomeArray
Next
If you're not going to be doing anything special in the Gets and Sets, you could simplify your code a little, as in the following (which initializes the read only array to contain the numbers 1, 2, 3 and 4):
Public Class ABC
Public Property Type As String
Public ReadOnly Property SomeArray As Integer() = {1,2,3,4}
End Class
I have two properties in my VB6 code:
Public Property Get PropFileID() As Long
PropFileID = m_FileID
End Property
Public Property Get PropFileIDArray() As Long()
PropFileIDArray = m_FileIDArray
End Property
While debugging, I can see the first property (PropFileID) being assigned a value without error. m_FileID has a value, and after passing through the Get accessor, PropFileID gets the same value.
While debugging the second property (PropFileIDArray), I can see that m_FileIDArray has a valid array value. However, after passing through the Get accessor, PropFileIDArray remains empty.
Am I making some kind of error in the syntax?
Any suggestions would be greatly appreciated
The class code looks ok. Maybe something is wrong in the consuming part? Here is an example that works for me:
'Class1
Private m_FileIDArray(2) As Long
Public Sub SetValues()
m_FileIDArray(0) = 0
m_FileIDArray(1) = 1
m_FileIDArray(2) = 2
End Sub
Public Property Get PropFileIDArray() As Long()
PropFileIDArray = m_FileIDArray
End Property
'Form
Private Sub Form_Load()
Dim class1 As class1
Set class1 = New class1
class1.SetValues
Dim pa As Variant
pa = class1.PropFileIDArray
MsgBox pa(0)
MsgBox pa(1)
MsgBox pa(2)
Set class1 = Nothing
End Sub