How to Use Cell Text From Cell Being Checked by COUNTIF in Excel - excel

What I'm wanting to do is have a formula in one cell that counts the values in a range that conform to a lookup of that range cell's value compared to another cell.
OMG, now that I look at it, that is totally confusing. Let me try to clarify a lot here.
Say we have Cell1, which will hold the counting formula. I have a list of values in a two-column table, Table1. The range, Range1 that Cell1 will be counting from is a range of cells that have List Validation in them. Table1 holds references to all values that can result from those Lists, in column 1. I have another cell, Cell2, which holds a number value. Column 2 of Table1 holds values that reference Cell2. I need to count the number of values from Range1 whose row matches in Table12 match the value in Cell2. Is there a way I can do this with COUNTIF without referencing each cell individually? Is there some shorthand (like Range.currentValue) that I can use to get the value of the cell currently being checked? The range is 11 rows long, and I need to do a second range that has 12 rows counted.
Man, I really don't know how to clarify that any more... I'll post this for now, in case anyone can understand what I'm saying and knows the answer, while I work on a sample spreadsheet I can upload.
I did my best to visually represent what I'm trying to accomplish:
http://gyazo.com/b83295baf3b156683a5c39b40c806504
Extended explanation: http://gyazo.com/4048802050e3dcfca7aee238acc2f7dd

Use a helper column, say, between the brown and the first blue or at the right of the setup. Use a vlookup like
=vlookup(brownvalue,BluetableRange,2,false)
Then do a countif on the helper column
=countif(HelperColumn,"<="&GreenCellAddress)
You can hide the column with the helper if it upsets your spreadsheet design.

You can (and probably should) use a helper column as Teylyn suggests. But, for when that may be inconvenient, you can also use an array formula:
=SUM(COUNTIFS(listlookupcolumn,rangeoflists,numbervaluecolumn,"<="&numbertomatch))
To enter it as an array formula, type "ctrl-shift-enter" after editing the formula, rather than just "enter"
Rough explanation: since rangeoflists is in a place where a single value is expected, the countifs is calculated once for each value, and the array of results is passed to sum. Use the "evaluate formula" feature to see the intermediate result array.
Afterthought: It occurs to me now that this does rely on listlookupcolumn containing unique values. (Almost certainly true in this example.) You can modify the formula a bit to get around this:
=SUM(SIGN(COUNTIFS(listlookupcolumn,rangeoflists,numbervaluecolumn,"<="&numbertomatch)))
The SIGN function will keep you from double counting.
Again, you must use "ctrl-shift-enter" for this to work. (Yes, as I'm sure others are ready to point out, you can also use the sumproduct hack in this instance.)

Related

Sum cells in a row from columns with numbers given in a range

I want to sum values in a row, but only for specific column numbers (or headers) which are listed elsewhere and are not constant.
It might be some range, or even better one cell with array containing column numbers. In either case not whole range or array will be always fully populated.
Is this even possible without using VBA?
If there's no way to avoid VBA I can give it a shot.
You may try the following:
Formula in H8:
=SUMPRODUCT((COLUMN($B8:$G8)=H$2:H$5+1)*$B8:$G8)
It's actually simple in this case since the second array is already transposed. Keep that in mind if you want to do this in any other way.

COUNTIFS with unique values Excel

I am trying to produce a count of the number of times different strings come up in an Excel table. An example table, currently in SHEET1, would be this:
I have another table in another spreadsheet where I want to indicate, for each letter on the left in Table 1, how many entries for "za", "zc" or "zd" come up on the right. However, I would only like to only consider one entry of each.
The end result, on row B of SHEET2, would have to be something like this:
At the moment I am using a combination of SUM and COUNTIFS to do the job.
More specifically, applied to the example, I am using the following formula:
=SUM(COUNTIFS(Sheet1!A1:A18,Sheet2!$A1,Sheet1!B1:B18,{"za","zc","zd"}))
The formula is doing some of what is intended. However, it is not counting each entry just one time. Instead, its is counting, for each letter on the left, every entry of "za","zc" or "zd". The table that the formula is returning is as follows:
How can I change the formula so that it does what I intend?
Thank you.
My initial thought would be:
=SUM(MIN (1,COUNTIFS(Sheet1!A1:A18,Sheet2!$A1,Sheet1!B1:B18,{"za","zc","zd"}))
but I’m not where I can test if the MIN will apply properly to the COUNTIFS array of results. ;-)
EDITED: The MIN function is taking minimum of 1 or all of the items in the COUNTIFS array, rather than minimum of 1 and each item in the COUNTIFS array, which is what I was afraid of. Using
=MIN(COUNTIFS(Sheet1!A$1:A$18,Sheet2!$A1,Sheet1!B$1:B$18,"za"),1)+MIN(COUNTIFS(Sheet1!A$1:A$18,Sheet2!$A1,Sheet1!B$1:B$18,"zc"),1)+MIN(COUNTIFS(Sheet1!A$1:A$18,Sheet2!$A1,Sheet1!B$1:B$18,"zd"),1)
will gain the desired results. It is a little clunky, but simpler than an array formula. If you want an array formula, you can use:
=SUM(FREQUENCY(IFERROR(MATCH({"za","zc","zd"},(IF(Sheet1!$A$1:$A$18=$A5,Sheet1!$B$1:$B$18)),0),""),IFERROR(MATCH({"za","zc","zd"},(IF(Sheet1!$A$1:$A$18=$A5,Sheet1!$B$1:$B$18)),0),"")))
This uses the FREQUENCY function to take a set of values and see how many items in another set of values fall within each of the data ranges. Since you need text instead of numbers, we use the MATCH function to find out the first time the value occurs in your list, returning "" with the IFERROR function if it doesn't. (We only need the first occurrence since you don't want to know how many occurrences there are). Since it is text, we use the same input for both arguments for FREQUENCY.
Therefore, if you need to change the values you are looking for or the ranges in which you are searching, make sure to change both! Alternately, you could list the values out somewhere, say in F1:F3, and make a named range for this, another one for A1:A18, and another for B1:B18. Your formula would then look something like this:
=SUM(FREQUENCY(IFERROR(MATCH(SearchValues,(IF(colA=$A2,colB)),0),""),IFERROR(MATCH(SearchValues,(IF(colA=$A2,colB)),0),"")))
Then you need only change your named range definitions and your formulas would update. :-)
NOTE: Since this is an array formula, you must close out of the cell by pressing CTRL+SHIFT+ENTER rather than only ENTER. When you look at the formula bar, you should see
{=SUM(FREQUENCY(IFERROR(MATCH(SearchValues,(IF(colA=$A2,colB)),0),""),IFERROR(MATCH(SearchValues,(IF(colA=$A2,colB)),0),"")))}
It does NOT work to enter the curly braces yourself. ;-)
You can use this formula at B1 and fill down:
B1:
=SUMPRODUCT(((Sheet1!$A$1:$A$18=A1)*(Sheet1!$B$1:$B$18= {"za","zc","zd"}))/
COUNTIFS(Sheet1!$A$1:$A$18,Sheet1!$A$1:$A$18,Sheet1!$B$1:$B$18,Sheet1!$B$1:$B$18))

Excel Performance - INDEX-MATCH combination

I am using excel to create data sets that are used in a vba application later. I am using this formula:
=INDEX(BaseData!$L$2:$L$10000;MATCH(DataSet!D5&DataSet!E5&DataSet!K5;INDEX(B‌​aseData!$B$2:$B$10000&BaseData!$C$2:$C$10000&BaseData!$D$2:$D$10000;0);0))
usually with a range from f.ex.: A2 - A10000, because my data can be differently long and often vary in data selection.
However, this slows my excel extremely down. I switched to manual calculations, but then, when activating automatic again, my excel instance takes extremely long and often crashes.
I also tried to past some data, but when creating a new dataset, I have to pull the formula down again and sometimes through this errors occur in my data set.
Any suggestions what I can do to make the INDEX-MATCH formulas more performant?
I appreciate your replies!
UPDATE
I guess a lot of performance goes away because index-match does not select the exact range, but also counts in blank rows. How to get the exactl range with index match automatically?
As I mention in my comment above, as long as this is a 'regular' formula and not an Array Formula, you may find success simply replacing "A1:A10000" with "A:A". However barring that, you can create a cell which will calculate reference the number of rows of data which you have, and then use that cell to indirectly reference the complete column with data in it.
CALCULATING YOUR DESIRED RANGE
For the following example to work, I assume that: Column A includes an index key in the form of numbers only; Column A includes no numbers in the header and above; and that the index rows are continuous, with no breaks. Start with the following formula:
=COUNT(A:A)
If my assumptions above hold, then this will return the number of data elements in your table. Once we know where this data starts, we can use this COUNT to determine where it ends. Assume your header is in row 2. (I like to include the header so that if you insert a row beneath the header, Excel picks up that you want to include the new row in your formulas).With that in mind, this formula will create the Excel-style reference which finds the last cell in column A which has data in it:
=ADDRESS(ROW(A2)+1+COUNT(A:A),COLUMN(A2),1,1)
Assuming 50 rows of data [which start at row 3, below the header], and all other assumptions above, this formula will return the text result "$A$53".
If you wanted to do the same thing, but instead return the full range in Column A where data exists (from the header to row 53), you could do as follows:
=ADDRESS(ROW(A2),COLUMN(A2),1,1)&":"&ADDRESS(ROW(A2)+1+COUNT(A:A),COLUMN(A2),1,1)
This returns the text string result "$A$2:$A$53", which is a reference to the full index of unique ID values. It will automatically move around as you would generally expect if you insert any rows or columns. Now assume for your INDEX that you want to pull the same data, but for column B, instead. The formula will be exactly the same, except that where I have "COLUMN(A2)" above, replace with "COLUMN(B2)".
REFERENCING YOUR CALCULATED RANGE
So now you have the address of your proper, limited columns - but how do you actually reference those areas in a formula? By using the INDIRECT function. INDIRECT says "Evaluate some specific criteria. It will create a cell reference. Now look at that cell reference." In its simplest form, this could look like this:
=INDIRECT(A1)
Assume that A1 holds the value "B5". Indirect will pick up the value "B5", and instead of displaying "B5", it will go to B5, and pick up the value there. So to use this with the above, wrap the whole thing in the INDIRECT function. Instead of picking up the text string "$A$1:$A$53", it will actually now reference that range properly. Like so:
=INDIRECT(ADDRESS(ROW(A2),COLUMN(A2),1,1)&":"&ADDRESS(ROW(A2)+1+COUNT(A:A),COLUMN(A2),1,1))
USING A NAMED RANGE
But that is a very long formula to have, and you won't want to use it within a specific cell for a simple INDEX/MATCH. Instead of entering these formulas in cells (although you could), I recommend you go to the Formula Ribbon -> Name Manager -> New Name. Call the name for the index of A "ID_COLUMN". Call the name for the index of "B_COLUMN" (or something more specific).
FINAL FORMULA
Now, if you wanted to make an INDEX/MATCH of your table, which automatically grows/shrinks as you change the data, your formula would look like this [this would, for example, pick the row from column B where column A has the number 100]:
=INDEX(ID_COLUMN,MATCH(100, B_COLUMN, 0))

Simple Enquiry with Complex Answer - How do I Select RowA6-Row(last non-blank) for a simple formula

I have many columns all labeled with many many values underneath, which can be words or numbers
Here is the current equation =INDEX(AK6:AK94,MODE(MATCH(AK6:AK94,AK6:AK94,0))) I have this on the in cell 5 of each column.
The number of values in each column may increase or decrease. If i reference the entire column (until the end of the worksheet) the blank spaces interfere with an accurate output.
How do I reference cell A6 to Last Non-Blank
There are much more efficient - and non-volatile - set-ups available for determining the last non-blank cell in a range than, for example, the SUMPRODUCT/MAX one given by sancho.s, though only if the blank cells within that range are all "genuine" blanks, and not the null string "" e.g. as a result of formulas in those cells.
If this can be guaranteed, then, for a range containing mixed datatypes (some text, some numerics) you can use:
=MAX(MATCH(REPT("z",255),A:A),MATCH(9.9E+307,A:A))
which will be far more efficient than any solution (such as the SUMPRODUCT/MAX set-up) which tests each individual cell within the specified range as to whether it is blank or not.
What's more, the above construction can reference the entirety of column A with no detriment to calculation speed, thus eliminating the need to select a limited range. (Note that using the same range, i.e. A:A, within SUMPRODUCT (or any other array formula) would not at all be a good idea, since this would be forcing Excel to calculate more than a million cells individually, leading to noticeably slower workbook performance).
As for forming a dynamic range, I'm constantly surprised that so many sources around the internet continue to advocate set-ups involving volatile functions such as OFFSET and INDIRECT (I've even seen several sites using ADDRESS for this purpose), especially when there is a perfectly good non-volatile (actually, not fully non-volatile, but near enough) INDEX set-up available, viz:
AK6:INDEX(A:A,LastRow)
where LastRow is a Defined Name given the formula I posted above.
Regards
You need to determine the row of last non-blank cell in the column. The method for this would depend on whether there are blank cells in the middle, for instance.
Two alternatives are (taken from here*):
=SUMPRODUCT(MAX(($AK6:$AK94<>"")*(ROW(AK6:AK94))))
=INDEX(MAX(($AK6:$AK94<>"")*(ROW(AK6:AK94))),0)
Then you can use this value with OFFSET to get a reference to the target cell. So your range will be (using the second form)
A6:OFFSET(AK1,INDEX(MAX(($AK6:$AK94<>"")*(ROW(AK6:AK94))),0)-1,0)
This expression will be embedded in a formula.
Notes:
You may have to change absolute/relative references.
Depending on the formula you embed the expression in, I foresee you might need to enter your formula as an array formula, with Ctrl+Shift+Enter.
*This aims at getting the last non-blank value instead of a reference to the cell, but some of the results posted are useful.
Would counting the non blank cells work, then use offset to move that number of rows.
Have a look at this:
MATCH(1,A6:OFFSET(A6,COUNTIF(A6:A600,">0"),))
the offset & count resolve to complete A6:A14 on my simple test sheet.
One option is to increase the number of rows in the formula to be as high as you might need, and add an extra IF function in the formula to handle blanks, e.g. this version will allow you up to 995 rows of data
=INDEX(AK6:AK1000,MODE(IF(AK6:AK1000<>"",MATCH(AK6:AK1000,AK6:AK1000,0))))
.....but will still work if you have fewer rows and blanks in that range
confirm with CTRL+SHIFT+ENTER

DSUM: How to define the criteria range using braces?

I think that it's easier to explain my problem with an example:
Based on the spreadsheet above, the formula =DSUM(A4:D8,B4,A1:A2) works, returning 20.
Why =DSUM(A4:D8,B4,{"OrderID";">10567"}) does not work? (It returns #VALUE!)
Based on what's said about D-Functions on this page, I think you need to have the criteria in a separate cell.
EDIT: If the goal of including the criteria in the formula is to make it more readable, you could work with named ranges instead.
EDIT 2: In response to your comments.
It's not possible to do what you want (include the criteria in the formula) because of how the DSUM() function works. Take a look at the documentation for DSUM and compare it with VLOOKUP:
The syntax for the DSum function is:
DSum( range, field, criteria )
range is the range of cells that you want to apply the criteria against.
field is the column to sum the values. You can either specify the numerical position of the column in the list or the column label in double quotation marks.
criteria is the range of cells that contains your criteria.
Note the difference:
The syntax for the VLookup function is:
VLookup( value, table_array, index_number, not_exact_match )
value is the value to search for in the first column of the table_array.
table_array is two or more columns of data that is sorted in ascending order.
index_number is the column number in table_array from which the matching value must be returned. The first column is 1.
As DSUM is looking for a range of cells that contain the criteria, there's nothing you can do to avoid passing it just that - a range of cells.
I think the best you can do is define your different criteria as named ranges, which will make it a lot easier to reference the different ones depending on what you want to do in the formula. Unfortunately, if the regular SUM function is not fast enough for you, there's not much else you can do - you will have to specify criteria in cells to use DSUM.
You may use SUMIF(A5:A8;>10567;D5:D8). A very useful and underused function.
The 2nd parameter may be a REF to another cell with the condition.
From DSUM documentation
Criteria is the range of cells that
contains the conditions that you
specify. You can use any range for the
criteria argument, as long as it
includes at least one column label and
at least one cell below the column
label in which you specify a condition
for the column.
VLOOKUP uses an array of values.
table_array Required. The range of
cells that contains the data. You can
use a reference to a range (for
example, A2:D8), or a range name.
Dsum sucks, try this:
=SUMPRODUCT((A5:A8>10569)*(B5:B8))
Generally I would advise you not to hard code stuff like this, it's "bad practice", but as you like.

Resources