Type mismatch error with a if then statement - excel

I am trying to write a If then statement that cant take out the rows on my worksheet that have been declined or void. So I am trying to get it to look into a Column then delete the rows with those values.
If Columns("K:K") = "Declined" Or "Void" Then
Selection.Delete Shift:=x1Up
End If

You'll instead need to loop through your range. One way to do it is:
Sub t()
Dim rng As Range, curCel As Range
Dim i As Long
Set rng = Range("K1:K100") ' Change as needed
For i = rng.Cells(rng.Rows.Count, 1).Row To rng.Cells(1, 1).Row Step -1
Set curCel = Cells(i, rng.column)
If curCel.Value = "Declined" or curCel.value = "Void" Then
curCel.EntireRow.Delete
End If
Next i
End Sub

you can loop through your cells and remove the rows. I would fully qualify your sheet and try to avoid using ActiveSheet. In the example below we are going from the bottom to the top so not to revisit cells twice or adjust the increment counter.
Dim i As Long
Dim iUsedRange As Long
iUsedRange = ActiveSheet.UsedRange.Rows.Count
For i = iUsedRange To 1 Step -1
If ActiveSheet.Cells(i, 11).Value = "Declined" Or ActiveSheet.Cells(i, 11).Value = "Void" Then
ActiveSheet.Cells(i, 11).EntireRow.Delete Shift:=xlUp
End If
Next i

Related

How to apply a condition to "used range" in whole column as a loop in excel using VBA?

I am beginner at VBA, I am stuck plz help. In this image(linked at the end of paragraph), I am trying to insert line above the cells which contains different name than the name of upper cell. Plz tell me if there is an easier way to do this or how to apply the given if else condition to whole "G" Column...
Still I am adding my code below if you don't need the image...
Sub ScanColumn()
'Application.ScreenUpdating = False
Dim varRange As Range
Dim currentCell As String
Dim upperCell As String
Dim emptyCell As String
currentCell = ActiveCell.Value
bottomCell = ActiveCell.Offset(1, 0).Value
emptyCell = ""
Dim intResult As Integer
intResult = StrComp(bottomCell, currentCell)
Dim emptyResult As Integer
emptyResult = StrComp(currentCell, emptyCell)
'I want to apply below condition to whole G column in used range
If emptyResult = 0 Then
ActiveCell.Select
ElseIf intResult = 0 Then
ActiveCell.Offset(1, 0).Select
Else
ActiveCell.Offset(1).EntireRow.Insert
ActiveCell.Offset(2, 0).Select
End If
End Sub
Here you have, just call the function "evaluateColumn" and pass the parameters, as example the "trial" sub.
Function evaluateColumn(column As String, startRow As Long, wsh As Worksheet)
Dim lastRow As Long
lastRow = wsh.Range(column & wsh.Rows.Count).End(xlUp).Row
Dim i As Long: i = startRow
Do While i < lastRow
If wsh.Cells(i, column).Value <> wsh.Cells(i + 1, column).Value And wsh.Cells(i, column).Value <> "" And wsh.Cells(i + 1, column).Value <> "" Then
wsh.Range(column & i + 1).EntireRow.Insert shift:=xlShiftDown, CopyOrigin:=xlFormatFromLeftOrAbove
i = i + 1
lastRow = lastRow + 1
End If
i = i + 1
Loop
End Function
Sub trial()
evaluateColumn "G", 2, ThisWorkbook.Worksheets("Sheet2")
End Sub
As you can see from the difference between my answer and the one below, your question isn't entirely clear. My code is an event procedure. It will run automatically, as you select a cell within the used range of column G.
If the value of the selected cell is the same as the cell below it the next row's cell will be selected.
If there is a value in either of the two cells, a blank row will be inserted and that row's cell selected. (If you want another row enable the row below the insertion.)
If either of the above conditions are true, do nothing and proceed with the selection the user made.
In order to let this code work it must be installed in the code sheet of the worksheet on which you want the action. It will not work if you install it in a standard code module, like Module1.
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim TriggerRange As Range
Dim Off As Long ' offset from Target for selection
' if more than one cell is selected choose the first cell
If Target.Cells.CountLarge > 1 Then Set Target = ActiveCell
Set TriggerRange = Range(Cells(2, "G"), Cells(Rows.Count, "G").End(xlUp))
' this code will run only if a cell in this range is selected
' Debug.Print TriggerRange.Address(0, 0)
If Not Application.Intersect(Target, TriggerRange) Is Nothing Then
Application.EnableEvents = False
With Target
If .Value = .Offset(1).Value Then
Off = 1
ElseIf WorksheetFunction.CountA(.Resize(2, 1)) Then
Rows(.Row).Insert
' Off = 1 ' or -1 to change the selection
End If
.Offset(Off).Select
End With
Application.EnableEvents = True
End If
End Sub

VBA Index Match with a loop with two conditions

I hope that someone could help me with an index match formula that is made using a loop and storing the results data on the column.
Let's say that my data is following to make it simple:
We have an employee column and a salary column. I want to find all the salary options for HR employees.
I would like to store automatically all the results found on the column J (Researched input is in column I). And I want to finish the loop after not finding any new values.
Here is the data:
My initial code is down below without a loop to go down on the range:
Sub test()
Dim oCell As Range
Dim i As Long
i = 1
Do While Worksheets("Sheet1").Cells(i, 9).Value <> ""
Set oCell = Worksheets("Sheet1").Range("A:A").Find(What:=Worksheets("Sheet1").Cells(i, 9))
If Not oCell Is Nothing Then Worksheets("Sheet1").Cells(i, 10) = oCell.Offset(0, 1)
i = i + 1
Loop
End Sub
The problem stems from two main things:
The .Find range you are searching is the entire column A, which is then set to a .Range object (oCell). However, from my VBA understanding the .Find method cannot apply the cell address of each instance of the string/search parameter you are looking for. It will only apply the cell address of the first one it finds. To set a .Range object of non-contiguous rows you could use UNION function.
The .Find(What:= ... is set to a dynamic range which moves down column I as the loop continues. This means it will never find a match because it is searching the preceding column.
Here is a suggested solution, which hopefully you can adapt to your real world data:
Option Explicit
'
Sub test()
Dim oCell As Range
Dim i As Long
i = 1
Do While Worksheets("Sheet1").Cells(i, 2).Value <> ""
' Included as a sense check when stepping through your code to confirm loop is on correct cell
'Debug.Print Cells(i, 2).Address
'Debug.Print Cells(i, 2).Value
'Debug.Print "NEXT"
Set oCell = Worksheets("Sheet1").Range("A1:A10").Find(What:="HR")
If Not oCell Is Nothing Then Worksheets("Sheet1").Cells(i, 3) = oCell.Offset(0, 1)
i = i + 1
Loop
End Sub
Try this:
Option Explicit
Sub test()
Dim i As Long
Dim wb as Excel.Workbook
Dim ws as Excel.Worksheet
i = 2 ' we don't need the header
set wb = ActiveWorkBook
set ws = wb.Sheets("Sheet1") ' or wb.Sheets(1)
Do While ws.Cells(i, 1) <> ""
If ws.Cells(i,1) = "HR" then
ws.Cells(i, 3) = ws.Cells(i,2)
End If
i = i + 1
Loop
End Sub
Tested and found working

VBA - running an excel macro take forever

I am running this macro and its either taking forever or something is wrong with the way I wrote it. I am new to Excel Macros, and I can't seem to figure out how to write this better that it won't crash my PC.
Sub Test()
ScreenUpdating = True
Dim maxRows As Integer
maxRows = 2332
For i = maxRows To 2 Step -1
'if the cell is empty, delete the row
'otherwise delete the first cell of the row and shift over
If Cells(i, 2).Value = "" Then
Rows(i).Delete
Else
Cells(i, 1).Delete
End If
Next i
ScreenUpdating = False
End Sub
In general, whenever delete is used, it is a good idea to do it only once, for all the cases. However, in the case of the OP, there are two cases separately - deleting a whole row and deleting only one cell. Thus, the delete method could be used twice:
Sub TestMe()
Dim maxRows As Long: maxRows = 2332
Dim myRangeRows As Range
Dim myRangeCells As Range
Dim i As Long
For i = maxRows To 2 Step -1
With Worksheets(1)
If .Cells(i, 2) = "" Then
If myRangeRows Is Nothing Then
Set myRangeRows = .Rows(i)
Else
Set myRangeRows = Union(.Rows(i), myRangeRows)
End If
Else
If myRangeCells Is Nothing Then
Set myRangeCells = .Cells(i, 1)
Else
Set myRangeCells = Union(.Cells(i, 1), myRangeCells)
End If
End If
End With
Next i
If Not myRangeRows Is Nothing Then myRangeRows.Delete
If Not myRangeCells Is Nothing Then myRangeCells.Delete
End Sub
Additionally, whenever the cell in Excel is referred like this Cells(i, 2).Value, then the referring is either to the ActiveSheet or to the Worksheet in which the code resides. Thus, it is a good practice to explicitly mention the worksheet, like in this case:
With Worksheets(1)
If .Cells(i, 2) = "" Then

How do I populate the same column using the text parameters from other columns?

I'm creating a macro document that pulls information from several columns and places that information in assigned buckets in one specific column.
I made the first portion of the code work where it populated no recovery required into the selected column but I do not think it accurately populated the results and I cannot get the second if statement to run.
Sub DecisionTree()
Dim cell As Range
Dim Member_state As String
Dim NO_DR As String
NO_DR = "No Recovery Required"
Dim i As Integer
For i = 1 To 14000 'ActiveSheet.Rows.Count
If ActiveSheet.Cells(RowIndex:=i, ColumnIndex:="D").Value = "Arkansas" Then
ActiveSheet.Cells(RowIndex:=i, ColumnIndex:="K").Value = NO_DR
Else
If ActiveSheet.Cells(RowIndex:=i, ColumnIndex:="E").Value = 1 Then
ActiveSheet.Cells(RowIndex:=i, ColumnIndex:="K").Value = "One"
End If
End If
Next
End Sub
I would like answers for why my if statements are not properly calculating and how I can add other if statements to populate the same column
As far as I can see I only ajusted your code a bit and used ElseIf but your code should work. This is how you could escalate your criterias:
Option Explicit
Sub DecisionTree()
Dim cell As Range
Dim Member_state As String
Dim NO_DR As String
Dim ws As Worksheet 'Declare and use worksheet/workbook references
Set ws = ThisWorkbook.Sheets("SheetName") 'change this to the name of the worksheet you are working on
NO_DR = "No Recovery Required"
Dim i As Long, LastRow As Long 'always long, in case your data exceeds 32k rows and anyways working with 32bits will force it to long.
With ws 'this will allow you to use the reference without writting it
LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row 'this calculate the last row with data, in this case on column A (1)
For i = 1 To LastRow
If .Cells(i, "D") = "Arkansas" Then 'You don't need to write rowindex and column index, just their values.
.Cells(i, "K") = NO_DR 'also, you don't need to specify .Value to change it's value
ElseIf .Cells(i, "E") = 1 Then 'You can use ElseIf statement instead using else, so you can use as many as you need
.Cells(i, "K") = "One"
ElseIf .Cells(i, "J") = "Cat" Then 'another statement
.Cells(i, "K") = "Cat"'Your code
End If
Next
End With
End Sub
It's throwing an error that the object range failed after changing some of the content and a type mismatch for "YES". ElseIf .Cells(i, "EP") = True Then 'You can use ElseIf statement (issue line)
Sub DecisionTree()
Dim cell As Range
Dim NO_DR As String
Dim YES As Boolean
Dim ws As Worksheet 'Declare and use worksheet/workbook references
YES = True
Set ws = ThisWorkbook.Sheets("Napa Data") 'change this to the name of the worksheet you are working on
NO_DR = "No Recovery Required"
Dim i As Long, LastRow As Long 'always long, in case your data exceeds 32k rows and anyways working with 32bits will force it to long.
With ws 'this will allow you to use the reference without writting it
LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row 'this calculate the last row with data, in this case on column A (1)
For i = 1 To LastRow
If .Cells(i, "J") = "8-RTO No Recovery,RPO No Recovery" Then 'You don't need to write rowindex and column index, just their values.
.Cells(i, "FI") = NO_DR 'also, you don't need to specify .Value to change it's value
ElseIf .Cells(i, "EP") = True Then 'You can use ElseIf statement instead using else, so you can use as many as you need
.Cells(i, "J") = "Vendor"
ElseIf .Cells(i, "EF") = "Boulder" Or "Silver" Or "Nap" Or "Irma" Or "Budlign" Or "Sheffield" Then 'another statement I have to add an if statement consisting of like 6 factors
.Cells(i, "J") = "Enabled/Present" 'Your code
End If
Next
End With
End Sub

Convert a range's value from text to Number

I want to delete negative values in a range in excel. I have a code that deletes but not all the values.
I got to know that I should first change the value to numeric type. I have the below code in which I have tried to do so with cDec and Convert.ToInt32 but not successful. I am new to vba, I don't know much about its data types. Your help will be highly appreciable:
Sub Button1_Click()
Dim ws As Worksheet
Dim i As Integer
i = 1
Set ws = Sheets("Recovered_Sheet1")
ws.Activate
Dim r As Excel.Range
For Each r In Range("A1:A250").Rows
If Not IsEmpty(ActiveCell.Value) Then
'move to the row below
ActiveCell.Offset(1, 0).Select
ActiveCell.Value = CDec(ActiveCell.Value)
End If
Next r
Do While Cells(i, 1).Value <> ""
If Cells(i, 1) < 0 Then
Cells(i, 1).EntireRow.Delete
End If
i = i + 1
Loop
End Sub
Here is one way of doing that. Note that when deleting rows, you should work from the bottom up. Also, you don't need to change the Excel data type before running this macro, unless you have some other reason to do so (in which case there are more efficient methods than going cell by cell).
Edit Since text and blanks will return False with .Value < 0, there's no need to test anything else.
Option Explicit
Sub DelNegNumRows()
Dim I As Long
For I = 250 To 1 Step -1
With Cells(I, 1)
If .Value < 0 Then
.EntireRow.Delete
End If
End With
Next I
End Sub
Depending on the characteristics of your range, you may not need to check all 250 rows (although if that is the size of your database, you won't perceive a speed advantage to making the range smaller). For example, if all of your rows with data are non-blank, you can do something like:
lastrow = cells(1,1).end(xldown).row
or, if there might be blanks, and you want to find the last row in column A that has any data, something like:
lastrow = cells(rows.Count,1).end(xlup).row
You could then cycle, in the macro above:
for I = lastrow to 1 step -1
Sub Button1_Click()
Dim I As Long
Dim lastrow As Long
lastrow = Cells(Rows.Count, 1).End(xlUp).Row
For I = lastrow To 1 Step -1
With Cells(I, 2)
If .Value < 0 Then
.EntireRow.Delete
End If
End With
Next I
End Sub

Resources