Products

Export to PDF

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:

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);
    }
});