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

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

Related

Reset index cycle for-next

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).

skip over a value in a loop and then continue to loop?

I need to be able to run a loop starting at 0, have it identify a certain value (in this case piecenumblack) and then skip that value, and then continue the loop until it hits 11. I'm really unsure what type of loop to use and I've had no success with a Do, While, or For loop.
Dim piecenumblack As Integer
For i = 0 To piecenumblack
Next
For i = 11 To piecenumblack Step -1
Next
You could add an If to the inside of the loop:
Dim piecenumblack As Integer
piecenumblack = 3
For i = 0 To 11
If i <> piecenumblack then
'Do Code
End If
Next
This would then skip doing any code when i = 3 then continue on with 4,5,6..11.

Error Resetting not working

I am writing a macro to renumber points and lines. In the following code, the Err.Number is not resetting and the code breaks at 2nd instance of error. How to fix this?
S = 0
SS = 0
Surfaces = Y
Do
SS = SS + 1
Handler:
S = S + 1
On Error GoTo Handler
Set hybridBodyShape1 = hybridBodyShapes1.Item("Line_Extract_" & S)
hybridBodyShape1.Name = "Line_Extract_" & SS
Set hybridBodyShape1 = hybridBodyShapes1.Item("Point_Extract_" & S)
hybridBodyShape1.Name = "Point_Extract_" & SS
On Error GoTo 0
Loop Until S = Surfaces - 1
I don't know what you expect the loop (or your error "handler") to do, but you probably should change the implementation to something like this:
On Error Resume Next
Do
If Err.Number = 0 Then SS = SS + 1
Err.Clear
S = S + 1
Set hybridBodyShape1 = hybridBodyShapes1.Item("Line_Extract_" & S)
hybridBodyShape1.Name = "Line_Extract_" & SS
If Err.Number = 0 Then
Set hybridBodyShape1 = hybridBodyShapes1.Item("Point_Extract_" & S)
hybridBodyShape1.Name = "Point_Extract_" & SS
End If
Loop Until S = Surfaces - 1
On Error GoTo 0
The Err object doesn't magically reset itself just because you jump to a label in case of an error.
In VBA, once the script throws an error, it is not automatically reset by the fact that you have an error handler enabled. To properly reset the error, you should have a Resume statement somewhere. Typical error handling routines look like this:
Sub ErrorProne()
Dim i As Integer
Dim myArr(4) As Integer
On Error Goto ErrHndl
Do While True
myArr(i) = i '<-- will bug on 5th iteration
Loop
PostLoop:
'More code goes here
Exit Sub
ErrHndl:
Resume PostLoop
End Sub
For a fuller description on how to use Error Handling, see Chip Pearson's site: http://www.cpearson.com/excel/errorhandling.htm

VBA: Don't go into loop when array is empty

I have a loop that can look like this:
For Each article In artAll
Next
or like this:
For i = 0 To Ubound(artAll)
Next
When the array length is 0, I get an error message. What is a good way to skip the loop when the array is empty? I suspect that I should use
On Error Goto
but I need help finalizing a solution.
If Len(Join(artAll, "")) = 0 Then
'your for loops here
Should work
I use this function to test for empty arrays:
Public Function isArrayEmpty(parArray As Variant) As Boolean
'Returns false if not an array or dynamic array that has not been initialised (ReDim) or has been erased (Erase)
If IsArray(parArray) = False Then isArrayEmpty = True
On Error Resume Next
If UBound(parArray) < LBound(parArray) Then isArrayEmpty = True: Exit Function Else: isArrayEmpty = False
End Function
Then in your main code:
If isArrayEmpty(yourArray) Then
'do something - typically:
MsgBox "Empty Array"
Exit Function
End If
For i = LBound(yourArray,1) To UBound(yourArray,1)
'do something
Next i
I like the solution given by #Dan but thought I would throw out there how I would normally handle an undimensionalized array:
Dim lngUboundTest As Long
lngUboundTest = -1
On Error Resume Next
lngUboundTest = UBound(artAll)
On Error GoTo 0
If lngUboundTest >= 0 Then
'Your loop...
This is an old question, but I found this solution to the problem, and it could be helpful to others:
If (Not myArray) = True Then
'Undimensionalized array. Respond as needed.
Else
'Array isn't empty, you can run your loop.
End If
It helped my out in a recent project, and found it to be very handy.
I found this thread looking for a solution to a problem where looping through a multidimensional array would fail if a dimensioned element was empty. I created the array by looping through a source that could have up to 6 datasets. Then after processing I would repeat this 19 more times.
Dim varDeskData As Variant
Dim varDesk As Variant
ReDim varDesk(1 To 6)
For y = 1 To 6
ReDim varDeskData(1 To 4)
varDeskData(1) = "nifty integer from source(y)"
varDeskData(2) = "nifty string from source(y)"
varDeskData(3) = "another nifty string from source(y)"
varDeskData(4) = "another nifty string from source(y)"
varDesk(y) = varDeskData
Next y
When I ran the following, I would get the first three processed but then it would fail on the fourth, because I had only loaded three into the parent array:
For y = 1 To 6
If varDesk(y)(1) > 0 Then
... do nifty stuff ...
End If
End If
Using the IsEmpty procedure on the top level elements of the parent array fixed this:
For y = 1 To 6
If IsEmpty(varDesk(y)) = False Then
If varDesk(y)(1) > 0 Then
... do nifty stuff ...
End If
End If
End If

This array is fixed or temporarily locked

I am using split function and assigning the value in a variable and running the code in loop after few iterations its giving an error of "This array is fixed or temporarily locked (Visual Basic)"..
e.g; here value of movies_cat1 read from excel is in form of this------
"Movies->List All Movies , Movies->World Cinema->Asia , Movies->Movies by Language->Sinhalese , Movies->Drama"
For crow = 1 To 100
Value = Worksheets("Movies_categories").Range("A" & crow).Value
cat_final = Worksheets("Movies_categories").Range("B" & crow).Value
If Value = "y" Or Value = "Y" Then
'Loop for reading the data from tabsheet- Movies
For crowss = 5 To 3000
movies_cat1 = Worksheets("Movies").Range("B" & crowss).Value
movies_language = Worksheets("Movies").Range("C" & crowss).Value
If movies_language = "English" Then
Temp = Split(movies_cat, ",") 'run time Error:10 occurs here..
For Each boken_c In Temp
flag = 0
boken_c = Trim(boken_c)
If RTrim(LTrim(boken_c)) = LTrim(RTrim(cat_final)) Then
flag = 1
GoTo Line4:
End If
Next boken_c
End If
Next crowss
End If
Line4: Next crow
Error occurs at this statement: Temp = Split(movies_cat, ","), it says that the array is fixed or temporarily locked, because i think initially its taking 'temp' as a variable, but while returning the value of split function, variable 'Temp' becomes array after completion of first loop(i.e after crow = 6,7....)
Your line4 label is outside the for loop on the temp variable so when you goto it leaves it locked.
You really should restructure your code to not use a goto inside the for each loop.
Maybe:
For crow = 1 To 100
Value = Worksheets("Movies_categories").Range("A" & crow).Value
cat_final = Worksheets("Movies_categories").Range("B" & crow).Value
If Value = "y" Or Value = "Y" Then
'Loop for reading the data from tabsheet- Movies
For crowss = 5 To 3000
movies_cat1 = Worksheets("Movies").Range("B" & crowss).Value
movies_language = Worksheets("Movies").Range("C" & crowss).Value
If movies_language = "English" Then
Temp = Split(movies_cat, ",") 'run time Error:10 occurs here..
For Each boken_c In Temp
flag = 0
boken_c = Trim(boken_c)
If RTrim(LTrim(boken_c)) = LTrim(RTrim(cat_final)) Then
flag = 1
**Exit For**
End If
**If flag = 1 Then Exit For**
Next boken_c
End If
**If flag = 1 Then Exit For**
Next crowss
End If
Next crow
(Note the **d lines.)
I had this problem too with VBA. I cannot say I am proud of how I managed to get it, but it is supplied here just in can anyone else accidentally slips up on this.
It is quite interesting to debug as the failure occurs at the call to a sub or function - not at the point of failure. Luckily, you can follow the code through to the offending line of the called routine before it reports the error.
Call Sub1(gArray(3))
debug.print gArray(3)
...
Sub Sub1(i as integer)
Redim gArray(0)
End sub
Clearly the VB RT is not going to like this as by the time the debug.print executes, the array dimension does not exist. Ok why the hell would you want to pass a globally declared array anyway? Guilty as charged.
So in the example above you get the error at the call to Sub1, but the thing causing it is the Redim in the sub.
The moral to the story is do not pass global variables as parameters to subs. Another simple fix is to declare the Sub1 slightly differently:
Sub Sub1(ByVal i as integer)
This means the i variable is copied (but not returned) by the Sub.
Thanks, Deanna for the answer! I have a similar message on ReDim Preserve statement at the last line in next fragment of code:
If StrComp(Mid(s, 1, lE), txtE, vbBinaryCompare) = 0 Then
For i = iMdl To 1 Step -1
With blks(i)
If .lnEnd = 0 Then ' ".lnEnd" is a member of blks(i)
.lnEnd = ln
GoTo NXT
End If
End With
Next
errBegWith = errBegWith & ln & ", "
NXT:
End If
'...
ReDim Preserve blks(iMdl)
And after extracting assignment .lnEnd = ln from inside of the With the program works fine:
If StrComp(Mid(s, 1, lE), txtE, vbBinaryCompare) = 0 Then
For i = iMdl To 1 Step -1
If blks(i).lnEnd = 0 Then
blks(i).lnEnd = ln
GoTo NXT
End If
Next
errBegWith = errBegWith & ln & ", "
NXT:
End If
'...
ReDim Preserve blks(iMdl)