I am trying to search for a persons' name within another Range.Find but I keep getting Run-Time Error 91 - Object variable or With block variable not set.
Something happens to "rngFound" within "getPaid".
Sub EmailClick()
Dim lastSeasonRow As Double
lastSeasonRow = Worksheets("Season 2014-2015").Range("A" & Worksheets("Season 2014-2015").Rows.Count).End(xlUp).Row
Dim lastSeasonEmailRow1 As Double
lastSeasonEmailRow1 = Worksheets("Email").Range("A" & Worksheets("Email").Rows.Count).End(xlUp).Row
Dim rng As Range
Dim rngFound As Range
Dim getPaid As Range
Dim ErrorEmail As String
Dim colMyCol As New Collection 'Our collection
For j = 2 To lastSeasonRow
Set rng = Worksheets("Email").Range("A2:A" & lastSeasonEmailRow1)
Set rngFound = rng.Find(Worksheets("Season 2014-2015").Cells(j, 1).Value)
If Not rngFound Is Nothing Then
' If its Found
If DoesItemExist(colMyCol, rngFound.Offset(0, 1).Value) = False Then
'Check If Already completed swimmer's family
Dim CountSwimmers As String
CountSwimmers = Application.CountIf(Worksheets("Email").Range("C2:C" & lastSeasonEmailRow1), rngFound.Offset(0, 2).Value)
If CountSwimmers > 1 Then
For s = 1 To CountSwimmers
If s = 1 Then
'If first swimmer
Set rng = Worksheets("Email").Range("C2:C" & lastSeasonEmailRow1)
Set rngFound = rng.Find(rngFound.Offset(0, 2).Value)
Debug.Print rngFound.Offset(0, -2).Value
Set rngBFound = rngFound
Else
'Next swimmer in family
Set rngFound = rng.FindNext(rngFound)
Debug.Print rngFound.Offset(0, -2).Value
********************** When Debugging, above line is Highlighted.
End If
********************************' TODO: Grab Worksheet's Name with persons' name and get Money column**
Set getPaid = Worksheets("Season 2014-2015").Range("A2:A" & lastSeasonRow).Find(rngFound.Offset(0, -2).Value)
If Not getPaid Is Nothing Then
'If its found
If getPaid.Offset(0, 14).Value <> "" Then
'If they do owe money
Debug.Print getPaid.Offset(0, 14).Value
Else
End If
End If
Next s
'write name to list, if name in array skip it, when lastSeasonRow, remove array.
colMyCol.Add (rngFound.Offset(0, -1).Value)
'TODO: change values below to strings that will correspond with aboves combined values
If rngFound.Value = "Michael" Then
Call Send_Email_Using_VBA(rngFound.Offset(0, 2).Value, rngFound.Offset(0, 1).Value, rngFound.Value, Worksheets("Season 2014-2015").Cells(j, 15).Value)
End If
Else
Debug.Print rngFound.Value
If Worksheets("Season 2014-2015").Cells(j, 15).Value <> "" Then
'If they do owe money
If rngFound.Offset(0, 3).Value <> "" Then
'if multiple emails (primary and cc)
If rngFound.Value = "Michael" Then
Call Send_Email_Using_VBA(rngFound.Offset(0, 2).Value, rngFound.Offset(0, 1).Value, rngFound.Value, Worksheets("Season 2014-2015").Cells(j, 15).Value, rngFound.Offset(0, 3).Value)
End If
Else
If rngFound.Value = "Michael" Then
Call Send_Email_Using_VBA(rngFound.Offset(0, 2).Value, rngFound.Offset(0, 1).Value, rngFound.Value, Worksheets("Season 2014-2015").Cells(j, 15).Value)
End If
End If
End If
End If
End If
Else
ErrorEmail = ErrorEmail + Worksheets("Season 2014-2015").Cells(j, 1).Value + vbNewLine
End If
Next j
If ErrorEmail <> "" Then
MsgBox ("No Email Found For: " & vbNewLine & ErrorEmail)
End If
End Sub
Thank You
EDIT: Added Images for data reference:
Email Worksheet
Season 2014-2015 WorkSheet
For this proposed solution, you will need to change the getPaid variable to type long and add a variable (e.g. gotPaid) of type double.
Dim getPaid As Long, gotPaid As Double
Change the following section of code.
Set getPaid = Worksheets("Season 2014-2015").Range("A2:A" & lastSeasonRow).Find(rngFound.Offset(0, -2).Value)
If Not getPaid Is Nothing Then
'If its found
If getPaid.Offset(0, 14).Value <> "" Then
'If they do owe money
Debug.Print getPaid.Offset(0, 14).Value
Else
End If
End If
To this.
With Worksheets("Season 2014-2015")
gotPaid = Application.SumIfs(.Columns("O"), .Columns("A"), rngFound.Offset(0, -2).Value)
getPaid = Application.CountIfs(.Columns("A"), rngFound.Offset(0, -2).Value)
If CBool(getPaid) Then
'If its found
If CBool(gotPaid) Then
'If they do owe money
Debug.Print rngFound.Offset(0, -2).Value & ": " & gotPaid
Else
End If
End If
End With
By shuffling off the second find operation, you are not redefining the first and the .FindNext should keep operating until you meet the CountSwimmers number. Alternately you could do this by not reusing the same variables but the worksheet functions should work well here.
Due to your speciality helper functions like DoesItemExist this could not be tested but it does compile.
Related
I'm having a bit of trouble with this and I'm not sure why...
My code (such that it is, a work in progress) is getting stuck on this line:
Set starRange = .Range(Cells(title), Cells(LR, 3))
Can I not use a range variable to set a new range in this way?
Sub cellPainter()
Dim ws As Worksheet
Dim starRange, titleRange, found As Range
Dim errorList() As String
Dim i, LR As Integer
i = 0
ReDim errorList(i)
errorList(i) = ""
For Each ws In ActiveWorkbook.Worksheets
With ws
LR = .Cells(.Rows.Count, "C").End(xlUp).Row
Set titleRange = .Range("C4")
If InStr(1, titleRange, "Title", vbBinaryCompare) < 1 Then
Set found = .Range("C:C").Find("Title", LookIn:=xlValues)
If Not found Is Nothing Then
titleRange = found
Else
errorList(i) = ws.Name
i = i + 1
ReDim Preserve errorList(i)
End If
End If
Set starRange = .Range(Cells(titleRange), Cells(LR, 3))
For Each cell In starRange
If InStr(1, cell, "*", vbTextCompare) > 0 Then Range(cell, cell.Offset(0, 2)).Interior.ColorIndex = 40
If InStr(1, cell, "*", vbTextCompare) = 0 Then Range(cell, cell.Offset(0, 2)).Interior.ColorIndex = 0
Next cell
End With
Next ws
If errorList(0) <> "" Then
txt = MsgBox("The following worksheets were missing the Title row, and no colour changes could be made:" & vbNewLine)
For j = 0 To i
txt = txt & vbCrLf & errorList(j)
Next j
MsgBox txt
End If
End Sub
Edit:
Rory cracked it!
When using a variable inside Range, the Cells property is not required:
Set starRange = .Range(titleRange, .Cells(LR, 3))
I need to find the match for each cell(C:C)value of sheet1 in sheet2 (C:C) and if the value matches copy the corresponding next cell i.e, D:D and replace in sheet 2. If it does not match then copy and paste the Range A to D in the next empty cell in sheet 2
Sub Method1()
Dim strSearch As String
Dim strOut As String
Dim bFailed As Boolean
Dim i As Integer
strSearch = Sheet1.Range("C2")
i = 1
Do Until ActiveCell.Value = Empty
ActiveCell.Offset(1, 0).Select 'move down 1 row
i = i + 1 'keep a count of the ID for later use
Loop
'ActiveCell.Value = i
On Error Resume Next
strOut = Application.WorksheetFunction.VLookup(strSearch, Sheet2.Range("C:C"), 2, False)
If Err.Number <> 0 Then bFailed = True
On Error GoTo 0
If Not bFailed Then
MsgBox "corresponding value is " & vbNewLine & strOut
Else
MsgBox strSearch & " not found"
End If
End Sub
Sheet1:`enter code here
Sheet2:
However, I made change to my code and it does the job, but I want to repeat the function for each cell in C:C, have a look
Sub Method1()
Dim strSearch As String
Dim strOut As String
Dim bFailed As Boolean
Dim i As Integer
strSearch = Sheet1.Range("C2")
i = 1
'Do Until ActiveCell.Value = Empty
ActiveCell.Offset(1, 0).Select 'move down 1 row
i = i + 1 'keep a count of the ID for later use
' Loop
'ActiveCell.Value = i
On Error Resume Next
strOut = Application.WorksheetFunction.VLookup(strSearch, Sheet2.Range("C:C"), 1, False)
If Err.Number <> 0 Then bFailed = True
On Error GoTo 0
If Not bFailed Then
Worksheets("Sheet1").Range("e2").Copy
Worksheets("Sheet2").Range("e2").PasteSpecial Paste:=xlPasteFormulas
Application.CutCopyMode = False
ActiveCell.Interior.ColorIndex = 6
MsgBox "corresponding value been copied " & vbNewLine & strOut
Else
MsgBox strSearch & " not found"
End If
End Sub
Try this:
Sub Method1()
Dim cSearch As Range, m
Set cSearch = Sheet1.Range("C2")
Do While Len(cSearch.Value) > 0
'omit the "WorksheetFunction" or this will throw a run-time error
' if there's no match. Instead we check the return value for an error
m = Application.Match(cSearch.Value, Sheet2.Range("C:C"), 0)
If Not IsError(m) Then
'got a match - update ColD on sheet2
Sheet2.Cells(m, "D").Value = cSearch.Offset(0, 1).Value
Else
'no match - add row to sheet2 (edit)
cSearch.Offset(0, -2).Resize(1, 4).Copy _
Sheet2.Cells(Rows.Count, "A").End(xlUp).Offset(1, 0)
End If
Set cSearch = cSearch.Offset(1, 0) 'next value to look up
Loop
End Sub
I am trying to implement some VBA code such that if the word, "LowLimit" in the first row. If found, then carry out the calculations and move to next sheet. If not found, then go to next sheet.
I have declared the word "LowLimit", Dim lowLimHdr As String. How do implement the IF...THEN using this argument before entering into my calculations?
This is what I have so far:
Sub ReturnMarginal()
'UpdatebySUPERtoolsforExcel2016
Dim xOut As Worksheet
Dim xWb As Workbook
Dim xWks As Worksheet
Dim InterSectRange As Range
Dim lowLimCol As Integer
Dim hiLimCol As Integer
Dim measCol As Integer
Dim lowLimHdr As String
Application.ScreenUpdating = False
Set xWb = ActiveWorkbook
For Each xWks In xWb.Sheets
xRow = 1
With xWks
FindString = "LowLimit"
'If
.Cells(xRow, 16) = "Meas-LO"
.Cells(xRow, 17) = "Meas-Hi"
.Cells(xRow, 18) = "Min Value"
.Cells(xRow, 19) = "Marginal"
LastRow = .UsedRange.Rows.Count
lowLimCol = Application.WorksheetFunction.Match("LowLimit", xWks.Range("1:1"), 0)
hiLimCol = Application.WorksheetFunction.Match("HighLimit", xWks.Range("1:1"), 0)
measLimCol = Application.WorksheetFunction.Match("MeasValue", xWks.Range("1:1"), 0)
.Range("P2:P" & LastRow).Formula = "=" & Cells(2, measLimCol).Address(False, False) & "-" & Cells(2, lowLimCol).Address(False, False)
.Range("Q2:Q" & LastRow).Formula = "=" & Cells(2, hiLimCol).Address(False, False) & "-" & Cells(2, measLimCol).Address(False, False)
.Range("R2").Formula = "=min(P2,Q2)"
.Range("R2").AutoFill Destination:=.Range("R2:R" & LastRow)
.Range("S2").Formula = "=IF(AND(R2>=-3, R2<=3), ""Marginal"", R2)"
.Range("S2").AutoFill Destination:=.Range("S2:S" & LastRow)
End With
Application.ScreenUpdating = True 'turn it back on
Next xWks
End Sub
If Not xWks.Rows(1).Find(FindString) Is Nothing Then
' do your calculations
End If
You need to dim your variables lowLimCol, HighLimCol and measCol as Variants because in the case of no match, Application.Match returns an error variant, otherwise a number that represents the index of the found column.
Dim lowLimCol. hiLimCol, measCol
lowLimCol = Application.Match("LowLimit", xWks.Range("1:1"), 0)
hiLimCol = Application.Match("HighLimit", xWks.Range("1:1"), 0)
measLimCol = Application.Match("MeasValue", xWks.Range("1:1"), 0)
' Check if all these columns were found in the header to proceed:
If Not (IsError(lowLimCol) Or IsError(highLimCol) Or IsError(measLimCol)) Then
'
' You calculations here
'
End If
p.s. the variable lowLimHdr is your code seems unnecessary.
You could also keep them declared as integers and then use
If Application.WorksheetFunction.CountIf(Range("1:1"), LowLimHdr) > 0 Then
' do all my calcuations in here
End If
That's assuming that any sheet with "LowLimit" will definitely have the other headers too, otherwise previous answer is better for error catching.
EDIT: In a similar vein to A.S.H's answer, to do full error catching in case any of the headers are missing you'd need a triple check:
If Application.WorksheetFunction.CountIf(Range("1:1"), "LowLimit") > 0 And _
Application.WorksheetFunction.CountIf(Range("1:1"), "HighLimit") > 0 And _
Application.WorksheetFunction.CountIf(Range("1:1"), "MeasValue") > 0 Then
' do all my calcuations in here
End If
First off, ill give credit where credit is due. This is put together using code from u/Joe Was from Mr.Excel.com and exceltip.com.
Now that I have gotten that out of the way I am trying to create a search function that will search through my 9 sheet document in excel, to find a value that was typed into a search box. Then paste those values onto the first page of the workbook.
What do I need to change in my code to make it paste to the right place on the search page? I have tried changing things in the last loop because that is where I get the "Run-Time error 91. Object variable or with block variable not set".
I've googled that error, but variables always screw me up so that may be the problem.
The search page.
This is where the Debugger stops.
This is my code so far.
Sub Find_one()
'Find Function For ERF Spreadsheet'
'Type in Box, Press Button, Display the Results'
Dim ws As Worksheet, Found As Range
Dim myText As String, FirstAddress As String
Dim AddressStr As String, foundNum As Integer
myText = Range("D5")
If myText = "" Then Exit Sub
For Each ws In ThisWorkbook.Worksheets
With ws
'Do not search sheet1'
If ws.Name = "Sheet1" Then GoTo myNext
Set Found = .UsedRange.Find(What:=myText, LookIn:=xlValues, LookAt:=xlPart, MatchCase:=False)
If Not Found Is Nothing Then
FirstAddress = Found.Address
Do
foundNum = foundNum + 1
AddressStr = AddressStr & .Name & " " & Found.Address & vbCrLf
Set Found = .UsedRange.FindNext(Found)
'Found.EntireRow.Copy _
'Destination:=Worksheets("Sheet4").Range("A65536").End(xlUp).Offset(1, 0)
Loop While Not Found Is Nothing And Found.Address <> FirstAddress
End If
myNext:
End With
Next ws
If Len(AddressStr) Then
Sheet8.Range("B18") = ws.Cells(x, 1)
Sheet8.Range("C18") = ws.Cells(x, 2)
Sheet8.Range("D18") = ws.Cells(x, 3)
Sheet8.Range("E18") = ws.Cells(x, 4)
Sheet8.Range("F18") = ws.Cells(x, 5)
Sheet8.Range("G18") = ws.Cells(x, 6)
Sheet8.Range("H18") = ws.Cells(x, 7)
Sheet8.Range("I18") = ws.Cells(x, 8)
Sheet8.Range("J18") = ws.Cells(x, 9)
Else:
MsgBox "Unable to find " & myText & " in this workbook.", vbExclamation
End If
End Sub
This is the original code for the last loop...
If Len(AddressStr) Then
MsgBox "Found: """ & myText & """ " & foundNum & " times." & vbCr & _
AddressStr, vbOKOnly, myText & " found in these cells"
Else:
MsgBox "Unable to find " & myText & " in this workbook.", vbExclamation
End If
Here, try this out. I redid how I interpreted the first section. I'm not entirely sure what you're trying to do with everything so let me know if this works or where it went wrong.
Sub FindOne()
Dim k As Integer
Dim myText As String, searchColumn As String
Dim totalValues As Long
Dim nextCell As Range
k = ThisWorkbook.Worksheets.Count
myText = Sheets(1).Range("D5").Value
If myText = "" Then
MsgBox "No Address Found"
Exit Sub
End If
Select Case ComboBox1.Value
Case "Equipment Number"
searchColumn = "A"
Case "Sequence Number"
searchColumn = "B"
Case "Repair Order Number(s)"
searchColumn = "D"
Else
MsgBox "Please select a value for what you are searching by."
End Sub
End Select
For i = 2 To k
totalValues = Sheets(i).Range("A65536").End(xlUp).Row
ReDim AddressArray(totalValues) As String
For j = 0 To totalValues
AddressArray(j) = Sheets(i).Range(searchColumn & j + 1).Value
Next j
For j = 0 To totalValues
If (InStr(1, AddressArray(j), myText) > 0) Then
Set nextCell = Sheets(1).Range("A65536").End(xlUp).Offset(1, 0)
Range(nextCell, nextCell.Offset(0, 8)).Value = Sheets(i).Range("A" & j, "I" & j).Value
End If
Next j
Next i
End Sub
Also I have no clue what that second part of the code is supposed to be, so if you want to elaborate on the section with If Len(AddressStr) Then, I'd appreciate it because that really doesn't even work as an If...Then statement lol :)
My mind is broken. I have spent days trying to figure out why this is happening:
After a user form is filled out there is a button to populate a corresponding spreadsheet. The sheet is determined by the first combo box (catSel.value). To find the last empty row I use the rngSrch portion of the code below.
On one sheet If Application.WorksheetFunction.CountA(Acell.EntireRow) = 0 comes back as false and firstBlankRow = Acell.row is not run.
I have tried deleting the sheet and creating a new one(copying one that works), changing the name and commenting out/changing the code.
Any ideas why this is happening? Also ws.Range("A" & firstBlankRow) = Me.equipId.value is coming back with Run-time Error ‘1004’: method ‘Range’ of object ’_worksheet’ failed
Private Sub AddCont_Click()
Dim firstBlankRow As Long
Dim ws As Worksheet
Dim srchRng As Range
Dim Acell As Range
Set ws = Worksheets(CatSel.value)
On Error GoTo Err
With ws
Set srchRng = .UsedRange.Columns(1).Find("")
If Not srchRng Is Nothing Then
Set srchRng =.UsedRange.Columns(1).SpecialCells(xlCellTypeBlanks)
For Each Acell In srchRng
If Application.WorksheetFunction.CountA(Acell.EntireRow) = 0 Then
firstBlankRow = Acell.row
Exit For
End If
Next
Else
If Application.WorksheetFunction.CountA(Cells(.Rows.Count, 1).EntireRow) = 0 Then
MsgBox "Please start a new sheet"
Else
firstBlankRow = .UsedRange.SpecialCells(xlCellTypeBlanks).row + 1
End If
End If
'Equipment ID
ws.Range("A" & firstBlankRow) = Me.equipId.value
'Parent or Next Level
ws.Range("B" & firstBlankRow) = Me.NextLev.value
'Keyword
ws.Range("C" & firstBlankRow) = Me.KeySel.value
'Cost Center
ws.Range("E" & firstBlankRow) = Me.CostSel.value
'Department
ws.Range("F" & firstBlankRow) = Me.DepartSel.value
'Location 1
ws.Range("G" & firstBlankRow) = Me.Loc1.value
'Location 2
ws.Range("H" & firstBlankRow) = Me.Loc2.value
'Location 3
ws.Range("I" & firstBlankRow) = Me.Loc3.value
'Location 4
ws.Range("J" & firstBlankRow) = Me.Loc4.value
'Beginning of specs
'L5
ws.Range("L" & firstBlankRow) = Me.L3Sel.value
'M5
ws.Range("M" & firstBlankRow) = Me.M3Sel.value
'N5
ws.Range("N" & firstBlankRow) = Me.N3sel.value
'O5
ws.Range("O" & firstBlankRow) = Me.O3Sel.value
'P5
ws.Range("P" & firstBlankRow) = Me.P3Sel.value
'Q5
ws.Range("Q" & firstBlankRow) = Me.Q3Sel.value
'R5
ws.Range("R" & firstBlankRow) = Me.R3Sel.value
'S5
ws.Range("S" & firstBlankRow) = Me.S3Sel.value
'T5
ws.Range("T" & firstBlankRow) = Me.T3Sel.value
'U5
ws.Range("U" & firstBlankRow) = Me.U3Sel.value
MsgBox ("successfully Added")
End With
Err: MsgBox ("something went wrong")
End Sub
I think in this part of the code
Set srchRng = .UsedRange.Columns(1).Find("")
If Not srchRng Is Nothing Then
Set srchRng =.UsedRange.Columns(1).SpecialCells(xlCellTypeBlanks)
For Each Acell In srchRng
If Application.WorksheetFunction.CountA(Acell.EntireRow) = 0 Then
firstBlankRow = Acell.row
Exit For
End If
Next
Else
If Application.WorksheetFunction.CountA(Cells(.Rows.Count, 1).EntireRow) = 0 Then
MsgBox "Please start a new sheet"
Else
firstBlankRow = .UsedRange.SpecialCells(xlCellTypeBlanks).row + 1
End If
End If
you are trying to find the first blank row, so that you can insert a new record.
If so, I suggest you replace that code with:
If IsEmpty(.Cells(.Rows.Count, 1)) Then
firstBlankRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
Else
MsgBox "Please start a new sheet"
Exit Sub
End If
That code will look for the last non-empty cell in column A and set the firstBlankRow variable to point to the row after it.
If your records sometimes have an empty value in column A, but you have another column that can be guaranteed to always have a value, just change the above code to refer to that column instead of to column 1. E.g. (assuming column D is always populated):
If IsEmpty(.Cells(.Rows.Count, "D")) Then
firstBlankRow = .Cells(.Rows.Count, "D").End(xlUp).Row + 1
Else
MsgBox "Please start a new sheet"
Exit Sub
End If
If you have records where no column is guaranteed to be non-empty, perhaps this code will work:
firstBlankRow = .Rows.Count + 1
If IsEmpty(.Cells(.Rows.Count, "A")) Then
For firstBlankRow = .Cells(.Rows.Count, "A").End(xlUp).Row + 1 To .Rows.Count
If Application.WorksheetFunction.CountA(.Rows(firstBlankRow)) = 0 Then
Exit For
End If
Next
End If
If firstBlankRow = .Rows.Count + 1 Then
MsgBox "Please start a new sheet"
Exit Sub
End If