Export to XLSX
The Render extension allows users to convert spreadsheet JSON notation or Jspreadsheet data grids into XLSX files. It can be used independently for JSON to XLSX conversion, without requiring Jspreadsheet.
Export to XLSX using Node.js
From version 11, it is possible to generate files on the backend using Node.js
Documentation
Available settings
Property | Description |
---|---|
filename: string | File name. Default: jspreadsheet.xlsx |
onbeforerender: (spreadsheetConfig) => spreadsheetConfig | Intercepts the render to overwrite spreadsheet configuration |
onbeforesave: (blob) => boolean | void | Intercepts the file generation |
onsuccess: (file) => void | Used to intercept the blob file |
Installation
Choose one of the following options:
Using NPM
$ npm install @jspreadsheet/render
Using a CDN
<script src="https://cdn.jsdelivr.net/npm/@jspreadsheet/render/dist/index.min.js"></script>
Excel Limitations
When exporting files to XLSX using this extension, be aware of certain Excel limitations that are not present in Jspreadsheet. Despite these limitations, the extension is designed to handle data effectively during export. The list below highlights some of these constraints, though it is not exhaustive:
- Worksheet Name Length: Excel restricts worksheet names to 30 characters.
- Dynamic Source for Dropdowns: Due to Excel's limitations, dropdowns with a dynamic source that spans more than a single row or column are ignored during rendering.
- Cell vs. Column Dropdowns: If a cell contains dropdowns configured at the column level and within the cell itself, its specific configuration takes precedence during export. Additionally, if a cell has both a dropdown and a list validation, the list validation will be excluded from the export.
- Dropdown Source Character Limit: When exporting a dropdown, if the total number of characters in the source exceeds Excel's allowed limit, the export process will trim options from the source to prevent the resulting XLSX file from breaking.
- Groups: Groups that are only partially within other groups are not exported due to Excel limitations; Excel allows up to seven levels of groups, so if a group is nested within seven or more other groups, it is not exported;
Code samples
Create a XLSX file using JavaScript
How to create an online XLSX exporter
<html>
<script src="https://jspreadsheet.com/v11/jspreadsheet.js"></script>
<script src="https://jsuites.net/v5/jsuites.js"></script>
<link rel="stylesheet" href="https://jspreadsheet.com/v11/jspreadsheet.css" type="text/css" />
<link rel="stylesheet" href="https://jsuites.net/v5/jsuites.css" type="text/css" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jszip.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@jspreadsheet/render/dist/index.min.js"></script>
<div id='spreadsheet'></div>
<p><input type="button" value="Download" id="btn1" /></p>
<script>
const download = function(spreadsheet) {
jspreadsheet.render(spreadsheet, {
filename: 'file.xlsx',
});
}
// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('Njg5NDY2OTU2OGY4ZDBhZTQzNGNhNDA1NmQyNGVhYzQ0M2ZiYzFjZTQ5ZTYyNDhhZDRhMjU2NjNkMjg5OWU2ZjU5YTg1ODcyZTk3YWE3ZmVhNDFlZWY4YmQwM2JmMTBjNzlmMTU4MzE5YTZlZjk3ZDgxNmJiNDQzZTAyMjgwMjMsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU9ETXhNak0zTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');
// Add-on for Spreadsheet
jspreadsheet.setExtensions({ render });
// Create the spreadsheets
let worksheets = jspreadsheet(document.getElementById('spreadsheet'), {
worksheets: [
{ minDimensions: [6, 6] },
{ minDimensions: [6, 6] },
],
});
document.getElementById("btn1").onclick = function() {
download(worksheets[0].parent);
}
</script>
</html>
import React, { useRef } from "react";
import { Spreadsheet, Worksheet } from "@jspreadsheet/react";
import jspreadsheet from "jspreadsheet";
import render from "@jspreadsheet/render";
import "jsuites/dist/jsuites.css";
import "jspreadsheet/dist/jspreadsheet.css";
// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('Njg5NDY2OTU2OGY4ZDBhZTQzNGNhNDA1NmQyNGVhYzQ0M2ZiYzFjZTQ5ZTYyNDhhZDRhMjU2NjNkMjg5OWU2ZjU5YTg1ODcyZTk3YWE3ZmVhNDFlZWY4YmQwM2JmMTBjNzlmMTU4MzE5YTZlZjk3ZDgxNmJiNDQzZTAyMjgwMjMsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU9ETXhNak0zTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');
// Add-on for your JSS data grid
jspreadsheet.setExtensions({ render });
export default function App() {
// Spreadsheet array of worksheets
const spreadsheet = useRef();
const download = function() {
jspreadsheet.render(spreadsheet.current[0].parent.el, {
filename: 'file.xlsx',
});
}
// Render component
return (
<>
<Spreadsheet ref={spreadsheet}>
<Worksheet />
<Worksheet />
</Spreadsheet>
<input type="button" value="Download" onClick={() => download()} />
</>
);
}
<template>
<Spreadsheet ref="spreadsheet" :license="license" :extensions="extensions">
<Worksheet :minDimensions="[10,10]" />
<Worksheet :minDimensions="[10,10]" />
</Spreadsheet>
<input type="button" value=Download" @click="download" />
</template>
<script>
import { Spreadsheet, Worksheet, jspreadsheet } from "@jspreadsheet/vue";
import render from "@jspreadsheet/render";
import "jsuites/dist/jsuites.css";
import "jspreadsheet/dist/jspreadsheet.css";
// Define the data grid license
const license = 'Njg5NDY2OTU2OGY4ZDBhZTQzNGNhNDA1NmQyNGVhYzQ0M2ZiYzFjZTQ5ZTYyNDhhZDRhMjU2NjNkMjg5OWU2ZjU5YTg1ODcyZTk3YWE3ZmVhNDFlZWY4YmQwM2JmMTBjNzlmMTU4MzE5YTZlZjk3ZDgxNmJiNDQzZTAyMjgwMjMsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU9ETXhNak0zTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5';
// Define the data grid extensions
const extensions = { render };
export default {
components: {
Spreadsheet,
Worksheet,
},
methods: {
download() {
// Spreadsheet instance
jspreadsheet.render(this.$refs.spreadsheet.current[0].parent.el, {
filename: 'file.xlsx',
});
}
},
data() {
return {
license,
extensions,
};
}
}
</script>
import { Component, ViewChild, ElementRef } from "@angular/core";
import jspreadsheet from "jspreadsheet";
import render from "@jspreadsheet/render";
// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('Njg5NDY2OTU2OGY4ZDBhZTQzNGNhNDA1NmQyNGVhYzQ0M2ZiYzFjZTQ5ZTYyNDhhZDRhMjU2NjNkMjg5OWU2ZjU5YTg1ODcyZTk3YWE3ZmVhNDFlZWY4YmQwM2JmMTBjNzlmMTU4MzE5YTZlZjk3ZDgxNmJiNDQzZTAyMjgwMjMsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU9ETXhNak0zTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');
// Extensions
jspreadsheet.setExtensions({ render });
@Component({
standalone: true,
selector: "app-root",
template: `<div #spreadsheet></div>
<input type="button" value="Generate XLSX" (click)="this.export()" />`
})
export class AppComponent {
@ViewChild("spreadsheet") spreadsheet: ElementRef;
// Worksheets
worksheets: jspreadsheet.worksheetInstance[];
// Create a new data grid
ngAfterViewInit() {
// Create spreadsheet
this.worksheets = jspreadsheet(this.spreadsheet.nativeElement, {
worksheets: [
{ minDimensions: [6, 6] },
{ minDimensions: [6, 6] }
]
});
}
export() {
// Spreadsheet instance
jspreadsheet.render!(this.worksheets[0].parent.el, {
filename: 'file.xlsx',
});
}
}
Backend XLSX Export
From version Jspreadsheet version 11 you can generate XLSX files on your backend as the example below.
const jspreadsheet = require('jspreadsheet');
const formula = require('@jspreadsheet/formula-pro');
const render = require('@jspreadsheet/render');
const { writeFile } = require('node:fs/promises');
jspreadsheet.setLicense({
clientId: '356a192b7913b04c54574d18c28d46e6395428ab',
licenseKey: 'Njg5NDY2OTU2OGY4ZDBhZTQzNGNhNDA1NmQyNGVhYzQ0M2ZiYzFjZTQ5ZTYyNDhhZDRhMjU2NjNkMjg5OWU2ZjU5YTg1ODcyZTk3YWE3ZmVhNDFlZWY4YmQwM2JmMTBjNzlmMTU4MzE5YTZlZjk3ZDgxNmJiNDQzZTAyMjgwMjMsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU9ETXhNak0zTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5'
});
jspreadsheet.setExtensions({ formula,render })
let spreadsheet = jspreadsheet(null, {
worksheets: [{
worksheetName: "Sheet1",
data: [
['10', '15', '20', '=OFFSET(A1, 2, 2)', '=OFFSET(A1, 0, 0, 2, 2)'],
['67', '44', '99', '=OFFSET(A1, 0, 2)', ''],
['11', '16', '21', '=OFFSET(A1, 2, 0)', ''],
['68', '45', '100'],
]
}],
});
jspreadsheet.render(spreadsheet[0].parent, {
onsuccess: async function(file) {
// Save the file to the backend
await writeFile('test.xlsx', file);
}
});