Excel VBA get a range value from visible cells after applying autofilter - vba

Is it not possible to do something simple like this to get the range value of B2?
crdata.Range("B2").SpecialCells(xlCellTypeVisible).Value
I have applied the autofilter to filter out with the given criteria and trying to return the range of B2 as a function.

Set the .SpecialCells(xlCellTypeVisible) to a Range, then use Cells(row, column) on this range to pick out the value that you require. If you are using headers in the result then you may also have to use Offset(1,0) to address your data. So where 'MySheet' has been defined as a Worksheet object, smething like:
Set rsltRng = MySheet.Autofilter.Range.SpecialCells(xlCellTypeVisible)
msgbox rsltRng.cells(2,2)

Related

Adding a single cell to a Range in a formula

I have a Sub that dynamically selects a range of cells and then passes that range in to the Internal Rate of Return Formula. I need to have a single cell appended to the beginning of the range for the formula to work. See below:
Dim calcrange As Range
Set calcrange = Range(Range("B57"), Range("B57").End(xlToRight))
Range("IRR").Formula = "=IRR(" & calcrange.Address & ")"
So ideally, what I'd like to do is add a named range cell "InvestmentOutlay" to be the first cell in the range. The InvestmentOutlay Cell is on a previous sheet, but the order I'd like the formula to run through is
=IRR(InvestmentOutlay,B57,C57, etc)
... Is this possible to do?
Like this, using Union to join two ranges?
Set calcrange = Union(Range("InvestmentOutlay"), Range(Range("B57"), Range("B57").End(xlToRight)))

Finding average of selection and then assigning it to a cell

I am attempting to create some dynamic code that, at this point, will select a bunch of cells, move the selection over two columns, then find the average of that selection and send that value to a cell. This is what I have so far, I am getting stuck at averaging the selection I've made:
Sub StatMakersub(Rng1 As Range)
Dim MyRange As Range
Dim Cell As Object
Dim InQuestion As Range
Dim SelAvg As Object
'Check every cell in the range for matching criteria.
For Each Cell In Rng1
If Cell.Value = 2000 Then
If MyRange Is Nothing Then
Set MyRange = Range(Cell.Address)
Else
Set MyRange = Union(MyRange, Range(Cell.Address))
End If
End If
Next
'Select the new range of only matching criteria
MyRange.Select
Selection.Offset(0, 2).Select
Set InQuestion = Selection
Range("P2").Formula = "=Average(Selection)"
Range("Q2").Formula = "=STDDEVA(Selection)"
End Sub
I can't find much on the web about how to average range variables.
You can calculate the average of a selection in this way:
Application.WorksheetFunction.Average("Here you put your range")
The result is a value and not an object, so you should use a variable. Taking names from your case you should use it like this:
SelAvgResult = Application.WorksheetFunction.Average(InQuestion)
I put another name for the variable, but you may still use SelAvg if you like. Just remind to define it as a variable (you may choose your desired format depending on the data size) instead of object if you do not need it anymore.
You may use then this variable for setting the value of your desired cell.
I have a last note: your code seems to replicate the already existing formula AVERAGEIF. If your criteria column is for instance column A and value you should use for calculating the average are in column C, You could directly set the value of the cell where you want the average like this:
=AVERAGEIF(A:A, "2000", C:C)
In this case you would avoid VBA.
Have you tried using the Sum worksheet function for calculating the sum of the range?
Xsum = WorksheetFunction.Sum(arrayX)
and dividing the Xsum value with the length of the array?
One thing I should metion is that you do not need to select the range to work with it. You can use it directly and doing so will also improve how fast your code runs.
To insert your worksheet functions, use the Range.Address function to generate a cell reference to put into the formulas.
https://msdn.microsoft.com/en-us/library/office/ff837625.aspx

Is there a VBA method equivalent to the SQL SELECT query?

With an Excel Worksheet, I'm trying to search rows that matches some criteria in their cells value.
I need something like the SQL SELECT query to proceed search through Excel Worksheet, is there such method in VBA? A method that returns a Range of rows that matches the search criteria.
I have tried with the Range AutoFilter method but I can not use the returned object as a Range to access cells in the returned rows.
I'm really new to Excel VBA so sorry if my question looks strange or stupid
You can use the Union() function to create a range. Here's an simplified example (say you wanted to select the entire rows in which the value in the A column was an even number and highlight them yellow):
Sub UnionTest()
Dim myRange As Range
Dim cell As Range
For Each cell In Range("A1:A100")
If cell Mod 2 = 0 Then
If myRange Is Nothing Then
Set myRange = cell
Else
Set myRange = Union(myRange, cell)
End If
End If
Next
myRange.EntireRow.Interior.Color = vbYellow
End Sub
Please note that you need to check if the range is empty or not before you use union on it (and color it but to make the code easier to read I have omitted it here), thus the If-Then statement. Depending on what you want to do to each row, it might be more effecient to just do the process on the row during the for-each loop.
Hava a look at these funcitons
VLOOKUP
HLOOKUP - same as VLookup but for rows
LOOKUP()
INDEX() and MATCH()
OFFSET() and MATCH()
How to find data in an Excel table
How to Use VLOOKUP or HLOOKUP to find an exact match
Hope these help

Copy/Paste cells next to cells that have certain string

I am trying to look up cells in a certain column that have a string (e.g. Names), copy the corresponding cells in the column to its right (i.e. offset(0,1) ), then paste it to a column in a different sheet. I have the following code to find the range variable that I want. However, I can't select it from a different sheet!
When I use Sheets(1).MyRange.Copy, it doesn't accept it. Am I referring to the range in a wrong way? What am I doing wrong?
Here's code that I use to get MyRange:
Option Explicit
Sub SelectByValue(Rng1 As Range, Value As Double)
Dim MyRange As Range
Dim Cell As Object
'Check every cell in the range for matching criteria.
For Each Cell In Rng1
If Cell.Value = Value Then
If MyRange Is Nothing Then
Set MyRange = Range(Cell.Address)
Else
Set MyRange = Union(MyRange, Range(Cell.Address))
End If
End If
Next
End Sub
Sub CallSelectByValue()
'Call the macro and pass all the required variables to it.
'In the line below, change the Range, Minimum Value, and Maximum Value as needed
Call SelectByValue(Sheets(1).Range("A1:A20"), "Tom")
End Sub
One More Question: Rather than specifying the exact range to look at (e.g. "A1:A20"), I would LOVE to look at all of column A. But I don't want to use ("A:A") so it wouldn't look at all rows of A. Isn't there a method to look only in cells that have entries in column A?
Thank you VERY much.
Al
You only need MyRange.Copy.
To restrict only to cells in column A which might have values, you could use
With Sheet1
Set rngToSearch = Application.Intersect(.Columns(1), .UsedRange)
End With
...or maybe look at .SpecialsCells()

Range address, where do I find the sheet?

I work on a UDF and the user inputs a range, say "sheet1!A1:C8".
In the VBA I write the following:
Function RelativeSearch(Search, rng As Range, Row, Column)
MsgBox rng.Address
Here the msgbox only gives me A1:C8. How can I get the "Sheet1"?
I have tried to make rng as string but that does not work as I have to use rng.find later in the code.
Anyone know of a way to get the sheet from the range?
The Range object has a Worksheet property, so:
rng.Worksheet.Name will do what you want.
In addition the Address property has an External argument, so:
rng.Address(External:=True) yields the entire range address, e.g., [Book1]Sheet1!$D$28.
To get a reference to the Sheet, use rng.Parent.
In your specific case, you are looking for rng.Parent.Name.
So you could do
MsgBox rng.Parent.Name & "!" & rng.Address
This is not an answer to the question you asked, but I suspect it might help you avoid having to ask the question.
If you are trying to find, within rng, the value passed as Search, and then return a value derived by some offset by Row and Column, there is no need to know what worksheet rng is on:
Excel formula (perhaps in cell Sheet4!D6):
=RelativeSearch("b",Sheet1!A1:A6,3,2)
Code which will search the range A1:A6 in Sheet1 for the value "b" and then return the value from the cell that is 3 rows below and 2 columns to the right:
Function RelativeSearch(Search, rng As Range, Row, Column)
Dim r As Range
Set r = rng.Find(What:=Search, LookIn:=xlValues, LookAt:=xlWhole)
If r Is Nothing Then
RelativeSearch = CVErr(xlErrNA)
Else
RelativeSearch = r.Offset(Row, Column).Value
End If
End Function
(If you want it to be consistent with VLOOKUP's syntax, you will need to use r.Offset(Row - 1, Column - 1) rather than r.Offset(Row, Column).)