Formula

Put the row thresholds in ascending order, put the column thresholds in ascending order, and use MATCH(..., 1) twice inside INDEX:

=INDEX(B2:D4, MATCH(G1, A2:A4, 1), MATCH(G2, B1:D1, 1))

With row headers 0, 10, 20, column headers 0, 100, 200, a row input of 17, and a column input of 150, the formula returned the value at row header 10 and column header 100.

Test setup

We created a private Google Sheet using only synthetic numbers. The matrix was:

Threshold 0 100 200
0 5 10 15
10 20 25 30
20 35 40 45

The test inputs were 17 for the row and 150 for the column. The formula was entered twice in separate cells. A third check used -1, below the smallest row header.

Tested steps

  1. Sort both header ranges from smallest to largest.
  2. Enter the row input and column input in two cells.
  3. Enter the formula above, adjusting the ranges to match the sheet.
  4. Repeat the formula in a second cell without changing the data.
  5. Test an input below the smallest header so the lower-bound behavior is visible.

Both live runs returned 25. The below-minimum test returned #N/A.

Why it works

Google documents that MATCH with search type 1 assumes an ascending range and returns the position of the largest value less than or equal to the search key. INDEX then uses the two returned positions to select one cell from the matrix.

Limits and safer variants

Do not use this form on unsorted headers. If inputs below the minimum are expected, decide whether they should be rejected, clamped, or given a fallback with IFNA; those are different business rules and should not be hidden in the lookup.