Export to PDF
The Export to PDF extension provides seamless integration with the Jspreadsheet data grid plugin, enabling users to efficiently export their spreadsheets as PDFs in any language when the appropriate TTF font is loaded. This extension ensures easy data sharing and maintains the spreadsheet's original structure during conversion, making it a versatile solution for multi-language applications.
Documentation
Methods
Method | Description |
---|---|
print |
Opens the print modal programmatically. Specify the target spreadsheet instance or an array of worksheets. If no instance is provided, the function uses the currently active spreadsheet by default. An alert displays if no spreadsheet is in focus.print(spreadsheet?: Object|Object[], options?: printOptions) => void |
print.setFont |
Customizes the language for printing by defining a TTF font that includes all symbols and characters in your language.print.setFont(ttf: String) => void |
print.getPdf |
Generates a PDF from a spreadsheet and returns a promise with the PDF as a base64 string.print.getPdf(spreadsheet: Object, scope?: scope, config?: pdfConfig) => Promise<string> |
Options
The print
function accepts an options object with the following properties:
Property | Type | Description |
---|---|---|
onsuccess |
(pdfBuffer: Buffer) => void |
Callback function executed when PDF generation is successful |
onerror |
(error: Error) => void |
Optional callback function executed when PDF generation fails |
scope |
scope |
Defines the scope of content to include in the PDF |
config |
pdfConfig |
Configuration options for PDF formatting and layout |
Scope Options
The scope
property allows you to specify what content to include in the PDF:
Property | Type | Description |
---|---|---|
type |
'spreadsheet' | 'worksheet' | 'cells' |
Defines the scope type |
worksheetIndex |
number |
Index of the specific worksheet to export |
range |
{ start: [number, number], end: [number, number] } |
Cell range to export when type is 'cells' |
PDF Configuration Options
The config
property provides extensive customization for PDF output:
Property | Type | Description |
---|---|---|
pageSize |
'Letter' | 'Tabloid' | 'Legal' | 'A3' | 'A4' | 'A5' | 'B4' | 'B5' |
Paper size for the PDF |
pageOrientation |
'portrait' | 'landscape' |
Page orientation |
pageScale |
'normal' | 'page' | 'width' | 'height' |
Scaling options for content |
pageMargins |
'narrow' | 'normal' | 'wide' |
Margin settings |
orderOfPages |
'horizontal' | 'vertical' |
Order in which pages are arranged |
horizontalAlignment |
'left' | 'center' | 'right' |
Horizontal alignment of content |
verticalAlignment |
'top' | 'center' | 'bottom' |
Vertical alignment of content |
showGridLines |
boolean |
Whether to show grid lines in the PDF |
showNotes |
boolean |
Whether to include cell notes |
showPositionIdentifiers |
boolean |
Whether to show column/row headers |
showPageNumber |
boolean |
Whether to display page numbers |
showSpreadsheetTitle |
boolean |
Whether to show the spreadsheet title |
showWorksheetTitle |
boolean |
Whether to show worksheet names |
showCurrentDate |
boolean |
Whether to display the current date |
showCurrentTime |
boolean |
Whether to display the current time |
repeatFrozenRows |
boolean |
Whether to repeat frozen rows on each page |
repeatFrozenColumns |
boolean |
Whether to repeat frozen columns on each page |
Installation
Choose one of the following options:
Using NPM
npm install @jspreadsheet/print
Using a CDN
<script src="https://cdn.jsdelivr.net/npm/@jspreadsheet/print/dist/index.min.js"></script>
International
To export a spreadsheet in a language other than English, define a TTF font that includes all required symbols and characters for that language. Download and load your TTF font using setFont(string)
. The following resources may be helpful:
- Export in Japanese with Pretendard Regular
- Export in Korean using Noto Sans Korean
- Export in Chinese with FengGuangMingRui
- Export in Hindu with Noto Sans Devanagari
Example
print.setFont('./Pretendard-Regular.ttf');
Examples
Basic example of customizing fonts
Select a language below to set the corresponding font for displaying spreadsheet values in the PDF.
<html>
<script src="https://jspreadsheet.com/v12/jspreadsheet.js"></script>
<link rel="stylesheet" href="https://jspreadsheet.com/v12/jspreadsheet.css" type="text/css" />
<script src="https://jsuites.net/v5/jsuites.js"></script>
<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" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lemonadejs/studio/dist/style.min.css" type="text/css" />
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/studio/dist/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.js"></script>
<script src="https://unpkg.com/@pdf-lib/[email protected]"></script>
<script src="https://unpkg.com/[email protected]/runtime.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@jspreadsheet/print/dist/index.min.js"></script>
<div id="spreadsheet"></div><br><br>
<select id='selectedLanguage' class='jss_object'>
<option value='la'>Latin script</option>
<option value='jp'>Japanese</option>
<option value='ch'>Chinese</option>
<option value='kr'>Korean</option>
<option value='in'>Hindi</option>
</select>
<input type="button" id="btn1" class="jss_object" value="Print">
<script>
const dataExamples = {
la: [["Hello", "World"]],
jp: [["ハロー・", "ワールド"]],
kr: [["안녕", "세상"]],
ch: [["你好", "世界"]],
in: [["नमस्ते", "दुनिया"]],
};
let changeLanguage = function(event) {
let lang = event.target.value
spreadsheet[0].setData(dataExamples[lang])
if (lang === 'jp' || lang === 'kr' || lang === 'la') {
// Pretendard Regular - Free font from https://fontmeme.com/fonts/pretendard-jp-font/
print.setFont('./font/Pretendard-Regular.ttf')
} else if (lang === 'ch') {
// FengGuangMingRui Regular - Download from https://chinesefonts.org/fonts/fengguangmingrui-regular
print.setFont('./font/FengGuangMingRui-Regular.ttf')
} else if (lang === 'in') {
// Noto Sans Regular - Free font from https://fonts.google.com/noto/specimen/Noto+Sans
print.setFont('./font/NotoSans-Regular.ttf')
}
}
// Set the license for both plugin and the spreadsheet
jspreadsheet.setLicense('NjQwYTJhNjYyNjg5ZGJlYjA1NmNlZTBlNzBkZDZiNmRhM2U3YTc2ZTAzMTUwZDQ5MWFjMzdjNzExMGFkZTU5ZGU3YzA2YThkMzc2NjA5NTZiNGM3YmU0ZDYwODUxNTJlZTQwMjAzZTk4ZWFjMThlNzI3NjhiZTAzYmVmNzBhYzEsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU9ETXhNRFUwTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');
// Set the extensions
jspreadsheet.setExtensions({ print });
// Create the spreadsheet
const spreadsheet = jspreadsheet(document.getElementById('spreadsheet'), {
worksheets: [{
data: [['Hello', 'World']],
minDimensions: [6, 6],
}]
});
spreadsheet[0].setData(dataExamples['la'])
document.getElementById("btn1").onclick = () => print(spreadsheet[0])
document.getElementById("selectedLanguage").onchange = (e) => changeLanguage(e)
</script>
</html>
import React, { useRef, useState } from "react";
import { Spreadsheet, Worksheet } from "@jspreadsheet/react";
import print from "@jspreadsheet/print";
import "jsuites/dist/jsuites.css";
import "jspreadsheet/dist/jspreadsheet.css";
import "@lemonadejs/studio/dist/style.css";
// License
const license = 'NjQwYTJhNjYyNjg5ZGJlYjA1NmNlZTBlNzBkZDZiNmRhM2U3YTc2ZTAzMTUwZDQ5MWFjMzdjNzExMGFkZTU5ZGU3YzA2YThkMzc2NjA5NTZiNGM3YmU0ZDYwODUxNTJlZTQwMjAzZTk4ZWFjMThlNzI3NjhiZTAzYmVmNzBhYzEsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU9ETXhNRFUwTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5';
// Extensions
const extensions = { print };
export default function App() {
const [lang, setLang] = useState('la')
const spreadsheet = useRef();
const dataExamples = {
la: [["Hello", "World"]],
jp: [["ハロー・", "ワールド"]],
kr: [["안녕", "세상"]],
ch: [["你好", "世界"]],
in: [["नमस्ते", "दुनिया"]],
};
const data = [...dataExamples.la]
const changeLanguage = (event) => {
const newLanguage = event.target.value
spreadsheet.current[0].setData(dataExamples[newLanguage])
setLang(newLanguage)
if (newLanguage === 'jp' || newLanguage === 'kr' || newLanguage === 'la') {
print.setFont('./fonts/Pretendard-Regular.ttf')
} else if (newLanguage === 'ch') {
print.setFont('./fonts/FengGuangMingRui-Regular.ttf')
} else if (newLanguage === 'in') {
print.setFont('./fonts/NotoSans-Regular.ttf')
}
}
return (
<>
<Spreadsheet ref={spreadsheet} license={license} extensions={extensions} toolbar={true}>
<Worksheet data={data} />
</Spreadsheet>
<select id='selectedLanguage' onChange={(event) => changeLanguage(event)} value={lang}>
<option value='la'>Latin script</option>
<option value='jp'>Japanese</option>
<option value='ch'>Chinese</option>
<option value='kr'>Korean</option>
<option value='in'>Hindi</option>
</select>
<button onClick={() => print(spreadsheet.current[0])}>Export/Print</button>
</>
);
}
<template>
<Spreadsheet ref="spreadsheet" :license="license" :extensions="extensions">
<Worksheet :data="data"></Worksheet>
</Spreadsheet>
<select id="selectedLanguage" @change="changeLanguage" v-model="lang">
<option value="la">Latin script</option>
<option value="jp">Japanese</option>
<option value="ch">Chinese</option>
<option value="kr">Korean</option>
<option value="in">Hindi</option>
</select>
<button @click="print">Export/Print</button>
</template>
<script>
import { Spreadsheet, Worksheet } from "@jspreadsheet/vue";
import print from "@jspreadsheet/vue";
import "jsuites/dist/jsuites.css";
import "jspreadsheet/dist/jspreadsheet.css";
import "@lemonadejs/studio/dist/style.css";
const dataExamples = {
la: [["Hello", "World"]],
jp: [["ハロー・", "ワールド"]],
kr: [["안녕", "세상"]],
ch: [["你好", "世界"]],
in: [["नमस्ते", "दुनिया"]],
};
const license = 'NjQwYTJhNjYyNjg5ZGJlYjA1NmNlZTBlNzBkZDZiNmRhM2U3YTc2ZTAzMTUwZDQ5MWFjMzdjNzExMGFkZTU5ZGU3YzA2YThkMzc2NjA5NTZiNGM3YmU0ZDYwODUxNTJlZTQwMjAzZTk4ZWFjMThlNzI3NjhiZTAzYmVmNzBhYzEsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU9ETXhNRFUwTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5';
export default {
name: "App",
components: {
Spreadsheet,
Worksheet,
},
data() {
return {
lang: "la",
license: license,
extensions: {
print
},
data: [],
};
},
created() {
this.data = [...dataExamples["la"]];
},
methods: {
print() {
print(this.$refs.spreadsheet.current[0]);
},
changeLanguage(event) {
const newLanguage = event.target.value;
this.lang = newLanguage;
this.$refs.spreadsheet.current[0].setData(dataExamples[this.lang]);
if (newLanguage === "jp" || newLanguage === "kr" || newLanguage === "la") {
print.setFont("./fonts/Pretendard-Regular.ttf");
} else if (newLanguage === "ch") {
print.setFont("./fonts/FengGuangMingRui-Regular.ttf");
} else if (newLanguage === "in") {
print.setFont("./fonts/NotoSans-Regular.ttf");
}
},
},
}
</script>
import { Component, ViewChild, ElementRef } from "@angular/core";
import jspreadsheet from "jspreadsheet";
import print from "@jspreadsheet/print";
import "jsuites/dist/jsuites.css";
import "jspreadsheet/dist/jspreadsheet.css";
import "@lemonadejs/studio/dist/style.css";
// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('NjQwYTJhNjYyNjg5ZGJlYjA1NmNlZTBlNzBkZDZiNmRhM2U3YTc2ZTAzMTUwZDQ5MWFjMzdjNzExMGFkZTU5ZGU3YzA2YThkMzc2NjA5NTZiNGM3YmU0ZDYwODUxNTJlZTQwMjAzZTk4ZWFjMThlNzI3NjhiZTAzYmVmNzBhYzEsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU9ETXhNRFUwTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');
// Extensions
jspreadsheet.setExtensions({ print });
// Add language type for the possible languages in this example
type Language = 'la' | 'jp' | 'ch' | 'kr' | 'in';
const dataExamples = {
la: [["Hello", "World"]],
jp: [["ハロー・", "ワールド"]],
kr: [["안녕", "세상"]],
ch: [["你好", "世界"]],
in: [["नमस्ते", "दुनिया"]],
};
@Component({
standalone: true,
selector: "app-root",
template: `<div #spreadsheet></div>
<select id="selectedLanguage" (change)="changeLanguage($event)">
<option value="la">Latin script</option>
<option value="jp">Japanese</option>
<option value="ch">Chinese</option>
<option value="kr">Korean</option>
<option value="in">Hindi</option>
</select>
<button (click)="handleClick()">Export/Print</button>`
})
export class AppComponent {
@ViewChild("spreadsheet") spreadsheet: ElementRef;
worksheets: jspreadsheet.worksheetInstance[];
// Create a new data grid
ngAfterViewInit() {
// Create spreadsheet
this.worksheets = jspreadsheet(this.spreadsheet.nativeElement, {
worksheets: [{
minDimensions: [6, 6]
}]
});
}
changeLanguage(event: any) {
let lang: Language = event.target.value;
// You should add the assets folder to angular.json in projects.<project-name>.architect.options.assets
if (lang === 'jp' || lang === 'kr' || lang === 'la') {
print.setFont('assets/fonts/Pretendard-Regular.ttf');
} else if (lang === 'ch') {
print.setFont('assets/fonts/FengGuangMingRui-Regular.ttf');
} else if (lang === 'in') {
print.setFont('assets/fonts/NotoSans-Regular.ttf');
}
this.worksheets[0].setData(dataExamples[lang])
}
handleClick() {
print(this.worksheets[0])
}
}
Backend PDF Export
From version Jspreadsheet version 12 you can generate PDF files on your backend from a virtual spreadsheet as the example below.
const jspreadsheet = require('jspreadsheet');
const formula = require('@jspreadsheet/formula-pro');
const print = require('@jspreadsheet/print');
const { writeFile } = require('node:fs/promises');
jspreadsheet.setLicense({
clientId: '356a192b7913b04c54574d18c28d46e6395428ab',
licenseKey: 'NjQwYTJhNjYyNjg5ZGJlYjA1NmNlZTBlNzBkZDZiNmRhM2U3YTc2ZTAzMTUwZDQ5MWFjMzdjNzExMGFkZTU5ZGU3YzA2YThkMzc2NjA5NTZiNGM3YmU0ZDYwODUxNTJlZTQwMjAzZTk4ZWFjMThlNzI3NjhiZTAzYmVmNzBhYzEsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU9ETXhNRFUwTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5'
});
jspreadsheet.setExtensions({ formula, print })
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.print(spreadsheet[0].parent, {
onsuccess: async function(file) {
// Save the file to the backend
await writeFile('a.pdf', file);
}
});