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

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

Related

IF() Multiple Cells are equal then "TRUE" with only taking number values in a range

I am trying to write a formula to take only number formats from a row to in order to use an IF formula that illicit the value of "No" if all cells are equal to each other.
See a snippet of my file here:
The problem I am having is that the formula is taking the blank cells (no formats) and counting them in the equation still, so all of my values are "Yes". How do I let my formula only calculate from cells that have numbers in them for each row? I have tried the IFNUMBER(), IFEMPTY() etc... but I am not sure I am employing these correctly e.g. nesting into my formula. I need to ignore the blanks in each row.
Note: I need to only take the cells with number values. I have cleared the contents of values of the rows that do not have number values.
Here is the equation that I currently have:
=IFERROR(IF(AND(ROUND($E2,3)=ROUND($F2,3),ROUND($F2,3)=ROUND($G2,3),ROUND($G2,3)=ROUND($H2,3),ROUND($H2,3)=ROUND($I2,3),ROUND($I2,3)=ROUND($J2,3),ROUND($J2,3)=ROUND($K2,3),ROUND($K2,3)=ROUND($L2,3),ROUND($L2,3)=ROUND($M2,3),ROUND($M2,3)=ROUND($N2,3)),"No","Yes"),"")
Note: this is taking blanks and counting them (as stated from above). It should produce a "Yes" if there are numbers different in the column and a "No" if there are no numbers differences. Currently, it is always producing a "Yes" because it is counting the blanks in the columns.
I am open to a vba solution as well, I have the following from code, but I do not know how to set the range for each row to only look for number formats:
Here is my vba code:
Dim arng As Range
Dim aworkrng As Range
Dim brng As Range
Dim bworkrng As Range
On Error Resume Next
Set aworkrng = Range("O2:O1550")
Set bworkrng = Range("E2:N1550")
Set brng = Range("E2:N2")
On Error Resume Next
For Each arng In aworkrng
If Not IsEmpty(brng.Value) Then
arng.Formula = _
"=IFERROR(IF(AND(ROUND(RC5,3)=ROUND(RC6,3),ROUND(RC6,3)=ROUND(RC7,3),ROUND(RC7,3)=ROUND(RC8,3),ROUND(RC8,3)=ROUND(RC9,3),ROUND(RC9,3)=ROUND(RC10,3),ROUND(RC10,3)=ROUND(RC11,3),ROUND(RC11,3)=ROUND(RC12,3),ROUND(RC12,3)=ROUND(RC13,3),ROUND(RC13,3)=ROUND(RC14,3)),""No"",""Yes""),"""")"
Range("O3").Select
End If
Next
If anyone can help me on this, I would great appreciate it!
Try:
=IF(MIN(E2:N2)=MAX(E2:N2),"No","Yes")

Best way to return data from multiple columns into one row?

I have a sheet with just order numbers and another with order numbers and all of the data associated with those order numbers. I want to match the order numbers and transfer all of the available data into the other sheet. I've been trying to use loops and VLOOKUP but I'm having problems (plus I have 116 columns I want to transfer data from so my vlookup expression doesn't look very nice). Any advice would be appreciated!
this is what I have so far and I'm getting an object error.
I don't think it's the right way to go about it in general though.
Dim LookUpRange As Range
Dim row As Range
Set LookUpRange = Worksheets("batches").Range("B4:B1384")
Set row = Worksheets("batches").Range("C:DL")
For Each row In LookUpRange
row.Select
Selection.FormulaArray ="=VLOOKUP(RC[-1],OrderLvl!RC[-1]:R[1380]C[113],{2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,207,108,109,110,111,112,113,114,115},FALSE)"
Next row
End Sub
Please consider this VBA script to resolve your inquiry:
Sub LookupOuput()
Dim OrderNumberColumn As Range
Set OrderNumberColumn = Worksheets("batches").Range("B2:B1384")
Dim LookUpRange As Range
Set LookUpRange = Worksheets("OrderLvl").Range("C:DL")
Dim cell As Range
Dim FindResult As Range
For Each cell In OrderNumberColumn
If Not cell.Value2 = Empty Then
Set FindResult = LookUpRange.Find(what:=cell.Value2)
If Not FindResult Is Nothing Then
cell.Range("A1:DJ1").Value2 = LookUpRange.Rows(FindResult.row).Value2
End If
End If
Next cell
End Sub
Basically searches for each Order Number in the first sheet on the second sheet. This outputs (if search term exists) the cell that that string is found which we later refer to its row number to output the whole row to the first sheet. Cheers,
A regular VLOOKUP may be able to give you what you need, if you use a small trick...
Insert a row above the data table, and put sequential numbers in
each cell of that row. (ie, A1 = 1, B1 = 2, C1 = 3, etc...)
Do the same thing on your blank table.
Assuming that your first order number is in cell A2, put the following formula into B2: =VLOOKUP($A2,[other sheet name]!$A$1:$DZ$5000,B$1,0)
Drag this formula across all 116 columns, then down all however many rows you've got.
You'll need to adjust the ranges, obviously, but make sure that your lookup array starts in column A. (or alternatively, that your numbers start in the same column as the first column in your array.) Adding the numbers along the top allows you to change what column of the array you're referencing, just by dragging the cell formula.

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

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

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)

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()