Specify dynamic rows for Index formula in excel - excel

I have a number of datasets on a sheet that calculate monthly and annual staff hires and terminations. I have another dataset to calculate the annual running staffing totals for specific disciplines by subtracting one specific row from another. The funcion I use is:
=LET(duration, SEQUENCE(1,(StudioProjectedOperatingMonths+12)/12, COLUMN(K:K)),
StartRow, 25,
RowsUntilSecondRow, 44,
DisciplineEntryIndex, ROW(INDEX(DisciplineTbl[Discipline],MATCH(J113,DisciplineTbl[Discipline],0)))-ROW(DisciplineTbl[#Headers])-1,
FirstRow, StartRow+DisciplineEntryIndex,
SecondRow, StartRow+RowsUntilSecondRow+DisciplineEntryIndex,
DisciplineValues, INDEX($1:$84,{25;69},duration),
StaffInOut, LET(x, DisciplineValues,INDEX(x,1)-INDEX(x,2)),
SCAN(0, StaffInOut,LAMBDA(x,y,x+y))
)
This gives the correct result when inserted in to K113 (highlighted cell below):
However, when I drag copy the formula from K113 to K114 etc I have to adjust the row references in the Index function to be INDEX($1:$84,{26;70},duration) and so on.
To try and get around this, I created the variables FirstRow and SecondRow which start off at 25 and 69 as per the Index part of the full formula above, and use the indexed row of the discipline in the discipline table to add a value. For example, if the Discipline is Programming it will add 0, if Design it will add 1 etc.
My thinking was to replace the INDEX($1:$84,{25;69},duration) part of the formula with INDEX($1:$84,{FirstRow;SecondRow},duration) but unfortunately it doesn't like this syntax.
Is there a way to make this work or do I need to approach it differently?

Related

Excel ultra-dynamic ranges with OFFSET(...COLUMN()) to convert to non-volatile

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!

How can you in Excel total predefined values depending on cell values

I have a spreadsheet with two tabs. The first one contains Vehicle Types and a numeric score value.
Second Tab has like a variety of these vehicle types and what should be the total score. Depending on the vehicle types present in the respective neighbour cell.
See images below for illustration.
Is there a way via formula to get the total, in Column B in sheet 2, of the corresponding numeric values of column a from sheet 1?
For example, as per the illustration B2 in sheet would total 3; whereby in sheet 1 bus has a score of 1 and car 2.
Update:
As per the answer below, I have used the formula;
=SUMPRODUCT(ISNUMBER(FIND(" "&sheet1!A$2:A$4&" "," "&SUBSTITUTE(A4,CHAR(10)," ")&" "))*sheet1!B$2:B$4)
However, I am unfortunately getting zero as the value. Changing the line breaks in column A in sheet2 I am duly able to get the total. Is there a way to do it so irrespective of how the list is presented in the column the total will work?
I think you are after something like this:
Formula in E2:
=SUMPRODUCT(VLOOKUP(FILTERXML("<t><s>"&SUBSTITUTE(D2,CHAR(10),"</s><s>")&"</s></t>","//s"),A$2:B$4,2,FALSE))
If one has O365 you could just use SUM instead since it would auto-CSE the formula.
If you don't have Excel 2013 or later, you could try the following as another option (shorter but not my favourite):
=SUMPRODUCT(ISNUMBER(FIND(" "&A$2:A$4&" "," "&SUBSTITUTE(D2,CHAR(10)," ")&" "))*B$2:B$4)

SumIF Using Table/Named Range Instead of Single Cell Criteria

I have 2 sheets in a workbook (Sheet1, Sheet2).
Sheet 2 contains a table (Named Table1) with 5 columns:
Takeaways
Household
Clothing
Fuel
Groceries
On sheet one, I have 2 columns:
Expense Name
Expense Total
Now, what I am trying to do is:
Set the range for the Expense Name (Range 1)
Set the range for the Expense Total (Range 2)
Compare Range 1 with the respective column in the table and only add up the values for matches
For example, in Range 1 (B6:B16):
BP
Caltex
McDonalds
KFC
In Range 2 (C6:C16):
300
400
200
150
Now, all I want to do is add up the values for the Takeaways (McDonalds, KFC) and exclude anything that DOES NOT match the criteria.
So my sum total will be all occurrences of Takeaways - provided they are listed in my table - 350 in this case.
But I cannot seem to get the formula to work.
I used these sources:
https://exceljet.net/excel-functions/excel-sumifs-function
Selecting a Specific Column of a Named Range for the SUMIF Function
and ended up with this formula:
=SUMIF($B$6:$B$16;Table1[Takeaways];C6:C16)
This source:
https://excelchamps.com/blog/sumif-sumifs-or-logic/
and ended up with this formula:
=SUM(SUMIFS(C6:C16;B6:B16;Table1[Takeaways]))
Both formulae return 0.
BUT, with BOTH of them, if I change Table1[Takeaways] to "McDonalds", then it correctly identifies every occurrence of the word "McDonalds" in Range 1.
EDIT:
I have updated the formulae above to match the images below.
This is the table that contains the references:
This table contains the data:
Formula:
Cell C4 (Next to Takeaways): =SUMIF($B$6:B$16;Table1[Takeaways];C6:C16)
Cell C5 (Next to Fuel): =SUM(SUMIFS(C6:C16;B6:B16;Table1[Fuel]))
It appears that ONLY BP is being detected in the formula.
This is a an output table when I use the formulae with a single cell reference and not a table or used range:
Formula:
Cell F4 (Next to BP): =SUMIF($B$6:B$16;"BP";C6:C16)
Cell F5 (Next to Caltex): =SUM(SUMIFS(C6:C16;B6:B16;"Caltex"))
Cell F6 (Next to McDonalds): =SUMIF($B$6:B$16;"McDonalds";C6:C16)
Cell F7 (Next to KFC): =SUM(SUMIFS(C6:C16;B6:B16;"KFC"))
If I understand correctly what you're trying to achieve, I think your setup is not right conceptually.
It looks like you're trying to track expenses, and each expense (or payee) is allocated to a category ("Takeaways", "Household" etc.). From a relational-model point of view, your second table (which defines the category for each expense/payee) should only have two columns (or variables): Expense Name and Expense Category.
The table you set up ('Sheet 2') uses the categories (i.e., possible values) as different columns (i.e., variables). But there's only variable, namely the "Expense Category", and the categories themselves are the possible values.
If you set it up like that, the problem changes: you can add a dependent column to your first table that shows the category for each payee (or "Expense Name"), using a VLOOKUP() from the second table.
You can then sum the expenses for all payees matching that category.
Note: I've created the illustration using LibreOffice Calc, so there might be some small differences, but the logic is the same.
Without seeing the data in L and K I can't give you a full answer - but likely it's to do with the way you're pulling your Array
Try something similar to this
=SUMPRODUCT(SUMIFS($L$11:$L$43,$K$11:$K$43,CHOOSE({1,2},Takeaways,"anything else you wanted to sum")))
Remember SUMIFS is for multiple criteria, so if you're only calculating one, you'll need =SUMPRODUCT(SUMIF(
The way the above works is with vertical vectors only, but changing your named ranges so the table of 2 columns is 2 named ranges instead should be okay - unless it's part of your requirements
Table 2 would become expense_Name and expense_Total etc
I was about to close this as a duplicate of my own question here but there is a bit of a difference in using a named range I think. However the logic behind this follows more or less the same approach.
Working further on my partial solution below I derived the following formula:
=SUMPRODUCT(COUNTIF(Table1[Takeaways];Range1)*Range2)
The COUNTIF() part counts the number of occurrences of the cell value in your table. Therefore make sure there are no duplicates in your table. If the value is present in the table the result of COUNTIF() will be 0. This way we create a matrix of 1's and 0's. By multiplying and the use of SUMPRODUCT() we force excel to perform matrix calculations and return the correct result.
Partial solution
I used the following formula:
=SUMPRODUCT(ISNUMBER(MATCH(Range1;Table1[Takeaways]))*Range2)
The formula does the following:
The MATCH()checks if the value in Range1 is present in your table and returns the position of the matching value in your table.
The ISNUMBER() checks if a match is found by checking if the MATCH() fucntion returned a number
Multiplying this with Range2 forces matrix calculation, using the SUMPRODUCT() function
EDIT:
This worked for a really limited sample. As soon as I added the fourth row to my data the formula stopped working as intended. See screenshot:
It took the first two values into the sum correctly, the fourth is not taken into account.

HLOOKUP with wildcard and SUM more than one column

I need help with the following:
I have a worksheet containing some data. Row 1 is header and from row 2 downward is the data. At the end there is total for all the data above. This worksheet is dynamic, i.e., if week 1 has 200 rows of data, then week 2 could have 250 or 190 rows of data.
Likewise, the columns across, change every week. This week I have 18 columns and next week I could have 20 columns.
Within row # 1, the header, I have two headings "CTAEO1P" and "CTAEO2P".
On another worksheet, I want to add the "totals" of both of those columns i.e., Individual totals of CTAEO1P = 32.98 + CTAEO2P = 46.25 = 79.23
I am using named ranges and named the whole of the worksheet with data as "MT". The range is whole of the worksheet so when next week I copy the data over from another worksheet, I should not have to adjust the range.
I am using the following formula, courtesy of another expert on this forum:
=HLOOKUP("CT*",MT,MATCH(9^99,INDEX(MT,0,MATCH("CT*",INDEX(MT,1,0),0))),0)
This formula look for any column that starts with "CT" and then "Match(9^99" and "index" finds the last number within that column (the total in this case) and then return that value on the worksheet. In this case this formula is returning "32.98" only, as this is the first occurrence.
I think I can use "Sumproduct" formula here but then a) I would have to create more than one named range, one for the header row and another for the "Total" row, b) every week I would have to adjust the range for "Total" row. Unless, if I can nest "Match(9^99..." part within "SUMPRODUCT" function.
I want to use "MT" range alone and want to add the totals of all the columns that start with "CT".
I hope I have been able to explain my problem better enough to make some sense, however, if you need any further information, then please let me know.
Regards
Tariq
I will forget about the MT range, as long as your data starts in A1 this will work
=SUMPRODUCT(ISNUMBER(SEARCH("CT*";OFFSET(A1;0;0;1;MATCH(9^99;2:2))))*OFFSET(A1;MATCH(9^99;A:A)-1;0;1;MATCH(9^99;2:2)))
Depending on your regional settings you may need to replace field separator ";" by ","
I think you can use a relatively simple SUMPRODUCT solution like this
=SUMPRODUCT((LEFT(INDEX(MT,1,0),2)="CT")*ISNUMBER(MT),MT)/2
SUMPRODUCT will total all values in the relevant columns, including the totals so divison by 2 will ensure you get the correct count
If you don't like that approach then assuming first column of MT always has data and that the totals for each column will all be in the same row you can use SUMIF like this
=SUMIF(INDEX(MT,1,0),"CT*",INDEX(MT,MATCH(9^99,INDEX(MT,0,1)),0))
That should be more efficient than the first version

Excel: If Cell in Column = text value of X, then display text (in the same row, but different column) on another sheet

This is a confusing request.
I have an excel tab with a lot of data, for now I'll focus on 3 points of that data.
Team
Quarter
Task Name
In one tab I have a long list of this data displaying all the tasks for all the teams and what Quarter they will be on.
I WANT to load another tab, and take that data (from the original tab) and insert it into a non-list format. So I would have Quarters 1,2,3,4 as columns going across the screen, and Team Groups going down. I want each "task" that is labeled as Q1 to know to list in the Q1 section of that Teams "Block"
So something like this: "If Column A=TeamA,AND Quarter=Q1, then insert Task Name ... here."
Basically, if the formula = true, I want to print a list of those items within that team section of the excel document.
I'd like to be able to add/move things around at the data level, and have things automatically shift in the Display tab. I honestly have no idea where to start.
If there is never a possibility that there could be more that 1 task for a given team and quarter, then you can use a formula solution.
Given a data setup like this (in a sheet named 'Sheet1'):
And expected results like this (in a different sheet):
The formula in cell B2 and copied over and down is:
=IFERROR(INDEX(Sheet1!$C$2:$C$7,MATCH(1,INDEX((Sheet1!$A$2:$A$7=$A2)*(Sheet1!$B$2:$B$7=B$1),),0)),"")
I came across this situation. When I have to insert the values into a table from an Excel sheet I need all information in 1 Column instead of 2 multiple rows. In Excel my Data looks like:
ProductID----OrderID
9353510---- 1212259
9650934---- 1381676
9572474---- 1381677
9632365---- 1374217
9353182---- 1212260
9353182---- 1219361
9353182---- 1212815
9353513---- 1130308
9353320---- 1130288
9360957---- 1187479
9353077---- 1104558
9353077---- 1130926
9353124---- 1300853
I wanted single row for each product in shape of
(ProductID,'OrdersIDn1,OrderIDn2,.....')
For quick solution I fix it with a third column ColumnC to number the Sale of Product
=IF(A2<>A1,1,IF(A2=A1,C1+1,1))
and fourth Column D as a placeholder to concatenate with previous row value of same product:
=IF(A2=A1,D1+","&TEXT(B2,"########"),TEXT(B2,"########"))
Then Column E is the final column I required to hide/blank out duplicate row values and keep only the correct one:
=IF(A2<>A3,"("&A2&",'"&D2&"'),","")
Final Output required is only from Column E
ProductID Order Id Sno PlaceHolder Required Column
9353510 1212259 1 1212259 (9353510,'1212259'),
9650934 1381676 1 1381676 (9650934,'1381676'),
9572474 1381677 1 1381677 (9572474,'1381677'),
9632365 1374217 1 1374217 (9632365,'1374217'),
9353182 1212260 1 1212260
9353182 1219361 2 1212260,1219361
9353182 1212815 3 1212260,1219361,1212815 (9353182,'1212260,1219361,1212815'),
9353513 1130308 1 1130308 (9353513,'1130308'),
9353320 1130288 1 1130288 (9353320,'1130288'),
9360957 1187479 1 1187479 (9360957,'1187479'),
9353077 1104558 1 1104558
9353077 1130926 2 1104558,1130926 (9353077,'1104558,1130926')
You will notice that final values are only with the Maximum Number of ProductSno which I need to avoid duplication ..
In Your case Product could be Team and Order could be Quarter and Output could be
(Team,Q1,Q2,....),
Based on my understanding of your summary above, you want to put non-numerical data into a grid of teams and quarters.
The offset worksheet function will work well for this in conjunction with the match or vlookup functions. I have often done this task by doing the following steps.
In my data table, I have to concatenate the Team and quarter columns so I have a unique lookup value at the leftmost column of your table (Note: you can eventually hide this for ease of reading).
Note: You will want to name the input range for best formula management. Ideally use an Excel Table (2007 or greater) or create a dynamically named range with the offset and CountA functions working together (http://tinyurl.com/yfhfsal)
First, VLOOKUP arguments are VLOOKUP(Lookup_Value,Table_Array,Col_Index_num,[Range Lookup]) See http://tinyurl.com/22t64x7
In the first cell of your output area you would have a VLOOKUP formula that would look like this
=Vlookup(TeamName&Quarter,Input_List,Column#_Where_Tasks_Are,False)
The Lookup value should be referencing cells where you have the team names and quarter names listed down the sides and across the top. The input list is from the sheet you have the data stored. The number three represents the column number the tasks are listed in your source data, and the False tells the function it will only use an exact match in your putput.

Resources