search for multiple values - loop - vba

I think this can only be done in VBA. I tried VLOOKUP, but no luck.
I want to search a whole sheet for certain values. These values come from a row in another sheet. Once each value is found, it looks to the top most row and pulls that value.
I might need to loop through each value in the row and search the sheet from there?
my thought/example:
Sheet1!A:A
1234
5325
6346
6342
look in sheet 2 for 1234. lets say its found in cell G5, it will then look at the value in G1 and input that into cell A1 on sheet 2. I'm sorry for making this really confusing.
Here's what I have starting out:
Sub FindValues()
Dim SearchRow As String
Dim SearchRange As Range, cl As Range
Dim FirstFound As String
Dim sh As Worksheet
' Set Search value
SearchRow = Sheets("sheet2").Range("B:B")
getting error on the last line. run-time error '13': type mismatch

You need to Set a Range object. You cannot assign it to a string unless you are looking for a property that is a string like the Address property.
Dim SearchRow As String
Dim SearchRange As Range
SearchRow = Sheets("sheet2").Range("B:B").address
Set SearchRange = Sheets("sheet2").Range("B:B")

Please consider the following code for your requirements:
Sub FindValues()
Dim SearchRow As Range
Dim SearchRange As Range
Dim Cell As Range
Dim FirstFound As Range
' Set Search value
Set SearchRow = Sheets("Sheet1").Range("B:B")
Set SearchRange = Sheets("Sheet2").Range("A:K")
For Each Cell In SearchRow
Set FirstFound = SearchRange.Find(Cell.Value2)
If Not FirstFound Is Nothing Then
Cell.Offset(0, 1).Value2 = SearchRange.Cells(1, FirstFound.Column).Value2
Else
Cell.Offset(0, 1).Value2 = "No Value Found"
End If
Next
End Sub
Note that as per your description I assumed that the SearchRange was more than just 1 column.
Basically the script loops through each Cell in the SearchRow and looks for the value in the SearchRange. If it finds the value and returns a subrange representing cells with the search value and sets the value to the right of each Cell to the value of the top cell of the column where the value was found. Hope this serves your needs. Cheers.

Related

Fill Empty Blank Cells with value within a region horizontaly defined

I'm trying to fill blank cells in a certain region with 0. The reagion should be defined in the current workbook but in sheet2 (not the current sheet). Also the place where it is supposed to fill is between columns
BU:CQ in the current region (not all 100 000 000 lines). Just the number of lines that define the table between columns BU and CQ. I know the problem lies in defining the region... See the code below.
What is missing?
Sub FillEmptyBlankCellWithValue()
Dim cell As Range
Dim InputValue As String
On Error Resume Next
InputValue = "0"
For Each cell In ThisWorkbook.Sheets("Sheet2").Range(BU).CurrentRegion
'.Cells(Rows.Count, 2).End(xlUp).Row
If IsEmpty(cell) Then
cell.Value = InputValue
End If
Next
End Sub
I've this code that i'm positive that works! But i don't wnat selection! I want somthing that specifies the sheet and a fixed range.
Now my idea is to replace "selection" with the desired range. - In this case in particular the range should be 1 - between BU:CQ; 2 - starting at row 2; 3 - working the way down until last row (not empty = end of the table that goes from column A to DE)
Sub FillEmptyBlankCellWithValue()
Dim cell As Range
Dim InputValue As String
On Error Resume Next
For Each cell In Selection
If IsEmpty(cell) Then
cell.Value = "0"
End If
Next
End Sub'
PS: And I also need to specify the sheet, since the button that will execute the code will be in the same workbook but not in the same sheet.
Use SpecialsCells:
On Error Resume Next 'for the case the range would be all filled
With ws
Intersect(.UsedRange, .Range("BU:CQ")).SpecialCells(xlCellTypeBlanks).Value = 0
End With
On Error GoTo 0
MUCH faster than looping !
Try using cells() references, such as:
For i = cells(1,"BU").Column to cells(1,"CQ").Column
cells(1,i).value = "Moo"
Next i
In your current code you list Range(BU) which is not appropriate syntax. Note that Range() can be used for named ranges, e.g., Range("TheseCells"), but the actual cell references are written as Range("A1"), etc. For Cell(), you would use Cells(row,col).
Edit1
With if statement, with second loop:
Dim i as long, j as long, lr as long
lr = cells(rows.count,1).end(xlup).row
For i = 2 to lr 'assumes headers in row 1
For j = cells(1,"BU").Column to cells(1,"CQ").Column
If cells(i,j).value = "" then cells(i,j).value = "Moo"
Next j
Next i
First off, you should reference the worksheet you're working with using:
Set ws = Excel.Application.ThisWorkbook.Worksheets(MyWorksheetName)
Otherwise VBA is going to choose the worksheet for you, and it may or may not be the worksheet you want to work with.
And then use it to specify ranges on specific worksheets such as ws.Range or ws.Cells. This is a much better method for specifying which worksheet you're working on.
Now for your question:
I would reference the range using the following syntax:
Dim MyRange As Range
Set MyRange = ws.Range("BU:CQ")
I would iterate through the range like so:
Edit: I tested this and it works. Obviously you will want to change the range and worksheet reference; I assume you're competent enough to do this yourself. I didn't make a variable for my worksheet because another way to reference a worksheet is to use the worksheet's (Name) property in the property window, which you can set to whatever you want; this is a free, global variable.
Where I defined testWS in the properties window:
Public Sub test()
Dim MyRange As Range
Dim tblHeight As Long
Dim tblLength As Long
Dim offsetLen As Long
Dim i As Long
Dim j As Long
With testWS
'set this this to your "BU:CQ" range
Set MyRange = .Range("P:W")
'set this to "A:BU" to get the offset from A to BU
offsetLen = .Range("A:P").Columns.Count - 1
'set this to your "A" range
tblHeight = .Range("P" & .Rows.Count).End(xlUp).Row
tblLength = MyRange.Columns.Count
End With
'iterate through the number of rows
For i = 1 To tblHeight
'iterate through the number of columns
For j = 1 To tblLength
If IsEmpty(testWS.Cells(i, offsetLen + j).Value) Then
testWS.Cells(i, offsetLen + j).Value = 0
End If
Next
Next
End Sub
Before:
After (I stopped it early, so it didn't go through all the rows in the file):
If there's a better way to do this, then let me know.

VBA clear cell range based on a certain condition

This problem may seems pretty simple but I have been dealing with it for 2 days now and cant get it done. I searched other forums to see if they have this same problem but didnt find close to tyhis one.
So I have range K:T starting from row 2 and need to clear the cells that contains #N/A. I wrote the code below but cant seem to make it work.
Sub Clear_cells()
Dim rng As Range, i As Integer
'Set the range to evaluate to rng.
Set rng = Range("K:T")
'Loop backwards through the rows
'in the range that you want to evaluate.
For i = rng.Rows.count To 1 Step -1
'If cell i in the range contains an "N/A", delete cell content
If rng.Cells(i).Value = "#N/A" Then rng.Cells(i).CellRange.ClearContents (1)
Next
End Sub
If your cells contain an error value (i.e. #N/A) rather than the string "#N/A" then you need to check for an error value instead of checking for a string.
Replace
For i = rng.Rows.count To 1 Step -1
'If cell i in the range contains an "N/A", delete cell content
If rng.Cells(i).Value = "#N/A" Then rng.Cells(i).CellRange.ClearContents (1)
Next
with
Dim cel As Range
For Each cel in rng
If IsError(cel.Value) Then
If cel.Value = CVErr(xlErrNA) Then cel.ClearContents
End If
Next
or, if you want to check for all error conditions (such as #DIV/0!), just use
Dim cel As Range
For Each cel in rng
If IsError(cel.Value) Then cel.ClearContents
Next
use the function isna to check for #N/A
If Application.WorksheetFunction.IsNa(rng.Cells(i)) Then rng.Cells(i).CellRange.ClearContents (1)

VBA removing rows from a spreadsheet if cells contain a certain string

I am very new to VBA. I am trying to isolate a particular customers transactions on a spread sheet.
Column "A" contains the Customer payment method (prepaid or various other methods). Column "D" contains the customer we are shipping too, Column "L" contains the customer we are shipping from.
If the cell in column "A" has 'prepaid' I want to search column "D" for the customer name (jaba). I will then delete all rows which do not contain this customer. IF the cell in column "A" is not 'prepaid' I want it to search column "L" for the customer name, and delete all rows which do not contain this string. When I run the code provided below I get an 1004 error on the following script 'If cell3.Find(ContainWord) Is Nothing Then'. Any help would be much appreciated.
Sub DoNotContainClearCells()
Dim rng As Range
Dim rng2 As Range
Dim rng3 As Range
Dim cell As Range
Dim cell2 As Range
Dim cell3 As Range
Dim ContainWord As String
'What range do you want to search?
Set rng = Range("A:A")
Set rng2 = Range("D:D")
Set rng3 = Range("L:L")
'What phrase do you want to test for?
ContainWord = "jaba"
For Each cell In rng
If cell.Value = "prepaid" Then
'Loop through each cell in range and test cell contents
For Each cell2 In rng2.Cells
If cell2.Find(ContainWord) Is Nothing Then EntireRow.Delete
Next cell2
Else
'Loop through each cell in range and test cell contents
For Each cell3 In rng3.Cells
If cell3.Find(ContainWord) Is Nothing Then EntireRow.Delete
Next cell3
End If
Next
End Sub
Without discussing the logic of your code, which is not part of the question, I can tell you that the
Run-time error '1004': Object required
in this line:
If cell3.Find(ContainWord) Is Nothing Then EntireRow.Delete
is because the EntireRow.Delete is missing a range (see Range.EntireRow Property (Excel))
Solution: Replace these lines:
If cell2.Find(ContainWord) Is Nothing Then EntireRow.Delete
If cell3.Find(ContainWord) Is Nothing Then EntireRow.Delete
with these:
If cell2.Find(ContainWord) Is Nothing Then cell2.EntireRow.Delete
If cell3.Find(ContainWord) Is Nothing Then cell3.EntireRow.Delete
Suggest to always have at the top of the modules\classes\userforms:
Option Explicit
This would have given a Compile error: Variable not defined highlighting the error earlier at compiling time (see Option Explicit Statement)

Find cells with same value within one column and return values from separate column of same row

I want to find all the cells in Column L with a particular value and return the values in Column D of the same row as those cells found.
So far, I am only able to return one result, which would be the top most result in my list, but I want to find all the rest as well, which I don't know the code to use.
Just to further explain: Value in cell D11 is the value I want to find in Column L of sheet "Master List". Supposedly I find the value in cells L13, L15 and L20, I want to return the value in cell D13, D15 and D20 into cells "C37:C39" of ws. Note: no. of cells that have the value may vary so the values returned will just appear from C37 downwards (something like automatic multiple selection, copy and paste)
Here's a little something to start the ball rolling:
Sub FindRelatedProducts()
Dim cell As Excel.Range
Dim D11Value As Variant
Dim D11Row As Variant
Dim ws As Worksheet: Set ws = Sheets("RShip")
Set cell = ws.Range("D11")
D11Value = cell.Value
With Sheets("Master List")
D11Row = Application.Match(D11Value, .Range("L:L"), 0)
If Not IsError(D11Row) Then
ws.Range("C37") = .Range("D" & D11Row).Value
End If
End With
End Sub
Here's an example using range variables.
You'll want to define a range for the input data range and a range for the output data. Then in the VBA you will want to change the wrk, inRng and outRng variables to be the named ranges you defined and change the column indexes in the for and if blocks to match the column index of the data you are looking for.
Option Explicit
Option Base 1
Sub FindValues()
Dim wrk As Worksheet
Dim inRng As Range
Dim outRng As Range
Dim cntr As Long
Dim outCntr As Long
Dim findVal As Double
Set wrk = Worksheets("Data")
Set inRng = wrk.Range("LookupRange")
Set outRng = wrk.Range("OutputRange")
' Clear the output range in case you have fewer values on this run than on the previous one
outRng.ClearContents
' Set the value you are looking for
findVal = 1
' Iterate through the rows in the input range. If you find the result you want then write it to the output range
For cntr = 1 To inRng.Rows.Count
If inRng(cntr, 1) = findVal Then ' Assumes the value you are finding is in column 1 of the input range
outRng(outCntr, 1) = inRng(cntr, 2) ' Assumes the values you are exporting is in column 2 of the input range
outCntr = outCntr + 1
End If
Next cntr
End Sub

Passing range objects to functions in excel-vba -- receive "Object Required" error

I'm trying to build a function that will take an input cell (say "B5") and return a range object that refers to a table (of which the supplied cell is the top-right entry)
Sub Macro1()
Dim testCell As Range
testCell = Worksheets("HMA").Range("B5")
ReturnTable testCell
End Sub
Function ReturnTable(cell As Range)
firstcell = cell
lastrow = firstcell.End(x1Down)
Table = Range(firstcell, lastrow + 5).Value
End Function
I've been running into a lot of problems here, and I feel like I'm missing something simple. The error that I'm getting is "Object Required" at the lastRow line.
Looking through it in debug mode I see that testCell is assigned the value of the range object (I assume this is the default). What am I missing here?
Is my approach even sound? Should I be looking at solving this problem in a different way?
The End returns a Range object, so, lastrow must be a range variable.
Function ReturnTable(firstcell as Range) as Range 'add this as range to tell the result of the function is a range
dim LastCell as Range
Set LastCell = firstcell.END(xldown)
Set ReturnTable = Range(firstcell, lastcell) 'must use the same name of the function
End Function
If you want 5 cells below lastcell, use LastCell.Offset(5,0)
And in Macro1, you probably will want something like
Set SomeVar = ReturnTable(testcell)
When you assign Objects (like Range) you have to use "Set".
If you assign Range without "Set" VBA will assign the value of the Range and not the Range itself.
Set testCell = Worksheets("HMA").Range("B5")