I have 3 columns with percentages.
I would like to put an up or down arrow in the same cell as each percentage depending on the previous percentage.
ex: H10 = 54, L10 = 55, P10 = 50
I'd like L10 to read 55 with an up arrow and P10 to read 50 with a down arrow. Then I want to copy this formula down to the 500th rows for columns L and P.
I was able to create this for 1 row (H10, L10 and P10), but when I tried to copy it down to the other rows, it continued to reference the first row (H10, L10 and P10), . I tried to remove the "$" absolute reference and got an error message saying I cannot use relative references. How can I copy this formatting all the way down.
The fields I am using (row H, row L, row P):
Here's what I did to get around this:
I added another cell and calculated the difference between the rows, then set the formula to evaluate if the difference was negative or positive (greater than or less than 0), if it was positive there is an up arrow and if negative there is a down arrow. I made the new row small enough that only the arrow shows and the number doesn't, and I don't have borders on the two rows (the one with the number and the one with the formula) so it looks like the additional row is actually part of the row that has the true value (not the calculation).
There is one way I can think of to get a relative reference while only using what "looks like" an absolute reference.
= $A1
returns the same thing as:
= OFFSET($A$1,ROW()-ROW($A$1),0)
Notice that the formula above uses only absolute references but effectively returns a relative reference.
Try using this method to see if it will work in your case.
Related
I have a sheet that have Measure in meters, Value, and Distance columns (see attached screenshot). The Distance simply returns the difference between each row of the Measure column.
What I want to do is every time the Distance is greater than 10m (which I've used conditional formatting to highlight green), return in column E the measure values from the previous row up to the previous green cell, kind of like grouping them and displaying as a range. Then also return the min and max Value within that range of rows (probably in column F & G).
Ex. E6 would return something like "148000-148040" in text format, E16 would be "148090-148180", E17 would just be "148200". Then F6 = -91.09, G6 = -43.91, F16 = 15.49, G16 = 138.06 and so on.
Not sure if this would require VBA, but if it can be done with formulas that'd be great.
Sorry if this is confusing or if a similar question has been asked before.
Thank you!
I think this demonstrates the power of the new (ish) Xlookup very well (in this case, using backwards search):
For the range:
=IF(D3=10,"",XLOOKUP(TRUE,D2:D$2>10,B2:B$2,B$2,0,-1)&"-"&B2)
Min:
=IF(D3=10,"",MIN(XLOOKUP(TRUE,D2:D$2>10,C2:C$2,C$2,0,-1):C2))
Max:
=IF(D3=10,"",MAX(XLOOKUP(TRUE,D2:D$2>10,C2:C$2,C$2,0,-1):C2))
I have a small data set of 2 columns and several rows (columns A and B)
I want to return each instance of codeblk 3 in a formula that is elsewhere in my sheet, (so a vlookup is out as it only shows the first instance) if it does not appear then a message to say its not there should come up.
I have the formula partially working but i cant see the reason why its not displaying the values.
My formula is as below:
This is an array
{=IF(ISERROR(INDEX($A$55:$B$70,SMALL(IF($B$55:$B$70=3,ROW($B$55:$B$70)),ROW(1:1))-1,1)),"No value's produced",INDEX($A$2:$C$7,SMALL(IF($B$55:$B$70=3,ROW($B$55:$B$70)),ROW(1:1))-1,1))}
The result that shows up is only "No values produced" but it should reflect statement B, C and D in 3 separate cells (when changing ROW(1:1), ROW(2:2) etc)
{=SMALL(IF($B$56:$B$69=4,ROW($B$56:$B$69)),ROW(1:1))} - This produces the result 68 which is the correct row.
Any ideas?
Thanks,
This is an array formula - Validate the formula with Ctrl+Shift+Enter while still in the formula bar
=IFERROR(INDEX($A$55:$B$70,SMALL(IF($B$55:$B$70=3,ROW($B$55:$B$70)-54),ROW(1:1)),1),"No value's produced")
The issue you are facing is that your index starts it's first row on $B$55, you need to offset the row numbers in the array to reflect this. For example, the INDEX contains 16 rows but if you had a match on the first row you are asking for the 55th row from that INDEX(), it just can't fulfil that.
EDIT
The offset was out of sync as your original formula included another -1 outside of the IF(), I also left an additional bracket in play (the formula above has now been edited)
The ROW() function will essentially translate $B$55:$B$70 into ROW(55:70) which will produce the array {55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70} so the offset is needed to translate those row numbers in to the position they represent in the indexed data of INDEX().
The other IF() statement then produces and array of {FALSE;2;3;4;FALSE etc.
You can see these results by highlighting parts of the formula in the formula bar and hitting F9 to calculate.
have a table that i would like it to select the smallest size picture frame that could be used based on the size values,
basically return the smallest frame that would fit the image.
For example i have 4 standard sizes:
a b c
Size1 150 150
Size2 300 300
Size3 540 570
Size4 800 800
I want to have a size in another cell e.g. 290 x 300 and would like it to pick the smallest size possible to fit i.e. in this case size2.
I've followed a few guides and have the following that will print out the value if the values are exact but not if they are slightly under one of the options
=VLOOKUP($A$8,CHOOSE({1,2},$B$2:$B$5&", "&$A$2:$A$5,$C$2:$C$5),2,0)
Any helo / direction would be much appreactiated!
Thanks
Assuming order does matter (e.g. there is a difference between 500x550 and 550x500), you can use this array formula:
= INDEX($A$2:$A$5,MATCH(2,MMULT((E2:F2<=$B$2:$C$5)+0,{1;1}),0))
Note this is an array formula, so you must press Ctrl+Shift+Enter after typing this formula rather than just pressing Enter.
See below for working example.
Assuming order does not matter (e.g. there is not a difference between 500x550 and 550x500), the formula gets considerably longer because of reversing the order of the E2:F2 array. There is possibly a better way to do this but this is the easiest way I can think of to do it. Unfortunately Excel has no way of handling 3D arrays, otherwise this would be not much different from the original formula above. Anyway, here is the formula (line breaks added for readability)
= INDEX($A$2:$A$5,MIN(MATCH(2,MMULT((E2:F2<=$B$2:$C$5)+0,{1;1}),0),
MATCH(2,MMULT((INDEX(E2:F2,N(IF({1},MAX(COLUMN(E2:F2))-
COLUMN(E2:F2)+1)))<=$B$2:$C$5)+0,{1;1}),0)))
Note this is also an array formula.
See below, working example. Note how it yields the same result as above in every cell except cell G4, since again this is considering 550x500 and 500x550.
It is not clear what is in cell A8. Going by your question, I assume it must be dimensions in the format "W x H" (example: 290 x 300). If so, try:
In D2: 1
// Copy next down
In D3: D2+1
// Wherever you want it
=CONCATENATE("Size ",MIN(VLOOKUP(LEFT(A8,FIND(" ",A8)-1)+0,B2:D5,3,TRUE),VLOOKUP(RIGHT(A8,LEN(A8)-FIND("x ",A8)-1)+0,C2:D5,2,TRUE)))
Alternatively, if you split the width and height into 2 cells A8 and B8, this simpler version should do the trick:
In D2: 1
// Copy next down
In D3: D2+1
//Wherever you want it
=CONCATENATE("Size ",MIN(VLOOKUP(A8,B2:D5,3,TRUE),VLOOKUP(B8,C2:D5,2,TRUE)))
These assume the sizes all use a "Size #" naming convention. If otherwise, you could add another column at the right to equal column A, then use vlookup to identify the match, like this (again assumes "W x H" in cell A8):
In D2: 1
// Copy next down
In D3: D2+1
// Copy next down
In E2: =A2
// Wherever you want it
=VLOOKUP(MIN(VLOOKUP(LEFT(A8,FIND(" ",A8)-1)+0,B2:D5,3,TRUE),VLOOKUP(RIGHT(A8,LEN(A8)-FIND("x ",A8)-1)+0,C2:D5,2,TRUE)),D2:E5,2,FALSE)
I have a range of value (say H6:H20) containing values "g","y" or "r".
In order to count each status and use that as the source of a donut chart, I made a range of 3 cells calculating =COUNTIF($H$6:$H$20,"Green") etc...
Then I tried to be more elegant and create a single array formula returning the count for each letter, that I could eventually use as the source of my chart, without having intermediry calculation range. But I can't get this working.
Input:
g
r
y
g
g
r
g
g
y
Expected output (with a single array formula):
5
2
2
My try: =COUNTIF({"g","y","r"},$H$6:$H$20) -> error
Other try: =SUMPRODUCT(1*$H$6:$H$20={"g","y","r"}) -> error
(both entered in a 3 cells range with Ctrl+Shift+Enter, of course)
What is the right formula ?
You don't need an array formula, though you do need to store that formula as a Defined Name within Name Manager, e.g.:
Name: Series_Values
Refers to: =COUNTIF(Sheet1!$H$6:$H$20,{"g","y","r"})
Change the sheet name (Sheet1 here) as required.
You can then add a series to a chart with the following syntax for the Series values entry:
='Sheet1'!Series_Values
Again, amend the sheet name as required, though be sure to retain the exclamation mark and apostrophes (the latter are not strictly necessary if the worksheet name contains no spacing, though in any case it is good practice).
Excel will actually amend this to:
=Book1!Series_Values
(where Book1 is the assumed workbook name), though this is not important here.
Regards
That's what FREQUENCY function is for. Select 3 cells and CTRL+SHIFT+ENTER following formula:
=FREQUENCY(MATCH($H$6:$H$20,{"g","y","r"},0),MATCH($H$6:$H$20,{"g","y","r"},0))
Assuming this isn't dynamic, and you have a definite amount of rows, you can use the following. Let's say you're putting this formula in row 20:
=COUNTIF($A$1:$A$9,INDEX({"g","r","y"},ABS(20-(ROW()+1))))
and drag down.
Edit: If you want in the same cell, just combine COUNTIF()?
=COUNTIF($A$1:$A$9,"g")&","&COUNTIF($A$1:$A$9,"r")&","&COUNTIF($A$1:$A$9,"y")
=IF({"g","y","r"}="g",COUNTIF($H$6:$H$20,"g"),IF({"g","y","r"}="y",COUNTIF($H$6:$H$20,"y"),IF({"g","y","r"}="r",COUNTIF($H$6:$H$20,"r"))))
long solution as I don't have time to make a more elegant one. You can see the array object with F9 in the formula bar.
As seen in the picture I have 5 sets of 2's in one column.
I would like it so that each set is in its own column.
Is there a way to do that?
I tried text to columns, but it did not work.
General solution
Imagine I have a vertical array starting in cell B2, which I want to separate into N stacked columns. I will place these columns from cell E4, as the picture indicates.
The code which achieves what I want is:
+OFFSET($B$2,(ROW()-ROW($E$4))*N+(COLUMN()-COLUMN($E$4)),0)
Replace N with your desired number (and the origin and destination cell with your particular values, B2 and E4 in this example), and expand the formula vertically and horizontally to form your desired matrix of N columns. For the case of N=3, you get:
(PS: if your array is horizontal, use transpose to transform to vertical. You can then transpose the resulting matrix, to get the final result.)
Explanation
The logic is simple. The function OFFSET has three compulsory inputs. The first one is the first point of your array you want to transform (in the example above, $B$2. The point you select has an index of 0, the one below an index of 1, etc. So, what you want is to put these ordered index into a matrix form, as shown below (for the case of N=3):
The rule to move these indexes is given in the second entry of the OFFSET function. This is basically a formula that calculates a sequence 0, 1, 2, 3 ... using some fixed values (the number of the row and columns of the first cell where you are putting the result, ROW($E$4) and COLUMN($E$4), which are equal to 4 and 5 respectively), and the variable values of the cell where you are placing the number (ROW() and COLUMN()). The formula computes the difference between actual row and reference row number, scale it by N, and adds any difference between actual and reference column. This formula gives the desired series 0, 1, 2, 3... for our desired output matrix.
Finally, the last item of OFFSET is equal to zero, since we are transforming with a vertical column of data, so no horizontal offset is needed.
You can do it with e.g. formula; enter this to C1 and fill down and right:
=OFFSET($A$1,ROW()-1+(COLUMN()-3)*6,0)
Take the total cells, dived it by 3 and cut and paste. I wasted a 30 mins trying all the solutions offered out there.
I gave up and now my project is complete. Only took about 15 seconds.
To split one column into multiple columns with column first order, in other words, without transpose, we can modify the formula as shown in https://www.extendoffice.com/documents/excel/3132-excel-convert-vector-to-matrix.html, which is the solution for row first order, i.e., with transpose, exchange the roles of ROW() and COLUMN(), example code:
=OFFSET($A$1:$A$10494,ROW()-ROW($B$1)+((COLUMN()-COLUMN($B$1))*(ROWS($A$1:$A$10494)/18)),0,1,1)
Here $a1:$a$10494 is source, $b$1 is destination, 18 is columns numbers to split into.
This can be used to get back the table structure of %debug print output in pdb, for example, which will split the output into narrow bands.