I have many formulas that reference a large list and at the time I just have them to 1000 to make it easy. There will come a day that I will surpass 1000 and I don't want to have to continuously update the function but at the same time I don't want to have an excessive range.
The following function is in cell CM4 and I have data in cells CM11:CM52 and each day one more gets added at the bottom. What kind of function could I use to just take the average of CM11:CM52 that will reference CM11:CM53 tomorrow and so on and so on?
The following formula is a simple one that is in my worksheet:
=AVERAGE(CM11:CM1000)
Many formulas do not have a cost to using full column references. AVERAGE() is one of them so there is no problem using
=AVERAGE(A:A)
Or if you want to start on a certain row:
=AVERAGE(CM11:CM1048576)
For those formulas that do matter ie Array Types then we can make it dynamic with INDEX/MATCH
=AVERAGE(CM11:INDEX(CM:CM,MATCH(1E+99,CM:CM))
If the column in question is text then use "zzz" instead of 1E+99
I would suggest adding your data to a table (insert>table). This will allow the formulas to update automatically.
Summary
I need an array formula that takes a row of data of certain length from Sheet1. For that row, in each column that is not blank, I need to grab the Sheet1 header value for that column and display that data in a continuous row on Sheet2 (without any spaces in between the row's cells).
Background
I have a table of data (employees and industry certifications with expiration date being the table's cell data) on sheet 1, with a row for each employee the spreadsheet is tracking. The certifications are the columns.
We are using this information to link to ID Badge Printer software (Bodno Silver), where we are limited to linking columns of data to a particular textbox.
The problem lies in the fact that not everyone has every certification. The rows are peppered with blanks separating the certifications that each employee does have. While setting up the required text boxes in the badge software template, that each link to a specific column, I quickly realized that since not everyone has every certification if we used the data how it was we would have a bunch of strange looking blanks in between the listed certifications rather than a continuous list.
What I did
My solution to this (which I'm open to a better one if anyone knows of one, other than "use better software"), was to create a new sheet and array formulas that no one would use except for me and the id printer software. This sheet would have a similar data table that took the rows of data interspersed with blank cells between expiration dates, and put the matching column headers for cells that had a date in them into a continuous row of the same maximum length (eliminating the blank cells).
Essentially, this would allow me to circumvent the restrictions of the badge software and each textbox would be MatchedCert1, MatchedCert2, MatchedCert3, etc. up to the original maximum number of certifications.
Pictures are probably better than my words at explaining what I am going for:
Sheet1 (source)
Sheet2 (result)
The array formulas
I worked on this one for a while. What I thought would be a simple INDEX, MATCH, ISBLANK formula (that I could create using the appropriate relative and absolute cell linking) and then expand to the whole sheet turned into a witch hunt and me praying for forgiveness for my sins to all that may be holy. Also a lot of googling.... I realized quickly that this one may not be so simple after all.
Finally, I arrived at the following two array formulas in order to correctly show what I was going for:
First Column of training section
{=IFERROR(INDEX(Sheet1!$E$2:$P3,1,MATCH(FALSE,ISBLANK(Sheet1!E3:Q3),0)),"")}
(easy enough, right? I thought so...)
I felt good about this until I tried to think through what would be required to get the formula to be universal so that I could use it on the entire table.
I feel dirty just putting the following in public, but here goes...
Second column through last column array formula
{=IFNA(INDEX(INDIRECT(ADDRESS(ROW($E$2),(MATCH(E3,Sheet1!$2:$2,0)+1),1,1, "Sheet1")&":"&ADDRESS(ROW(E3),COLUMN($Q3),1)),1,MATCH(FALSE, ISBLANK(INDEX(INDIRECT("Sheet1!"&ADDRESS(ROW(E3),(MATCH(E3,Sheet1!$2:$2,0)+1),1)&":"&ADDRESS(ROW(E3),COLUMN($Q3),1)),0,0)), 0)),"")}
(please don't call the police...)
[ninja edit] While this array formula works for 2nd result column through the final column, it doesn't work if there's not a blank column following the result range. The actual spreadsheet has 4 different groups of certifications that run horizontally, but I was able to just add a blank column in the corresponding data from the other sheet easily enough, so I just let it go. I'd give somebody a nickle for the answer to why that's the case here too [/edit]
Results
The first array formula, and INDEX MATCH using ISBLANK is rather straightforward.
The biggest question for me here, and the thing that drove me absolutely nuts for a couple of days, is why the second array formula requires the additional INDEX function nested inside of the ISBLANK function.
While taking the function apart and experimenting I realized that if I have any INDIRECT reference inside a ISBLANK function, which is itself inside of a MATCH function, the result of the match was ALWAYS 1:
{=MATCH(FALSE,ISBLANK(INDIRECT("$E3:$Q3")), 0)}
The above ALWAYS returns 1, whereas if I put the range in explicitly, the function would work just fine. That wasn't an option for me, since I needed to dynamically return the starting position for the match using the previous cell's address.
However, adding an INDEX function (with a column and row value of 0) to encapsulate the INDIRECT function provides the correct answer. I figured this out just by trial and error.
Questions
Can someone with more knowledge please let me know what is causing this behavior?
As a broader question, given I am limited to using formulas (no VBA), I would also like to know if I'm going about this in the wrong way or if there is a much simpler way of accomplishing this without this behemoth of a formula?
I know this sheet will probably require maintenance in a year - good luck future self!
Put this in E3, Copy over and down
=IFERROR(INDEX(Sheet1!$2:$2,AGGREGATE(15,6,COLUMN(INDEX($E:$P,MATCH($C3,Sheet1!$C:$C,0),0))/(INDEX(Sheet1!$E:$P,MATCH($C3,Sheet1!$C:$C,0),0)<>""),COLUMN(A:A))),"")
As to why your formula is not working, it is too convoluted to parse. One note, unless the sheets is the variable, one should avoid INDIRECT as much as possible. INDEX can almost always be used in its place.
Both INDIRECT and ADDRESS are volatile functions. Volatile functions will re-calculate every time Excel re-calculates, leading to a lot of unnecessary computations.
Not a solution but to answer why you are seeing this behavior:
EDIT: PREVIOUS EXPLANATION WAS JUST PLAIN WRONG
This confused me so, I did a bit of investigation:
I think that your problem is actually coming from the ISBLANK function because it is intended to be used with single values, and cannot handle ranges. Any BLANKs which are returned by functions are only converted to numeric values (0), when the BLANK is returned to (or displayed on) the sheet. If the function is returning to another function, the BLANK value seems to be preserved.
EDIT: ADDING A SOLUTION WITHOUT ARRAY FORMULAS
This is probably more complex than using an array formula... but I strongly dislike them, so do all I can to remove them.
Firstly, I would add an index to your positions in the results sheet:
=IF(F$7>COUNTIFS($F3:$L3,"<>"),
"",
IF(
MINIFS(
$F$7:$L$7,$F$7:$L$7,
">" & IFNA(INDEX($F$7:$L$7,MATCH(E9,$F$2:$L$2,0)),0),
$F3:$L3,
"<>"
)=0,
"",
INDEX(
$F$2:$L$2,
MATCH(
MINIFS(
$F$7:$L$7,$F$7:$L$7,
">" & IFNA(INDEX($F$7:$L$7,MATCH(E9,$F$2:$L$2,0)),0),
$F3:$L3,
"<>"
),
$F$7:$L$7,
0
)
)
)
)
Basically, the formula looks at the cert in the previous cell, and looks for the next, minimum index, greater than that.
Using COUNTIF and VLOOKUP, the goal is to count my inventory of Laptops and return the number I have in stock.
My current formula is this:
=COUNTIF($A$3:$A$10000,H4)
As my table only has one entry for "Laptop", the formula evaluates to 1.
The next step was to incorporate some sort of VLOOKUP for quantity. As an example, Row 17 has an entry for "Monitor" with a specific model, with a column E (quantity) value of 5:
Monitor HP Compaq LA1951G 1FL SVR 5
I could use a VLOOKUP here:
=VLOOKUP(H6,$A$3:$E$10000,5,FALSE)
However, I have a second set of monitors with a different model. From what I understand of VLOOKUP, the formula stops evaluating at the first match.
I'm considering simply listing every possible model in our environment and strictly using VLOOKUP only, but this makes my life more complicated.
Any suggestions on a better way of doing this before I do a lot of manual work would be appreciated. I've linked a sanitized copy of my workbook via Google Sheets here.
I believe the SUMIF() function would be more useful here.
Replace the
=COUNTIF($A$3:$A$10000,H4)
with
=SUMIF(A:E,H4,E:E)
Having done this same process for many companies, I suggest you also consider a Pivot Table. It can automatically update, auto-sum everything, and auto-count everything if you've set it up properly.
Pivot Tables also work in Excel and Sheets equally well. Just make sure that you're defining entire Columns of data for the basis of the data sets and it will be dynamic! E.G. Don't do A1:F50, do A:F for your data set definitions.
I'm fairly new to excel but have been learning lots. Please go easy on me.
Have 30,000 pieces of data, and constantly filtering this data set. As such, all my formulas constantly need to be updated to the new range (for example, a filter may change my range from B7000:B9000 from B1:B30000). I was able to make it so I can retrieve the row numbers for the first and last visible column.
I was hoping to be able to reference this within my cells to expand my range. What I tried (just as an example),
=INDEX(Helper!D3:Helper!E3),MATCH... (rest of the formula is correct)
In the Helper Spreadsheets for D3 I have
=Concatenate("'Sheet 1'!U"&D2)
Where, D2 is the formula I have used to grab my first visible row. In this case my D2 displays 7000
Is this doable or am I totally approaching this wrong? I've seemed to hit a brick wall and I can't figure out how to get this to work. Thanks again.
EDIT:
I am trying to use index and match on a range of cells to populate a fairly large table. Problem is range keeps changing every time I filter data. So I have 30 iterations of this data I need to get through in an already fairly complex algorithm i'm running. I was hoping to save a few steps by having my formulas auto expand depending on the filter, which would save me lots of headache as right now I have to go through and edit each formula by hand to the range the filter sets.
I thought I had it figured out by getting a way to grab the 1st and last visible column, however now I can't enter those into a reference as a formula for example as in the case above.
i have a little problem with final formulas in one of my column. How to start. maybe i will explain what i have a then what i want.
i have an excel worksheet with 3 sheets. i want to record goods and what are these goods made of. first is sheet called Goods where is possible to put number of goods i want to make. In this case i want to make 1x sandwich1 and at the same time 3x sandwich2. i dont want make sandwich3 this time.
Second sheet is Matrix sheet where I record every good and what it is made of. This sheet is basic sheet and all other sheets take list of goods (resp. ingredients) from this sheet. Simply when i want to make sandwich1 i look at matrix and know that i need 1x1pc of egg + 1x5g of cheese. And for 3x sandwiche2 i need 3x10g of sausages.
Final sheet is called Ingredients. It is a list of used ingredients from Matrix sheet (exactly same order) to make these sandwiches. I want to fill formulas into column B which would go through one ingredient ofter ingredient and count needed amount of it. So it would look into matrix in the same row and where there is some number it would multiply with number of items from Goods sheet. The list of goods is also in the same order as in the matrix sheet.
I hope you understand now what i want and will try to help me. I think there will be SUMPRODUCT, SUMIF and maybe INDERECT functions but i am not that skilled in excel
thanks for any suggestions
You can use MMULT function here - it's an "array formula" which you need to enter in a range. You can do that like this:
In Ingredients worksheet enter this formula in B2
=MMULT(Matrix!C2:E4+0;Goods!B2:B4+0)
[I'm assuming you have a European version of Excel where ; is used to separate arguments]
Now select the whole range B2:B4, press F2 key to select formula and hold down CTRL and SHIFT keys and press ENTER. This "array enters" the formula in the range and you should now see curly braces like { and } around the formula and also the correct results.
You cannot change part of that array now, only the whole thing
Note that I'm assuming that the contents of Goods!A2:A4 will be the same as Matrix!C1:E1 and in the same order. You can extend the ranges to be as large as you like as long as that principle still holds
I suspect that this is an issue of "when all you have is a hammer, every problem is a nail". For reasons known only to you you are using a spreadsheet to solve a problem that databases were made to do. Any solution to this problem in a spreadsheet will be entirely dependent on the integrity of your data - add another column or get things out of order and it will fail.
That said, what you have in your link is effectively a pivot table and what you need is the unpivoted version of this - the instructions for getting this are here.
When you have that, you can use the various database functions in excel to get your answer.