Find cell value in another sheet - excel

I have to excel sheet and, using vba, I would like to get a value in one of those, search it in the other one and return a correspondant value in the first sheet.
Given the sheet 1:
I would like to search the string I inserted in A5 in another sheet:
Sheet 2:
Once I found the match (A2 in this case), I would get the 'value' (in D2 in this case) and report it in the cell B5 of the Sheet1.
That's what I tried:
Dim rgFound As Range
Dim defVal As Range
Dim currParam As Range
Dim currParamDict As Range
For Each defVal In Range("B:B")
Set currParam = Cells(Range(defVal).Row, Range(defVal).Column - 1)
If currParam Is Nothing Then
Debug.Print "Name was not found."
End If
Set rgFound = Worksheets("Sheet2").Range("A:A").Find(currParam.value)
If rgFound Is Nothing Then
Debug.Print "Name was not found."
Else
Set currParamDict = Cells(Range(rgFound).Row, Range(rgFound).Column + 3)
defVal.value = currParamDict.value
End If
Next defVal
That's clearly wrong since the compiler gives me an error on Range at the line:
Set currParam = Cells(Range(defVal).Row, Range(defVal).Column - 1)

Try this
Sub x()
Dim rgFound As Range
Dim defVal As Range
Dim currParam As Range
Dim currParamDict As Range
With Worksheets("Sheet1")
For Each defVal In .Range("A2", .Range("A" & Rows.Count).End(xlUp)).Offset(, 1)
Set currParam = defVal.Offset(, -1)
If Len(currParam.Value) > 0 Then
Set rgFound = Worksheets("Sheet2").Range("A:A").Find(currParam.Value)
If rgFound Is Nothing Then
Debug.Print "Name was not found."
Else
Set currParamDict = rgFound.Offset(, 3)
defVal.Value = currParamDict.Value
End If
End If
Next defVal
End With
End Sub

Related

Selecting element from VBA union

I have a task to make a VBA macro based on few sections in .xls file.
I know that in this file it will always be three sections which starts with specific name in example file "Block". But starting row where "Block" is written each time could be different.
Example of .xls file:
enter image description here
My approach had been to search for address of each column containing string "Block"
And later make further code based on knowing there start of each block are.
My code so far:
Public Values
Sub Macro1()
FindAll ("Block")
Debug.Print Values
'
End Sub
Sub FindAll(text)
Dim fnd As String, FirstFound As String
Dim FoundCell As Range, rng As Range
Dim myRange As Range, LastCell As Range
fnd = text
Set myRange = ActiveSheet.UsedRange
Set LastCell = myRange.Cells(myRange.Cells.Count)
Set FoundCell = myRange.Find(what:=fnd, after:=LastCell)
'Test to see if anything was found
If Not FoundCell Is Nothing Then
FirstFound = FoundCell.Address
Else
GoTo NothingFound
End If
Set rng = FoundCell
'Loop until cycled through all unique finds
Do Until FoundCell Is Nothing
'Find next cell with fnd value
Set FoundCell = myRange.FindNext(after:=FoundCell)
'Add found cell to rng range variable
Set rng = Union(rng, FoundCell)
'Test to see if cycled through to first found cell
If FoundCell.Address = FirstFound Then Exit Do
Loop
'Creates global value with all found adresses
Values = rng.Address
Exit Sub
Output Is received as intended:
$A$5,$A$8,$A$1
However I struggle to select element for further coding.
I tried:
Debug.Print Values.Rows.item(1).Adress
Debug.Print Values.Rows.item(1,1).Adress
Debug.Print Values.Rows.item(1)
Debug.Print Values.Rows.item(1,1)
But it yields "Run-time error '424' "
My desired output would be to create three variables containing addresses for these sections.
That
Debug.Print Section_1
Debug.Print Section_2
Debug.Print Section_3
Would yield:
$A$1
$A$5
$A$8
Is there a way to select nth element from union in VBA?
If you want to access the single cells of the range, you can simply loop over it:
Dim cell as Range
For Each cell In rng
Debug.Print cell.Address
Next
Could also be done using an index:
Dim i As Long
For i = 1 To rng.Count
Debug.Print rng(i).Address
Next
Now in your example, you combine single cells using Union. If you combine larger ranges and want to access those ranges, you can use the Areas-Property. However, Excel will optimize the areas, if you do Union(Range("A1"), Range("A2)), you will end up with one area A1:A2.
With ActiveSheet
Set rng = Union(.Range("D5:E16"), .Range("A1:F12"), .Range("X4"))
End With
Dim a As Range
For Each a In rng.Areas
Debug.Print a.Address
Next
For i = 1 to rng.Areas.Count
Debug.Print rng(i).Address
Next
Btw: Every Range (even a single cell) has the Areas-property set, so it's always safe to loop over the Areas of a range.
Try,
Public Values
Public rngDB() As Range
Sub Macro1()
Dim i As Integer
FindAll ("Block")
Debug.Print Values
For i = LBound(rngDB) To UBound(rngDB)
Debug.Print rngDB(i).Address
Debug.Print rngDB(i).Cells(1).Address
Debug.Print rngDB(i).Cells(1, 2).Address
Debug.Print rngDB(i).Cells(2, 1).Address
Next i
End Sub
Sub FindAll(text)
Dim fnd As String, FirstFound As String
Dim FoundCell As Range, rng As Range
Dim myRange As Range, LastCell As Range
Dim sAddress() As String
Dim n As Integer
fnd = text
Set myRange = ActiveSheet.UsedRange
Set LastCell = myRange.Cells(myRange.Cells.Count)
Set FoundCell = myRange.Find(what:=fnd, after:=LastCell)
'Test to see if anything was found
If Not FoundCell Is Nothing Then
FirstFound = FoundCell.Address
Else
'GoTo NothingFound
End If
Set rng = FoundCell
'Loop until cycled through all unique finds
Do
n = n + 1
ReDim Preserve rngDB(1 To n)
ReDim Preserve sAddress(1 To n)
Set rngDB(n) = FoundCell.CurrentRegion
sAddress(n) = rngDB(n).Address
Set FoundCell = myRange.FindNext(after:=FoundCell)
Loop While FoundCell.Address <> FirstFound
'Creates global value with all found adresses
If n Then
Values = Join(sAddress, ",")
End If
End Sub

Validation summary of mandatory cells in excel

I have got an excel workbook, it has 5 static tabs and more tabs can be created using a template tab.
In each tab there is a certain field or a range that is mandatory to be filled out also in the new created tabs (might be up to 60).
My question is how can I go about seeing in, lets say in mainsheet, a summary which shows me:
Which tab has missing fields
Which fields is missing (an address of a cell)
I tried naming the range "MyRange" and counting if the cells are non blank.
But this will not work for the newly created sheets.
I also tried a conditional formatting but again this will not give me a summary.
In the meantime I also bumped into a sort of solution but this is also not the thing I am looking for:
Sub listEmptyCells()
Dim emptyAddresses() As String
Dim i As Long
Dim ws As Worksheet
Dim rng As Range
Set ws = Sheets("1.Data Source") ' CHANGE AS NECESSARY
Set rng = ws.Range("B30:B32")
If WorksheetFunction.CountBlank(rng) = 0 Then
MsgBox ("No empty cells in the range")
Exit Sub
End If
emptyAddresses() = Split(rng.SpecialCells(xlCellTypeBlanks).Address, ",")
For i = LBound(emptyAddresses) To UBound(emptyAddresses)
ws.Cells(i + 1, 2).Value = emptyAddresses(i)
Next i
End Sub
Your help and guidance here would be highly appreciated
All the best
Jacek
Here's one approach:
Sub listEmptyCells()
Const CHECK_RANGE As String = "B30:B32" 'range to locate empty cells in
Dim i As Long, r As Long, rngCheck As Range, rngEmpty As Range
Dim ws As Worksheet, wb As Workbook, wsSummary As Worksheet
Dim rwSummary As Range, s As String, c As Range
Set wb = ThisWorkbook
Set wsSummary = wb.Worksheets("Summary")
Set rwSummary = wsSummary.Range("A2:B2") 'first row of results
rwSummary.Resize(wb.Worksheets.Count).Clear 'remove previous results
For i = 1 To wb.Worksheets.Count
Set ws = wb.Worksheets(i)
If ws.Name <> wsSummary.Name Then 'exclude specific sheet(s)
s = ""
Set rngEmpty = Nothing
'which range to check - special case or use default?
Select Case ws.Name
Case "Sheet One": Set rngCheck = ws.Range("A1:A10")
Case "Sheet Two": Set rngCheck = ws.Range("G34:G56,H10")
Case Else: Set rngCheck = ws.Range(CHECK_RANGE) 'default range
End Select
'loop cells in check range
For Each c In rngCheck.Cells
If Len(c.Value) = 0 Then
If rngEmpty Is Nothing Then
Set rngEmpty = c
Else
Set rngEmpty = Application.Union(rngEmpty, c)
End If
End If
Next c
If Not rngEmpty Is Nothing Then
s = rngEmpty.Count & " required cell(s) not filled:" & _
rngEmpty.Address(False, False)
End If
With rwSummary 'record results
.Cells(1).Value = ws.Name
.Cells(2).Value = IIf(s <> "", s, "OK")
.Font.Color = IIf(s <> "", vbRed, vbGreen)
End With
Set rwSummary = rwSummary.Offset(1, 0) 'next summary row
End If
Next i
End Sub

Creating Named Range From data with criteria

I came across this code that was provided on a prior question on this topic. It is the exact issue I am trying to solve.
I pasted the code, changed the column range to "A", as my values are in Columns A & B. Column A is my "Category" or criteria and I want Column B to be the values displayed in the named range.
Here is my column data:
When I run the code, I am getting an error:
1004: Method 'Range' of object'_Worksheet'Failed
It Debugs at:
Set rng = sht.Range(cell.Offset(0,1))
Here is the code I am using:
Dim featuresRng As Range
Dim rng As Range
Dim sht As Worksheet
Dim counter As Long
Dim cell As Range
Set sht = ThisWorkbook.Worksheets("Category Details")
Set featuresRng = sht.Range(sht.Range("A1"), sht.Range("A" & sht.Rows.Count).End(xlUp)) 'dynamically set the range of features
counter = 0 'this counter will help us avoid Union(Nothing, some range), which would give an error
For Each cell In featuresRng 'loop through the range of features
If cell.Value = "Essential Oils" Then
counter = counter + 1
If counter = 1 Then
Set rng = sht.Range(cell.Offset(0, 1))
Else
Set rng = Union(rng, sht.Range(cell.Offset(0, 1))) 'build the range
End If
End If
Next cell
Debug.Print rng.Address
sht.Names.Add "Something", rng
End Sub`

Referencing a cells address and storing it in a Range object

I am iterating through a column and wanting to catch the cells that meet the string of text that I am searching for. My problem occurs when I try and set the address of the cell that has met the criteria of the search into a Range object. Line:
Set testRng = i.Range.Adress
Gives me error " Wrong number of arguments or invalid property assignment" and I'm not sure what the issue is here?
This is the entire code I am working with:
Sub Tester()
Dim rng As Range
Dim testRng As Range
Dim i As Variant
Dim cmpr As String
Dim usrInputA As String
usrInputA = InputBox("Col 1 Criteria: ")
Set rng = Range("A2:A10")
For Each i In rng
cmpr = i.Value
If InStr(cmpr, usrInputA) Then
If testRng Is Nothing Then
Set testRng = i.Range.Address
Else
Set testRng = testRng & "," & i.Range.Address
End If
Else
MsgBox "No hit"
End If
Next
End Sub
You should declare i as a Range (not Variant)
Use Union to group together a collection of cells instead of trying to manually build the string yourself
Switch the order of your range set. You only need Set rngTest = i once so I would put this at the bottom so you don't have to keep spamming it.
Option Explicit
Sub Tester()
Dim testRng As Range, i As Range
Dim usrInputA As String
Dim LR as Long
usrInputA = InputBox("Col 1 Criteria: ")
LR = Range("A" & Rows.Count).End(xlUp).Row
For Each i In Range("A2:A" & LR)
If InStr(i, usrInputA) Then
If Not testRng Is Nothing Then
Set testRng = Union(testRng, i)
Else
Set testRng = i
End If
End If
Next i
If Not testRng is Nothing Then
'Do what with testRng?
End If
End Sub

VBA - determine if a cell value (String) matches a Value (String) in a named range

apologies if this has already been answered although I have searched and search with no luck. in a nutshell im trying to change the cell colour if that cell value does not match a value in a named range.
I have tried a number of methods although none are working for me , any help from the vba gurus would be greatly appreciated.
essentially I have a list of values on sheet1(Create) G2:G5000 that I need to know when they don't match value on sheet2(lists) S2:S64 <--this has a named range of Make.
please see a copy of my current code below
Sub testMake()
Dim MkData As Range, MkVal As Range
Dim MKArray As Variant
Set MkData = Worksheets("Create").Range("G2:G5000")
Set MkVal = Worksheets("Lists").Range("Make")
For Each MyCell In MkData
If MyCell.Value <> Range("MkVal") Then
MyCell.Interior.ColorIndex = 6
Else
MyCell.Interior.ColorIndex = xlNone
End If
Next
End Sub
Thanks you all for any help in advance, I have been looking at this for a few days now and seem to be no closer than when I started.
While I would use conditional formatting you could slightly adapt your code as below to do this programatically:
Sub testMake()
Dim MkData As Range
Dim MkVal As Range
Dim MKArray As Variant
Dim lngRow As Long
Dim rng1 As Range
Dim rng2 As Range
MKArray = Worksheets("Create").Range("G2:G5000").Value2
Set rng1 = Worksheets("Create").Range("G2")
Set MkVal = Range("Make")
For lngRow = 1 To UBound(MKArray)
If IsError(Application.Match(MKArray(lngRow, 1), MkVal, 0)) Then
If Not rng2 Is Nothing Then
Set rng2 = Union(rng2, rng1.Offset(lngRow - 1, 0))
Else
Set rng2 = rng1.Offset(lngRow - 1, 0)
End If
End If
Next
If Not rng2 Is Nothing Then rng2.Interior.ColorIndex = 6
End Sub
You could be using Worksheet function Vlookup to compare between the two ranges:
Sub testMake()
Dim MkData As Range, MkVal As Range
Dim MKArray As Variant
Dim result As Variant
Set MkData = Worksheets("Create").Range("G2:G5000")
Set MkVal = Worksheets("Lists").Range("Make")
For Each MyCell In MkData
On Error Resume Next
result = Application.WorksheetFunction.VLookup(MyCell, MkVal, 1, False)
If Err <> 0 Then
result = CVErr(xlErrNA)
End If
If Not IsError(result) Then
MyCell.Interior.ColorIndex = xlNone
Else
MyCell.Interior.ColorIndex = 6
End If
Next
End Sub

Resources