How to convert a range of arbitrary size, to it's string representation, to be later used using INDIRECT ?
ADDRESS only works for a single cell.
No scripting please :)
Only formulas.
EDIT 1 ;
Also assume the range is computed through a complex formula. So no cell addresses are available.
EDIT 2 ;
=ArrayFormula(IF((OFFSET(INDIRECT(PayStaff),0,10)>PayrollStart)*(OFFSET(INDIRECT(PayStaff),0,10)<=PayrollEnd),(OFFSET(INDIRECT(PayStaff),0,10)-PayrollStart),0)+IF((OFFSET(INDIRECT(PayStaff),0,11)>=PayrollStart)*(OFFSET(INDIRECT(PayStaff),0,11)<PayrollEnd),(PayrollEnd-OFFSET(INDIRECT(PayStaff),0,11)),0))
No sample sheet as this is a hypothetical type question.
Above is an actual formula I'm using, one of many in my efforts at fully automation. At any time, the range string in "PayStaff" can change, coupled with repeated but identical OFFSET calls, soon makes the formula unreadable. One of my ideas to solve the readability is to get the range-string of (eg: OFFSET(INDIRECT(PayStaff),0,10) ) and reuse it, shortening the formula and increasing readability. Also note, the example does NOT have size increase of range which I require as well.
But lets suppose that PayStaff = "A1:A10", where the number of rows can vary. Considering that OFFSET has 4 parameters, how to get the resultant range as a string? Is this possible?
I just used this to do something similar, hope this helps:
// <range here> = is the range you want to describe,
// can be output of some other formula but has to be a
// rectangle for this to work.
// Remove // comments and line breaks before pasting to sheet.
// concatenate top left corner with colon and bottom right corner.
=CONCATENATE(
// use address to get top left corner
ADDRESS(ROW(<range here>), COLUMN(<range here>)),
":",
// use address to get bottom right corner
ADDRESS(
ROW(<range here>)+ROWS(<range here>)-1,
COLUMN(<range here>)+COLUMNS(<range here>)-1
)
)
This would give you the start of the range as a string:
=cell("Address",OFFSET(INDIRECT(PayStaff),0,10))
The end of the range is more awkward - you would have to add the number of rows in the range (-1) to the row offset:
=cell("Address",OFFSET(INDIRECT(PayStaff),rows(indirect(PayStaff))-1,10))
Related
Here's how it looks.
Hi. I'll try to be as specific as possible about this :)
I'm making a Google Sheet page similarly to a game character progression, that will automatically fill up based on data from other sheets: specifically, these "EXP" bars fill up with values based on the hidden cell A5.
For instance, the cells from D5 to BA5 represent LV1.
As the function shows, every time the value in A5 reaches an even number (for LV1, it's all even numbers from 2 to 100), one of the slots will fill up with a number, that with conditional formatting, will change the color of the cell and make it look like an actual exp bar filling up.
I'm using the function =COUNTIF(A5,">=2") and manually changing it to ">=4", ">=6" etc until ">=100" for the first bar. The second bar will have its 50 cells with all even numbers from ">=102" to ">=200".
So, to get to the question: is there an array formula that facilitates the process of filling a great amount of these bars with functions, without changing them all manually? Even automating *some *of this process would be great. Besides it being tedious, it leaves a lot of room for human error.
Thank you in advance to whoever's got an answer.
P
I haven't tried much as at the moment I am very confused by the vast amount of options array formulas provide. I have 48h of experience in the matter.
I suggest you to use the values of columns and rows here as helpers to do calculations. If you know that every column adds 2 and every row adds 100 you can set a formula like this for the whole range (select the whole range and add just one rule of conditional formatting):
=$A$5>((Column(D5)-3)*2+(Row(D5)-5)*100))
You use $symbol to make A5 steady and D5 value will "move" to each cell for conditional formatting, so you don't have to make an ARRAYFORMULA for this
I am formatting a column in a way that the 2 lowest values are painted green, with the custom formula:
=K6<SMALL($K$6:$K$44; 3)
From my understanding this takes the third lowest value and paints the ones beneath that (the two lowest) green.
This worked fine until, today we had value 168, 169.5 169.5 and values above that. It only colored 168 as green although, 169.5 is the 2nd lowest value. Why does it not mark all 3 green?
Is there a way I can easily fix this ? So that it always marks the 2 lowest values, even if there are multiple of them.
You asked for conditional formatting that:
...always marks the 2 lowest values, even if there are multiple of them.
Try the following formula
=OR(K6=MIN(SORTN($K$6:$K$44,2,2,1,1)),K6=MAX(SORTN($K$6:$K$44,2,2,1,1)))
(Do adjust the formula according to your ranges and locale)
Try rank(), like this:
=rank(K6; unique(K$6:K$44); true) <= 2
I am need to calculate the dimensions from cell values that are entered as strings into a single cell vs. 3 separate cells and I do not want to break the dimensions into Length (L) x Width (W) x Height (H) Columns.. instead I am hoping there is a relatively simple function that would allow me to calculate the total cubic dimensions from that single cell.
I am aware of this tutorial that can take a string and be used to break it into 3 separate cells.. but that defeats the point of what I am trying to do.
My data looks like this:
Dimensions
Cub/In.
CF
70x13x13
11830
6.85
24*18*13
5616
3.25
24x16x12
16x24x10
Right now the data is entered as either "LxWxH" or "L*W*H" in that text formant and the columns that have values like the 5616 above are me manually re-entering "=24*18*13".. literally one character difference.
I did try a CONCATENATE to just append an "=" to the beginning but got errors on all in Google Sheets (for comparison) or a Literal string into processed as a formula in Excel.
=CONCATENATE(“=”,B1)
Looking for a simple way to do this calculation in a single column and being able to have to enter the data once or utilize the existing data. I don't mind doing a single bulk replace of "x" to "*" on the input column to standardize the source column but don't want to have to do a series of bulk replaces every time I want to run through the data.
Thoughts?
Use SUBSTITUTE to get them all to the same, then use SPLIT and wrap in PRODUCT:
=PRODUCT(SPLIT(SUBSTITUTE(A2,"*","x"),"x"))
Or shorter Version shown by #JvdV:
=PRODUCT(SPLIT(A2,"*x"))
I'm trying to count the number of empty cells that exist in a column between each non-empty cell but haven't been able to work out how.
Using this, I'm also trying to find the largest "empty distances" and locate the cell in the center of these distances.
The sheet I'm working with lists a set of marker colors and denotes the ones that are owned out of the full set of colors. I'm trying to find the largest ranges of missing colors and then find the colors in the middle of those ranges in order to find a handful of markers that would best help to fill out the spectrum.
Columns 1-6 are information- Column 7 marks whether the color is owned:
I may have an answer that helps you.
I could only get it to work using a helper column, but someone may know how to eliminate that requirement.
The helper column creates an array, basically listing the row numbers of the rows that have an "x" in your column B.
The main formula then measures the gap between each of these listed row numbers. It also checks the gap before the first "x", and after the last "x". Note that I have the data starting on row 2, which complicates the formula, but makes the sample sheet clearer - this can easily be changed to row 1 if you prefer.
={F2-1;
query(ArrayFormula(if(isnumber(F3:F),F3:F-F2:F-1,"")),
"select Col1 where Col1 > 0",0);
counta(A2:A)-indirect("F"&COUNTA(F$2:F))}
See a sample sheet here:
https://docs.google.com/spreadsheets/d/19QUFGRqTT6BqOsBrEBpTIxQCeNdRa5mzXhxQpCZ8sV4/edit?usp=sharing
Then I used a second formula to calculate the max gap between "x"s, (or before the first or after the last x).
Note that calculating the midpoint of the gaps, and doing a lookup of the corresponding mid-point colour, is something that can be added to this answer, if you share a sample copy of your sheet and share it for editing.
Let me know if this helps. I'll add more explanation to describe what the formula is doing tomorrow.
And I'll provide a second tab with the formulas adjusted to work with data beginning on row 1.
You can also get the lengths of the gaps using Frequency:
=ArrayFormula(frequency(if((B1:B20<>"X")*(A1:A20<>""),row(B1:B20)),if((B1:B20="X")*(A1:A20<>""),row(B1:B20))))
but finding the centres of the gaps and allowing for equal-sized gaps is more difficult.
This should find the position of the "X" at the end of the longest gap:
=ArrayFormula(
sum(frequency(if((B1:B20<>"X")*(A1:A20<>""),row(B1:B20)),
if((B1:B20="X")*(A1:A20<>""),row(B1:B20)))*(sequence(countif(B1:B20,"X")+1,1)<=
match(max(frequency(if((B1:B20<>"X")*(A1:A20<>""),row(B1:B20)),
if((B1:B20="X")*(A1:A20<>""),row(B1:B20)))),frequency(if((B1:B20<>"X")*(A1:A20<>""),row(B1:B20)),
if((B1:B20="X")*(A1:A20<>""),row(B1:B20))),0)))+
countif(sequence(countif(B1:B20,"X")+1,1),"<="&
match(max(frequency(if((B1:B20<>"X")*(A1:A20<>""),row(B1:B20)),
if((B1:B20="X")*(A1:A20<>""),row(B1:B20)))),frequency(if((B1:B20<>"X")*(A1:A20<>""),row(B1:B20)),
if((B1:B20="X")*(A1:A20<>""),row(B1:B20))),0))
)
and then it should just be a case of working backwards from there to the centre of the longest gap. However the formula needs further refinement to deal with the cases
(1) Where the longest gap is after the last "X"
(2) Where there is a tie for the longest gap
(3) Where there is a need to list the longest, second longest, third longest gap etc.
Is there a way to delete empty cells in a given range and shift the column up to the desired display as shown below? Closest I came was
=ARRAYFORMULA({A1:C1; TRANSPOSE(SPLIT(TRANSPOSE(QUERY(A2:C,,999^99)), " "))})
which removes empty cells, but splits the first names and surnames into separate cells, which I have not figured out how to avoid. Pfa a made-up sample of current and desired displays:
Current Display
Desired Display
I'm new at this, but I came up with a bit of a brute force method, which may help you.
={
{(A1:C1)};
{FILTER(A2:A100,A2:A100<>"");indirect("N1:N" & 100-counta(A2:A100))},
{FILTER(B2:B100,B2:B100<>"");indirect("N1:N" & 100-counta(B2:B100))},
{FILTER(C2:C100,C2:C100<>"");indirect("N1:N" & 100-counta(C2:C100))}}
Assuming your data block is in columns A1:C100, this formula filters blank cells from each individual column, and then pads each column with blank cells at the bottom, to make the three arrays equal in length/dimension.
Note that in "100-counta(...", the 100 is the expected maximum length of your data column.
This could be calculated, and must be the same for all three columns.
Note also that the first array is horizontal (ends with a semi-colon), followed by the three columns, stacked beside each other (ends with a comma).
Here is a working example.
https://docs.google.com/spreadsheets/d/1MGaqqGrkmIliuAzEqxPtdEVZXWPN2K5W7jFFM-ZnwgE/edit?usp=sharing
If I missed something you were trying to achieve, let me know.
Also, I'm sure that there is a more elegant way to do this, or one not requiring the use of a block of "reserved" blank cells, but I couldn't think of that at the moment.
Edit: The formula as follows also works. But you need to remember to set the "100" value to be equal to the number of rows in your data block, since we pad the columns with the necessary number of blanks rows, after removing the blank cells in each column.
={
{(A1:C1)};
{FILTER(A2:A,A2:A<>"");indirect("N1:N" & 100-counta(A2:A))},
{FILTER(B2:B,B2:B<>"");indirect("N1:N" & 100-counta(B2:B))},
{FILTER(C2:C,C2:C<>"");indirect("N1:N" & 100-counta(C2:C))}}