CSV Workbench
Delimited files get a real grid (typed columns, frozen headers, one-click sorting) at any size, ordinary CSVs included, up to log-file scale. Two million rows parse to a working grid in 2.6 seconds.
Entering the grid
Table files are detected on open (delimiter and header row inferred) and the grid activates automatically. The extension does not decide it: a .csv or .tsv always opens in the grid, and any other file whose content carries real table structure, a tab-delimited .txt for instance, opens there too, while logs and prose stay in the text editor. Toggle between grid and raw text any time with ⇧⌘C. The status bar shows live rows × columns and parse progress.
2,083,723 rows × 50 typed columns from a 1 GB file. Headers stay frozen; the grid scrolls at full speed.
No file is needed to start one. Toggle the grid on an empty document and a blank three-column sheet appears, comma delimited, rows numbered from 1; empty .csv, .tsv, and .psv files open straight to the same sheet. Deleting every row of a headerless table leaves the sheet standing too, at the table's width, ready to refill.
Sorting
Click any column header to sort; click the same header again to flip direction. Type inference runs underneath, so numeric columns sort as numbers without being asked.
CSV ▸ Sort Rows… is the full instrument: any column, compared six ways: Text (case-insensitive), Text (case-sensitive bytes), Natural (Finder-style, so file2 sorts before file10), Numeric, Currency (symbols and thousands separators stripped; accounting (1,234.56) reads as negative), and Date: ascending or descending, with a secondary “Then by” column for ties and the header row kept in place. Sorts are stable (equal keys keep their original order) and move rows verbatim, never reformatting content: two million rows sort in 8.2 s (measured). An explicit type choice sticks for the session, so later header clicks keep treating the column the way you told it to; currency-heavy columns are detected automatically. Files beyond the in-place rewrite cap aren't sorted blind; Caxton offers to stream the sorted result to a new document instead.
A sort you use twice is worth a name: the dialog's Preset menu saves the whole configuration (columns, types, direction, header handling) and re-applies it to any file from the same menu.
Sorted by the numeric count column: 1,000,100 rows moved verbatim, one undo step.
Editing cells
Double-click a cell to edit it in place. Edits write through to the underlying text, participate in normal undo/redo, and re-align the grid immediately.
Growing the table is a click at either edge: a + past the last header cell appends a column, and the empty row past the end carries a + in its gutter that appends a row with the first cell selected, ready to type. Typing straight into that empty row works too, and so does typing past the last column: one empty column always waits at the right edge, and committing a value there adds the column with the value at that row. Structural edits (rows, columns, fills) apply in place, so the view stays where you are working instead of jumping to the top.
In-place cell editing on a million-row file. Esc cancels; Return commits.
Cells the inline editor can't do justice (multiline values, very long fields) open in the full-value editor (CSV ▸ Edit Cell Value…, right-click ▸ Edit Full Value…, or simply by editing such a cell): a real text view in a sheet. Edit the decoded value and quoting is handled for you on save, or flip to Raw (as stored) to see and edit the field's exact bytes, quotes and all: deliberate structure surgery, settled by a full reparse. ⌘↩ saves, Esc cancels.
A multiline cell in the full-value editor: decoded view, with Raw a checkbox away.
Short rows show their missing tail cells dimmed, “not part of the row” at a glance. Editing a dimmed cell materializes it: the row is padded out to that column, one undo step.
Fill and Fill Series
The selection grows a fill handle at its corner. Drag it in any direction and Caxton continues what the selection started, showing a live preview of the cell count and last value: a single value copies, 10, 20 continues 30, 40, Item01 becomes Item02 with its padding intact, and dates advance by real calendar rules: month ends stay month ends, February 29 returns in the next leap year. Irregular values repeat as a pattern rather than inventing a trend. Hold ⌥ to copy instead of continuing.
Right-click ▸ Fill Series… opens the full dialog: linear and growth series; date and time steps from seconds to years; text-plus-number patterns; weekday and month name lists; or an exact repeat of the selection, terminated by the selection, a count, or a stop value, optionally writing only into empty cells, with a preview of exactly what will be written. Decimal arithmetic is exact: 0.1, 0.2 continues 0.3, never 0.30000000000000004.
Fill Down ⌘D, Fill Up, Fill Right ⌘R, and Fill Left copy the selection’s edge across it, Excel-style. Every fill is one undo step, and very large fills state how many cells they will replace before running.
Selection
Drag across cells (or ⇧-click) for a rectangular range; click row numbers or column headers and drag for whole rows and columns. Any selection copies as proper delimited text, and blocks paste back in (including straight from Excel or Google Sheets) as one undo step. Pasting a single value into a selected range fills the range. Raw delimited text spreads as well: comma or semicolon separated lines pasted into a cell land as cells and rows, quotes respected, and pasted into a blank sheet they become the whole table. A paste wider than the table clips the overflow evenly and the banner counts what was dropped.
Selected rows and columns move by drag and delete with ⌫. Column edges drag to resize; double-click an edge to auto-fit the column, and double-click a header cell to rename it in place.
A whole-column selection is a full column context: with a header clicked, Insert/Delete/Move/Split/Combine Column, Extract Column, and Count Frequent all enable directly, and the sort and filter dialogs preselect that column.
Select more than one cell and the status bar answers the first questions you'd ask: cell count, sum, average, how many are numeric, how many blank, computed off the main thread, with an honest “first N scanned” note on very large selections.
Columns in view
Hide Column tucks columns out of sight without touching the data (operations and copies still include them, Excel-style), and Show All Columns brings everything back. Freeze Columns pins the first one to three (or everything up to the selected column) so identifiers stay put while you scroll wide files. Auto-Fit All Columns sizes every column to its content, and widths, hidden flags, and sort choices follow their columns through moves, inserts, and deletes.
Scrolled deep into a 50-column file: the first two columns stay pinned while the rest scroll.
⌘L in the grid is Go to Cell: type 5000 for a row or 5000:12 for an exact cell, header-aware, and honest when a row filter hides the target.
Header tools
Promote Row to Header lifts any row to the top and turns the header on: one undo step, the old header stays as data. Rename Column… opens the header cell for editing (double-clicking it does the same). Add Header Row generates Column1…ColumnN placeholders above headerless data. Duplicate header names are preserved in the file; pickers stay unambiguous because every column title carries its number (“3: amount” vs “7: amount”).
Numbered columns without a header row
When First Row Is Header is off, the grid shows a frozen numbered band (1, 2, 3…) so columns keep their identity. It behaves exactly like a real header: click to select a column, drag to select several, drag edges to resize, click the sort affordance to sort. Dialogs use the same numbers, so “column 3” means the same thing everywhere.
Headerless data with the numbered band pinned at the top; column 3 selected by clicking its number.
Advanced Row Filter
CSV ▸ Advanced Filter… (or the filter bar's panel button while in the grid) filters rows with multiple conditions. Each condition targets the whole line, any column, or one specific column, with Contains, Does Not Contain, Equals, Greater Than, or Less Than (the comparisons are numeric: both sides must parse; Does Not Contain on the any-column scope means no field contains the text), match case, ≠ exclude, and and/or chaining, where AND binds tighter than OR. Whole-line conditions test the raw record, so a query containing a comma can match across fields, which per-column filtering can't. The panel keeps its conditions between opens, so a filter can be tweaked and re-run; Clear Row Filter restores everything.
Three conditions, three scopes: a whole-line match, a column equality, and an any-column exclude, chained with and/or.
Filter by Column Values
CSV ▸ Filter by Column Values… is the checkbox filter: every distinct value in a column, with its count, most frequent first. Search the list, check what you want to see, Apply. Lists cap at 10,000 distinct values and say so, and with everything checked, no filter is applied, because a truncated list can't honestly exclude what it never showed.
Distinct values with counts on a two-million-row column: search, check, apply.
Right-clicking a cell offers the same power one click at a time: Filter to the cell's value, Exclude it, or filter Greater Than / Less Than a numeric value.
Row filters and the text filter bar can both drive the grid; the last one you apply wins, a banner says what happened, and clearing one hands the view back to the other. Nothing is ever silently overwritten.
Filtering in the grid
The text filter engine works in grid mode too: conditions apply to whole records, and the grid shows only matching rows.
Filtered to matching records: the grid mirrors the filter with original row numbers intact.
The CSV menu
Everything in the CSV menu operates on the whole file consistently: every row rewritten, undo as one step:
- Row & column surgery: insert/delete rows, insert/delete/move columns.
- Sort Rows…: the typed, two-key sort described above.
- Split Column… / Combine with Next Column…: split each value at the first separator or at a character position; or merge two adjacent columns with a separator of your choice.
- Insert Sequential Numbers…: add a numbered column before the selected one, starting at any value, with a “#” header.
- Extract Column to New Document: pull a column out as its own file.
- Remove Embedded Newlines…: flatten multi-line cells.
- Transpose: swap rows and columns (up to 100,000 cells).
- Delete Duplicate Rows…: match on all columns or a chosen subset; keep the first occurrence, the last, or none; or bookmark duplicates instead of deleting them.
- Count Frequent Values in Column: a ranked frequency table.
- Advanced Filter…: the multi-condition row filter described above; Clear Row Filter restores.
- Convert Delimiter: rewrite as CSV, TSV, pipe, semicolon, or a custom delimiter.
- Quote All Cells / Remove Unnecessary Quotes: force RFC 4180 quotes onto every cell, or strip the decorative ones; rows with quoting problems are never touched.
- Normalize Column Count…: pad short rows to the expected width with empty cells; optionally trim rows with surplus cells.
- Convert Fixed-Width to Columns…: split a fixed-width text file at the character widths you give into a new delimited document, with a live preview of the first line. Works from the text view, at any file size.
- Edit Cell Value… / Rename Column… / Promote Row to Header / Add Header Row: the cell editor and header tools described above.
- Hide Column / Show All Columns / Freeze Columns / Auto-Fit All Columns: the view controls described above.
- Filter by Column Values…: the checkbox value filter described above.
- First Row Is Header: toggle header-row treatment.
Malformed files
Rows that don't parse cleanly get explicit parse states rather than silent guesses; you can see exactly which rows are suspect and why, and the raw text view is always one keystroke away. Short rows show their missing cells dimmed, Normalize Column Count… repairs widths in one undoable pass, and classic-Mac CR-only files are detected and open in the grid like any other CSV.