Passing names of class fields to a private sub to update in VB.Net - vb.net

I thought this might be simple to achieve, but I can't figure out how to make it work.
I have a series of fields within a class that I want to check the value of. So instead of writing the same if ... then ... else statement I thought passing this through a private method would be ideal.
Private Sub checkParameter(ByRef p_param As Object, ByRef p_private_field As Object, p_exception As String)
If Not p_param Then
Throw New Exception(p_exception)
Else
p_private_field = p_param
End If
End Sub
Of course the problem is that I want the p_private_field to be the actual private field I am passing in.
So if I called the method with the following code:
checkParameter(i_input_folder, "p_input_folder", "Input folder must be supplied")
Then the method would check that i_input_folder did have a value and if so then assign it to the private field p_input_folder and if not throw the exception with the message provided.
Any help would be greatly appreciated.
Cheers

Seems just like a little typo
checkParameter(i_input_folder, "p_input_folder", "Input folder must be supplied")
You pass in your second parameter as string (the name of the filed i guess), but you have to pass the object itself
checkParameter(i_input_folder, p_input_folder, "Input folder must be supplied")

Related

Set a Property Value From Database of Properties

My database has the formname, control, and control property type value stored.
I would like to have a line of code like this.
Forms(i%).Controls(ControlName$)).controlpropertytype$ = NewValue
I am currently using a select case structure to handle the various property types. It would be much simpler to have a single statement take care of it.
Using a helper function, you can achieve this with one line of code. Here's an example of setting a TextBox on Form1 to the value 'aaa':
Option Explicit
Private Sub Test()
CallByName FindForm("Form1").Controls("Text1"), "Text", VbLet, "aaa"
End Sub
Public Function FindForm(ByVal Name As String) As Form
Dim f As Form
For Each f In Forms
If UCase(f.Name) = UCase(Name) Then
Set FindForm = f
Exit Function
End If
Next
End Function
While this is an interesting exercise, I would not recommend this approach. It assumes the form and the control can both be found, but if they can't be found this one-liner will crash your app.
Here's documentation for CallByName.

How ByVal works for Objects in vb.net?

My question is regarding the concept for working of ByVal in vb.net.
Here is the code:
Private Sub ManipulateDetails()
Dim tObject1 as New customdatatype
tObject1.sName = "Stack"
tObject1.sLastName = "Over"
GetManipulateDetails(tObject1)
End Sub
Private Function GetManipulateDetails(ByVal tObject1 as customdatatype)
tObject1.sName = "Stack-Over-Flow"
tObject1.sLastName = "Flow-Over-Stack"
Return tObject1
End Function
In the above code snippet I am sending tObject1 as ByVal in the GetManipulateDetails function, when the values are changed in this subroutine the object which is returned back, manipulates the actual object which was passed.
i.e. if I quickwatch the object in the method ManipulateDetails I can see the manipulated details.
Also if I am returning the object in the subroutine function the value is getting reflected in the original object which was passed.
as the value is getting changed even without returning the object from the function GetManipulateDetails, I am confused whether this is happening because of ByRef?? or there is some other mechanism which is making this work.
It may be clearer if we use different names:
Private Sub ManipulateDetails()
Dim tObject1 as New customdatatype
tObject1.sName = "Stack"
tObject1.sLastName = "Over"
GetManipulateDetails(tObject1)
End Sub
Private Function GetManipulateDetails(ByVal tother as customdatatype) as customdatatype
tother.sName = "Stack-Over-Flow"
tother.sLastName = "Flow-Over-Stack"
Return tother
End Function
Before you call GetManipulateDetails, tObject1 is a reference to an object of type customdatatype. When you call GetManipulateDetails, tother gets a copy of tObject1. Importantly, what this means is that now, tObject1 and tother are both references to the same object. What was copied was the reference, not the object. Within GetManipulateDetails, it can use its copy of the reference to access the object and make changes to it.
ByVal parameters are always copied - but parameters are either value types or references. They're never reference types (aka objects) themselves.

Why does my function's name appear twice in the "locals" window?

I have created a Class Module in which I have defined a function. Whenever that function is called, it is listed twice in the locals window. Only the second one's value changes, the first one stays either empty or "zero", depending on its type, until the end of the code's execution. I don't have this problem with functions defined in standard modules. Did I do something wrong, is this a bug, or is there a logical reason behind this?
Contents of the TestClass class module:
Public Value As Double
Function AddFive() As Double
AddFive = Me.Value + 5
End Function
Contents of the standard module:
Sub TestSub()
Dim TestObject As New TestClass
TestObject.Value = 2
MsgBox TestObject.AddFive
End Sub
Here is a screenshot showing that, when the code is executed line-by-line, the function's value is listed twice in the locals window, and only the second value has changed after the function's code was executed.
(link to screenshot)
I'm using VBA for Excel 2010.
Thanks in advance.
The issue is more in how you are doing it. If you have a function that just adds 5 to an internal variable of a class object, then it's technically a void (Sub in VBA) since you don't need a return value.
Your code should be:
CLASS
Public Value As Double
Sub AddFive()
Me.Value = Me.Value + 5
End Sub
MODULE
Sub test()
Dim testObject As New TestClass
testObject.Value = 2
testObject.AddFive
MsgBox testObject.Value
End Sub
I can imagine there could be a number of reasons why there are 2 variables created, but I find it a bit pointless to go into why there is unexpected behavior since you are doing improper code.
If you want, you can even write class function that will show it's value + 5 in a msgbox and this would not create an extra variable either. But that is strange and I think you want the code above. But here it is regardless:
CLASS
Public Value As Double
Sub ShowPlusFive()
MsgBox Me.Value + 5
End Sub
MODULE
Sub test()
Dim testObject As New TestClass
testObject.Value = 2
testObject.ShowPlusFive
End Sub

VB.NET How To Tell If New Class Instance Was Ended Early?

I'm trying to detect if the Sub New() in my class has ended early due to missing fields. Below is a sample of my code:
Class Account
Public Sub New(ByVal Firstname As String, ByVal LastName As String, ByVal Username As String, ByVal Email As String, ByVal Password As String)
' Check For Blank Fields
If Firstname = "" Or LastName = "" Or Username = "" Or Email = "" Or Password = "" Then
MessageBox.Show("Please Enter All Information Requested")
Exit Sub
End If
' Set Public Variables Of Class
Firstname = Firstname
LastName = LastName
Username = Username
Email = Email
Password = Password
End Sub
Public Shared Sub OtherUse()
End Sub
End Class
' Create New Instance
Dim Process As New Account(txtFirstName.Text, txtLastName.Text, txtUsername.Text, txtEmail.Text, txtPassword.Text)
' HERE - How Can I Catch The Early Exit From The Instance Due To Potential Missing Fields?
' Use Instance For Other Use
Process.OtherUse()
How would I catch the Exit Sub from the class in the parent form to prevent the further processing of Process.OtherUse()?
You're approaching this problem the wrong way. Validate the input first, and then once the input is valid, create a new Account using New.
Another option would be to initialize data in New without checking if it's valid or not, then have an IsValid method in that class that you would call from another class to know whether or not the messagebox should be shown.
One way or another, the Account class shouldn't be responsible for a UI concern like showing a MessageBox on the screen. And the constructor should only be responsible for constructing the object, not validating the input, because you can't "abort" a constructor. You have a reference to a new object even though you call Exit Sub.
A fourth alternative, in addition to the three mentioned by Meta-Knight:
Have the constructor throw an exception when the parameters aren’t valid.
As an aside, your use of Or, while working, is a logical error: And and Or are bitwise arithmetic operations. You want a logical operation, OrElse (there’s also AndAlso). These may seem similar to Or and And and in this particular case, both happen to work. But they are actually quite different semantically, bitwise operations are just wrong here (it’s a pity that this code even compiles. The compiler shouldn’t allow this).

VBA [classes] - how to access a previously instanciated instance of a class in another sub

I've created the instance "Lassie" of the class "Dog" within a particular sub in my program. I have also given it some useful properties, such as Lassie.Age = 7 and Lassie.HeelCapability = False.
Now I would like to access another sub and change the Lassie.HeelCapability to True.
How do I go about defining the instance "Lassie" within this new sub so it can be worked with?
All the code I have come accross goes like this:
Dim Lassie As classDog
Set Lassie = New classDog
Essentially what I am looking for is a way to import the existing instance "Lassie" into another sub, without using the keyword "New" and thereby creating a new "Lassie" (without all the properties previously given).
The errormessages I have been receiving tell me either "object required" or "object variable or with block variable not set".
Surely there is a way to do this.
Thanks in advance.
You will need to pass 'Lassie' as a parameter to your other sub.
public sub DeclareSub()
Dim Lassie as classDog
Lassie = new classDog
OtherSub Lassie
end sub
public sub OtherSub(ByRef dog as classDog)
end sub
The variable 'dog' in the subroutine 'OtherSub' refers to the same object instance as the variable 'Lassie' from 'DeclareSub'.
Pass the object in ByRef to your new Subroutine.
Sub ChangeHeel(ByRef olassie As classDog)
'change the object here, and it will be changed in the calling sub
olassie.HeelCapability = True
End Sub