Loop variable ends with a value one above expected - arrays

In VBA, running in Excel, I am running a basic loop that fills an array with values. The code is as below.
What I find curious, is the value of Counter starts at 0, yet ends at 7, rather than 6. I can note this when I'm looking in the Locals window and running the code step-by-step. It seems the value becomes 7 on its last instance of running 'Next'
Is this normal, or is there something I'm doing wrong?
It doesn't seem to change the outcome here, but if I'm using more complicated code, I want to be sure this is what I should be expecting.
Sub ArrayLoop()
Dim myArray(6) As String
Dim Counter As Integer
For Counter = 0 To 6
myArray(Counter) = Range("A1").Offset(Counter, 0).Value
Next
End Sub

This is normal: last iteration of the loop increments Counter to 7 and triggers the exit from loop
Counter = 7 ( > 6 )
There are algorithms based on the exit value of the Counter:
Option Explicit
Sub ArrayLoop()
Dim myArray(6) As String
Dim Counter As Integer
For Counter = 0 To 6
myArray(Counter) = Range("A1").Offset(Counter, 0).Value
Next
Do
Debug.Print Counter '---> 7, 6, 5, 4, 3, 2, 1
Counter = Counter - 1
Loop While Counter > 0
Debug.Print Counter '---> 0
End Sub

remember that arrays are zero indexed. So technically the 7th time through the loop it should give you some sort of out of bounds error. Although there is technically nothing wrong with the way you are adding your values to the array.
Also remember that counter increments +1 each time after the loop is completed.
if you wanted it to only use 6 values you would have to change to
For Counter = 0 To 5
myArray(Counter) = Range("A1").Offset(Counter, 0).Value
Next
this would start at 0 the first time through the loop add the value to the array with a 0 index, then increase the index each time +1 and increase the offset by 1 row each time through the loop. And it would only run the loop 6 times.

Related

How can I add something to an array and move everything down?

I'm trying to add a score to an array and check if that score is higher than the rest, and put it in the correct position and move everything else down. I have a 2-dimensional array highScores(9, 1), where the first part is each score, and the second part is the name when 0 and the score when 1. I want to be able to check where the new score should be entered and then move everything down if need be.
This is what I have so far, and it doesn't work.
Sub AddScore(name As String, score As String)
For i = 9 To 0 Step -1
If score > highScores(i, 1) Then
For j = i To 1 Step -1
highScores(j - 1, 0) = highScores(j, 0)
highScores(j - 1, 1) = highScores(j, 1)
Next
highScores(i, 0) = name
highScores(i, 1) = score
Exit For
End If
Next
End Sub
I'm guessing that the score at element 9 is the highest score and the score at element 0 is the lowest.
You were close, but not quite there. For a start, you should never do mathematical comparisons on strings. You should convert the strings to numeric values. For this there are several ways, but for you the simplest is to use the Val function.
Next. Have a think about what you're trying to achieve. Iterate through the scores from lowest to highest checking the score to see if it is higher than any in the array. If it is, move each high score down to the next element. A key thing here is to remember that element 0 has nowhere to go, it just gets overwritten by the one above. So start going along the array from element 1 to element i where you will be placing the new score. For example element 1 overwrites element 0, element 2 overwrites element 1 and so on. When this is done, you simply overwrite element i with the new values.
Finally, rather than use Exit For, use Exit Sub to leave that sub entirely. Exit For will only leave the inner For..Next loop and will then try to continue the outer loop.
Private Sub AddScore(name As String, score As String)
For i As Integer = 9 To 0 Step -1
If Val(score) > Val(highScores(i, 1)) Then
For j As Integer = 1 To i
highScores(j - 1, 0) = highScores(j, 0)
highScores(j - 1, 1) = highScores(j, 1)
Next
highScores(i, 0) = name
highScores(i, 1) = score
Exit Sub
End If
Next
End Sub

Are my arrays incompatible?

I am trying to loop through an array that contains split strings, done via this line:
repHolder() = Split(rep, ",")
That's all fine and good, however, when I try to loop through this repHolder() array via a for loop, I am met each time with a subscript out of range error.
This makes no sense to me. When I step through the array it fails on the first element every time; this line:
If repHolder(j) = counter Then
I tried setting j to 0 and 1, both of which failed on the first sequence of the loop. This suggests to me because the array doesn't have a defined size; that I cannot loop through it this way, but that still makes little sense to me as it is still filled with elements.
Here is the entire code block of what I am trying to do:
Dim repHolder() As String
Dim strHolder() As String
Dim counter As Variant
Dim j As Integer
For Each rep In repNames()
repHolder() = Split(rep, ",")
Next rep
For Each rangeCell In repComboRange
k = 1
Do
If rangeCell.Value = repCombos(k) Then 'At this point, if rangecell = repcombos(k)
Range(rangeCell, rangeCell.End(xlToRight)).Copy
strHolder() = Split(rangeCell.Value, "/")
For Each counter In strHolder()
Stop
For j = 1 To 17
If repHolder(j) = counter Then
You are looping through repNames() and setting this new array via split (over and over again for each repName element...)
For Each rep In repNames()
repHolder() = Split(rep, ",")
Next rep
Every iteration of this loop resets repHolder() to a split of the rep element dropping whatever values were just set in that array in the previous iteration. So once it's done only the last element of RepNames() has been split into the repHolder() array.
For instance, if RepNames() looks like:
Element 0: "james,linda,mahesh,bob"
Element 1: "rajesh,sam,barb,carrie"
Element 2: ""
Then after all this iterating your repHolder array is going to be empty because there is nothing in the final element.
Stick a breakpoint (F9) on you For Each rangeCell In repComboRange line and look at your Locals pane in VBE. Check out the values that are stored in your repHolder() array at that point in time. I suspect there will be nothing in there.
The other oddball here is that you are looping 1 through 17. repHolder() will be a 0-based array so that should be 0 through 16. But... even that is nonsense since this really only makes sense as a For Each loop (or to use the uBound(repHolder) to determine how many times to loop:
For Each counter In strHolder()
Stop
For each repHolderElem in repHolder
If repHolderElem = counter Then
....
Next repHolderElem

How would I loop through an array and find any combination of numbers that adds up to equal a target number?

I have thought about this issue a lot, and I have found a way to do it, but there has to be a better way. I want to enter a target number, then loop through an array and find any possible combination of numbers that adds up to equal that target number.
For example, I know this code works to find all combinations of two numbers that add up to equal the target number:
For i as Integer = 0 To MyArray.Length - 1
For j as Integer = (i + 1) To MyArray.Length - 1
If(MyArray(i) + MyArray(j)) = TargetNumber Then
'Output these two numbers
EndIf
Next
Next
As you can see, this algorithm is designed only to get combinations of two numbers that add up to equal the target number. I know that I could nest another For loop (or as many as I want) to find as many numbers as I want to find, but there has to be a better, more efficient way. I don't want to have to nest another loop every time I want to find another number. Any suggestions? Should I avoid using arrays and try some other approach? Any help is appreciated.
This wont repeat any number in the BasicNums array, and it means that only specified number can print out the number combination.
Code below:
Module Module1
Dim BasicNums() As Integer = {1, 2, 3, 4, 5, 6, 7, 8}
Dim nums As New List(Of Integer)
Dim TargetNumber As Integer
Sub Main()
TargetNumber = Console.ReadLine()
Recursion(0, 0, 0) 'start recursive
Console.ReadLine() 'pause the console
End Sub
Sub Recursion(ByVal depth As Integer, ByVal start As Integer, ByVal count As Integer)
'depth -> the recursion's depth (the 'for' count)
'start -> where the next for starts
'count -> current number count
If count = TargetNumber Then
'when [count] equals [TargetNumber] print the combination nums
For j As Integer = 0 To nums.Count - 1
Console.Write(nums(j) & " ")
Next
Console.Write(vbCrLf)
Return
ElseIf depth = BasicNums.Length - 1 Then
'stop the recursion when the recursion meets the length of [BasicNums]
Return
End If
For i As Integer = start To BasicNums.Length - 1
nums.Add(BasicNums(i))
Recursion(depth + 1, i + 1, count + BasicNums(i))
nums.Remove(BasicNums(i))
Next
End Sub
End Module
Example Input:
7
Output:
1 2 4
1 6
2 5
3 4
7

Trouble looping through a data file and storing integers in an array

I am having a problem with a loop. I am writing a program that loops through lottery drawings and does some different analysis' on the drawings. The problem I am having is since a loop is 0-based but there is no number 0 in lottery drawings I cant figure out how to start the loop at 1 instead of 0. Also, when I cut out an integer, if the integer is a single digit the loop doesn't see the zero before the single digit and counts all of the 0-9 in all of the integers. I am trying to grab an integer and then tick that element of the array. Here is the loop.
'Choices(59) is passed into the loop from a click event
Private Sub GetFrequency(Choices() As Integer)
Dim Size As Integer = UsersChosenHistory.Length() 'Size
Dim Number As Integer = 1
Dim Start As Integer = 0
Dim Finish As Integer = 3'Grab 3 chars, a space + 2 digit Integer
For i As Integer = 1 To Size - 1 Step 1
Number.ToString("d2")'I've also tried Number.ToString("D2") (Capitol D)
Number = UsersChosenHistory.Substring(Start, Finish) 'Grab an integer
Choices(Number) += "1" 'Store it in the corresponding array element
Start += 1
Next
End Sub
When running through the loop with the F11 key the single digits do not show the leading "0" even though the data file does include the "0", and as I mentioned above the array shows a "0" as the first digit in the frequence grid. I'm really confused with this loop, any help will be greatly appreciated. I'm just learning VB.Net and this has me stumped. Thanks in advance.
For i As Integer = 0 To Size - 1 Step 1
Number = int.Parse(UsersChosenHistory.Substring(i*3,3).Replace(" ",""))
Choices(Number) += "1"
Next
For the "0" issue, ignore it. Choices(0) will never be incremented.

Stepping up an array in a loop vb

This code simply completes a shift of characters for every negative variable in the loop. It then displays this text for every loop completed. (The name variable is actually a parameter for one of the subroutines, so does need to remain being called 'variable')
Counter = 0
dim counterarray(24)
For variable = -1 to -25
completeshift()
displaytext()
counter = counter + 1
next
So in this code, i would like to know how to step up each variable in the array every time the loop is complete. Basically i need the first
loop displaytext() to go into counterarray(0), the second to go into counterarray(1) etc until all of them have been completed.
Not entirely sure what your question is, but if you want that loop to work you need to add step - 1
For variable = -1 to -25 step -1
completeshift()
displaytext()
counter = counter + 1
next
You are not using variable for anything so you may as well write,
Dim counterarray(24)
For i = 0 to 24
completeshift()
counterarray(i) = displaytext()
Next
probably too elaborate but ...
Dim count = 25
Dim counterArray(count - 1) As String
Enumerable.Range(0, count).Zip(Enumerable.Range(-count, count).Reverse(),
Function(counter, variable) counterArray(counter) = DisplayText())

Resources