What FILTER Actually Returns

FILTER is a dynamic array function. You give it an array, a condition, and an optional message for empty results. Excel returns every row where the condition is TRUE and spills the output down and across as far as it needs. The source range stays untouched. This matters because a normal AutoFilter hides rows visually but still forces you to copy the visible cells somewhere else. FILTER hands you a live result you can point a chart or a SUM at.

Excel grid showing a FILTER formula spilling West-region Sales rows into a separate block

The Syntax in Plain Terms

The function takes three arguments. The first is the range you want returned. The second is a boolean condition of the same height. The third is what to show when no rows match. Keep all three in mind even on simple jobs, because the empty-result message is the part most people forget and then panic about later.

1
Select the range to return

Click an empty cell and start typing =FILTER(. Highlight your data block, for example A2:D100 on the Sales sheet. This is the range whose rows you want back, not just the column you filter on.

2
Write one boolean condition

Add the condition after the comma. To keep West rows, type C2:C100="West". The condition range must have the same number of rows as your return range, or Excel throws a #VALUE! error.

3
Add the empty message

Type a comma, then "none" in quotes as the third argument. Now if no row matches, the cell shows none instead of a #CALC! error, which is far easier for a teammate to read.

4
Press Enter and let it spill

Press Enter. Excel drops the matching rows starting at your formula cell. You will see a light blue border around the spilled block. Do not type inside that border, or you will get a #SPILL! error.

Filter a Text Column Like Region

Text conditions are the most common use. On our Sales table the Region column holds values like West, East, and North. A single equals test is enough. You can also test partial matches with the SEARCH function nested inside, which is handy when people type the region inconsistently.

5
Match an exact region

Use =FILTER(A2:D100, C2:C100="West", "none"). Every row where the Region column equals West appears. The match is case-insensitive, so West and west both work.

6
Match a partial string

To catch anything containing east, write =FILTER(A2:D100, ISNUMBER(SEARCH("east", C2:C100)), "none"). SEARCH returns a number when found and an error when not, so ISNUMBER turns it into a TRUE or FALSE test.

7
Exclude a value instead

Prefix the test with NOT or use <>. For rows that are not West, write =FILTER(A2:D100, C2:C100<>"West", "none"). This returns everything else, which is a quick way to build a reject list.

Pro Tip

I recommend pointing the return range at a proper Excel Table, such as Sales[#All], instead of a fixed A2:D100. Then new rows you add to the table are picked up automatically. A common mistake is hard-coding the last row, so the report silently misses data once the table grows past row 100.

Filter With a Number Condition

Numbers open up the useful comparisons: greater than, less than, and between. On the Orders table the Amount column holds dollar values, so I filter deals above a threshold to build a manager view without touching the raw list.

8
Keep rows above a threshold

On the Orders table, write =FILTER(A2:E500, E2:E500>5000, "none") to return every deal over $5,000. The Amount column must be real numbers, not text that looks like money, or the comparison fails silently.

9
Combine two number tests

Use the multiply trick for AND logic. =FILTER(A2:E500, (E2:E500>=1000)*(E2:E500<=5000), "none") keeps only mid-size deals. Each test in parentheses becomes a column of 1s and 0s, and multiplication acts as AND.

10
Use OR with addition

For OR logic, add the tests: =FILTER(A2:E500, (C2:C500="West")+(C2:C500="East"), "none"). A row in either region passes. Mixing plus and times lets you build nearly any rule.

Filter Rows Between Two Dates

Date filtering turns FILTER into a live period report. On the Orders table the OrderDate column holds real dates, so a pair of greater-than and less-than tests pulls a window like the first quarter without a single helper column. I build every monthly view this way because the window slides when I change two cells.

11
Set the start and end dates

Write =FILTER(Orders, (Orders[OrderDate]>=DATE(2026,1,1))*(Orders[OrderDate]<=DATE(2026,3,31)), "none") to keep Q1 2026 rows. Both tests must be TRUE, so multiply them to get an AND between the two dates.

12
Drive the dates from cells

Put the start in G1 and the end in G2, then use (Orders[OrderDate]>=G1)*(Orders[OrderDate]<=G2). Change either cell and the report slides to a new window with no formula edit. This is my go-to month picker.

13
Open-ended windows

Drop one test for a half-open range, like (Orders[OrderDate]>=G1) to show everything from the start date forward. Use this for a running year-to-date list that grows each day.

Filter on Two or More Columns at Once

Real requests rarely involve one column. A manager wants West region AND deals above $5,000 AND closed status. You stack those conditions with the multiply trick so every rule must hold.

14
Stack conditions with AND

Write =FILTER(Sales, (Sales[Region]="West")*(Sales[Amount]>5000)*(Sales[Status]="Closed"), "none") using structured references on a Table named Sales. Each parenthesis is one rule; multiplication means all must be TRUE.

15
Reference a cell for the threshold

Put 5000 in cell G1 and write (Sales[Amount]>G1). Now the report updates when someone changes G1, with no formula edit. I do this whenever a threshold changes often.

16
Handle a blank filter cell

If G1 can be empty, wrap with IF: (G1="",1,(Sales[Amount]>G1)). The 1 means always pass that rule when G1 is blank, so the filter still returns rows. This avoids a confusing empty report.

Nest FILTER Inside SUM and Other Functions

FILTER returns a range, so you can drop it straight into another function. The most practical combo is SUM wrapped around FILTER, which gives you a conditional total without building a pivot table for a one-off question.

17
Sum the filtered rows

Write =SUM(FILTER(Sales[Amount], Sales[Region]="West", 0)). FILTER returns just the West amounts, SUM adds them. The 0 as the third argument means a blank sum instead of text when nothing matches.

18
Count matches with COUNTA

Use =COUNTA(FILTER(Sales[Region], Sales[Region]="West", "none")) to count West rows. COUNTA counts the spilled cells. This is faster than COUNTIF when the condition is already complex.

19
Sort the filtered result

Wrap with SORT: =SORT(FILTER(Sales, Sales[Amount]>1000, "none"), 5, -1) returns the big deals sorted by the fifth column, Amount, in descending order. Chaining dynamic array functions like this is where the real speed comes from.

Watch Out

A common mistake is referencing the spilled output with a normal cell click, then dragging that reference. The spilled range shifts as data changes, so a fixed reference can break. Reference the formula cell itself, not the spilled cells below it.

Why FILTER Throws #SPILL! and #CALC!

Two errors show up most. #SPILL! means something blocks the cells Excel wants to fill. #CALC! with FILTER usually means no rows matched and you left out the empty message. Both are easy to fix once you know the cause.

20
Clear the spill path

If you see #SPILL!, look for a value, a merged cell, or a border in the cells below your formula. Delete or move it. Excel needs a clear rectangular area equal to the result size.

21
Add the empty message

If you see #CALC!, the condition matched zero rows and the third argument was missing. Add "none" or 0 as the third argument and the error becomes a clean result.

22
Check row height match

A #VALUE! here often means your condition range has a different row count than the return range. Make both cover exactly rows 2 through the last data row, for example A2:D100 with C2:C100.

FILTER vs VLOOKUP and Pivot Tables

FILTER returns many rows; VLOOKUP returns one value per match. A pivot table also summarizes, but it is a static object you must refresh. For a live sub-list that feeds another formula, FILTER wins. For a single lookup value, see our focused guide on the classic lookup approach before you reach for FILTER.

You can also link this technique to broader data cleaning habits. When the source is messy, filter it first, then clean. That order saves time because you only fix the rows you actually use.

Next Steps and a Quick Checklist

Start with one condition on a real table, confirm the spill looks right, then add a second rule. Build the empty message in from the start. Once that works, wrap SUM around it for a live total. Keep the return range pointed at a Table so new rows flow in.

Pairs worth learning next: SORT to reorder the spilled block, UNIQUE to drop duplicates before filtering, and SEQUENCE to build test data fast. Each one is a dynamic array function that chains with FILTER cleanly.