Using Find Function to return cell address - excel

I am using the find function to search through a number of different ranges for a specific heading.
If this heading is present I would then like to extract the information from the cell below. Is it possible for the find function to return the address of the cell found and then I can simply search for Cell(x +1, y) to extract the data from below?
My current code is;
For i = 1 To LastRow
X = VirtMat(i, 1)
Set TestRange = Range(X)
Set BILL = TestRange.Find("Loss Number:")
If Not BILL Is Nothing Then 'RETURN CELL ADRESS AND EXTRACT INFO
Else: rpd(cr, 1) = "NOINFO"
End If
Next

As per MSDN:
Finds specific information in a range, and returns a Range object that represents the first cell where that information is found.
So the answer your question is yes. You can use Address or Row and Column Property of the Range Obejct.
Debug.Print BILL.Address '~~> default is A1 notation
Debug.Print BILL.Row '~~> returns row number
Debug.Print BILL.Column '~~> column number
In fact you can directly get the value in the cell adjacent or below it.
Example: To get value below the found cell, use Offset Method.
Debug.Print BILL.Offset(1, 0).Value

Related

How to use a fixed cell in a formula in vba

I have an issue with using a formula that contains a fixed cell in VBA. The issue comes when the row number of the variable in the new data changes.
The issue is explained using a simple example as follow. I hope you find it understandable.
Let's say I have a column of numbers (Time) and I want to multiply them by a variable in a cell (The cell below Variable in the following table, $A$2).
First result from first raw data:
The results in the table are calculated using the following formula "=R2C1*RC[-1]" in vba
Now in the next calculation, the row number and variable change and the part of the formula which is using a fixed cell cause problem.
Second raw data to be processed
Because it does not update the row number and use the old row number. I want it to find its location like the second part of the formula (B2 changes to B7).
Thank you for your help!
Cheers,
Aryan
you should reference the found cell row in your formula
ActiveCell.FormulaR1C1 = "=R" & ActiveCell.Row + 1 & "C1*RC[-1]"
but you should also avoid the Activate/ActiveXXX/Select/Selection pattern since is prone to have you quickly lose control over the actually active thing
finally you an use a loop to find all "Time" occurrences (see Here for more info about the pattern)
Option Explicit
Sub main()
Dim f As Range, firstCell As Range
With Worksheets("myWorksheetName") ' reference your worksheet (change myWorksheetName to your actual sheet name)
With .Range("B1", .Cells(.Rows.Count, "B").End(xlUp)) 'reference its column B cells from row 1 down to last not empty one
Set f = .Find("Time", LookIn:=xlValues, lookat:=xlWhole) 'search referenced range for first occurrence of "time"
If Not f Is Nothing Then ' if found...
Set firstCell = f ' store first occurrence cell
Do
f.Offset(1, 1).Resize(4).FormulaR1C1 = "=R" & f.Row + 1 & "C1*RC[-1]" ' populate the range one column to the right of found cell and 4 rows wide with the formula containg the reference of found cell row +1
Set f = .FindNext(f) ' serach for the next "Time" occurrence
Loop While f.Row <> firstCell.Row ' loop till you wrap back to initial occurrence
End If
End With
End With
End Sub
The notation R2C1 is an absolute reference to row 2, column 1.
If you want a reference that is relative to the current cell, you need to use relative reference notation.
RC[-1] points to a cell in the current row and one column to the left
R[1]C points to a cell one row down from the current cell and in the same column as the current cell.
Google for "R1C1 reference". You will find many articles, for e.g. https://smurfonspreadsheets.wordpress.com/2007/11/12/r1c1-notation/

How to refer to a column in a excel with something like Cells("Name").Value instead of Cells(n,m) in vbscript?

I have an excel with predefined column headers.The problem is these column headers can be at any position for every iteration that is only column headers are fixed not their position(index). So, I need to get the column index based on the column name for further processing.
I found another way to access the column as described in the question, so I though I should change my first answer accordingly. But I thought maybe that answer works for other cases.
Here is a quicker way to get hold of a column containing the value:
Sub Macro1()
ColumnByValue("age").Offset(5, 0).Value = "17"
End Sub
Function ColumnByValue(col As String) As Range
Set ColumnByValue = Range("1:1").Find(col)
End Function
Use .Find() to locate the cell containing the column you are looking for.
I wrote the following example to add a value at a certain column, on a specified row number. You might want to change the code so that it adds the value to the bottom of the existing values instead. For simplicity, the code below will find the column, go down to the specified row and change the value to the value specified by the caller.
Sub Macro1()
Dim result As Boolean
result = add_value_to_column("age", atRow:=3, newValue:=17)
'was that successful?
If result = True Then
MsgBox "value was added"
Else
MsgBox "value NOT added. maybe column does not exist"
End If
End Sub
Function add_value_to_column(col_name As String, _
atRow As Integer, _
newValue As String) As Boolean
Dim c As Range
'Assuming the header row is the first row at the top (1:1)
With Range("1:1")
'try to find the column specified in the function parameters
Set c = .Find(col_name, LookIn:=xlValues)
'If the column was found then it will not be nothing
'NOT NOTHING = THING :)
If Not c Is Nothing Then
'access the row specified in the parameter, at the column,
'and set the value for that location
Cells(atRow, c.Column).Value = newValue
'Optioal: inform the caller that the value was set
add_value_to_column = True
Else
'optional: inform the caller that column was not found
add_value_to_column = False
End If
End With
End Function
Here is an image showing a sample data set. Running the code above has added the value 17 to the age column for the row number 3

Trying to find the next instance of exact string in cells

I need assistance finding the next instance of an exact string within a cell.
To be precise, I want to look through a series of headings and find the next instance of a declared variable to obtain the column number, and I want to look through that series of headings to find the next empty cell and save that number, and finally, I'd like to take that first column number, and search from second row until I find the first instance of an empty cell, and save that number into a variable. What I have been doing is this:
With Rows(1)
Set found = .Find(what:=Target, After:=.Cells(1, 1))
End With
But it seems that if I accidentally type "s" it will find the first instance of a cell that contains a string that contains the substring "s" (LastName), and not the first cell that contains only "s".
my fear is that if there are columns with " " in them then my program will not function correctly.
Besides that, I sort by a column and when a cell in that column is empty my program pushes it all the way to the bottom of the list and I am trying to delete that empty cell space.
I tried doing Application.WorksheetFunction.Match, HLookup and VLookup and in general the worksheet functions aren't working for me.
So just to give an example of what I want to do:
I have 10 Columns with headings. I want to find the first instance of a column that
contains exactly the string I send into this class. For instance, if the
columns are "FirstName | LastName | Name", I want it to return "Name"
and not "FirstName".
I want to find a column that the user requests as a sort key and verify it's existence
I also want to find a column that is empty (last column)
Finally, I want to find the last row that has a value in relation to the SortColumn.
If you set the lookat parameter to xlWhole, it will only match the whole contents of the cell, so for example:
With Rows(1)
Set found = .Find(what:=target, After:=.Cells(1, 1), lookat:=xlWhole)
End With
To check whether a value was found, you can check whether found is nothing.
Dim exists As Boolean
If Not found Is Nothing Then exists = True
To locate the first empty cell at the end of a row or column of values, I would use the End property to find the last cell in the row/column containing data, then use Offset to find the next cell:
With Rows(1)
Set found = .Find(what:=target, After:=.Cells(1, 1), lookat:=xlWhole)
End With
Dim emptyCell As Range
If Not found Is Nothing Then
Dim col As Integer
col = found.Column
Set emptyCell = Columns(col).End(xlDown)
emptyCell.Offset(1, 0).Select
End If
However, you can't use this if there are some empty cells in the middle of your table of values. (eg if you have values in A1,A2,A3, then A4 is blank and you have more values in A5,A6,A7).
You can use a do loop:
headerToFind = "Name" 'or whatever header you're looking for
x = 1 'or whatever header row is
y = 1 'or whatever first column with header is
Do Until Cells(x,y) = ""
If Cells(x,y) = headerToFind then
MsgBox "The header you are looking for is in row " & x & ", column " & y
Exit Sub
End If
y = y + 1
Loop
MsgBox "Header not found"
In place of the message boxes, put whatever code you want to do with what you find. The first MsgBox will execute if and when the header is found (with x being equal to the row number and y being the column number). The second MsgBox will execute if the desired header is not found.

How do I get the current cell number whilst looping through a range of cells (Excel VBA)

I'm trying to get the current cell number whilst looping through a range of cells.
For Each i In Sheet3.Range("A3:A213")
msgbox(Sheet3.Range("B"&currentcellnumberinloop).Value)
Next
The purpose of this is to retrieve a value from another cell in the same row e.g. A1 and B1.
The i is probably declared as Range object(or Variant). Therefore to get the row number and retrieve the value in neighboring B column you have to call the .Row method of the i object
Sub ForEachAndFor()
Dim i As Range
For Each i In Sheet3.Range("A3:A213")
MsgBox Sheet3.Range("B" & i.Row).Value
Next
End Sub
You could also use the Offset(how_many_rows_up_or_down, how_many_columns_left_or_right)
you indicate rows down with a positive number an rows up with a negative number
same applies to the columns, use - to navigate to the left of the current cell, and positive number to the right of the current cell.
Sub ForEachSub()
Dim i as Range
For Each i in Sheet3.Range("A3:A213")
MsgBox i.Offset(0, 1).Value
next i
End Sub
Try this
Dim i as Integer
For Each i In Sheet3.Range("A3:D213").Rows.Count
msgbox(Sheet3.Range("B" & i).Value)
Next i
In your code variable i is of a Range type, thus you have to treat it that way. You can use Offset to get to what is in relation to your i address, like that:
For Each i In Sheet3.Range("A3:A213")
MsgBox (i.Offset(0, 1).Value)
Next i

Search for a Cell in Excel using VBA

Problem:
I would like to find a value of a cell next to or below the cell content a text value for a workbook.
Example:
In Sheet2, I have two cells stand random (assume its index is unknown and total is not a defined name)
I want to search for the value "200" stands next to the total and put it in sheet 2 (an active cell). In case, there are multiple cell that contains the word "Total" list all of them and if possible, put the name of the sheet that contains the cell that I am looking for. Value 200 Sheet2
My Approach:
1. User input
Go to each cell and search for it. This will take time if search for the whole limitation of cell in excel. So the search only limit to 100 columns x 10000 rows.
After find its index, offset to 1 columns to get the value
Write the result ActiveCell.Value = Search_Value. Then continue to search for the rest of sheets. Offset 1 coloum and 1 row to write the second value...
Searching is a very difficult concept, and I truly have no idea how to do the search part. Please help
With Worksheets(1).Range("a1:a500")
counter=0
Set c = .Find("Total", lookin:=xlValues)
If Not c Is Nothing Then
firstAddress = c.Address
Do
counter=counter+1
Worksheets(2).range("A1").offset(counter,0)=c.offset(0,1)
Set c = .FindNext(c)
Loop While Not c Is Nothing And c.Address <> firstAddress
End If
End With
firstaddress holds the location of the first cell found (so we know when to stop); firstaddress.offset(0,1) will give you the value you are trying to save, so setting worksheet(2).range("a1").offset(counter,0) will list all the values it finds on the 2nd tab, from a1 down to however many it finds in the range

Resources