Skip to main content

WebSQL and SQLite

WebSQL is a popular SQL-based in-browser database available on Chrome. In practice, it is powered by SQLite, and most simple SQLite-compatible queries work as-is in WebSQL.

The public demo https://sheetjs.com/sql generates a database from workbook.

caution

WebSQL is only supported in Chromium-based browsers including Chrome.

Safari historically supported WebSQL but Safari 13 dropped support. Legacy browsers including Internet Explorer and Firefox never added support.

WebSQL Details

Importing data from spreadsheets is straightforward using the generate_sql helper function from "Generating Tables".

The Web SQL Database API is callback-based. The following snippet wraps transactions in Promise objects:

const db = openDatabase('sheetql', '1.0', 'SheetJS WebSQL Test', 2097152);
const stmts = generate_sql(ws, wsname);

// NOTE: tx.executeSql and db.transaction use callbacks. This wraps in Promises
for(var stmt of stmts) await new Promise((res, rej) => {
db.transaction(tx =>
tx.executeSql(stmt, [],
(tx, data) => res(data), // if the query is successful, return the data
(tx, err) => rej(err) // if the query fails, reject with the error
));
});

The result of a SQL SELECT statement is a SQLResultSet. The rows property is a SQLResultSetRowList. It is an "array-like" structure that has length and properties like 0, 1, etc. However, this is not a real Array object!

A real Array can be created using Array.from:

db.readTransaction(tx =>
tx.executeSQL("SELECT * FROM DatabaseTable", [], (tx, data) => {
// data.rows is "array-like", so `Array.from` can make it a real array
const aoo = Array.from(data.rows);
const ws = XLSX.utils.json_to_sheet(aoo);
// ... perform an export here OR wrap in a Promise
})
);

Live Demo

note

This demo was last tested on 2023 February 26

The following demo generates a database with 5 fixed SQL statements. Queries can be changed in the Live Editor. The WebSQL database can be inspected in the "WebSQL" section of the "Application" Tab of Developer Tools:

WebSQL view in Developer Tools

Result
Loading...
Live Editor

Server-Side SQLite

Most platforms offer a simple way to query SQLite database files.

The following example shows how to query for each table in an SQLite database, query for the data for each table, add each non-empty table to a workbook, and export as XLSX.

The Northwind database is available in SQLite form.

note

This demo was last tested on 2023 February 26

NodeJS

The better-sqlite3 module provides a very simple API for working with SQLite databases. Statement#all runs a prepared statement and returns an array of JS objects.

0) Download northwind.db.

1) Install the dependencies:

npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz [email protected]

2) Save the following to node.mjs:

node.mjs
/* Load SQLite3 connector library */
import Database from "better-sqlite3";

/* Load SheetJS library */
import * as XLSX from 'xlsx';
import * as fs from 'fs';
XLSX.set_fs(fs);

/* Initialize database */
var db = Database("northwind.db");

/* Create new workbook */
var wb = XLSX.utils.book_new();

/* Get list of table names */
var sql = db.prepare("SELECT name FROM sqlite_master WHERE type='table'");
var result = sql.all();

/* Loop across each name */
result.forEach(function(row) {
/* Get first 100K rows */
var aoo = db.prepare("SELECT * FROM '" + row.name + "' LIMIT 100000").all();
if(aoo.length > 0) {
/* Create Worksheet from the row objects */
var ws = XLSX.utils.json_to_sheet(aoo, {dense: true});
/* Add to Workbook */
XLSX.utils.book_append_sheet(wb, ws, row.name);
}
});

/* Write File */
XLSX.writeFile(wb, "node.xlsx");

3) Run node node.mjs and open node.xlsx

Bun

Bun ships with a built-in high-performance module bun:sqlite.

0) Download northwind.db.

1) Install the dependencies:

npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz

2) Save the following to bun.mjs:

bun.mjs
/* Load SQLite3 connector library */
import { Database } from "bun:sqlite";

/* Load SheetJS library */
import * as XLSX from 'xlsx';
import * as fs from 'fs';
XLSX.set_fs(fs);

/* Initialize database */
var db = Database.open("northwind.db");

/* Create new workbook */
var wb = XLSX.utils.book_new();

/* Get list of table names */
var sql = db.prepare("SELECT name FROM sqlite_master WHERE type='table'");
var result = sql.all();

/* Loop across each name */
result.forEach(function(row) {
/* Get first 100K rows */
var aoo = db.prepare("SELECT * FROM '" + row.name + "' LIMIT 100000").all();
if(aoo.length > 0) {
/* Create Worksheet from the row objects */
var ws = XLSX.utils.json_to_sheet(aoo, {dense: true});
/* Add to Workbook */
XLSX.utils.book_append_sheet(wb, ws, row.name);
}
});

/* Write File */
XLSX.writeFile(wb, "bun.xlsx");

3) Run bun bun.mjs and open bun.xlsx

Deno

Deno sqlite library returns raw arrays of arrays.

0) Download northwind.db.

1) Save the following to deno.ts:

deno.ts
/* Load SQLite3 connector library */
import { DB } from "https://deno.land/x/sqlite/mod.ts";

/* Load SheetJS library */
// @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts"
import * as XLSX from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs';

/* Initialize database */
var db = new DB("northwind.db");

/* Create new workbook */
var wb = XLSX.utils.book_new();

/* Get list of table names */
var sql = db.prepareQuery("SELECT name FROM sqlite_master WHERE type='table'");
var result = sql.all();
/* Loop across each name */
result.forEach(function(row) {
/* Get first 100K rows */
var query = db.prepareQuery("SELECT * FROM '" + row[0] + "' LIMIT 100000")
var aoa = query.all();
if(aoa.length > 0) {
/* Create array of arrays */
var data = [query.columns().map(x => x.name)].concat(aoa);
/* Create Worksheet from the aoa */
var ws = XLSX.utils.aoa_to_sheet(data, {dense: true});
/* Add to Workbook */
XLSX.utils.book_append_sheet(wb, ws, row[0]);
}
});

/* Write File */
XLSX.writeFile(wb, "deno.xlsx");

2) Run deno run --allow-read --allow-write deno.ts and open deno.xlsx