VBA Excel Delete Row Based on Value in Column - vba

Would like to delete rows from a report based on the data in column M. Report is of variable size row-wise but the same width in columns. "Valid" in a cell means it gets deleted.
Sub Create()
Dim Range1 As Range
Set Range1 = Range("M:M")
For Each cell In Range1
If ActiveCell.Value = "Valid" _
Then ActiveCell.EntireRow.Delete
Next cell
End Sub

It now about the ActiveCell but cells in the column "M:M". Also, you need to start form the bottom up (not obvious but true). So, assuming there are fewer rows than 10000, you need something like this:
Sub Create()
Dim LastRow As Long
Dim i As Long
LastRow = Range("M10000").End(xlUp).Row
For i = LastRow To 1 Step -1
If Range("M" & i) = "Valid" Then
Range("M" & i).EntireRow.Delete
End If
Next
End Sub

I found a way using your For Each :
Public Sub Create()
Dim Range1 As Range
Dim Cell
Dim LastRow As Long
Set Range1 = Range("M1")
' assume, there is some data in the first row of your sheet
LastRow = Range1.CurrentRegion.Rows.Count
' otherwise, find last cell in column M with a value, assume before row 10000
LastRow = Range("M10000").End(xlUp).Row
' select the cells to process
Set Range1 = Range(Range1, Range1.Offset(LastRow, 0))
' process the rows
For Each Cell In Range1
If Cell.Value = "Valid" Then
Debug.Print "' delete row from at address :: " & Cell.Address
Range(Cell.Address).EntireRow.Delete
End If
Next
End Sub

Related

How can I write a Macro to sum a Column that has #N/A values in it?

I am looking to create a macro that sums a column that will always contain a few #N/A values, the number of cells in the column will change daily and so will the position of the #N/A values.
I also want to put the result in the first empty cell below that last value i.e. the first empty cell at the bottom of the column.
This is as far as I could get:
Option Explicit
Sub Total()
'
' Total Macro
Dim rg As Range
Dim Cell As Range, Target As Range
Set Target = Range("D65536").End(xlUp)
For Each Cell In Target
Cell.Errors(xlEvaluateToError).Ignore = True
Set rg = Range("D65536").End(xlUp)
rg.Offset(1, 0).Value = "=sumif(D1:D100 " <> 0 & rg.Row & ")"
Range("D65536").End(xlUp).Select
Selection.Font.Bold = True
Next
End Sub
Im using D1:D100 but only because 100 will cover the amount of cells in my Column. This is giving a strange result of more #N/As followed by a True. I dont think I should be trying to use a formula within the code.
Thanks
I would loop through and check if the value is numeric then add it to the total:
Sub mysum()
Dim lstRow As Long
Dim ws As Worksheet
Dim i As Long
Set ws = Worksheets("Sheet5") 'Change to your sheet
With ws
lstRow = .Cells(.Rows.Count, 4).End(xlUp).Row
For i = 1 To lstRow
If IsNumeric(.Cells(i, 4)) Then
.Cells(lstRow + 1, 4) = .Cells(lstRow + 1, 4) + .Cells(i, 4)
End If
Next i
End With
End Sub
You could use SpecialCells():
Sub total()
With Worksheets("SheetName") '<--| Change to your actual sheet name
With .Range("D1", .Cells(.Rows.Count, 4).End(xlUp))
.Cells(.Rows.Count,1).Offset(1).Value = WorksheetFunction.Sum(.SpecialCells(xlCellTypeConstants, xlNumbers))
End With
End With
End Sub

How to pick value based on condition in macros

I want to compare the data so I have to pick a value based on a condition. The example data that I have is like:
The condition is:
I want to pick the value of PO NO. that always placed 2 column after text "PO NO."
How do I get that value? After that copy and paste it in another column (example:column A)
It depends on how do you want to use those values, if you just want to put them into some continued ranges in current workbook, then I think the Filter function is sufficient, if you want to do some further calculation, you may want to write some VBA code:
Press ALT + F11 in your current worksheet.
Press ALT + I then press M.
Press Ctrl + G to open the "Immediate" window
Then write the following lines:
Sub myValues()
Dim rCount As Long
Dim i As Long
Let rCount = ThisWorkbook.ActiveSheet.Cells(Rows.Count, 6).End(xlUp).Row
For i = 1 to rCount
If WorksheetFunction.Trim(ThisWorkbook.ActiveSheet.Cells(i,6).Text) = "PO No." Then
Debug.Print ThisWorkbook.ActiveSheet.Cells(i,8).Text
End If
Next
End Sub
Now you could get all the PO NO values in the "Immediate" window.
You can extract the value you want using this formula.
=INDEX(F44:H49,MATCH("PO No.",F44:F49,0),3)
The problem which remains to be solved is how to define the range F44:F49. Your question delivers no hint as to how that should be done. Perhaps knowing where you want to value to appear would offer a clue.
You can iterate over each cell in the column and gather your post numbers, offsetted by 2 columns, like I mentioned in comments
Sub Test()
Dim WS As Worksheet
Dim ParamRange As Range
Dim LastRow As Long
Dim Cell As Range
Dim i As Long
Set WS = ActiveSheet 'or whatever sheet your want
With WS
LastRow = .Cells(.Rows.Count, "F").End(xlUp).Row
Set ParamRange = .Range("F1:F" & LastRow)
End With
For Each Cell In ParamRange 'iterate over column
If Cell.Value2 = "PO NO." Then
i = i + 1
'Debug.Print to Immediate
Debug.Print i, CurrentSearch.Offset(ColumnOffset:=2).Value2
'Paste in "A" column
CurrentSearch.Offset(ColumnOffset:=-5).Value2 = CurrentSearch.Offset(ColumnOffset:=2).Value2
End If
Next
End Sub
So you just need to collect all Cell.Offset(ColumnOffset:=2).Value2 values.
Alternatively, without iteration over cells (and faster), but little bit complicated:
Sub Test()
Dim WS As Worksheet
Dim ParamRange As Range
Dim CurrentSearch As Range
Dim FirstSearch As Range
Dim LastRow As Long
Dim Cell As Range
Dim i As Long
Set WS = ActiveSheet 'or whatever sheet your want
With WS
LastRow = .Cells(.Rows.Count, "F").End(xlUp).Row
Set ParamRange = .Range("F1:F" & LastRow)
End With
'Get first search
Set CurrentSearch = ParamRange.Find(What:="PO NO.", LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not CurrentSearch Is Nothing Then
i = i + 1
'Debug.Print to Immediate
Debug.Print i, CurrentSearch.Offset(ColumnOffset:=2).Value2
'Paste in "A" column
CurrentSearch.Offset(ColumnOffset:=-5).Value2 = CurrentSearch.Offset(ColumnOffset:=2).Value2
Set FirstSearch = CurrentSearch
Do
'Get next search
Set CurrentSearch = ParamRange.FindNext(After:=CurrentSearch)
If Not CurrentSearch Is Nothing Then
If CurrentSearch.Address = FirstSearch.Address Then Exit Do
i = i + 1
'Debug.Print to Immediate
Debug.Print i, CurrentSearch.Offset(ColumnOffset:=2).Value2
'Paste in "A" column
CurrentSearch.Offset(ColumnOffset:=-5).Value2 = CurrentSearch.Offset(ColumnOffset:=2).Value2
Else
Exit Do
End If
Loop
End If
End Sub
Links:
Range.Offset
Find last row, column or last cell
.Find and .FindNext in Excel VBA

using a formula in vba to compare cells and enter results in another cell

I going to use a formula in VBA to compare to columns of data and if a match is found then enter some data from one sheet to another. I have used a formula on the first row and this works I get the desired results, I want to automate it as this will be part of other automations on the report. I have got some code which enters a column heading then applies the sumif function to the entire column but I get the same results all the way down, it is the results for the first row.
Code
Sub ImportCosting()
Dim z As Workbook
Dim x As Workbook
Set x = Workbooks.Open("C:\Documents\Reports\MEP.xlsx")
With Workbooks("MEP")
Worksheets("DynamicReport").Range("P5").Value = "Budget"
Worksheets("DynamicReport").Range("Q5").Value = "Forecast"
End With
Set z = Workbooks.Open("C:\Documents\Reports\Budget.xlsx")
With x.Worksheets("DynamicReport")
lastRow = .Cells(Rows.Count, 5).End(xlUp).Row
For Each rng In .Range("P6:P" & lastRow)
rng.Formula = "=SUMIF('[Budget.xlsx]DynamicReport'!$C:$C,$B6,'[Budget.xlsx]DynamicReport'!H:H)"
rng.Value = rng.Value
Next rng
End With
End sub
Hope I have explained the problem correctly. Can anyone tell me where I have gone wrong and how to get it so that the sumif function is applied to each row and not the results for the first row repeated.
Thanks
I am not sure but I guess you want to change the B6 to the rng.row
I guess you are getting the same result in every cell of rng because you are putting B6 as the criteria for sum so change that to the corresponding row number in the B column so that you get the desired result.
Change this:
rng.Formula = "=SUMIF('[Budget.xlsx]DynamicReport'!$C:$C,$B6,'[Budget.xlsx]DynamicReport'!H:H)"
to this
rng.Formula = "=SUMIF('[Budget.xlsx]DynamicReport'!$C:$C,$B" & rng.Row & ",'[Budget.xlsx]DynamicReport'!H:H)"
pls try below
Sub ImportCosting()
Dim z As Workbook
Dim x As Workbook
Set x = Workbooks.Open("C:\Documents\Reports\MEP.xlsx")
With Workbooks("Bank.xlsx")
Worksheets("DynamicReport").Range("P5").Value = "Budget"
Worksheets("DynamicReport").Range("Q5").Value = "Forecast"
End With
Set z = Workbooks.Open("C:\Documents\Reports\Budget.xlsx")
With x.Worksheets("DynamicReport")
lastRow = .Cells(Rows.Count, 5).End(xlUp).Row '"E"
For Each Rng In .Range("P6:P" & lastRow)
Rng.Formula = "=SUMIF([Budget.xlsx]DynamicReport!$C:$C,[Budget.xlsx]DynamicReport!$B$" & Rng.Row & ",[Budget.xlsx]DynamicReport!H:H)"
'Rng.Value = Application.WorksheetFunction.SumIf(z.Worksheets("DynamicReport").Range("C:C"), z.Worksheets("DynamicReport").Range("B" & Rng.row), z.Worksheets("DynamicReport").Range("H:H"))
Rng.Value = Rng.Value
Next Rng
End With
End Sub

Row Number reference with VBA

I have searched a bit for a VBA code that will list me a row reference and am not finding results. Perhaps I am missing what the actual term for it is?
I have a list of names in Column A, starting at A2. Then what I would like is a listing of 1,2,3,4,5 going down Column B, starting from B2, until the names stop.
I can do this as a formula but need to have the values set there by a macro in this case.
Can this be done?
If I understand you correctly then this should work:
Sub test()
Dim lastRow As Long, counter As Long
Dim cell As Range
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("NAME_OF_YOUR_WORKSHEET")
lastRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
counter = 1
For Each cell In ws.Range("B2:B" & lastRow)
cell.Value = counter
counter = counter + 1
Next cell
End Sub
No need for a loop:
Sub NumberRows()
With Sheets("Sheet Name Here")
With .Range("B2:B" & .Cells(.Rows.Count, 1).End(xlUp).Row)
.Formula = "=ROW()-1"
.Value = .Value
End With
End With
End Sub

macro that highlights rows that do not exist in an other worksheet

I have one file with two worksheets, both are full of names and addresses. I need a macro that will highlight rows in the first sheet if the cell A of that row does not match any rows from column A of the second sheet.
So if the first cell in a row has no matching data in any of the data in column A of sheet2 then that row is highlighted red.
Also I might want to expand this in the future so could I also specify that Sheet1 can be the active sheet, but sheet2 is called by the sheet name?
Try below code :
Sub Sample()
Dim lastRow As Integer
Dim rng As Range
lastRow = Sheets("Sheet1").Range("A65000").End(xlUp).Row
For i = 1 To lastRow
Set rng = Sheets("sheet2").Range("A:A").Find(Sheets("Sheet1").Cells(i, 1))
If rng Is Nothing Then
Sheets("Sheet1").Cells(i, 1).EntireRow.Interior.Color = vbRed
End If
Next
End Sub
Here's an ugly brute-force approach:
Dim r As Range
Dim s As Range
For Each r In ActiveSheet.UsedRange.Rows
For Each s In Sheets("Sheet2").UsedRange.Rows
If r.Cells(1, 1).Value = s.Cells(1, 1).Value Then
r.Interior.ColorIndex = 3
End If
Next s
Next r
Here's a slicker way:
Dim r As Range
Dim s As Range
Set s = Sheets("Sheet2").Columns(1)
For Each r In ActiveSheet.UsedRange.Rows
If Not (s.Find(r.Cells(1, 1).Value) Is Nothing) Then
r.Interior.ColorIndex = 3
End If
Next r
how about this:
Sub CondFormatting()
Range("D1:D" & Range("A1").End(xlDown).Row).Formula = "=IF(ISERROR(VLOOKUP(A:A,Sheet2!A:A,1,FALSE)),""NOT FOUND"",VLOOKUP(A:A,Sheet2!A:A,1,FALSE))"
With Columns("D:D")
.FormatConditions.Delete
.FormatConditions.Add Type:=xlCellValue, Operator:=xlEqual, Formula1:="=""NOT FOUND"""
.FormatConditions(1).Interior.ColorIndex = 3
End With
Range("I16").Select
End Sub
here is an approach using a Worksheet formula:
=IF(ISERROR(VLOOKUP(A:A,Sheet2!A:A,1,FALSE)),"NOT FOUND",VLOOKUP(A:A,Sheet2!A:A,1,FALSE))
then you would use Conditional formatting to turn the cells red if column A doesn't find a match!
HTH
Philip