How to declare global variable that reads the last line of richtextbox - vb.net

I have this code
Dim totalLines As Integer = frmTerminal.rtbDisplay.Lines.Length
Dim lastLine As String = frmTerminal.rtbDisplay.Lines(totalLines - 1)
That code effectively reads the last line of my richtextbox and it is very useful to all of my functions.
Problem:
Because most of my functions rely on detecting the last line of a richtextbox I would like to declare it as global and public variable. But whenever I make it global and public it result in an error stating that
An unhandled exception of type 'System.TypeInitializationException' occurred in xxxxxx.exe
It means something like I want to count the lines of a not yet created richtextbox, so my question is how do I effectively get the lastline of a richtextbox in a global and public way?

You could try using a public property
Public ReadOnly Property LastLine() As String
Get
Dim returnValue As String = String.Empty
If rtbDisplay.Lines.Count > 0 Then
returnValue = rtbDisplay.Lines(rtbDisplay.Lines.Count - 1)
End If
Return returnValue
End Get
End Property

While declaring it as public variable may not help, you can declare it as a public property in your class.
Public ReadOnly Property LastLine() As String
Get
Return frmTerminal.rtbDisplay.Lines(frmTerminal.rtbDisplay.Lines.Length - 1)
End Get
End Property

Related

How to set 2 arguments on Let function in a class in vba (for excel)?

I am creating a Class in vba (for excel) to process blocks of data. After some manipulation of a text file I end up with blocks of data (variable asdatablock() ) which I want to process in a For Loop
I created my own Class called ClDataBlock from which I can get key data by a simple call of the property required. 1st pass seems to work and I am now trying to expand my Let function to 2 argument but it’s not working. How do I specify the 2nd argument?
Dim TheDataBlock As New ClDataBlock
For i = 0 to UBound(asdatablock)
asDataBlockLine = Split(asdatablock(i), vbLf) ‘ split block into line
TheDataBlock.LineToProcess = asDataBlockLine(5) ‘allocate line to process by the class
Dvariable1 = TheDataBlock.TheVariable1
‘and so on for the key variables needed base don the class properties defined
Next i
In the Class Module the Let function takes 2 arguments
Public Property Let LineToProcess(stheline As String, sdataneeded As String)
code extract of what I am looking at -
'in the class module
Dim pdMass As Double
Private pthelineprocessed As String
Public Property Let LineToProcess(stheline As String, sdataneeded As String)
pthelineprocessed = DeleteSpaces(Replace(stheline, vbLf, ""))
Dim aslinedatafield() As String
Select Case sdataneeded
'THIS IS AN EXTRACT FROM THE FUNCTION
'THERE ARE AS NUMBER OF CASES WHICH ARE DEALT WITH
Case Is = "MA"
aslinedatafield() = Split(pthelineprocessed, " ")
pdbMass = CDbl(aslinedatafield(2))
End select
End function
Public Property Get TheMass() As Double
TheMass = pdMass
End Property
'in the "main" module
Dim TheDataBlock As New ClDataBlock
For i = 0 to UBound(asdatablock)
TheDataBlock.LineToProcess = asDataBlockLines(5) 'Need to pass argument "MA" as well
dmass = TheDataBlock.TheMass
'and so on for all the data to be extracted
Next i
When a Property has 2 or more arguments, the last argument is what is getting assigned. In other words, the syntax is like this:
TheDataBlock.LineToProcess("MA") = asDataBlockLine(5)
This means you need to change the signature of your property:
Public Property Let LineToProcess(sdataneeded As String, stheline As String)

VBA assigning to array

In the code snippet I create an array of string and want to assign it to another.
Dim rfms(0) As String
rfms(0) = "X"
The next line is not working
Me.SelectedRfms = rfms
But when I created the next function:
Function ReturnTheArrayInParamter(p() As String) As String()
ReturnTheArrayInParamter = p
End Function
This is working:
Me.SelectedRfms = ReturnTheArrayInParamter(rfms)
The definition of Me.SelectedRfms is the next:
Private pSelectedRfms() As String
''''''''''''''''''''''
' SelectedRfms property
''''''''''''''''''''''
Public Property Get SelectedRfms() As String()
SelectedRfms = pSelectedRfms
End Property
Public Property Let SelectedRfms(value() As String)
pSelectedRfms = value
End Property
Can you explain why the first one is not working and why the second is working.
You cannot assign an array declared with a fixed size to a property, use:
ReDim rfms(0) As String
(The indirect function does not use a fixed size array)

Passing Enum Array or list to Function

I want to compare an enum array to single enum instance.
Introduction
I have a class with an enum type array\list
Public Enum InvalidEmailType
Multiple_Updates
Period_Before_At_Sign
Missing_Dot_Com
End Enum
Public Class CustomerClass
Public CustomerName As String
Public ErrorTypeList = [Enum].GetValues(GetType(InvalidEmailType))
Public ErrorDescription As String
End Class
Depending on what values are added to the list, I want to run specific code.
In order to do this I compare the entire list to a single instance:
If UpdateCustomer.MatchErrorType(customer.ErrorTypeList, InvalidEmailType.Trailing_Period) = True Then
'Run Code
End If
Inside the function I compare the entire list against the single instance.
In other words, I loop through the entire list inside the class and check if the value is there:
Public Shared Function MatchErrorType(CustomerErrortypeList As List(Of InvalidEmailType), EmailError As InvalidEmailType) As Boolean
MatchErrorType = False
Dim Found As InvalidEmailType = CustomerErrortypeList.Where(Function(match) match.ToString = EmailError.ToString).OrderByDescending(Function(match) match.ToString).FirstOrDefault()
If Found > 0 Then
MatchErrorType = True
End If
End Function
Here is the problem:
How do I declare the array\list in the function parameters?
List(Of InvalidEmailType) does not work, as I get a cast error
Unable to cast object of type 'EmailValidationReport.InvalidEmailType[]' to type 'System.Collections.Generic.List`1[EmailValidationReport.InvalidEmailType]'
Set ErrorTypeList to a List(of InvalidEmailType) instead of array.
Public ErrorTypeList = [Enum].GetValues(GetType(InvalidEmailType)) _
.Cast(of InvalidEmailType)().ToList()
or
Dim list = customer.ErrorTypeList.Cast(of InvalidEmailType)().ToList()
If UpdateCustomer.MatchErrorType(list, InvalidEmailType.Trailing_Period) Then
'Run Code
End If
Since you aren't doing anything that is specific to List or Array, you can make your method signature take in an IEnumerable instead of a List. This should be able to handle both List and Array (and a few more types as well).
Public Shared Function MatchErrorType(CustomerErrortypeList As IEnumerable(Of InvalidEmailType), EmailError As InvalidEmailType) As Boolean
Dim Found As InvalidEmailType = CustomerErrortypeList.Where(Function(match) match.ToString = EmailError.ToString).OrderByDescending(Function(match) match.ToString).FirstOrDefault()
MatchErrorType = (Found > 0)
End Function

Performance Enum vs class?

i found few new style (for me) to "define" output from select query.
Private Enum Item
ID
Item
Description
End Enum
Private Class Item
Private ID as String
Private Item as String
Private Desc as String
End Class
I 'm thinking of using either one of them. by using class i does not need to re-cast the element type before i display. but Enum seems like easier to understand.
Anyone have some suggestion how to decide?
Enum members are numeric (usually integer, but can be long). But they are not variable and do not change at runtime. So your enum equates to:
Private Enum Item
ID = 0
Item = 1
Description = 2
End Enum
If you want Description to be a string, then a class is a better idea. Enums are used to reference or index something or limit/define a selection. Like:
Public Property Stooge As Stooges
Friend Enum Stooges
Larry
Moe
Curly
Shemp
CurlyJoe
End Enum
The Stooge Property must be one of those values. in code it will show you the text ("moe") but store and integer (1). users will be shown the text in drop downs etc.
You can associate a description with Enum constants:
Public Enum Stooges
<Description("Larry - Funny one")> Larry
<Description("Moe - 'Smart' One")> Moe
<Description("Curly - Sore One")> Curly
<Description("Shemp - One with bad haircut")> Shemp
<Description("CurlyJoe - Last one")> CurlyJoe
End Enum
To get the description for a single one:
Public Shared Function GetDescription(ByVal EnumConstant As [Enum]) As String
Dim fi As Reflection.FieldInfo =
EnumConstant.GetType().GetField(EnumConstant.ToString())
Dim attr() As DescriptionAttribute =
DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute),
False), DescriptionAttribute())
If attr.Length > 0 Then
Return attr(0).Description
Else
Return EnumConstant.ToString() ' return enum name if no Descr
End If
End Function
Usage: str = enumHelper.GetDescription(Stooge.Moe) (enumHelper is the name of the calss where the static/shared function resides).
To get a String Array of all the descriptions:
Public Shared Function GetDescriptions(ByVal type As Type) As String()
Dim n As Integer = 0
Dim enumValues As Array
Try
enumValues = [Enum].GetValues(type)
Dim Descr(enumValues.Length - 1) As String
For Each value As [Enum] In enumValues
Descr(n) = GetDescription(value)
n += 1
Next
Return Descr
Catch ex As Exception
MessageBox.Show(ex.Message)
Return Nothing
End Try
End Function
Usage: Dim strEnum As String() = enumHelper.GetDescriptions(GetType(Stooges))
From your question, what you really mean is Struct vs Class. I would default to creating a class. The main reason to use a struct vs a class, is when you need value semantics -- assignment/parameters copies the bits, not a pointer. This is fairly rare in my experience. Unless you have a compelling reason (and you know the difference), go with a class.

Variable Value Passing to another Form, VB.NET

I do have Two Public Variables, each are from two different forms..
Form1.VB
Public UserNo As String
Form2.VB
Public MyUserNo As String
On my Form2.VB File, I assign value to the UserNo of Form1.VB
Form1.UserNo = MyUserNo
Whenever I access the Form1.VB, the Value of the MyUserNo got empty, What should I do? Both Forms are not closed.
I also tried to re-assign the value when I need to use it on the Form1.VB
UserNo = Form2.MyUserNo
First Correct is Syntax is:
Form1.VB
Public UserNo As String
Form2.VB
Public MyUserNo As String
In Form1
UserNo=Form2.MyUserNo
Second Thing:
First you should store some value in MyUserNo before storing it into UserNo.
That's why you are getting empty value.
Make the variable static/Shared and try again,it should work.
You can have more than one instance of a form, you know. Forms are objects, just like anything else. You need a variable in each form to hold a reference to the instance of each form that you are using.
If you don't call InitializeComponent(), your complete GUI is not going to render.
...
InitializeComponent()
Form1.UserNo = MyUserNo
...
Try this:
[Form1.UserNo = form2.MyUserNo]
it work
add it to form what you want value in next form
Function getvariable()
Return (VARIABLE)
End Function
In next form to get VARIABLE
VARIABLE2 = Form.getvariable()
Use variable value as Public
For Example
In Form1:
Public Str1 as String
So in Form2 you can use:
Str2=Form1.Str1
'In frmMain i Start frmBase
Dim f As New frmBase
f.Text = "New caption for frmBase"
f.ShowDialog(Me)
'in frmBase i read and write a textbox
Dim str As String = CType(Me.Owner, frmMain).txtRicetta.Text
Console.WriteLine(str)
CType(Me.Owner, frmMain).txtRicetta.Text = "12345"
Console.WriteLine(CType(Me.Owner, frmMain).txtRicetta.Text)
What you need to do is create your variables in a module as private, then generate some assessors for them.
Example:
Module modVariables
Private strUserNoSTR as String = New String(String.Empty)
Public Property getUserNoSTR() As String
Get
Return strUserNoSTR
End Get
Set(ByVal strUserNo As String)
strUserNoSTR = strUserNo
End Set
End Property
Private strMyUserNoSTR As String = New String(String.Empty)
Public Property getMyUserNoSTR As String
Get
Return strMyUserNoSTR
End Get
Set(ByVal strMyUserNo As String)
strMyUserNoSTR = strMyUserNo
End Set
End Property
End Module
After you generate the getter and setter public methods you can notice that your two private variables are within them, when you create the variables they are accessible from any form.
The reason why you keep losing the variables value is because when you try to access its value from another form (basically you're calling it from another class) the compiler has to create a new instance of that variable and when that happened the variable is set back to its original value which is of type empty string. Calling them from a module keeps them from being re-instantiated.
How To Use Them:
To get the value of strMyUserNo you call the getter of strMyUserNoSTR:
TextBox.Text = getMyUserNoSTR
To set the value of strMyUserNoSTR:
getMyUserNoSTR = someValuePlacedInThisVariable 'This sets it's value.
TextBox.Text = getMyUserNoSTR 'Now it's value is someValuePlacedInThisVariable.