A fast, privacy‑first spreadsheet editor for the browser. Open CSV or Excel
files (.csv / .xlsx / .xls / .tsv), work on them like a real spreadsheet,
and save them back — no account, no server, no build step.
Everything runs locally in your browser; your data never leaves your machine.
The one exception, made explicit: the Photo → table (OCR) feature loads Tesseract.js from a CDN the first time you use it, and Tesseract processes your image in your browser. That OCR path is the only part of the app that touches a network. Everything else — editing, formulas, Excel import/export, and the one‑click HTML report — happens fully offline. (There is also an optional web font for the UI.)
index.html → the page shell
styles.css → the design system
app.js → all application logic
parsing.worker.js → large-file parsing off the main thread
xlsx.full.min.js → SheetJS (Excel .xlsx import/export), vendored — loaded as a plain <script>, no build
That's the whole app. No build step and no runtime dependencies — open index.html
and it runs. The only third‑party file is SheetJS, committed straight into the repo so
there is nothing to install. (There is a minimal package.json, but it exists only
to describe the optional test runner in tests/; the app never uses it.)
One network dependency, disclosed: the Photo → table (OCR) feature loads Tesseract.js from a CDN the first time you use it. That OCR pass is the only part of the app that touches a network — everything else, including the one‑click HTML report, runs fully offline.
Everything you do has a shortcut — and you can bring them all up in‑app with
? (or the hint in the status bar): arrow navigation, Shift+Arrow range
extension, Enter/Tab commit, F2 formula‑bar edit, ⌘/Ctrl+C/Z/S/D,
⌘/Ctrl+B/I/U formatting, and more. It's fast even at scale because only the
visible rows are in the DOM.
Live demo → akhlas17.github.io/web-based-csv-editor
Full key list: CHEATSHEET.md — or press
?inside the app.
The interface is built to feel like a real spreadsheet rather than a web widget: a neutral grey command bar up top, a Excel‑style sheet tab and a clean status bar at the bottom, and a spreadsheet grid beneath. The accent is the familiar Excel green on file, selection, and the active sheet — and the whole chrome reads naturally in both light and dark themes (toggle in the top‑right).
There is nothing to install. Either open index.html directly in your browser,
or serve the folder:
python3 -m http.server 8000
# → http://localhost:8000Then open a file (or drop it onto the window) and you're editing.
- Open CSV / Excel files (
.csv,.xlsx,.xls,.tsv) by picking one, dragging one in, or pasting (CSV/TSV) from the clipboard - Open a photo as a table (OCR) — hit 📷 Photo → table on the toolbar and choose a PNG/JPEG/WebP screenshot or photo of a table. Tesseract.js (loaded lazily from a CDN on first use) reads the text out in your browser, and a heuristic splits it into rows and columns — tab/pipe/whitespace layouts and plain word grids. The result lands in the grid and is fully editable before you keep working. This is the only feature that touches a network (the Tesseract download); your image is processed in the browser and never uploaded
- Edit like a spreadsheet
Enter/Space— start (or move-edit) the active cellTab/Shift+Tab— move to the next / previous cell↑↓←→— move the active cellShift + ↑↓←→— extend the selection range from the anchor (like Google Sheets)Ctrl/Cmd+A— select the whole gridCtrl/Cmd+B/I/U— bold / italic / underline the selectionBackspace/Delete— clear the selected cells- Save on blur — click away, press a key, or move on; the value is never lost
- Selection engine — click a cell, row number, or column header; drag to multi-select; the whole grid, a row, a column, or any rectangular range
- Right-click context menu — a two-pane menu with a left category rail
(Clipboard · Text · Format · Fill · Sort · Rows · Columns · Freeze) and the items
for the active category on the right; hover to switch categories or use the
arrow keys (
←/→category,↑/↓item,Enterrun,Escclose). The items adapt to what you right-click — a cell, a row, or a column header - Statistics bar — live
Σ Sum/x̄ Average/min/max/n Countfor the selection, with aΣ moremenu; understands$,%,(1,234)negatives, and dates - Automatic formatting (Google-Sheets style): numbers, percentages, currency and dates right-align with tabular figures, negatives highlight in red, text and booleans align left
- Manual formatting — Bold / Italic / Underline (toolbar buttons, or
Ctrl/Cmd+B/I/U), Align left / center / right, Word wrap (tall rows for wrapped text), and Clear formatting — applied to any selection, all in the context menu too, all undo-able and remembered with the file - Formulas — type
=into any cell (or the formula bar) and compute:- Arithmetic —
+ - * / ( ), unary minus, Excel-style trailing%(=Salary*0.10,=16%*100) - Functions —
SUM,AVERAGE,MIN,MAX,COUNTover a cell, range (A1:B3), whole column (C:C), or a header-name alias (=SUM(Salary)) - Live recompute — values update as source cells change; circular
references are caught and show
#CYCLE!; errors (#DIV/0!,#VALUE!,#REF!,#NAME?) render right in the grid like Excel - Integrates everywhere — resolved values drive the grid (right-aligned
numbers), the statistics bar, sorting, and copy & export (
Ctrl+CandCtrl/Cmd+Syield computed values, not formula text) - Formula bar — name box (
C3) + editable input;Entercommits,Escreverts,F2jumps in; clicking another cell commits first, then moves (Excel semantics)
- Arithmetic —
- Auto-filter — click a column's funnel to open an Excel‑style filter with
five modes, plus a live match count as you tweak it:
- In list — multi‑select the exact values to keep (with per‑value counts), plus a search box to narrow the value list while you pick (Google‑Sheets style — hidden values stay checked, so you never lose a selection).
- Contains / Starts‑with — case‑insensitive text filters
- Is — exact match · Is empty — keep only blank cells
- Multiple columns combine with AND; the status bar shows
Col: kept/totalper column, and filtered columns keep their blue funnel on the header
- Charts — hit Chart (toolbar) over a selection to preview a Bar, Line or Pie chart on a live canvas; "Show" pins it in a floating panel that redraws automatically as you edit the data. One numeric column = bars against that column's labels; several columns = one series each; formulas resolve to their numbers for the chart
- Copy as —
Copy as ▾turns the selection into Markdown (| a | b |table), JSON (array of objects, numbers stay numbers), or SQL (INSERT INTO …statements with proper quote escaping) — all written to the clipboard - Conditional formatting — the Format button adds highlight rules to a selection: is / is not / greater-than / at-least / less-than / at-most / contains / between / top-N / bottom-N / blank, each with a color swatch. First matching rule wins; colors are drawn live as the data changes, and the rules are undo-able and remembered with the file
- Data tools
- Fill down (
Ctrl/Cmd+D) and Fill right (Ctrl/Cmd+Shift+R) - Case conversion: lowercase / UPPERCASE / Title Case
- Find & Replace (
Ctrl/Cmd+H) with match-case and whole-cell options - Sort any column by value (numeric or text) — one toggle per header cycles unsorted → A→Z → Z→A (a small arrow shows the active direction)
- Per-column duplicate and move up / down
- Add / delete rows and columns, insert above/below and left/right
- Fill down (
- Layout — resizable columns (drag the grip, double‑click to auto‑fit), widths remembered per file; sticky header; light & dark themes
- Freeze panes — the Freeze button pins the top 1 / 2 / 3 / 5 rows so they stay visible while the rest of the grid scrolls; right-click any row and choose Freeze rows above to freeze everything above that row (or Unfreeze to clear it). Frozen rows keep working (edit, select, delete) and the freeze count is remembered with the file
- Move safely — Undo / Redo (
Ctrl/Cmd+Z,Ctrl/Cmd+Shift+Z) - Autosave to
localStorage— revisit the same grid later - Export to
.csv(button, orCtrl/Cmd+S) or to Excel.xlsxfrom the Export menu — numbers, booleans and computed formula values are written as native Excel cells (summable); Open also reads.xlsx/.xlsstraight back in - Share as a report — the Report button (or Export ▸ HTML report)
produces a single self‑contained
.htmlfile with a snapshot of the current grid: a summary (rows, columns, types, per‑column stats), per‑column type badges, a lightweight SVG bar chart for any numeric column, and a data table. It has zero external assets and zero JavaScript — send the file anywhere and it renders identically offline, and it's stamped "data never left your machine" - Big files stay fast — DOM virtualization keeps the grid responsive at tens of thousands of rows, and parsing runs in a Web Worker so the UI never freezes
The app ships with a small sample dataset so you can feel the keyboard flow
immediately. Press Enter on any cell, Tab through it, sort a column, then hit
Ctrl/Cmd+S to save as CSV — or open the Export menu to write .csv, .tsv,
or Excel .xlsx (and to open an .xlsx file back in). Hit Report to grab a
portable single‑file HTML snapshot, or 📷 Photo → table to turn a picture of a
table into an editable grid.
The app is a single‑page module with no framework and no state library: one
state object is the source of truth, and every change calls render() to
re‑draw the visible part of the grid. Because of virtualization, only the rows
inside the viewport (plus a small overscan buffer) ever exist in the DOM — that
is what makes large files cheap to scroll.
A few places that are friendly to tinker with:
app.js → renderHeader()/renderBody()— the row and column renderingapp.js → parseText()/parsing.worker.js— the RFC‑4180 CSV parserstyles.css— a token‑based design system (colors, spacing, fonts via CSS custom properties under:root)
The app is plain JavaScript, so a browser devtools console is the fastest way to inspect state while you work. There is no build step to keep green.
There is no build step to keep green, so the tests are a thin browser harness in
tests/ — they drive the real app (served locally with python3 -m http.server)
through Playwright and assert on observable behaviour: edit/undo, the filter panel,
Backspace handling, index‑remap, Excel round‑trip, accessibility, the one‑click
HTML report builder, and the OCR text→table heuristic.
# one‑time setup (Playwright is a dev-only tool; the app itself still has no deps)
npm i -g playwright && npx playwright install chromium
# run the whole suite
npm test # → node tests/run-tests.cjsWe welcome contributions. The bar is simple: small, focused, working. Please read CONTRIBUTING.md for how to set up, what we accept, and how to open a good pull request.
MIT — do whatever you want, just keep the attribution.