Reset index cycle for-next - vba

Good morning,
I have a problem with the for-next loop. At the second iteration of the cycle, the exit from the cycle occurs even if the exit condition on variable j is not respected. I would have solved the problem with the goTo statement. However I am wondering why index reset does not work in this case.
Thank you.
For j = LBound(AttivitaTemp) To UBound(AttivitaTemp)
If confronta(AttivitaTemp(j), AttivitaFinali) = "#N/D" Then
activityTemp = AttivitaTemp(j)
rigaTemp = confronta(activityTemp, Attivita)
SuccessioniTemp = estrai_riga(MatriceElenchiSuccessioni, rigaTemp)
SuccessioniTemp = cancella_vuoti_vettore(SuccessioniTemp)
ESsuccessioni = EF(rigaTemp)
For k = LBound(SuccessioniTemp) To UBound(SuccessioniTemp)
rigaTemp = confronta(SuccessioniTemp(k), Attivita)
ES(rigaTemp) = Application.WorksheetFunction.Max(ES(rigaTemp), ESsuccessioni)
EF(rigaTemp) = ES(rigaTemp) + Durate(rigaTemp)
Next
VettoreSuccessioniTemp = unisci_vettori(VettoreSuccessioniTemp, SuccessioniTemp)
If j = UBound(AttivitaTemp) Then
AttivitaTemp = VettoreSuccessioniTemp
ReDim VettoreSuccessioniTemp(0)
j = LBound(AttivitaTemp) - 1
'GoTo ricomincia_ciclo_j
End If
End If
Next
Observing the variable j at the second iteration it results j = 0, with the next it goes to j = 1 but the for loop is not re-executed, although UBound (AttivitaTemp) is equal to 1.
In other words, why does this simple cycle work instead, which conceptually does the same thing?
For x = 0 To 2
If x = 2 Then
x = -1
End If
Next

I solved it by myself: the problem is that even if it is possible to reset the iterator, it is not possible to update the conditions of the for loop (the values of "from" and "to" remain "frozen" even if during the loop they are changed).

Related

Can I optimize my for loop using LINQ in vb.net?

I have a for loop that is working as intended. I iterate over an array of values and replace bad values (-99999) with the closest good value (if the bad value is on either end of the array) or the average of the two surrounding values (if the bad value is in the middle of the array). However, these nested loops smelled to me and I am looking for any suggested means of optimizing this (in terms of readability or performance).
I could access or remove the bad values using Dim badValues = MeasuredValues.Where(Function(x) x = -99999) but I'm not sure how I can keep track of the indexes for calculating the replacement value when using .Where. I'm no vb.net expert.
For index = 0 To MeasuredValues.Count - 1
If MeasuredValues(index) = -99999 Then
Dim nextGoodValue = -99999
Dim previousGoodValue = -99999
Dim replacementValue = -99999
For j = index To MeasuredValues.Count - 1
If MeasuredValues(j) <> -99999 Then
nextGoodValue = MeasuredValues(j)
Exit For
End If
Next
For k = index To 0 Step -1
If MeasuredValues(k) <> -99999 Then
previousGoodValue = MeasuredValues(k)
Exit For
End If
Next
If previousGoodValue = -99999 Then
replacementValue = nextGoodValue
ElseIf nextGoodValue = -99999 Then
replacementValue = previousGoodValue
Else
replacementValue = (nextGoodValue + previousGoodValue) / 2
End If
MeasuredValues(index) = replacementValue
End If
Next
Thanks for your time, please let me know if you need more info or have any questions.

Do-While loop (VBA) not looping

so I thought this would be a simple logical problem, but for the life of me I cannot find the issue with this code block. I have checked around on Stack for a solution, but all other do/while loop problems appear to be primarily with other languages.
What I am trying to do is simply loop through an array & add a new worksheet for each element in the array that is not null. Pretty simple right? Yet for some reason it simply loops through once and thats it.
Here is the code block:
Dim repNames() As String
Dim x As Integer
x = 25
ReDim repNames(1 To x)
repNames(1) = "Ahern"
repNames(2) = "Castronovo"
repNames(3) = "Glick"
repNames(4) = "Fields"
repNames(5) = "Murphy"
repNames(6) = "Sleeter"
repNames(7) = "Vivian"
repNames(8) = "Walschot"
repNames(9) = "Wilson"
Dim i As Integer
i = 1
Do 'Loop keeps creating only 1 new sheet. Should create 9.
Worksheets.Add.Name = repNames(i)
i = i + 2
Loop While repNames(i) <> Null
I believe the problem is with this line: Loop While repNames(i) <> Null,
but obviously the logical test seems to hold up.
Any help would be hugely appreciated!
As others note, Null is not the comparison you want to make. Testing anything for equivalence with Null will return Null -- even ?Null = Null returns Null, which is why your loop is exiting early. (Note: To test for a Null, you need to use the IsNull function which returns a boolean, but that is NOT how you test for an empty string.)
In VBA, to test for a zero-length string or empty string, you can use either "" or vbNullString constant, or some people use the Len function to check for zero-length.
Rectifying that error, as originally written in your code, your logical test should abort the loop if any item is an empty string, but none of the items are empty strings (at least not in the example data you've provided) so you end up with an infinite loop which will error once i exceeds the number of items in the repNames array.
This would be probably better suited as a For Each loop.
Dim rep as Variant
For Each rep in repNames
Worksheets.Add.Name = rep
Next
If you need to skip empty values, or duplicate values, you can add that logic as needed within the loop:
For Each rep in repNames
If rep <> vbNullString 'only process non-zero-length strings
Worksheets.Add.name = rep
End If
Next
Etc.
Firstly, you should be comparing to vbNullString. This loops multiple times:
' Declare variables
Dim repNames() As String
Dim x As Integer
Dim i As Integer
' Set data
x = 25
ReDim repNames(1 To x)
repNames(1) = "Ahern"
repNames(2) = "Castronovo"
repNames(3) = "Glick"
repNames(4) = "Fields"
repNames(5) = "Murphy"
repNames(6) = "Sleeter"
repNames(7) = "Vivian"
repNames(8) = "Walschot"
repNames(9) = "Wilson"
' Loop through items
i = 1
Do
Worksheets.Add.Name = repNames(i)
i = i + 2
Loop While repNames(i) <> vbNullString
There is one more problem – why i = i + 2 ? In your question you say you wanted the loop to execute 9 times, but using i = i + 2 skips every other item. If you indeed want to loop through every item:
Do
Worksheets.Add.Name = repNames(i)
i = i + 1
Loop While repNames(i) <> vbNullString
Here you go, I have changed the loop conditional, and changed i=i+2 to i=i+1. A regular while loop would be better than a do while encase the first element is empty
Dim repNames()
Dim x As Integer
x = 25
ReDim repNames(1 To x)
repNames(1) = "Ahern"
repNames(2) = "Castronovo"
repNames(3) = "Glick"
repNames(4) = "Fields"
repNames(5) = "Murphy"
repNames(6) = "Sleeter"
repNames(7) = "Vivian"
repNames(8) = "Walschot"
repNames(9) = "Wilson"
Dim i As Integer
i = 1
Do While repNames(i) <> ""
Worksheets.Add.Name = repNames(i)
i = i + 1
Loop

Loop through Excel Ranges Filling Combobox VB.Net

I have a program that needs to iterate through a very large excel range, to combine two ranges into one combo box value. I have the following code to do so, but all it does is iterate the first value five times. If I remove the first FOR loop, then it simply only returns the first value and never completes. Any suggestions on what I can do to polish this code up and get it working?
Dim i As Integer
If TenantBox.SelectedItem = "CNS" Then
WFMBook.Workbooks.Open("C:\Schedule.xlsx")
For i = 0 To 5 Step +1
For Each CNSCell In WFMBook.Range("A3:A1441").Cells
f = CNSCell.Value.ToString
Next
For Each tst In WFMBook.Range("B3:B1441").Cells
l = tst.Value.ToString
Next
ComboBox1.Items.Add(f + " " + l)
If (i = 5) Then
Exit For
End If
Console.WriteLine(i)
Next
End If
Try this, just change the x to 1 if VBA is 1 based.
If TenantBox.SelectedItem = "CNS" Then
WFMBook.Workbooks.Open("C:\XHSchedule.xlsx")
Dim colCount = WFMBook.Range("A3:A8").Cells.Count
For x = 1 To colCount Step +1
For Each CNSCell In WFMBook.Range("A3:A8").Cells
f = WFMBook.Range("A3:A8").Cells(x).Value.ToString
l = WFMBook.Range("B3:B8").Cells(x).Value.ToString
Next
ComboBox1.Items.Add(f + " " + l)
Next
End If

Don't go into this loop if the array is empty

Til now the method I use to avoid going into for loops which loop through an array which is currently empty is the following:
if len(join(array,"") > 0 then
for i = 1 to ubound(array)
code
next
end if
But this is no joke, I just recently used that line of code if len(join(array,"") > 0 then and that caused the deletion of array and it crashed my program 5 times in a row. I know that sounds hard to believe but here is a screen shot
for some reason the code len(join(array,"") > 0 would destroy the variables2 array. And here is a screen shot that shows that the variables array is clearly full before I go to the bad code: So now I'm trying to use a different code I tried:
if not isempty(array) then
But that's not working. Any ideas?
If Len(Join(greek_act, "")) > 0 Then
For i = 1 To UBound(greek_act)
For j = 1 To UBound(variables2)
If greek_act(i) = variables2(j) Then
variables2(j) = ""
Exit For
End If
Next
Next
variables2 = remove_blanks(variables2)
End If
'variables2 array is full
If Len(Join(greek_letters, "")) > 0 Then
'variables2 array gets destroyed and program crashes here.
For i = 1 To UBound(greek_letters)
rightres1 = Replace(rightres1, greek_letters(i), variables2(i))
Next
End If
Never mind, I decided to just go ahead with the following solution since it appears that the program is temporarily acting up
On Error Resume Next
For i = 1 To UBound(greek_letters)
rightres1 = Replace(rightres1, greek_letters(i), variables2(i))
Next
On Error GoTo 0``
For the Join() technique to work reliably, you must complete the Dimming/ReDimming process:
Sub dural()
Dim greek_ary(1 To 3) As String
s = Join(greek_ary, "")
MsgBox Len(s)
End Sub
Without filling the array, the Len will report 0
Since this is a common test I like to use a reusable function like this:
Function IsArrayEmpty(anArray As Variant)
Dim i As Integer
On Error Resume Next
i = UBound(anArray, 1)
If Err.Number = 0 Then
IsVarArrayEmpty = False
Else
IsVarArrayEmpty = True
End If
End Function
Now in your main Sub do this:
If Not IsArrayEmpty(greek_act) Then
For i = 1 To UBound(greek_act)
For j = 1 To UBound(variables2)
If greek_act(i) = variables2(j) Then
variables2(j) = ""
Exit For
End If
Next
Next
variables2 = remove_blanks(variables2)
End If

For Loop Step -1

I want to know why this loop doesn't show anything in VB.NET.
I think this code will create an infinite loop. But it doesn't show anything.
Dim i as Integer
For i = 1 to 3 Step - 1
MessageBox.Show(i)
Next
Is that loop different with this code (in java/c#) ?
for(int i = 1;i <= 3;i--)
{
// print i
}
http://msdn.microsoft.com/en-us/library/5z06z1kb.aspx
With a negative step size the loop only executes if counter >= end. So in this case with i = 1, that is less than the ending value so the loop doesn't execute at all.
It doesn't show anything because you are running the counter backwards without reversing the start and end conditions.
Think of the loop like this:
Dim counter As Int32 = 1
Do
If counter <= 1 Then
Exit Do
End If
Console.WriteLine("The counter is at " & counter)
counter +=1
Loop
Obviously this won't work properly.
You need to reverse the start and end conditions:
For counter = 3 To 1 Step -1
Console.WriteLine("counter: " & counter)
Next
For i = 1 to 3 Step - 1
It won't create an infinite loop. The loop will simply be skipped, because you can't get from 1 to 3 with a step value of -1.
Is that loop different with this code (in java/c#) ?
This loop will also end immediately, because the initial value (i = 1) meets the exit condition (i <= 3).