Excel: =COUNTIF or =COUNTIFS referencing a range as their criteria - excel

I have used a macro to get me a list of around 600,000 files (hosted on a server) that are then listed into an Excel sheet. From this list, I need to know how many DON'T meet a certain criteria and I have a few different statistics being calculated based on the files and their types (PNG, JPG, .DOC, PDF, etc). What I'm calculating or excluding from this list is changing often depending on what data I'm analyzing from this list. So that I don't have to constantly update a formula with a list of exclusions from this list, I'm trying to write a function that will just exclude a list in another column.
My current solution is a simple =COUNTIFS(A:A,{"<>","<>JPEG File","<>Outlook File", etc}). The "<>" is there because it keeps counting blank cells after the list if it is not included. I want to actually replace the COUNTIFS criteria part with a list of items in another column. I tried =COUNTIF(A:A,"<>"&C:C) and this doesn't work, but is returning a value equivalent to COUNTA, not actually excluding the items in the C column that I add (I think it's function in an AND capacity for the criteria and not as an OR). I tried doing a =COUNTA(A:A)-COUNTIF(A:A, C:C) but again, COUNTIF seems to be counting C:C as a list of AND criteria and not ORs.
The ideal would be if this actually worked: =COUNTIFS(A:A, "<>", A:A, "<>C:C") except that COUNTIFS doesn't allow a range as a criteria, so this obviously can't work.
Is there another solution that I'm just not seeing? Knowing myself, I wouldn't be surprised if it was actually super obvious and something I should have seen or I'm just misunderstanding something here.

=SUMPRODUCT(--(ISNA(MATCH(A:A,C:C,0))))-COUNTIF(A:A,"")
Where A:A is dataset and C:C is list to exclude. Example:

Related

Excel dynamic filter array

Hello my dear excel friends!
My "List" table consists of 10 columns that I filter by needed criterias in the second tab, which works perfectly. Now I have problems with the following filtering:
Cell B7 = Name
Cell B8:F8 = Items 1-5
Cell B9:F8 should be the order number (different amount for each item) of the respected items in the cells above.
Depending on the Name the items are spilling differently without any problems with
=IFERROR(TRANSPOSE(UNIQUE(FILTER(List[Item];(List[Name]=$B$7))));"")
Now I want to spill out the order numbers for each item in each column. The amount of orders can differ depending on the column. Unfortunately for now I can do it only for one column and have to copy the function to the next column:
=IFERROR(UNIQUE(FILTER(List[Order];(List[Item]=B8)*(List[Name]=$B$7)));"")
I have tried to do it with IFS but could not achieve the needed results. I can imagine something like B9# but somehow can not implement it into my function. Is there a way to do it?
Very difficult to give a rigorous solution for such a case. The following is convoluted though should work for smallish ranges:
=LET(μ,List[Item],κ,List[Name],η,B7:B11,ρ,MAX(COUNTIF(κ,η)),λ,TRIM(MID(FILTERXML("<a><b>"&TEXTJOIN(REPT(CHAR(32),50),,IFERROR(IF(INDEX(TRANSPOSE(κ),SEQUENCE(,ROWS(κ)+1))=η,TRANSPOSE(μ),""),"</b><b>"))&"</b></a>","//b"),SEQUENCE(,ρ,1,50),50)),IFERROR(INDEX(λ,SEQUENCE(ROWS(η)),SEQUENCE(,ρ)),""))
I've assumed that B7:B11 is your list of names. Amend as required.
In my opinion a non-spill formula to be copied down is preferable.

Excel advanced filter not showing results

Trying to put an advanced filter on an imported data list and copy to new sheet.
It only seems to either show everything in results or nothing except headers. I'm sure this is to do with my criteria, but I have tried every permutation I can think of (short of using VBA as I'm not competent with it), but nothing seems to yield actionable results.
If someone could have a look at the screenshots below and provide some direction I'd be most grateful.
The headers for the criteria are directly copied from the table headers and I've tried by separating the OR formulas into descending cells in the same column. Maybe it's to do with the syntax of the formulas I'm using, but I was informed by multiple sources online to have a formula that always returns a Boolean result and to have it tied to the first data in the worksheet that I want sorted (hence the B2, K2, O2, etc.).
Teylyn:
I was using this format for the criteria before, but it gave the same results - nothing at all!
criteria 2
Just tried again with the above criteria and no results again.
Additionally have tried with the following criteria - same again.
criteria 3
I need it to filter for every permutation of criteria columns 1, 2 & 3, hence the OR formulas being used before - I thought it might be filtering for AND all first row criteria, OR, AND all second row criteria.
I've even gone so far as to format all criteria such that it searches for first column (B2<=TODAY()-3) AND 2nd column AND 3rd column (O2="Not booked") then underneath, to imply OR, 1st column (B2<=TODAY()-3) AND 2nd column AND 3rd column (O2="Sent"). Setting out each permutation in this tiresome fashion. Still no results.
I can send you a dropbox link to the file if it will help.
You are not using Advanced filter correctly. It does not work with formulas like the ones you enter. You put one condition per cell, not a formula with OR().
Take a look at the documentation:
https://support.office.com/en-us/article/filter-by-using-advanced-criteria-4c9222fe-8529-4cd7-a898-3f16abdff32b#bkmk_5
or here:
https://www.techrepublic.com/blog/microsoft-office/how-to-use-and-and-or-operators-with-excels-advanced-filter/

Can these formulas be simplified? Why does INDIRECT function seem to not work inside an ISBLANK test within a MATCH formula?

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.

Make COUNTIFS ignore blank cells

I am trying to use a COUNTIFS formula to calculate how many installs are done. This is done by searching through a large table containing many blank cells. When using the following formula, I receive a #VALUE! error because Excel sees the blank cells as 0s and gets confused trying to count strings and integers:
=COUNTIFS(B10:B152,"Installs",D10:N152,"Done")
The range D10:N152 contains blanks and is causing the error.
Can I make Excel ignore those blanks or see them as strings instead of integers?
For COUNTIFS:
Important Each additional range must have the same number of rows and columns as the criteria_range1 argument. The ranges do not have to be adjacent to each other.
Maybe add a helper column, say O with:
=IF(MATCH("Done",D10:N10,0)>=1,"Done","")
copied down to suit and then:
=COUNTIFS(B10:B152,"Installs",O10:O152,"Done")
Now we know only one Done per row (and assuming Done is on its own in a cell) then a helper column with say:
=COUNTIF(D10:N10,"Done")
would be a shorter formula than =IF(MATCH("Done",D10:N10,0)>=1,"Done","") and also allow a shorter formula than =COUNTIFS(B10:B152,"Installs",O10:O152,"Done") for the counting, say:
=SUM(O:O)
instead (assuming the rest of ColumnO is blank or text, otherwise =SUM(O10:O152).
However I aimed for a formula as similar as possible to that used by OP, for which the helper column needed to be populated with Done also. At the time I was allowing for the possibility there might be more than one Done per row.
As pointed out in a comment, the helper column might have been populated with fewer keystrokes than =IF(MATCH("Done",D10:N10,0)>=1,"Done",""), if only by excluding the result for failure of the test, say =IF(MATCH("Done",D10:N10,0)>=1,"Done") since MATCH never ‘fails’ – rather it returns #N/A where no match is found, which is good enough for a COUNTIF function since that does not count #N/As when the criterion is Done.
Try this FormulaArray:
=SUM(($B$10:$B$152="Installs")*($D$10:$N$152="Done"))

Cross table comparisons, sumproduct

I am trying to compare two different Excel (2010/xlsx) tables with related data to find matches. They would be on different sheets but in the same workbook (not that it should affect the problem).
I think the best route is some combination of sumproduct, match, and index... but I haven't been able to get them to work so far. I see the main question (cell G17) being solved by creating a subset of rows from Table 2 to compare against their corresponding data in Table 1 (index/match), then using arrays to do a multiple criteria selection to count how many match the criteria I chose (sumproduct).
I have played around with vlookup, countif(s), and sumif(s) but haven't seen a good way to apply them to this problem.
You can use SUMIF as a "quasi-lookup" like this
=SUMPRODUCT((file="doc")*(modified < SUMIF(user,creator,create)))
I'm not sure how to do it in a single cell as you've asked, but I would create an extra column in the second table which uses vlookup to find the created date, and another column containing whether or not the created date is greater than the modified date. Finally, you could use countif to combine them.
To be more concrete, in your example, I would put =vlookup(F3,A$3:D$5,2,FALSE) in cell I3, and =I3>H3 into cell J3, and expand both of these down. Then cell G17 could be given by =countif(J3:J5,TRUE).

Resources