Skip to main content
ExcelList All Matches (INDEX AGGREGATE)Lookup & ReferenceArray FormulasData Extraction

The Problem

Have you ever faced the frustrating scenario where you know there are multiple instances of a value in your data, but Excel’s common lookup functions only return the first one? It’s a common spreadsheet headache. You might be tracking customer orders for a specific product, logging employee skills, or compiling project tasks, only to find VLOOKUP or XLOOKUP falling short. They are designed for unique matches, leaving you in a lurch when you need a comprehensive list.

What is List All Matches (INDEX AGGREGATE)? List All Matches (INDEX AGGREGATE) is an Excel formula combination that retrieves every instance of a lookup value, addressing the limitations of functions like VLOOKUP or XLOOKUP. It is commonly used to extract multiple matching records from a dataset into a vertical list, ensuring no relevant data point is overlooked. This powerful technique empowers you to pull every single matching item, not just the first one.

Trying to manually sift through hundreds or thousands of rows to find every occurrence is not only tedious but also highly prone to errors. You need a reliable, automated method to extract all relevant data points into a clear, usable list, and that’s precisely what our List All Matches (INDEX AGGREGATE) recipe delivers.

Business Context & Real-World Use Case

Imagine you’re a marketing manager at a growing e-commerce company. Your task is to identify all products that appeared in a recent promotional campaign and list their sales figures from different regions. Your raw data includes thousands of sales transactions, each with a product ID, region, and sales amount. A single product ID might appear multiple times, associated with sales in different regions or at different times.

Doing this manually would involve filtering your massive sales dataset for each product ID, copying and pasting the results, and then repeating the process for potentially hundreds of product IDs. In my years as a data analyst, I've seen teams waste countless hours on this exact manual process, leading to delays in reporting and often, incomplete or inaccurate insights. This is an inefficient use of resources and introduces significant room for human error.

Automating this process using List All Matches (INDEX AGGREGATE) provides immense business value. You can swiftly pull all relevant sales data for a specific product, analyze regional performance, or identify top-selling items from the campaign without missing a single transaction. This enables quicker, data-driven decisions on future marketing strategies, inventory management, and promotional planning. It transforms hours of manual labor into seconds of automated calculation, freeing up your team to focus on strategic analysis rather than data extraction. An accurate and complete list of matches is crucial for robust financial reporting, effective inventory management, and precise customer segmentation.

The Ingredients: Understanding List All Matches (INDEX AGGREGATE)'s Setup

While our cookbook refers to this powerful technique as LIST(), under the hood, we are orchestrating a sophisticated dance between the INDEX and AGGREGATE functions, often complemented by ROW, IFERROR, and ROWS. This combination creates a robust solution for extracting multiple matches.

The general structure of the formula you'll be building for List All Matches (INDEX AGGREGATE) is designed to progressively pull each match into a new cell.

Here's the exact syntax you'll be using, though we will break down the Variables that make up this specific INDEX AGGREGATE combination:

=LIST()

Let's delve into the key Variables that drive this formula:

Variables Description
Return_Range The range containing the values you want to retrieve. This is where INDEX looks for the final result. (e.g., B:B for Product Names)
Lookup_Range The column or range where Excel will search for your Lookup_Value. (e.g., A:A for Product IDs)
Lookup_Value The specific value you are searching for within the Lookup_Range. This can be a cell reference or a hardcoded value. (e.g., C1 containing "Widget X")
AGGREGATE_Function For this recipe, we typically use 15 (for SMALL) to retrieve the k-th smallest value.
AGGREGATE_Option We use 6 (for IGNORE ERRORS) to tell AGGREGATE to skip any error values that result from the match logic. This is crucial for filtering out non-matches.
Row_Number_Array This is generated by ROW(Lookup_Range) / (Lookup_Range = Lookup_Value). It creates an array of row numbers for matching values and #DIV/0! errors for non-matching values.
Relative_Row_Adjust MIN(ROW(Lookup_Range)) - 1. This subtracts the starting row number of your Lookup_Range to convert absolute row numbers to relative row numbers, making the INDEX function work correctly within a specified range.
Row_Counter A dynamic cell reference like ROWS($A$1:A1) or ROW(A1) which increments as you drag the formula down, serving as the k argument for AGGREGATE (i.e., finding the 1st, 2nd, 3rd match, and so on).
Error_Handling The IFERROR function is often wrapped around the entire formula to display a blank cell ("") or custom message when no more matches are found, preventing unsightly error messages like #NUM!.

The Recipe: Step-by-Step Instructions

Let’s prepare a delicious data dish by listing all project tasks assigned to a specific team member.

Example Data:

Suppose you have a project task list in Sheet1 with the following columns:

Task ID Assigned To Task Description Due Date
T001 Alice Design UI 2024-03-15
T002 Bob Develop Backend API 2024-03-20
T003 Alice Write Documentation 2024-03-25
T004 Charlie Test Module A 2024-03-22
T005 Alice Client Meeting Prep 2024-03-18
T006 Bob Database Migration 2024-03-28
T007 Alice Code Review - Feature X 2024-04-01

Our goal is to list all tasks assigned to "Alice" in a separate section of our worksheet.

Ingredients We Need:

  • Return_Range: Column C (Task Description)
  • Lookup_Range: Column B (Assigned To)
  • Lookup_Value: "Alice" (or a cell containing "Alice")
  • Extraction Location: Let's say we want the results starting from cell F2.

Here’s how to whip up the List All Matches (INDEX AGGREGATE) formula:

  1. Prepare Your Worksheet:

    • Select Your Lookup Cell: In a convenient cell, say E2, type the name of the person you want to search for, e.g., "Alice". This will be our Lookup_Value.
    • Create Headers: In cell F1, type "Alice's Tasks".
  2. Start Building the Formula with IFERROR:

    • Select Your Output Cell: Click on cell F2, where the first matching task description will appear.
    • Enter the IFERROR wrapper: Type =IFERROR(, which will gracefully handle cases where no more matches are found.
  3. Integrate the INDEX Function:

    • Specify the Return_Range: Inside IFERROR, type INDEX(C:C,. C:C is our Return_Range as it contains the Task Descriptions we want to retrieve. Make sure to use absolute references if your data spans only a part of the column, e.g., $C$2:$C$8. For entire columns, C:C works well.
  4. Introduce AGGREGATE for Row Numbers:

    • Add AGGREGATE: After the Return_Range, type AGGREGATE(15, 6,.
      • 15 tells AGGREGATE to use the SMALL function, which finds the k-th smallest value.
      • 6 instructs AGGREGATE to ignore error values, which is crucial for filtering out non-matches.
  5. Construct the Match Logic (Row_Number_Array):

    • Create the condition: Inside AGGREGATE, type (ROW(B:B) / (B:B=$E$2)),.
      • B:B=$E$2 checks each cell in column B against the Lookup_Value in E2. It returns an array of TRUE (match) or FALSE (no match).
      • ROW(B:B) returns the row number for each cell in column B.
      • Dividing ROW(B:B) by (B:B=$E$2) results in the actual row number for TRUE values (because TRUE evaluates to 1) and #DIV/0! errors for FALSE values (because FALSE evaluates to 0, and you can't divide by zero). This cleverly gives us an array of row numbers for our matches and errors for non-matches.
  6. Add the Row_Counter (k-value for AGGREGATE):

    • Specify the k-value: After the previous array, type ROWS($F$2:F2))).
      • ROWS($F$2:F2) is our Row_Counter. When dragged down, this changes to ROWS($F$2:F3), ROWS($F$2:F4), etc., effectively returning 1, 2, 3, and so on. This makes AGGREGATE look for the 1st, 2nd, 3rd smallest valid row number.
    • Note on Relative Row Adjust: If your data does not start on row 1, you would typically include - MIN(ROW(Lookup_Range)) + 1 before the closing parenthesis of AGGREGATE to adjust the row numbers to be relative to the start of your INDEX range. However, when INDEX uses full column references (like C:C), this adjustment is often implicitly handled. For simplicity and broad applicability with full columns, we'll often omit it if the Return_Range is a full column. If INDEX uses a partial range like C2:C8, then AGGREGATE(..., (ROW(B2:B8) / (B2:B8=$E$2)), ...) would need - MIN(ROW(B2:B8)) + 1 inside AGGREGATE. For this example, with C:C and B:B, it generally works without the adjustment.
  7. Finalize the IFERROR:

    • Complete the IFERROR: Type ,""). This tells Excel to display a blank cell if the formula results in an error (meaning no more matches are found).

The Final Working Formula for cell F2:

=IFERROR(INDEX(C:C, AGGREGATE(15, 6, (ROW(B:B) / (B:B=$E$2)), ROWS($F$2:F2))), "")

Now, drag the formula down from F2 to F8 (or further, to accommodate all potential matches).

The Result in Column F will be:

F1
Alice's Tasks
Design UI
Write Documentation
Client Meeting Prep
Code Review - Feature X

This powerful List All Matches (INDEX AGGREGATE) formula combination will dynamically expand to list every task assigned to "Alice," stopping at a blank cell once all matches are exhausted. It's a robust solution for extracting all relevant data points.

Pro Tips: Level Up Your Skills

To truly master List All Matches (INDEX AGGREGATE) and elevate your Excel game, consider these expert insights:

  • Dynamic Lookup Value: Always reference a cell for your Lookup_Value (like $E$2 in our example). This makes your formula flexible, allowing you to quickly change the item you're searching for without editing the formula itself.
  • Array Management: Use caution when scaling arrays over massive rows. While INDEX AGGREGATE is powerful, applying it to entire columns (like A:A) in a very large dataset (tens or hundreds of thousands of rows) can lead to noticeable performance degradation. For such scenarios, consider converting your data to an Excel Table and using structured references, or limiting your ranges to only the necessary data. In newer versions of Excel, FILTER is a more performant alternative for listing multiple matches.
  • Named Ranges for Clarity: For complex formulas, define Named Ranges for your Return_Range, Lookup_Range, and Lookup_Value. For instance, name B:B as AssignedTo and C:C as TaskDescription. Your formula then becomes IFERROR(INDEX(TaskDescription, AGGREGATE(..., (ROW(AssignedTo) / (AssignedTo=$E$2)), ...)), ""), which is much easier to read and maintain.
  • Horizontal Listing: If you need to list matches horizontally instead of vertically, you can achieve this by changing ROWS($F$2:F2) to COLUMNS($F$2:F2) and dragging the formula across columns.
  • Error Message Customization: Instead of ,"") for IFERROR, you could use ,"No more matches found") to provide more context to the user when the list is exhausted.

Troubleshooting: Common Errors & Fixes

Even the best recipes can run into snags. Here are common issues you might encounter with List All Matches (INDEX AGGREGATE) and how to fix them, ensuring your data dish is perfect every time.

1. #NUM! Error

  • Symptom: You see #NUM! in your result cells instead of values or blank cells. This is a very common error when working with AGGREGATE.
  • Cause: The AGGREGATE function, specifically when using SMALL (function number 15), returns #NUM! if it cannot find the k-th smallest value. This typically means either your Row_Number_Array is completely empty (no matches found at all) or the Row_Counter has exceeded the number of available matches. While IFERROR usually catches this, sometimes the IFERROR might be structured incorrectly, or the error occurs at an intermediate step before IFERROR can handle it. It can also happen if the k argument (our Row_Counter) is zero or negative.
  • Step-by-Step Fix:
    1. Check Lookup_Value: Ensure the Lookup_Value (e.g., $E$2 in our example) is spelled exactly as it appears in your Lookup_Range. Even a subtle extra space can prevent a match. Use TRIM() on both your Lookup_Value and Lookup_Range data temporarily to rule out leading/trailing spaces if necessary.
    2. Verify Ranges: Double-check that your Return_Range (e.g., C:C) and Lookup_Range (e.g., B:B) correctly encompass your data. Incorrect range references are a frequent culprit.
    3. Ensure IFERROR Placement: Make sure the IFERROR function wraps the entire INDEX(AGGREGATE(...)) part of your formula. For instance, =IFERROR(INDEX(C:C, AGGREGATE(...)), ""). If IFERROR is placed incorrectly, it might not catch the #NUM! from AGGREGATE.
    4. Row_Counter Check: Confirm your Row_Counter (e.g., ROWS($F$2:F2)) starts correctly at 1 and increments properly as you drag the formula down. The absolute reference $F$2 is crucial for the starting point.

2. #VALUE! Error

  • Symptom: Your formula returns #VALUE!. This error signifies an issue with the data types being used in the formula's calculations.
  • Cause: The most common reason for #VALUE! in this specific INDEX AGGREGATE pattern is a data type mismatch within the (ROW(Lookup_Range) / (Lookup_Range = Lookup_Value)) part. If any cell in your Lookup_Range contains an error value (like #N/A, #REF!, etc.) itself, or if Lookup_Value contains an error, this can propagate a #VALUE! error. It can also occur if Excel tries to perform a mathematical operation on non-numeric data unexpectedly, or if an array operation is attempting to combine arrays of incompatible sizes.
  • Step-by-Step Fix:
    1. Inspect Source Data for Errors: Carefully examine your Lookup_Range (e.g., B:B) and the Lookup_Value (e.g., $E$2) for any existing Excel error values. If you find any, resolve them in the source data.
    2. Clean Data Types: Ensure that Lookup_Value is of a compatible type with the data in Lookup_Range. For text lookups, this is usually straightforward, but if you're looking up numbers disguised as text, you might need to convert them (e.g., using VALUE() or Text to Columns).
    3. Validate Range Consistency: Confirm that the ranges provided to ROW() and the conditional (Lookup_Range = Lookup_Value) are consistent. For example, if you use ROW(B:B), ensure the condition also refers to B:B. In some complex setups, mismatched range sizes within an array operation can lead to #VALUE!.
    4. Confirm AGGREGATE Options: Ensure you're using AGGREGATE with 6 (IGNORE ERRORS) for the option argument. This is specifically designed to bypass errors like #DIV/0! that naturally occur when creating the Row_Number_Array, but it won't necessarily fix #VALUE! if the error originates from an incompatible data type at an earlier stage.

3. Not All Matches Listed / Incorrect Matches

  • Symptom: The formula only returns the first few matches, or it skips some, or it returns incorrect values entirely.
  • Cause: This usually points to issues with the Row_Counter's absolute/relative references or incorrect range definitions. If the Row_Counter doesn't increment correctly, AGGREGATE might repeatedly return the same match or stop prematurely. Incorrect Relative_Row_Adjust logic can also lead to misaligned results, especially if your data does not start from row 1 and you're using partial ranges for INDEX.
  • Step-by-Step Fix:
    1. Check Row_Counter References: This is the most critical element. Ensure your Row_Counter (e.g., ROWS($F$2:F2)) has the starting cell reference ($F$2) as an absolute reference (with dollar signs) and the ending cell reference (F2) as a relative reference (no dollar signs). When dragged down, ROWS($F$2:F2) should become ROWS($F$2:F3), ROWS($F$2:F4), etc., correctly incrementing the k value.
    2. Absolute References for Ranges: Confirm that your Return_Range and Lookup_Range are absolutely referenced (e.g., $C$2:$C$8 or C:C). If they are relative, dragging the formula will shift these ranges, leading to incorrect lookups.
    3. Review Relative_Row_Adjust (if used): If your INDEX range is not a full column (e.g., INDEX($C$2:$C$8, ...)) and your AGGREGATE array uses ROW($B$2:$B$8), you must include the adjustment - MIN(ROW($B$2:$B$8)) + 1 inside AGGREGATE to align the row numbers. Without it, INDEX will be looking at sheet row numbers when it expects row numbers relative to its own range. For full column references, this adjustment is often not needed.

Quick Reference

Element Description
Syntax =IFERROR(INDEX(Return_Range, AGGREGATE(15, 6, (ROW(Lookup_Range) / (Lookup_Range=Lookup_Value)), Row_Counter) - Relative_Row_Adjust), "")
Most Common Use Extracting all matching records (e.g., customer orders, employee skills, product IDs) from a dataset where a simple VLOOKUP or XLOOKUP would only return the first match.
Key Benefit Enables comprehensive data extraction for reporting and analysis, eliminating manual searching and preventing missed data points.

Related Functions

👨‍💻

Written by The Head Chef

Former 10-year Financial Analyst who survived countless month-end closes. I build these recipes to save you from weekend-ruining spreadsheet errors.

Read the full story →

You might also find these useful 💡