Compile error: Next without For || VBA - vba

I have a problem with my code, an error appears, and I don;t understand why. The error is:
"Compile error: Next without For"
I do not understand why it is like that. I am new to coding so any help and comments are more than welcome.
This is the code, the Next which is pointed as the one without For is provided a comment.
Sub CGT_Cost()
startrow = Worksheets("GUTS").Cells(10, 1) 'Here I put 1
endrow = Worksheets("GUTS").Cells(11, 1) 'Here I put 1000
For x = endrow To startrow Step -1
If Cells(x, "Q").Value = "Sale" Then
If Cells(x, "D").Value = "1" Then
For i = 1 To 1000
If Cells(x - i, "R").Value <> "1" Then
Next i
Else
Range("G" & x).FormulaR1C1 = "=R[-" & i & "]C/R[-" & i & "]C[-1]*RC[-1]"
End If
End If
End If
Next x
End Sub
Thank you all in advance,
with best regards,
Artur.

Every For statement with a body must have a matching Next, and every If-Then statement with a body must have a matching End If.
Example:
For i = 1 To 10 '<---- This is the header
Hello(i) = "Blah" '<---- This is the body
Next i '<---- This is the closing statement
You have part of the body of your If statement inside your For i loop, and part of it outside. It has to be either ALL inside or ALL outside. Think through the logic and see what it is you want to do.

you have overlapping loops-perhaps
Sub CGT_Cost()
startrow = Worksheets("GUTS").Cells(10, 1) 'Here I put 1
endrow = Worksheets("GUTS").Cells(11, 1) 'Here I put 1000
For x = endrow To startrow Step -1
If Cells(x, "Q").Value = "Sale" Then
If Cells(x, "D").Value = "1" Then
For i = 1 To 1000
If Cells(x - i, "R").Value <> "1" Then
'
Else
Range("G" & x).FormulaR1C1 = "=R[-" & i & "]C/R[-" & i & "]C[-1]*RC[-1]"
End If
Next i
End If
End If
Next x
End Sub

Related

Adding multiple values in one cell

I have this piece of code
Sub neviem()
Dim ws As Worksheet
Dim i As Range
Dim j As Long
Set i = Range("GKC")
For j = i.Rows.Count To 1 Step -1
If IsEmpty(Range("E3").Value) Then
If i(j, 1) Like Range("E2") Then
i(j, 1).Offset(0, 1).Copy Range("E2").Offset(1, 0)
End If
ElseIf i(j, 1) Like Range("E2") Then
i(j, 1).Offset(0, 1).Copy Range("E2").Offset(1, 0) & "," & Range("E2").Value
End If
Next
End Sub
With this code I'm trying to add multiple text values in the same cell. The first part is ok when I run it, it will add a text value. The problem is when I run it for a second time it gives me an error
runtime err 1004 copy method class failed
so I'm not able to put more text values next to the one I already have.
Is this possible in VBA?
Instead this i(j, 1).Offset(0, 1).Copy Range("E2").Offset(1, 0) & "," & Range("E2").Value
Try this i(j, 1).Offset(0, 1) = Range("E3") & "," & Range("E2")

Why is my Excel VBA macro crashing?

So I made a Excel macro and when i try to run it, it keeps crashing. Here it is:
result = "fail"
j = 4
Do While result = "fail" Or Cells(2, j) <> " "
If Cells(2, j).Value >= 15 Then
result = "pass"
Else
j = j + 1
End If
Loop
Your Do While loop Do While result = "fail" Or Cells(2, j) <> " " will run if either result = "fail" or Cells(2, j) <> " ".
I think you meant to exit the loop once you reach an empty cell, or you get result = "pass". So, you need to change your Or to And:
Do While result = "fail" And Cells(2, j) <> " "
If you want to exit in case there are only empty space in the cell, add also Trim.
Do While result = "fail" And Trim(Cells(2, j)) <> ""
changed or to and.
the loop needs to stop somewhere, currently it is going into an endless loop.
pls try below code and let me know if this is what you wanted or I have understood your requirement incorrectly.
Sub tester()
result = "fail"
j = 4
Do While result = "fail" And Cells(2, j) <> ""
If Cells(2, j).Value >= 15 Then
result = "pass"
Else
j = j + 1
End If
Loop
End Sub

Optimise excel VBA code - combine resident address

I have done the following 2 VBA code in excel. Main purpose is to combine multiple address rows into a single line. Problem is it takes forever to run. Is there anyway I can optimise it?
The data is as such, there is a case# for each of the customer address. The customer address can be split into multiple rows. Example: "Address row 1 - Block 56", "Address row 2 - Parry Avenue", "address row 3 - Postal code". There is a blank space between each new address.
My purpose is to combine the address into a single line, and remove the empty rows in between the case numbers eg "Block 56 Parry Avenue Postal code". There are approx 26K case numbers.
Sub test()
Dim l As Long
Dim lEnd As Long
Dim wks As Worksheet
Dim temp As String
Application.EnableEvents = False
Application.ScreenUpdating = False
Set wks = Sheets("data")
wks.Activate
lEnd = ActiveSheet.UsedRange.Rows.Count
For l = 3 To lEnd
If Not IsEmpty(Cells(l, 1)) Then
Do Until IsEmpty(Cells(l + 1, 4))
temp = Cells(l, 4).Value & " " & Cells(l + 1, 4).Value
Cells(l, 4).Value = temp
Cells(l + 1, 4).EntireRow.Delete
Loop
Else: Cells(l, 1).EntireRow.Delete
Do Until IsEmpty(Cells(l + 1, 4))
temp = Cells(l, 4).Value & " " & Cells(l + 1, 4).Value
Cells(l, 4).Value = temp
Cells(l + 1, 4).EntireRow.Delete
Loop
End If
Next l
End Sub
and the 2nd code I tried
Sub transformdata()
'
Dim temp As String
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Range("A3").Select
Do Until IsEmpty(ActiveCell) And IsEmpty(ActiveCell.Offset(1, 0))
Do Until IsEmpty(ActiveCell.Offset(1, 3))
temp = ActiveCell.Offset(, 3).Value & " " & ActiveCell.Offset(1, 3).Value
ActiveCell.Offset(, 3).Value = temp
ActiveCell.Offset(1, 3).EntireRow.Delete
Loop
ActiveCell.Offset(1, 0).EntireRow.Delete
ActiveCell.Offset(1, 0).Select
Loop
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Change the line lEnd = ActiveSheet.UsedRange.Rows.Count. Incorrect way of finding last row. You may want to see This
To delete rows where Cells(l, 1) is empty, use Autofilter. See This
Do not delete rows in a straight loop. Use a reverse loop. Or what you could do is identify the cells that you want to delete in a loop and then delete them in one go after the loop. You may want to see This
Here is a basic example.
Let's say your worksheet looks like this
If you run this code
Sub test()
Dim wks As Worksheet
Dim lRow As Long, i As Long
Dim temp As String
Application.ScreenUpdating = False
Set wks = Sheets("data")
With wks
'~~> Find Last Row
lRow = .Range("C" & .Rows.Count).End(xlUp).Row
For i = lRow To 2 Step -1
If Len(Trim(.Range("C" & i).Value)) <> 0 Then
If temp = "" Then
temp = .Range("C" & i).Value
Else
temp = .Range("C" & i).Value & "," & temp
End If
Else
.Range("D" & i + 1).Value = temp
temp = ""
End If
Next i
End With
End Sub
You will get this output
Now simply run the autofilter to delete the rows where Col D is empty :) I have already give you the link above for the same.
The code below will copy all the data into an array, consolidate it, and add it to a new worksheet. You'll need to make COLUMNCOUNT = the number of columns that contain data.
Sub TransformData2()
Const COLUMNCOUNT = 4
Dim SourceData, NewData
Dim count As Long, x1 As Long, x2 As Long, y As Long
SourceData = Range("A" & Range("D" & Rows.count).End(xlUp).Row, Cells(3, COLUMNCOUNT))
For x1 = 1 To UBound(SourceData, 1)
count = count + 1
If count = 1 Then
ReDim NewData(1 To 4, 1 To count)
Else
ReDim Preserve NewData(1 To 4, 1 To count)
End If
For y = 1 To UBound(SourceData, 2)
NewData(y, count) = SourceData(x1, y)
Next
x2 = x1 + 1
Do
NewData(4, count) = NewData(4, count) & " " & SourceData(x2, 4)
x2 = x2 + 1
If x2 > UBound(SourceData, 1) Then Exit Do
Loop Until IsEmpty(SourceData(x2, 4))
x1 = x2
Next
ThisWorkbook.Worksheets.Add
Range("A1").Resize(UBound(NewData, 2), UBound(NewData, 1)).Value = WorksheetFunction.Transpose(NewData)
End Sub

vba code not taking correct value of a cell from file

This is my code:
Dim RowLast As Long
Dim sunmLast As Long
Dim tempLast As Long
Dim filterCriteria As String
Dim perporig As Workbook
Dim x As String
tempLast = ThisWorkbook.Sheets("combine BOMs").Cells(Rows.Count, "E").End(xlUp).Row
Range("D5:G" & tempLast).ClearContents
Range("G5:G" & tempLast).Interior.ColorIndex = 0
tempLast = ThisWorkbook.Sheets("combine BOMs").Cells(Rows.Count, "A").End(xlUp).Row
Range("A5:A" & tempLast).ClearContents
tempLast = ThisWorkbook.Sheets("combine BOMs").Cells(Rows.Count, "B").End(xlUp).Row
'Perpetual
Set perporig = Workbooks.Open("\\Etnfps02\vol1\DATA\Inventory\Daily tracking\perpetual.xlsx", UpdateLinks:=False, ReadOnly:=True)
RowLast = perporig.Sheets("perpetual").Cells(Rows.Count, "A").End(xlUp).Row
perporig.Sheets("perpetual").Cells(3, 1) = "Part Number"
For i = 5 To tempLast
Cells(i, 1) = i - 4
perporig.Sheets("perpetual").AutoFilterMode = False
filterCriteria = ThisWorkbook.Sheets("combine BOMs").Range("B" & i).Value
perporig.Sheets("perpetual").Range("A3:J" & RowLast).AutoFilter Field:=1, Criteria1:=filterCriteria
Counter = perporig.Sheets("perpetual").Cells(RowLast + 1, 1).End(xlUp).Row
If Counter = 3 Then
Cells(i, 5).Value = "Not on perpetual"
Else
ThisWorkbook.Sheets("combine BOMs").Cells(i, 5).Value = WorksheetFunction.Sum(perporig.Sheets("perpetual").Range("H4:H" & RowLast).SpecialCells(xlCellTypeVisible))
x = perporig.Sheets("perpetual").Cells(Cells(RowLast + 1, 1).End(xlUp).Row, 4).Value
MsgBox x, vbOKOnly, perporig.Sheets("perpetual").Cells(RowLast + 1, 1).End(xlUp).Row
ThisWorkbook.Sheets("combine BOMs").Cells(i, 4).Value = x
End If
perporig.Sheets("perpetual").AutoFilterMode = False
Next
perporig.Close savechanges:=False
This is the file from which I am clicking my button (or ThisWorkbook)
This is the perpetual file when it is running on the last row of data:
Notice the difference in D9280: it shows stocking type as "P" in the perpetual file, but "B" in my final result, which comes up in cell D12 in ThisWorkbook. To debug, I created a Msgbox prompt for everytime it gets that value for all rows. For every other row, it gives the correct value ("P"), but for this one, msgbox shows "B". The title of the msgbox is the row number, which shows it is taking the correct row whilr getting the value, just that I don't know why it is taking wrong value. I have tried for different data sources, it seems to be coming up with "B" in wrong places every so often.
In the code, just above the line, I have the line to get the on hand quantity, which it does take correctly (I used xltypevisible to paste values for this field, but that is only because I wanted a sum of the results and this was the only way I knew). It's only this stocking type column which shows wrong values randomly.
Any ideas?
Thanks!
1)
Cells(i, 1) = i - 4
as it is written , it refers to perporig.Cells(i, 1)
is this what you want?
2)
perporig.Sheets("perpetual").Range("A3:J" & RowLast).AutoFilter Field:=1, Criteria1:=filterCriteria
would filter from row 3, while you have headers in row 4 and data from row 5 downwards
change it to
perporig.Sheets("perpetual").Range("A4:J" & RowLast).AutoFilter Field:=1, Criteria1:=filterCriteria
3)
what do you think is Counter doing? Not certainly count visible rows only
Credits to findwindow, I found the answer. The .cells(cells()) part didn't have the correct sheet reference for the inner cells():
Instead of
x = perporig.Sheets("perpetual").Cells(Cells(RowLast + 1, 1).End(xlUp).Row, 4).Value
MsgBox x, vbOKOnly, perporig.Sheets("perpetual").Cells(RowLast + 1, 1).End(xlUp).Row
I used this:
With perporig.Sheets("perpetual")
x = .Cells(.Cells(RowLast + 1, 1).End(xlUp).Row, 4).Value
MsgBox x, vbOKOnly, .Cells(RowLast + 1, 1).End(xlUp).Row
End With
And it worked.
Thanks for your help!

How to insert new line in the same cell

I have a small suggestion as I am new to excel vba,
I like to update the some string in a particular cell(j,8) , where t is a string to be update ,t varies from 1 to 10 .
I like to update t value in "alt enter " in a specific cell
if the cell is already fill , I like to add new line
destlastrow = bsmWS.Range("A" & bsmWS.Rows.Count).End(xlUp).Row 'Checking the BSM/CMS/LDP/RCTA (Test Catalog)
For j = 2 To destlastrow
b = onlyDigits(bsmWS.Range("A" & j).value)
If InStr(b, "T") Or InStr(b, "") = 0 Then ' Check if it Test case or Test case ID
' do something
ElseIf InStr(b, "T") Or InStr(b, "D") Then
'do something
ElseIf InStr(b, "P") Or InStr(b, "D") Then
'do something
Else
iComp = StrComp(A, b, vbBinaryCompare)
Select Case iComp
Case 0
With tabWS
Inc value
erow = .Cells(.Rows.Count, 1).End(xlUp).Offset(1, 0).Row
.Range(.Cells(i, 2), .Cells(i, 3)).Copy .Range(.Cells(value, 8), .Cells(value, 9))
tabWS.Range("B" & i).Interior.ColorIndex = 4
End With 'tabWS
End Select
t = tabWS.Cells(value, 8).value
bsmWS.Cells(j, 8).value = t & vbCrLf
Exit For
End If
Next j
Above is my snippet. I want to update "t" value which I get it from another worksheet, want to update into another worksheet (j,8).
Can someone give a valuable suggestion , how to add new lines in (j,8)
More clarity:
If cell (5,8) has already a value
cell (5,8) = "Already a string"
How can I add a new line in the same cell
dim t as string
t= "new line add"
How I can add t value in the next line to cell(5,8)
To get a new line you can use vbNewLine instead of vbCrLf.
To add to the text already in the cell use you can do it like this
bsmWS.Cells(j, 8).value = bsmWS.Cells(j, 8).value & vbNewLine & t