Else without If & Next without For in Vba Excel - excel

I'm trying to learn vba excel. With below code I want that the sheet 1 (A1:C8) will be filled with numbers [1-24].
I'm getting the following errors: Else without If and Next without For
Public Sub InsertNummer()
Worksheets("sheet1").Activate
Dim Count, RO, CL As Integer
For CL = 1 To 3 Step 1
For RO = 1 To 8 Step 1
If CL = 1 Then
For Count = 1 To 8 Step 1
Cells(RO, CL).Value = Count
ElseIf CL = 2 Then
For Count = 9 To 16 Step 1
Cells(RO, CL).Value = Count
Else
For Count = 17 To 24 Step 1
Cells(RO, CL).Value = Count
End If
Next Count
Next RO
Next CL
End Sub

You may want to spend some more time looking through how For Loops work correctly.
They really are quite basic and easy to learn but I've got you a code here which is much simpler to achieve the same results:
Sub InsertNumber()
Dim CL As Long, RO As Long, Count As Long
Count = 1
For CL = 1 To 3 'Columns 1 to 3
For RO = 1 To 8 'Rows 1 to 8
Cells(RO, CL) = Count
Count = Count + 1
Next RO
Next CL
End Sub
With Loops or If statements, they need to be ended in the order they were started.
So for an if statement in a for loop within an if statement you do:
If ...
For ...
If ...
Elseif ...
Else ...
End If
Next
End If
The structure needs to be kept like that.

Related

How can i let excel VBA sum up my list of variable values to a certain number and create multiple "sets"

good evening, im quite a long lurker here but i have ran into an issue i cant seem to find a solution for. i have no idea if i post this correctly as i dont have any base code to provide because im not sure if it is possible at all in VBA.
i have a list with values that is variable in size and the induvidual values range from 1 to 33. (this is based on pallet amounts in trucks) what i would like to be able to do is select that range and have a vba code sort out the best way to sum up my values to 33 (But never ever over 33!) and create an array with the values and move on to the next "set" and put the next values that add to 33 in a new array. i know how to do it chronically (thanks to another user here on stackoverflow) but that would mean that it isnt the most efficient option.
lets say i have a list of 5 different values:
10
15
8
22
19
this would create the following "sets":
25
30
19
but if the order of the 5 values would change to:
19
22
15
10
8
it would create the following sets:
19
22
15
18
now i have found a way to define a variable to the optimal number of trucks the code should create, but with the second list it would result in an error if the code i have now goes through that list chronically.
so to summarize, is it possible to create a code that would look at a selection of values and decide what the best most efficient way is of combining values the closest to 33.
ill provide the code i have now, please note it is not at all finished yet and very basic as its just the start of my project and pretty much the core feature of what i want to achieve. if i need to provide more info or details please let me know
thanks in advance. and many thanks to a huge group of people here who unbeknownst to themselves have already helped me save hours upon hours of work by providing their solutions to problems i had but didnt need to ask
here is my code:
Sub test()
Dim ref, b As Range
Dim volume, i As Integer
Dim test1(), check, total As Double
Dim c As Long
Set ref = Selection
volume = ref.Cells.Count
c = ref.Column
ReDim test1(1 To volume)
'this creates a total of all the values i select
For Each b In ref
total = total + b
Next b
'this determines when to round up or down
check = total / 33 - Application.WorksheetFunction.RoundDown(total / 33, 0)
If check < 0.6 Then
total = Application.WorksheetFunction.RoundDown(total / 33, 0)
Else
total = Application.WorksheetFunction.RoundUp(total / 33, 0)
End If
'this creates an array with all the values
i = 1
Do Until i = volume + 1
test1(i) = Cells(i, c).Value
i = i + 1
Loop
'this is just a way for me to check and verify my current part of the code
MsgBox (Round(test1(8), 2))
MsgBox (total)
End Sub
You can change the cell result location as per your wish. I am showing the result in the immediate window.
Sub test()
Dim CellsCount As Integer
CellsCount = Selection.Cells.Count
Dim i, j As Long
Dim x, y As Long
Dim SumLoop As Long
SumLoop = 0
x = 1
y = 1
For i = x To CellsCount
Do
For j = y To CellsCount
SumLoop = SumLoop + Selection.Cells(j).Value
If SumLoop < 33 Then
Debug.Print SumLoop
y = j + 1
If y = CellsCount + 1 Then Exit Sub
Else
SumLoop = 0
x = j
y = j
Exit For
End If
Next
Loop While SumLoop < 33
Next
End Sub
This is a straight brute force, checking every single combination, if your set gets too big this will slow way down but it was <1 second on a set of 1,000.
I loaded values into Column A. Outputs the lowest amount of trucks you need.
You can probably reduce the amount of variables by using a type or class but wanted to keep it relatively simple.
Dim i As Long
Dim lr As Long
Dim limit As Long
Dim count As Long
Dim sets As Long
Dim best As Long
Dim start As Long
Dim addset As Boolean
Dim loopcounter As Long
limit = 33
With Sheets("Sheet1")
lr = .Cells(.Rows.count, 1).End(xlUp).Row
Dim arr() As Long
ReDim arr(0 To lr - 2)
For i = 2 To lr
arr(i - 2) = .Cells(i, 1).Value 'Load array
Next i
start = 0
i = start
Do
If count + arr(i) <= limit Then
count = count + arr(i)
addset = False 'Just for tracking the final set
Else
addset = True
sets = sets + 1
count = arr(i)
End If
i = i + 1
If i > UBound(arr) Then
i = 0 'reset index
End If
loopcounter = loopcounter + 1 'tracking items in set
If loopcounter > UBound(arr) Then
If addset = False Then
sets = sets + 1 'adding final set if not already added
End If
Debug.Print start, sets
If best > sets Or best = 0 Then
best = sets 'Get the lowest value
End If
'resetting values
loopcounter = 0
sets = 0
start = start + 1
i = start
If start > UBound(arr) Then
Exit Do
End If
End If
Loop
End With
Debug.Print best

i = empty how can i solve this?

Dim a As Integer
a = 0
For i = 4 To i + 1
Set xRange = Sheets("sayfa4").Rows(i)
For j = 1 To 10
If Sheets("sayfa4").Cells(i, j) > 0 And Sheets("sayfa4").Cells(i, j) = Application.WorksheetFunction.Min(xRange) Then
a = a + 1
Sheets("sayfa4").Cells(i, j).ClearContents
Sheets("sayfa4").Cells(15 + a, 1) = i
Sheets("sayfa4").Cells(15 + a, 2) = j
i = j - 1
End If
Next j
Next i
i don't get any errors or something i just can't execute it nothing happens on excel sheet can you help me guys what is the problem
when i try with F8 it shows "i = empty"
my main problem is declaring the next i actually
when i choose a cell(i,j) and printing the value of it
my next i should be j and after i should start to search min value of j row and it turns out next i
I tryed to understand your logic and rewrote the code:
Option Explicit
Sub test()
Dim a As Integer
Dim i As Long, j As Long
Dim xRange As Range
a = 0
i = 4
For i = 4 To i + 1
Set xRange = Sheets("sayfa4").Rows(i)
For j = 1 To 10
If Sheets("sayfa4").Cells(i, j) > 0 And Sheets("sayfa4").Cells(i, j) = Application.WorksheetFunction.Min(xRange) Then
a = a + 1
'Sheets("sayfa4").Cells(i, j).ClearContents
Sheets("sayfa4").Cells(15 + a, 1) = i
Sheets("sayfa4").Cells(15 + a, 2) = j
Exit For
'i = j - 1
End If
Next j
Next i
End Sub
If you are looking for the minimum value of a selection, this code should solve your issue
This statement is meaningless
For i = 4 To i + 1
this is because i is uninitialized or zero and so the loop is really For i=4 to 1 which will be ignored.
If you do not know how many times to iterate use a Do Loop instead. Only use For for fixed iterations and do not alter the iteration variable inside the loop.
If you want to stop the loop use Exit For, or Exit Do and if you want to end the function or subroutine processing use Exit Function or Exit Sub.
To skip to the next iteration in VBA you would use an If structure, since it does not have a continuation keyword like other languages have. (thanks #BigBen)

For Loops to perform a Step of 3 only after inserting a value into 6 rows of cells

The following code I have Will paste a value code of "01" to a cell and then skip 4 rows continuously, until reaching the end of count within the for loop. I want to run a similar loop for "02", but rather than "Step" (skip) 4 rows, I would like it to insert the value in 6 consecutive rows within the same column and then skip 3 rows continuously until reaching the end of count. I am 2 weeks new to vba, so I hope I am explaining this correctly.
Dim i As Long
If Sheet3.Range("C22").Value = "01" Then
For i = 3 To 202 Step 4
ActiveWorkbook.Sheets("CrewEntries").Cells(i, 6).Value = _
ActiveWorkbook.Sheets("MonData").Cells(22, 5).Value
Next i
ElseIf Sheet3.Range("C22").Value = "02" Then
For i = 3 To 152
ActiveWorkbook.Sheets("CrewEntries").Cells(i, 6).Value = _
ActiveWorkbook.Sheets("MonData").Cells(22, 5).Value
Next i
End If
Maybe like this:
Dim i As Long, v
v = ActiveWorkbook.Sheets("MonData").Cells(22, 5).Value
If Sheet3.Range("C22").Value = "01" Then
For i = 3 To 202 Step 4
ActiveWorkbook.Sheets("CrewEntries").Cells(i, 6).Value = v
Next i
ElseIf Sheet3.Range("C22").Value = "02" Then
For i = 3 To 152 Step 9 '6 filled + 3 empty = 9
ActiveWorkbook.Sheets("CrewEntries").Cells(i, 6).Value = v
Next i
End If
For such a kind of question, I would advise a while-loop, as in this piece of pseudo-code:
dim condition as boolean
dim loop_step, interesting_value as integer
condition = true
loop_step = 1 'just in order to be sure that it never is 0, this might create an infinite loop
interesting_value = 0 ' or some other initialisation value
while condition do
if <some_first_condition>
then
do_first_thing(interesting_value, ...)
loop_step = 3
else
do_second_thing(interesting_value, ...)
loop_step = 6
end if
interesting_value = interesting_value + loop_step
if <some_other_condition> then condition = false
Wend
Sub EarningCode()
Dim CpID As String
Dim i As Long
Dim p As Long
CpID = ActiveWorkbook.Sheets("MonData").Cells(22, 3).Value
For i = 3 To 452
If p = 9 Then
p = 1
Else
p = p + 1
End If
If p < 7 Then
ThisWorkbook.Worksheets("CrewEntries").Cells(i, 4).Value = "02"
End If
Next i
End Sub

VBA Code to add first 10 even numbers regardless of number of inputs in a column

I ran into a problem when I try to add the first 10 even numbers in a column regardless of the number of inputs someone has entered into said column.
The issue occurs when there are less than 10 inputs (in my case 7) and I have tried to break the loop if there are no more numbers after the last one but it doesn't seem to work as it crashes Excel; most probably because it loops infinitely.
The original code was fine until I entered below 10 even numbers. When I did it would loop infinitely and crash so I inputted a forceful break in the code (hence the Count=999) but it does not seem to work
Sub TenPosInt()
Dim Total As Integer, size As Integer, myRange As range
Dim Count As Integer
Count = 1
Set myRange = range("W:W")
size = WorksheetFunction.CountA(myRange)
While Count <= 10
If IsEmpty(Cells(Count, "W")) Then
Count = 999
End If
If Cells(Count, "W").Value Mod 2 = 0 Then
Total = Total + Cells(Count, "W").Value
Count = Count + 1
End If
Wend
MsgBox Total
End Sub
My Inputs are currently 2,4,6,5,2,4,6,8,1,3,5 so it does not meet the 10 even integers, however I still want it to run regardless (hence the Count=999 line). The correct return should be 32.
A Do-While/Until loop is recommended instead of While-Wend (see this).*
Here I use a separate counter for row and the number of even values (and stole David's idea of combining the two conditions in the Do line).
Sub TenPosInt()
Dim Total As Long, r As Long, Count As Long
r = 1
Do Until Count = 10 Or Cells(r, "W") = vbNullString
If Cells(r, "W").Value Mod 2 = 0 Then
Total = Total + Cells(r, "W").Value
Count = Count + 1
End If
r = r + 1
Loop
MsgBox Total & " (" & Count & " even numbers)"
End Sub
*Actually I would be more inclined to use one of the other gent's answers, but I have tried to stick as close to yours as possible. (Also a good idea to check a cell is numeric before checking for even-ness.)
Just for fun - here is an approach that uses a For...Next loop, allows for non-numeric entries in Column W, and handles the possibility of blank rows between entries.
Sub TenPosInt()
Dim lastRow As Long
lastRow = Cells(Rows.Count, "W").End(xlUp).Row
Dim i As Long
For i = 1 To lastRow
If Not IsEmpty(Cells(i, "W")) Then
If IsNumeric(Cells(i, "W")) Then
If Cells(i, "W").Value Mod 2 = 0 Then
Dim counter As Long
counter = counter + 1
Dim total As Long
total = total + Cells(i, "W").Value
If counter = 10 Then Exit For
End If
End If
End If
Next
MsgBox total
End Sub
Why not use a standard for loop across a range? this would give more specific inputs for the subroutine.
Description of what is occuring below has been commented out to allow for copy/pasting more easily.
'Define your range (you use columns("W"), but narrow that)... assuming you start in row 2 (assumes row 1 is headers), move to the last row, of the same columns:
lr = cells(rows.count,"W").end(xlup).row
'so you know the last row, loop through the rows:
for i = 2 to lr
'Now you will be doing your assessment for each cell in column "W"
if isnumeric(cells(i,"W").value) AND cells(i,"W").value mod 2 = 0 then
s = s + cells(i,"W").value
counter = counter + 1
if counter = 10 then exit for
end if
'Do that for each i, so close the loop
next i
'You now have determined a total of 10 items in the range and have added your items. Print it:
debug.print s
Edit1: got a comment to not break-up the code in an explanatory fashion, so I have added ' to comment out my explanations in an effort to make my coding portion copy/pasteable as a lump.

Autofill increments when given a string

I've beeing searching around for quite a while and trying.
What I want to do, is basically an auto-fill that only increments when it finds a value of "02:00" on the column F
1 00:15 
1 00:45 
1 01:00 
1 01:15 
1 01:30 
1 01:45 
1 02:00  -
2 00:15 
2 00:45 
2 01:00 
2 01:15 
2 01:30 
2 01:45 
2 02:00 -
3 00:15 
3 00:45 
3 01:00 
3 01:15 
3 01:30 
3 01:45 
3 02:00 
The code I've does it almost right but always end up filling the column with the last value of the iterator.
'Days :D
i = 0
For Each c In Range("F57:F77")
For Each x In Range("E57:F77")
x.Value = i
If c.Value = "02:00 " Then
i = i + 1
If i >= 4 Then
'Exits when overlap
Exit Sub
End If
Debug.Print i
End If
Next
Next
Have you considered using a native worksheet function like COUNTIF for a bulk operation?
With Worksheets("Sheet7")
With .Range("F57", .Cells(Rows.Count, "F").End(xlUp))
.Offset(0, -1).Formula = "=COUNTIF(F$57:F57, ""02:00"")+1"
.Cells = .Value
End With
End With
How about:
Sub qwerty()
Dim x As Long, r As Range
x = 1
For Each r In Range("F57:F77")
r.Offset(0, -1).Value = x
If r.Text = "02:00" Then x = x + 1
Next r
End Sub

Resources