All posts
Feature6 min read

Filter CSV Columns by Value — Search, Copy, and Bulk Replace in Your Browser

A faster column filter for CSV files in 2026: filter by exact value or empty cells, search format-aware values, copy unique values to clipboard, bulk find and replace with a row-level animation that shows what changed. 100% browser-based.

Filtering a CSV column by its actual values is one of those operations that should take three seconds and frequently takes thirty: open the file in a spreadsheet, wait for it to load, click into the header, find the dropdown, scroll a list of 12,000 unique strings to find the four you care about. csvdiff.app already had a per-column value filter; this update makes it dramatically faster to use on real-world data — including columns full of empties, datetime strings, and values you want to clean up in bulk.

Every change in this post happens in your browser. Your CSV bytes never leave the tab. The features below work on any CSV opened in either the diff view or the standalone viewer.

Filter by Exact Value, Including Empty Cells

Click the funnel icon in any column header and you get a popover listing every distinct value in that column, sorted by frequency, with the row count next to each. Tick a value (or several) and the table filters down to rows where that column matches. Untick to clear, or hit the Clear shortcut in the popover header.

A long-standing miss in the previous version: empty cells were silently excluded from the value list. If your "department" column has 15 rows with a value and 4 rows that are blank, you could filter to the 15 — but had no way to surface the 4 blanks except by scrolling the table looking for dashes. The filter now includes blank values as a dedicated entry (rendered as italic "empty" with the count), pushed to the bottom of the list. Selecting it filters to rows where that column is blank — useful for finding missing data, validating exports, or zeroing in on rows that need follow-up.

Filter department
Clear
Search values…
engineering5
product3
data2
empty4
4 uniquelocal · no upload
Per-column filter on a "department" column with three populated values and one blank. The italic empty entry sits at the bottom — selecting it filters to rows where the column is missing.

Search Inside the Filter — Format-Aware

When a column has hundreds of unique values, scanning a list is too slow. The filter popover has a search box that narrows the value list as you type. New in this update: search matches both the raw value and the formatted display value. If you have applied a Currency format to a salary column, searching "120,000" finds the row whose underlying value is "1.2e5" — the search sees what your eyes see. Same for dates: searching "Mar 14" matches an underlying ISO string of 2022-03-14.

Filter joined
Clear
Mar
14 Mar 2022
02 Mar 2023
21 Mar 20242
3 uniquelocal · no upload
Searching "Mar" inside the filter on a date column. Underlying values are ISO strings; the filter renders and matches the formatted display, so the search hits as expected.

Datetime Format Support — 2020-07-31 14:32:09.000

A frequent shape in database exports is a SQL-style datetime: 2020-07-31 14:32:09.000. Earlier, the column format menu auto-detected a Date but only offered date-only outputs (YYYY-MM-DD, MMM DD YYYY, and so on), which threw away the time component. The Date format now exposes datetime outputs that preserve the time:

  • YYYY-MM-DD HH:mm:ss — full ISO-style datetime
  • YYYY-MM-DD HH:mm — minute precision, no seconds
  • MM/DD/YYYY HH:mm — US-style with time
  • DD MMM YYYY HH:mm — readable mixed format

Auto-detection got smarter too: if half or more of the date-shaped samples carry a time component, the default output flips to YYYY-MM-DD HH:mm:ss instead of YYYY-MM-DD. The parser also normalizes "YYYY-MM-DD HH:mm:ss[.fff]" to ISO internally so Safari (which is stricter than Chrome about non-ISO strings) parses these dates reliably.

Format created_atReset
Detected Date · YYYY-MM-DD HH:mm:ssApply
PlainDate
Preview
2020-07-31 14:32:09.0002020-07-31 14:32:09
2021-02-04 09:15:00.0002021-02-04 09:15:00
2024-11-08 22:47:31.5002024-11-08 22:47:31
SQL-style timestamps with millisecond fractions — Date format with YYYY-MM-DD HH:mm:ss output.
Ask AI to suggest format
A "created_at" column of SQL-style datetimes. Auto-detect picks Date with a datetime output; the live preview shows three real samples re-rendered with time preserved.

Copy Unique Column Values to Clipboard

Common analyst chore: "give me the list of distinct order statuses in this export". A new copy button in the filter popover header does it in one click. With nothing selected, it copies every value visible in the list (after any search filter you have applied). With one or more values ticked, it copies just the selection. The copied text uses the formatted display values, newline-separated — so pasting into a doc, a Slack message, or a spreadsheet column gives you exactly what you saw on screen.

Filter order_status
Clear
Search values…
pending142
shipped318
delivered605
returned27
cancelled14
5 uniquelocal · no upload
ClipboardCopied 5
pending
shipped
delivered
returned
cancelled
newline-separated · paste anywhere
One click on the copy icon (top-right of the popover) writes the visible unique values to your clipboard, newline-separated, ready to paste anywhere.

Tip: combine it with the search box. Type "201" in the search to narrow a 50,000-row "order_id" column to only IDs containing 201, then copy the filtered list directly. No spreadsheet round-trip.

Bulk Find-and-Replace, With a Row Flash

Selecting one or more values in the filter popover opens a small replace bar at the top. Type a replacement, hit Apply, and every cell in the column whose value matches your selection is rewritten. This was already there — what is new is the surrounding UX:

  • Affected rows briefly flash green to show exactly which rows were touched — instead of the whole table silently re-rendering and leaving you to guess.
  • The filter no longer clears after Apply. It re-pins to the new replacement value, so the same set of rows stays in view. You can verify the change, then clear the filter when you are ready.
  • Replace previews show the formatted display values, so a date or number column shows real-looking strings in the preview block before you commit.
Filter departmentClear
engineer
Apply
Preview · 5 cells
engengineer5
Search values…
eng5
product3
data2
1 selectedlocal · no upload
After Apply · row flash5 updated
#department
1engengineer
2engengineer
3engengineer
4engengineer
5engengineer
filter pinned to "engineer" · click Clear to see all rows
Bulk replace "eng" → "engineer" in a department column. Five cells match; after Apply, those rows flash green (right) and the filter re-pins to "engineer" instead of clearing.

Higher-Contrast Count Pills

Small visual change worth calling out: the row-count pill next to each value in the filter list used to be tertiary-text color on the lightest fill, which was hard to read on bright displays. It now uses secondary-text on a slightly stronger fill — readable at a glance, still subdued enough not to compete with the value name itself.

Why the Filter Stays Pinned After Replace

The previous behavior was to clear the filter after Apply. The intent was "you replaced those values, so they no longer exist; clearing the filter avoids showing zero rows." In practice it meant the table reset to all rows and you lost track of what just happened. The new behavior — re-pinning the filter to the replacement value — keeps continuity: the same rows that were filtered before remain filtered after, the flash animation shows you which ones changed, and one click on Clear puts you back to seeing the whole table when you are done. It is a smaller change than the rest, but it is the one that makes the workflow feel coherent.

Try It

Open any CSV in the viewer or the diff tool, hover a column header, and click the funnel icon. Search, filter, copy, replace — all in one popover, all on your machine. If you have not used csvdiff.app before, drop two files into the diff page or one file into the viewer and start there.

Try it yourself

Ready to diff your files?

Upload two CSV files and see the differences in seconds. 100% client-side — your data never leaves the browser.

Start comparing →

Ready to diff?

Drop your files, see the deltas, export the merge. Takes 30 seconds.