How to pass the values to other function - vb.net

I am trying to do this using VB.NET
I want to use a function in my codes like the following:
'Read all the content from the text file - Function One
'Write to SQL Table - Function Two
I am reading content of the text file form the Function one, but I also want to pass the values to function two.
I have more than 25 parameters of passing from function one to function two.
It is a simple question. Anyone can help to solve this issue.

You haven't give any sample so it's hard to help. You should definitely learn how to use classes. Group your variable together that have the same context.
Class Student
Public Property Age As Integer
Public Property Name As String
' ...
End Class
When loading your data, you put it in an object.
Dim student As New Student
student.Age = 20
student.Name = "Bob"
After that you just need to pass the class as parameter to your function
Func(student)
Sub Func(ByVal student As Student)
End Sub

Related

list.add for a list (of ClassType) not adding to list - no errors reported

;tldr ...Orders.Add(order class variable) does not add a record the the Orders list, but also does not generate any errors.
I'll try to make a long story short and I apologize for the book you are about to read - I'm coming back to VB after spending a while in Python and C#. There is a bit of an explanation before any of the code...
I have a command-line exe program that at its base is working fine. We get 4 differently formatted CSV files that the program reads, and based on the file name, runs them through a parser that pulls the text information out of the file and populates a Public Class that in turn calls a function to populate a database table. The class is a single instance class named DataRecord. This program works absolutely fine (and has for well over 18 months now). It reads one line, if a batch# doesn't exist it creates one, and post the data class to the DB, and loops thru the file one line at a time doing so.
Also, their are 2 files to this program - the OrderAutomation main program file and the DBAccess file (which handle the DataRecord Class and all the various DB calls to verify information and to push the record into the database tables.
It used to be for all 4 file types, each file was a single batch all from a single region (data delimiters) - but now 1 of the file types will start sending multiple regions in a single file (and not necessarily in order) - so I need to modify the program that if its this 1 file type, it goes through the entire file, grouping each region together (each region will get its own Batch#).
I figured this would be fairly simple. I'd create an additional class (VTLData) that has some basic region separation data, and then a list of the DataRecord class. That looks like this:
Public Class VTLData
Public Property Locality As String
Public Property ARProvider As String
Public Property CORegion As String
Public Property BatchID As String
Public Property ProviderZip As String
Public Property IsValidRegion As Boolean
Public Property Orders As List(Of RecordData)
Public Sub New(s As String)
Locality = s
ARProvider = "00000000"
CORegion = "XX"
BatchID = "VXX-00000"
ProviderZip = "00000"
IsValidRegion = True
Orders = New List(Of RecordData)
End Sub
End Class
Like I said earlier - the RecordData class has no changes and is working fine.
There is a point in the program where I know this is the new file type (basically the region information has gone from a zip code to a set of specific text values) so when I test for that, if it's new, I set a boolean NewVTL to true. Because the file can contain more than one region, I have a VTLList property that is a List (of VTLData). I make sure I don't already have a Region in this list already - and if so, reference that index in the list.
When I get to the point where the program normally processes the record, I added the following (VTLIndex is the index variable for the list - at this time its value is 0):
If NewVTL Then
DB.data.CanProcess = CanProcessLine
DB.VTLList(VTLIndex).Orders.Add(DB.data)
Else
. - the old processing method
.
.
End If
I have a watch set for the VTLList(VTLIndex).Orders.Count value - that is at 0 when that line is reached, and stays at 0 when that line is processed.
I've tried creating a Push procedure in the VTLData class where you pass in the db.data class values, create a new instance of the record data and try to assign it that way
Public Sub PushOrder(item As RecordData)
Dim order As New RecordData
With order
.ARProviderNumber = ARProvider
.OrderID = item.OrderID
.AcctSuffix = item.AcctSuffix
.BatchID = BatchID
. - the 70 some other items in the recorddata class
.
.
End With
Orders.Add(order)
End Sub
This would also run without error, but not increase the count of .Orders.Count value.
I'm assuming its something stupid that I'm missing and I'm hoping someone can filter through all this and be like "You forgot to do blah..."
The only other thing I can think of is the do that Push function, but start it with Orders.Add(new RecordData) - and then modify the individual values through an index (.Orders(0).ARProviderNumber = data.ARProviderNumber... etc)
But based on other things I've done in VB - this should be working - I'm sure I'm just missing something...
So thanks for reaching this point - and thank you for letting me know what mistake I've made!!!
So the only way I got this to work for me was to create a Function in the VTLData class that did the following:
Public Function PushOrder(item As RecordData) As Boolean
Dim i As Integer = Orders.Count
Orders.Add(New RecordData)
With Orders(i)
.ARProviderNumber = ARProvider
.OrderID = item.OrderID
.AcctSuffix = item.AcctSuffix
.
. - more fields being populated
.
End With
If Orders.Count <= i Then Return False
Return True
End Function

Sorting a SortedDictionary by key length in Visual Basic?

I'm writing a script that anonymizes participant data from a file.
Basically, I have:
A folder of plaintext participant data (sometimes CSV, sometimes XML, sometimes TXT)
A file of known usernames and accompanying anonymous IDs (e.g. jsmith1 as a known username, User123 as an anonymous ID)
I want to replace every instance of the known username with the corresponding anonymous ID.
Generally speaking, what I have works just fine -- it loads in the usernames and anonymous IDs into a dictionary and one by one runs a find-and-replace on the document text for each.
However, this script also strips out names, and it runs into some difficulty when it encounters names contained in other names. So, for example, I have two pairs:
John,User123
Johnny,User456
Now, when I run the find-and-replace, it may first encounter John, and as a result it replaces Johnny with User123ny, and then doesn't trigger Johnny.
The simplest solution I can think of is just to run the find-and-replace from longest key to shortest. To do that, it looks like I need a SortedDictionary.
However, I can't seem to convince Visual Basic to take my custom Comparer for this. How do you specify this? What I have is:
Sub Main()
Dim nameDict As New SortedDictionary(Of String, String)(AddressOf SortKeyByLength)
End Sub
Public Function SortKeyByLength(key1 As String, key2 As String) As Integer
If key1.Length > key2.Length Then
Return 1
ElseIf key1.Length < key2.Length Then
Return -1
Else
Return 0
End If
End Function
(The full details above are in case anyone has any better ideas for how to resolve this problem in general.)
I think it takes a class that implements the IComparer interface, so you'd want something like:
Public Class ByLengthComparer
Implements IComparer(Of String)
Public Function Compare(key1 As String, key2 As String) As Integer Implements IComparer(Of String).Compare
If key1.Length > key2.Length Then
Return 1
ElseIf key1.Length < key2.Length Then
Return -1
Else
'[edit: in response to comments below]
'Return 0
Return key1.Compare(key2)
End If
End Function
End Class
Then, inside your main method, you'd call it like this:
Dim nameDict As New SortedDictionary(Of String, String)(New ByLengthComparer())
You might want to take a look (or a relook) at the documentation for the SortedDictionary constructor, and how to make a class that implements IComparer.

Passing a variable to another form, from another when invoked by an action

I might be making this more complicated than I have to.
I have a form in Visual Basic that is adding a row of data to an Access Database.
What will happen (or rather what I would like to happen) is that when the form is created, a row will be added to said database. Once that row is added, I want to have another form open (called NewWindowA) which will pull information on that database that is related to the ID of the row that was created from the first form.
I know that in NewWindowA I need to have the form load the values on Load. But my question is: How do you pass a value to a new window that's invoked by some action?
You can make a constructor of newwindowa that takes the id Like :
Public Sub New(ByVal ID as Integer)
'Do stuff
End Sub
Another Choice you have that you make a global property in newwindowa
Private _ID As Integer
Public Property ID() As Integer
Get
Return _ID
End Get
Set(ByVal value As Integer)
_ID = value
End Set
End Property
When you want to call neweindowa:
Dim n as New NewWindowA
n.ID = 12312
n.Show()
just create a public sub in the new form possibly called (prepareUI)
that new sub has the parameter you want to pass as its parameters
access the controls and fill them .
in the original form
instantiate the new form and call the show method
and then call the sub prepareUI sending the paremateres you need

Should I create individual properties in a class or just a method to set the values?

I am learning vb.net and I am having trouble wrapping my head around the following...
I can create several properties of a custom class and get/set values or I can create a method to set them all at once. If each property is going to allow read and write should I just make a method to assign values all at once? I assume that I am missing a very important piece here. Example:
I can create 2 properties:
Public Class Employee
Public Property LastName as string
Get
Return strLastName
End get
Set(ByVal value as string)
strLastName= value
End Set
End Property
Public Property FirstName as string
Get
Return strFirstName
End get
Set(ByVal value as string)
strFirstName= value
End Set
End Property
End Class
or I can create a method:
Public Class Employee
Public Sub AddEmployee(ByVal strLastName, ByVal strFirstName)
LastName = strLastName
FirstName = strFirstName
End Sub
End Class
I apologize for such a noob question, but any insight is greatly appreciated. thank you!
If you only have a single method, you will have to use it even if you only want to change the value of a single field.
Additionally, in such a method, if you need to validate the input, you will need to write quite a lot of code for validation that is not relevant to all of the fields.
If values must be updated together, use a method to update them together and do not provide setters.
The reality of things is that how to do this depends on what you are modelling in your class. There are no hard and fast rules that say that properties are better than methods or vice versa.
There is no reason not to support both properties and a method that sets multiple properties.
Commonly, a constructor is used to create an instance of the class and to set some properties. In VB, naming a class method "New" defines it as a constructor. In your example, if you rename your AddEmployeee method to New, you will have a perfectly fine constructor. Then you program can create new instances as such:
Dim emp1 as New Employee("Burdell", "George")

DNN Dal+ - retrieve individual info class collection items (vb.NET)

I can't seem to find any answers that work. Here's the setup:
Info class:
Public Class ProductStageInfo
Private _ProductNumber As String
Private _ProductReference As String
Public Sub New()
End Sub
Public Property ProductNumber() As String
Get
Return _ProductNumber
End Get
Set(ByVal Value As String)
_ProductNumber = Value
End Set
End Property
End Class
and so on; I have four class declarations in the info class, the one above has fifteen different items - product number, product reference, product name, and so forth. The other's are catalogue classifications, which 'stage' of production the product is in, quality assurance questions; etc.
Then in the Controller class for DNN, I have those various info classes filled via queries to the DB DNN was deployed on; example:
Public Shared Function LoadStages(ByVal ProductNumber As String) As List(Of ProductStageInfo)
Return CBO.FillCollection(Of ProductStageInfo)(CType(DataProvider.Instance().ExecuteReader("Product_LoadStages", ProductNumber), IDataReader))
End Function
and everything works so far, I can fill a datalist using <%# DataBinder.Eval(Container.DataItem, "ProductNumber" %> and in code behind:
Dim ProductStageList As List(Of ProductStageInfo)
ProductStageList = ProductController.LoadStages(ProductNumber)
ProductStageDataList.DataSource = ProductStageList
ProductStageDataList.DataBind()
so far, so good...
but now I need to allow individuals to 'create' stages, and one of the business reqs' is that people shouldn't be able to create, for example, a delivery stage before a packaging stage.
So, how do I go about 'finding' a product number, product reference, stage number, within a collection? I thought I could fill the collection with all the stages of a certain product number, and then do an if/then stage = 0 found, stage > 5 found, etc.
If ProductStageList.Contains(strProductNumber) then
end if
gives error value of type string cannot be converted to namespace.ProductStageInfo; same thing for ProductStageList.Find...
maybe I just don't understand the whole collection/index/thing. All the examples I've found are regarding single dimension collections - 'how to find name within this collection', and the responses use strings to search through them, but somehow the Info class is being treated differently, and I'm not sure how to translate this...
any hints, tips, advice, tutorials.... appreciate it :)
thanks!
Pretty sure I just found the answer by reviewing another module; basically I need to create an empty object instead of a list object of the same class and use the two to iterate through using for/each, etc.
Dim objStages As ProductStagesInfo
Dim intStages, StageSelected As Integer
Dim intStageOption As Integer = -1
Dim blnValid As Boolean = True
Dim ProductChosen As String = lblStagesCNHeader.Text
Dim ProductStageList As List(Of ProductStagesInfo) = ProductController.LoadStages(ProductChosenNumber)
For intStages = 0 To StageList.Count - 1
objStages = StageList(intStages)
intStageOption += 1
Select objStages.StageSetNumber
Case "0"
Next
objStages._ provides me the ability to get the data I needed to do the business logic
<.<
seems so simple once you see it, wish I could just store it all in my brain
blah!