sub will not loop through second if statement vba - vba

Really hope someone out there can help me. So i have the following code. The independent codes work fine by themself, but when executing the script, it only loops through the first condition. What i want it to do is to loop through all the code, each time. I think it's a small thing I am missing, but i can't seem to find a solution.
Sub Copypre()
Dim i As Integer
Dim n As Integer
For i = 2 To 10
'Checks the number of entries in the "Pre" table, to make sure that there are no spaces between the lines
On Error Resume Next
n = Worksheets("Pre").Range("A2:A6000").Cells.SpecialCells(xlCellTypeConstants).Count
If n = Null Then
n = i
'Goes through the different sheets to find all "pre" values and paste them in the "Pre" sheet
If ThisWorkbook.Sheets("273").Range("A" & i).Value = "Pre" Then
Range(Cells(i, 1), Cells(i, 3)).Select
Selection.Copy
Sheets("Pre").Select
Range("A" & n).Select
ActiveSheet.Paste
Sheets("2736").Select
End If
End If
Next i
End Sub

There are a couple of issues with your code, but the main issue may be that If n = Null will never be true since an integer cannot be Null. You could change this to If n = 0.
A couple of things to consider:
Error handling: Always go back to normal error handling with On Error GoTo 0 as soon as possible. This way you would have known (assuming that there is no sheet "2736" in your workbook) that your code is trying to select a sheet that does not exist.
Range argument: Be carefull when not specifying the sheet when using the Range (and Cells) argument. When you switch back and fourth between different sheets that you select, there is a change that you may loose track of what sheet the Range is returning data from. Consider declaring each worksheet and then copy your ranges like:
Dim w273 As Worksheet
Set w273 = ThisWorkbook.Sheets("273")
w273.Range(w273.Cells(i, 1), w273.Cells(i, 3)).Copy

Loops can quickly consume time with long columns of data and I suspect that your code was heavily redacted. Try this alternate method of block copying across to the destination worksheet.
Sub Copypre()
With Sheets("273").Cells(1, 1).CurrentRegion
.AutoFilter
.Columns(1).AutoFilter field:=1, Criteria1:="=Pre"
If CBool(Application.Subtotal(103, .Offset(1, 0))) Then
.Offset(1, 0).Resize(, 3).Copy _
Destination:=Sheets("Pre").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
End If
.AutoFilter
End With
End Sub
All that can get accomplished without a single variable declaration.
Addendum:
As to your original question, the whole if "pre"/copy/paste section is nested within the if n = Null so it can only be reached if n = Null is true. If there are no .SpecialCells(xlCellTypeConstants)to count, n will be assigned its default value (e.g. 0). Zero is not equal to Null so that condition is never met. To check your code, add the following line.
On Error Resume Next
n = Worksheets("Pre").Range("A2:A6000").Cells.SpecialCells(xlCellTypeConstants).Count
Debug.Print "n is " & n
After running it, open the Immediate window with Ctrl+G. If there are no non-formula values in Pre!A2:A6000 you should see n is 0.

Thanks allot for all the advices. The null trick worked! I am totally new to VBA so it's nice to get some tips and tricks from experts. I will try to make the code more simple as Jeeped mentioned, as this is not very elegant. In regards to the sheets, i can totally understand the confusion, i have fixed that also. It works now and looks like this:
Sub Copypre()
Dim i As Integer
Dim n As Integer
For i = 2 To 5000
' Checks the number of entries in the "Pre" table, to make sure that there are no spaces between the lines
On Error Resume Next
n = Worksheets("Pre").Range("A2:A6000").Cells.SpecialCells(xlCellTypeConstants).Count
' Goes through the different sheets to find all pre values and paste them in the "Pre" sheet
If ThisWorkbook.Sheets("2736").Range("A" & i).Value = "Pre" Then
Sheets("2736").Select
Sheets("2736").Range(Cells(i, 1), Cells(i, 3)).Select
Selection.Copy
Sheets("Pre").Select
Range("A" & (n + 2)).Select
ActiveSheet.Paste
Sheets("2736").Select
Sheets("2736").Select
Range(Cells(i, 5), Cells(i, 6)).Select
Selection.Copy
Sheets("Pre").Select
Range("E" & (n + 2)).Select
ActiveSheet.Paste
Sheets("2736").Select
End If
Next i
End Sub

Related

Do Loop + Match

I am looking to delete everything that does not match my inputbox value. However, it seems like the loop I am using is not working at all! It seems the code does not read the loop. The loop should delete the entire row of each cell in the column E that does not match my inputbox variable. I run the code, insert the value in the input box and nothing gets deleted.
Can someone PLEASE help me??
'Get the Tenrox code to be deleted
tenroxcode = InputBox("Insert the Tenrox Code that you want to keep")
'Find and delete all unnecessary tenrox codes
r = Application.Match(tenroxcode, Columns("E"), 0)
Do While IsError(r)
Rows(r).EntireRow.Delete
r = Application.Match(tenroxcode, Columns("E"), 0)
Loop
Try this:
tenroxcode = InputBox("Insert the Tenrox Code that you want to keep")
With Worksheets("Sheet1") ' change as needed
With .UsedRange.Columns(5) 'assumes data is in column a1 and contiguous across cells
If Not .Find(tenroxcode, lookat:=xlWhole) is Nothing Then
.AutoFilter 1, "<>" & tenroxcode
.offset(1).specialcells(xlCellTypeVisible).entirerow.delete 'offset so header row stays
End If
End With
.AutoFilterMode = False
End With
A simple way to do this is to use the Autofilter to filter on anything that doesn't match your condition, and then delete the rows. And I'd suggest turning your data into an Excel Table first, because it simplifies code.
Simply fire up the macro recorder, and you'll get code like this::
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=1, Criteria1:= _
"<>SomeValue", Operator:=xlAnd
Range("Table1[Column1]").Select
Selection.EntireRow.Delete
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=1
That should be enough to get you started.

Excel VBA Type Mismatch with If function

I am very new to VBA and have been teaching myself for the last week. I have taken on a task that is maybe a bit to complex for me.
I have a document with columns A - AE
I need to go through this document and move information on to separate sheets, depending on what it is.
I am now trying to use an IF statement that needs to match 2 requirements before it moves the information. I can get each individual requirement to work but not both together as keep getting a Type Mismatch error.
I have no idea what i am doing wrong. Any help will be much appreciated.
Sub copyrows()
Dim Test As Range, Cell As Object
Set Test = Range("G2:Z4000") 'Substitute with the range which includes your True/False values
For Each Cell In Test
If IsEmpty(Cell) Then
Exit Sub
End If
If Cell.Value = "Refund" And "Commission" Then
Cell.EntireRow.Copy
Sheet3.Select 'Substitute with your sheet
ActiveSheet.Range("A65536").End(xlUp).Select
Selection.Offset(1, 0).Select
ActiveSheet.Paste
End If
Next
End Sub
If Cell.Value = "Refund" And "Commission" Then
Should instead read:
If Cell.Value = "Refund" Or Cell.Value = "Commission" Then
You have to be explicit with each condition separated by boolean operators like AND or OR.
The reason for your error is already mentioned in the answer above by #IanL
However, your code is far from being optimized.
You can replace your 5 lines:
Cell.EntireRow.Copy
Sheet3.Select 'Substitute with your sheet
ActiveSheet.Range("A65536").End(xlUp).Select
Selection.Offset(1, 0).Select
ActiveSheet.Paste
With 1:
Cell.EntireRow.Copy Destination:=Sheet3.Range("A65536").End(xlUp).Offset(1)
Which is not using Select, ActiveSheet, or Selection, just using fully qualified Range object.

How to get VLOOKUP to select down to the lowest row in VBA?

Looking to automate the insertion of a VLOOKUP formula in a cell.
When recording the macro I instruct it to populate the columns below with the same formula. Works great, however, there is an issue when the table that the VLOOKUP searches through changes (more or less rows).
As it's recorded, the VLOOKUP drops down to the final row in the table (273). However, I want to set it up so that it will go down to the very last row. Meaning that I can run the script on tables of varying numbers of rows.
Selected columns will remain the same.
Range("AJ2").Select
ActiveCell.FormulaR1C1 = _
"=VLOOKUP(RC[-20], Previous!R2C2:R273C22,17,FALSE)"
try this:
With Worksheets("Previous")
Range("AJ2").FormulaR1C1 = _
"=VLOOKUP(RC[-20], Previous!R2C2:R" & .Cells(.Rows.Count, 2).End(xlUp).Row & "C22,17,FALSE)"
End With
where:
Range("AJ2")
will implicitly reference the ActiveSheet
.Cells(.Rows.Count, 2).End(xlUp).Row
will reference "Previous" worksheet, being inside a With Worksheets("Previous")- End With block
#nbayly said it, plenty of posts on this. Infact i have provided an answer to this before here:
How to Replace RC Formula Value with Variable
below is slightly modified for a dynamic range, which is what i believe you are looking for
For j = n To 10 Step -1
If Cells(j, 1).Value = "" Then
Cells(j, 1).Formula = "=VLookup(RC20,Previous!R2C2:R273C22,17,FALSE)"
End If
Next j
remember to define j as long and n=sheets("sheetname)".cells(rows.count,1).end(xlup).row
replace 10 in j = n to 10 with the starting row number

VBA Look for Duplicate, then assesses another cells value

I initially asked a question below.
Basically I want VBA to look at Column L:L. If the cell=program, and the cell below does not equal lathe I want the row above to be deleted. If the cell doesn't equal program continue looking until the end of the data.
Realized I needed to look at the data different, as I was losing rows that I needed to stay.
New logic, which I think will still use some of the old program, but
it needed to be sorted using another column. I need the VBA to look at
column E:E. If the cell in the row below is a duplicate of the cell
above, then look at column L in that row to see if the cell says
Program. If so the cell below should be Lathe. If not lathe delete the
Program Row, If it is Lathe leave both rows. If the Cells in Column E
are not duplicates, continue looking. EX. If E5=E6, If not continue
looking. If yes Look at L5 to see if it say Program. If so look at L6
for Lathe. If not delete ROW5.
This I what I received that answered teh first question which I think will still get used
Dim rngCheck as Range
Dim rngCell as Range
Set rngCheck = Range("L1", "L" & Rows.Count - 1)
For each rngCell in rngCheck
If rngCell.value = "Program" And rngCell.offset(1,0).value <> "lathe" then
rngCell.offset(-1,0).EntireRow.Delete
End if
Next rngCell
This should do it
For i = ThisWorksheet.Cells.SpecialCells(xlCellTypeLastCell).Row to 2 step -1
' that row do you mean the duplicate or the original (I am using original)
If ThisWorksheet.Cells(i, 5) = ThisWorksheet.Cells(i-1, 5) and _
ThisWorksheet.Cells(i-1, 12) = "Program" and ThisWorksheet.Cells(i, 12) <> "Lathe"
ThisWorksheet.Rows(i-1).EntireRow.Delete
End If
Next i
When deleting it is best to iterate from last to first. If prevent you from skipping rows.
Sub RemoveRows()
Dim x As Long
With Worksheets("Sheet1")
For x = .Range("E" & .Rows.Count).End(xlUp).Row To 2 Step -1
If .Cells(x, "E").Value = .Cells(x - 1, "E").Value And Cells(x - 1, "L").Value = "Program" Then
.Rows(x).Delete
End If
Next
End With
End Sub

How can I put consecutive numbers in an active range of cells using VBA?

I have a selected series of 400 cells in one common and want to number them. However, I want this to be dynamic so if I select a bigger range it will number them. Basically how do I number the active cells. I tried doing it using a macro but because of the way my data is structured there is nothing in the row to start and consequently I couldn't get an xldown function to work. Thanks in advance I really appreciate it.
This will fill either a single-column or single-row contiguous selection (i.e. a single area):
Sub Tester()
With Selection
If .Columns.Count = 1 Then
.Value = .Parent.Evaluate("Row(1:" & .Rows.Count & ")")
ElseIf .Rows.Count = 1 Then
.Value = Application.Transpose( _
.Parent.Evaluate("Row(1:" & .Columns.Count & ")"))
End If
End With
End Sub