How to get each value in an array and show it in a listbox - vb.net-2010

Hi I am new to VB and I have problems with using array. My code is like that.
This is class FindFactorsObject.vb
Public Sub FindFactors()
count = 0
temp = Convert.ToInt32(Math.Sqrt(_x))
For i As Integer = 1 To temp
If _x Mod i = 0 Then
ReDim array(count)
array(count) = i
count += 1
End If
Next
So I created an array and stored the results. Now I want to display each value in my array in Form.vb and if it is possible can somebody teach me how to make delay for each of the displayed value. Thanks very much

Always declare your variables, if possible to their exact types, you think they will take care of. When you say 'Now I want to display each value in my array in Form.vb' I understood literally: in the Form so, we will print them on your form
Public Sub FindFactors(_x As Integer)
Dim temp As Integer = Convert.ToInt32(Math.Sqrt(_x))
Dim l As New List(Of Integer)
For i As Integer = 1 To temp
If _x Mod i = 0 Then
l.add(i)
End If
Next
Dim pf As New PointF(20, 20)
For Each i As Integer In l
creategraphics.drawstring(i.ToString, New font(font.fontFamily, 24), brushes.cadetblue, pf)
pf = New PointF(pf.X, pf.Y + 30)
Next
End Sub

Related

Fill in missing numbers in different lists twice. ArgumentOutOfRangeException

I need your help to prepare data. I am reading a byte array. I make bytes to unsigned integers. I read in different blocks of that array and write the UInt32s in 5 lists in total. The data has been stored compressed; that is, some spaces are missing and I need to fill them up. To make it clear, I made a compilable test project for you and wrote the data into an excel file.
This is the original data. From the left to the right: Sizes, Addresses, Indexes, Number_of_items, Description
You can see that in column C the 2, 3, and 4 are missing. So I select columns C through E, and move them down 3 rows. I fill the gaps with 2, 3, 4 in column C and 1, 1, 1 in the other two columns.
I do this until I reach the end of column B. Columns B, C, D, and E must have the same length.
Where I have a little problem
I fail because a While or For loop evaluates the List.Count property only once. That is, if I add something to a list within the loop, the loop doesn't run often enough. I've provisionally worked around this by writing While True and catching an OutOfRangeException. Maybe someone has a better idea; or even an idea that completely replaces my approach :D
Step № 2
If a row has a 2 in column D, I select columns B through E below the 2, and move the contents down one row (only one, because the difference is 1).
I want to do this until I get to the bottom of the table. This will make all columns the same length.
Again, I have the problem that I use While True and go out using an exception. Does anyone have a better idea?
FormMain.vb
Public NotInheritable Class FormMain
Private Sizes As New List(Of UInt32) From {
58_355UI,
20_270UI,
4_830UI,
4_443UI,
25_177UI,
8_844UI,
4_101UI,
4_200UI,
14_991UI,
12_639UI,
12_894UI,
14_165UI,
12_954UI,
26_670UI,
7_388UI}
Private Addresses As New List(Of UInt32) From {4_323UI, 62_706UI, 83_646UI, 88_935UI, 93_883UI, 128_259UI, 132_718UI,
137_254UI, 152_590UI, 178_485UI, 193_022UI, 206_718UI}
Private Indexes As New List(Of UInt32) From {1UI, 5UI, 6UI, 9UI, 10UI, 12UI}
Private NumberOfItems As New List(Of UInt32) From {1UI, 2UI, 1UI, 2UI, 1UI, 2UI}
Private Description As New List(Of UInt32) From {1UI, 1UI, 1UI, 1UI, 1UI, 1UI}
Private Sub ButtonStart_Click(sender As Object, e As EventArgs) Handles ButtonStart.Click
Dim RopD As New Reprocessing_of_parsed_data(Sizes, Addresses, Indexes, NumberOfItems, Description)
RopD.Fill_gaps()
End Sub
End Class
Reprocessing_of_parsed_data.vb
Public NotInheritable Class Reprocessing_of_parsed_data
Public Property Sizes As New List(Of UInteger)
Public Property Addresses As New List(Of UInteger)
Public Property Indexes As New List(Of UInteger)
Public Property Number_of_items As New List(Of UInteger)
Public Property Description As New List(Of UInteger)
Public Sub New(sizes As List(Of UInt32), addresses As List(Of UInt32), indexes As List(Of UInt32), number_of_items As List(Of UInt32), description As List(Of UInt32))
Me.Sizes = sizes
Me.Addresses = addresses
Me.Indexes = indexes
Me.Number_of_items = number_of_items
Me.Description = description
End Sub
Public Sub Fill_gaps()
Dim counterForAddressesList As Integer = 0
'Dim ListCount As Integer = Indexes.Count - 2
Dim i As Integer = 0
While True 'i < ListCount - 2
Try
Dim delta As Integer = CInt(Indexes(i + 1) - Indexes(i)) - 1
Dim number As UInt32 = Indexes(i)
While delta > 0
number += 1UI
counterForAddressesList += 1
Indexes.Insert(CInt(number) - 1, number)
Number_of_items.Insert(CInt(number) - 1, 1UI)
Description.Insert(CInt(number) - 1, 1UI)
delta -= 1
'ListCount += 1
End While
counterForAddressesList += 1
i += 1
Catch ex As ArgumentOutOfRangeException
Exit While
End Try
End While
' Step 2
Dim j As Integer = 0
While True
Try
If Number_of_items(j) > 1UI Then
Dim delta As Integer = CInt(Number_of_items(j)) - 1
While delta > 0
Addresses.Insert(j + 1, UInteger.MaxValue)
Indexes.Insert(j + 1, UInteger.MaxValue)
Number_of_items.Insert(j + 1, UInteger.MaxValue)
Description.Insert(j + 1, UInteger.MaxValue)
delta -= 1
j += 1
End While
End If
j += 1
Catch ex As ArgumentOutOfRangeException
Exit While
End Try
End While
End Sub
End Class
It is never a good idea to catch an index out of bounds exception in a Try-Catch-statement. Only conditions you are not in control of (often I/O errors) should be handled at runtime. An index being out of bounds is a design error and must be fixed at design time.
I extracted the two steps from Sub Fill_gaps into two new methods to make the code easier to read and test.
Public Sub Fill_gaps() ' A better name would be "Decompress"
PrintTable() 'For testing
FillGaps()
PrintTable() 'For testing
AddMissingNumberOfItems()
PrintTable() 'For testing
End Sub
I also added a method PrintTable for testing
Private Sub PrintTable()
Console.WriteLine()
Console.WriteLine($" A B C D E")
For i = 0 To Sizes.Count - 1
Dim A = Sizes(i)
Dim B = If(i < Addresses.Count, Addresses(i), 0UI)
Dim C = If(i < Indexes.Count, Indexes(i), 0UI)
Dim D = If(i < NumberOfItems.Count, NumberOfItems(i), 0UI)
Dim E = If(i < Description.Count, Description(i), 0UI)
Console.WriteLine($"{A,10}{B,10}{C,10}{D,10}{E,10}")
Next
End Sub
Step 1: fill the gaps (the method is self-explanatory):
Private Sub FillGaps()
' Fill gaps in columns C, D and E.
' The number of Addresses B indicates the total number of indexes.
' Append empty items to C, D and E until the list counts matches the
' expected total number of indexes.
Dim originalIndexCount = Indexes.Count 'Save original count
Do While Indexes.Count < Addresses.Count
Indexes.Add(CUInt(Indexes.Count + 1)) ' Make index 1-based
NumberOfItems.Add(1)
Description.Add(1)
Loop
'Move the rows to where the index indicates.
'We do it backwards to not overwrite existing items.
For i As Integer = originalIndexCount - 1 To 0 Step -1
Dim targetIndex = CInt(Indexes(i)) - 1 ' Subtract 1, indexes are 0-based
If targetIndex <> i Then
' Copy to target position
Indexes(targetIndex) = Indexes(i)
NumberOfItems(targetIndex) = NumberOfItems(i)
Description(targetIndex) = Description(i)
'Clear resp. initialize old row
Indexes(i) = CUInt(i + 1) ' Make index 1-based
NumberOfItems(i) = 1
Description(i) = 1
End If
Next
End Sub
Step 2:
Private Sub AddMissingNumberOfItems()
' Insert empty rows after items with NumberOfItems > 1.
' We do it backwards to not mess up our indexes.
For i As Integer = Indexes.Count - 1 To 0 Step -1
For k As UInteger = 2 To NumberOfItems(i)
Addresses.Insert(i + 1, 0)
Indexes.Insert(i + 1, 0)
NumberOfItems.Insert(i + 1, 0)
Description.Insert(i + 1, 0)
Next
Next
End Sub
If you use the following test list for the descriptions, you will better see which rows have been moved or added
Private Description As New List(Of UInt32) From {2UI, 3UI, 4UI, 5UI, 6UI, 7UI}

create 1000, 8-character random ID's, all unique and display in a text box

enter image description hereWrite a program to display 1000 8-character random user IDs in a text box after you click a button. Make sure the program verifies that none of the IDs are identical. Each userid should include a mixture of alphabetic characters and numbers.
What I have so far, which could be enough to get by as a random ID generator alone, but it does not loop 1000 times to be displayed in the label, and doesn't check for repeated ID's.
Public Class Form1
Private Sub btnGenerateRandomID_Click(sender As Object, e As EventArgs) Handles btnGenerateRandomID.Click
Dim rand As New Random
Dim char1 As String
Dim char2 As String
Dim char3 As String
Dim char4 As String
Dim char5 As String
Dim char6 As String
Dim char7 As String
Dim char8 As String
char1 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
char2 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
char3 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
char4 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
char5 = rand.Next(0, 9)
char6 = rand.Next(0, 9)
char7 = rand.Next(0, 9)
char8 = rand.Next(0, 9)
lblRandomId.Text = char1 + char2 + char3 + char4 + char5 + char6 + char7 + char8
End Sub
End Class
Thanks.
EDIT:
Public Class Form1
'Write a program to display 1000 8-character random user IDs in a text
'box after you click a button. Make sure the program verifies that none Of the IDs are identical.
'Each userid should include a mixture Of alphabetic characters And numbers.
Private Sub btnGenerateRandomID_Click(sender As Object, e As EventArgs) Handles btnGenerateRandomID.Click
Dim strChar As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
Dim rand As New Random
Dim strID As String = ""
For count_ids As Integer = 0 To 999
For count_chars As Integer = 0 To 7
strID += strChar(rand.Next(0, 62))
Next count_chars
lblRandomId.Text = strID
Next
End Sub
End Class
Here is the actual question "Q. Write a program to display 1000 8-character random user IDs in a text box after you click a button. Make sure the program verifies that none of the IDs are identical. Each userid should include a mixture of alphabetic characters and numbers.
Explain your program in your essay, with screenshots. Include a paragraph on the random number generator used in Visual Basic, and answer the question: how should the random number generator be best seeded?"
First of all, Welcome to StackOverflow,
From what i understand from your post you want to generate 1000 8 Character long Unique ID's
First of all we declare our variables
Dim Characters As String = "AZERTYUIOPQSDFGHJKLMWXCVBN0123456789" 'Declare All Characters on one string
Dim IDsList As New List(Of String) With {.Capacity = 1000} 'You can limit the capacity to 1000
Dim Id As String = ""
Dim Rand As New Random
Now we begin to genearte ID's and add them to IDsList using a nested loop
For i As Integer = 0 To 999 'This is a Zero Based Index so 999 is actually 1000
For _i As Integer = 0 To 7 'This also means 7 is 8
Id += Characters(Rand.Next(0, 36))
Next
IDsList.Add(Id)
Id = ""
Next
'You can Check for duplicates by adding this piece of code or use the next one instead
Dim NoDupesIDsList As New List(Of String)
NoDupesIDsList = IDsList.Distinct.ToList
For i As Integer = 0 To 999 'This is a Zero Based Index so 999 is actually 1000
For _i As Integer = 0 To 7 'This also means 7 is 8
Id += Characters(Rand.Next(0, 36))
Next
If not IDsList.contains(Id) then
IDsList.Add(Id)
End if
Id = ""
Next
Use a Textbox with multiline and scroll bar for better experience
Feel free to ask me anything via comments
PS: I tested my method and it's working , enjoy it !
This function will return the ASCII characters between 48 an 122. That will include some characters that are not letters or numbers but this makes the ids even more unique and simplifies the code.
The For loop builds the ids with a length of 8. Then the id is checked for uniqueness with the .Contains method. Only if it is not in the list, it is added to the list and the counter is incremented.
Private Rnd As New Random
Private Function GetListOfIDs() As List(Of String)
Dim Counter As Integer
Dim lst As New List(Of String)
Dim id As String = ""
Do While Counter < 1000
id = ""
For i = 0 To 7
id &= Chr(Rnd.Next(48, 123))
Next
If Not lst.Contains(id) Then
lst.Add(id)
Counter += 1
End If
Loop
Return lst
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lst = GetListOfIDs()
TextBox1.Text = String.Join(vbCrLf, lst)
End Sub
EDIT
As per suggestion by Caius Jard in comments I have added a solution using a HashSet. Same idea only a HashSet will not accept duplicate entries. The .Add method returns a boolean telling you if the Add was successful.
Private Function GetListOfIDs() As HashSet(Of String)
Dim hs As New HashSet(Of String)
Dim id As String = ""
Do While hs.Count < 1001
id = ""
For i = 0 To 7
id &= Chr(Rnd.Next(48, 123))
Next
If hs.Add(id) Then
Counter += 1
End If
Loop
Return hs
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim hs = BuildHashSet()
TextBox1.Text = String.Join(vbCrLf, hs)
End Sub
This method is probably more efficient because a HashSet is designed for hight performance. For 1000 items I did not notice any difference in the user interface. The text box updated immediately with both methods.
This will create the names:
Function RandomName(length As Integer) As String
Shared rnd As New Random()
Shared corpus() As Char = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray()
Return New String(Enumerable.Range(0, length).Select(Function(c) corpus(rnd.Next(corpus.Length))).ToArray())
End Function
Iterator Function GetUniqueNames(length As Integer, count As Integer) As IEnumerable(Of String)
Dim names As New HashSet(Of String)
For i As Integer = 0 To count
Dim name As String = RandomName(length)
While names.Contains(name)
'Potential (but unlikely) halting problem
name = RandomName(length)
End While
names.Add(name)
Yield name
Next
End Function
Dim uniqueNames = GetUniqueNames(8, 1000)
But do you really want to display 1000 of them in a single label?
lblRandomId.Text = string.Join(vbCrLf, uniqueNames)
Let's talk about your code.
Dim strChar As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
This assignment will work in your loop because a String is really an array of Char. This is why you can refer to an index in the string.
Dim rand As New Random()
The .net Random class provides a seed for Random based on system time. Only rarely would you want to provide a seed.
From the docs https://learn.microsoft.com/en-us/dotnet/api/system.random?view=netcore-3.1
CONSTRUCTORS
Random() Initializes a new instance of the Random class
using a default seed value.
Random(Int32) Initializes a new instance of the Random class, using
the specified seed value.
For count_ids As Integer = 0 To 999
A For loop is not appropriate for this problem. We only want to increment the counter if we get a unique ID. The above For loop will increment on every iteration.
Do While Counter < 1000
'Code here
Loop
Notice in my code the counter is only incremented if the ID is unique.
The following loop should work fine but above this code we need to reset strID to an empty string. Otherwise we will have a very long string.
For count_chars As Integer = 0 To 7
strID += strChar(rand.Next(0, 62))
Next count_chars
You should not update the user interface (the label) on each iteration of the loop. Repainting the screen is one of the slowest operations in code. This line will overwrite the string in the label on every iteration.
lblRandomId.Text = strID
Move the update of the UI to after both loops are complete
Your code never checks for duplicates.
Now let's fix it.
We use a List(Of T) to accumulate the IDs. The T stands for Type; in our case it is String. A List is like an array only you don't have to know ahead of time how many entries there will be. No ReDim Preserve required.
Moved Dim strID As String = "" to the beginning of the inner loop so we will get a new strID on each iteration of the outer loop.
Changed strID &= strChar(rand.Next(0, 62)). &= instead of +=. In VB.net we use the ampersand to concatenate strings although the plus sign will work. The .Next method of the Random class has an overload that takes 2 Integers. It is inclusive of the first and exclusive of the second which means (0, 62) will return numbers form 0 to 61. Your string with a length of 62 has indexes of 0 to 61.
Next we check for duplicates with the .Contains method of the List class. This method does just what you would expect. We pass the new ID to the method and it returns a Boolean telling if the string is already in the list.
If it is not in the list, we add it to the list and increment the counter. The counter is only incremented if we have a successful add.
Finally we update the user interface by using a method of the String class. the .Join method takes a separator and the list to join. The TextBox must be multiline and have scroll bars.
I changed the names of the controls so I could test it in my testing program.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lst As New List(Of String)
Dim strChar As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
Dim rand As New Random()
Dim counter As Integer
Do While counter < 1000
Dim strID As String = ""
For count_chars = 0 To 7
strID &= strChar(rand.Next(0, 62))
Next
If Not lst.Contains(strID) Then
lst.Add(strID)
counter += 1
End If
Loop
TextBox1.Text = String.Join(vbCrLf, lst)
End Sub
EDIT
The official documentation for this method can be found here.
https://learn.microsoft.com/en-us/dotnet/api/system.string.join?view=netcore-3.1
I know it will be difficult to read but just take a look. Eventually you will be able to understand it and will be using these docs a lot.
String.Join(separator, List(Of String))
The separator is what to put between the strings in the list. In our case that is vbCrLf which is a vb constant for new line. Cr = Carraiage Return and Lf = Line Feed. Other types of collections that contain strings can also use this method.
The method takes each string in the list and adds the separator. After it is done with the list it returns one long string which we display in the TextBox.

how do i change the colour of a button based on a string input

For my computing project I am creating a game of risk this requires me to randomly generate the initial countries of the players (I have started with 2 players for simplicity), for this I am going to have the buttons (which represent the countries) to change colour to denote which of the players country it is.
I have tried to assign each player a string value of their colour then set the button back colour to that value. The problem with that at the moment is with the line of "b.Tag.BackColor = Players_Colours(N)" as the value that Players_Colours(N) gives is "S"c for some reason.
Any ideas why that is the case or anything would be appreciated.
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
End Sub
Public Function Random_country_picker(ByVal players)
Dim County_List = {"Oxfordshire", "Buckinhamshire", "Berkshire", "London", "Hampshire", "Surrey", "West_Sussex", "East_Sussex", "Kent", "Bedfordshire", "Cambridgeshire", "Hertfordshire", "Essex", "Cornwall", "Devon", "Gloucestershire", "Whiltshire", "Lancashire", "Cumbria", "Cheshire", "Manchester", "Merseyside", "Lincolnshire", "Staffordshire", "Herefordshire", "County_Durham", "North_Yorkshire", "South_Yorkshire", "Warwickshire", "Northumberland", "West_Yorkshire", "East_Yorkshire", "Shropshire", "Northamptonshire", "Derbyshire", "Nottinghamshire", "Worcestershire", "Somerset", "Dorset", "Isle_Of_White", "Norfolk", "Suffolk"}
Dim value As String
Dim num = 0
Dim nump = 42 / players
Dim N As Integer
Dim Players_Colours As String
Dim z As String
Players_Colours = {"Pink", "Red"}.ToString
N = 0
Randomize()
Dim rnd As New Random()
Dim index As Integer
While nump > num
If N > Players_Colours.Length Then
N = 0
End If
index = rnd.Next(0, County_List.Length)
value = County_List(index)
For Each b As Windows.Forms.Button In Me.Controls
If b.Tag = index Then
b.Tag.BackColor = Players_Colours(N)
End If
Next
Array.Clear(County_List, index, 1)
num += 1
N += 1
End While
Return 0
End Function
Random_country_picker(2)

VBA comparing multiple variables

There any way to compare multiple variables in VBA? For example:
Dim x As Integer
Dim y As Integer
Dim z As Integer
x = 99
y = 2
z = 3
I would like to return the smallest of the values.
I understand I could use select case x > y for all possible permutations but that seems unwieldy for more than 3 variables.
I have tried the worksheet function
solution = Application.WorksheetFunction.Min(x, y, z)
but that returns 2 and I would like it to return the variable name to be passed to another function.
many thanks,
Edit: My apologies if this was confusing, I am still a VBA novice. Here's my problem a little more generally:
I have a list of codes that correspond to names, many names per code. I want to loop through every name per code and count the number of instances that name appears on a list and choose the name with the LEAST occurrences. (could be 0 or could be the same as another name). obviously if there were 2 names it would be easy to do a if x>y then but I'm stumped as for comparing more than 3. Thanks for reading.
Use a public array rather than multiple variables. This will make it easy to iterate through them all and get the highest value, as well as reference the variable with the highest value later on:
Public myArray(0 To 2) As Integer
Public index As Integer
Public Sub calcMin()
Dim i As Integer
Dim maxValue As Integer
myArray(0) = 99
myArray(1) = 2
myArray(2) = 3
For i = 0 To UBound(myArray)
If myArray(i) < maxValue Then
maxValue = myArray(i)
index = i
End If
Next i
End Sub
Function yourFunction(valueToPass As Integer)
'your function's code here
End Function
Then pass the variable to yourFunction like so: yourFunction(myArray(index))
Same idea as Mike's but with an example to call a sub with the min value found:
Sub main()
Dim arrComp(2) As Integer
arrComp(0) = 99
arrComp(1) = 2
arrComp(2) = 3
'It is important to initialize the tmpVal to a value from the array
'to consider the chance where negative and positive values are used
Dim tmpVal As Integer: tmpVal = arrComp(LBound(arrComp))
Dim i As Integer, minIndex As Integer
For i = LBound(arrComp) To UBound(arrComp)
If arrComp(i) < tmpVal Then
tmpVal = arrComp(i)
minIndex = i
End If
Next i
showMinVal arrComp(minIndex)
End Sub
Sub showMinVal(MinVal As Integer)
MsgBox "The min value is " & MinVal
End Sub
Or, a workaround if you want the name associated to the value, you could define a new Type:
'Types must be declared at the top of the module
Type tVarName
varName As String
varVal As Integer
End Type
Sub main()
Dim arrComp(2) As tVarName
arrComp(0).varName = "x"
arrComp(0).varVal = 99
arrComp(1).varName = "y"
arrComp(1).varVal = 2
arrComp(2).varName = "z"
arrComp(2).varVal = 3
Dim tmpVal As Integer: tmpVal = arrComp(LBound(arrComp)).varVal
Dim i As Integer, minIndex As Integer
For i = LBound(arrComp) To UBound(arrComp)
If arrComp(i).varVal < tmpVal Then
tmpVal = arrComp(i).varVal
minIndex = i
End If
Next i
showMinVal arrComp(minIndex)
End Sub
'Sub showing min value along with the name associated to it
Sub showMinVal(MinVal As tVarName)
MsgBox "The min value is " & MinVal.varName & " = " & MinVal.varVal
End Sub

Need help with VB.NET List Logic

Hey guys, so I am creating a List(Of String), always of size 9.
This list contains True/False values. I need to go through this list and find the 3 values that are True (will never be more than 3, but could be less) and then set 3 string values in my code to the 3 index's of those values + 1.
Here is my current code:
Private Sub SetDenialReasons(ByVal LoanData As DataRow)
Dim reasons As New List(Of String)
With reasons
.Add(LoanData.Item("IsDenialReasonDTI").ToString)
.Add(LoanData.Item("IsDenialReasonEmploymentHistory").ToString)
.Add(LoanData.Item("IsDenialReasonCreditHistory").ToString)
.Add(LoanData.Item("IsDenialReasonCollateral").ToString)
.Add(LoanData.Item("IsDenialReasonCash").ToString)
.Add(LoanData.Item("IsDenialReasonInverifiableInfo").ToString)
.Add(LoanData.Item("IsDenialReasonIncomplete").ToString)
.Add(LoanData.Item("IsDenialReasonMortgageInsuranceDenied").ToString)
.Add(LoanData.Item("IsDenialReasonOther").ToString)
End With
Dim count As Integer = 0
For Each item As String In reasons
If item = "True" Then
count += 1
End If
Next
If count = 1 Then
DenialReason1 = (reasons.IndexOf("True") + 1).ToString
ElseIf count = 2 Then
DenialReason1 = (reasons.IndexOf("True") + 1).ToString
DenialReason2 = (reasons.LastIndexOf("True") + 1).ToString
ElseIf count >= 3 Then
Dim tempIndex As Integer = reasons.IndexOf("True")
DenialReason1 = (reasons.IndexOf("True") + 1).ToString
DenialReason2 = (reasons.IndexOf("True", tempIndex, reasons.Count - 1) + 1).ToString
DenialReason3 = (reasons.LastIndexOf("True") + 1).ToString
End If
End Sub
I had 3 True's next to each other in the array and the code failed with an exception saying count must be positive or something.
Now if there are less than 3 True's, it should set the remaining DenialReason's that haven't been set yet as blank (however they are set as blank in the constructor already to account for this).
Any ideas?
Perhaps you could modify your For Each code to handle the assignment of the DenialReasons. This still feels like a hack, but I think it may be cleaner that what you have. If you use this code, you don't need the code that begins with If count = 1...:
Dim count As Integer = 0
Dim index As Integer = 1
For Each item As String In reasons
If item = "True" Then
count += 1
Select Case count
Case 1
DenialReason1 = index.ToString()
Case 2
DenialReason2 = index.ToString()
Case 3
DenialReason3 = index.ToString()
End Select
End If
index += 1
Next
The index variable above assumes a 1-based index. I think this is cleaner than using IndexOf().
I think a better solution might be to have a list of DenialReasons and add to that list as items are true:
Dim count As Integer = 0
Dim index As Integer = 1
Dim denialReasons As New List(Of String)()
For Each item As String In reasons
If item = "True" Then
denialReasons.Add(index)
End If
index += 1
Next
Then you can simply iterate through your list of denialReasons. This is flexible so that if, for whatever reason, you have more than three DenialReasons, you don't have to add another hard-coded variable.