Excel VBA Loop find x and remove row - error - excel

I used record macro to create some code and then I put it in a loop. It works but there is an error in the find function which causes it to only work once. I tried to do something with the error but I am not having any luck having it loop. I've looked a couple of days here and there but I am at a loss. Hope you can help me. Much appreciated.
i = 1
On Error GoTo notfound
Do While Sheet1.Cells(i, 1) <> ""
Columns("J:J").Select
Selection.Find(What:="x", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
Rows(ActiveCell.Row).EntireRow.Delete
notfound: msgbox "Finished"
GoTo notfound
Exit Sub
i = i + 1
Loop

I've corrected, completed, formatted and commented your code. This should take you one step closer to what you want to do.
Private Sub Sample()
Dim Crit As Variant ' the criterium to look for
Dim Fnd As Range ' the cell to find
Dim i As Long
' never create an error handler if you don't know which error to exect
' On Error GoTo notfound
i = 1
' the cell can't be "" only its value can do thjat
Do While Sheet1.Cells(i, 1).Value <> ""
Crit = "x"
' Columns("J:J").Select
' don't Select anything, address cells or ranges instead
Set Fnd = Columns("J:J").Find(What:=Crit, _
After:=ActiveCell, _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
' where is the 'Activecell'?
' a) it doesn't change while this loop is running
' but it might get deleted by this loop's action
' b) it must be in the range you are searching
' that's why your code will fail most of the time.
' don't Activate anything. Instead address the object you want to deal with.
If Fnd Is Nothing Then
MsgBox "I didn't find """ & Crit & """"
Else
Sheet1.Rows(Fnd.Row).EntireRow.Delete
End If
i = i + 1
Loop
End Sub
This code will look for "x" in column J for as long as there is a value in column A and delete the row where it is found. It's hard to imagine a relationship between the number of entries in column A and the number of "x" in column J but, hopefully, this isn't your problem. Instead, your obvious problem is the cell in which you want to start the search. It definitely isn't ActiveCell but it might be Cells(1, "J"). You can also omit this instruction and VBA will start the search after J1.
You want to LookIn formulas. If there are formulas in column J the Formula will be different from the Value. You may wish to search in xlValues.

Related

Delete exact matches

I need Excel to delete columns as long as the header is NOT "Event Notes."
For related purposes, I found and successfully used the InStr function to find certain headers and delete the columns. But now I just want it to, starting at the end, delete columns until it finds THE EXACT STRING "Event Notes."
So far, I've had it delete EVERYTHING that didn't contain Event Notes; now it's finding "Event Notes Dates" and exiting the For loop.
Thanks a bunch for any assistance!
For iCounter = myWorksheet.Cells.Find(What:="*", LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column To 1 Step -1
If InStr(1, myWorksheet.Cells(1, iCounter).Value, "Event Notes") = 1 Then
Exit For
Else
myWorksheet.Columns(iCounter).EntireColumn.Delete
End If
Next iCounter
following my comment, you should simply compare the range value to the "target" one
As per this little revision of your code
With myWorksheet ' reference your sheet.
For iCounter = .Cells.Find(What:="*", LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column To 1 Step -1
If .Cells(1, iCounter).Value = "Event Notes" Then
Exit For
Else
.Columns(iCounter).EntireColumn.Delete
End If
Next iCounter
End With

Copy a range to a variable, then offset that range variable and save the value to another variable

So I am trying to search for a cell range with a specific string, then copy the contents of the cell 3 spaces under it to save to another spreadsheet.
The code I have so far does this, but it seems clumsy to need to select the cell then offset it with variableName.Select then ActiveCell.Offset(blahblah).
Is it possible to offset to (and pull the value from) the desired cell by calling variableName.Offset(3,0).Value or something of that nature to clean up the code?
Here is the code I have so far, and thanks in advance for your help!
Dim ra As Range
Sheets("starting").Activate
Set ra = Cells.Find(What:="Product Name", LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True)
'finds correct cell
If ra Is Nothing Then
MsgBox ("Search Error: Not found")
Else
MsgBox (ra.Address) ' to test
End If
Dim foundCell
ra.Select
ActiveCell.Offset(3, 0).Select
'foundCell = Cells(ra).Offset(0, 3) '.Address '.value ' <<< not grabbing the data
foundCell = ActiveCell.Value
MsgBox foundCell 'shows the value of the desired cell now! (to test)
Sheets("testing").Activate
Sheets("testing").Cells(2, "F").Value = foundCell '2,"F" will be replaced by a range stored in a variable
This will do the same thing:
Sub Test()
Dim ra As Range
Set ra = Sheets("starting").Cells.Find(What:="Product Name", LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True)
If ra Is Nothing Then
MsgBox ("Search Error: Not found")
Else
MsgBox (ra.Address) ' to test
Sheets("testing").Cells(2, 6) = ra.Offset(3, 0)
End If
End Sub
I've put the copying it into the testing sheet within the If ra Is Nothing test.
As your code stands it would display the message "Search Error: Not found" and then try offset three rows from the value it didn't find giving an Object variable or With block variable not set error.

How to check whether a row contains certain text

I am trying to check whether Row 1 of my active sheet named "Exceptions" contains the text "Control  Date" (two spaces) or "Control Date".
My code finds the condition false.
Dim a As Range
Dim exceptions As Worksheet
Set exceptions = ActiveWorkbook.Worksheets("Exceptions")
For Each c In Exceptions.Range("A1:Z1")
If c = "Control Date" Then
Cells.Find(What:="control date", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
Else
Cells.Find(What:="Control Date", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
End If
Next c
Example of a worksheet with two spaces in "Control  Date"
How to write the condition
As far as checking if the cell value is "Control Date" with a single space or one with two spaces, there are two ways of going about it:
Use the like operator
The like operator makes it easy to compare a string to a basic pattern. In this example, using the wildcard character * (Zero or more characters) will return true regardless of how many spaces are between Control and Date.
If cell.Value2 Like "Control*Date" Then
' Do something with that cell
End If
Use the or operator
Using the or operator ok to use as well, although not a flexible and perhaps a bit more difficult to see what's going on for your specific example.
If cell.Value2 = "Control Date" Or cell.Value2 = "Control Date" Then
' Do something with that cell
End If
Worksheet Codename
Each worksheet has whats called a codename. This is a reference that can be called directly in the code to that specific worksheet by it's name.
To set this name, in the properties window update the name property
So instead of
Dim Exceptions As Worksheet
Set Exceptions = ActiveWorkbook.Worksheets("Exceptions")
For Each cell In Exceptions.Range("A1:Z1")
' Do something...
Next cell
you can call the worksheet reference directly
For Each cell In Exceptions.Range("A1:Z1")
' Do something...
Next cell
Putting it together
Instead of using c for your variable, I like to make my variables easier to read and follow so I used cell.
Also, instead of hard coding your header columns in range, you could loop the cells of the entire first row. This is option suggestion though.
Lastly, be more explicit in what property you are looking for in your Cell. In my example I use .value2 to show I am looking for the value of that cell.
Public Sub Demo()
Dim cell As Range
For Each cell In Exceptions.Rows(1).Cells
If cell.Value2 Like "Control*Date" Then
' Do something with that cell
End If
Next cell
End Sub
Why duplicate the data into a third column? Whenever you need the "combined" date, just go get it, but do not store it twice.
Option Explicit '<<-- always have this
Sub doFindControl()
Dim a As Range
Dim c As Range '<<-- add this
Dim colDate As Long, colNumber As Long, colBlank As Long '<<--add this
Dim exceptions As Worksheet
Set exceptions = ActiveWorkbook.Worksheets("Exceptions")
For Each c In exceptions.Range("A1:Z1")
' first find the 2 key columns
If InStr(c, "Control") > 0 Then
If InStr(c, "Date") > 0 Then
colDate = c.Column
ElseIf InStr(c, "Number") > 0 Then
colNumber = c.Column
End If
' second look for the first blank column for you to put results in
ElseIf c.Text = "" Then
colBlank = c.Column
Exit For ' stop looking after its found
End If
Next c
' now you have the 2 FROM columns, and the TO column
MsgBox (colDate & " " & colNumber & " " & colBlank)
' and you can loop thru all the rest of the rows doing combine
End Sub
Thank you for all the answers! Robert Todar's answer led me to my lightbulb moment, and I can't believe at how simple the answer was. All I had to do was change this code:
Cells.Find(What:="Control Date", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
to:
Cells.Find(What:="Control*Date", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate

Macro to look up value in sheet 2 from a cell in sheet 1, and input date into corresponding row in sheet 2

I'm really new to VBA, and could do with your help please.
Sheet2 is a long list of data (jobs) where each row in column B contains a unique job reference number.
I want users to input one of these numbers into a cell in Sheet 1 (G11), then the macro searches Sheet2ColumnB for the number, goes across 21 cells in that same row, then enters today's date and time into that cell.
(It then goes back to Sheet1 and says "Job Booked Out" but I think I can do this bit)
I've tried to modify some other code I've found, but get errors in the 4th line, and I have no clue if it works.
Sub CloseJob()
Dim cell As Range
Dim temp As Range
For Each cell In Sheets("Sheet1").UsedRange.cell("G11").Cells
If cell <> "" And cell.Row <> 1 Then
Set temp = Sheets("Sheet2").Columns("B").Find(What:=cell.Value, _
LookIn:=xlFormulas, LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=True)
'if found
If Not temp Is Nothing Then
'if the search_criteria is in the same sheet
cell.Offset(0, 21) = Date
End If
End If
Next
End Sub
Error:
"Run-time error 483. Object doesn't support this property or method"
by your narrative you seem after this:
Sub CloseJob()
Dim temp As Range
Set temp = Sheets("Sheet2").Columns("B").Find(What:=Sheets("Sheet1").Range("G11").Value, _
LookIn:=xlFormulas, LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=True)
'if found
If Not temp Is Nothing Then temp.Offset(0, 21) = Date
End Sub
notice I changed LookAt:=xlPart to LookAt:=xlWhole for an exact match
Test and I will be able to get connect with like minded peopl

MsgBox after not finding a value

I have a macro that runs an InputBox in which user types number and then excel finds a cell in a certain range which contains that value. I'd like to make an MsgBox which would make an alert if given number is not found and run InputBox again until the value is in range.
I have kinda idea how do I do it, but can't make the finding itself work. I've recorded a macro but don't know how to set it properly if it doesn't find anything.
My code so far:
Sub leftbutton()
Start: n = InputBox("Podaj numer punktu z wykresu") 'give me a point number from a chart
If n = "" Then Exit Sub
If n = "0" Then
MsgBox ("Liczba musi byc wieksza od zera") 'number must be > 0
GoTo Start
End If
If Not IsNumeric(n) Then
MsgBox ("Podaj liczbe!") 'give me a number!
GoTo Start
End If
Range("AS3:AS50000").Select
if
Selection.Find(What:=n, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase _
:=False, SearchFormat:=False).Activate 'now how to know if it finds value or not?
Then msgbox("Nie ma takiego punktu na wykresie") 'there's no such point on a chart
Goto Start
Else '~> select cell with the found value
End If
End Sub
Code below will check in your range you specified and either give you error if nothing is found or row number of cell with match.
Dim FindResult As Object
n=... 'set whatever value you want to find
Range("AS3:AS50000").Select
Set FindResult = Selection.Find(n, LookIn:=xlFormulas, LookAt:=xlWhole)
If FindResult Is Nothing Then
MsgBox ("missing")
Else
MsgBox (FindResult.Row)
End If

Resources