Try a preview of our new docs site here: docs.treb.app
Embedding
You can embed a spreadsheet in a webpage or blog with a single script tag. When it runs, in will insert the spreadsheet and add any required dependencies.
This section talks about embedding a spreadsheet in a simple web page. If you are using a front-end framework like React or Svelte, jump ahead to the frameworks section.
Basic Embedding
Here’s the simplest possible HTML page that loads a spreadsheet:
<html>
<body>
<script src="https://treb.app/treb/current/embed.js" data-treb></script>
</body>
</html>
Open this example page in your browser
We try to keep the core library a reasonable size (it’s about 160K gzipped) so some functions are moved into support libraries that are loaded on demand. If you are running from your own webserver, as long as the files are in the same directory they’ll get loaded as needed.
Loading a document
TREB has a native document format, using JSON. It’s compact and efficient (actually it’s somewhat verbose, but it’s designed to compress well). TREB can also read CSV, TSV and XLSX files.
We recommend using JSON files if possible. CSV/TSV files don’t retain style information, or support multiple sheets, and XLSX files are huge and slow to read. It’s easy to convert existing XLSX or CSV/TSV files to our native format, so we suggest that you do that and serve JSON files. But you can point to any file you like.
To load a file in the embedded spreadsheet, you pass the file as a value for the data-treb
attrribute. So for example:
<script src="https://treb.app/treb/current/embed.js"
data-treb='https://treb.app/doc/sample.treb.json'></script>
This will create a TREB component and load the linked file:
Other ways to embed
Script tag
The script above is a loader which adds the actual script tags to the document, adds a div element for the spreadsheet, and then inserts the markup. If you want a little more control you can add the script files manually, and then either use div tags to insert spreadsheets or use the API.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<script defer type="module" src="https://treb.app/treb/current/treb-bundle.js"></script>
</head>
<body>
<!-- insert the spreadsheet in this div tag -->
<div data-treb></div>
</body>
</html>
Open this example page in your browser
In this case, any <div/>
tag that has a data-treb
attribute will be replaced with a spreadsheet. As in the previous example, you can load a document by setting the document URI as the value of the data-treb
attribute.
IFrame
The above examples include the script directly in the page. If you want to fully isolate the spreadsheet script, for security or other reasons, you can use an iframe. The download includes a page intended for embedding in an iframe.
<iframe style='border:0; width: 500px; height: 400px'
src='https://treb.app/treb/current/frame.html' ></iframe>
When using an iframe, you can pass options to the spreadsheet using GET
parameters in the src
URL (see below for a list of options). To load a document, use the parameter doc=URL
. For example,
<iframe style='border:0; width: 500px; height: 400px'
src='https://treb.app/treb/current/frame.html?doc=https://treb.app/doc/single-factor-sensitivity.treb.json' ></iframe>
Open an example page using an IFrame
Frameworks
If you are using a front-end framework, you can use our node module to add spreadsheets to your web app.
Add the library using npm/yarn/pnpm
> npm add -D @trebco/treb
Here’s how to use it in a React component:
import React from 'react';
// import TREB module
import { TREB, type EmbeddedSpreadsheetOptions } from '@trebco/treb';
// import TREB stylesheet
import '@trebco/treb/treb-bundle.css';
class SpreadsheetComponent extends React.Component<{ options?: EmbeddedSpreadsheetOptions }> {
// reference to our DOM node
public container: React.RefObject<HTMLDivElement>;
constructor(props) {
super(props);
this.container = React.createRef();
}
public componentDidMount() {
const options: EmbeddedSpreadsheetOptions = this.props.options || {};
TREB.CreateSpreadsheet({
...options,
container: this.container.current,
});
}
public render() {
return (
<div ref={this.container}></div>
);
}
}
export default SpreadsheetComponent;
Here’s how to use it in a Svelte component:
<script lang="ts">
// import the onMount handler from svelte
import { onMount } from 'svelte';
// import TREB module and options type
import { TREB, type EmbeddedSpreadsheetOptions } from '@trebco/treb';
// import stylesheet
import '@trebco/treb/treb-bundle.css';
// pass any options as a parameter
export let options: EmbeddedSpreadsheetOptions = {};
// reference to the HTML node we will use to mount the spreadsheet
let container: HTMLElement;
onMount(() => {
// create spreadsheet, passing options and a reference to the container node
TREB.CreateSpreadsheet({
...options,
container,
});
});
</script>
<div bind:this={container}></div>
Layout & styling
Use standard CSS or inline styles on the containing element (the element that has the data-treb
attribute) to set a size for the embedded spreadsheet. If you don’t, it will use a default size.
You can style the spreadsheet with CSS; see the gallery page for more. But note that because the spreadsheet cells are painted, they won’t automatically update to changes in CSS. You should call the UpdateTheme
API method any time you modify the stylesheet to ensure the spreadsheet is updated.
Configuration
To configure the spreadsheet, add a data-options
attribute to the tag with the options you want. For example,
<div data-treb='https://treb.app/doc/sample.treb.json' data-options='toolbar,scroll=C2'></div>
Compared to the previous example, this one adds the toolbar button to the sidebar and scrolls the document to C2:
Separate embedded spreadsheets on the same web page are independent.
Options
Mulitple options can be passed as a data-options
argument separated by commas. Configuration options can be boolean (true or false) or take a value.
To set an option to true, it’s sufficient to just pass the option, so toolbar
is the same as toolbar=true
. To set another value, pass the value as toolbar=false
, tab_bar=auto
or scale=1.1
.
Available options include:
Option | Default | Description |
---|---|---|
dnd | false | Allow drag-and-drop of supported files (XLSX, CSV, TSV or treb files) |
expand | false | Allow expanding the spreadsheet. By default, the spreadsheet retains its size (number of rows and columns) |
storage_key | Save changes to browser localStorage, using the given name. If the name exists in localStorage, the modified document will be loaded instead of the original. | |
formula_bar | true | Show the formula bar |
expand_formula_button | false | Show the "expand formula" button (multiple rows) |
scroll | Scroll to the given address when the document is loaded | |
sheet | Open the named sheet (tab) when the document is loaded | |
resizable | true | Allow resizing the spreadsheet, and add the resize handle |
export | true | Show the "download as XLSX" button allowing export of the document |
popout | true | Show the "open in new tab" button |
headers | true | Show row/column headers |
recalculate | false | Recalculate on load. By default, only volatile functions (like DATE and NOW) will update on load. |
scrollbars | true | Show document scrollbars. If scrollbars are disabled, the document cannot be scrolled |
tab_bar | "auto" | Show the tab bar (pages or sheets). Setting to `auto` (the default) will show the tab bar if there are multiple sheets and hide it otherwise. |
add_tab | false | Allow adding sheets; sheets can be added either via the structure menu (in the toolbar) or via the add sheet button in the tab bar. |
delete_tab | false | Show the delete tab button in the tab bar |
collapsed | false | Start with the sidebar hidden |
global_name | Create a global variable for the spreadsheet (like on the front page of this website). This can be handy for debugging. | |
toolbar | false | Show the toolbar button. Set to "show" to show the toolbar on load |
scale | 1.0 | Set the view scale |
scale_control | false | Show the scale buttons. This will also show the tab bar. |
persist_scale | false | If a website visitor changes the spreadsheet scale, this option will store the new scale in localStorage. |
For the complete list of options, see the API reference.
Fonts & Styling
As a general matter, we think using different fonts and different font sizes in a spreadsheet can be distracting. So we discourage it. That’s just our bias. The toolbar has a control to change font size (actually scale, which is preferable). You can also change fonts, but there’s no toolbar control for that – you can change fonts using the API or using CSS.
CSS and Cell Styles
There are two layers of styling in TREB: themes and cell styles. Themes are CSS applied to the whole document. Cell styles are specific to a cell or range of cells. Themes are set by the host (the containing document); cell styles are specified in the spreadsheet itself.
Note that CSS styling won’t work if you embed the spreadsheet in an IFrame. This section assumes you are embedding the spreadsheet with a script tag.
In the absence of a cell style, the theme controls. So there are default fonts and font sizes in the theme, and these apply to every cell. If the CSS changes, then every cell will change. CSS is external to any document, so if you open the same spreadsheet on web pages with different CSS, it may look different.
Cell styles override the theme and persist with the document. So if you open a file that has cell styles, it should (theoretically) look the same on any web page.
The great thing about CSS is that we can define different defaults for different environments. We pick a couple of basic fonts that look good on windows, mac, and (some distros of) linux; then we can generally assume any file will look good on any website, in any browser.
If you set a specific font in a cell style or CSS and it’s not available on a particular platform, you may get ugly text as the browser defaults to Arial or Times or something.
How do I Set Cell Styles?
There are three properties relevant to fonts: font_face, font_size.unit and font_size.value. Font face can have multiple values, like in CSS, to provide fallbacks or fonts for different platforms.
You can use pt
or px
for the font size, but we recommend using em
or %
which are relative to the base cell font size. This is useful in case there are different font sizes for different platforms.
sheet.ApplyStyle('B2:G7', {
font_face: 'Comic Sans MS',
font_size: {
value: 1.5,
unit: 'em',
},
});
The first parameter to ApplyStyle
is a range. Set this to undefined
and it will apply to the active selection.
This example sets font sizes (and colors) in cell styles, but leaves the font face to the theme:
Can I Use Web Fonts?
The best way to use web fonts would be to use the font loading API to ensure your fonts are loaded, and then create the spreadsheet on the page after fonts are ready.
If you create the spreadsheet before fonts are loaded, and you use those fonts in either CSS or cell styles, you’ll probably see the spreadsheet render with fallback fonts (whatever is set in the browser), and it won’t update automatically.
You can update when fonts are loaded by reloading the theme, with
sheet.UpdateTheme();
IE11 doesn’t support the font loading API, so if you need to support that you’ll have to resort to a workaround (they do exist).
/* apply to spreadsheet UI */
.treb-main.treb-theme {
font-family: 'Caveat', cursive;
font-size: 16pt;
}
/* apply to spreadsheet cells */
.treb-main.treb-theme .grid-cells {
font-family: inherit;
font-size: 14pt;
}
We’re not saying you should do this, just that you can.
What About Font Features?
Font features are not supported, unfortunately. That’s because we paint the spreadsheet, rather than using layout, and HTML canvas (as of 2022) does not support most font features.
Complex Numbers
TREB supports complex numbers as an intrinsic type. You can use complex numbers anywhere you would use real numbers. You can type them in cells and use them as arguments to functions. See below for a list of functions that work with complex numbers.
Complex number support is very much a work in progress. If you have questions, comments, or feature requests, please let us know.
Parsing
When entering a complex number, you must use the token i
(lower-case ASCII “i”, unicode U+0069) for the imaginary component. The token i
on its own implies a value of 1i
. The magnitude must precede the token, for example 3i
or 1.2i
.
When entering a formula, complex numbers are not automatically treated as atomic units. Normal precendence rules apply, so
=B3 * 2-3i
is the equivalent of
=(B3 * 2) - 3i
You can of course use parentheses to group them explicitly.
=B3 * (2 - 3i)
Rendering and Formatting
When displaying complex numbers, TREB uses an italic character 𝑖
(mathematical italic small i, unicode U+1D456). We believe this character is available in the default fonts on all platforms we support. If necessary, you can change this character using a run-time option.
Generally speaking we try to render complex numbers in the simplest possible way.
If a complex value has no imaginary value (or if it would render as 0
in the current number format), when displaying the value we will omit the imaginary component. The same goes for the real component, if there is an imaginary component. So complex numbers may render as
3.2
2𝑖
0.00
Number formatting is not well defined for complex numbers. At the moment, we use the currently selected number format and apply it to both the real and imaginary components.
We recommend that you use only basic number formats like “General” or “Number”. Fractional number formats also work well. Increasing or decreasing the decimal (or fractional) precision works as expected.
TREB only displays complex numbers in rectangular form, but you can use the Abs
and Arg
functions to get components for the polar form.
Import & Export
We don’t (for now) supporing importing or exporting complex numbers in XLSX files. The XLSX format doesn’t have a complex type. Excel has a number of functions that work with complex numbers, but the actual values they use are strings.
For the time being, we’re just punting on this issue, but we are open to suggestions.
Functions and Operators
The following functions and operators support complex numbers:
Unary operators
- - (negation)
Binary operators
- + (addition)
- - (subtraction)
- / (division)
- * (multiplication)
- ^ (exponentiation) (see note)
Equalities
- = (equality)
- <> (inequality)
Functions specifically written for complex numbers
- ComplexLog - the complex Log function
- Arg - returns the principal argument of a complex number
- Real - returns the real component of a complex number
- Imaginary - returns the coefficient of the imaginary component
- Conjugate - returns the complex conjugate
- Complex - treats real values as complex for function purposes (see note)
Functions updated to support complex arguments
Note: the SQRT
function returns NaN for some operations on real values, like SQRT(-1)
. The same is true for the POWER
function and the exponentiation operator ^
.
We don’t want to change existing behavior, so we are leaving this as-is for real values. If the argument to SQRT
is complex, e.g. SQRT(-1 + 0i)
it will return the complex result 𝑖
. If the argument is real, however, SQRT(-1)
will return NaN.
Our reasoning here is twofold: first, we do not want to change existing behavior or expectations. Second, we do not want functions to accidentally introduce complex numbers into models that expect real values only.
This presents a problem for values returned from functions which may be in either real or complex domain. To resolve this, and create a pattern for consistent behavior, we provide the function COMPLEX
. This function coerces real values to the complex domain.
=SQRT(-1)
returnsNaN
=SQRT(-1 + 0i)
returns𝑖
=SQRT(COMPLEX(-1))
returns𝑖
The function REAL
can be used for the converse, i.e. ensuring a number is treated as real, although this may lose information if a number has an imaginary compnent.
Programming Interface
The default script (described above in the embedding section) adds a TREB
object to the global namespace.
You can also use the ES module treb-bundle.mjs
(included in the download). If you use the ES module, access the TREB object by importing it:
<script type='module'>
import { TREB } from 'https://treb.app/treb/current/esm/treb-bundle.mjs';
</script>
The javascript module includes styles, injected into the page at runtime. The ES module does not (this helps if you have strict CSP settings). If you use the ES module, you must also reference the stylesheet. See the example below.
However you access the TREB
object it works the same way.
Creating a spreadsheet
The TREB
object has a method CreateSpreadsheet
that creates spreadsheet instances in the document.
CreateSpreadsheet
takes an options parameter. The most important option is the node where you want to insert your spreadsheet. The following example shows how to create a spreadsheet in a DOM node:
<html>
<head>
<!-- the es module does not inject styles, so you need to include the stylesheet -->
<link rel='stylesheet' href='https://treb.app/treb/current/esm/treb-bundle.css'>
<script type='module'>
// import from esm
import { TREB } from 'https://treb.app/treb/current/esm/treb-bundle.mjs';
// run this when the DOM is complete
document.addEventListener("DOMContentLoaded", () => {
// get the node
const container = document.querySelector('.embedded-spreadsheet');
// call CreateSpreadsheet with the container node
TREB.CreateSpreadsheet({ container });
});
</script>
</head>
<body>
<!-- we will use script to insert the spreadsheet in this div -->
<div class="embedded-spreadsheet"></div>
</body>
</html>
Open this example page in your browser
For more information, see the API page for Create Spreadsheet.
API Reference
The API reference is available here. This is a work in progress, so please let us know if you have any questions or if anything isn’t clear.
If you use typescript (or an editor that supports it), there’s a typings file included in the download.