Autofilter not working as intended - vba

I'm trying to delete all rows that contain a specific value in column with autofilter. For some reason, it doesn't work as intended and only deletes some of the rows with the specified value, and I'm determined to find out WHY
My code is as simple as this:
Function GetRowRange(sheet, column, value) As Range
'check for a valid section column
sheet.AutoFilterMode = False
sheet.UsedRange.AutoFilter Field:=column, Criteria1:=value
Set GetRowRange = sheet.AutoFilter.Range.SpecialCells(xlCellTypeVisible)
sheet.AutoFilterMode = False
End Function
With GetRowRange(importsheet, importsheet.UsedRange.Find("stato_4").column, "0")
.Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count).Delete
End With
Update
it makes no sense. I try to change my delete function to:
For Each Row In GetRowRange(importsheet, importsheet.UsedRange.Find("stato_4").column, "0").Offset(1, 0).Rows
Row.EntireRow.Delete
iront = iront + 1
Next
MsgBox iront
and it will recognize that there are 42 rows in the range (iront = 42), but none of them get deleted

I think if you have less than 8192 rows (pre Excel 2010), you could delete them using Special Cells?
Add a formula column that throws an error if the row contains the value you want to test for.
TRY THIS:
' Now, this formula will put an #N/A in each row where the column matches the criteria.
Range("C1:C" & Range("A1").End(xlDown).Row).FormulaR1C1 = "=IF(C[-2]=criteria,NA(),"""")"
'Then use SpecialCells with Error code xlErrors to return the range containing the rows to be deleted.
Range("C1:C" & Range("A1").end(xldown).row).SpecialCells(xlCellTypeFormulas,xlErrors).entirerow.delete
There is more on that on Oxgrid
HTH
Philip

Not sure UsedRange is reliable. Try using something like Range("A1").CurrentRegion

Related

Excel VBA deleting certain rows with certain conditions

I found a code online which works but I am failing to change it for my purpose. Each entry in my spreadsheet contains different formulas as well as an Iferror function with the aim of making cells with error messages appear as blank. For example lets say a cell E3 is dependent on cell F3 with a certain formula (for clarification lets say F3/2.5). It is obvious if there is no entry in cell F3 then an error message would display in cell E3. For this reason, I use the IFERROR function to display the cell as blank. The difficulty arises when I want to delete blank rows after a click on the macro button. However, since that cell does have an entry (a formula which in turn returns an error message), that cell does not delete. Also I need to run this code over 3 different selection ranges. Please can someone help! The code I found was from a different thread on this forum and is:
`sub foo()
dim r As Range, rows As Long, i As Long
Set r = ActiveSheet.Range("A1:Z50")
rows = r.rows.Count
For i = rows To 1 Step (-1)
If WorksheetFunction.CountA(r.rows(i)) = 0 Then r.rows(i).Delete
Next
End Sub`
Thanks Alot!
EDIT: If statement added to the autofilter as it was deleting a row when there were no blanks
You will want to set up a column in the spreadsheet with the following sumproduct:
=SUMPRODUCT((LEN(A1:F1)>0)*1)
This is calculating how many cells' values have a length more than 0 hence are not blank, you will need to adjust cell references accordingly as I tested on a small sample of fake data.
Following this you can just loop:
For i = rows To 1 Step (-1)
If Cells(i,"G") = 0 Then r.rows(i).Delete 'My formula is in column "G"
Next
Or set up an auto-filter and delete entire rows of the visible cells:
Dim lrow As Integer
If Not WorksheetFunction.CountIf(Range("G:G"), "0") = 0 Then
Range("A1:G1").AutoFilter
Range("A1:G1").AutoFilter Field:=7, Criteria1:="0"
lrow = Cells(rows.Count, 7).End(xlUp).Row + 1
Range("G2:G" & lrow).SpecialCells(xlCellTypeVisible).EntireRow.Delete
Range("A1:G1").AutoFilter
End If
The only problem with using a leading column to calculate for this is if you have a lot of data coming and going as you will need to replenish the formula, though you could use auto complete in the code i guess.

Manipulating Excel spreadsheet, removing rows based on values in a column and then removing more rows based on values in another column

I have a rather complicated problem.
I have a log file that when put into excel the column "I" contains event IDs, and the column J contains a custom key that keeps a particular even grouped.
All i want to do is remove any rows that do not contain the value of say 102 in the event id column.
And THEN i need to check the custom key (column J) and remove rows that are duplicates since any duplicates will falsely show other statistics i want.
I have gotten as far as being able to retrieve the values from the columns using com objects and .entirecolumn cell value etc, but I am completely stumped as to how i can piece together a solid way to remove rows. I could not figure out how to get the row for each value.
To give a bit more clarity this is my thought process on what i need to do:
If cell value in Column I does not = 102 Then delete the row that cell contains.
Repeat for all rows in spreadsheet.
And THEN-
Read every cell in column J and remove all rows containing duplicates based on the values in column J.
Save spreadsheet.
Can any kind persons help me?
Additional Info:
Column I holds a string that is an event id number e.g = 1029
Column J holds a string that is a mix of numbers and letters = 1ASER0X3NEX0S
Ellz, I do agree with Macro Man in that your tags are misleading and, more importantly, I did indeed need to know the details of Column J.
However, I got so sick of rude posts today and yours was polite and respectful so I've pasted some code below that will do the trick ... provided Column J can be a string (the details of which you haven't given us ... see what Macro Man's getting at?).
There are many ways to test for duplicates. One is to try and add a unique key to a collection and see if it throws an error. Many wouldn't like that philosophy but it seemed to be okay for you because it also gives you a collection of all the unique (ie remaining) keys in Column J.
Sub Delete102sAndDuplicates()
Dim ws As Worksheet
Dim uniques As Collection
Dim rng As Range
Dim rowPair As Range
Dim iCell As Range
Dim jCell As Range
Dim delRows As Range
Set ws = ThisWorkbook.Worksheets("Sheet1")
Set rng = Intersect(ws.UsedRange, ws.Range("I:J"))
Set uniques = New Collection
For Each rowPair In rng.Rows
Set iCell = rowPair.Cells(, 1)
Set jCell = rowPair.Cells(, 2)
On Error Resume Next
uniques.Add jCell.Value2, jCell.Text
If Err = 457 Or iCell.Value2 = 102 Then
On Error GoTo 0
If delRows Is Nothing Then
Set delRows = rowPair.EntireRow
Else
Set delRows = Union(delRows, rowPair.EntireRow)
End If
End If
Next
If Not delRows is Nothing then
MsgBox delRows.Address(False, False) & " deleted."
delRows.Delete
End If
End Sub
There are a number of ways in which this can be done, and which is best will depend on how frequently you perform this task and whether you want to have it fully automated. Since you've tagged your question with VBA I assume you'll be happy with a VBA-based answer:
Sub removeValues()
Range("I1").Select 'Start at the top of the I column
'We are going to go down the column until we hit an empty row
Do Until IsEmpty(ActiveCell.Value) = True
If ActiveCell.Value <> 102 Then
ActiveCell.EntireRow.Delete 'Then delete the row
Else
ActiveCell.Offset(1).Select 'Select the cell below
End If
Loop
'Now we have removed all non-102 values from the column, let`s remove the duplicates from the J column
Range("A:J").RemoveDuplicates Columns:=10, Header:=xlNo
End Sub
The key line there is Range("A:J").RemoveDuplicates. It will remove rows from the range you specify according to duplicates it finds in the column you specify. In that case, it will remove items from the A-J columns based on duplicates in column 10 (which is J). If your data extends beyond the J column, then you'll need to replace "A:J" with the appropriate range. Note that the Columns value is relative to the index of the first column, so while the J column is 10 when that range starts at A (1), it would be 2 for example if the range were only I:J. Does that make sense?
(Note: Using ActiveCell is not really best practice, but it's the method that most obviously translates to what you were trying to do and as it seems you're new to VBA I thought it would be the easiest to understand).

Adjust criteria to depend on multiple values

I have been working on a code to copy the data from one specific range(always the same) and paste in another spreadsheet always in the row below. So basically, it starts pasting on row 11, but if I run again it will paste on the row 12 and there it goes.. The code has been working fine, but there is only one problem. It identifies the next empty row(to paste) based on the value of the column AP, but i want it to identify based on the values of all the columns between AP:BA. Thus, if there is any value on those cells, it should copy on the row below, not only if there is a value on AP. Does someone know how to change my code in order to solve this problem? Thank You very much
Sub Copy_Shanghai()
Dim count As Integer
count = 11
Do While Worksheets("Time Evolution").Range("AP" & count).Value <> ""
'<>"" means "is not empty", as long as this happens we go down looking for empty cell
count = count + 1
Loop
'Now count is row with first empty cell outside of top 10 rows in column C
Worksheets("Fill").Range("E5:P5").Copy
Worksheets("Time Evolution").Range("AP" & count).PasteSpecial xlPasteValues
End Sub

EXCEL 2010: Change the range of an auto filter with a MACRO

The following gave me the Range of the autofilter on worksheet Planning
rAddress = Worksheets("Planning").AutoFilter.Range.Address
Range("C12").Select
Range("C12") = rAddress =[$B$4:$I$183]
I would like to change the autofilter range without removing the current autofilter by using the following range as input.
Worksheets("Planning").Select
Rownumber = WorksheetFunction.CountA(Range("B:B")) - 1
Range("$B$4:$I$" & (Rownumber + 4))
How do I code a macro to change to this new range WITHOUT removing and reinstating the autofilter?
The Autofilter range will expand itself when you add new rows to your Worksheet. If you need 4 more rows, just add them to the bottom:
'Returns $A$1:$C$13 (your value will depend on your data).
Debug.Print ActiveSheet.AutoFilter.Range.Address
ActiveSheet.Cells(ActiveSheet.UsedRange.Rows.Count + 1, 1).Value = "foo"
'Is now $A$1:$C$14
Debug.Print ActiveSheet.AutoFilter.Range.Address
My experience is, that the AutoFilter needs values in the first column to detect added rows properly. So if you only want the AutoFilter to act on newly added data, simply fill in values into the first column.

Getting a total copied set of rows in VBA and storing it in a variable

I have a fairly simple syntax question:
I'm trying to copy and paste n rows from one excel file to another. In addition, I'd like to store the total copied rows into a variable.
Can someone help me accomplish this?
For example:
1)
Activate CSV file
Apply Filter to Column B (Page Title) & uncheck "blanks" ("<>") filter**
Windows("Test_Origin.xlsm").Activate
ActiveSheet.Range("$A$1:$J$206").AutoFilter Field:=2, Criteria1:="<>"
2)
Copy Filtered Lines with data (Excluding Row 1)
Range("B2:F189").Select
Selection.Copy
copiedRowTotal = total *FILTERED* rows copied over from original sheet, then Test Number iterates that many times
copiedRowTotal = Selection.Rows.Count
MsgBox copiedRowTotal
Thanks
An indirect way to do this is
Range("B2:F189").Copy
Range("M2").PasteSpecial xlPasteValues
copiedRowTotal = Selection.Rows.Count
Selection.Clear
The code copies the range & does a paste special operation on a separate location.
By doing this, only filtered rows are copied to M2 & the area (where the filtered rows are pasted) is highlighted when PasteSpecial operation is done.
Doing a Selection.Rows.Count gives one, the number of filtered rows that were pasted.
After figuring out the number of filtered rows, the selection is cleared up.
I don't believe there is a way to get the visible cell count directly. I tried using the 'SpecialCells(xlSpecialCellsVisible)' function, but could not get the correct count with a filter applied. Here is a quick function I wrote that works with a filter applied.
Also be aware that sometimes a filter can mess with the selected range at times, so it's something to note.
Public Sub TestIt()
Dim visibleCount As Long
visibleCount = GetVisibleCount(Sheets(1).Range("A2:H3000"))
MsgBox visibleCount
End Sub
Public Function GetVisibleCount(rng As Range) As Long
Dim loopRow As Range
GetVisibleCount = 0
For Each loopRow In rng.Rows
If loopRow.Hidden = False Then
GetVisibleCount = GetVisibleCount + 1
End If
Next loopRow
End Function
copiedrowtotal = selection.rows.count ' its not selection.totalcells
I think this would do the trick
After seeing your update let me tell you probably these would work
dim i as long
i = Application.WorksheetFunction.Subtotal(2,worksheets("Sheet").Range("B2:F189"))
Now i has the number of filtered rows in it! If you have included header in your range then do -1 at the end else just leave it up
argument 2 in subtotal is => counting the rows and then sheet name
and then specify range to count filtered rows
instead I would select only one column if you applied filter for many columns!
Hope it helps dont forget to accept an answer ! :