enter image description here
Looking at the above image, I am wondering how do I find the average starting at a number that matches certain criteria? For example, given the range J3:Q3, how would I start find the averaging after a number is greater than 50 (so in this example L3:Q3)?
You can add a custome made Function in VBA in your Worksheet that you can call it from your worksheet.
In your Excel Worksheet you need to type
=Average_Cells(first_cell_for_average, value_above)
first_cell_for_average - you can put A3, the function will handle the rest.
value_above = in your post it's 50, you can modify it later to whatever value you want.
The Function Code:
Public Function Average_Cells(ByRef first_Cell As Range, larger_Than As Long) As Double
' Row 3 in your post
last_col = ActiveSheet.Cells(3, ActiveSheet.Columns.count).End(xlToLeft).Column
first_Col = first_Cell.Cells(1, 1).Column
For col = first_Col To last_col
If Cells(3, col).Value > larger_Than Then
GoTo Exit_For
End If
Next
Exit_For:
Average_Cells = Application.WorksheetFunction.Average(Range(Cells(3, col), Cells(3, last_col)))
End Function
Hack-y method:
Fill in J4 with
=IF(J3>50, J3, '')
And then copy it until Q4.
Then fill in J5 with
=AVERAGE(J4:Q4)
Related
EDIT, in short:
I have an excel table that looks like this:
tabel
Each cell contains a range of numbers.
I'm looking for a function that can search for a number in the whole table and indicate me the column and row where the range that it belongs to is located.
So, if I search for number 2346, it should function like this:
function (2346) > result (C1, R2)
I have a huge archive of photos (about 300.000 items) in a library.
Photos are stored in boxes, the boxes in shelves.
Each box has a range of inventory numbers of photos.
I want to create a map of the deposit that looks like this:
Shelf 1 - contains boxes 1, 2, 3, etc.
Box 1 - contains photos with inventory numbers between 1257-1321
Box 2 -"- between 2345-2522
Box 3 -"- between 123523-123643
Translated in an excel table, it would look like this:
Column 1 would be Shelf 1, containing the boxes with the images:
cell in column 1 / row 1 (that's box 1) contains the range of numbers: 1257-1321
cell in column 1 / row 2 (box 2), the range: 2345-2522
cell in column 1 / row 3 (box 3), range: 123523-123643
They are not in order, because they entered in more than 100 years in the collection, and they are arranged as they entered and by subject. Not to mention that the deposit has been moved a few times. So, I have a hard time to find one image when I'm looking for it.
But if I have this excel table, this map of the deposit, supposedly I want to enter the inventory number that I'm looking for, let's say "2346", and a formula that search throughout the whole table would indicate me that the item (number I look for, is in a range that is located in column 1, row 2, that means shelf one, box 2 in the deposit).
Actually the concept is very simple, excel is able to do MUCH more difficult tasks, and I'm amazed I can't find a way to do this. I'm a photographer and librarian, so my experience in programming is close to zero.
Thank you very much if you can help!
It's a bit of a lenghty one but not hard to understand, I made some sample data like so:
="C"&SUMPRODUCT(((VALUE(LEFT($A$1:$B$3,SEARCH("-",$A$1:$B$3)-1))<=D3)*(VALUE(RIGHT($A$1:$B$3,LEN($A$1:$B$3)-SEARCH("-",$A$1:$B$3)))>=D3))*COLUMN($A$1:$B$3))&", "&"R"&SUMPRODUCT(((VALUE(LEFT($A$1:$B$3,SEARCH("-",$A$1:$B$3)-1))<=D3)*(VALUE(RIGHT($A$1:$B$3,LEN($A$1:$B$3)-SEARCH("-",$A$1:$B$3)))>=D3))*ROW($A$1:$B$3))
Youll just have to change ranges
If you set up your worksheet like the image below (sheet name "Library"):
You could try the code:
Option Explicit
Sub Painting()
Dim LastRow As Long, i As Long, SearchValue As Long
Dim arrData As Variant
'Let s say that all data appears in sheet called Library
With ThisWorkbook.Worksheets("Library")
'Let s say that we are looking for the value in cell H1
SearchValue = .Range("H1").Value
'Find the Last row of column A sheet Library
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
'Create as array from Column A row 2 up to Column D row LastRow
arrData = .Range(.Cells(2, 1), .Cells(LastRow, 4)).Value
'Loop Array to find a match
For i = LBound(arrData) To UBound(arrData)
If arrData(i, 3) <= SearchValue And arrData(i, 4) >= SearchValue Then
'Pop up with Shelf & Box name
MsgBox "Search Value " & SearchValue & " included in:" & vbNewLine & "Shelf: " & arrData(i, 1) & vbNewLine & "Box: " & arrData(i, 2)
'Select the line where the Search Value found
.Range("A" & i + 1 & ":D" & i + 1).Select
'Exit the loop
Exit For
End If
Next i
End With
End Sub
Result:
I have numbers in a column (i.e., 1 to 10 in column A) and a few numbers in another column (i.e six numbers in column E).
I want to place numbers of column E in column B randomly, so that absolute difference between An and Bn is more than my desirable number (D1).
I used RandomSelection function:
Function RandomSelection(aRng As Range)
Dim index As Integer
Randomize
index = Int(aRng.Count * Rnd + 1)
RandomSelection = aRng.Cells(index).Value
End Function
Put this in B2 and copy down:
=AGGREGATE(15,6,$E$2:$E$7/(ABS($E$2:$E$7-A2)>=$D$1),RANDBETWEEN(1,SUMPRODUCT(--(ABS($E$2:$E$7-A2)>=$D$1))))
I changed the numbers in E2:E7 so it would return values that are greater. As stated in the comments. Getting numbers 1-6 to work with 1-10 left many errors as one cannot find a number 1-6 that returns a number greater than 5 with an X of 2-5.
You can accomplish what you want by using RANDBETWEEN and ABS Formulas.
Dim RndmzRng As Range
Set RndmzRng = Range("B2:B21")
Dim AbsValRng As Range
Set AbsValRng = Range("C2:C21")
Dim cel As range
With ActiveSheet
RndmzRng.Formula = "=RANDBETWEEN(1,6)" 'so you don't need data in ColE
'can be use with cell references, "=RANDBETWEEN($E$2,$E$3") where E2=1 and E3=6
AbsValRng.Formula = "=ABS(B2-A2)" 'Absolute formula
For Each cel In AbsValRng 'colors the cells green that are > the value in Range("D1")
If cel.Value > Range("D1").Value Then
cel.Value = cel.Value - Range("D1").Value
End If
Next
End With
Heylo, I am trying to write an excel function that takes a user-selected range and performs different calculations based on the column the cell being populated lines up with. The screenshot below shows the setup of the columns.
I want to set AA5 to be "=myFunction($AA1:$AD4)", and then I want click-and-drag to use the autofill feature to populate AB5, AC5, and AD5 with the same "=myFunction($AA1:$AD4)" but this myFunction will do different things based on which cell is being populated during the autofill.
I know how to do this in a subroutine where the user would select the first open cell AA5, and is prompted for the range to use for calculations. I would do something along the lines of:
Sub CalcCells()
Dim myRange As Range
Set myRange = Application.InputBox("Select the cells you want to use...", Type:=8)
Dim numColumn As Long
For numColumn = 0 To myRange.Columns.Count - 1
Select Case numColumn
Case Is = 0
ActiveCell.Offset(0, numColumn).Formula = "=SUM(" + myRange.Columns(1) + ")"
Case Is = 1
ActiveCell.Offset(0, numColumn).Formula = "=SUMPRODUCT(" + myRange.Columns(1) + "," + myRange.Columns(2) + ")"
Case Is = 2
ActiveCell.Offset(0, numColumn).Formula = "=SUMPRODUCT(" + myRange.Columns(1) + "," + myRange.Columns(3) + ")/SUM(" + myRange.Columns(1) + ")"
Case Is = 3
ActievCell.Offset(0, numColumn).Formula = "=SUMSQ(" + myRange.Columns(4) + ")"
End Select
Next numColumn
End Sub
So basically I want to do exactly this, but I want it to be a function that when I click and drag and autofill AB5:AD5 it knows which column the cell lines up with and performs a calculation based on that, and uses it as an argument/parameter almost. It will not always be 4 rows either, so it needs to be capable of accommodating varying row counts, but the .Columns should work with that as long as the user selects only the same datatype.
Is this possible and how can I do it? Thank you for any help in advance. I've done a lot of searching and I don't know if I'm not searching the right way, but i cannot find anything that really helps.
What about something like this? Basically, you get the column of the cell you enter the formula into with Application.Caller.Column. Then inputRange.Column gives you the leftmost column of your input range. Based on the difference of the two, you know which worksheet function you want to use. If the difference is 0, your formula is entered in the 1st column, so you use Sum. If the difference is 1, you use Sumproduct, and so on.
Function SummarizeCells(inputRange As Range) As Double
Dim col As Long
col = Application.Caller.Column - inputRange.Column
Select Case col
Case 0
SummarizeCells = WorksheetFunction.Sum(inputRange.Columns(1))
Case 1
SummarizeCells = WorksheetFunction.SumProduct(inputRange.Columns(1), inputRange.Columns(2))
Case 2
SummarizeCells = WorksheetFunction.SumProduct(inputRange.Columns(1), inputRange.Columns(3)) / WorksheetFunction.Sum(inputRange.Columns(1))
Case 3
SummarizeCells = WorksheetFunction.SumSq(inputRange.Columns(4))
End Select
End Function
A sample view here:
In Microsoft Excel I want to create a table to be something like in picture below.
I already try using vlookup and index but I can't make it work like I want.
Please help me
Try to use VBA:
Sub TransformTbl()
Dim i As Long, j As Long, cnt As Long
With ActiveSheet
.Range("G1:I1") = Array("Date", "Event", "Place")
cnt = 1
For j = 2 To 4 'column
For i = 2 To 5 'row
If Len(.Cells(i, j)) <> 0 Then
cnt = cnt + 1
.Cells(cnt, 7) = .Cells(1, j) 'Date
.Cells(cnt, 8) = .Cells(i, j) 'Event
.Cells(cnt, 9) = .Cells(i, 1) 'Place
End If
Next i
Next j
End With
End Sub
I wrote a solution and it works fine with me. The formula is really complex and probably hard to understand. Though I'll try my best to explain it, updating the formula may still be a difficult work. All these three formula are written in Array Formula, press ctrl+shift+enter to complete.
Formula in G6:
=IFERROR(OFFSET($A$5,0,SMALL(
IF($B$6:$D$9<>"",1,99999999)*(COLUMN($B$6:$D$9)-1),ROW(A1))),"")
The outer IFERROR keeps your sheet from any #Err. The OFFSET for calling the right date. The formula inside SMALL generate an array with the rule: If there is an event, the value will be the number of the date for offset, otherwise, it will be 99999999 which giving the OFFSET an error and be blocked by IFERROR. With the data you gave, the array will be
{ 1,99999999, 3;
1, 2,99999999;
1,99999999,99999999;
99999999,99999999, 3 }
Formula in H6:
=IFERROR(OFFSET($A$5,
SMALL(IF($B$6:$D$9<>"",ROW($B$6:$D$9)-5)*
IF(COLUMN($B$6:$D$9)=MATCH(G6,$B$5:$D$5,0)+1,1,99999999),99999999),COUNTIF($G$6:G6,G6)),
MATCH(G6,$B$5:$D$5,0)),"")
The IFERROR and OFFSET works the same as G6. The formula in OFFSET.ROW generate nearly the same array as G6. This time the value is the row of event with the date determined by column G. Other gives 999999999 or more.
Formula in I6:
=IFERROR(OFFSET($A$5,MAX((ROW($B$6:$D$9)-5)*($B$6:$D$9=H6)*
(COLUMN($B$6:$D$9)=MATCH(G6,$B$5:$D$5,0)+1)),0),"")
IFERROR and OFFSET are still the same. And this time only the event which matches the date and the name of itself has a value, other remains 0.
Finally, I apologize for the poor readability. Wish someone can help me out with this :]
I have to average sets of 3 columns.
EXAMPLE:
Blood_Patient1_0_R1, Blood_Patient1_0_R2, Blood_Patient1_0_R3
There average is in a new column Blood_Patient1_0
Similarly, Blood_Patient1_3_5_R1, Blood_Patient1_3_5_R2, Blood_Patient1_3_5_R3
The average is in a new column Blood_Patient1_3_5
This process is being repeated for 8 such sets of columns.
Currently I am averaging using the formula: IF(ISERROR(AVERAGE(B7:D7)),"",AVERAGE(B7:D7)) and auto-filling 21,000 plus rows.
Since there is a pattern in column headings, I was thinking to automate the whole process.
This is what I have thought so far in terms of algorithm:
0, 3_5, 6_25 are time values in column headers.
at each time instant, there are 3 replicates R1, R2,R3 as part of column headers
for time array [3.5h, 6.25h, 9.5h, 11.5h, 16.5h, 25h, 49h, and 156h
]
create a new column
for rows from 2 to 21458
average over replicates from R1 to R3 using above formula
I do not know how to write this in excel. Any help would be appreciated.
Give this a go.
This solution assumes that you have a continuous data set, that is, no gaps between the columns you wish to search through.
Firstly, you will need to include this function. Paste it into the same module as the subroutine. The purpose of this function is to allow the string in each heading to be compared against an array of substrings, as opposed to the single substring permitted by the InStr function.
Function Time_Search(strCheck As String, ParamArray anyOf()) As Boolean
Dim item As Long
For item = 0 To UBound(anyOf)
If InStr(1, strCheck, anyOf(item)) <> 0 Then
Time_Search = True
Exit Function
End If
Next
End Function
Next, paste in this subroutine. I have assummed that the dataset begins at cell A1. Also, I have allowed for a dynamic range, should the number of columns or rows ever change.
Sub Insert_Average_Columns()
Dim HeaderRange As Range
Dim LastRow As Long
Dim c As Range
Set HeaderRange = Range(Range("A1"), Range("A1").End(xlToRight))
LastRow = Range("A" & Rows.Count).End(xlUp).Row
For Each c In HeaderRange.Cells
If Right(c.Value, 2) = "R3" Then
If Time_Search(c.Value, "3_5", "6_25", "9_5", "11_5", "16_5", "25", "49", "156") Then
c.Offset(0, 1).EntireColumn.Insert
c.Offset(0, 1) = "Average of " & Left(c.Value, Len(c.Value) - 3)
c.Offset(1, 1).FormulaR1C1 = "=IFERROR(AVERAGE(RC[-3]:RC[-1]),"""")"
c.Offset(1, 1).AutoFill Range(c.Offset(1, 1).Address, Cells(LastRow, c.Offset(1, 1).Column))
End If
End If
Next c
End Sub
There is one issue with your data. If you want the procedure to insert an average column for T = 25, then it will do so for all columns where T contains the string "25". If there are T= 8.25, 10.25, 15.25, etc, these will all have averages applied. The only way around it would be to include more of the heading string in the parameter array, but I presume you will be dealing with a variable Blood_Patient ID so that probably isn't an option.