A really basic question I m afraid:
How do I use a value as any part of an array?
Sub test()
Dim x As Variant
x = Array(1, 2, 3, 8, 9, 10, 1585)
If InStr(Cells(1,1).Value, x) Then
MsgBox "OK"
End If
End Sub
In this code I am trying to check if the cell contains any value from the array
You can use Match and check whether a number is returned (which means the value is found in the array).
Sub test()
Dim x As Variant
x = Array(1, 2, 3, 8, 9, 10, 1585)
If IsNumeric(Application.Match(Cells(1, 1).Value, x, 0)) Then
MsgBox "OK"
End If
End Sub
Alternatively, if it doesn't have to be an array one could simply use a string as such:
Sub test()
Dim arrayString As String
arrayString = "1, 2, 3, 8, 9, 10, 1585"
If InStr(1, arrayString, Cells(1, 1), vbTextCompare) > 0 Then
MsgBox "OK"
End If
End Sub
Related
I have a spreadsheet like this, and I would like to have a function that returns the list of row numbers non-empty cells in column B. In this case, it should return "2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 22, 23, 25, 26)
How do I do this in VBA?
Function GetEmptyCount()
Dim arr(), x&, cell
With Range("B1:B" & Cells(Rows.Count - 1, "B").End(xlUp).Row)
For Each cell In .SpecialCells(xlCellTypeBlanks).Cells
x = x + 1
ReDim Preserve arr(1 To x)
arr(x) = cell.Row
Next
End With
GetEmptyCount = arr
End Function
Sub Test()
Dim x, c
x = GetEmptyCount()
For Each c In x: MsgBox c: Next
End Sub
You can check the length of the cell value something like
IF(Length(Cell) > 0 THEN
// Include the row
ELSE
// skip the row
This is my logic
arr(1,2,3,4,5,6,7,8,9)
arr1(3,4,5)
arr2(2,0)
arr3(6,7,45,8,3)
(arr,arr1)....-> True
(arr,arr2)....-> False
(arr,arr3)....-> False
using word VBA, how to find that the value in arr2 must present in arr? if one of the value in arr2 didn't match with arr then it should come out of the particular array(Example: arr2(0,9)) and then start checking with next array(arr3). I want to compare one arr with multiple arrays**(arr1,arr2,arr3)**. I tried the below mentioned logic.
For j = 1 To UBound(arr1)
For k = 1 To UBound(arr2)
If arr1(j) = arr2(k) Then
\\.......
End If
Next
Next
Is this what you had in mind?
Sub TestMatched()
Dim Arr() As Variant
Arr = Array(33, 4, 15)
Debug.Print Matched(Arr)
End Sub
Private Function Matched(Arr2() As Variant) As Long
Dim Arr1() As Variant
Dim i As Long
Arr1 = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
For i = LBound(Arr2) To UBound(Arr2)
If Not IsError(Application.Match(Arr2(i), Arr1, 0)) Then
Matched = Arr2(i)
Exit For
End If
Next i
End Function
I have the below line that is receiving a "Object doesn't support the property or method error, but i am not seeing any issues.
Dim compliance As Worksheet
Dim report As Worksheet
Dim completeList As Worksheet
Sub getcompliance()
Dim i As Long
Dim n As Long
Dim Source As String
Set compliance = ActiveWorkbook.Worksheets("Compliance")
Set report = ActiveWorkbook.Worksheets("Report")
For i = 3 To report.UsedRange.Rows.Count
For n = 2 To compliance.UsedRange.Rows.Count
report(i, 19) = Application.WorksheetFunction.VLookup(report("i, 3"), compliance("A1:AC2400"), 29, False)
Next n
Next i
End Sub
Your line saying
report(i, 19) = Application.WorksheetFunction.VLookup(report("i, 3"), compliance("A1:AC2400"), 29, False)
should probably say
report.Cells(i, 19) = Application.WorksheetFunction.VLookup(report.Cells(i, 3), compliance.Range("A1:AC2400"), 29, False)
but, if so, why are you doing that in a For n loop?
Perhaps you mean your code to be:
Dim compliance As Worksheet
Dim report As Worksheet
Dim completeList As Worksheet
Sub getcompliance()
Dim i As Long
Set compliance = ActiveWorkbook.Worksheets("Compliance")
Set report = ActiveWorkbook.Worksheets("Report")
For i = 3 To report.UsedRange.Rows.Count
report.Cells(i, 19) = Application.WorksheetFunction.VLookup(report.Cells(i, 3), compliance.Range("A1:AC" & compliance.UsedRange.Rows.Count), 29, False)
'Or, simply using the full columns:
'report.Cells(i, 19) = Application.WorksheetFunction.VLookup(report.Cells(i, 3), compliance.Range("A:AC"), 29, False)
Next i
End Sub
' vvvvv vvvvvvvvvvvvv
report.Cells(i, 19) = WorksheetFunction.VLookup(report.Cells(i, 3), compliance.Range("A1:AC2400"), 29, False)
' ^^^^^^
I want to print a list of eight numbers to the worksheet, but only if they are all unique.
An ideal code would be something along the lines of
If a <> b <> c Then
Rather than
If a <> b And a <> c And b <> c Then
Is this possible, given that the values are called from an array using the code following:
Cells(2, 8) = numarr(i)
Cells(2, 9) = numarr(j)
Cells(2, 10) = numarr(k)
Cells(2, 11) = numarr(l)
Cells(3, 8) = numarr(m)
Cells(3, 9) = numarr(n)
Cells(3, 10) = numarr(o)
Cells(3, 11) = numarr(p)
Thanks!
The quick and dirty way to do this is with a Dictionary, which requires a unique key. Just keep dumping numbers in from your array until you hit one that's already in the Dictionary. Just make it into a function and pass your array to it:
Private Function AllUnique(incoming As Variant) As Boolean
If Not IsArray(incoming) Then Err.Raise 13
Dim candidates As Scripting.Dictionary
Set candidates = New Scripting.Dictionary
Dim index As Long
For index = LBound(incoming) To UBound(incoming)
If candidates.Exists(incoming(index)) Then Exit Function
candidates.Add incoming(index), index
Next index
AllUnique = True
End Function
I am going to throw in the direct comparison method:
Public Function AreEqual(ParamArray values() As Variant) As Boolean
Dim i As Long, j As Long, N As Long
Dim x As Double
N = UBound(values) + 1
For i = 1 To N - 1
x = values(i - 1)
For j = i + 1 To N
If values(j - 1) <> x Then
AreEqual = False
Exit Function
End If
Next j
Next i
AreEqual = True
End Function
To be used as
If AreEqual(num1,num2,num3,...) then
...
End If
As a slight variation of the Collection answer given above by #ja72, this function should be able to take any set of simple values of any type and determine if they're all identical or not. (The exception to this being the fourth test line for Strings, in which the Collection key is not case-sensitive.) I'm taking advantage of the hashing algorithm for adding keys to a Collection to ensure unique-ness.
Option Explicit
Sub Test()
Debug.Print AllValuesIdentical(14, 14, 14, 14, 14, 14, 14, 14, 14) 'true
Debug.Print AllValuesIdentical(5, 5, 5, 5, 5, 3, 5, 5) 'false
Debug.Print AllValuesIdentical("go", "go", "go", "go") 'true
Debug.Print AllValuesIdentical("go", "go", "go", "GO") 'also true
Debug.Print AllValuesIdentical(283.14, 283.14, 283.14) 'true
End Sub
Function AllValuesIdentical(ParamArray vals() As Variant) As Boolean
Dim uniqueCheck As Collection
Dim val As Variant
Set uniqueCheck = New Collection
On Error Resume Next
For Each val In vals
uniqueCheck.Add val, CStr(val)
Next val
If uniqueCheck.Count = 1 Then
AllValuesIdentical = True
Else
AllValuesIdentical = False
End If
On Error GoTo 0
Set uniqueCheck = Nothing
End Function
In cells A1:A66000 I have the numbers 1, 2, ... 66000.
Sub addData()
Application.ScreenUpdating = False
Cells(1, 1) = 1
Cells(2, 1).Formula = "=A1+1"
Range(Range("A66000"), Range("A66000").End(xlUp)).Select
Selection.FillDown
Application.ScreenUpdating = True
End Sub
The following code loads the data into an array and finds the index of the number 2. It returns the correct result, 2.
Sub test()
Dim arr As Variant
arr = ArrayFromRange(Range("A1:A65536"))
MsgBox Application.WorksheetFunction.Match(2, Application.Index(arr, 0, 1), 0)
End Sub
However, changing the array size causes a Type Mismatch error due to the Index function.
Sub test()
Dim arr As Variant
arr = ArrayFromRange(Range("A1:A65537"))
MsgBox Application.WorksheetFunction.Match(2, Application.Index(arr, 0, 1), 0)
End Sub
How can I get around this? I'm using Excel 2007.
EDIT: I forgot to include this handy function that I'm calling
Function ArrayFromRange(rg As Range) As Variant()
'==============================================================================================
'Returns an array from a given range
' BG Feb 2013
'==============================================================================================
If (rg.Cells.Count = 1) Then
Dim arr(1 To 1, 1 To 1) As Variant
arr(1, 1) = rg.Value
ArrayFromRange = arr
Else
ArrayFromRange = rg ' Arr is now an allocated array
End If
End Function
Since there's a hard limit on the size of an array you can pass to WorksheetFunction.xxxx in VBA, you can instead leave the data on the sheet, and query it directly. This has the advantage of being much faster...
Sub test()
Dim arr As Variant, v, t, i As Long
Dim rng As Range
Set rng = ActiveSheet.Range("A1:A65536")
arr = rng.Value
'array-based approach
t = Timer
For i = 1 To 100
v = Application.WorksheetFunction.Match(i, Application.Index(arr, 0, 1), 0)
If i <= 5 Then Debug.Print v
Next i
Debug.Print Timer - t '>> 1.55 sec
'query worksheet directly
t = Timer
For i = 1 To 100
v = rng.Parent.Evaluate("MATCH(" & i & ", INDEX(" & rng.Address() & ", 0, 1), 0)")
If i < 5 Then Debug.Print v
Next i
Debug.Print Timer - t '>> 0.008 sec
End Sub