This commit is contained in:
SheetJS 2023-03-28 00:57:47 -04:00
parent 4471237699
commit 6baef4dae7
9 changed files with 260 additions and 110 deletions

@ -161,7 +161,7 @@ Bower is deprecated and the maintainers recommend using other tools.
:::
[Bower](https://bower.io/) plays nice with the CDN tarballs:
The Bower package manager plays nice with the CDN tarballs:
<pre><code parentName="pre" {...{"className": "language-bash"}}>{`\
npx bower install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}

@ -10,15 +10,6 @@ import current from '/version.js';
# Bun
[Bun](https://bun.sh/) is a JavaScript runtime powered by JavaScriptCore.
:::caution Bun support is considered experimental.
Great open source software grows with user tests and reports. Any issues should
be reported to the Bun project for further diagnosis.
:::
Each standalone release script is available at <https://cdn.sheetjs.com/>.
<div><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs`}>https://cdn.sheetjs.com/xlsx-{current}/package/xlsx.mjs</a> is the URL for {current}</div><br/>
@ -31,6 +22,13 @@ import * as fs from 'fs';
XLSX.set_fs(fs);
```
:::caution Bun support is considered experimental.
Great open source software grows with user tests and reports. Any issues should
be reported to the Bun project for further diagnosis.
:::
## Encoding support
If Encoding support is required, `cpexcel.full.mjs` must be manually imported.

@ -5,7 +5,7 @@ pagination_next: demos/grid/index
sidebar_position: 1
---
[ReactJS](https://reactjs.org/) is a JS library for building user interfaces.
ReactJS is a JS library for building user interfaces.
This demo tries to cover common React data flow ideas and strategies. React
familiarity is assumed.

@ -5,7 +5,7 @@ pagination_next: demos/grid/index
sidebar_position: 2
---
[VueJS](https://vuejs.org/) is a JS library for building user interfaces.
VueJS is a JS library for building user interfaces.
This demo covers common VueJS data flow ideas and strategies. Single-File
Components (SFC) and VueJS familiarity is assumed.

@ -8,7 +8,7 @@ sidebar_position: 3
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
[Angular](https://angular.io/) is a JS library for building user interfaces.
Angular is a JS library for building user interfaces.
This demo tries to cover common Angular data flow ideas and strategies. Angular
and TypeScript familiarity is assumed.

@ -5,7 +5,7 @@ pagination_next: demos/grid/index
sidebar_position: 4
---
[Svelte](https://svelte.dev/) is a JS library for building user interfaces.
Svelte is a JS library for building user interfaces.
This demo tries to cover common Svelte data flow ideas and strategies. Svelte
familiarity is assumed.

@ -0,0 +1,204 @@
---
title: Java + Nashorn
pagination_prev: demos/bigdata/index
pagination_next: solutions/input
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Nashorn is a JavaScript engine for Java. It shipped with Java distributions
starting with Java 8 and was eventually removed in Java 15. The project was
spun off and a compatible standalone release is available for Java 15+.
The [Standalone scripts](/docs/getting-started/installation/standalone) can be
parsed and evaluated in a Nashorn context.
## Integration Details
_Initialize Nashorn_
`global` must be created from a Nashorn engine:
```java
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Scanner;
/* initialize nashorn engine */
ScriptEngine engine = (new ScriptEngineManager()).getEngineByName("javascript");
/* create global */
engine.eval("var global = (function(){ return this; }).call(null);");
```
_Load SheetJS Scripts_
The main library can be loaded by reading the script from the file system and
evaluating in the Nashorn context:
```java
engine.eval(new Scanner(
SheetJS.class.getResourceAsStream("/xlsx.full.min.js")
).useDelimiter("\\Z").next());
```
To confirm the library is loaded, `XLSX.version` can be printed using the
Nashorn `print` built-in:
```java
engine.eval("print('SheetJS Version ' + XLSX.version);");
```
### Reading Files
Nashorn does not properly project `byte[]` into a JS array or `Int8Array`. The
recommended workaround is to copy the data in the JS context using the JS code:
```js
function b2a(b) {
var out = typeof Uint8Array == 'function' ? new Uint8Array(b.length) : new Array(b.length);
/* `b` is similar to Int8Array (values in the range -128 .. 127 ) */
for(var i = 0; i < out.length; i++) out[i] = (b[i] + 256) & 0xFF;
return out;
}
```
This function should be embedded in the Java code:
```java
/* read spreadsheet bytes */
engine.put("bytes", Files.readAllBytes(Paths.get(args[0])));
/* convert signed byte array to JS Uint8Array or unsigned byte array */
engine.eval(
"function b2a(b) {" +
"var out = typeof Uint8Array == 'function' ? new Uint8Array(b.length) : new Array(b.length);" +
"for(var i = 0; i < out.length; i++) out[i] = (b[i] + 256) & 0xFF;" +
"return out;" +
"}" +
"var u8a = b2a(bytes)"
);
/* parse workbook */
engine.eval("var wb = XLSX.read(u8a, {type: 'array'})");
```
## Complete Example
:::note
This demo was last tested on 2023 March 27 using:
- OpenJDK 19.0.1 + Nashorn 15.4 standalone
- OpenJDK 11.0.18 + Official Nashorn
:::
<Tabs groupId="java">
<TabItem value="stdlib" label="Java 8 - 14">
Nashorn is available without additional dependencies
</TabItem>
<TabItem value="standalone" label="Java 15+">
0) Download Nashorn and its dependencies:
```bash
curl -LO "https://search.maven.org/remotecontent?filepath=org/openjdk/nashorn/nashorn-core/15.4/nashorn-core-15.4.jar"
curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm/9.5/asm-9.5.jar"
curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-tree/9.5/asm-tree-9.5.jar"
curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-commons/9.5/asm-commons-9.5.jar"
curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-analysis/9.5/asm-analysis-9.5.jar"
curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-util/9.5/asm-util-9.5.jar"
```
</TabItem>
</Tabs>
1) Download the standalone script, shim script, and the test file:
<ul>
<li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li>
<li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js`}>shim.min.js</a></li>
<li><a href="https://sheetjs.com/pres.xlsx">pres.xlsx</a></li>
</ul>
```bash
curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js
curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js
curl -LO https://sheetjs.com/pres.xlsx
```
2) Download [`SheetJSNashorn.java`](pathname:///nashorn/SheetJSNashorn.java):
```bash
curl -LO https://docs.sheetjs.com/nashorn/SheetJSNashorn.java
```
3) Build the sample class:
```bash
javac SheetJSNashorn.java
```
This program tries to parse the file specified by the first argument
4) Run the command directly:
<Tabs groupId="java">
<TabItem value="stdlib" label="Java 8 - 14">
```bash
java SheetJSNashorn pres.xlsx
```
</TabItem>
<TabItem value="standalone" label="Java 15+">
```bash
java -cp .:asm-9.5.jar:asm-tree-9.5.jar:asm-commons-9.5.jar:asm-analysis-9.5.jar:asm-util-9.5.jar:nashorn-core-15.4.jar SheetJSNashorn pres.xlsx
```
</TabItem>
</Tabs>
5) Assemble a Java Archive:
```bash
jar -cf SheetJSNashorn.jar SheetJSNashorn.class xlsx.full.min.js shim.min.js
```
6) Verify the Java Archive.
Create new directory and copy the archives and test file:
```bash
mkdir -p sheethorn
cp *.jar pres.xlsx sheethorn
cd sheethorn
```
Invoke the command in the archive:
<Tabs groupId="java">
<TabItem value="stdlib" label="Java 8 - 14">
```bash
java -cp .:SheetJSNashorn.jar SheetJSNashorn pres.xlsx
```
</TabItem>
<TabItem value="standalone" label="Java 15+">
```bash
java -cp .:asm-9.5.jar:asm-tree-9.5.jar:asm-commons-9.5.jar:asm-analysis-9.5.jar:asm-util-9.5.jar:nashorn-core-15.4.jar:SheetJSNashorn.jar SheetJSNashorn pres.xlsx
```
</TabItem>
</Tabs>

@ -240,6 +240,13 @@ build/bin/jerry xlsx.jerry.js; echo $?
</details>
### Nashorn
Nashorn shipped with some versions of Java. It is now a standalone library.
This demo has been moved [to a dedicated page](/docs/demos/engines/nashorn).
### QuickJS
QuickJS is an embeddable JS engine written in C. It provides a separate set of
@ -255,15 +262,6 @@ Rhino is an ES3+ engine in Java.
This demo has been moved [to a dedicated page](/docs/demos/engines/rhino).
## Legacy Engines
:::warning
These examples were written when the engines were maintained. New projects
should not use these engines. The demos are included for legacy deployments.
:::
### ChakraCore
:::caution
@ -342,90 +340,3 @@ ready, it will read the bundled test data and print the contents as CSV.
```
</details>
### Nashorn
:::caution
Nashorn shipped with Java 8. It was deprecated in Java 11 and was officially
removed in JDK 15. New Java applications should use [Rhino](#rhino).
:::
Nashorn ships with Java. 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:
```js
var global = (function(){ return this; }).call(null);
load('shim.min.js');
load('xlsx.full.min.js');
```
The Java `nio` API provides the `Files.readAllBytes` method to read a file into
a byte array. To use in `XLSX.read`, the demo copies the bytes into a plain JS
array and calls `XLSX.read` with type `"array"`.
<details><summary><b>Complete Example</b> (click to show)</summary>
0) Ensure `jjs` is available on system path
1) Download the standalone script, the shim and the test file:
<ul>
<li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li>
<li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js`}>shim.min.js</a></li>
<li><a href="https://sheetjs.com/pres.numbers">pres.numbers</a></li>
</ul>
2) Save the following script to `SheetJSNashorn.js`:
```js title="SheetJSNashorn.js"
/* sheetjs (C) 2013-present SheetJS -- https://sheetjs.com */
/* load module */
var global = (function(){ return this; }).call(null);
load('shim.min.js');
load('xlsx.full.min.js');
/* helper to convert byte array to plain JS array */
function b2a(b) {
var out = new Array(b.length);
for(var i = 0; i < out.length; i++) out[i] = (b[i] < 0 ? b[i] + 256 : b[i]);
return out;
}
function process_file(path) {
java.lang.System.out.println(path);
/* read file */
var path = java.nio.file.Paths.get(path);
var bytes = java.nio.file.Files.readAllBytes(path);
var u8a = b2a(bytes);
/* read data */
var wb = XLSX.read(u8a);
/* get first worksheet as an array of arrays */
var ws = wb.Sheets[wb.SheetNames[0]];
var js = XLSX.utils.sheet_to_json(ws, {header:1});
/* print out every line */
js.forEach(function(l) { java.lang.System.out.println(JSON.stringify(l)); });
}
process_file('pres.numbers');
```
3) Test the script:
```bash
jjs SheetJSNashorn.js
```
It will print out the first worksheet contents.
</details>

@ -0,0 +1,37 @@
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Scanner;
public class SheetJSNashorn {
public static void main(String[] args) throws Exception {
/* initialize */
ScriptEngine engine = (new ScriptEngineManager()).getEngineByName("javascript");
/* read script file */
engine.eval("var global = (function(){ return this; }).call(null);");
engine.eval(new Scanner(SheetJSNashorn.class.getResourceAsStream("/shim.min.js")).useDelimiter("\\Z").next());
engine.eval(new Scanner(SheetJSNashorn.class.getResourceAsStream("/xlsx.full.min.js")).useDelimiter("\\Z").next());
engine.eval("print('SheetJS Version ' + XLSX.version);");
/* read spreadsheet bytes */
engine.put("bytes", Files.readAllBytes(Paths.get(args[0])));
/* convert signed byte array to JS Uint8Array or unsigned byte array */
engine.eval("function b2a(b) {" +
"var out = typeof Uint8Array == 'function' ? new Uint8Array(b.length) : new Array(b.length);" +
"for(var i = 0; i < out.length; i++) out[i] = (b[i] + 256) & 0xFF;" +
"return out;" +
"}" +
"var u8a = b2a(bytes)");
/* parse workbook */
engine.eval("var wb = XLSX.read(u8a, {type: 'array'})");
/* get first worksheet as CSV */
engine.eval("var ws = wb.Sheets[wb.SheetNames[0]];");
Object res = engine.eval("XLSX.utils.sheet_to_csv(ws)");
System.out.println(res);
}
}