.find finding empty cell - vba

I have a VBA code that searches for a value in another workbook, in all sheets of it, and then writes yes or no in the source file. I use the .find argument inside a loop so it searches in all sheets, and this is inside another loop so it searches for multiple values. The searched value is set as a variable. Turns out that when I went to look in a sample if it was doing it right, sometimes it returns the address of an empty cell, for example: the searched value is 8 and it says that it found the value but when I look at the address of it, it is an empty cell, so in reality the find didn't really work.
Also, I set a variable using a value from the source file that needs to be the same value of a cell offset from the result, and if it is not, I made the code continue searching. When it finds this empty cells, it stops, I don't know why...
The code is something like this, I left some parts of it that are not useful.
dim NFE as range
dim searchedvalue as range
dim validation as range
dim sh as worksheet, wb as workbook
set searchedvalue = thisworkbook.worksheets (name).range
set validation = thisworkbook.worksheets (name).range
for each sh in wb.worksheets
set nfe = Workbooks(wbname).Sheets(sh.Name).Columns([column]).Find(searchedvalue, LookIn:=xlValues, lookat:=xlWhole)
if nfe.offset ().value = validation then
exit for
thisworkbook.range().value = "yes"
else
thisworkbook.range ().value = "no"
end if
next sh
What is wrong?

I discovered the issue. My code was missing a thisworkbook.sheets string when defining searchedvalue, so when it would set it, it would get an empty cell and that would give me the wrong result. Works fine now, thank you all for the help.

Related

run time error 1004 application defined or object defined error - looping over same range in different worksheets

Could you please help me in solving the following issue:
Sub PBLSearch()
Dim PBLRng As Range
Dim PBL As Range
Dim SearchRng As Range
Dim SourceWsNr As Integer
For SourceWsNr = 1 To 2
Debug.Print Workbooks("Book1.xlsx").Sheets(SourceWsNr).Name
Set PBLRng = Workbooks("Book1.xlsx").Sheets(SourceWsNr).Range(Range("A1"), Range("A1").End(xlDown))
For Each PBL In PBLRng.Cells
Debug.Print PBL.Value
Next PBL
Next SourceWsNr
End Sub
The code works fine when the SourceWsNr equals 1, but as soon as this changes to 2, i get the error mentioned in the subject.
Is it because i re-set the PBLRng variable? I couldn't find any solution to this problem...
Thank you very much in advance.
Best Regards,
S. Sz.
The problem is the line
Workbooks("Book1.xlsx").Sheets(SourceWsNr).Range(Range("A1"), Range("A1").End(xlDown))
The Range("A1") and Range("A1").End(xlDown) are referencing the cells on the active worksheet which is why it fails on the second sheet (the arguments for the range method of a sheet have to be on the same sheet). You have to specify the sheet each time when calling Range This should do it:
With ActiveWorkbook.Sheets(SourceWsNr)
Set PBLRng = .Range("A1", .Range("A1").End(xlDown))
End With
Edit: you might also consider using another way to find the last row, like .Cells(.Rows.count,1).End(xlUp). It depends on your specific needs though.

Copying Data from External workbook based on headers not in order to another workbook

I hope this is the right place to ask this question as I am on the verge of going crazy. I am so rusty and I have zero experience with VBA (only with C++, java)
The problem:
I am trying to copy data from one workbook to another.
Lets say I have a workbook (called DATA) with several worksheets filled with data. Each column of data has a unique heading (all headings on the same row).
On the other hand I have another workbook (called REPORT) with one worksheet that contains only the heading of the data (in one row). They are not in the same order as in DATA workbook. For example I have 3 headings in REPORT worksheet that can be found in different worksheets in DATA workbook.
I need to loop through all the worksheets in the DATA workbook and copy paste the whole column to the REPORT worksheet when the same heading is found.
This image may help to understand. Explanation
Thanks ALOT for your help in advance. I have searched alot for this code but found similar stuff but didnt manage to understand any .
First attempt at doing it, but getting an error of Run-time error '1004'.
Any help?
Dim MyFile As String
Dim ws As Worksheet
''Workbook that contains one worksheet with all the headings ONLY NO DATA
Dim TargetWS As Worksheet
Set TargetWS = ActiveSheet
Dim TargetHeader As Range
''Location of Headers I want to search for in source file
Set TargetHeader = TargetWS.Range("A1:G")
''Source workbook that contains multiple sheets with data and headings _
not in same order as target file
Dim SourceWB As Workbook
Set SourceWB = Workbooks("Source.xlsx")
Dim SourceHeaderRow As Integer: SourceHeaderRow = 1
Dim SourceCell As Range
''Stores the col of the found value and the last row of data in that col
Dim RealLastRow As Long
Dim SourceCol As Integer
''Looping through all worksheets in source file, looking for the heading I want _
then copying that whole column to the target file I have
For Each ws In SourceWB.Sheets
ws.Activate
For Each Cell In TargetHeader
If Cell.Value <> "" Then
Set SourceCell = Rows(SourceHeaderRow).Find _
(Cell.Value, LookIn:=xlValues, LookAt:=xlWhole)
If Not SourceCell Is Nothing Then
SourceCol = SourceCell.Column
RealLastRow = Columns(SourceCol).Find("*", LookIn:=xlValues, _
SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
If RealLastRow > SourceHeaderRow Then
Range(Cells(SourceHeaderRow + 1, SourceCol), Cells(RealLastRow, _
SourceCol)).Copy
TargetWS.Cells(2, Cell.Column).PasteSpecial xlPasteValues
End If
End If
End If
Next
Next
Your question didn't specify what part of the problem you're actually stuck on, so I'll assume you don't know how to start. Note that nobody on here is going to provide you with the full working solution to your problem - that's upto you to figure out.
A few tips to get you to start working:
The first question you're going to ask yourself with problems involving multiple workbooks is typically going to be which workbook am i going to attach my macro to?
In your case, the REPORT Workbook looks like a saner option, since you probably want someone to be clicking on something in the report in order to generate it. You could also argue the other way around though.
Once you have chosen where to put your VBA, you have to establish a reference to the other workbook.
You either have to load the other Excel file from disk using Workbooks.Open, or have both Workbooks be open at the same time in your Excel Instance, which I'd recommend for you because it's easier. In this case simply establish the reference using the Workbooks object.
Dim exampleRefToDATA As Workbook: Set exampleRefToDATA = Workbooks("data.xlsx") ' or index
Then, cycle through each Worksheet
using something like For Each ws As WorkSheet In exampleRefToDATA.WorkSheets as your For Loop
In that Loop, loop through the first column using something like
For Each allName As Range In ws.Range(... for you to figure out ...)
In this Loop, you'll have to look if that name is in your REPORTS sheet by doing another loop like
For Each thisName As Range in Range(... seriously, there's enough on stackoverflow on how to properly iterate over the used range of a row ...)
Note how this Range() call is Equivalent to ActiveWorkbook.ActiveWorkSheet.Range, which is your Reports sheet.
Then just check for equality and copy the row over if necessary. Again, copying a row has also been covered here before.
Hope this was helpful for you.

range names not in name manager

Running VBA code allowed me to detect that applying a filter in a sheet creates a range name that does NOT appear in the name manager (the range name either just associates to the headers or the whole table). Is there any way of knowing why this happens and/or a way of preventing it? Is it just an Excel glitch?
the part of the vba code that causes the error I tried to run was the following:
For Each Rng In ActiveWorkbook.Names
Set Rng2 = Range(Rng)
If Not Intersect(Rng2, Range(rng1.Offset(1, 0), rng1.End(xlDown)).EntireRow) Is Nothing Then ActiveWorkbook.Names(Rng.Name).Delete
Next Rng
When I was debugging, I noticed that my Rng (which is a name object, by the way) points towards a range I never created (and I know this because the sheet that it's in has no other range names and I never put any in it)
I used this vba code to verify that the name existed in this sheet:
Sub test()
Dim Rng As Name
For Each Rng In Sheets("WindHail Zone 2").Names
'ActiveWorkbook.Names(Rng.Name).Delete
MsgBox Rng
Next Rng
End Sub
I removed the comment block from the first line of the for loop to the second line to delete it. I removed the filter on that tab and reput it on, only to come to the same issue.
Thanks!
Not so clear to me what your're trying to achieve but as long as "hidden" names and range intersection are involved you must take into account what follows:
filtering does create hidden "names"
but all of them ends with the string "_FilterDatabase"
range intersection wold return an error if applied to ranges not belonging to the same sheet
so here what you should try
For Each Rng In ActiveWorkbook.Names
Set rng2 = Range(Rng)
If rng2.Parent.Name = rng1.Parent.Name And InStr(Rng.Name, "_FilterDatabase") = 0 Then 'the first check is for ranges belonging to the same worksheet and the second is for rng2 not deriving from any filtering
' now you can safely "Intersect"
If Not Intersect(rng2, Range(rng1.Offset(1, 0), rng1.End(xlDown)).EntireRow) Is Nothing Then ActiveWorkbook.Names(Rng.Name).Delete
End If
Next Rng

Excel vba code using ThisWorkbook.Sheets(1).Range not working, but Sheet1.Range works fine. Why?

When I use wb.Sheets(1).Range("A:A").Find(What:=ID, LookIn:=xlValues) I get error 91 - Object Variable or With Block not set. When I use Sheet1.Range("A:A").Find(What:=ID, LookIn:=xlValues) it returns correct value.
Why the difference?
Is there a flowchart I can reference or any simple information available to understand which sub-commands (I don't know the proper word) work with ThisWorkbook and Sheets(#) versus Sheet#.Whatever?
I am hesitant to use Sheet("Name") because names might change later. I am using ThisWorkbook rather than ActiveWorkbook to keep all code attached to the appropriate workbook.
Anything you can offer for simple reference info would be great. I have researched, but still don't understand which sub-commands work with which parent commands. (Again, probably wrong terminology).
Private Sub lstExample_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Dim wb As Workbook
Dim I As Integer
Dim ID As String
Dim findValue As Range
Set wb = ThisWorkbook
'Get the values of the selected row in listbox on doubleclick
For I = 0 To lstExample.ListCount - 1
If lstExample.Selected(I) = True Then
'Set listbox column 1 as ID value to find
ID = lstExample.List(I, 1)
End If
Next I
'Match ID (column A) on Sheet1
Set findValue = wb.Sheets(1).Range("A:A").Find(What:=ID, LookIn:=xlValues)
MsgBox findValue
End Sub
There is no difference between the properties of Sheets(1) and Sheet1 as long as both are the same object - Worksheet Object in your case.
You're getting that error because findValue Is Nothing. That is, it couldn't find the ID in the column. When using the Find method, it's best to specify every argument. Find remembers the last find you did, even if you did it in the UI and your using Find in VBA.
For instance, if you check MatchCase in the UI when you do a Find. Then you do a Find in VBA and don't specify the MatchCase property, it will use whatever you set the last time.

Referring to Dynamic Named Ranges in VBA

I'm having troubling referring to a Dynamic Name Range in VBA.
My ranges are defined as
=OFFSET(Sheet!$B$2,0,0,COUNTA(Sheet!$B:$B)-1,1)
My code should search one range for all entries in another range, the intention being that any missing entries will be added. So far I have
Sub UpdateSummary()
Dim Cell As Range
Dim rngF As Range
Set rngF = Nothing
' Step through each cell in data range
For Each Cell In Worksheets("Aspect").Range("A_Date")
' search Summary range for current cell value
Set rngF = Worksheets("Summary").Range("Sum_Date").Find(Cell.Value) // Does not work
If rngF Is Nothing Then
' Add date to Summary
End If
Set rngF = Nothing
Next Cell
End Sub
The For loop seems to work ok. However, using the .Find method is giving me an error message.
Application-defined or object-defined error
It does work if I replace the named range with a specific range ($B$2:$B$5000), so it seems to be down to how the named range is being passed.
Any ideas would be appreciated.
Thanks.
The error is almost definitely because Excel can't find a named range Sum_Date that refers to a range on a worksheet named Summary. The most common causes are
Sum_Date refers to a sheet other than Summary. Check the RefersTo property of Sum_Date and make sure nothing is misspelled.
There is not a named range Sum_Date, that is, it's misspelled in the VBA code. Check the spelling of the named range in the Name Manager.
There is an error in the RefersTo formula of Sum_Date. It sounds like you already verified that this isn't the case.
I've had the a similar if not the same problem & here's how I solved it:
I first realized that the method I used to create my named range, using the Name Manager, my named range had a scope of Workbook. This is important because, it doesn't belong to the worksheet, & therefore will not be found there.
So, Worksheets("Summary").Range("Sum_Date") would not work for me.
Since my range belonged to the workbook, the way I was able to find is to use ActiveWorkbook.Names("Sum_Date")
For me I used it to remove the formula from named range that I am using in many places. The huge advantage is that named range is updated only once instead of the formula being called for every cell location that ranged is called. Huge time delay difference!
Public last_Selection As String
Private Sub Worksheet_Change(ByVal Target As Range)
'excel data change detection
If Range(last_Selection).Column = 2 Then
'Disable events, so this only executes once
Application.EnableEvents = False
'This can be done with a complex formula in a cell,
'but this is easily understood
Range("B1").End(xlDown).Select
ActiveWorkbook.Names("last_Entry").Value = ActiveCell.Row
'Re-enable so this routine will execute on the next change
Application.EnableEvents = True
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
'constantly store the last cell to know which one was previously edited
last_Selection = Target.Address
End Sub
I know this is a very old thread, but I had the same issue today and I was looking for solution for quite a long time. So maybe this will help someone.
The named "range" defined by the =OFFSET(...) formula is actually a named FORMULA, so in VBA you have to evaluate it first to get the range. E.g.:
Set rgNamedRange = Worksheets("Summary").Evaluate("Sum_Date")
Credits to a guy named "shg" from mrexcel.com, who got me on right track. :)
I have been experimenting with this for a few days and eventually I came up with the following. It may not be the most efficient but it did work for me!
The named range of "OhDear" was set up in the normal way
Dim vItem As Variant
Set vItem = Names("OhDear")
Debug.Print vItem.Name
Worth a try don't you think!
This does not work if instead of using a variant you use something like: Dim Nm as Name: Set Nm = Names("OhDear"). Any variations using 'Nm' failed!!!