I have an Excel Sheet that I need to conditionally format so I can tell how close numbers in the cells are to the midpoint of a range. These are the rules:
Blanks = WHITE
Values outside of my desired range (Rows B and C) = RED
Values inside of my desired range will scale with the midpoint = GREEN and the outer points = YELLOW
Format Rules
If I make a separate condition on every row, it is CORRECT and looks like this:
Correct
But that would take an insane amount of time to create rules for every row.
If I make the following formula to try to speed things up, it calculates correctly for the first row and then incorrectly for the remaining rows (only using the numbers from the first row).
3-Color Scale Example:
Minimum =INDIRECT("B"&RIGHT(ADDRESS(ROW(),COLUMN(),4,1),LEN(ROW())))
Midpoint =(INDIRECT("B"&RIGHT(ADDRESS(ROW(),COLUMN(),4,1),LEN(ROW())))+INDIRECT("C"&RIGHT(ADDRESS(ROW(),COLUMN(),4,1),LEN(ROW()))))/2
Maximum =INDIRECT("C"&RIGHT(ADDRESS(ROW(),COLUMN(),4,1),LEN(ROW())))
Incorrect:
Color scales don't accept relative references in the value formulas. You'll have to bite the bullet and use absolute references and adjust the row number for each row.
Related
I think I made a breakthrough with "ultra-dynamic" ranges. That's how I call them because not only they are dynamic; but also they refer to different ranges based on the cell address in which they are written in! Now I need to advance this breakthrough even further. Those of you using dynamic ranges in Excel, especially the dynamic-range-gurus, will be thrilled to read below and can possibly help in this advancement:
Disclaimer: If you are not familiar with dynamic ranges do not attempt to read below!
Background:
Our sheet has cells with calculations on top and a pivot table below.
Each cell above refers to the pivot table cells below in the same column.
The first column of the pivot table (titled "Row Labels" by default) is sorted from top to bottom in descending order. Each of the next columns has the result of a different test.
At one point somewhere in the middle rows of the pivot table there is a "marker line" that separates the top part of the pivot from the bottom one.
Let's call the top part "Uppers" and the bottom part "Downers".
Let's call both parts together "Population". Population is a non-contiguous range because the "marker line" that separates the Uppers from the Downers intervenes.
For each cell above the pivot there are calculations for the pivot column exactly below that need to refer to the Uppers or Downers or Population of the column itself.
Previously, my formulas in all of the cells above were a repetition of something like this below:
= MAX( OFFSET($A$79,$B$5+1,COLUMN()-1,$B$6,1) )
This example gives the maximum of the area of the Downers in the same column below.
Where:
A79 is the top left corner of the pivot table,
B5 has the row number of the marker line (relative to A79) to signify that our column's Downers area starts from the first row below that marker row (hence the "+1"). The formula of that cell has an XMATCH formula to produce the resulting row number. For example if the Uppers are positive numbers and the Downers are negative numbers, all sorted in descending order, the XMATCH is searching for the 0 row that separates the two parts of the population.
COLUMN()-1 returns the current column's number for offsetting to the right and the -1 is necessary because the first column is 0 rather than 1 offset to the right, and
B6 has the number of rows ("height") to the last row number of the pivot (relative to B5) where our Downers end. The cell contains the usual COUNTA function that counts the number of rows in the pivot table and from this number it subtracts the number of the marker row in B5 to get the "height" of the Downers range.
The OFFSET... part of the formula when copied to any cell with calculations above the pivot will always give the Downer's area in the same column.
And here we come to the "ultra"-dynamic part: I tested (and it works!) naming a range as:
ColDowners: =OFFSET($A$79,$B$5+1,COLUMN()-1,$B$6,1)
And I substituted all the cells with calculations that refer to the Downers with something like:
= MAX( ColDowners )
Miraculously, all cells with this named ultra-dynamic range, are calculated with the correct values for the Downers exactly below them in the same column! Sometimes when the Workbook is initially loaded, the cells appear with 0 values, but immediately when you hit F9 to Calculate they get the correct value (which of course is not a problem).
So this range is "dynamic" in two ways: (1) because start and end rows are dynamic (as usual) and (2) because it results to a different range depending on where it's written!!
And now for the advancement. Any dynamic-range-guru's input would be extremely valuable:
OFFSET is a volatile function with the known performance issues. Can we replace it with two non-volatile INDEX functions separated by a colon (":")? I know how to name a range that starts from a specific cell and ends in a different one every time (eg. =A$155:INDEX(...COLUMN()...)). But can BOTH the start and end of the range be INDEXified [sic]? i.e. can it be something like =INDEX(...COLUMN()...):INDEX(...COLUMN()...). And, consequently, if we name a range with this formula, will it work?
Answers will have to exclude volatile functions like INDIRECT and will have to be as simple as possible. The resulting range of the formula of the ultra-dynamic range will have to be different depending on which COLUMN() it's written in in the sheet (like the OFFSET one above) and will have to be "able" to start from a specific number of rows below A79 (the number written in B5 in the example above) and end in the one written in B6.
The correct formula that defines an ultra-dynamic-range for replacing the 'OFFSET' formula:
=OFFSET($A$79,$B$5+1,COLUMN()-1,$B$6,1)
Is:
=INDEX($A:$XX,ROW($A$79)+$B$5+1,COLUMN()):INDEX($A:$XX,ROW($A$79)+$B$7,COLUMN())
Where in B7 is the number of the last row of the pivot. (=Something like B5+B6 plus/minus 1 or 2 - test it for your case)
If you Define a Name of a Dynamic Range with this ultra-dynamic formula, it will adapt to give you different ranges depending on the location of the cell where you copied it to!! It will always give you the same parallel range in your column and will produce different results in different columns! I tested it and it works perfectly, plus it made my calculations lightning faster since INDEX is non-volatile (as opposed to OFFSET).
One more tip for the example above: I also tried nested range names and they work! For example I Defined the Range for ColPopulation as:
=(ColUppers,ColDowners)
Note that this is an ultra-dynamic-nested-range-name! Of course, it can work only for simple functions (such as =MAX(ColPopulation)) and will not work in functions such as SUMPRODUCT that need contiguous ranges. Still, it is a very useful thing to know that you can Define Ranges by adding other range names with commas!
Great help from all involved! Thanks a lot!
I am looking to check the combined widths of each column on various sheets with the intent of making the total print area widths match across all sheets in the workbook. When I enter =CELL("Width", A1) into a cell I get the width in points (rounded, but good enough for what I'm doing), but then it also fills the next cell to the right with "FALSE". This is annoying, since I would like to be able to simply drag the formula across all the columns that I want to check and then sum them. I know how to work around the issue so I can drag it vertically instead, but just wondering if there is a way to alter this behavior so I don't have to?
Also - bonus points if anyone can tell me what the secondary cell is there for in the first place.
The documentation is helpful here:
"width": Returns an array with 2 items.
The 1st item in the array is the column width of the cell, rounded off to an integer. Each unit of column width is equal to the width of one character in the default font size.
The 2nd item in the array is a Boolean value, the value is TRUE if the column width is the default or FALSE if the width has been explicitly set by the user.
If you only want the 1st item in the array, you can use INDEX:
=INDEX(CELL("width",A1),1)
If by "secondary cell" you mean the one to the right with FALSE, you are seeing Excel's new spill functionality.
Excel formulas that return multiple values, also known as an array, return results to neighboring cells. This behavior is called spilling.
Based on your version of Excel, you're seeing the full array result of CELL.
EDIT:
A better way to do this is to use the implicit intersection operator # to return the first value of the array:
=#CELL("width",A1)
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.
i have some data in excel 2007 and draw a line chart with them, so i have two series: one for data and a series for average to compare data with average. now i want to add a fix value for series 2(average) to draw average line in chart.
series 2(average) value ={Sheet3!$I$18,Sheet3!$I$18,Sheet3!$I$18}
the average value is in i18 cell
but it has error about "the formula you typed contains an Error"
any body to help me to draw average line?
my data are in d24:d26 cells
and average is in i18
if i use const number it's working like below:
series 2(average) value ={5003,5003,5003}
but i want read the series value from cells, which on change the average number(i18 cell) the charge series(average line) change too.
In cell G24 enter
=$I$18
Copy to cells G25 and G26.
Now select cells G24 to G26 and copy. Select the chart and use Paste Special. Accept the defaults. The chart now has the average line.
By definition, a line needs at least two data points, beginning and end. You could leave cell G25 empty, but then you must tell Excel to connect the line between empty cells. That setting is in the Select Data dialog behind the button "Hidden and empty cells". With that approach you can avoid duplicating the average value for each data point.
Here is a screenshot with such a setup.
Edit: It can be done with just one cell but it's a lot more preparation.
Add the single cell to the chart as a new series.
Change that series to XY Scatter
Edit the series values, set X to 1, set Y to the cell value
add horizontal error bars to the average series, with settings being Plus, No Cap, Fixed value (count the number of data points in the line and enter that as the fixed value)
format the error bar line as desired and format the data marker to be invisible. Here is how this can look:
I have this chart in which if any point in graphs exceeds specific limit then its color should change.
can anyone suggest me how to get the chart in VBA and then apply this kind of condition e.g i want to change the color of highest point in the above graph . Any help would be highly appreciated.
Using: ActiveWorkbook.Sheets("Sheet1").ChartObjects("Chart1").Chart.SeriesCollection(1)
Color of each point is .Points(PointNumber).Interior.Color
The number of points you have to cycle though is .Points.Count
The value of each point is .Points(PointNumber).Value
colors of the markers themselves (Applies only to line, scatter, and radar charts):
.Points(PointNumber).MarkerBackgroundColor = RGB(0,255,0) ' green
.Points(PointNumber).MarkerForegroundColor = RGB(255,0,0) ' red
.Points(PointNumber).MarkerStyle = xlMarkerStyleCircle ' change the shape
Let's take another approach, which does not require any code.
Assume your data is in columns A (sequence number or time) and B value, starting in A2 and B2, since your labels are in A1 and B1. We'll add a series to the chart that includes any deviant values from column B. This series will draw a marker in front of any deviant points so the original point will still be present, and instead of reformatting this point the new series displays a point.
In cell C1, enter "Deviant".
In Cell C2, enter a formula that detects a deviant point, something like:
=IF(AND(B2>upperlimit,B2
This puts the value into column C if column B exceeds upper and lower limits, otherwise it puts #N/A into column C, #N/A will not result in a plotted point.
Copy the data in column C, select the chart, and Paste Special as a new series. Format this series to have no line and whatever glaring marker you want to use to indicate an out of control point.