Skip to main content

Ruby + Bindings

ExecJS is a Ruby abstraction over a number of JS runtimes including V8.

SheetJS is a JavaScript library for reading and writing data from spreadsheets.

This demo uses ExecJS and SheetJS to pull data from sheets and print CSV rows. We'll explore how to load SheetJS in ExecJS contexts and process data in Ruby.

The "Complete Example" section includes a complete Ruby script for reading data from files.

Integration Details​

The SheetJS Standalone scripts can be parsed and evaluated in every supported runtime.

Initialize ExecJS​

The require command performs the required initialization steps:

require "execjs"

Load SheetJS Scripts​

The main library can be loaded and compiled in a new context:

require "execjs"

source = File.open("xlsx.full.min.js", "rb").read;
source.force_encoding("UTF-8");
context = ExecJS.compile(source);

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

puts context.eval("XLSX.version");

Reading and Writing Files​

The architecture of ExecJS forces users to combine reading and writing in one function step. Base64 strings should be used for interchange. For example, the following snippet reads data from pres.numbers, generates an XLSB file, and writes to sheetjsw.xlsb:

require "base64"

# read and encode data to Base64
data = Base64.strict_encode64(File.open("pres.numbers", "rb").read);

# define function and call with the data
xlsb = context.call(<<EOF, data);
function(data) {
/* parse data -- the argument is the data from Ruby code */
var wb = XLSX.read(data, {type: 'base64'});
/* write XLSB data (encoded as base64) */
return XLSX.write(wb, {bookType: "xlsb", type: "base64"});
}
EOF
# at this point, `xlsb` is a Base64-encoded string

# decode and write to file
File.write("sheetjsw.xlsb", Base64.strict_decode64(xlsb), mode: "wb");

The strict_ variants ensure that no newlines are added to the strings.

Complete Example​

Tested Deployments

This demo was tested in the following deployments:

PlatformRubyExecJSDate
darwin-x642.6.102.9.12024-04-25
darwin-arm2.6.102.9.12024-05-25
win10-x643.2.32.9.12024-03-10
win11-arm3.0.22.9.12024-05-25
linux-x643.0.52.9.12024-03-21
linux-arm3.1.22.9.12024-05-25

When the demo was last tested, there was no official Ruby release for Windows on ARM. The win11-arm test was run in WSL. The win10-x64 test used the official Ruby for Windows x64 release.

  1. Install Ruby, gem (RubyGems), and the dependencies:
gem install execjs
Installation Notes (click to show)

The command may need to be run as an administrator or root user:

sudo gem install execjs

On Arch Linux-based platforms including the Steam Deck, rubygems must be installed through the package manager:

sudo pacman -Syu rubygems
  1. Create a new project folder:
mkdir sheetjs-rb
cd sheetjs-rb
  1. Download the SheetJS Standalone script and the test file. Save both files in the project directory:
curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js
curl -LO https://docs.sheetjs.com/pres.numbers
  1. Download ExecSheetJS.rb:
curl -LO https://docs.sheetjs.com/execjs/ExecSheetJS.rb
  1. Run the demo:
ruby ExecSheetJS.rb pres.numbers

If the program succeeded, the CSV contents will be printed to console and the file sheetjsw.xlsb will be created. That file can be opened with Excel.

If a JavaScript runtime is not available, the script will throw an error:

execjs/runtimes.rb:68:in `autodetect': Could not find a JavaScript runtime. See https://github.com/rails/execjs for a list of available runtimes. (ExecJS::RuntimeUnavailable)

ExecJS 2.9.1 supports the Bun runtime. Install the Bun runtime1, restart the terminal, and re-run the script.

Footnotes​

  1. curl -fsSL https://bun.sh/install | bash can be run from macOS, Linux, and Windows WSL. ↩