Skip to main content

Java + Rhino

Rhino is an ES3+ engine in Java.

The Standalone scripts can be parsed and evaluated in a Rhino context.

This demo wraps workbooks and sheets into separate Java classes. The final result is a JAR.

caution

Rhino does not support Uint8Array, so certain formats like NUMBERS cannot be parsed or written from Rhino JS code!

Integration Details

note

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

Context context = Context.enter();
context.setOptimizationLevel(-1);

Binary strings can be passed back and forth.

Initialize Rhino

Rhino does not provide a global variable. It can be created:

Context cx = Context.enter();
Scriptable scope = cx.initStandardObjects();

/* Disable optimization */
cx.setOptimizationLevel(-1);

/* Initialize `global` variable */
String s = "var global = (function(){ return this; }).call(null);";
cx.evaluateString(scope, s, "<cmd>", 1, null);

Load SheetJS Scripts

The main library can be loaded by reading the scripts from the Java Archive and evaluating in the Rhino context:

/* pull source from JAR */
String s = new Scanner(
SheetJS.class.getResourceAsStream("/xlsx.full.min.js")
).useDelimiter("\\Z").next();
/* evaluate */
cx.evaluateString(scope, s, "<cmd>", 1, null);

To confirm the library is loaded, XLSX.version can be inspected:

/* get handle to XLSX */
Object XLSX = scope.get("XLSX", scope);
if(XLSX == Scriptable.NOT_FOUND) throw new Exception("XLSX not found");

/* get the version string */
String version = ((NativeObject)XLSX).get("version", scope).toString();
System.out.println("SheetJS version " + version);

Reading Files

A binary string can be generated from a byte array:

  static String read_file(String file) throws IOException {
/* read file -> array of bytes */
byte[] b = Files.readAllBytes(Paths.get(file));

/* construct binary string */
StringBuilder sb = new StringBuilder();
for(int i = 0; i < b.length; ++i) sb.append(Character.toString((char)(b[i] < 0 ? b[i] + 256 : b[i])));
return sb.toString();
}

This string can be loaded into the JS engine and processed:

  /* options argument */
String os = "q = {'type':'binary', 'WTF':1};";
NativeObject o = (NativeObject)cx.evaluateString(scope, os, "<cmd>", 2, null);

/* set up function arguments */
String data = read_file(path_to_file);
Object args[] = {data, o};

/* call read -> wb workbook */
NativeObject nXLSX = (NativeObject)XLSX;
Function readfunc = (Function)XLSX.get("read", scope);
NativeObject wb = (NativeObject)readfunc.call(cx, scope, nXLSX, args);

wb will be a reference to the JS workbook object.

Complete Example

note

This demo was tested on 2023 February 14 using Rhino 1.7.14.

0) Ensure Java is installed. Create a folder for the project, download the JAR and rename to rhino.jar:

mkdir sheetjs-java
cd sheetjs-java
curl -L -o rhino.jar https://github.com/mozilla/rhino/releases/download/Rhino1_7_14_Release/rhino-1.7.14.jar

1) Download the standalone script and the test file:

curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js
curl -LO https://sheetjs.com/pres.xlsx

2) Download SheetJSRhino.zip and unzip

curl -LO https://docs.sheetjs.com/rhino/SheetJSRhino.zip
unzip SheetJSRhino.zip

3) Save the following code to SheetJSRhino.java:

SheetJSRhino.java
/* sheetjs (C) 2013-present  SheetJS -- https://sheetjs.com */
/* vim: set ts=2: */
import com.sheetjs.SheetJS;
import com.sheetjs.SheetJSFile;
import com.sheetjs.SheetJSSheet;

public class SheetJSRhino {
public static void main(String args[]) throws Exception {
try {
SheetJS sjs = new SheetJS();

/* open file */
SheetJSFile xl = sjs.read_file(args[0]);

/* get sheetnames */
String[] sheetnames = xl.get_sheet_names();
System.err.println(sheetnames[0]);

/* convert to CSV */
SheetJSSheet sheet = xl.get_sheet(0);
String csv = sheet.get_csv();
System.out.println(csv);
} catch(Exception e) { throw e; } finally { SheetJS.close(); }
}
}

4) Assemble SheetJS.jar from the demo code:

javac -cp .:rhino.jar SheetJSRhino.java
jar -cf SheetJS.jar SheetJSRhino.class com/sheetjs/*.class xlsx.full.min.js

5) Test the program:

java -cp .:SheetJS.jar:rhino.jar SheetJSRhino pres.xlsx

If successful, a CSV will be printed to console.