I need to read the data from an Excel spreadsheet like so using Visual Basic.
v|123|t
t|123|t
g|123|t
I want to read the first column of the spreadsheet and check if it is a V or not. I'm looking to build a script that will delete everything that is not a V, but I am stuck on this.
A quick method using AutoFilter. This filters out anything from the first column that isn't "v" then deletes it and removes the filter.
Sub vFilter()
With ActiveSheet
.AutoFilterMode = False
With Range("A1", Range("A" & Rows.Count).End(xlUp))
.AutoFilter 1, "<>v"
On Error Resume Next
.EntireRow.Delete
End With
.AutoFilterMode = False
End With
End Sub
Autofilter is very useful when working with data in tables.
You can select a range of cells (ie the whole table), then click the Filter button found on the Excel Ribbon>Data>Sort&Filter.
This will add drop down lists to each of the top cells in your selection.
You can use these to reduce the list to only show those with a V in the first column.
You can then select all the rows and delete them.
This what the VBA code posted by KFichter is doing.
If you need to just do it once, use autofilters manually.
Harvey
Related
I have a table full of data that I have a drop down list that when you select the drop down item it filters the column in a table.
The problem I have is I want to have a simple reset button to unfilter the column. It's as simple as that. I don't want the filters to disappear though.
I have tried a boat load of solutions
For reference I used another submission to this site which did not work I got a "400" error message
VBA Unfilter range
Worksheets("Sheet1").ShowAllData
Another solution I tried
With ActiveSheet
.Cells.EntireColumn.Hidden = True
.Cells.EntireRow.Hidden = True
.AutoFilterMode = True
End With
There has to be something super simple I'm not accouting for here.
I was able to figure it out. I'm not sure of the exact science behind it but the range of the table has to be selected before anything.
Sub Unfilter()
'Unfilter all table columns
ActiveSheet.Range("R15:BH1072").Select
If ActiveSheet.FilterMode = True Then
ActiveSheet.ShowAllData
End If
End Sub
Note that if you are using a TABLE instead of a RANGE you will have to corretcly reference the table because it belongs to a different object collection:
Using a table: ActiveSheet.ListObjects("Table288").Range.AutoFilter Field:=1
Using a range: just the range: ActiveSheet.Range("$P$6:$R$10").AutoFilter Field:=1
Note: I used this via Macro recorder to to show the example, your code should be tweaked to fit your needs.
I am considering in particular Excel VBA's AutoFilter method, but I think my question is valid also for the GUI.
When I apply a filter to an Excel worksheet, without selecting anything, the filter applies to all rows from the second onwards. Is there any way to include the first row, so that it may be filtered out as well?
This is something that you can use to see how the filter works:
Sub Makro2()
Rows("1:1").Insert Shift:=xlDown
With Range("a1")
.value = "Filter Me"
.AutoFilter
End With
End Sub
It adds additional row on the first row and then names it "FilterMe". Then it filters. You can read more about AutoFilter here.
I would like to know if there is a faster way do this than the code I am using. I got the code using xlUp from the recorder.
rCnt = Cells(Rows.Count, "B").End(xlUp).Row
ActiveSheet.Range("$B$1:$J" & rCnt).AutoFilter Field:=5, _
Criteria1:=Application.Transpose(arrCodes), Operator:=xlFilterValues
Rows("2:" & rCnt).Delete Shift:=xlUp
And actually, if there was some way to flip the filter, I wouldn't need to delete at all as this is a temporary table that I copy from. However, all my research has failed to find a way to do
Criteria1:=Application.Transpose(<>arrCodes)
and arrCodes has too many elements to list in the filter. And the stuff that is not in arrCodes is way too numerous to make an array from. Thanks.
If you want to just use Excel UI and not formulas or VBA, you can do the following simple steps to get an "inverse" filter. This could then be ported to VBA if needed:
Apply the filter with the opposite conditions
Color those cells in one column (either font or background)
Clear the filter
Filter again but this time by cells in that column without color
Copy those results where you want them
This will not work well if the column already has some background colors. If that is the case, you can add a new column and color it. If this is in VBA, you could automate those steps. There are limits, but this is quick and simple if it applies.
I've had success in the past with building then deleting a range. You can combine ranges with Union(). I've attached a bit of example code, it's not wonderful but it shows the basic concept. This example deletes rows with odd numbers in column A in rows 2 through 11.
Public Sub DeleteRows()
Dim deleteThis As Range
For i = 2 To 11
If Sheet1.Cells(i, 1).Value Mod 2 = 1 Then
If deleteThis Is Nothing Then
Set deleteThis = Sheet1.Rows(i)
Else
Set deleteThis = Union(deleteThis, Sheet1.Rows(i))
End If
End If
Next i
deleteThis.Delete xlShiftUp
End Sub
I am trying to come up with a way to delete all rows (and shift cells up, if possible) where the website column cell contains the word none. The table contains 5000+ records and this would save me a great amount of time.
I appreciate any suggestions.
This is not necessarily a VBA task - This specific task is easiest sollowed with Auto filter.
1.Insert Auto filter (In Excel 2010 click on home-> (Editing) Sort & Filter -> Filter)
2. Filter on the 'Websites' column
3. Mark the 'none' and delete them
4. Clear filter
Ok I know this for VBA but if you need to do this for a once off bulk delete you can use the following Excel functionality: http://blog.contextures.com/archives/2010/06/21/fast-way-to-find-and-delete-excel-rows/ Hope this helps anyone
Example looking for the string "paper":
In the Find and Replace dialog box, type "paper" in the Find What box.
Click Find All, to see a list of cells with "paper"
Select an item in the list, and press Ctrl+A, to select the entire list, and to select all the "paper" cells on the worksheet.
On the Ribbon's Home tab, click Delete, and then click Delete Sheet Rows.
In the "Developer Tab" go to "Visual Basic" and create a Module. Copy paste the following. Remember changing the code, depending on what you want. Then run the module.
Sub sbDelete_Rows_IF_Cell_Contains_String_Text_Value()
Dim lRow As Long
Dim iCntr As Long
lRow = 390
For iCntr = lRow To 1 Step -1
If Cells(iCntr, 5).Value = "none" Then
Rows(iCntr).Delete
End If
Next
End Sub
lRow : Put the number of the rows that the current file has.
The number "5" in the "If" is for the fifth (E) column
I'd like to add to #MBK's answer. Although I found #MBK's answer to be very helpful in solving a similar problem, it'd be better if #MBK included a screenshot of how to filter a particular column.
This was alluded to in another comment, but you could try something like this.
Sub FilterAndDelete()
Application.DisplayAlerts = False
With Sheet1 'Change this to your sheet name
.AutoFilterMode = False
.Range("A3:K3").AutoFilter
.Range("A3:K3").AutoFilter Field:=5, Criteria1:="none"
.UsedRange.Offset(1, 0).Resize(ActiveSheet.UsedRange.Rows.Count - 1).Rows.Delete
End With
Application.DisplayAlerts = True
End Sub
I haven't tested this and it is from memory, so it may require some tweaking but it should get the job done without looping through thousands of rows. You'll need to remove the 11-Jul so that UsedRange is correct or change the offset to 2 rows instead of 1 in the .Offset(1,0).
Generally, before I do .Delete I will run the macro with .Select instead of the Delete that way I can be sure the correct range will be deleted, that may be worth doing to check to ensure the appropriate range is being deleted.
Try this ...
Dim r as Range
Dim x as Integer
For x = 5000 to 4 step -1 '---> or change as you want //Thanx 4 KazJaw
set r = range("E" & format(x))
if ucase(r.Value) = "NONE" then
Rows(x).EntireRow.Delete
end if
Next
Delete rows 1 and 2 so that your headings are on row 1
Put this in a macro (IT WILL CHECK THROUGH ROW 75000, YOU CAN LOWER THE NUMBER IF YOU WOULD LIKE
Columns("E:E").Select
Selection.AutoFilter
ActiveSheet.Range("$E$1:$E$75000").AutoFilter Field:=1, Criteria1:="none"
Range("E2:E75000").SpecialCells(xlCellTypeVisible).Select
Selection.EntireRow.Delete
ActiveSheet.Cells.EntireRow.Hidden = False
ActiveSheet.Range("$E$1:$E$75000").AutoFilter Field:=1
Columns("E:E").Select
Selection.AutoFilter
Range("E2").Select
Range("A1").Select
I am trying to create a macro that will automatically delete rows from a raw data file based on multiple criteria. I have been able to create a macro that will delete rows where certain columns have blank values, but I also need to delete rows that have a date that is equal or greater than a date contained in a specific cell in another worksheet. I have been all over the internet but have not found an explanation that addresses this particular case or one similar enough for me to figure it out. I am working on automating a number of other reports, and this is the final piece that I need to be able to finish several of them. Here is the code I am trying to use.
Sub Deletedatesbeyondreportmonth()
Application.ScreenUpdating = False
With ActiveSheet
.AutoFilterMode = False
.Columns("E").AutoFilter Field:=1, Criteria1:=">= sheets("Sheet2").Range("C1")"
.AutoFilter.Range.Offset(1, 0).EntireRow.Delete
.AutoFilterMode = False
End With
End Sub
If I replace the criteria sheets("Sheet2").Range("C1") with the actual value that is contained in the specified cell the macro works, however I need it to be able to run based off the value contained in that cell. I have played with some syntax variations and got different error messages, but haven't been able to figure it out. If I run this as is, it highlights the word Sheet2 on the criteria line and says:
Compile Error expected: End of statement
It's probably the nested double-quotes. Try using double-double-quotes, like:
.Columns("E").AutoFilter Field:=1, Criteria1:=">= sheets(""Sheet2"").Range(""C1"")"
Example here.
when you encapsulate VBA logic by quotes you actually hardcode the string, so it will use the text Sheets("Sheet2").Range("C1") in the filter rather than evaluate the Range value. You need to use the following:
.Columns("E").AutoFilter Field:=1, Criteria1:=">=" & Sheets("Sheet2").Range("C1")