Returning entry from an array that fits a range condition - excel-2007

Is there a way to have a cell in Excel 2007 view through an array of six numbers and return the highest of any of the numbers that fit into a specified range?
My particular numbers in the array are 22 18 14 10 7 4 and my range is 6 to 12. I was thinking of creating a separate column with the AND function to simplify some steps but I can't make it work.

I am not sure what you are referring to when you say array, but if the array refers to cells:
{=MAX(IF(B18:G18<12,IF(B18:G18>6,B18:G18,0),0))}
Will give you the value between (6,12) which is highest in the range A1:A6.
Be sure to make the function an array wise function by using control + shift + enter.

Related

Count the number of instances of a digit in a range of cells

If I have a column and the cells are
579
39
357
3467
34579
I want to be able to count the number of times any of the digits occurs. For example, 3 occurs 4 times in this range.
I tried using the countif function, but this seems to only work if the only thing in the cell is a 3.
Is this possible using a function, or will I have to do a workaround?
Try using using Application Evaluate on a native SUMPRODUCT function.
application.evaluate("SUMPRODUCT(LEN(A2:A99)-LEN(SUBSTITUTE(A2:A99, 3, """")))")
This will count multiple occurrences within a single value; e.g. 233453 hold 3 occurrences of 3.
If I was doing this, I would qualify the parent worksheet in those cell range addresses to avoid any confusion. The external parameter of the Range.Address property can help you construct a string to be evaluated as a formula.

How to Find the Length of a Column in VBA with a Variable Last Row

I'm a beginner to vba and hope to use it in order to automate a process. I have a computer program that provides me an excel spreadsheet, where the amount of data in the columns can change. For example, I could have a column of length 9 one time:
1
3
2
4
24
23
432
55
2
Or a column of length 5 (note: actual column sizes are usually in the thousands):
1
2
3
4
8
I want to write code that will grab this column, not knowing how long the column will be. Something like:
Dim list1 As Array
'I don't know how to find the upper bound
list1 = Range("A1:A" & Upper Bound).Value
Any help is appreciated. Thanks!
If you are working with constant values in these columns and are working with larger amounts of cells in these columns, it could be useful to use the count function:
dim x As Long
x = Worksheets(*sheet name*).Range(*column range*).Cells.SpecialCells(xlCellTypeConstants).Count
x is being passed the number of non-empty cells in your column. So you may want to be careful in your column range not to include any headers, if applicable.
I believe this will get you the last row. You might need to be careful if you're looking to count all values (e.g. the first couple rows are blank).
Dim lastRow As Long
lastRow = Cells(Rows.Count, "A").End(xlUp).Row
To get the data from column A into a 2d variant array, use the following:
Dim vA As Variant
vA = [a1:index(a:a,counta(a:a))]
This assumes that there are no blank cells within the data, and that the data starts in row 1.

AVG of Cells Next to Cells used in Another Formula

I am new to asking questions here so I hope I get this correct. I am helping my dad with a spreadsheet and I'm having issues with figuring out how to do one formula. Dont know if it can be done with a formula or if it has to be done with macros.
This is a scoring sheet with multiple matches. For each match there is a total score and the cell next to the score is an X count (number of bulleyes). In the same row (column K) I calculate the top 6 total scores and average them:
=AVERAGE(LARGE((N15,Q15,T15,W15,Z15,AC15,AF15,AI15,AL15,AO15,AR15,AU15,AX15,BA15,BD15,BG15,BJ15),{1,2,3,4,5,6}))
Now I need to take the AVG of the X counts that are next to the total scores that are used in the formula above and put solution in column L.
For example, if the cells that are used for AVG score in that row are:
N15,Q15,T15,W15,Z15,AC15
then the cells that would need to be used for the X count AVG would be:
O15,R15,U15,X15,AA15,AD15
This result would be put into L15
Please help. If any clarification is needed just let me know.
Screen Shot:
Please try the following formula:
=SUMPRODUCT(O15:BM15,
--(MOD(COLUMN(N15:BL15)-COLUMN($N15),3)=0),
--(N15:BL15+O15:BM15/10^3+COLUMN(N15:BL15)/10^6>=
LARGE(N15:BL15+O15:BM15/10^3+COLUMN(N15:BL15)/10^6,6))
)/6
How does it work?
SUMPRODUCT has 3 parameters - first is the array to sum, next 2 parameters return an array of 0 and 1 to choose only interesting elements of the first array.
MOD(COLUMN(N15:BL15)-COLUMN($N15),3)=0)
This part is included to avoid listing every single cell. If the score is in every third column of the input range, we can calculate column number relative to first column, and function MOD(column,3) returns: {1,0,0,1,0,0...}. So only every third column of input array will be included in sum.
(N15:BL15+O15:BM15/10^3+COLUMN(N15:BL15)/10^6>=
LARGE(N15:BL15+O15:BM15/10^3+COLUMN(N15:BL15)/10^6,6)
This part is to decide which 6 of the scores should be included in the final sum. The trickiest part is to decide what to do with ties. My approach is to take:
if two scores are the same, take the one with higher number of bulleyes
if it is still tied, take the one from first columns
This means that instead of N15 value we calculate:
N15+O15/10^3+COLUMN(N15)/10^6
With your sample data it evaluates to: 566.017014. First three decimal places is the number of bulleyes, next 3 is column number.
You can use the same formula to calculate average of top 6 scores by changing the first parameter:
=SUMPRODUCT(N15:BL15,
--(MOD(COLUMN(N15:BL15)-COLUMN($N15),3)=0),
--(N15:BL15+O15:BM15/10^3+COLUMN(N15:BL15)/10^6>=
LARGE(N15:BL15+O15:BM15/10^3+COLUMN(N15:BL15)/10^6,6))
)/6
You can try this not so elegant solution:
=SUMPRODUCT(INDEX(N15:BK15,MATCH(LARGE((N15,Q15,T15,W15,Z15,AC15,AF15,AI15,AL15,AO15,AR15,AU15,AX15,BA15,BD15,BG15,BJ15),{1,2,3,4,5,6}),N15:BK15,0)+1))/6
Entered as array formula by Ctr+Shift+Enter in Cell L15:M15 (2 cells) which should look like this:
{=SUMPRODUCT(INDEX(N15:BK15,MATCH(LARGE((N15,Q15,T15,W15,Z15,AC15,AF15,AI15,AL15,AO15,AR15,AU15,AX15,BA15,BD15,BG15,BJ15),{1,2,3,4,5,6}),N15:BK15,0)+1))/6}
with added braces.
The number 6 is the equates to the number of top scores you want returned.
Now, why 2 cells (L15:M15). I cannot make SUMPRODUCT evaluate the resulting array from the INDEX so we have to enter it at 2 cells. I don't think that would be a problem since in your screen shot, Column M is not used.
Note: If the range evaluated have less than 6 items, it will error out. Also good point by user3964075. It may or may not be able to deal with ties.

Visual Basic in Excel - WorksheetFunction.max

What is the behavior of this function to be when the values being compared are equal?
If
Cell1 = 10
Cell2 = 11
Debug.Print WorksheetFunction.max(Cell1,Cell2)
Will return Cell2. But if
Cell1 = 10
Cell2 = 10
It returns Cell1.
What am I missing here?
UPDATE:
I have a label at Offset(0,-3)
If one value is greater then I get the appropriate label.
When the values are equal I get on label in particular.
Since I have not defined a consequence when the vales are equal, I wonder what I am missing
about the behavior of this function such that it will choose one value over the other when they are equal.
How much more coding should I assume is necessary?
Function testWinner(rng As Range) As String
testWinner = WorksheetFunction.Index(rng, WorksheetFunction.Match(WorksheetFunction.max(rng), rng, 0)).Offset(0, -3)
End Function
It's nothing to do with Max (now that you've edited your question). Max simply returns the value (since they are all the same) and your Match function is looking for an exact match so it scans through the range until it finds the first match then that position is passed to Index.
WorksheetFunction.Max does not return a cell/range. It returns the largest value in a set of value.
By the way: in case of when both values are equal (10,10), the result of Min, Max and Average function will be the same: 10.
If by saying the behaviour of function you mean how it works, it sorts data and gets the highest value. So, in case of set of value: {10, 10, 8}
Max(10,10,8)** = 10
Max.K({10,10,8},2) = 10 'where K = 2, which means the second highest value
Max.K({10,10,8},3) = 8 'where K = 3, which means the third highest value
On the other hand...
row/column A B
1 10 =RANK(A$1:A$3,A1) 'returns 1
2 10 =RANK(A$1:A$3,A2) 'returns 1
3 8 =RANK(A$1:A$3,A3) 'returns 3
Is it more understandable, now?
In your updated example the following happens in your testWinner function:
The Max value is determined: in example one this is 15 (in example 2 it's 14). Note that only the value but not a reference to any cell is returned
The MATCH function searches through through D2:D3 for the value 15 (14). It does so top down and return the first exact match. I.e. in the first example, this results in 1 (in the second example the result is 2)
INDEX will return the 2nd element of D2:D3 (the 1st in the second example), i.e. cell D2 (D3 in ex. 2)
OFFSET returns the cell three to the left
Thus, the answer to your question is not the return of the MAX function - but the MATCH function - which goes top to bottom until it finds the first element matching your criteria, in your case the max.
Independent of this: why do you use a User-Defined-Function for this? If you'd build this with the normal Excel functions, performance would be higher - and non-VBA users could still understand it. Using =INDEX($A$2:$A$3,MATCH(MAX($D$2:$D$3),$D$2:$D$3,0)) you would save the OFFSET - and make it less error prone, as you can now insert columns between A and D without breaking your model!

VBA conditional cell selection

I was having a play around with excel 2007 VBA and was hoping to create a Macro that generates a random number, then outputs a string based on the number generated. For example,
Number String
1 Athena
2 Belerephone
3 Castor
4 Dionysos
If the random number is 4, the output would be Dionysos, 1 would be Athena and so on.
Basically, I want the Macro to search through the "Number" column, find the cell that matches the randomly generated number, then output the string in the cell to its right.
I have a table of a similar nature in my Excel worksheet.
So far I have not had much success at doing this, any thoughts?
With your data in A1 thru B4, use:
=VLOOKUP(RANDBETWEEN(1,4),A1:B4,2,FALSE) or its VBA equivalent
EDIT#1 :
With the upper bound of the table stored in cell D3 :
=VLOOKUP(RANDBETWEEN(1,D3),INDIRECT("A1:B" & D3),2,FALSE)
You can use application.worksheetfunction.vlookup to perform a vlookup within your macro, and use the 1+Int(10 * Rnd()) function to return random numbers from 1 to 10 (and possibly 11, but statistically unlikely).