Excel VBA Looking for Text in a Whole Column - vba

I have the following code to find the phrase "Please Review" in Column "I" and if not found show message, if found it must run the rest of my code but its not liking my IF code:
Sub OUTPUT()
Sheets("OUTPUT").Select
If Range("a2").Value < 1 Then
Else
Range("A2:I" & Range("A1").End(xlDown).Row + 1).ClearContents
End If
Sheets("SF Data").Select
If Range("I2:I192754").Value <> "Please Review" Then
MsgBox "Nudda"
Else
Columns("A:I").Select
Selection.AutoFilter
Range("I2").Select
ActiveSheet.Range("A1:I" & Range("A1").End(xlDown).Row + 1).AutoFilter Field:=9, Criteria1:= _
"Please Review"
Range("A2:I" & Range("A1").End(xlDown).Row + 1).Select
Selection.SpecialCells(xlCellTypeVisible).Select
Application.CutCopyMode = False
Selection.Copy
Sheets("OUTPUT").Select
Range("A2").Select
ActiveSheet.Paste
Sheets("SF Data").Select
ActiveSheet.Range("$A$1:$I$192754").AutoFilter Field:=9
Sheets("OUTPUT").Select
End If
MsgBox "Sanity Check performed. " & Format(Now, "mmmm d, yyyy hh:mm AM/PM")
End Sub
Many thanks guys

I believe the following should help you out, you should try to avoid Select & Activate statements, also by declaring your worksheets your code is more legible, to find the string I used the Find method and allocated the result to a Range variable to see if anything was found:
Sub OUTPUT()
Dim wsOut As Worksheet: Set wsOut = Sheets("OUTPUT")
Dim wsSF As Worksheet: Set wsSF = Sheets("SF Data")
'Declare and set the worksheets you are working with
Dim FoundPlease As Range
Dim LastRow As Long
If wsOut.Range("A2").Value > 1 Then wsOut.Range("A2:I" & wsOut.Range("A1").End(xlDown).Row + 1).ClearContents
'Clear contents if A2 > 1
LastRow = wsSF.Cells(wsSF.Rows.Count, "I").End(xlUp).Row
'find the last row with data on Column I in SF Data
Set FoundPlease = wsSF.Range("I2:I" & LastRow).Find(What:="Please Review", LookAt:=xlWhole)
'Search for "Please Review" on Column I in SF Data
If FoundPlease Is Nothing Then 'if not found
MsgBox "Nudda"
Else 'if found
wsSF.Cells.AutoFilter
wsSF.Range("A1:I" & wsSF.Range("A1").End(xlDown).Row + 1).AutoFilter Field:=9, Criteria1:="Please Review"
wsSF.Range("A2:I" & wsSF.Range("A1").End(xlDown).Row + 1).SpecialCells(xlCellTypeVisible).Copy
wsOut.Range("A2").PasteSpecial xlPasteAll
wsSF.Range("$A$1:$I$" & LastRow).AutoFilter Field:=9
End If
MsgBox "Sanity Check performed. " & Format(Now, "mmmm d, yyyy hh:mm AM/PM")
End Sub

It is giving an error, because Range("I2:I192754").Value <> "Please Review" is a bit illegal. If you want to check whether in one of the cells in the range there is the string "Please Review" present, you may consider using =CountIf() function:
Sub TestMe()
If WorksheetFunction.CountIf(Range("I2:I192754"), "Please Review") > 0 Then
Debug.Print WorksheetFunction.CountIf(Range("I2:I192754"), "Please Review")
End If
End Sub
Later, you may take a look at this topic - How to avoid using Select in Excel VBA.

One way would be to check each cell individually:
Dim TextFound As Boolean
TextFound=False
For Each cell In Range("I2:I192754")
If cell.value="Please Review" Then
TextFound=True
Exit For
End If
Next
If TextFound Then
...
Else
...
End IF

Related

VBA check if columns are the same

I have two Sheets in Excel that I need to check if the columns are the same in both sheets before processing them.
I have created a macro to do this check, but I'm wondering if there is a better way to achieve this.
Sub CheckColumns()
Sheets("Source1").Select
Range("A1").Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
Sheets("Sheet1").Select
Range("A1").Select
ActiveSheet.Paste
Sheets("Source2").Select
Range("A1").Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
Sheets("Sheet1").Select
Range("A2").Select
ActiveSheet.Paste
Range("A3") = "=IF(A1=A2,0,1)"
Range("A3").Copy
Range("A2").Select
Selection.End(xlToRight).Select
ActiveCell.Offset(1, 0).Range("A1").Select
Range(Selection, Selection.End(xlToLeft)).Select
ActiveSheet.Paste
Range("A4") = "=SUM(3:3)"
If Range("A4").Value = 0 Then
MsgBox "Same Columns"
Else
MsgBox "different Columns"
End If
End Sub
First of all you need to avoid selection; How to avoid using Select in Excel VBA macros
Specificaally about your code; I would try comparing two arrays as it always faster to work with arrays and also it doesn't need a dummy-sheet. However, your approach, except the selection part is faster in my mind. So I would include the explicit version of your approach shortly.
Sub CheckColumns()
Dim arrS1 As Variant, arrS2 As Variant
Dim LastRow As Long
With Worksheets("Source1")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
arrS1 = .Range("A1:A" & LastRow)
End With
With Worksheets("Source2")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
arrS2 = .Range("A1:A" & LastRow)
End With
If UBound(arrS1) <> UBound(arrS2) Then
MsgBox "Different Columns"
Exit Sub
End If
same = True
For i = LBound(arrS1) to UBound(arrS1)
If arrS1(i) <> arrS1(i) Then
same = False
Exit For
End If
Next i
If same = True Then
MsgBox "Same Column"
Else
MsgBox "Item " & i & " does not match. Stopped checking further"
End If
End Sub
This is the explicit version of your method:
Sub CheckColumns()
Dim rngrS1 As Range, rngS2 As Range, rngSH As Range
Dim LastRow1 As Long, LastRow2 As Long
With Worksheets("Source1")
LastRow1 = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rngS1 = .Range("A1:A" & LastRow)
End With
With Worksheets("Source2")
LastRow2 = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rngS2 = .Range("A1:A" & LastRow)
End With
If LastRow1 <> LastRow2 Or rngS1(1) <> rngS2(1) Then
'Second condition checks names of the columns
MsgBox "Different Columns"
Exit Sub
End If
With Worksheets("Sheet1")
Set rngSH = .Range("A1:A" & LastRow1)
End With
rngSH.Value = rngS1.Value
Set rngSH = rngSH.Offset(0,1)
rngSH.Value = rngS2.Value
Set rngSH = rngSH.Offset(0,1)
rngSH.formula "=IF(A1=B1,0,1)"
Worksheets(Sheet1).Range("D2") = "Sum(C:C)"
If Worksheets(Sheet1).Range("D2").Value <> 0 Then
MsgBox "Different Columns"
Else
MsgBox "Same Columns"
End If
End Sub
You could declare two arrays and compare that way...
Sub Compare()
Dim FirstSheet As Variant, SecondSheet As Variant
Dim a As Long, b As Long
FirstSheet = Sheets("Source1").Range("A1:" & _
Mid(Sheets("Source1").Range("A1").End(xlToRight).Address, 2, _
InStr(Right(Sheets("Source1").Range("A1").End(xlToRight).Address, _
Len(Sheets("Source1").Range("A1").End(xlToRight).Address) - 2), "$")) & 1)
SecondSheet = Sheets("Source2").Range("A1:" & _
Mid(Sheets("Source2").Range("A1").End(xlToRight).Address, 2, _
InStr(Right(Sheets("Source2").Range("A1").End(xlToRight).Address, _
Len(Sheets("Source2").Range("A1").End(xlToRight).Address) - 2), "$")) & 1)
On Error Resume Next
For a = 1 To WorksheetFunction.Max(Sheets("Source1").Range("A1:" & _
Mid(Sheets("Source1").Range("A1").End(xlToRight).Address, 2, _
InStr(Right(Sheets("Source1").Range("A1").End(xlToRight).Address, _
Len(Sheets("Source1").Range("A1").End(xlToRight).Address) - 2), "$")) & 1).Cells.Count, _
Sheets("Source1").Range("A1:" & Mid(Sheets("Source1").Range("A1").End(xlToRight).Address, 2, _
InStr(Right(Sheets("Source1").Range("A1").End(xlToRight).Address, _
Len(Sheets("Source1").Range("A1").End(xlToRight).Address) - 2), "$")) & 1))
If FirstSheet(1, a) <> SecondSheet(1, a) Then b = b + 1
Next
On Error GoTo 0
If b = 0 Then
MsgBox "Same Columns"
Else
MsgBox "different Columns"
End If
End Sub

UserForm to Search for, Cut, and Paste info onto new Sheet with Additional Info

I have two UserForms in my Worksheet, one to add clients and one to remove. The "Add Client" works perfect, however the "Remove Client" does not. I have used Breakpoints to see where my code is going wrong and what seems to be happening is it skips from "Private Sub OkButton2_Click()" to "On Error GoTo Err_Execute" and from "If Range("A" & CStr(LSearchRow)).Value = DCNameTextBox1.Value Then" all the way down to "End If"
I want the VBA upon the user clicking Okay to search for what was input in the Name box, cut that row from A to F(deleting the entire row), paste the info in the next empty row in sheet 2 and add the additional info the user put into the user form. I have looked at a lot of different codes and questions and none of them seem to quite do what I want.
Private Sub OkButton2_Click()
Dim emptyRow As Long
Dim LSearchRow As Integer
Dim LCopyToRow As Integer
On Error GoTo Err_Execute
'Start search in row 3
LSearchRow = 3
'Start copying data to row 3 in Sheet2 (row counter variable)
LCopyToRow = 3
While Len(Range("A" & CStr(LSearchRow)).Value) > 0
'If value in column A = "Client Name", copy entire row to Sheet2
If Range("A" & CStr(LSearchRow)).Value = DCNameTextBox1.Value Then
'Select row in Sheet1 to copy
Rows(CStr(LSearchRow) & "A:F" & CStr(LSearchRow)).Select
Selection.Copy
'Paste row into Sheet2 in next row
Sheets("Sheet2").Select
Rows(CStr(LCopyToRow) & "A:F" & CStr(LCopyToRow)).Select
ActiveSheet.Paste
'Add/Transfer Discharge info
Sheets("Sheet2").Cells(emptyRow, 7).Value = DCDateTextBox.Value
Sheets("Sheet2").Cells(emptyRow, 8).Value = DispoTextBox.Value
Sheets("Sheet2").Cells(emptyRow, 9).Value = ReasonTextBox.Value
'Move counter to next row
LCopyToRow = LCopyToRow + 1
'Go back to Sheet1 to continue searching
Sheets("Sheet1").Select
End If
LSearchRow = LSearchRow + 1
Wend
'Position on cell A3
Application.CutCopyMode = False
Range("A3").Select
MsgBox "Client has been moved to Discharge list."
Exit Sub
Err_Execute:
MsgBox "An error occurred."
End Sub
Using Range.Find is a little more efficient.
Private Sub OkButton2_Click()
Dim Source As Range, Target As Range
With Worksheets("Sheet1")
Set Source = .Range("A3", .Range("A" & .Rows.Count).End(xlUp))
End With
Set Target = Source.Find(What:=DCNameTextBox1.Value, LookIn:=xlValues, LookAt:=xlWhole)
If Not Target Is Nothing Then
'Reference the next enmpty row on Sheet2
With Worksheets("Sheet2")
With .Range("A" & .Rows.Count).End(xlUp).Offset(1)
'.Range("A1:F1") is relative to the row of it's parent range
.Range("A1:F1").Value = Target.Range("A1:F1").Value
.Range("H1:J1").Value = Array(DCDateTextBox.Value, DispoTextBox.Value, ReasonTextBox.Value)
Set Source = .Range("A3", .Range("A" & .Rows.Count).End(xlUp))
End With
End With
Target.Range("A1:F1").Delete Shift:=xlShiftUp
MsgBox "Client has been moved to Discharge list."
Else
MsgBox "Client not found", vbInformation, "No Data"
End If
Range("A3").Select
End Sub

VBA using Loop with .find and .copy values

I want to use a loop in my SearchFunction in a way it will search for a customer till the right customer is found. I'm using a custom msgbox to define if the found customer is the customer i was looking for.
So basicly i want this:
MsgBox "Is this the customer you were looking for?"
Yes: it will copy cells(sheet2) and paste them into the invoice (sheet1)
No: it will find next customer (and ask same question)**
** And keep doing/asking this till last found customer is shown.
This is how the msgbox looks like when a customer has been found:
Custom msgbox
At the moment it searches for a customer and shows it in a custom msgbox. When i say 'Yes this is the customer', it will copie the values like it should and paste them in the invoice. But when i say 'no this not my customer' it won't go to the next found customer but it will exit the SearchFunction.
I have tried using a Loop but i couldn't get it to work. Also i tried .findnext but i couldn't embed it to the code i'm using..
This is the code that i am using:
Sub SearchCustomer()
'
' Search for customer
'
'*****************************************************************************************************
Dim Finalrow As Integer
Dim I As Integer
Dim cC As Object
Dim iR As Integer
Dim foundrange As Range
'*****************************************************************************************************
' This Searches for the customer
'*****************************************************************************************************
' Set up searchrange
Set foundrange = Sheets("sheet2").Cells.Find(What:=Sheets("sheet1").Range("B12").Value, LookIn:=xlFormulas, LookAt:=xlPart)
' Checks if fields are filled
If Sheets("sheet1").Range("B12").Value = "" Then
MsgBox "Please fill in a search key", vbOKOnly, "Search customer"
Else
'When nothing is found
If foundrange Is Nothing Then
MsgBox "Customer not found," & vbNewLine & vbNewLine & "Refine your search key", vbOKOnly, "Search customer"
Else
Finalrow = Sheets("sheet1").Range("A1000").End(xlUp).Row
For I = 2 To Finalrow
'When range is found
If Worksheets("sheet2").Cells(I, 1) = foundrange Then
Set cC = New clsMsgbox
cC.Title = "Search contact"
cC.Prompt = "Is this the customer you searched for?" & vbNewLine & "" & vbNewLine & Worksheets("sheet2").Cells(I, 1) & vbNewLine & Worksheets("sheet2").Cells(I, 2) _
& vbNewLine & Worksheets("sheet2").Cells(I, 3) & vbNewLine & Worksheets("sheet2").Cells(I, 4) & vbNewLine & Worksheets("sheet2").Cells(I, 5)
cC.Icon = Question + DefaultButton2
cC.ButtonText1 = "Yes"
cC.ButtonText2 = "No"
iR = cC.MessageBox()
If iR = Button1 Then
'Name
Worksheets("sheet2").Cells(I, 1).Copy
Worksheets("sheet1").Range("B12").PasteSpecial xlPasteFormulasAndNumberFormats
'Adress
Worksheets("sheet2").Cells(I, 2).Copy
Worksheets("sheet1").Range("B13").PasteSpecial xlPasteFormulasAndNumberFormats
'Zipcode & City
Worksheets("sheet2").Cells(I, 3).Copy
Worksheets("sheet1").Range("B14").PasteSpecial xlPasteFormulasAndNumberFormats
'Phonenumber
Worksheets("sheet2").Cells(I, 4).Copy
Worksheets("sheet1").Range("B15").PasteSpecial xlPasteFormulasAndNumberFormats
'E-mail
Worksheets("sheet2").Cells(I, 5).Copy
Worksheets("sheet1").Range("B16").PasteSpecial xlPasteFormulasAndNumberFormats
ElseIf iR = Button2 Then
MsgBox "Customer not found", vbOKOnly, "Contact zoeken"
End If
Range("B12").Select
End If 'gevonden item
Next I
Application.CutCopyMode = False
End If
End If
End Sub
Some help would be great! Been searching for a long time now.
Thanks in advanced!
Greets Mikos
You need to restructure your code, the For loop doesn't make sense for looping over search results. You need a Do While Loop, see examples in Range.FindNext Method
Pseudo code:
Set foundrange = Sheets("sheet2").Cells.Find(What:=...)
Do While Not foundrange Is Nothing
If Msgbox(<Customer data from foundrange.Row>) = vbYes Then
' copy stuff
Exit Do ' we're done
Else
Set foundrange = Sheets("sheet2").Cells.FindNext(After:=foundrange)
End If
Loop
P.S. These are not the droids you're looking for!
Many thanks to Andre451 because he solved my problem!
Final code:
Sub SearchCustomer()
'
' Search customer
'
'*****************************************************************************************************
Dim Finalrow As Integer
Dim foundrange As Range
Dim answer As Integer
'*****************************************************************************************************
' Search for customername
'*****************************************************************************************************
' Search Range
Set foundrange = Sheets("sheet2").Cells.Find(What:=Sheets("sheet1").Range("B12").Value, LookIn:=xlFormulas, LookAt:=xlPart)
Finalrow = Sheets("sheet1").Range("A:A").End(xlDown).Row
' Checks if search range is filled
If Sheets("sheet1").Range("B12").Value = "" Then
MsgBox "Please fill in a searchkey", vbOKOnly, "Search customer"
Else
Do While Not foundrange Is Nothing
If MsgBox("Is this the customer you were looking for? " & foundrange, vbYesNo + vbQuestion, "Zoek klant") = vbYes Then
'Name
foundrange.Copy
Worksheets("sheet1").Range("B12").PasteSpecial xlPasteFormulasAndNumberFormats
'Address
foundrange.Offset(0, 1).Copy
Worksheets("sheet1").Range("B13").PasteSpecial xlPasteFormulasAndNumberFormats
'Zipcode and City
foundrange.Offset(0, 2).Copy
Worksheets("sheet1").Range("B14").PasteSpecial xlPasteFormulasAndNumberFormats
'Phonenumber
foundrange.Offset(0, 3).Copy
Worksheets("sheet1").Range("B15").PasteSpecial xlPasteFormulasAndNumberFormats
'Email
foundrange.Offset(0, 4).Copy
Worksheets("sheet1").Range("B16").PasteSpecial xlPasteFormulasAndNumberFormats
Exit Do
Else
Set foundrange = Sheets("sheet2").Cells.FindNext(After:=foundrange)
End If
Loop
Range("B12").Select
Application.CutCopyMode = False
End If
End Sub
Thanks again!

Yet another Excel VBA 404 error

I want this script to check the cells on column A if there is a URL-link in them, and if it is true then perform some cut-paste operations.
String #5 returns error 404, please help to solve this!
Sub xxxxxx()
Worksheets("1 (2)").Activate
For i = 1 To 2200
Range("A" & i).Select
If (cell.Range("A1").Hyperlinks.Count >= 1) Then
ActiveCell.Offset(1, 0).Range("A1").Select
Selection.Cut
ActiveCell.Offset(-1, 2).Range("A1").Select
ActiveSheet.Paste
End If
Next i
End Sub
Per #Siddharth Rout post about not using Activate/Select, I've rewritten your code below. No need to check hyperlinks inside the loop every time since it's always checking cell A1
Sub xxxxxx()
Dim ws As Worksheet
Set ws = Worksheets("1 (2)")
Dim LastRow As Long
LastRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
If (ws.Range("A1").Hyperlinks.Count > 0) Then
For i = 2 To LastRow
Range("A" & i).Offset(-1, 2).Value = Range("A" & i).Value
Range("A" & i).Clear
Next i
End If
End Sub

Malformed VLookup formula when trying to use Range.Formula property

I have Excel sheets that will have data from many sources that will be grouped together so that what needs to be looked upon is above what you are looking from so there will be many VLookups on separate portions of one sheet.
Sub linkFDCfdv()
Range("A1").Select
Dim doesFDChaveDescription As Boolean
Dim isLastRowFDC As Boolean
Dim myRange As String
Dim firstFDCrow As Long
Dim lastFDCrow As Long
While Len(Selection.Value) > 0
If Selection.Value = "FDC" Then
If isLastRowFDC = False Then
firstFDCrow = ActiveCell.Row
End If
isLastRowFDC = True
ActiveCell.Offset(0, 3).range("A1").Select
If Len(Selection.Value) > 0 Then
doesFDChaveDescription = True
Else
doesFDChaveDescription = False
End If
ActiveCell.Offset(0, -3).range("A1").Select
Else
If isLastRowFDC = True Then
lastFDCrow = ActiveCell.Row - 1
End If
End If
If Selection.Value = "FDV" Then
ActiveCell.Offset(0, 10).range("A1").Select
myRange = "B" & firstFDCrow & ":D" & lastFDCrow
ActiveCell.Formula = "=VLOOKUP(R[0]C[-2]," & myRange & ",2)"
ActiveCell.Offset(0, -10).range("A1").Select
End If
ActiveCell.Offset(1, 0).range("A1").Select
Wend
End Sub
What's happening is that my macro makes the formula:
=VLOOKUP(I9,'B3':'D8',2)
If I take out the ' marks the macro works perfectly.
That is because you are using a mix of R1C1 style with A1 style. Is this what you are trying?
ActiveCell.Formula = "=VLOOKUP(" & ActiveCell.Offset(,-2).Address & _
"," & myRange & ",2)"