Match Function in Specific Column Excel VBA - vba

I'm trying to write a program in VBA for Excel 2011 that can search a column (which column that is is determined by another variable) for the number 1 so that it knows where to start an iteration.
Say that the number of the column is given by colnumvar. The only way I can think of is the Match function, which led me to write the following:
Dim rowvar As Integer
rowvar = WorksheetFunction.Match(1,Range(Cells(1,colnumvar),Cells(1000,colnumvar)),0)
This gave me an error, however. After playing around with it some more, I realized that it must not accept the Cells([row],[col]) way of doing it, but rather wants something like Range("A1:A100"). Unfortunately, I can't do it that way, since the program is figuring out what column to look in. Any help for figuring out how to get past this would be greatly appreciated!

What you mean to do is better served with Range.Find.
Dim rngtrg As Range, rngsrc As Range
Dim ws As Worksheet
Set ws = ActiveSheet
Set rngsrc = ws.Range(ws.Cells(1,colnumvar),ws.Cells(1000,colnumvar))
Set rngtrg = rngsrc.Find(1,...)
rowvar = rngtrg.Row

this easy function retreive the positoin of that you find
Function rowvar(ByRef c As Integer) As Integer
Dim keySrc As Integer
keySrc = 22 'wath you want to find
rowvar = WorksheetFunction.Match(keySrc, Range(Cells(1, c), Cells(1000, c)), 0)
End Function
use with rowvar(x)

Related

Error Finding multiple date ranges in Excel List

Getting an object variable or with variable not set error. All i'm trying to do is position myself to be able to analyze data from the newStartDate to the newEndDate and compare it to the data in between oldStartDate and oldEndDate. Stuck on the finding the addresses of the dates in the "Master List" Unsure why i'm struggling with this it's a simple task, but I can't seem to solve the error. Any thoughts? I have read the other posts similar to this and can't seem to figure out what i'm doing differently. Thanks in advance Code below:
Note: 1/1/14 is the date set in the range of newStartDate. This date does not exist as business was not conducted until the second. I had found in a post that that the "Set newStartDateFinder" line at the bottom would find the next closest date if the exact date was not found..i'm beginning to think that's not the case since when I attempt to run the debugger it appears to be empty.
Option Explicit
Sub Gather_Calculate_Performance()
'Variable declaration
Dim EBM As Workbook
Dim masterList, controlOut As Worksheet
Dim newStartDate As Range
Dim newEndDate As Range
Dim oldStartDate As Range
Dim oldEndDate As Range
Dim newStartDateFinder As Range
Dim newEndDateFinder As Range
Dim oldStartDateFinder As Range
Dim oldEndDateFinder As Range
'Setting main objects
Set EBM = Workbooks("Monthly Analysis (DEV)")
Set masterList = EBM.Sheets("Master List")
Set controlOut = EBM.Sheets("Control.Output")
'setting main variables
Set newStartDate = controlOut.Range("B" & 5)
Set newEndDate = controlOut.Range("B" & 6)
Set oldStartDate = controlOut.Range("D" & 5)
Set oldEndDate = controlOut.Range("D" & 6)
'Find addresses for dates
Set newStartDateFinder = masterList.Range("A:A").Find(newStartDate, LookIn:=xlValues, LookAt:=xlWhole)
Debug.Print newStartDateFinder.Address
End Sub
Yes, the Find function will look for an exact match, if you set the LookAt argument to xlWhole. (Setting it to xlPart would find matches where the search string exists in part of the cell. So, the Find function won't work in the way you suspected here.
I was thinking you could use a VLOOKUP or MATCH function to find the next closest date to newStartDate but after testing, it didn't work the way I thought it would.
However, this loop while work. If I find a more efficient way, I will update the answer.
'Find addresses for dates
Dim i as Integer
i = 0
Do
Set newStartDateFinder = masterList.Range("A:A").Find(newStartDate.Value +i, LookIn:=xlValues, LookAt:=xlWhole)
i = i + 1
Loop Until Not newStartDateFinder is Nothing
Debug.Print newStartDateFinder.Address

Unique Value Function in Excel

I created the following function using Excel 2010. It seem to work only when i use the function in the same sheet the array was created (sheet2) and if a value is typed in the function e.g.: =KeyExists(1443). I need to use this function in another sheet within the workbook and needs to be a cell reference. Stumped on why its not working.
Option Explicit
Function KeyExists(k)
Dim d As Object
Dim c As Variant
Dim i As Long
Dim lr As Long
Dim msg As String
Set d = CreateObject("Scripting.Dictionary")
lr = WorkSheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Row
c = Range("A2:A" & lr)
For i = 1 To UBound(c, 1)
d(c(i, 1)) = 1
Next i
If d.exists(k) Then
msg = "key exists"
Else
msg = "key does not exist"
End If KeyExists = msg
End Function
'parts of the code derived from:
'hiker95, 07/26/2012
'http://www.mrexcel.com/forum/showthread.php?649576-Extract-unique-values-from-one-column-using-VBA
Change it from Sheet2 to the active sheet:
lr = ActiveWorkbook.ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
If the unique Keys are only in Sheet2 Column A2 and onward... You can create a dynamic named Range and reference it anywhere in the Workbook.
Say you have data:
Create a dynamic named range Keys with =OFFSET(Sheet2!$A$1,1,0,COUNTA(Sheet2!$A:$A)-1,1).
Then say you want to check for values in C4, use formula below:
=IF(ISNUMBER(IFERROR(MATCH(C4,Keys,0),"")),"key exists","key does not exists")
There is no need to use VBA for what you want to achieve your goal. e.g.
I agree with commenters regarding the Dictionary. In my opinion, it would be much easier to do without it. I also think other ways would be vastly quicker, depending on how much data you have.
Example:
Function KeyExists(k As Range) As String
Dim ws As Worksheet
Dim c As Range, i As Long
' Set ws to the worksheet to which k belongs.
' This avoids activeworksheet and also allows for
' qualified references to other sheets if necessary.
ws = k.Worksheet
Set c = ws.Range("A2:A" & ws.Cells(Rows.Count, 1).End(xlUp).Row)
On Error Resume Next
i = Application.WorksheetFunction.Match(k.Value, c, 0)
On Error GoTo 0
If i <> 0 Then
KeyExists = "Key exists"
Else
KeyExists = "Key does not exist"
End If
End Function
Using MATCH will most likely be a lot faster than adding every entry of data into a Dictionary.
A case where you might argue using Dictionary is marginally better, is if you want to make sure the value is unique. But even then, you'd have to use round-about logic to deal with the what-if of encountering duplicate keys and what to do at that point.
Your question does not really specifiy whether or not you need to perform this check or not, or what to do if duplicates are found, so it's hard to advise on it. In any case, if you opt for this method I would recommend creating a separate procedure that declares and builds the dictionary and run it on Worksheet_Open or something like that, leaving you to use a very short function for querying the existence of a key. This circumvents you having to build the dictionary every time the formula runs and will most likely be faster (and require more coding) than my solution.

excel vba moving non-contiguous range selection to an array

In the situation where the user select two non-contiguous column ranges i wrote the following:
Dim count long
Dim points variant
Dim i long
Set user_range = ActiveWindow.RangeSelection
count = user_range.count / 2
ReDim points(1 To count, 1 To 2)
For i = 1 To count
MsgBox "value is" & user_range.Areas.Item(1).Value(i,1)
points(i, 1) = user_range.Areas.Item(1).Value(i,1)
points(i, 2) = user_range.Areas.Item(2).Value(i,1)
Next i
But i get an object error when i try this. Am i indexing Value wrong?
This should work right? Is there an easier way to do this?
Any help is greatly appreciated!
Thanks,
Russ
I'm afraid your code does not compile. First of all, you need to declare your variables correctly. You should also use Option Explicit.
Option Explicit
Dim count As Long
Dim points As Variant
Dim i As Long
Dim user_range As Range
The count and ReDim lines are OK, but you are assuming that the two selections are both the same size. Will that always be the case?
Then I'm not sure what it is you want to do, but I'm guessing you just want to save the values in user_range into points.
You need to adress them a bit different:
points(i, 1) = user_range.Areas(1).Cells(i, 1).Value 'Selection 1
points(i, 2) = user_range.Areas(2).Cells(i, 1).Value 'Selection 2

Trying to find the number of rows in a particular sheet

Update: I figured out my error - the variable sheetRange needed the Sheets("Schedule"). added to it as well
Sorry for the inconvenience.
I have a relatively simple problem in that I am trying to use VBA to find the number of rows in a particular sheet. I am getting a pop up box that just says 400 and am not really sure where my syntax is off.
Sub PhxCheck()
Dim i As Integer, x As Integer, numofRows As Integer
Dim top As Range, bottom As Range, sheetRange As Range
Dim phxContract As String, contractID As String
Set top = Sheets("Schedule").Range("A3")
Set bottom = Sheets("Schedule").Range("A65536").End(xlUp)
Set sheetRange = Range(top, bottom)
numofRows = sheetRange.Rows.Count
Cells(30, 1).Value = numofRows
End Sub
The error happens when I add Sheets("Schedule"). to the top and bottom ranges.
Thanks for your help!
You can simplify your code a lot and avoid using redundant variables which will limit mistakes.
All you need is:
With Sheets("Schedule")
Cells(30, 1).Value = .Range("A3", .Cells(Rows.Count, "A").End(xlUp)).Rows.Count
End With
I understand you solved your problem yourself, but perhaps the above will help you or someone else searching for a similar problem.

Problems with VLOOKUP in VBA

All,
I'm trying to use vlookup in a simple VBA function, but it is continually returning #VALUE!
Here is the code:
Public Function getAreaName(UBR As Integer) As String
Dim result As String
Dim sheet As Worksheet
Set sheet = ActiveWorkbook.Sheets("UBR Report")
' check level 3 then 2 then 4 then 5
result = Application.WorksheetFunction.VLookup(UBR, sheet.Range("UBRLookup"), Application.WorksheetFunction.Column(sheet.Range("UBRLookup[Level 3]")), False)
getAreaName = result
End Function
Any thoughts?
I'm not quite sure what you're trying to do with the "UBRLookup[Level 3]" reference, but as Joseph has pointed out, that's the bit that you're doing wrong.
[ is not a valid character for a named range in Excel.
The column that you're referencing needs to be a numeric value, the offset from the start of the table-array you've defined as your named range.
The below should work, provided the column you want to pull out is the second column in your named range (e.g. what you're referring to as [level 3] is in the second column).
Public Function getAreaName(UBR As Integer) As String
Dim result As String
Dim sheet As Worksheet
Set sheet = ActiveWorkbook.Sheets("UBR Report")
result = Application.WorksheetFunction.VLookup(UBR, sheet.Range("UBRLookup"), 2, False)
getAreaName = result
End Function
Update:
I've had a look at Excel 2007 and from what I can see the column function isn't exposed as an Application.WorksheetFunction.
You can use it on the sheet with =Column(D4), but when trying to autocomplete within the vba editor, the function isn't there. This may be due to a difference in versions, so I'll ignore that for now.
It still definitely seems like you're mis-using the third argument. If you really don't want to use the number reference we need to find out where the function is going wrong.
A few tests along the lines of
Debug.Print Application.WorksheetFunction.Column(D4)
Debug.Print sheet.Range("UBRLookup[Level 3]")
should hopefully help to show you exactly where it's going wrong - I believe that it will object to both of the above, but if it returns some useful information then we may be a step closer to your solution.
Break you function up into more pieces. Then debug it and make sure every piece is set up the way you expect.
Example:
Public Function getAreaName(UBR As Integer) As String
Dim result As String
Dim sheet As Worksheet
Set sheet = ActiveWorkbook.Sheets("UBR Report")
Dim range as Range = sheet.Range("UBRLookup")
Dim column as Column = Application.WorksheetFunction
.Column(sheet.Range("UBRLookup[Level 3]"))
result = Application.WorksheetFunction.VLookup(UBR, range, column, False)
getAreaName = result
End Function
In fact, just by doing that I noticed something weird. You use a range in two different places, but in one place you're looking for UBRLookup, and in another you're looking for UBRLookup[Level 3], is that correct?
I am disturbed by
Dim column as Column =
Application.WorksheetFunction.Column(sheet.Range("UBRLookup[Level 3]"))
You should Dim column as long, I think, and maybe use a variable name that's not to be confused with a property, like lngCol.
This part: sheet.Range("UBRLookup[Level 3]") is suspect as "UBRLookup[Level 3]" is not a valid range name.