0

First I opened this question: Check merged cell and compare adjacent to set unique value from compared cells values. Same scenario, Key value at column 6 and value at column 31 but now requirements have changed.

Now I need to search every cell in column 6 and for each occurrence of this search, copy the the value (column 25) from the first occurrence to the others. I mean, if I have five results of searching "KEY_VALUE", I need to copy the value in column 25 associated with the first result of the search to the others results in their correspondent cells in column 25.

Problem is, when I run my code I get run time error 91: object variable or with block variable not set even when I do have a With block.

I was reading Object variable or with block not set - but in my case, I'm trying to assign a string variable with the result of the search not a range. Here's my code:

Sub CopyUUID()

Dim lRow As Long
Dim rng As Range
Dim searchResult As Range
Dim ws As Worksheet
Dim strSearch As String
Dim uuid As Variant
Set ws = Sheets(ActiveSheet.Name)

With ws
    lRow = .Range("F" & .Rows.count).End(xlUp).row
    Set rng = .Range(.Cells(3, 6), .Cells(lRow, 6))
    For Each cellchecked In rng.Cells
        If Not IsEmpty(cellchecked.Value) Or Not cellchecked.Value = "" Then
            'strSearch = cellchecked.Value
            Set searchResult = rng.Find(What:=cellchecked.Value, LookIn:=xlValues, _
                LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
                    MatchCase:=False, SearchFormat:=False)
            uuid = searchResult.Offset(0, 25).Value 'Gives error "run time error 91: object variable or with block variable not set"
            Do
                Set searchResult = rng.FindNext(After:=searchResult)
                If Not searchResult Is Nothing Then
                    searResult.Offset(0, 25).Value = uuid
                Else
                    Exit Do
                End If
            Loop
        Else
            'If cell is blank, skips execution as no continue exists in VBA
        End If
    Next cellchecked
End With
ExitProgram:
  Exit Sub
End Sub

What could be the problem?

Community
  • 1
  • 1
Edgar Sampere
  • 263
  • 4
  • 24
  • I cannot find an exit strategy on the `.FindNext`. Typically the original address would get checked to see if it has come full circle. You also see to keep looking up the duplicates after you have set a new value in column AE. –  Sep 10 '15 at 22:09
  • Is `searResult` a typo or is that in the code? –  Sep 10 '15 at 22:27
  • @Jeeped it's a typo, I completed that part but not tested it because it crashes before – Edgar Sampere Sep 10 '15 at 23:11

2 Answers2

1

You are only going to want to walk through a unique set of the values and some exit strategy on the Range.FindNext method should be implemented or it may go into an infinte loop.

Sub CopyUUID()

    Dim lRow As Long
    Dim chk As Range, rng As Range
    Dim rslt As Range, addr As String
    Dim ws As Worksheet
    Dim key As Variant, dKEYs As Object

    Set ws = Sheets(ActiveSheet.Name)
    Set dKEYs = CreateObject("Scripting.Dictionary")

    With ws
        lRow = .Range("F" & .Rows.Count).End(xlUp).Row
        Set rng = .Range(.Cells(3, 6), .Cells(lRow, 6))
        For Each chk In rng.Cells
            If CBool(Len(chk.Value2)) And Not dKEYs.exists(chk.Value2) Then
                dKEYs.Add key:=chk.Value2, Item:=chk.Offset(0, 25).Value
            End If
        Next chk
        For Each key In dKEYs
            Set rslt = rng.Find(What:=key, after:=rng(rng.Cells.Count), LookIn:=xlValues, _
                LookAt:=xlWhole, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
            addr = rslt.Address
            Do
                Set rslt = rng.FindNext(after:=rslt)
                If rslt.Address <> addr Then
                    rslt.Offset(0, 25) = dKEYs.Item(key)
                Else
                    Exit Do
                End If
            Loop
        Next key
    End With
ExitProgram:
    Exit Sub
End Sub

The dictionary object maintains a unique list of the first occurrence of each value in column F and the associated UUID value from column AE. Each will always be found at least once so even On Error Resume Next can be discarded (never a bad thing!).

To summarize, the above deals with three issues I found with your code.

  1. Corrects a misspelling on the var searchResult. It was used as searResult in at least one place.
  2. There is now an exit strategy to get out of the .FindNext once all the additional entries have been found and it loops back to the original.
  3. Each entry in column F is only run through once with the substitution in column AE being the value from the first occurrence. The original code would run through every entry in the column so it was performing the Range.Find / Range.FindNext method on the duplcaited values. This is not so much an error as simply an inefficiency but still best if avoided.
  • I'm out of the office but I'm checking this tomorrow – Edgar Sampere Sep 10 '15 at 23:20
  • Ok, now I'm checking this solution more calmly than before and I think it could be more efficient but going to test both your solutions and @Siddharth Rout one's. I just have one question though...Within the `Do...Loop` what does `If rslt.Address <> addr Then rslt.Offset(0, 25) = dKEYs.Item(key)` does exactly? As `dKEYs.Item(key)` is the associated value of the actual search ocurrence already saved in the dictionary, right? So it doesn't need to look for it, just get and set it? – Edgar Sampere Sep 11 '15 at 14:32
  • I tried running your code but I get same error 91 as before in this line: `If rslt.Address <> addr Then` – Edgar Sampere Sep 11 '15 at 14:39
  • Tried commenting Loop but now I get a _Type Mismatch_ Error on the Find method – Edgar Sampere Sep 11 '15 at 15:24
1

You are getting that error ("run time error 91: object variable or with block variable not set") because the code didn't find a match

Hence it is always advisable to check if a match has been found or not. Can you please check which message box do you see when you make the below change?

Set searchResult = Rng.Find(What:=cellchecked.Value, LookIn:=xlValues, _
                   LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
                   MatchCase:=False, SearchFormat:=False)

If searchResult Is Nothing Then
    Msgbox "No Match Found"
Else
    Msgbox "Match Found"

    uuid = searchResult.Offset(0, 25).Value
    '
    '~~> Rest of the code
    '
End If

I would recommend seeing This

Siddharth Rout
  • 147,039
  • 17
  • 206
  • 250
  • But doesn't it *have* to find a match, even if that match is itself? –  Sep 10 '15 at 22:43
  • 1
    `uuid = searchResult.Offset(0, 25).Value` is the line which is giving the error... – Siddharth Rout Sep 10 '15 at 22:51
  • wadr, if it *has* to find a match and it is not then error controlling out of the situation is not an ideal method beyond identifying that there is a problem. –  Sep 10 '15 at 22:54
  • True but I need to check if the user is actually getting that `Msgbox "No Match Found"` Before I look into other aspects. – Siddharth Rout Sep 10 '15 at 22:56
  • I have a feeling that OP may have misspelled the word `searchResult` in that offending line in the actual code... Lets see what OP has to say. – Siddharth Rout Sep 10 '15 at 22:59
  • Or Maybe OP marked the wrong line? He must have been talking about `searResult.Offset(0, 25).Value = uuid`? And then what you suggested in the comment would apply... i.e misspelled word – Siddharth Rout Sep 10 '15 at 23:05
  • This could take a while if he corrects the spelling and then immediately launches the code into an infinite loop... :D. –  Sep 10 '15 at 23:09
  • I think you should include the two comments which are below OP's question in your answer... – Siddharth Rout Sep 10 '15 at 23:11
  • I didn't marked any wrong line. The one giving the error is this one: `uuid = searchResult.Offset(0, 25).Value`. The code between the `Do...Loop` is untested. I just put it there in an attempt to clarify what I'm trying to achieve. If I delete it, and also remove the line I marked, the search works well. I tried it previously giving it an arbitrary cell from where to take a value and works fine. – Edgar Sampere Sep 10 '15 at 23:24
  • Did you try the suggestion that I gave? Can you try that and tell me which message box do you see @Kronos – Siddharth Rout Sep 10 '15 at 23:25
  • I also tried the loop before attempting to set the uuid variable and it doesn't goes into a infinite one. Sorry, I cannot test till tomorrow as I'm not in the office right now. I was in a hurry when I asked the question cause I was already leaving – Edgar Sampere Sep 10 '15 at 23:26
  • @Kronos: Ok, Test and post back when you can :) – Siddharth Rout Sep 10 '15 at 23:27
  • @SiddharthRout Maybe it's a coincidence lol, but I was following this post I thinks is yours[FInd and FindNext](http://stackoverflow.com) . I tried my code as per the section 3 method and find an arbitrary cell, eg .Find(What:=Range("F237").Value....) worked find and gave results – Edgar Sampere Sep 10 '15 at 23:30
  • @Kronos: Then you missed the `Set bCell = aCell` in the `Do Loop` :D And hence your code (once it crosses the initial error) will enter an infinite loop like jeeped mentioned – Siddharth Rout Sep 10 '15 at 23:31
  • But why does it enter an infinite loop? `Set bCell = aCell` is used in order to compare addresses so no value is checked twice and then it exist the loop, right? But, doesn't the find method searches for the next coincidence when the `FindNext` method is called? I think I'm misunderstanding how Find works – Edgar Sampere Sep 10 '15 at 23:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/89393/discussion-between-siddharth-rout-and-kronos). – Siddharth Rout Sep 11 '15 at 14:20