Skip to the solution
HardMachine Coding13 min read

Build a Mini Spreadsheet (Excel)

691 views

The problem

Question presented to candidate: "Build a small Excel: a grid of cells with column letters and row numbers. A cell holds a number, some text, or a formula such as =A1+B2 or =SUM(A1:A3). When a cell changes, everything that depends on it updates. Do not use eval, and do not freeze or crash when someone types a circular formula."

Requirements:

  • A 5 x 8 grid (A to E, 1 to 8) with a formula bar showing the raw content of the selected cell.
  • Formulas: numbers, cell references, + - * /, parentheses, unary minus, and SUM, AVERAGE, MIN, MAX over ranges and arguments.
  • Errors shown in the cell: #DIV/0!, #NAME? (unknown function), #REF! (outside the grid), #VALUE! (text in arithmetic), #ERROR! (syntax), #CYCLE! (circular reference).
  • Changing a cell recalculates only that cell and its dependents, in dependency order; show the recalculation order.
  • Excel-like editing: click to select, type to start editing, Enter commits and moves down, Tab commits and moves right, Escape cancels, arrows move the selection, Delete clears.

What a strong answer should cover:

  • A tokenizer and a recursive-descent parser that builds an AST with correct precedence, evaluated by a small interpreter: never eval or new Function.
  • A dependency graph (cell to the cells it reads) and its reverse (cell to the cells that read it).
  • Recalculation as a topological sort of the dirty set (the edited cell plus its transitive dependents), for example with Kahn's algorithm.
  • Cycle detection that falls out of the topological sort (nodes that never reach in-degree 0), marking those cells instead of recursing forever.
  • Keeping the engine framework-free and telling the UI to re-read it after each commit.

Clarifying questions expected:

  • "Which functions and operators must be supported, and should text be allowed in cells?"
  • "How should errors look, and should an error propagate to dependent cells?"
  • "Do we need absolute references like $A$1, copy and paste, or undo?"

Code / implementation expected: Yes. The parser, the dependency-aware recalculation and an editable grid.

  • React
  • Grid
  • Formulas

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

13 min read ยท 9 sections

React solution

Every file of the working solution. Open it in the playground to run and change it.

ReactComplete solution
import Spreadsheet from "./src/components/Spreadsheet";

const css = `
  body { margin: 0; background: #0f1115; color: #e6e6e6; font-family: system-ui, sans-serif; }
  .page { max-width: 760px; margin: 0 auto; padding: 20px 16px; }
  .ss-bar { display: flex; gap: 8px; margin-bottom: 8px; }
  .ss-name { min-width: 44px; padding: 6px 8px; border: 1px solid #2c3340; border-radius: 6px; background: #171a21; text-align: center; font: 600 13px ui-monospace, monospace; }
  .ss-bar input { flex: 1; min-width: 0; padding: 6px 8px; border: 1px solid #2c3340; border-radius: 6px; background: #0f1115; color: #e6e6e6; font: 13px ui-monospace, monospace; }
  .ss-scroll { overflow-x: auto; border: 1px solid #2c3340; border-radius: 8px; }
  table { border-collapse: collapse; width: 100%; min-width: 520px; font-size: 13px; }
  th { background: #171a21; color: #8b949e; font-weight: 500; padding: 4px 6px; border: 1px solid #262c36; }
  td { border: 1px solid #262c36; padding: 0 6px; height: 28px; min-width: 80px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 120px; cursor: cell; }
  td.num { text-align: right; font-variant-numeric: tabular-nums; }
  td.err { color: #ff8a80; }
  td.sel { outline: 2px solid #f9a825; outline-offset: -2px; background: #1c140a; }
  td input { width: 100%; box-sizing: border-box; border: 0; background: #1c140a; color: #ffe0b2; font: 13px ui-monospace, monospace; outline: none; padding: 4px 0; }
  .ss-status { font-size: 13px; color: #9aa4b2; }
`;

export default function App() {
  return (
    <main className="page">
      <style>{css}</style>
      <h1 style={{ fontSize: 18 }}>Budget</h1>
      <Spreadsheet />
    </main>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 89 of 107 in Machine coding

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextHard

Build a Date Picker Calendar with Range Selection

Continue