CSV Row Filter

Opening a 40,000-row export in a spreadsheet to pull out nine rows is a lot of ceremony for a filter you will use once. Paste it here, name a column, say what has to be true, and take the matching rows away as CSV.

CSV Row Filter — Keep or Drop Rows by Column Value Without a SpreadsheetBuildFigure

The filter runs on parsed cells, not on lines of text

Filtering a CSV with a text search is the obvious approach and it goes wrong in two directions at once. Searching for Bell across whole lines also matches a customer in Campbell, an address on Bellevue Road and a note that says bell rang. Searching for a value that happens to sit inside a quoted field containing the delimiter cannot even tell which column it landed in.

This reads the paste with a character-by-character parser first, so "Whitfield, Dana" is one cell, a doubled quote inside a quoted field comes back as a single quote, and a field with a line break inside it stays a single field instead of splitting the row in half. Only then are your conditions applied, and always to one named column.

Ten tests, and which ones surprise people

TestComparesWorth knowing
contains, does not containSubstring anywhere in the cellCase is ignored by default
is exactly, is notWhole cell, trimmed firstSurrounding spaces will not defeat it
starts with, ends withCell edgesAn empty value makes ends-with true for everything
greater than, less thanThe cell read as a numberAnything unparseable never matches
is empty or missingBlank cell or a short rowWhitespace-only counts as empty
has any valueThe opposite of the aboveUseful as a required-field check

The numeric tests strip one leading currency symbol, thousands commas, a trailing percent sign and accounting parentheses, so (1,234.50) is read as negative 1234.5. They deliberately stop there. A cell reading about 40 is not a number, will never satisfy a numeric test, and quietly falls out of the results rather than being guessed at.

AND, OR and the invert switch

Fill one condition and the other two stay out of the way. Fill two or three and the combiner decides: AND keeps a row only when every filled condition holds, OR keeps it when any one does. There is no bracketing, so a mixed expression like A and (B or C) cannot be written directly — run the tool twice, once for each half, or filter for the broad OR first and narrow the result in a second pass.

Invert flips the answer after the combiner has run, which is how you get not (A or B) — the rows where neither holds. It is the fastest way to build an exclusion list, and it pairs well with running the same conditions twice, once inverted, to check that the two halves add back up to the original row count.

Rows that are the wrong length

A row shorter than the header has missing fields, and missing is not the same as empty. A cell that exists and holds nothing was written by whatever produced the file; a cell past the end of a short row was never written at all. The preview marks the two differently, both satisfy the empty test, and the exported CSV pads short rows out to the full width so the result loads cleanly. If ragged rows are widespread, that is a sign of an unquoted delimiter upstream, and the CSV table cleaner will point at the exact rows.

Where this stops and something else starts

There is no grouping, no sorting and no arithmetic here — this narrows a table down and hands it back in the same shape. Once you have the rows you want, the CSV to JSON converter reshapes them for an API, table to Markdown puts them in a document, and the column statistics profiler tells you what the filtered subset actually looks like. For a list of plain values rather than a table, line tools is the smaller instrument.

One caution that applies to every tool of this shape, this one included: exports of customer records, payroll, patient data or anything else regulated should not be pasted into a web page without checking what your own policy allows, even when the page runs locally. The work here happens in your browser and nothing is transmitted, but the decision about where regulated data is allowed to go is yours and your organisation's, not a tool's.

Questions people ask

Can I filter on a column by number instead of by name?

Yes. Type a 1-based column number — 3 means the third column — and it is used when no header matches that text. Name matching runs first and ignores case and surrounding spaces, so a column literally called "3" still wins over the third position. With no header row the columns are called col1, col2 and so on, and either the generated name or the number works.

Why does my greater-than filter return nothing?

Because the column is not being read as a number. The numeric tests accept a plain number, one leading currency symbol, thousands commas, a trailing percent sign and accounting parentheses for negatives. Anything else — a unit suffix, a range, a note in the same cell, a stray non-breaking space pasted from a web page — fails to parse and the row never matches. Run the column through the profiler to see how many values in it are actually numeric.

Does it change my data?

No cell content is altered. The output holds the original values for the rows that matched, re-quoted where quoting is required, with short rows padded to the full column width so the file is square. Leading zeros, long identifiers and dates come back exactly as they went in, which is the main reason to do this here rather than by round-tripping the file through a spreadsheet.

How large a paste will it take?

It reads up to 500,000 characters and the first 20,000 rows, and tells you when it hits either limit rather than freezing the tab. The parser makes a single pass over the text, so within those limits it is fast, but the on-screen preview is capped at 25 rows because rendering a big table is slower than parsing one. The full result is always in the copy box.

Can I combine conditions with brackets?

Not in one pass. The three conditions are combined with a single AND or a single OR, and invert negates the whole thing afterwards. For a mixed expression, filter with the broader condition first, copy the result back into the input, and apply the second condition to that. Two passes give you the intersection of two different combinations without any bracketing syntax.

Related