vb.net class and array - arrays

I am having an issue with trying to take info from class and putting them into an array with the class data type. I am getting a null error. I can see its not adding the variable info into the array at all. I am unsure what it is I am missing. Can anyone point out to me what it is?
Here is the code:
Option Explicit On
Option Strict On
Option Infer Off
Public Class Form1
Public Class Chandelier
Private _strFinish As String
Private _intLights As Integer
Private _blnCrystal As Boolean
Private _dblTotal As Double
Public Property Finish As String
Get
Return _strFinish
End Get
Set(value As String)
_strFinish = value
End Set
End Property
Public Property Lights As Integer
Get
Return _intLights
End Get
Set(value As Integer)
If value > 0 Then
_intLights = value
Else
_intLights = 0
End If
End Set
End Property
Public Property Crystal As Boolean
Get
Return _blnCrystal
End Get
Set(value As Boolean)
_blnCrystal = value
End Set
End Property
Public Property Total As Double
Get
Return _dblTotal
End Get
Set(value As Double)
If value > 0 Then
_dblTotal = value
Else
_dblTotal = 0
End If
End Set
End Property
Public Sub New()
_strFinish = Nothing
_intLights = 0
_blnCrystal = False
_dblTotal = 0
End Sub
Public Function getCrystal() As Boolean
Return _blnCrystal
End Function
Public Function getPrice() As Double
Dim crystalPrice As Double
Dim price As Double
If _strFinish.Contains("Silver") Then
price = 39.99
If getCrystal() = True Then
crystalPrice = _intLights * 25.5
Else
crystalPrice = 0
End If
price = price + crystalPrice
End If
If _strFinish.Contains("Brass") Then
price = 49.99
If getCrystal() = True Then
crystalPrice = _intLights * 25.5
Else
crystalPrice = 0
End If
price = price + crystalPrice
End If
Return price
End Function
End Class
Public chandelierStyle(49) As Chandelier
Dim count As Integer = 0
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
Dim ceilingOrnament As New Chandelier
ceilingOrnament.Finish = cboFinish.SelectedItem.ToString
Integer.TryParse(cboLights.SelectedItem.ToString, ceilingOrnament.Lights)
If chkTrimmings.Checked Then
ceilingOrnament.Crystal = True
End If
Dim dblTotal As Double = ceilingOrnament.getPrice()
ceilingOrnament.Total = dblTotal
If count <= 49 Then
'here is where the error starts
chandelierStyle(count).Finish = ceilingOrnament.Finish
chandelierStyle(count).Lights = ceilingOrnament.Lights
chandelierStyle(count).Crystal = ceilingOrnament.Crystal
chandelierStyle(count).Total = ceilingOrnament.Total
count += 1
End If
End Sub

Just place your dynamic instance into the array, instead of trying to copy each individual field.
Change this:
If count <= 49 Then
'here is where the error starts
chandelierStyle(count).Finish = ceilingOrnament.Finish
chandelierStyle(count).Lights = ceilingOrnament.Lights
chandelierStyle(count).Crystal = ceilingOrnament.Crystal
chandelierStyle(count).Total = ceilingOrnament.Total
count += 1
End If
To:
If count <= 49 Then
'here is where the error starts
chandelierStyle(count) = ceilingOrnament
count += 1
End If

Looks like you create your array of 49 elements with this line:
Public chandelierStyle(49) As Chandelier
but you never actually initialize its contents. What you have is 49 empty slots, not 49 Chandelier instances. You need to first set each array slot to a new instance of Chandelier before you can update their properties in your button Click event.
You can use a For loop to initialize each array slot before you use it; something like:
For i As Integer = 0 To 49
chandelierStyle(i) = New Chandelier()
Next i
You'd have this loop in the constructor of the class (looks like it's a Form) that contains your chandelierStyle array.
Note: Don't quote me on that. :) I haven't used VB.NET for ages and there may be an easier way to do this.
Edit: Or, you can do what Idle_Mind suggested in his answer and just stash the ceilingOrnament instance in the appropriate array slot.

Related

Setting Class Object Array Property

I'm trying to set a property of an object which is part of a class object array, for excel in VBA.
The code looks like this:
Dim myClass(5) as class1
Dim i as integer
For i = 0 to 5
set myClass(i) = New class
myClass(i).myProperty = "SomeValue"
Next i
Class code is simply:
Private pmyProperty as string
Public Property Let myProperty(s as string)
pmyProperty = s
End Property
Public Property Get myProperty() as string
myProperty = pmyProperty
End Property
However when I run this, I get a compile error "expected: list separator." This hits on the myClass(i).myProperty = "SomeValue" line.
How do I set the value of a property of an class object that is part of an array?
Any help would be great!
So the actual code is as follows...
Module code:
Public Sub main_sb_BillingApp()
Dim intCountComplete As Integer
Dim intLastRow As Integer
Dim Line() As clsLine
Dim i As Integer, x As Integer
intCountComplete = WorksheetFunction.CountIf(Sheets(WS_NAME).Columns(COL_W_COMPLETE), "Yes")
intLastRow = Sheets(WS_NAME).Cells(LAST_ROW, COL_W_COMPLETE).End(xlUp).Row - 1
ReDim Line(intCountComplete - 1)
For i = ROW_W_HEADER + 1 To intLastRow
If Sheets(WS_NAME).Cells(i, COL_W_COMPLETE) = "Yes" Then
Set Line(x) = New clsLine
Line(x).Row = i
x = x + 1
End If
Next i
End Sub
Class code:
Private pDate As Date
Private pUJN As String
Private pDesc As String
Private pCharge As Currency
Private pCost As Currency
Private pMargin As Double
Private pComplete As Boolean
Private pRow As Integer
Public Property Let Row(i As Integer)
pRow = i
Update
End Property
Public Property Get Row() As Integer
Row = pRow
End Property
Private Sub Update()
With Sheets(WS_NAME)
pDate = .Cells(pRow, COL_W_DATE)
pUJN = .Cells(pRow, COL_W_UJN)
pDesc = .Cells(pRow, COL_W_DESC)
pCharge = .Cells(pRow, COL_W_CHARGE)
pCost = .Cells(pRow, COL_W_COST)
pMargin = .Cells(pRow, COL_W_MARGIN)
If .Cells(pRow, COL_W_COMPLETE) = "Yes" Then
pComplete = True
Else
pComplete = False
End If
End With
End Sub
Line is a VBA reserved keyword, so you're confusing the compiler. Change the name of your object array and it works just fine:
Dim lineArray() As clsLine
'...
Set lineArray(x) = New clsLine
lineArray(x).Row = i

Implementing a custom column sorting

I'm having issues implementing a custom sort on a datagrid column. Could someone explain what I'm doing wrong?
I'm trying to create a custom sort for column so that the strings are sorted by length first, then by their values. It reaches my custom made function, hits the "Throws not implemented line", and then gives me an InvalidOperationException error.
Private Sub customSorting(sender As Object, e As DataGridSortingEventArgs) Handles grid.Sorting
If e.Column.Header = "Test" Then
Dim comp As IComparer = New RowComparer(e.Column.SortDirection)
Dim lcv As ListCollectionView = CollectionViewSource.GetDefaultView(grid.ItemsSource)
lcv.CustomSort = comp
e.Handled = True
End If
End Sub
Private Class RowComparer
Implements System.Collections.IComparer
Private o As Integer = 0
Public Sub New(order As Integer)
o = order
End Sub
Public Function Compare(x As Object, y As Object) As Integer Implements IComparer.Compare
Throw New NotImplementedException()
If x.ToString.Length > y.ToString.Length Then
If o = 0 Then
Return 1
Else
Return -1
End If
ElseIf x.ToString.Length < y.ToString.Length Then
If o = 0 Then
Return -1
Else
Return 1
End If
Else
Return String.Compare(x, y)
End If
End Function
End Class
Visual studios automatically generated the 'Throw New NotImplementedException()' which was stopping my program.

Declaring Array in VBA class

I have several classes containing details about an onsite switchboard. I am using a Userform to store data in the variables declared in each class. I am struggling to store the data in any of my arrays. Am I going the right way about declaring these variables? Here's an example of one of my classes:
Dim pEquipID(3) As String
Dim pIr(3) As Integer
Dim pIm(3) As Integer
Dim pTripCurrent(3) As Integer
Dim pTripTime(3) As Integer
Dim pIsc(3) As Integer
Public Property Let EquipID(index As Integer, value As String)
pEquipID(index) = value
End Property
Public Property Let Ir(index As Integer, value As Integer)
pIr(index) = value
End Property
Public Property Let Im(index As Integer, value As Integer)
pIm(index) = value
End Property
Public Property Let TripCurrent(index As Integer, value As Integer)
pTripCurrent(index) = value
End Property
Public Property Let TripTime(index As Integer, value As Integer)
pTripTime(index) = value
End Property
Public Property Let Isc(index As Integer, value As Integer)
pIsc(index) = value
End Property
Public Property Get EquipID(index As Integer) As String
EquipID(index) = pEquipID(index)
End Property
Public Property Get Ir(index As Integer) As Integer
Ir(index) = pIr(index)
End Property
Public Property Get Im(index As Integer) As Integer
Im(index) = pIm(index)
End Property
Public Property Get TripCurrent(index As Integer) As Integer
TripCurrent(index) = pTripCurrent(index)
End Property
Public Property Get TripTime(index As Integer) As Integer
TripTime(index) = pTripTime(index)
End Property
Public Property Get Isc(index As Integer) As Integer
Isc(index) = pIsc(index)
End Property
And this is how I am storing the data:
Private Sub Enter1_Click()
'create class variables
Dim Transformer1 As cTransformer
Set Transformer1 = New cTransformer
Dim Fuse1 As cFuse
Set Fuse1 = New cFuse
Dim CircuitBreaker1 As cCircuitBreaker
Set CircuitBreaker1 = New cCircuitBreaker
Dim Pump1 As cPump
Set Pump1 = New cPump
Dim Cable1 As cCable
Set Cable1 = New cCable
'store circuit breaker entries
CircuitBreaker1.EquipID(0) = CB1ID1.value
CircuitBreaker1.EquipID(1) = CB2ID1.value
CircuitBreaker1.Ir(0) = Cb1Ir1.value
CircuitBreaker1.Ir(1) = CB2Ir1.value
CircuitBreaker1.Im(0) = CB1Im1.value
CircuitBreaker1.Im(1) = CB2Im1.value
CircuitBreaker1.Isc(0) = CB1Isc1.value
CircuitBreaker1.Isc(1) = CB2Isc1.value
CircuitBreaker1.TripCurrent(0) = CB1trip1.value
CircuitBreaker1.TripCurrent(1) = CB2trip1.value
CircuitBreaker1.TripTime(0) = CB1time1.value
CircuitBreaker1.TripTime(1) = CB2time1.value
When I debug.print the CircuitBreaker array the terminal prints blank values. I use a loop like this to print each array:
Dim count As integer
For count = 0 To 1 Step 1
Debug.Print CircuitBreaker1.EquipID(count)
Next count
Note that this print statement is inside Enter1_click()
Your Property Get is incorrect. Instead of:
Public Property Get EquipID(index As Integer) As String
EquipID(index) = pEquipID(index)
End Property
... it should be:
Public Property Get EquipID(index As Integer) As String
EquipID = pEquipID(index)
End Property

Array as a Class Member

I'm designing a dynamic buffer for outgoing messages. The data structure takes the form of a queue of nodes that have a Byte Array buffer as a member. Unfortunately in VBA, Arrays cannot be public members of a class.
For example, this is a no-no and will not compile:
'clsTest
Public Buffer() As Byte
You will get the following error: "Constants, fixed-length strings, arrays, user-defined types and Declare statements not allowed as Public members of object modules"
Well, that's fine, I'll just make it a private member with public Property accessors...
'clsTest
Private m_Buffer() As Byte
Public Property Let Buffer(buf() As Byte)
m_Buffer = buf
End Property
Public Property Get Buffer() As Byte()
Buffer = m_Buffer
End Property
...and then a few tests in a module to make sure it works:
'mdlMain
Public Sub Main()
Dim buf() As Byte
ReDim buf(0 To 4)
buf(0) = 1
buf(1) = 2
buf(2) = 3
buf(3) = 4
Dim oBuffer As clsTest
Set oBuffer = New clsTest
'Test #1, the assignment
oBuffer.Buffer = buf 'Success!
'Test #2, get the value of an index in the array
' Debug.Print oBuffer.Buffer(2) 'Fail
Debug.Print oBuffer.Buffer()(2) 'Success! This is from GSerg's comment
'Test #3, change the value of an index in the array and verify that it is actually modified
oBuffer.Buffer()(2) = 27
Debug.Print oBuffer.Buffer()(2) 'Fail, diplays "3" in the immediate window
End Sub
Test #1 works fine, but Test #2 breaks, Buffer is highlighted, and the error message is "Wrong number of arguments or invalid property assignment"
Test #2 now works! GSerg points out that in order to call the Property Get Buffer() correctly and also refer to a specific index in the buffer, TWO sets of parenthesis are necessary: oBuffer.Buffer()(2)
Test #3 fails - the original value of 3 is printed to the Immediate window. GSerg pointed out in his comment that the Public Property Get Buffer() only returns a copy and not the actual class member array, so modifications are lost.
How can this third issue be resolved make the class member array work as expected?
(I should clarify that the general question is "VBA doesn't allow arrays to be public members of classes. How can I get around this to have an array member of a class that behaves as if it was for all practical purposes including: #1 assigning the array, #2 getting values from the array, #3 assigning values in the array and #4 using the array directly in a call to CopyMemory (#3 and #4 are nearly equivalent)?)"
So it turns out I needed a little help from OleAut32.dll, specifically the 'VariantCopy' function. This function faithfully makes an exact copy of one Variant to another, including when it is ByRef!
'clsTest
Private Declare Sub VariantCopy Lib "OleAut32" (pvarDest As Any, pvargSrc As Any)
Private m_Buffer() As Byte
Public Property Let Buffer(buf As Variant)
m_Buffer = buf
End Property
Public Property Get Buffer() As Variant
Buffer = GetByRefVariant(m_Buffer)
End Property
Private Function GetByRefVariant(ByRef var As Variant) As Variant
VariantCopy GetByRefVariant, var
End Function
With this new definition, all the tests pass!
'mdlMain
Public Sub Main()
Dim buf() As Byte
ReDim buf(0 To 4)
buf(0) = 1
buf(1) = 2
buf(2) = 3
buf(3) = 4
Dim oBuffer As clsTest
Set oBuffer = New clsTest
'Test #1, the assignment
oBuffer.Buffer = buf 'Success!
'Test #2, get the value of an index in the array
Debug.Print oBuffer.Buffer()(2) 'Success! This is from GSerg's comment on the question
'Test #3, change the value of an index in the array and verify that it is actually modified
oBuffer.Buffer()(2) = 27
Debug.Print oBuffer.Buffer()(2) 'Success! Diplays "27" in the immediate window
End Sub
#Blackhawk,
I know it is an old post, but thought I'd post it anyway.
Below is a code I used to add an array of points to a class, I used a subclass to define the individual points, it sounds your challenge is similar:
Mainclass tCurve
Private pMaxAmplitude As Double
Private pCurvePoints() As cCurvePoint
Public cDay As Date
Public MaxGrad As Double
Public GradChange As New intCollection
Public TideMax As New intCollection
Public TideMin As New intCollection
Public TideAmplitude As New intCollection
Public TideLow As New intCollection
Public TideHigh As New intCollection
Private Sub Class_Initialize()
ReDim pCurvePoints(1 To 1500)
ReDim curvePoints(1 To 1500) As cCurvePoint
Dim i As Integer
For i = 1 To 1500
Set Me.curvePoint(i) = New cCurvePoint
Next
End Sub
Public Property Get curvePoint(Index As Integer) As cCurvePoint
Set curvePoint = pCurvePoints(Index)
End Property
Public Property Set curvePoint(Index As Integer, Value As cCurvePoint)
Set pCurvePoints(Index) = Value
End Property
subclass cCurvePoint
Option Explicit
Private pSlope As Double
Private pCurvature As Double
Private pY As Variant
Private pdY As Double
Private pRadius As Double
Private pArcLen As Double
Private pChordLen As Double
Public Property Let Slope(Value As Double)
pSlope = Value
End Property
Public Property Get Slope() As Double
Slope = pSlope
End Property
Public Property Let Curvature(Value As Double)
pCurvature = Value
End Property
Public Property Get Curvature() As Double
Curvature = pCurvature
End Property
Public Property Let valY(Value As Double)
pY = Value
End Property
Public Property Get valY() As Double
valY = pY
End Property
Public Property Let Radius(Value As Double)
pRadius = Value
End Property
Public Property Get Radius() As Double
Radius = pRadius
End Property
Public Property Let ArcLen(Value As Double)
pArcLen = Value
End Property
Public Property Get ArcLen() As Double
ArcLen = pArcLen
End Property
Public Property Let ChordLen(Value As Double)
pChordLen = Value
End Property
Public Property Get ChordLen() As Double
ChordLen = pChordLen
End Property
Public Property Let dY(Value As Double)
pdY = Value
End Property
Public Property Get dY() As Double
dY = pdY
End Property
This will create a tCurve with 1500 tCurve.Curvepoints().dY (for example)
The trick is to get the index process correct in the main class !
Good luck !
Not the most elegant solution, but modeling from the code you provided...
In clsTest:
Option Explicit
Dim ArrayStore() As Byte
Public Sub AssignArray(vInput As Variant, Optional lItemNum As Long = -1)
If Not lItemNum = -1 Then
ArrayStore(lItemNum) = vInput
Else
ArrayStore() = vInput
End If
End Sub
Public Function GetArrayValue(lItemNum As Long) As Byte
GetArrayValue = ArrayStore(lItemNum)
End Function
Public Function GetWholeArray() As Byte()
ReDim GetWholeArray(LBound(ArrayStore) To UBound(ArrayStore))
GetWholeArray = ArrayStore
End Function
And in mdlMain:
Sub test()
Dim buf() As Byte
Dim bufnew() As Byte
Dim oBuffer As New clsTest
ReDim buf(0 To 4)
buf(0) = 1
buf(1) = 2
buf(2) = 3
buf(3) = 4
oBuffer.AssignArray vInput:=buf
Debug.Print oBuffer.GetArrayValue(lItemNum:=2)
oBuffer.AssignArray vInput:=27, lItemNum:=2
Debug.Print oBuffer.GetArrayValue(lItemNum:=2)
bufnew() = oBuffer.GetWholeArray
Debug.Print bufnew(0)
Debug.Print bufnew(1)
Debug.Print bufnew(2)
Debug.Print bufnew(3)
End Sub
I added code to pass the class array to another array to prove accessibility.
Even though VBA won't allow us to pass arrays as properties, we can still use Functions to pick up where properties fall short.

How to retrieve column items from listview in code

I am new to wpf and am going for an MCTS exam. I have searched for 2 days now on how to retrieve row column items in code. I have been able to insert data into the listview by creating a structure and adding row items via code.
Public Structure SimpleData
Public Property Txt1 As String
Get
Return mTxt1
End Get
Set(value As String)
mTxt1 = value
End Set
End Property
Private mTxt1 As String
Public Property Txt2 As String
Get
Return mTxt2
End Get
Set(value As String)
mTxt2 = value
End Set
End Property
Private mTxt2 As String
Public Property Txt3 As String
Get
Return mTxt3
End Get
Set(value As String)
mTxt3 = value
End Set
End Property
Private mTxt3 As String
End Structure
Public Structure MyData
Public Property Desc() As String
Get
Return m_Desc
End Get
Set(value As String)
m_Desc = Value
End Set
End Property
Private m_Desc As String
Public Property Progress() As Integer
Get
Return m_Progress
End Get
Set(value As Integer)
m_Progress = Value
End Set
End Property
Private m_Progress As Integer
Public Property ProgressText() As String
Get
Return m_ProgressText
End Get
Set(value As String)
m_ProgressText = Value
End Set
End Property
Private m_ProgressText As String
Public Property Pic() As String
Get
Return m_Pic
End Get
Set(value As String)
m_Pic = Value
End Set
End Property
Private m_Pic As String
End Structure
Private Sub Button2_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button2.Click
Dim sd As New SimpleData
sd.Txt1 = "Today is"
sd.Txt2 = "a good day"
sd.Txt3 = "O YES!"
listView1.Items.Add(sd)
End Sub
I want to be able to retrieve row(0).Item(0).ToString, which is how to retrieve it in win forms. Expecting a response. Thanks in advance
Dim constr As String = "Put your connection string here"
Dim ds As New DataSet
Dim con As New SqlClient.SqlConnection(constr)
con.Open()
Dim sqladap As New SqlClient.SqlDataAdapter("select * from tbl_Employee", con)
sqladap.Fill(ds)
For i As Integer = 0 To ds.Tables(0).Columns.Count - 1
ListView1.Columns.Add(ds.Tables(0).Columns(i).ToString())
Next
For i As Integer = 0 To ds.Tables(0).Rows.Count - 1
Dim listRow As New ListViewItem
listRow.Text = ds.Tables(0).Rows(i)(0).ToString()
For j As Integer = 1 To ds.Tables(0).Columns.Count - 1
listRow.SubItems.Add(ds.Tables(0).Rows(i)(j).ToString())
Next
ListView1.Items.Add(listRow)
Next
Read data from Listview :
Dim name, room, subject, date, period As String
If listviewName.SelectedItems.Count > 0 then
For i As Integer = 0 To listviewName.SelectedItems.Count - 1
'*********** transfer selected data on declare String variable ************'
name= listviewName.SelectedItems(i).SubItems(0).Text
room = listviewName.SelectedItems(i).SubItems(1).Text
subject = listviewName.SelectedItems(i).SubItems(2).Text
date= listviewName.SelectedItems(i).SubItems(3).Text
period= listviewName.SelectedItems(i).SubItems(4).Text
'*********** delete **************'
cmd1.Connection = MYSQLCON
MYSQLCON.Open()
cmd1.CommandText = "DELETE FROM tablename WHERE columnname = '" & name & "'"
reader = cmd1.ExecuteReader
MYSQLCON.Close()
Next
End If
I have found the answer by casting the listview item to the created structure SimpleData then looping through it
Dim getitems = CType(listView1.SelectedItem, SimpleData)
For Each mem In getitems.Txt1
MsgBox(mem.ToString)
Next

Resources