## Explanation

In this example, the goal is to count visible rows where Region="West". Row 13 meets this criteria, but has been hidden. The SUBTOTAL function can easily generate sums and counts for visible rows. However, SUBTOTAL is not able to apply criteria like the COUNTIFS function without help. Conversely, COUNTIFS can easily apply criteria but is not able to distinguish between rows that are visible and rows that are hidden. One solution is to use Boolean logic to apply criteria, then use the SUBTOTAL function together with the OFFSET function to check visibility, and then tally up results with the SUMPRODUCT function. The details of this approach are described below.

### Overview

At the core, this formula works by setting up two arrays inside SUMPRODUCT. The first array applies criteria, and the second array handles visibility:

```
=SUMPRODUCT(criteria*visibility)
```

The formula in H7 takes this approach:

```
=SUMPRODUCT((data=H4)*(SUBTOTAL(103,OFFSET(INDEX(data,1),ROW(data)-MIN(ROW(data)),0))))
```

### Criteria

The criteria are applied with this part of the formula:

```
=(data=H4)
```

Because there are 12 values in **data** (C5:C16) this expression generates an array with 12 TRUE and FALSE results like this:

```
{FALSE;TRUE;FALSE;TRUE;FALSE;TRUE;FALSE;FALSE;TRUE;FALSE;FALSE;TRUE}
```

The TRUE values in this array indicate cells in **data** that contain "West". When this array is multiplied by the array returned by the SUBTOTAL function (described in detail below) the math operation coerces the TRUE and FALSE values to 1s and 0s, which creates this final array of results:

```
{0;1;0;1;0;1;0;0;1;0;0;1}
```

This array is used to apply the criteria Region="West" in one of the last steps below.

### Visibility

To check visibility, we use an expression like this:

```
(SUBTOTAL(103,OFFSET(INDEX(data,1),ROW(data)-MIN(ROW(data)),0)))
```

At a high level, we are using the SUBTOTAL function with *function_num* set to 103, which causes SUBTOTAL to *count* visible cells, ignoring cells that are hidden with a filter, or hidden manually. The reason the expression is complex is that we need an *array* of results, not a single result. This means we need to feed cells into SUBTOTAL one at a time using the OFFSET function. To do this, we have configured OFFSET to create the references needed for *ref1* inside SUBTOTAL like this:

```
OFFSET(INDEX(data,1),ROW(data)-MIN(ROW(data)),0)
```

Working from the inside out, *reference* is provided to OFFSET with the INDEX function like this:

```
INDEX(data,1) // first cell in data
```

We are simply asking INDEX for the first cell in the named range **data**, and INDEX (under the hood) returns C5 as a result:

```
OFFSET(C5,ROW(data)-MIN(ROW(data)),0)
```

The *rows* argument inside of OFFSET is created like this:

```
=ROW(data)-MIN(ROW(data))
={5;6;7;8;9;10;11;12;13;14;15;16}-5
={0;1;2;3;4;5;6;7;8;9;10;11}
```

Essentially, we are using this construction to create a zero-based index of offsets to give to the OFFSET function:

```
OFFSET(C5,{0;1;2;3;4;5;6;7;8;9;10;11},0)
```

Using these 12 row offsets, the OFFSET function returns an array of 12 cell references like this:

```
{C5;C6;C7;C8;C9;C10;C11;C12;C13;C14;C15;C16}
```

This array of references is returned to the SUBTOTAL function as the *ref1* argument:

```
(SUBTOTAL(103,{C5;C6;C7;C8;C9;C10;C11;C12;C13;C14;C15;C16}))
```

With *function_num* set to 103, SUBTOTAL returns the count of visible cells in each reference. Because each reference is provided separately, we get back an array with 12 counts like this:

```
{1;1;1;1;1;1;1;1;0;1;1;1}
```

Since we are feeding the references to SUBTOTAL one at a time, the only possible values are 1 and 0, which is exactly what we need when we multiply this array by the array we created for the criteria below. To recap, the complexity above is needed to get to *12 results* instead of the *single* result SUBTOTAL would give us if we provided a simple range.

### Adding up results

Finally, we are ready to add up the results. For this, we use the SUMPRODUCT function. Both arrays explained above are delivered to SUMPRODUCT like this:

```
=SUMPRODUCT({0;1;0;1;0;1;0;0;1;0;0;1}*{1;1;1;1;1;1;1;1;0;1;1;1})
```

After the two arrays are multiplied, we have:

```
=SUMPRODUCT({0;1;0;1;0;1;0;0;0;0;0;1}) // returns 4
```

In the final step, SUMPRODUCT sums the array and returns 4 as a final result.

### Multiple criteria

You can extend the formula to handle multiple criteria like this:

```
=SUMPRODUCT((criteria1)*(criteria2)*(SUBTOTAL(103,OFFSET(ref,rows,0,1))))
```

### Summing results

To return a sum of visible values (instead of a count), you can adapt the formula to include a range of cells to sum like this:

```
=SUMPRODUCT(criteria*visibility*sumrange)
```

The sum range is the range that contains values you want to sum. The criteria and visibility arrays work the same as explained above, excluding cells that are not visible. If you need partial matching, you can construct an expression using ISNUMBER + SEARCH, as explained here, to create the criteria array.