Error when setting some sheets in code but not with others - vba

I have a large macro for automating invoices for my company. Sometimes we have proforma invoices that mean we delete two of the three invoices that are manipulated (Client, Owner, and VAT). Therefore I have to check before each code is run whether the sheet exists.
The problem I've run into is that it will give me a run time error 424 when I set some of the sheets to be checked. In the code below it is the second time that the TVA sheet is checked for where the error occurs (If TVASheet Is Nothing Then). Mind you I have almost exactly the same code running above it except it is checking for ClientSheet instead.
'If the current payment is the only payment then we add to the TVA invoice
'that the rest is due
'on the date the balance of rental is due
If (Range("F3") <> "" And Range("G3") = "" And Range("H3") = "") Then
On Error Resume Next
Set TVASheet = Sheets("TVA Invoice")
On Error GoTo 0
If TVASheet Is Nothing Then
Else
Sheets("TVA Invoice").Select
If Cells.Find(What:="du paiement sera reçu", After:=ActiveCell, LookIn:= _
xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:= _
xlNext, MatchCase:=False, SearchFormat:=False) Is Nothing Then
Cells.Find(What:="Select!F3", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Offset(1, 0).Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Selection.Font.Bold = False
ActiveCell = _
"=100 - 100*TEXT(Select!F3,""0%"")&""% du paiement sera reçu le ""&PROPER(TEXT(Select!C30,""JJ-MMMM-AAAA""))&"""""
Else
End If
End If
Else
On Error Resume Next
Set TVASheet = Sheets("TVA Invoice")
On Error GoTo 0
If TVASheet Is Nothing Then
Else
Sheets("TVA Invoice").Select
If Cells.Find(What:="du paiement sera reçu", After:=ActiveCell, LookIn:= _
xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:= _
xlNext, MatchCase:=False, SearchFormat:=False) Is Nothing Then
Else
Cells.Find(What:="du paiement sera reçu", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Rows("1:1").EntireRow.Select
Selection.Delete Shift:=xlUp
End If
End If
End If
Sheets("Select").Select

Declare your TVASheet variable at the beginning of your code:
Dim TVASheet As Worksheet
Obviously the "TVA Invoice" sheet is not found and the Set command fails. Because of your On Error Resume Next the program continues and the interpreter has no clue what TVASheet should be in your If clause. You can avoid this by the declaration.

Related

How to use the find funtion to search for the Value of a text box?

I am trying to make a userform that can bring up data using an ID number.
I am trying to reference a text box and select it, and then using it as a reference to fill out the Time and comments in the sheet. I think the is I cant put "txtID.Value" into the Find function.
Here is an example of my code:
Sheet1.Select
Columns("A:A").Select
Selection.Find(What:="txtID.Value", After:=ActiveCell, LookIn:= _
xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:= _
xlNext, MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Select
ActiveCell.Offset(0, 8).Value = txtTime2
ActiveCell.Offset(0, 9).Value = txtComment2
When using the Find function, it's recommended to use a Range object, and set it to the result. This method allows you to trap a possible scenario where Find failed to find a match in the searched range Sheet1.Columns("A:A").
Also, try to avoid using Select, Selection and ActiveCell, and use fully qualified Range objects (like in the code below).
Code
Dim FndRng As Range
Set FndRng = Sheet1.Columns("A:A").Find(What:=txtID.Value, LookIn:=xlFormulas, LookAt:=xlPart, _
SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
If Not FndRng Is Nothing Then ' successful find
FndRng.Offset(, 8).Value = txtTime2
FndRng.Offset(, 9).Value = txtComment2
Else ' unable to fins the value in txtID
MsgBox "Unable to find " & txtID.Value & " in Sheet1"
End If
Note: if you have this code outisde the User_Form module, then you need to add the User_Form reference when trying to get the txtID.Value.
For eaxmple, let's say the name of your form is UserForm1, then change this line to:
Set FndRng = Sheet1.Columns("A:A").Find(What:=UserForm1.txtID.Value, LookIn:=xlFormulas, LookAt:=xlPart, _
SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
To Make it work, you will have to put the code as below, which is quite self explainatory.
Selection.Find(What:=Userform1.textbox1.value, After:=ActiveCell, LookIn:= _
xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:= _
xlNext, MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Select
hope this helps

Getting run-time error running VBA code not my own

I need to reverse engineer someone else's code and make it run. Right now it is throwing an error at me complaining that some variable isn't set.
I'm not sure what it is talking about exactly. Here is the top part of the subroutine with the error.
Sub OBI_Vendor_Detail_Macro()
Cells.Select
With Selection
.WrapText = False
.MergeCells = False
End With
Range("C4").Select
Cells.Find(What:="Grand Total", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
The last line produces this error Run-time error '91': Object variable or With block variable not set
Hope I've provided enough info. If not please let me know. Thanks.
You need to try to Find first, then check that you found something:
Dim foundCell As Range
Set foundCell = Cells.Find(What:="Grand Total", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not foundCell Is Nothing Then
foundCell.Activate
End If

VBA Run-Time Error 91 - 2

I have a macro which works for the first 36 rows but then shows a run-time 91 error. It shows the error in find statement. The purpose of the macro is to calculate the 90th percentile of the figures populated in a column, count the number of values which are equal or greater the percentile, and provide the division across various departments. Can anybody please help me to correct the error?
For bb = 1 To temcnt
cc = Sheets("tem").Cells(bb, ttc + 4).Value
Sheets("Geographic Strength").Activate
Cells.Find(What:=cc, After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
ff1 = ActiveCell.Column
Sheets("tem").Activate
rnggg = Range(Cells(2, 6), Cells(ttr, 6))
mamm = WorksheetFunction.CountIf(Range(Cells(2, 6), Cells(ttr, 6)), cc)
Sheets("geographic strength").Activate
f222 = Sheets("individual strength").Cells(1, iii).Value
**Cells.Find(What:=f222, After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
f333 = ActiveCell.Row**
'Error is in the above statement(Cells.Find)
Cells(f333, ff1).Value = mamm
Next bb
Sheets("tem").Delete
Next iii
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
it's because
Cells.Find(What:=f222, After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False)
didn't succeed in finding the wanted cell so it returns Nothing, and you can't Activate Nothing
so you could go like follows:
'... your code before
f222 = Sheets("individual strength").Cells(1, iii).Value
Dim found As Range
Set found = Cells.Find(What:=f222, After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False)
If Not found Is Nothing Then '<-- check if any cell has been found
found.Activate
f333 = ActiveCell.Row
'... rest of your code should f222 have been found
End If
' rest of your code

Looking for multiple terms (sorted by priority)

Would it be possible to use the find method to search for back-up options?
Here's my code right now:
Set foundCell = Cells.Find(What:="RCP 1", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False)
If Not foundCell Is Nothing Then
foundCell.Activate
foundCell.Rows("1:1").EntireRow.Select
Selection.Copy
Range("A" & (PLcount + 8)).Select
ActiveSheet.Paste
Else
Set foundCell = Cells.Find(What:="RCP- 1", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False)
If Not foundCell Is Nothing Then
foundCell.Activate
foundCell.Rows("1:1").EntireRow.Select
Selection.Copy
Range("A" & (PLcount + 8)).Select
ActiveSheet.Paste
End If
End If
I would like to be able to do something like below. Note the text after .Find(What:=)
Set foundCell = Cells.Find(What:="RCP 1" "RCP- 1" "RCP 1", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False)
If Not foundCell Is Nothing Then
foundCell.Activate
foundCell.Rows("1:1").EntireRow.Select
Selection.Copy
Range("A" & (PLcount + 8)).Select
ActiveSheet.Paste
End If
Where the first term is the first priority, the second term is the second priority, the third term is the third priority, etc.
EDIT - there is only limited support for wildcards in Find() - you would probably not class it as "regex-level" functionality:
* - zero or more characters
? - single character
~ - escapes * or ? if you want to find those literal characters
Alternatively can put the Find into a separate function:
Sub Tester()
Dim foundCell, PLCount As Long
PLCount = 3
Set foundCell = FindFirst(Cells, Array("RCP 1", "RCP- 1"))
If Not foundCell Is Nothing Then
'no need for any select/activate
foundCell.EntireRow.Copy Destination:=Range("A" & (PLCount + 8))
End If
End Sub
'return the first match to a value in the array "arrWhat"
' Returns Nothing if no match
Function FindFirst(rngWhere, arrWhat) As Range
Dim v, f As Range
For Each v In arrWhat
Set f = rngWhere.Find(what:=v, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not f Is Nothing Then Exit For
Next v
Set FindFirst = f
End Function

If (search term) found, do (action). If not, end if

If you guys could help me out, that would be great because it would really help me.
Here's what I'm trying to do:
Search for a cell with a specific term
If found, copy the entire row that the cell is in and paste it into a row above it.
If not found, do nothing and continue with the code
Here's my code:
Sub Test()
'
' Test Macro
'
' Keyboard Shortcut: Ctrl+b
'
Range("A5").Select
Cells.Find(What:="PL 1", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
If Not IsEmpty(ActiveCell.Value) Then
ActiveCell.Rows("1:1").EntireRow.Select
Selection.Copy
Range("A5").Select
ActiveSheet.Paste
End If
Range("A5").Select
Cells.Find(What:="PL 2", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
If Not IsEmpty(ActiveCell.Value) Then
ActiveCell.Rows("1:1").EntireRow.Select
Selection.Copy
Range("A6").Select
ActiveSheet.Paste
End If
Range("A5").Select
Cells.Find(What:="PL 3", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
If Not IsEmpty(ActiveCell.Value) Then
ActiveCell.Rows("1:1").EntireRow.Select
Selection.Copy
Range("A7").Select
ActiveSheet.Paste
End If
End Sub
My code only works if the value is found. If it's not found it runs into the error below:
Cells.Find is a function that returns a Range object reference; when it doesn't find anything, the reference will be Nothing. And you can't call .Activate on Nothing:
This method returns Nothing if no match is found. The Find method does not affect the selection or the active cell. (MSDN)
Cells.Find(What:="PL 2", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
You need to rewrite your code and avoid .Select and .Activate, and avoid working with ActiveCell and implicitly with ActiveSheet (which you are doing by not qualifying the Cells call with a proper worksheet reference).
Your formatting makes it hard to read the code, for several reasons:
Arguments are being specified on different lines
Line continuations are being palced at arbitrary locations
Nested member calls aren't lined up
Compare to:
Cells.Find(What:="PL 2", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False) _
.Activate
That's just readability. The problem is that you basically assume that .Find returns a valid object reference. Don't assume, explicitly check:
Set result = Cells.Find(...)
If Not result Is Nothing Then result.Activate
But really, you need to figure out a way to avoid .Select and .Activate.
You can try something like this instead (untested):
Sub HideAndSeek()
Dim foundCell As Range
For i = 1 To 3
Set foundCell = Cells.Find(What:="PL " & i, LookIn:=xlFormulas, LookAt:=xlPart)
If Not foundCell Is Nothing Then
Intersect(foundCell.EntireRow, ActiveSheet.UsedRange).Offset(-1, 0).Value = _
Intersect(foundCell.EntireRow, ActiveSheet.UsedRange).Value
End If
Set foundCell = Nothing
Next
End Sub
The principle being that you write the code you need once and then create a loop to repeat the code for you.
The other part of this answer is checking that the cell was found - to do this we check that the range was actually set (which means it isn't Nothing) using
If Not foundRange Is Nothing