SheetJSDev version bump 0.12.7: chrome extension
- `writeFile` support chrome extension (fixes #1051 h/t @atkinsam)
- demo refresh
Latest commit 08bb7e6 Mar 29, 2018
Failed to load latest commit information.
com/sheetjs version bump 0.12.5: ancillary utility update Mar 13, 2018
.gitignore version bump 0.12.5: ancillary utility update Mar 13, 2018
.swiftlint.yml version bump 0.12.1: BIFF5 features Feb 14, 2018
Makefile version bump 0.12.7: chrome extension Mar 29, 2018 version bump 0.12.7: chrome extension Mar 29, 2018
SheetJSCore.swift version bump 0.12.5: ancillary utility update Mar 13, 2018 version bump 0.12.5: ancillary utility update Mar 13, 2018
chakra.js updated demos [ci skip] Sep 12, 2017 version bump 0.12.1: BIFF5 features Feb 14, 2018
goja.go version bump 0.12.7: chrome extension Mar 29, 2018
main.swift version bump 0.12.5: ancillary utility update Mar 13, 2018
nashorn.js version bump 0.12.1: BIFF5 features Feb 14, 2018
sheetjs.duk.c version bump 0.12.5: ancillary utility update Mar 13, 2018

Other JS Engines and Deployments

There are many JS engines and deployments outside of web browsers. NodeJS is the most popular deployment, but there are many others for special use cases. Some optimize for low overhead and others optimize for ease of embedding within other applications. Since it was designed for ES3 engines, the library can be used in those settings! This demo tries to demonstrate a few alternative deployments.

Some engines provide no default global object. To create a global reference:

var global = (function(){ return this; }).call(null);

Swift + JavaScriptCore

iOS and OSX ship with the JavaScriptCore framework, enabling easy JS access from Swift and Objective-C. Hybrid function invocation is tricky, but explicit data passing is straightforward. The demo shows a standalone example for OSX. For playgrounds, the library should be copied to shared playground data directory (usually ~/Documents/Shared Playground Data):

/* This only works in a playground, see SheetJSCore.swift for standalone use */
import JavaScriptCore;
import PlaygroundSupport;

/* build path variable for the library */
let shared_dir = PlaygroundSupport.playgroundSharedDataDirectory;
let lib_path = shared_dir.appendingPathComponent("xlsx.full.min.js");

/* prepare JS context */
var context: JSContext! = JSContext();
var src = "var global = (function(){ return this; }).call(null);";

/* load library */
var lib = try? String(contentsOf: lib_path);
let XLSX: JSValue! = context.objectForKeyedSubscript("XLSX");

/* to verify the library was loaded, get the version string */
let XLSXversion: JSValue! = XLSX.objectForKeyedSubscript("version")
var version  = XLSXversion.toString();

Binary strings can be passed back and forth using String.Encoding.isoLatin1:

/* parse sheetjs.xls */
let file_path = shared_dir.appendingPathComponent("sheetjs.xls");
let data: String! = try String(contentsOf: file_path, encoding: String.Encoding.isoLatin1);
context.setObject(data, forKeyedSubscript: "payload" as (NSCopying & NSObjectProtocol)!);
src = "var wb =, {type:'binary'});";

/* write to sheetjsw.xlsx  */
let out_path = shared_dir.appendingPathComponent("sheetjsw.xlsx");
src = "var out = XLSX.write(wb, {type:'binary', bookType:'xlsx'})";
let outvalue: JSValue! = context.objectForKeyedSubscript("out");
var out: String! = outvalue.toString();
try? out.write(to: out_path, atomically: false, encoding: String.Encoding.isoLatin1);


Nashorn ships with Java 8. It includes a command-line tool jjs for running JS scripts. It is somewhat limited but does offer access to the full Java runtime.

The load function in jjs can load the minified source directly:

var global = (function(){ return this; }).call(null);

The Java nio API provides the Files.readAllBytes method to read a file into a byte array. To use in, the demo copies the bytes into a plain JS array and calls with type "array".


Rhino is an ES3+ engine written in Java. The SheetJSRhino class and com.sheetjs package show a complete JAR deployment, including the full XLSX source.

Due to code generation errors, optimization must be turned off:

Context context = Context.enter();


ChakraCore is an embeddable JS engine written in C++. The library and binary distributions include a command-line tool chakra for running JS scripts.

The simplest way to interact with the engine is to pass Base64 strings. The make target builds a very simple payload with the data.


Duktape is an embeddable JS engine written in C. The amalgamation makes integration extremely simple! It supports Buffer natively:

/* parse a C char array as a workbook object */
duk_config_buffer(ctx, -1, buf, len);
duk_put_global_string(ctx, "buf");
duk_eval_string_noresult("workbook =, {type:'buffer'});");

/* write a workbook object to a C char array */
duk_eval_string(ctx, "XLSX.write(workbook, {type:'array', bookType:'xlsx'})");
duk_size_t sz;
char *buf = (char *)duk_get_buffer_data(ctx, -1, sz);


Goja is a pure Go implementation of ECMAScript 5. As of this writing, there are some issues with processing Unicode data, but the xlsx.core.min.js script can be processed. []byte should be transformed to a binary string in the engine:

/* read file */
data, _ := ioutil.ReadFile("sheetjs.xlsx")

/* load into engine */
vm.Set("buf", data)

/* convert to binary string */
_, _ = vm.RunString("var bstr = ''; for(var i = 0; i < buf.length; ++i) bstr += String.fromCharCode(buf[i]);")

/* parse */
wb, _ = vm.RunString("wb =, {type:'binary', cellNF:true});")

On the write side, "base64" strings can be decoded in Go:

b64str, _ := vm.RunString("XLSX.write(wb, {type:'base64', bookType:'xlsx'})")
buf, _ := base64.StdEncoding.DecodeString(b64str.String())
_ = ioutil.WriteFile("sheetjs.xlsx", buf, 0644)