I have a spreadsheet that looks like this:
A B C
1 Section Task Dev Hours
2 4 PROJECT TOTAL =c3+....
3 4.1 Public site =c4+c5+...
4 4.1.1 User Accounts 2
5 4.1.2 Daily Deal =sum(c6:c7)
6 4.1.2.1 Model 4
7 4.1.2.2 View 2
What I'd like is a better way to compute subtotals in column C for non-leaf rows. Using =sum is error-prone as I add/remove rows. Also I can only use it when all children are leaves, or it will double-count things. Using addition is even more error-prone and extra annoying. Is there some way to tell {Excel,OpenOffice,LibreOffice,Google Documents} to roll up the values in column C for all following child rows, based on the outline numbers in column A? I would love a function like this:
=sum_children(A2)
Where A2 is the cell with the current row's outline number.
You can use an array formula to do this. For the formula below, I've assumed that your Section values are sorted as you have shown above. In C2, paste the following and enter the formula by pressing Ctrl+Shift+Enter:
=SUM(IF(LEFT($A3:$A$7,LEN(A2))=A2,IF(ISERROR(FIND(".",$A3:$A$7,LEN(A2)+2)),$C3:$C$7,0),0))
You should then be able to copy cell C2 and paste onto any of the cells below that represent a parent section.
Basically this formula checks Column A below the current row for strings that start with the current section and only sums the dev hours for those that don't have an additional period after the current section + "."
To avoid having to update these formulas when you add additional sections to your table, you can make the endpoints of the arrays (A7 and C7 in the example formula) a row way beyond the bottom of your table (e.g. A50 and C50). This could affect performance slightly, but really only if you go overboard and give yourself a 50,000 row pad.
Related
i have an excel sheet in which the first few columns contain titles and information and the rest are repetitive 3 columns sets (i'll refer to as col1,col2,col3), containing dates.
i added an other 3 columns set in which i want to show the last date set in that row(i'll refer to as last1,last2,last3).
currently i set "last3" to look for the last non blank cell in row, last2 to look for the one before and last1 2 before.
problem is, not every time i fill the information i fill the whole set, meaning i could have a situation where the set contains col1 col2 values but not col3, then last3 actually takes a col2 value and messes up everything.
is there a way (please please no VBA programming) to write an array function of some sort that looks for the last 3 col set containing any value, and copying it to the last col set?
thanks!!
I have cooked up this formula for you. It isn't pretty and it's volatile (meaning, it will slow down your worksheet if you have a large quantity of these formula in it) but it does the job. It's the same formula for all columns and all rows.
=INDEX(INDIRECT(ADDRESS(ROW(),1)&":"&ADDRESS(ROW(),COLUMN()-1)),,COUNTA(INDIRECT(ADDRESS(ROW(),4)&":"&ADDRESS(ROW(),COLUMN()-1)))-MOD(COUNTA(INDIRECT(ADDRESS(ROW(),4)&":"&ADDRESS(ROW(),COLUMN()-1))),3)-(2-MOD(COLUMN()-4,3))+(4-1))
In this formula the number 4 stands for the first column of the first set of 3. If you have more columns to the left or fewer, change this number wherever you find it.
The number 3 stands for sets of 3 columns. the "2" in 2-MOD(COLUMN()-4,3)) is also related to this number being used here to reverse the result of Mod(,3) which will be 1, 2 or 0.
-1 generally stands for an adjustment, for example COLUMN()-1 is the number of the column to the left of where the formula resides. But in ADDRESS(ROW(),1) the "1" specifies column A.
The formula specifies a range starting from column 4 to the last column to the left of the formula and counts the number of entries in it, excluding cells of its own group. The 3 entries to be retrieved are in the range extending from itself 2 cells to the left.
If you deploy this formula, replace it with hard values when you add the same formula to the right of columns where it is already deployed. Use Copy/Paste Values (after copying the formulas to the right. This is to reduce the load on your worksheet.
BTW, I took a hard look at this thread, where they deal with columns. Some of the solutions there can be reformulated to work on rows but I failed to make them work on sets of 3.
I am trying to determine the top 3 depending on the selected criteria, amount or count. User can choose between the two. I have the formula to determine top 3 but I don't know how to modify it to take in account of user's selection. User's selection is in J2.
In this case, count is selected but as you can see, my formula spits out amount.
I think I need an array formula nesting choose or offset or something. The formula I have in the selected cell is
=INDEX($A$3:$A$35,MATCH(1,INDEX(($E$3:$E$35=LARGE($E$3:$E$35,ROWS(I$7:I7)))*(COUNTIF(I$7:I7,$A$3:$A$35)=0),),0))
which calculates top 3. How can I get that to change depending on user selection?
Edit: I realize I can have two sets of data for each criteria and do an offset to select between the two but figured one of you wizards can probably do it all in one. (This data is used to drive a graph.)
Edit2: sorry if it was too abstract. There are two columns. E and F. E is a list of amounts. F is a list of counts. I want to find the top 3 of both. But obviously only one at a time. Depending on what the user chooses.
As you can see, even though the selection is currently count (J7), the results show the top 3 by amounts.
By using the number selected in J2, I should be able to nest an offset function to grab the column desired yes? 1 for column E, 2 for column F. That's how I understand the function to work. However, my attempts to nest has failed because I believe I need an array formula which is beyond my skillz.
Edit3: see pic. It shows the top 3 by each criteria. How do I combine them?
You could combine it into one (non-array) formula. Here is a simple example which perhaps you can adapt to your situation.
This is the formula in J7. Change the 2 in J2 to 1 and it will return the largest value in E rather than F.
=INDEX(OFFSET($E$3:$E$35,,J2-1,,),MATCH(1,INDEX((OFFSET($E$3:$E$35,,J2-1,,)=LARGE(OFFSET($E$3:$E$35,,J2-1,,),ROWS(I$7:I7)))*COUNTIF(I$7:I7,$A$3:$A$35)=0),),0))
Is it possible to generate a table of permutations in Excel without using VBA and without using any "helper" sheets or rows/columns?
For N columns, there would be N! rows.
For example, the table for N=3 would look like this:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
Open a blank worksheet and paste the following formula into cell A1. (I included line breaks for readability.)
= IF(ROW()<=FACT(COLUMN()-1),COLUMN(),
INDIRECT(ADDRESS(ROW()-FACT(SUMPRODUCT(((ROW()-1)>=FACT(ROW($A$2:$A$10)))+0)+1),
IF(COLUMN()=(SUMPRODUCT(((ROW()-1)>=FACT(ROW($A$2:$A$10)))+0)+2),1,COLUMN()+1))))
Simply drag this formula over N columns and then down N! rows in order to generate a full permutation table of order N.
A few things to note:
Because factorials grow very quickly, the formula above only works for N<=10. However, this isn't really a limitation because 10! = 3,628,800 which is a number that exceeds the maximum number of rows in Excel 2010 (which is 1,048,576). Therefore, Excel can't generate a permutation table for N=10 anyway.
If you want the top left of the table to be a cell other than A1, the formula can manually be modified to account for this shift. For example, if you want the table to start at A2 instead of A1, replace each instance of ROW() in the formula above with (ROW()-1).
Excluding the first row (which lists the numbers ascending) and the last row (which lists the numbers descending), the order in which the permutations are listed in this table are not in the same order as listed in the original question, but the pattern is still deterministic. See below for a screenshot of a permutation table using this formula of order 4, using conditional formatting to make it easy to spot the pattern of how the order of the permutations change as row numbers increase.
EDIT:
Another solution with all of the same properties as above except that the permutations are generated in a different order is the following:
= IF(ROW()<=FACT(COLUMN()-1),COLUMN(),
INDIRECT(ADDRESS(ROW()-FACT(SUMPRODUCT(((ROW()-1)>=FACT(ROW($A$2:$A$10)))+0)+1),COLUMN()))
+IF(ROW()<=FACT(COLUMN()),-1,
IF(INDIRECT(ADDRESS(ROW()-FACT(SUMPRODUCT(((ROW()-1)>=FACT(ROW($A$2:$A$10)))+0)+1),COLUMN()))
=INDIRECT(ADDRESS(ROW(),(SUMPRODUCT(((ROW()-1)>=FACT(ROW($A$2:$A$10)))+0)+2))),1,0)))
This formula is obviously longer than the first formula, but it still generally accomplishes the same thing: Open a blank worksheet and paste this formula into cell A1. Then drag the formula over N columns and then down N! rows in order to generate a full permutation table of order N.
As already stated, however, the order of the permutations changed as compared to the previous solution. The order of permutations in this solution is arguably better than that of the first solution because each column always contains "blocks" of numbers of the same size. See below for a screenshot of a permutation table using this formula of order 4, using conditional formatting to make it easy to spot the pattern of how the order of the permutations change as row numbers increase.
For those stumbling upon this in 2021 and beyond: if you have access to Power Query, a Cross join is a straightforward way to achieve this (and technically not VBA and doesn't use "helper" columns)
See documentation here.
I am trying to assemble a index/match combination and am having trouble figuring out how to make it work. I have experience with a lot of the formula types in excel, but unfortunately I am pretty ignorant when it comes to these functions.
I will explain what I am trying to do first, but I have attached 3 images at the end that will probably make things more clear.
In order to identify the specific values I want, I am having to use helper cells. These helper cells are denoted with the (helper) tag in the pictures. These cells go through and grab the adjusted closing price of the stock (column A) at the beginning (column C) and the end (Column D) of a dynamically calculated period.
I would like to consolidate these values into numerical order in columns F and G. The thought is that the first non zero number in C/D is belongs to the first predefined period and should go into columns F/G beside the #1 (column E). This gets carried on through all of the periods (ex: 2nd non zero goes beside the number 2, third nonzero number goes beside the number 3 etc.)
This is just an example of one stock. I need the function or formula to be dynamic enough to work on a wide variety of distributions. Sometimes there are up to 100 dynamically calculated periods within the stock analysis.
Below are the images that should provide more clarity
Image 1 is an example of what the data looks like
Image 2 is a crudely drawn example of how I would like the data to move
Image 3 is the desired result
Image 1
Image 2
Image 3
Updated image for Scott Craner showing out of order results
Please let me know if I can clarify any confusion.
If you just need to return the first value of each period (column C) and the last value of each period (column D), you could use index match and lookup to do this without even using helper columns.
Try this in cell F2
=INDEX(A2:A50,MATCH(E2,B2:B50,0))
And this in cell G2
=LOOKUP(E2,B2:B50,A2:A50)
Depending on much variance is in your overall number of rows, you could use indirect references in the formulas to dynamically update the ranges.
Example:
=INDEX(A2:INDIRECT("A"&COUNTA(A:A)),MATCH(E2,B2:INDIRECT("B"&COUNTA(A:A)),0))
You will need to open macro. Then do the following in recorded macro.
+ Filter only non-null value in C/D
+ Select whole column in C/D then copy the whole column
+ Turn off Filter
+ Paste the whole C/D in F/G
+ Stop macro
Gook Luck
Put this formula if F2:
=INDEX(INDEX(C:C,MATCH($E2,$B:$B,0)):INDEX(C:C,MATCH($E2,$B:$B,0)+COUNTIF($B:$B,$E2)-1),MATCH(1E+99,INDEX(C:C,MATCH($E2,$B:$B,0)):INDEX(C:C,MATCH($E2,$B:$B,0)+COUNTIF($B:$B,$E2)-1)))
Copy over one column and down the list.
Let's say column A has ten names in it, and column B ten values. I want the names of the people with the five highest column B values, in order, to populate on a different sheet. How would I do this? What if I wanted the lowest values?
you can also use vlookup to achieve the same but since your lookup value comes before the column you are looking up against then you need to use choose function to resolve this:
always using the same example table
put this formula in C2 to pull the top 5:
=VLOOKUP(LARGE($B$2:$B$99,ROW(1:1)),CHOOSE({2\1},$A$2:$A$99,$B$2:$B$99),2,0)
and put this in D2 to pull the low 5:
=VLOOKUP(SMALL($B$2:$B$99,ROW(1:1)),CHOOSE({2\1},$A$2:$A$99,$B$2:$B$99),2,0)
hope this works as well.
you can use the index matchfunction to achieve this:
Given the above example table:
Formula to pull top 5, put this in C2:
=INDEX($A$2:$A$99,MATCH(1,INDEX(($B$2:$B$99=LARGE($B$2:$B$99,ROWS(C$1:C1)))*(COUNTIF(C$1:C1,$A$2:$A$99)=0),),0))
Formula to pull low 5, put this in D2:
=INDEX($A$2:$A$99,MATCH(1,INDEX(($B$2:$B$99=SMALL($B$2:$B$99,ROWS(D$1:D1)))*(COUNTIF(D$1:D1,$A$2:$A$99)=0),),0))
For both, drag and fill down for 5 rows (because you want top/low 5). you can drag/fill down as many as you want.
you can adapt it to fit the lenght of your column by changing the $A$99 and $B$99 to any number of rows you have.
tell me if it works for you.