I would like to know what you guys would do in this situation.
I am basically returning a data set for Person, but I would like to know the most efficient way of doing things.
Public Class TestClass
Public Shared Function returnPersonData() As Person
Dim p As New Person
p.Address = "Here and there"
p.Name = "Mike"
p.Career = "Pilot"
Return p
End Function
End Class
Person class:
Public Class Person
Public Property Name As String
Public Property Address As String
Public Property Career As String
End Class
I would then get the name by doing this in another class:
Dim name As String = TestClass.returnPersonData.Name
Dim address As String = TestClass.returnPersonData.Address
My question is this: why does it re-run the returnPersonData function every time I need to extract info the name, address and career? Why can't I just call the function once, save it in a data set, and then just reference that?
Because you are calling it twice...
Dim name As String = TestClass.returnPersonData.Name ' <--- One time here
Dim address As String = TestClass.returnPersonData.Address ' <--- An other time here
Save the person class instance
Dim currentPerson As Person = TestClass.returnPersonData
Then you can get the name or address with
Dim name As String = currentPerson.Name
Dim address As String = currentPerson.Address
You could remove those two variables and just use currentPerson all the time.
Related
I'm a little new to classes on VB.NET (and to whole OOP concept in general) so sorry in advance for my poor explanation.
I've created a class like so:
Public Class MyApp
private var1 as integer = 2
Private Function getProfile(id As Integer)
'Imaginary server request according to ID
'Following that was received:
Dim name As String = "John"
Dim age As integer = 30
End Function
End Class
I want to be able to call getProfile by using myApp.getProfile and that's something I can handle.
What I can't manage is displaying only the age or name.
Something like this:
MyApp.getProfile(4341).age
How can I achieve something like this? Like having sub-functions in a function.
To call the method that way it needs to be static (marked Shared) and public. To make it return the name and age as properties you need a class with those properties. Example:
Public Class MyApp
Public Shared Function GetProfile(id As Integer)
Dim name As String = "John"
Dim age As integer = 30
return New ServerResult(name, age)
End Function
End Class
Public Class ServerResult
Public Name as String
Public Age as Integer
Public Sub New(n as String, a as Integer)
Name = n
age = a
End Sub
End Class
Usage example:
Dim age as Integer = MyApp.GetProfile(42).Age
Another:
Dim result As ServerResult = MyApp.GetProfile(1337)
Dim info As String = String.Format("{0}, {1}", result.Name, result.Age)
Note: Making the method static is based on how you wanted to call it. You might want to create an instance of the MyApp class instead, and have a method that is not static.
Alright, I have looked through 20 pages on here and can't find what I'm looking for... I've seen it in C# and other languages.. but not Visual Basic..
Say I have a class:
Public Class Cars
Private doors as integer
Private Liters as double
Private otherStuff as string
' more code'
end class
Say I also have a Form.. an inputForm we'll call it that has numerous textboxes for users to input these characteristics. The first textbox is labeled nameTextBox. Is there any way to assign the string value of that textbox as a new car?
something to the likes of..
dim nameTextBox.value as new car
??
The fields in your class are private, so they arent of much use - no other code will be able to see those values.
Public Class Car
Public Property Make As String
Public Property Model As String
Public Property Year As Integer
' something the class may use/need but doesnt expose
Private DealerCost As Decimal
' the constructor - called when you create a NEW car
Public Sub New(mk As String, md As String)
Make = mk
Model = md
End Sub
...
End Class
By specifying only a constructor which takes params, I am saying that you cannot create a new car without specifying those properties. If the constructor takes no params, then you can create an "empty" car object and set each property individually. You can do both - called overloading - so you can create a car with or without the Make and Model at the outset.
As Public Properties, other code can examine them to see what kind of car this is.
Dim myCar = New Car("Toyata", "Corolla")
myCar.Year = 2013
myCar.Color = Color.Blue
The text used of course can come from user input:
Dim myCar = New Car(tbMake.Text, tbModel.Text)
Dim yr As Int32
If Integer.TryParse(tbYear.Text, yr) Then
myCar.Year = yr
Else
' ToDo: scold user
End If
I have the Student class in VBA (Excel) implemented as follows
Option Explicit
Private name_ As String
Private surname_ As String
Private marks_ As New Collection
Public Property Get getMean() As Single
Dim sum As Double
Dim mark As Double
Dim count As Integer
For Each mark In marks_
sum = sum + mark
count = count + 1
Next mark
getMean = sum / count
End Property
Public Property Let setName(name As String)
name_ = name
End Property
Public Property Get getName() As String
getName = name_
End Property
Public Property Let setSurname(surname As String)
surname_ = surname
End Property
Public Property Get getSurname() As String
getSurname = surname_
End Property
Then I have a main sub where I write:
Dim stud1 As New Student
stud1.setName "Andy"
I got a compile error on stud1.setName "Andy" : Invalid use of property.
I don't understand why. Any Idea, please?
Since it's a property (not method) you should use = to apply a value:
Dim stud1 As New Student
stud1.setName = "Andy"
BTW, for simplicity, you can use the same name for get and set properties:
Public Property Let Name(name As String)
name_ = name
End Property
Public Property Get Name() As String
Name = name_
End Property
and then use them as follows:
Dim stud1 As New Student
'set name
stud1.Name = "Andy"
'get name
MsgBox stud1.Name
This question already has answers here:
How do optional Parameters in Let/Get Properties work?
(3 answers)
Closed 7 years ago.
My understanding of using the Let property in a class module so far is that you set it up in the class modules like this:
Dim pName as String
Public Property Let Name(Value As String)
pName = Value
End Property
And then you after you've created an object of this class you can set this property like so:
MyObject.Name = "Larry"
Question: Is it possible to somehow enter multiple arguments into a class property? For instance:
Dim pFirstName as String, pLastName as String
Public Property Let Name(FirstName As String, LastName As String)
pFirstName = FirstName
pLastName = LastName
End Property
How would you then go about setting this property outside the class?
MyObject.Name = ??
Or is this just plain not possible to do?
I realise there already are 2 workarounds but I thought answering your original question was worth giving a shot due to the amount of views this question is receiving.
The answer to
Is it possible to have multiple arguments in the Let Property in VBA?
is
YES! It's possible.
First let's talk about the GET property. Consider this being the Class1
Private firstName as String
Private lastName as String
Public Property Get Name() As String
Name = firstName & " " & lastName
End Property
The Name property will return the full name, that's great but how to use the Let property to assign firstName & lastName in one go?
Side note: You could pass a single string separated with a special character and split it inside the body of the Let and assign the first and last names but forget that, let's get it done properly...
OK, in VBA the default Let property for the current setup would take 1 parameter and assign it to either first or last name...
Something like:
Public Property Let Name(value As String)
firstName = value
End Property
Rule: the Get takes no parameters and the Let takes one. That is very logical because the Get returns the underlying value but the Let needs to grab a value from somewhere in order to assign it to the data it's representing. Worth remembering at this point that the Let property is assigned via the = sign ie. myObject.Name = "IdOnKnuu"
we know that if we stay consistent with the above rule, theoretically we should be able to add one parameter to the Get and one more to the Let.
Let's forget the Let - comment it out for now - and add a parameter to the Get property.
Private firstName As String
Private lastName As String
Public Property Get Name(first As String) As String
Name = firstName & " " & lastName
End Property
'Public Property Let Name(value As String)
' firstName = value
'End Property
Going back to the Module1 create an instance of Class1 and type c.Name(
oh, intelli-sense expecting something? Awesome!
At this point it's worth understanding that our Get property returns first + last which are both empty at the moment, so it doesn't matter what you are going to pass to the c.Name() it will return an empty string.
Ok, let's uncomment and tweak the Let property now...
Side node: if you jump back to Module1 and type c. and don't get intelli-sense it pretty much means that something in Class1 is broken... We already know - it's the Let property that's causing it
We have added a parameter to the Get property, let's do the same with the Let property...
Public Property Let Name(first As String, value As String)
firstName = value
End Property
Let's go back to the Module1 and try to use the Let property:
Remember, how you have used the Let property before? You needed to assign it a value
c.Name = "John"
But now, your Let property is expecting an extra parameter first as String.
Why don't we try this:
c.Name("John") = "Smith"
Hey! that compiles and runs (a quick F5)
Great, let's check the results!
Debug.print c.Name("John")
Uhm... that only shows Smith in the Immediate Window (Ctrl+G)... Not exactly what we were looking for....
Going back to the Let property we notice that we are grabbing 2 values via arguments but we only make use of one of them? We have the 2 different values coming in to the function, right? Let's treat the first one as the firstName and the second one as lastName
Public Property Let Name(first As String, last As String)
firstName = first
lastName = last
End Property
Going back to Module1
Sub Main()
Dim c As New Class1
c.Name("John") = "Smith"
Debug.Print c.Name("John")
End Sub
and re-running out current code gives us what we need ... it prints John Smith but wait!!! why do we have to pass the first name in order to retrieve the full name?
Ha! The trick to this is to make the first parameters of both properties Optional
Summarising, the code:
Class1.cls
Private firstName As String
Private lastName As String
Public Property Get Name(Optional first As String) As String
Name = firstName & " " & lastName
End Property
Public Property Let Name(Optional first As String, last As String)
firstName = first
lastName = last
End Property
Module1.bas
Sub Main()
Dim c As New Class1
c.Name("John") = "Smith"
Debug.Print c.Name ' prints John Smith
End Sub
So basically the assignment of two (or more) values through the Let property is possible in VBA. The thing that may throw you off a bit is the Syntax for it but I hope my explanation in this answer has helped you understand where things come from and why.
The Get property takes an optional parameter - it's really just a dummy parameter... it's not used anywhere within the Get property but it's allowing us to get the desired Let signature and allows us to pass two parameters to it. It also grants the easy to remember c.Name syntax.
The call
Debug.Print c.Name("first")
is still possible, however the "first" parameter just acts like a dummy and has no effect on the actual underlying data. It's a dummy and has no effect on the actual data - dump it and use:
Debug.print c.Name
definitely more convenient :)
As per your comment if you would prefer to encapsulate this logic then you can use something similar to the below.
Below includes the sub and function. The function returns a Person object:
Public Sub testing()
Dim t As Person
Set t = PersonData("John", "Smith")
End Sub
Public Function PersonData(firstName As String, lastName As String) As Person
Dim p As New Person
p.firstName = firstName
p.lastName = lastName
Set PersonData = p
End Function
Person Class:
Dim pFirstName As String, pLastName As String
Public Property Let FirstName(FirstName As String)
pFirstName = FirstName
End Property
Public Property Get FirstName() As String
FirstName = pFirstName
End Property
Public Property Let LastName(LastName As String)
pLastName = LastName
End Property
Public Property Get LastName() As String
LastName = pLastName
End Property
Use as Public Sub procedure within the class to perform this:
Public Sub testing()
Dim myPerson As New Person
myPerson.SetName "KaciRee", "Software"
End Sub
Person Class:
Dim pFirstName As String, pLastName As String
Public Property Let FirstName(FirstName As String)
pFirstName = FirstName
End Property
Public Property Get FirstName() As String
FirstName = pFirstName
End Property
Public Property Let LastName(LastName As String)
pLastName = LastName
End Property
Public Property Get LastName() As String
LastName = pLastName
End Property
Public Sub SetName(FirstName As String, LastName As String)
pFirstName = FirstName
pLastName = LastName
End Sub
I'm moving code from code-behind to classes and run into a problem. I have a method which makes a string (an html invoice). In the method a final amount is created. I want to make a class called Invoice which will have the method "CreateInvoice" which will return a string and I also want to set the finalCharge property of the object. I have all the heavy lifting done but it's setting up the class is the part I'm having troubles with
Public Class Invoice
Public finalCharge As Double
Public invoiceString As String
Public billingId As Integer
Public clientID As Integer
Public Shared Function CreateInvoice(ByVal bill_id As Integer, ByVal client_id As Integer) As String
... 'create string invoice
... 'tally final charge
End Function
'On my code-behind page.
dim y as string
dim x as Invoice
y = x.CreateInvoice(1225,8855) <-- this line doesn't work.
Thank you for helping be get sorted out!
It's a Shared function - which means you don't need (or want) an instance of the class to use it. You should call it like:
Invoice.CreateInvoice(1225, 8855)
That said, I'm not entirely sure it should be Shared to begin with, since you also state:
[I]...want to set the finalCharge property
Since a Shared function can only access Shared properties (since there is no instance), you may really want it to be an instance function:
Public Class Invoice
Public finalCharge As Double
Public invoiceString As String
Public billingId As Integer
Public clientID As Integer
Public Function CreateInvoice(ByVal bill_id As Integer, ByVal client_id As Integer) As String
... 'create string invoice
Me.finalCharge = ... 'tally final charge
End Function
End Class
In which case, you'd call it like:
Dim x as New Invoice()
Dim y as String = x.CreateInvoice(1225, 8855)
Dim finalCharge as Double = x.finalCharge