Formula Bar

Display and edit cell formulas and values

The Formula Bar is a compound component that displays the active cell reference and allows users to view and edit cell values and formulas. It consists of three main sub-components: FormulaBar, FormulaBarLabel, and FormulaBarInput.

Overview

The Formula Bar provides:

  • Cell reference display: Shows the active cell address (e.g., "A1", "Sheet2!B5")

  • Formula editing: Edit cell formulas and values in a larger input area

  • Formula preview: View complete formulas without cell width constraints

  • Function hints: Display function syntax and autocomplete

Components

FormulaBar

The parent container that wraps the formula bar components.

import { FormulaBar, FormulaBarLabel, FormulaBarInput } from "@rowsncolumns/spreadsheet";

<FormulaBar>
  <FormulaBarLabel>A1</FormulaBarLabel>
  <FormulaBarInput
    value="=SUM(A1:A10)"
    onChange={handleChange}
  />
</FormulaBar>

FormulaBarLabel

Displays the active cell reference or range.

import { FormulaBarLabel } from "@rowsncolumns/spreadsheet";
import { cellToAddress } from "@rowsncolumns/utils";

function MyFormulaBar() {
  const { activeCell, activeSheetId, selections } = useSpreadsheetState({});

  const label = selections.length > 1
    ? selectionToAddress(selections[0])
    : cellToAddress(activeCell);

  return (
    <FormulaBarLabel>
      {label}
    </FormulaBarLabel>
  );
}

FormulaBarInput

Input field for editing cell values and formulas.

import { FormulaBarInput } from "@rowsncolumns/spreadsheet";

<FormulaBarInput
  value={cellValue}
  onChange={(value) => onChange(activeSheetId, activeCell, value)}
  onKeyDown={handleKeyDown}
  functionDescriptions={functionDescriptions}
/>

Complete Example

import React, { useState } from "react";
import {
  SpreadsheetProvider,
  CanvasGrid,
  FormulaBar,
  FormulaBarLabel,
  FormulaBarInput,
  Sheet,
} from "@rowsncolumns/spreadsheet";
import {
  useSpreadsheetState,
  SheetData,
  CellData,
} from "@rowsncolumns/spreadsheet-state";
import { cellToAddress, selectionToAddress } from "@rowsncolumns/utils";
import { functionDescriptions } from "@rowsncolumns/functions";

function SpreadsheetWithFormulaBar() {
  const [sheets, setSheets] = useState<Sheet[]>([
    { sheetId: 1, rowCount: 100, columnCount: 26, title: "Sheet 1" }
  ]);
  const [sheetData, setSheetData] = useState<SheetData<CellData>>({});

  const {
    activeCell,
    activeSheetId,
    selections,
    getCellData,
    getSheetName,
    onChangeActiveCell,
    onChangeSelections,
    onChange,
  } = useSpreadsheetState({
    sheets,
    sheetData,
    onChangeSheets: setSheets,
    onChangeSheetData: setSheetData,
  });

  // Get current cell data
  const cellData = getCellData(
    activeSheetId,
    activeCell.rowIndex,
    activeCell.columnIndex
  );

  // Determine label (cell reference or range)
  const formulaBarLabel = selections.length > 0 && selections[0]
    ? selectionToAddress(selections[0])
    : cellToAddress(activeCell);

  // Get cell value (formula or formatted value)
  const cellValue = cellData?.userEnteredValue?.formulaValue
    || cellData?.formattedValue
    || "";

  return (
    <SpreadsheetProvider>
      <div className="flex flex-col h-screen">
        {/* Formula Bar */}
        <FormulaBar>
          <FormulaBarLabel>{formulaBarLabel}</FormulaBarLabel>
          <FormulaBarInput
            value={cellValue}
            onChange={(value) => {
              onChange?.(
                activeSheetId,
                activeCell,
                value,
                cellData?.formattedValue
              );
            }}
            functionDescriptions={functionDescriptions}
            getSheetName={getSheetName}
          />
        </FormulaBar>

        {/* Spreadsheet Grid */}
        <div className="flex-1">
          <CanvasGrid
            sheetId={activeSheetId}
            activeCell={activeCell}
            selections={selections}
            getCellData={getCellData}
            onChangeActiveCell={onChangeActiveCell}
            onChangeSelections={onChangeSelections}
            onChange={onChange}
            functionDescriptions={functionDescriptions}
          />
        </div>
      </div>
    </SpreadsheetProvider>
  );
}

export default SpreadsheetWithFormulaBar;

Props

FormulaBar

Prop
Type
Description

children

React.ReactNode

Child components (FormulaBarLabel, FormulaBarInput)

className

string

Optional CSS class name

FormulaBarLabel

Prop
Type
Description

children

React.ReactNode

Cell reference text (e.g., "A1", "B2:D5")

className

string

Optional CSS class name

FormulaBarInput

Prop
Type
Description

value

string

Current cell value or formula

onChange

(value: string) => void

Callback when value changes

onKeyDown

(e: React.KeyboardEvent) => void

Optional keyboard handler

functionDescriptions

CalculatorFunction[]

Function definitions for autocomplete

getSheetName

(sheetId: number) => string

Get sheet name by ID

className

string

Optional CSS class name

Features

Formula Autocomplete

The FormulaBarInput supports autocomplete for functions when functionDescriptions is provided:

import { functionDescriptions, functions } from "@rowsncolumns/functions";

<FormulaBarInput
  value={cellValue}
  onChange={onChange}
  functionDescriptions={functionDescriptions}
/>

When users type =SUM(, the input shows function hints and parameter information.

Multi-Cell Selection Display

When multiple cells are selected, the label shows the range:

const label = selections.length > 0 && selections[0]
  ? selectionToAddress(selections[0])  // "A1:E10"
  : cellToAddress(activeCell);         // "A1"

<FormulaBarLabel>{label}</FormulaBarLabel>

Named Range Display

Show named range when applicable:

const getFormulaBarLabel = () => {
  // Check if selection is a named range
  const selection = selections[0];
  const namedRange = namedRanges.find(nr =>
    rangesEqual(nr.range, selection?.range)
  );

  if (namedRange) {
    return namedRange.name; // "SalesData"
  }

  return selectionToAddress(selection) || cellToAddress(activeCell);
};

Cross-Sheet References

Display sheet names in cross-sheet references:

import { getSheetName } from "@rowsncolumns/spreadsheet-state";

const label = activeSheetId !== 1
  ? `${getSheetName(activeSheetId)}!${cellToAddress(activeCell)}`
  : cellToAddress(activeCell);

<FormulaBarLabel>{label}</FormulaBarLabel>

Keyboard Shortcuts

The Formula Bar supports standard keyboard shortcuts:

  • Enter: Confirm and move to next cell

  • Escape: Cancel editing

  • Tab: Autocomplete function name

  • F2: Edit cell in formula bar

  • Ctrl/Cmd + A: Select all text

Styling

The Formula Bar can be styled using CSS classes:

<FormulaBar className="border-b bg-white">
  <FormulaBarLabel className="font-mono text-sm px-3 py-2 border-r bg-gray-50" />
  <FormulaBarInput className="flex-1 px-3 py-2 font-mono text-sm" />
</FormulaBar>

Integration with Toolbar

Combine with toolbar for a complete spreadsheet interface:

import { Toolbar, FormulaBar } from "@rowsncolumns/spreadsheet";

<div className="flex flex-col h-screen">
  <Toolbar>
    {/* Toolbar buttons */}
  </Toolbar>

  <FormulaBar>
    <FormulaBarLabel>{label}</FormulaBarLabel>
    <FormulaBarInput value={value} onChange={onChange} />
  </FormulaBar>

  <div className="flex-1">
    <CanvasGrid {...props} />
  </div>
</div>

Advanced Usage

Custom Formula Validation

Validate formulas before applying:

const handleFormulaChange = (value: string) => {
  if (value.startsWith("=")) {
    // Validate formula syntax
    try {
      validateFormula(value);
      onChange(activeSheetId, activeCell, value);
    } catch (error) {
      console.error("Invalid formula:", error);
    }
  } else {
    onChange(activeSheetId, activeCell, value);
  }
};

<FormulaBarInput
  value={cellValue}
  onChange={handleFormulaChange}
/>

Formula Highlighting

Highlight cell references in formulas:

const highlightedFormula = useMemo(() => {
  if (!cellValue.startsWith("=")) return cellValue;

  // Highlight cell references (A1, B2:C5, etc.)
  return cellValue.replace(
    /([A-Z]+[0-9]+)(:[A-Z]+[0-9]+)?/g,
    '<span class="text-blue-600 font-semibold">$&</span>'
  );
}, [cellValue]);

Read-Only Mode

Disable editing in read-only mode:

<FormulaBarInput
  value={cellValue}
  onChange={readonly ? undefined : onChange}
  readOnly={readonly}
/>

Best Practices

  1. Always Show Cell Reference: Display the current cell or range reference in FormulaBarLabel

  2. Sync with Active Cell: Update formula bar when active cell changes

  3. Handle Long Formulas: Ensure the input can scroll for long formulas

  4. Provide Function Hints: Include functionDescriptions for better UX

  5. Validate Input: Check for formula errors before applying changes

  6. Support Keyboard Navigation: Implement standard spreadsheet keyboard shortcuts

Troubleshooting

Formula Bar Not Updating

  • Verify activeCell and selections are properly synced

  • Check that getCellData returns the correct cell data

  • Ensure onChange is called when cell values change

Autocomplete Not Working

  • Confirm functionDescriptions prop is provided

  • Check that function definitions are properly formatted

  • Verify the formula starts with "="

Performance Issues

  • Memoize cellValue calculation for large spreadsheets

  • Use debouncing for onChange handler

  • Consider lazy loading function descriptions

See Also

Last updated

Was this helpful?