forked from sheetjs/docs.sheetjs.com
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f77d0bd788 | |||
| f9dbcc069b | |||
| 38b268d40c | |||
| fc5a19d6cd | |||
| f5aabe0c29 | |||
| 7bb2ddcaea | |||
| a0e35dd7e1 | |||
| d922ad6246 | |||
| 5633b2387a | |||
| ef89abda1f | |||
| 6532f9fea8 | |||
| 67d7c1f993 | |||
| def11cf796 | |||
| b205f3f6a1 | |||
| f1a4f192d3 | |||
| 1327b2f98c | |||
| f39d01eb84 | |||
| 3875a9ee91 | |||
| d74827a012 | |||
| ac0f80025a | |||
| 609f7ff5f2 | |||
| e5d9d1c15e | |||
| 2d6b139ef7 | |||
| 4e3a0637ea | |||
| 8a65ff5698 | |||
| d77a40c6bf | |||
| 9af5473755 | |||
| 1f87dda979 | |||
| 1b242c12ef |
3
.gitignore
vendored
3
.gitignore
vendored
@ -4,4 +4,5 @@ package-lock.json
|
||||
pnpm-lock.yaml
|
||||
/docs
|
||||
node_modules
|
||||
.idea
|
||||
.idea
|
||||
.vscode
|
||||
2
Makefile
2
Makefile
@ -12,7 +12,7 @@ init:
|
||||
|
||||
.PHONY: dev
|
||||
dev:
|
||||
cd docz; npm run start -- --host=0.0.0.0 --no-open; cd ..
|
||||
cd docz; npm run start -- --host=0.0.0.0 --port 6996 --no-open; cd ..
|
||||
|
||||
.PHONY: serve
|
||||
serve:
|
||||
|
||||
@ -16,7 +16,7 @@ $ make init # install dependencies
|
||||
$ make # build static site
|
||||
$ make serve # serve static site
|
||||
|
||||
$ make dev # run dev server
|
||||
$ make dev # run dev server on port 6996
|
||||
$ make spell # spell check (.spelling custom dictionary)
|
||||
$ make graph # build format graph and legend
|
||||
```
|
||||
@ -99,7 +99,7 @@ tables in <https://docs.sheetjs.com/docs/demos/engines/>. The component script
|
||||
### Formats Graph
|
||||
|
||||
The formats graph and legend are written in the DOT language. Rebuilding the
|
||||
graphs will require Graphviz (`brew install graphviz` on macOS)
|
||||
graphs will require Graphviz and the "Indie Flower" font.
|
||||
|
||||
## Live Demos
|
||||
|
||||
|
||||
@ -1,417 +1,417 @@
|
||||
<?xml version="1.0"?>
|
||||
<?mso-application progid="Excel.Sheet"?>
|
||||
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">
|
||||
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
|
||||
<WindowHeight>10620</WindowHeight>
|
||||
<WindowWidth>11020</WindowWidth>
|
||||
<WindowTopX>2260</WindowTopX>
|
||||
<WindowTopY>19600</WindowTopY>
|
||||
<ActiveSheet>1</ActiveSheet>
|
||||
<ProtectStructure>False</ProtectStructure>
|
||||
<ProtectWindows>False</ProtectWindows>
|
||||
</ExcelWorkbook>
|
||||
<Styles>
|
||||
<Style ss:ID="Default" ss:Name="Normal">
|
||||
<Alignment ss:Vertical="Bottom"/>
|
||||
<Borders/>
|
||||
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#000000"/>
|
||||
<Interior/>
|
||||
<NumberFormat/>
|
||||
<Protection/>
|
||||
</Style>
|
||||
<Style ss:ID="s16">
|
||||
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#1C1E21"/>
|
||||
</Style>
|
||||
<Style ss:ID="s17">
|
||||
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#000000" ss:Bold="1"/>
|
||||
</Style>
|
||||
<Style ss:ID="s19">
|
||||
<Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/>
|
||||
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#000000" ss:Bold="1"/>
|
||||
</Style>
|
||||
<Style ss:ID="s20">
|
||||
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#467886" ss:Underline="Single"/>
|
||||
</Style>
|
||||
</Styles>
|
||||
<Worksheet ss:Name="Engines">
|
||||
<Table ss:ExpandedColumnCount="8" ss:ExpandedRowCount="18" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="16">
|
||||
<Column ss:Index="3" ss:Width="24"/>
|
||||
<Column ss:Width="31"/>
|
||||
<Column ss:Width="24"/>
|
||||
<Column ss:Width="31"/>
|
||||
<Column ss:Width="24"/>
|
||||
<Column ss:Width="31"/>
|
||||
<Row>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s17"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">MacOS</Data></Cell>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">Windows</Data></Cell>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">Linux</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">Engine</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">Lang</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">x64</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">ARM</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">x64</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">ARM</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">x64</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">ARM</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/duktape#complete-example"><Data ss:Type="String">Duktape</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/v8#complete-example"><Data ss:Type="String">V8</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C++</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/rhino#complete-example"><Data ss:Type="String">Rhino</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Java</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/jsc#complete-example"><Data ss:Type="String">JSC</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C++</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/jint#integration-example"><Data ss:Type="String">Jint</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C#</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/goja#complete-example"><Data ss:Type="String">Goja</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Go</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/nashorn#complete-example"><Data ss:Type="String">Nashorn</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Java</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/quickjs#integration-example"><Data ss:Type="String">QuickJS</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/hermes#integration-example"><Data ss:Type="String">Hermes</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C++</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/chakra#integration-example"><Data ss:Type="String">ChakraCore</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C++</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/boa#complete-example"><Data ss:Type="String">Boa</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Rust</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/perl#complete-example"><Data ss:Type="String">JE</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Perl</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/jerryscript#integration-example"><Data ss:Type="String">JerryScript</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✱</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✱</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/graaljs#complete-example"><Data ss:Type="String">GraalJS</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Java</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/mujs#integration-example"><Data ss:Type="String">MuJS</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✱</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✱</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/jurassic#integration-example"><Data ss:Type="String">Jurassic.NET</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C#</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
</Table>
|
||||
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
|
||||
<PageSetup>
|
||||
<Header x:Margin="0.3"/>
|
||||
<Footer x:Margin="0.3"/>
|
||||
<PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
|
||||
</PageSetup>
|
||||
<FreezePanes/>
|
||||
<FrozenNoSplit/>
|
||||
<SplitHorizontal>2</SplitHorizontal>
|
||||
<TopRowBottomPane>2</TopRowBottomPane>
|
||||
<ActivePane>2</ActivePane>
|
||||
<Panes>
|
||||
<Pane>
|
||||
<Number>3</Number>
|
||||
</Pane>
|
||||
<Pane>
|
||||
<Number>2</Number>
|
||||
<ActiveRow>12</ActiveRow>
|
||||
<ActiveCol>5</ActiveCol>
|
||||
</Pane>
|
||||
</Panes>
|
||||
<ProtectObjects>False</ProtectObjects>
|
||||
<ProtectScenarios>False</ProtectScenarios>
|
||||
</WorksheetOptions>
|
||||
</Worksheet>
|
||||
<Worksheet ss:Name="Bindings">
|
||||
<Table ss:ExpandedColumnCount="8" ss:ExpandedRowCount="20" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="16">
|
||||
<Column ss:Index="3" ss:Width="24"/>
|
||||
<Column ss:Width="31"/>
|
||||
<Column ss:Width="24"/>
|
||||
<Column ss:Width="31"/>
|
||||
<Column ss:Width="24"/>
|
||||
<Column ss:Width="31"/>
|
||||
<Row>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s17"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">MacOS</Data></Cell>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">Windows</Data></Cell>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">Linux</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">Engine</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">Lang</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">x64</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">ARM</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">x64</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">ARM</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">x64</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">ARM</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/duktape#perl"><Data ss:Type="String">Duktape</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Perl</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/duktape#php"><Data ss:Type="String">Duktape</Data></Cell>
|
||||
<Cell><Data ss:Type="String">PHP</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/duktape#python"><Data ss:Type="String">Duktape</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Python</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/duktape#rust"><Data ss:Type="String">Duktape</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Rust</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/duktape#zig"><Data ss:Type="String">Duktape</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Zig</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/v8#rust"><Data ss:Type="String">V8</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Rust</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/v8#java"><Data ss:Type="String">V8</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Java</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/v8#c"><Data ss:Type="String">V8</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C#</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/v8#python"><Data ss:Type="String">V8</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Python</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/jsc#swift"><Data ss:Type="String">JSC</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Swift</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/jsc#rust"><Data ss:Type="String">JSC</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Rust</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/rb#complete-example"><Data ss:Type="String">ExecJS</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Ruby</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✱</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
</Table>
|
||||
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
|
||||
<PageSetup>
|
||||
<Header x:Margin="0.3"/>
|
||||
<Footer x:Margin="0.3"/>
|
||||
<PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
|
||||
</PageSetup>
|
||||
<Selected/>
|
||||
<FreezePanes/>
|
||||
<FrozenNoSplit/>
|
||||
<SplitHorizontal>2</SplitHorizontal>
|
||||
<TopRowBottomPane>2</TopRowBottomPane>
|
||||
<ActivePane>2</ActivePane>
|
||||
<Panes>
|
||||
<Pane>
|
||||
<Number>3</Number>
|
||||
</Pane>
|
||||
<Pane>
|
||||
<Number>2</Number>
|
||||
<ActiveRow>3</ActiveRow>
|
||||
<ActiveCol>1</ActiveCol>
|
||||
</Pane>
|
||||
</Panes>
|
||||
<ProtectObjects>False</ProtectObjects>
|
||||
<ProtectScenarios>False</ProtectScenarios>
|
||||
</WorksheetOptions>
|
||||
</Worksheet>
|
||||
</Workbook>
|
||||
<?xml version="1.0"?>
|
||||
<?mso-application progid="Excel.Sheet"?>
|
||||
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">
|
||||
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
|
||||
<WindowHeight>10620</WindowHeight>
|
||||
<WindowWidth>11020</WindowWidth>
|
||||
<WindowTopX>2260</WindowTopX>
|
||||
<WindowTopY>19600</WindowTopY>
|
||||
<ActiveSheet>1</ActiveSheet>
|
||||
<ProtectStructure>False</ProtectStructure>
|
||||
<ProtectWindows>False</ProtectWindows>
|
||||
</ExcelWorkbook>
|
||||
<Styles>
|
||||
<Style ss:ID="Default" ss:Name="Normal">
|
||||
<Alignment ss:Vertical="Bottom"/>
|
||||
<Borders/>
|
||||
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#000000"/>
|
||||
<Interior/>
|
||||
<NumberFormat/>
|
||||
<Protection/>
|
||||
</Style>
|
||||
<Style ss:ID="s16">
|
||||
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#1C1E21"/>
|
||||
</Style>
|
||||
<Style ss:ID="s17">
|
||||
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#000000" ss:Bold="1"/>
|
||||
</Style>
|
||||
<Style ss:ID="s19">
|
||||
<Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/>
|
||||
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#000000" ss:Bold="1"/>
|
||||
</Style>
|
||||
<Style ss:ID="s20">
|
||||
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#467886" ss:Underline="Single"/>
|
||||
</Style>
|
||||
</Styles>
|
||||
<Worksheet ss:Name="Engines">
|
||||
<Table ss:ExpandedColumnCount="8" ss:ExpandedRowCount="18" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="16">
|
||||
<Column ss:Index="3" ss:Width="24"/>
|
||||
<Column ss:Width="31"/>
|
||||
<Column ss:Width="24"/>
|
||||
<Column ss:Width="31"/>
|
||||
<Column ss:Width="24"/>
|
||||
<Column ss:Width="31"/>
|
||||
<Row>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s17"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">MacOS</Data></Cell>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">Windows</Data></Cell>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">Linux</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">Engine</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">Lang</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">x64</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">ARM</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">x64</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">ARM</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">x64</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">ARM</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/duktape#complete-example"><Data ss:Type="String">Duktape</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/v8#complete-example"><Data ss:Type="String">V8</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C++</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/rhino#complete-example"><Data ss:Type="String">Rhino</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Java</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/jsc#complete-example"><Data ss:Type="String">JSC</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C++</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/jint#integration-example"><Data ss:Type="String">Jint</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C#</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/goja#complete-example"><Data ss:Type="String">Goja</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Go</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/nashorn#complete-example"><Data ss:Type="String">Nashorn</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Java</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/quickjs#integration-example"><Data ss:Type="String">QuickJS</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/hermes#integration-example"><Data ss:Type="String">Hermes</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C++</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/chakra#integration-example"><Data ss:Type="String">ChakraCore</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C++</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/boa#complete-example"><Data ss:Type="String">Boa</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Rust</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/perl#complete-example"><Data ss:Type="String">JE</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Perl</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✱</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✱</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/jerryscript#integration-example"><Data ss:Type="String">JerryScript</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✱</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✱</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/graaljs#complete-example"><Data ss:Type="String">GraalJS</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Java</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/mujs#integration-example"><Data ss:Type="String">MuJS</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✱</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✱</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/jurassic#integration-example"><Data ss:Type="String">Jurassic.NET</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C#</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
</Table>
|
||||
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
|
||||
<PageSetup>
|
||||
<Header x:Margin="0.3"/>
|
||||
<Footer x:Margin="0.3"/>
|
||||
<PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
|
||||
</PageSetup>
|
||||
<FreezePanes/>
|
||||
<FrozenNoSplit/>
|
||||
<SplitHorizontal>2</SplitHorizontal>
|
||||
<TopRowBottomPane>2</TopRowBottomPane>
|
||||
<ActivePane>2</ActivePane>
|
||||
<Panes>
|
||||
<Pane>
|
||||
<Number>3</Number>
|
||||
</Pane>
|
||||
<Pane>
|
||||
<Number>2</Number>
|
||||
<ActiveRow>12</ActiveRow>
|
||||
<ActiveCol>5</ActiveCol>
|
||||
</Pane>
|
||||
</Panes>
|
||||
<ProtectObjects>False</ProtectObjects>
|
||||
<ProtectScenarios>False</ProtectScenarios>
|
||||
</WorksheetOptions>
|
||||
</Worksheet>
|
||||
<Worksheet ss:Name="Bindings">
|
||||
<Table ss:ExpandedColumnCount="8" ss:ExpandedRowCount="20" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="16">
|
||||
<Column ss:Index="3" ss:Width="24"/>
|
||||
<Column ss:Width="31"/>
|
||||
<Column ss:Width="24"/>
|
||||
<Column ss:Width="31"/>
|
||||
<Column ss:Width="24"/>
|
||||
<Column ss:Width="31"/>
|
||||
<Row>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s17"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">MacOS</Data></Cell>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">Windows</Data></Cell>
|
||||
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">Linux</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">Engine</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">Lang</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">x64</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">ARM</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">x64</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">ARM</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">x64</Data></Cell>
|
||||
<Cell ss:StyleID="s17"><Data ss:Type="String">ARM</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/duktape#perl"><Data ss:Type="String">Duktape</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Perl</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/duktape#php"><Data ss:Type="String">Duktape</Data></Cell>
|
||||
<Cell><Data ss:Type="String">PHP</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/duktape#python"><Data ss:Type="String">Duktape</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Python</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/duktape#rust"><Data ss:Type="String">Duktape</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Rust</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/duktape#zig"><Data ss:Type="String">Duktape</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Zig</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/v8#rust"><Data ss:Type="String">V8</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Rust</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/v8#java"><Data ss:Type="String">V8</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Java</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/v8#c"><Data ss:Type="String">V8</Data></Cell>
|
||||
<Cell><Data ss:Type="String">C#</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/v8#python"><Data ss:Type="String">V8</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Python</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/jsc#swift"><Data ss:Type="String">JSC</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Swift</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/jsc#rust"><Data ss:Type="String">JSC</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Rust</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"/>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
<Row>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/rb#complete-example"><Data ss:Type="String">ExecJS</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Ruby</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✱</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
</Row>
|
||||
</Table>
|
||||
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
|
||||
<PageSetup>
|
||||
<Header x:Margin="0.3"/>
|
||||
<Footer x:Margin="0.3"/>
|
||||
<PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
|
||||
</PageSetup>
|
||||
<Selected/>
|
||||
<FreezePanes/>
|
||||
<FrozenNoSplit/>
|
||||
<SplitHorizontal>2</SplitHorizontal>
|
||||
<TopRowBottomPane>2</TopRowBottomPane>
|
||||
<ActivePane>2</ActivePane>
|
||||
<Panes>
|
||||
<Pane>
|
||||
<Number>3</Number>
|
||||
</Pane>
|
||||
<Pane>
|
||||
<Number>2</Number>
|
||||
<ActiveRow>3</ActiveRow>
|
||||
<ActiveCol>1</ActiveCol>
|
||||
</Pane>
|
||||
</Panes>
|
||||
<ProtectObjects>False</ProtectObjects>
|
||||
<ProtectScenarios>False</ProtectScenarios>
|
||||
</WorksheetOptions>
|
||||
</Worksheet>
|
||||
</Workbook>
|
||||
|
||||
@ -16,7 +16,7 @@ Each standalone release script is available at https://cdn.sheetjs.com/.
|
||||
|
||||
<CodeBlock language="html">{`\
|
||||
<!-- use version ${current} -->
|
||||
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>`}
|
||||
<script type="text/javascript" src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>`}
|
||||
</CodeBlock>
|
||||
|
||||
:::tip pass
|
||||
@ -44,7 +44,7 @@ reading and writing many spreadsheet formats.
|
||||
|
||||
<CodeBlock language="html">{`\
|
||||
<!-- use xlsx.full.min.js from version ${current} -->
|
||||
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>`}
|
||||
<script type="text/javascript" src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>`}
|
||||
</CodeBlock>
|
||||
|
||||
`xlsx.mini.min.js` is a slimmer build that omits the following features:
|
||||
@ -60,7 +60,7 @@ A single script tag should be added at the top of the HTML page:
|
||||
|
||||
<CodeBlock language="html">{`\
|
||||
<!-- use xlsx.mini.min.js from version ${current} -->
|
||||
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.mini.min.js"></script>`}
|
||||
<script type="text/javascript" src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.mini.min.js"></script>`}
|
||||
</CodeBlock>
|
||||
|
||||
</details>
|
||||
@ -118,20 +118,20 @@ importScripts("https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.mi
|
||||
|
||||
### Type Checker
|
||||
|
||||
:::danger VSCode Telemetry and Data Exfiltration
|
||||
:::danger VS Code Telemetry and Data Exfiltration
|
||||
|
||||
The official Microsoft builds of Visual Studio Code ("VSCode") embed telemetry
|
||||
and send information to external servers.
|
||||
The official builds of Visual Studio Code ("VS Code" or "VSCode") embed
|
||||
telemetry and send information to Microsoft servers.
|
||||
|
||||
**[VSCodium](https://vscodium.com/) is a telemetry-free fork of VSCode.**
|
||||
**[VSCodium](https://vscodium.com/) is a telemetry-free fork of VS Code.**
|
||||
|
||||
When writing code that may process personally identifiable information (PII),
|
||||
the SheetJS team strongly encourages building VSCode from source or using IDEs
|
||||
the SheetJS team strongly encourages building VS Code from source or using IDEs
|
||||
that do not exfiltrate data.
|
||||
|
||||
:::
|
||||
|
||||
The type checker integrated in VSCodium and VSCode does not currently provide
|
||||
The type checker integrated in VSCodium and VS Code does not currently provide
|
||||
type hints when using the standalone build. Using the JSDoc `@type` directive
|
||||
coupled with type imports, VSCodium will recognize the types:
|
||||
|
||||
@ -176,7 +176,7 @@ The `.d.ts` file extension must be omitted.
|
||||
|
||||
JSDoc types using the `@import` directive are not supported in `<script>` tags.
|
||||
|
||||
**This is a known bug with VSCode!**
|
||||
**This is a known bug with VS Code!**
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -121,12 +121,12 @@ This demo was last tested in the following deployments:
|
||||
|
||||
| Architecture | BunJS | Date |
|
||||
|:-------------|:---------|:-----------|
|
||||
| `darwin-x64` | `1.2.8` | 2025-03-31 |
|
||||
| `darwin-arm` | `1.2.7` | 2025-03-30 |
|
||||
| `win11-x64` | `1.2.8` | 2025-04-17 |
|
||||
| `win11-arm` | `1.2.3` | 2025-02-23 |
|
||||
| `linux-x64` | `1.2.10` | 2025-04-21 |
|
||||
| `linux-arm` | `1.2.2` | 2025-02-16 |
|
||||
| `darwin-x64` | `1.3.6` | 2026-01-20 |
|
||||
| `darwin-arm` | `1.3.6` | 2026-01-19 |
|
||||
| `win11-x64` | `1.3.6` | 2026-01-28 |
|
||||
| `win11-arm` | `1.3.10` | 2026-03-07 |
|
||||
| `linux-x64` | `1.3.6` | 2026-01-18 |
|
||||
| `linux-arm` | `1.3.10` | 2026-03-07 |
|
||||
|
||||
BunJS on Windows on ARM uses the X64 compatibility layer.
|
||||
|
||||
@ -137,42 +137,9 @@ BunJS on Windows on ARM uses the X64 compatibility layer.
|
||||
```bash
|
||||
mkdir sheetjs-bun-dle
|
||||
cd sheetjs-bun-dle
|
||||
echo "{}" > package.json
|
||||
bun init -y
|
||||
```
|
||||
|
||||
:::caution PowerShell Encoding Errors
|
||||
|
||||
The PowerShell file redirect will use the `UTF-16 LE` encoding. Bun does not
|
||||
support the encoding and will fail to install the package:
|
||||
|
||||
```
|
||||
bun add v1.1.42 (50eec002)
|
||||
1 | <20><>
|
||||
^
|
||||
error: Unexpected <20><>
|
||||
at <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:1:1
|
||||
```
|
||||
|
||||
The file must be resaved in UTF8 (without BOM) or ASCII.
|
||||
|
||||
0) Open `package.json` in VSCodium.
|
||||
|
||||
The current encoding is displayed in the lower-right corner:
|
||||
|
||||

|
||||
|
||||
1) Click the displayed encoding.
|
||||
|
||||
2) In the "Select Action" popup, select "Save with Encoding"
|
||||
|
||||
3) In the new list, select `UTF-8 utf8`:
|
||||
|
||||

|
||||
|
||||
VSCodium will automatically re-save the file.
|
||||
|
||||
:::
|
||||
|
||||
1) Install the SheetJS package tarball:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
|
||||
@ -469,14 +469,16 @@ The result is an array of "simple" objects with no nesting:
|
||||
|
||||
## Create a Workbook
|
||||
|
||||
With the cleaned dataset, `XLSX.utils.json_to_sheet`[^3] generates a worksheet:
|
||||
The [`json_to_sheet`](/docs/api/utilities/array#array-of-objects-input) method
|
||||
can generate a SheetJS worksheet from the cleaned dataset:
|
||||
|
||||
```js
|
||||
const worksheet = XLSX.utils.json_to_sheet(rows);
|
||||
```
|
||||
|
||||
`XLSX.utils.book_new`[^4] creates a new workbook and `XLSX.utils.book_append_sheet`[^5]
|
||||
appends a worksheet to the workbook. The new worksheet will be called "Dates":
|
||||
[`XLSX.utils.book_new`](/docs/api/utilities/wb) creates a new workbook and
|
||||
[`XLSX.utils.book_append_sheet`](/docs/api/utilities/wb) appends a worksheet to
|
||||
the workbook. The new worksheet will be called "Dates":
|
||||
|
||||
```js
|
||||
const workbook = XLSX.utils.book_new();
|
||||
@ -503,10 +505,12 @@ cell styling and frozen rows.
|
||||
<summary><b>Changing Header Names</b> (click to show)</summary>
|
||||
|
||||
By default, `json_to_sheet` creates a worksheet with a header row. In this case,
|
||||
the headers come from the JS object keys: "name" and "birthday".
|
||||
the headers come from the JS object keys: "name" and "birthday". The headers are
|
||||
written to the first row.
|
||||
|
||||
The headers are in cells `A1` and `B1`. `XLSX.utils.sheet_add_aoa`[^6] can write
|
||||
text values to the existing worksheet starting at cell `A1`:
|
||||
[`XLSX.utils.sheet_add_aoa`](/docs/api/utilities/array#array-of-arrays-input)
|
||||
can overwrite data in the worksheet. The following line will set `A1` to "Name"
|
||||
and set `B1` to "Birthday":
|
||||
|
||||
```js
|
||||
XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });
|
||||
@ -518,7 +522,7 @@ XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });
|
||||
<summary><b>Changing Column Widths</b> (click to show)</summary>
|
||||
|
||||
Some of the names are longer than the default column width. Column widths are
|
||||
set by setting the `"!cols"` worksheet property.[^7]
|
||||
stored in the [`"!cols"` worksheet property](/docs/csf/features/colprops).
|
||||
|
||||
The following line sets the width of column A to approximately 10 characters:
|
||||
|
||||
@ -541,9 +545,9 @@ After cleanup, the generated workbook looks like the screenshot below:
|
||||
|
||||
## Export a File
|
||||
|
||||
`XLSX.writeFile`[^8] creates a spreadsheet file and tries to write it to the
|
||||
system. In the browser, it will try to prompt the user to download the file. In
|
||||
NodeJS, it will write to the local directory.
|
||||
[`XLSX.writeFile`](/docs/api/write-options) creates a spreadsheet file and tries
|
||||
to write it to the system. In the browser, it will try to prompt the user to
|
||||
download the file. In NodeJS, it will write to the local directory.
|
||||
|
||||
```js
|
||||
XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true });
|
||||
@ -644,7 +648,7 @@ After saving the file, run a local web server in the folder with the HTML file.
|
||||
For example, if NodeJS is installed:
|
||||
|
||||
```bash
|
||||
npx http-server .
|
||||
npx -y http-server .
|
||||
```
|
||||
|
||||
The server process will display a URL (typically `http://127.0.0.1:8080`). Open
|
||||
@ -1165,14 +1169,8 @@ see a preview of the data. The Numbers app can open the file.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
[^1]: https://theunitedstates.io/congress-legislators/executive.json is the
|
||||
[^1]: `https://theunitedstates.io/congress-legislators/executive.json` is the
|
||||
original location of the example dataset. The contributors to the dataset
|
||||
dedicated the content to the public domain.
|
||||
dedicated the content to the public domain. When this demo was last tested,
|
||||
[^2]: See ["The Executive Branch"](https://github.com/unitedstates/congress-legislators#the-executive-branch)
|
||||
in the dataset documentation.
|
||||
[^3]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input)
|
||||
[^4]: See [`book_new` in "Utilities"](/docs/api/utilities/wb)
|
||||
[^5]: See [`book_append_sheet` in "Utilities"](/docs/api/utilities/wb)
|
||||
[^6]: See [`sheet_add_aoa` in "Utilities"](/docs/api/utilities/array#array-of-arrays-input)
|
||||
[^7]: See ["Column Properties"](/docs/csf/features/colprops)
|
||||
[^8]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
||||
@ -148,14 +148,15 @@ The file data is stored in an `ArrayBuffer`.
|
||||
|
||||
## Parse File
|
||||
|
||||
With the file data in hand, `XLSX.read`[^2] parses the workbook:
|
||||
With the file data in hand, [`XLSX.read`](/docs/api/parse-options) parses the
|
||||
file and generates a SheetJS workbook object:
|
||||
|
||||
```js
|
||||
const workbook = XLSX.read(file);
|
||||
```
|
||||
|
||||
The `workbook` object follows the "Common Spreadsheet Format"[^3], an in-memory
|
||||
format for representing workbooks, worksheets, cells, and spreadsheet features.
|
||||
The `workbook` object follows the ["Common Spreadsheet Format"](/docs/csf/), an
|
||||
in-memory schema for workbooks, worksheets, cells, and spreadsheet features.
|
||||
|
||||
|
||||
## Explore Dataset
|
||||
@ -170,8 +171,8 @@ To determine how to process the data, it is best to inspect the file first.
|
||||
|
||||
### List Sheet Names
|
||||
|
||||
As explained in the "Workbook Object"[^4] section, the `SheetNames` property is
|
||||
a ordered list of the sheet names in the workbook.
|
||||
As explained in the ["Workbook Object"](/docs/csf/book) page, the `SheetNames`
|
||||
property is a list of the sheet names in the workbook.
|
||||
|
||||
The following live code block displays an ordered list of the sheet names:
|
||||
|
||||
@ -195,21 +196,25 @@ function SheetJSheetNames() {
|
||||
|
||||
### Inspect Worksheet Data
|
||||
|
||||
The `Sheets` property of the workbook object[^5] is an object whose keys are
|
||||
sheet names and whose values are sheet objects. For example, the first worksheet
|
||||
is pulled by indexing `SheetNames` and using the name to index `Sheets`:
|
||||
The [`Sheets` property of the workbook object](/docs/csf/book) is an object
|
||||
whose keys are sheet names and whose values are sheet objects.
|
||||
|
||||
For example, the first worksheet can be pulled by indexing `SheetNames` and
|
||||
using the name to index `Sheets`:
|
||||
|
||||
```js
|
||||
var first_sheet = workbook.Sheets[workbook.SheetNames[0]];
|
||||
```
|
||||
|
||||
The actual worksheet object can be inspected directly[^6], but it is strongly
|
||||
recommended to use utility functions to present JS-friendly data structures.
|
||||
The [worksheet object](/docs/csf/sheet) can be inspected directly, but it is
|
||||
strongly recommended to use utility functions to extract relevant data.
|
||||
|
||||
### Preview HTML
|
||||
|
||||
The `sheet_to_html` utility function[^7] generates an HTML table from worksheet
|
||||
objects. The following live example shows the first 20 rows of data in a table:
|
||||
The [`sheet_to_html` function](/docs/api/utilities/html#html-table-output)
|
||||
generates an HTML table from worksheet objects.
|
||||
|
||||
The following live example shows the first 20 rows of data in a table:
|
||||
|
||||
<details>
|
||||
<summary><b>Live example</b> (click to show)</summary>
|
||||
@ -254,7 +259,8 @@ The key points from looking at the table are:
|
||||
|
||||
### Extract Raw Data
|
||||
|
||||
`XLSX.utils.sheet_to_json`[^8] generates arrays of data from worksheet objects.
|
||||
The [`sheet_to_json` function](/docs/api/utilities/array#array-output) generates
|
||||
arrays of data from worksheet objects.
|
||||
|
||||
For a complex layout like this, it is easiest to generate an "array of arrays"
|
||||
where each row is an array of cell values. The screenshot shows rows 5-8:
|
||||
@ -277,7 +283,7 @@ Row 7 includes the data for FY2007:
|
||||
```
|
||||
|
||||
`XLSX.utils.sheet_to_json` will generate an array of arrays if the option
|
||||
`header: 1` is specified[^9]:
|
||||
[`header: 1`](/docs/api/utilities/array#array-output) is specified:
|
||||
|
||||
```js
|
||||
const worksheet = workbook.Sheets[workbook.SheetNames[0]];
|
||||
@ -332,7 +338,9 @@ function SheetJSAoAHoles() {
|
||||
|
||||
</details>
|
||||
|
||||
The worksheet `!merges` property[^10] includes every merge range in the sheet.
|
||||
The [worksheet `!merges` property](/docs/csf/features/merges) includes every
|
||||
merge range in the sheet.
|
||||
|
||||
It is possible to loop through every merge block and fill cells, but in this
|
||||
case it is easier to post-process the raw data:
|
||||
|
||||
@ -489,20 +497,20 @@ function SheetJSAoAFilled() {
|
||||
### Select Data Rows
|
||||
|
||||
At this point, each data row will have the year in column `A` and dollar value
|
||||
in column `C`. The year (first value in the row) will be between 2007 and 2024.
|
||||
in column `C`. The year (first value in the row) will be between 2007 and 2029.
|
||||
The value (third value) will be positive. The following function tests a row
|
||||
against the requirements:
|
||||
|
||||
```js
|
||||
const is_valid_row = r =>
|
||||
r[0] >= 2007 && r[0] <= 2024 // year (column A) is between 2007 and 2024
|
||||
r[0] >= 2007 && r[0] <= 2029 // year (column A) is between 2007 and 2029
|
||||
&& r[2] > 0; // dollar value (column C) is positive
|
||||
```
|
||||
|
||||
`Array#filter`, using the previous test, can select the matching rows:
|
||||
|
||||
```js
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
|
||||
```
|
||||
|
||||
<details>
|
||||
@ -522,7 +530,7 @@ function SheetJSAoAFiltered() {
|
||||
var last_year = 0;
|
||||
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
|
||||
/* select data rows */
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
|
||||
/* display data */
|
||||
setRows(rows);
|
||||
})(); }, []);
|
||||
@ -539,7 +547,7 @@ Looking at the headers:
|
||||

|
||||
|
||||
The desired data is in column `I`. The column index can be calculated using
|
||||
`XLSX.utils.decode_col`[^11].
|
||||
the [`decode_col` utility function](/docs/csf/general#column-names).
|
||||
|
||||
<details>
|
||||
<summary><b>Column Index calculation</b> (click to show)</summary>
|
||||
@ -598,7 +606,7 @@ function SheetJSObjects() {
|
||||
var last_year = 0;
|
||||
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
|
||||
/* select data rows */
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
|
||||
/* generate row objects */
|
||||
const objects = rows.map(r => ({FY: r[0], FQ: r[1], total: r[8]}));
|
||||
/* display data */
|
||||
@ -617,7 +625,7 @@ At this point, `objects` is an array of objects.
|
||||
### ReactJS
|
||||
|
||||
The live demos in this example use ReactJS. In ReactJS, arrays of objects are
|
||||
best presented in simple HTML tables[^12]:
|
||||
best presented in [simple tables](/docs/demos/frontend/react#array-of-objects):
|
||||
|
||||
```jsx
|
||||
<table>
|
||||
@ -706,7 +714,7 @@ function StudentAidTotal() {
|
||||
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
|
||||
|
||||
/* select data rows */
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
|
||||
|
||||
/* generate row objects */
|
||||
const objects = rows.map(r => ({FY: r[0], FQ: r[1], total: r[8]}));
|
||||
@ -761,7 +769,7 @@ Save the following script to `SheetJSStandaloneDemo.html`:
|
||||
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
|
||||
\n\
|
||||
/* select data rows */
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
|
||||
\n\
|
||||
/* generate row objects */
|
||||
const objects = rows.map(r => ({FY: r[0], FQ: r[1], total: r[8]}));
|
||||
@ -781,7 +789,7 @@ After saving the file, run a local web server in the folder with the HTML file.
|
||||
For example, if NodeJS is installed:
|
||||
|
||||
```bash
|
||||
npx http-server .
|
||||
npx -y http-server .
|
||||
```
|
||||
|
||||
The server process will display a URL (typically `http://127.0.0.1:8080`). Open
|
||||
@ -827,7 +835,7 @@ const XLSX = require("xlsx");
|
||||
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
|
||||
|
||||
/* select data rows */
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
|
||||
|
||||
/* generate row objects */
|
||||
const objects = rows.map(r => ({FY: r[0], FQ: r[1], total: r[8]}));
|
||||
@ -900,7 +908,7 @@ Save the following script to `SheetJSNW.html`:
|
||||
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
|
||||
\n\
|
||||
/* select data rows */
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
|
||||
\n\
|
||||
/* generate row objects */
|
||||
const objects = rows.map(r => ({FY: r[0], FQ: r[1], total: r[8]}));
|
||||
@ -1001,7 +1009,7 @@ const App = () => {
|
||||
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
|
||||
|
||||
/* select data rows */
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
|
||||
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
|
||||
|
||||
/* generate row objects */
|
||||
const objects = rows.map(r => ({FY: r[0], FQ: r[1], total: r[8]}));
|
||||
@ -1053,7 +1061,7 @@ Press `a` to run on Android.
|
||||
|
||||
:::info Device Testing
|
||||
|
||||
The demo also runs on real Android devices! After enabling USB debugging[^13],
|
||||
The demo also runs on real Android devices! After enabling USB debugging[^2],
|
||||
the Android device can be connected to the computer with a USB cable.
|
||||
|
||||
:::
|
||||
@ -1088,15 +1096,4 @@ When the app is loaded, the data will be displayed in rows.
|
||||
</Tabs>
|
||||
|
||||
[^1]: The dataset URL has changed many times over the years. The current location for the CC0-licensed dataset can be found by [searching for "National Student Loan Data System" on `data.gov`](https://catalog.data.gov/dataset/?q=national+student+loan+data+system&publisher=Office+of+Federal+Student+Aid+%28FSA%29&organization=ed-gov). `PortfolioSummary.xls` is the file name within the dataset.
|
||||
[^2]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^3]: See ["SheetJS Data Model"](/docs/csf/)
|
||||
[^4]: See ["Workbook Object"](/docs/csf/book)
|
||||
[^5]: See ["Workbook Object"](/docs/csf/book)
|
||||
[^6]: See ["Sheet Objects"](/docs/csf/sheet)
|
||||
[^7]: See [`sheet_to_html` in "Utilities"](/docs/api/utilities/html#html-table-output)
|
||||
[^8]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^9]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^10]: See ["Merged Cells" in "SheetJS Data Model"](/docs/csf/features/merges)
|
||||
[^11]: See ["Column Names" in "Addresses and Ranges"](/docs/csf/general#column-names)
|
||||
[^12]: See ["Array of Objects" in "ReactJS"](/docs/demos/frontend/react#array-of-objects)
|
||||
[^13]: See ["Running on Device"](https://reactnative.dev/docs/running-on-device) in the React Native documentation for more details.
|
||||
[^2]: See ["Running on Device"](https://reactnative.dev/docs/running-on-device) in the React Native documentation for more details.
|
||||
@ -35,14 +35,21 @@ This demo was tested in the following configurations:
|
||||
|
||||
| Platform | Architecture | Date |
|
||||
|:------------------------------------------------------------------|:-------------|:-----------|
|
||||
| NVIDIA RTX 4090 (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2025-04-17 |
|
||||
| NVIDIA RTX 4090 (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-01-28 |
|
||||
| AMD RX 7900 XTX (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2025-01-12 |
|
||||
| AMD RX 7900 XTX (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-01-29 |
|
||||
| Intel Arc B580 (12 GB VRAM) + Ryzen Z1 Extreme (24 GB RAM) | `win11-x64` | 2025-01-24 |
|
||||
| Intel Arc B580 (12 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-02-08 |
|
||||
| Apple M4 Max 16-Core CPU + 40-Core GPU (48 GB unified memory) | `darwin-arm` | 2025-03-06 |
|
||||
| Apple M2 Max 12-Core CPU + 30-Core GPU (32 GB unified memory) | `darwin-arm` | 2025-03-25 |
|
||||
| NVIDIA RTX PRO 6000 (96 GB VRAM) + Ryzen Z2 Go (32 GB RAM) | `win11-x64` | 2025-11-15 |
|
||||
| NVIDIA RTX PRO 6000 (96 GB VRAM) + Ryzen Z2 Go (32 GB RAM) | `linux-x64` | 2025-11-15 |
|
||||
| NVIDIA RTX 5090 (32 GB VRAM) + Ryzen Z2 (32 GB RAM) | `win11-x64` | 2026-01-25 |
|
||||
| NVIDIA RTX 5090 (32 GB VRAM) + Ryzen Z2 Go (32 GB RAM) | `linux-x64` | 2025-11-15 |
|
||||
| AMD AI PRO R9700 (32 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2026-01-17 |
|
||||
| AMD AI PRO R9700 (32 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2026-01-17 |
|
||||
| AMD RX 9070 XT (16 GB VRAM) + Ryzen Z2 Go (32 GB RAM) | `win11-x64` | 2026-01-17 |
|
||||
| AMD RX 9070 XT (16 GB VRAM) + Ryzen Z2 Go (32 GB RAM) | `linux-x64` | 2026-01-17 |
|
||||
| AMD RX 7900 XTX (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2025-11-15 |
|
||||
| AMD RX 7900 XTX (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-11-15 |
|
||||
| Intel Arc B580 (12 GB VRAM) + Ryzen Z1 Extreme (24 GB RAM) | `win11-x64` | 2025-11-15 |
|
||||
| Intel Arc B580 (12 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-11-15 |
|
||||
| AMD RYZEN AI MAX+ 395 + Radeon 8060S (128 GB unified memory) | `linux-x64` | 2025-11-15 |
|
||||
| AMD RYZEN AI MAX+ 395 + Radeon 8060S (128 GB unified memory) | `win11-x64` | 2025-11-15 |
|
||||
| Apple M4 Max 16-Core CPU + 40-Core GPU (48 GB unified memory) | `darwin-arm` | 2025-11-15 |
|
||||
|
||||
SheetJS users have verified this demo in other configurations:
|
||||
|
||||
@ -52,7 +59,10 @@ SheetJS users have verified this demo in other configurations:
|
||||
| Platform | Architecture | Demo |
|
||||
|:---------------------------------------------------------------------|:-------------|:------------|
|
||||
| NVIDIA L40 (48 GB VRAM) + i9-13900K (32 GB RAM) | `linux-x64` | LangChainJS |
|
||||
| NVIDIA RTX 4090 (24 GB VRAM) + Ryzen Z2 Go (32 GB RAM) | `win11-x64` | LangChainJS |
|
||||
| NVIDIA RTX 4090 (24 GB VRAM) + Ryzen Z2 Go (32 GB RAM) | `linux-x64` | LangChainJS |
|
||||
| NVIDIA RTX 4080 SUPER (16 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | LangChainJS |
|
||||
| NVIDIA RTX 4080 SUPER (16 GB VRAM) + Ryzen Z2 Go (32 GB RAM) | `linux-x64` | LangChainJS |
|
||||
| NVIDIA RTX 4070 Ti SUPER (16 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | LangChainJS |
|
||||
| NVIDIA RTX 4070 Ti (12 GB VRAM) + Ryzen 7 5800x (64 GB RAM) | `win11-x64` | LangChainJS |
|
||||
| NVIDIA RTX 4060 (8 GB VRAM) + Ryzen 7 5700g (32 GB RAM) | `win11-x64` | LangChainJS |
|
||||
@ -67,6 +77,8 @@ SheetJS users have verified this demo in other configurations:
|
||||
| NVIDIA GTX 1070 (8 GB VRAM) + Ryzen 7 7700x (32 GB RAM) | `win11-x64` | LangChainJS |
|
||||
| AMD RX 6800 XT (16 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | LangChainJS |
|
||||
| Apple M4 10-Core CPU + 10-Core GPU (24 GB unified memory) | `darwin-arm` | LangChainJS |
|
||||
| Apple M3 Ultra 28-Core CPU + 60-Core GPU (96 GB unified memory) | `darwin-arm` | LangChainJS |
|
||||
| Apple M2 Max 12-Core CPU + 30-Core GPU (32 GB unified memory) | `darwin-arm` | LangChainJS |
|
||||
|
||||
</details>
|
||||
|
||||
@ -74,6 +86,7 @@ Special thanks to the following users for testing with multiple configurations:
|
||||
|
||||
- [Asadbek Karimov](https://asadk.dev/)
|
||||
- [Rasmus Tengstedt](https://tengstedt.dev/)
|
||||
- [Joban Dhillon](https://dhillon.dev/)
|
||||
|
||||
:::
|
||||
|
||||
@ -377,7 +390,7 @@ includes one header row and a number of data rows.
|
||||
|
||||
```js title="loadofsheet.mjs"
|
||||
import { Document } from "@langchain/core/documents";
|
||||
import { BufferLoader } from "langchain/document_loaders/fs/buffer";
|
||||
import { BufferLoader } from "@langchain/classic/document_loaders/fs/buffer";
|
||||
import { read, utils } from "xlsx";
|
||||
|
||||
/**
|
||||
@ -516,7 +529,7 @@ export class CSVLoader extends TextLoader {
|
||||
The SheetJS `read` method supports NodeJS Buffer objects directly[^6]:
|
||||
|
||||
```js title="Parsing a workbook in a BufferLoader"
|
||||
import { BufferLoader } from "langchain/document_loaders/fs/buffer";
|
||||
import { BufferLoader } from "@langchain/classic/document_loaders/fs/buffer";
|
||||
import { read, utils } from "xlsx";
|
||||
|
||||
export default class LoadOfSheet extends BufferLoader {
|
||||
@ -722,7 +735,7 @@ a [sample cars dataset](pathname:///cd.xls) and displays the results.
|
||||
|
||||
:::caution pass
|
||||
|
||||
This demo was tested using the ChatQA-1.5 model[^9] in Ollama.
|
||||
This demo was tested using the Phi-4[^9] in Ollama.
|
||||
|
||||
The tested model used up to 10GB VRAM. It is strongly recommended to run the
|
||||
demo on a GPU with at least 12GB VRAM or a newer Apple Silicon Mac with at least
|
||||
@ -748,7 +761,7 @@ Intel ARC GPUs require the Intel Extension for PyTorch (IPEX) and a special
|
||||
version of Ollama that ships with the associated LLM Library (IPEX-LLM).
|
||||
|
||||
<details>
|
||||
<summary><b>ARC Instructions</b> (click to show)</summary>
|
||||
<summary><b>ARC Instructions on Windows</b> (click to show)</summary>
|
||||
|
||||
These instructions are based on the official Intel recommendations.
|
||||
|
||||
@ -805,6 +818,82 @@ This window should be kept open throughout the demo.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>ARC Instructions on Linux</b> (click to show)</summary>
|
||||
|
||||
These instructions are based on the official Intel recommendations.
|
||||
|
||||
A) Install the dependencies from the [Battlemage quickstart](https://github.com/intel/ipex-llm/blob/main/docs/mddocs/Quickstart/bmg_quickstart.md#11-install-prerequisites)
|
||||
|
||||
B) Download and extract the [Ollama Portable Zip](https://github.com/intel/ipex-llm/blob/main/docs/mddocs/Quickstart/ollama_portable_zip_quickstart.md#linux-quickstart).
|
||||
|
||||
C) When this demo was last tested, the computer had an AMD processor. To force
|
||||
Ollama to use the GPU, uncomment the "single GPU" line in `start-ollama.sh`:
|
||||
|
||||
```bash title="start-ollama.sh (uncomment line)"
|
||||
export ONEAPI_DEVICE_SELECTOR=level_zero:0
|
||||
```
|
||||
|
||||
D) Run the `start-ollama.sh` script from the extracted folder.
|
||||
|
||||
</details>
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
|
||||
AMD GPUs may require special ROCm / HIP libraries.
|
||||
|
||||
<details>
|
||||
<summary><b>AMD Instructions on Windows</b> (click to show)</summary>
|
||||
|
||||
[`ollama-for-amd`](https://github.com/likelovewant/ollama-for-amd) is a
|
||||
community fork that provides support for many AMD GPUs.
|
||||
|
||||
[Installers](https://github.com/ByronLeeeee/Ollama-For-AMD-Installer/releases)
|
||||
are also provided by the community.
|
||||
|
||||
There are separate drivers for each GPU family. The following GPUs were tested:
|
||||
|
||||
| Name | GPU | Identifier |
|
||||
|:-----------------|:--------|:-----------|
|
||||
| AMD AI PRO R9700 | Navi 48 | `gfx1200` |
|
||||
| AMD RX 9070 XT | Navi 48 | `gfx1201` |
|
||||
| AND RX 7900 XTX | Navi 31 | `gfx1100` |
|
||||
|
||||
When this demo was last tested, the installer claimed `gfx1200` corresponded to
|
||||
Navi 48. `gfx1200` should be used for the PRO R9700, while `gfx1201` should be
|
||||
used for the 9070 XT.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>AMD Instructions on Linux</b> (click to show)</summary>
|
||||
|
||||
The official Ollama release is compatible with AMD cards. However, in some test
|
||||
runs, Ollama will try to use the CPU. Some environment variables were required:
|
||||
|
||||
```bash
|
||||
export OLLAMA_USE_ROCM=1
|
||||
export OLLAMA_GPU_LAYERS=999
|
||||
export OLLAMA_VULKAN=1
|
||||
```
|
||||
|
||||
In addition, `HSA_OVERRIDE_GFX_VERSION` must be set to a specific version based
|
||||
on the card, which may not match the official version:
|
||||
|
||||
| Name | Value | Command |
|
||||
|:-----------------|:---------|:-------------------------------------------|
|
||||
| AMD AI PRO R9700 | `12.0.0` | `export HSA_OVERRIDE_GFX_VERSION="12.0.0"` |
|
||||
| AMD RX 9070 XT | `12.0.0` | `export HSA_OVERRIDE_GFX_VERSION="12.0.0"` |
|
||||
| AND RX 7900 XTX | `11.0.0` | `export HSA_OVERRIDE_GFX_VERSION="11.0.0"` |
|
||||
|
||||
These environment variables may not be used by the Ollama service, so it is
|
||||
strongly recommended to stop the default service and run `ollama serve` in a
|
||||
separate terminal window.
|
||||
|
||||
</details>
|
||||
|
||||
:::
|
||||
|
||||
After installing dependencies, start a new terminal session.
|
||||
@ -853,7 +942,7 @@ npm i --save https://sheet.lol/balls/xlsx-${current}.tgz`}
|
||||
4) Install dependencies:
|
||||
|
||||
```bash
|
||||
npm i --save @langchain/core@0.3.44 langchain@0.3.21 @langchain/ollama@0.2.0 peggy@3.0.2
|
||||
npm i --save @langchain/core@1.1.15 langchain@1.2.10 @langchain/classic@1.0.9 @langchain/ollama@1.2.0 peggy@5.0.6
|
||||
```
|
||||
|
||||
:::note pass
|
||||
@ -862,7 +951,7 @@ In some test runs, there were error messages relating to dependency and peer
|
||||
dependency versions. The `--force` flag will suppress version mismatch errors:
|
||||
|
||||
```bash
|
||||
npm i --save @langchain/core@0.3.44 langchain@0.3.21 @langchain/ollama@0.2.0 peggy@3.0.2 --force
|
||||
npm i --save @langchain/core@1.1.15 langchain@1.2.10 @langchain/classic@1.0.9 @langchain/ollama@1.2.0 peggy@5.0.6 --force
|
||||
```
|
||||
|
||||
:::
|
||||
@ -889,14 +978,14 @@ curl.exe -LO https://docs.sheetjs.com/cd.xls
|
||||
|
||||
:::
|
||||
|
||||
6) Install the `llama3-chatqa:8b-v1.5-q8_0` model using Ollama:
|
||||
6) Install the `phi4:14b` model using Ollama:
|
||||
|
||||
```bash
|
||||
ollama pull llama3-chatqa:8b-v1.5-q8_0
|
||||
ollama pull phi4:14b
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary><b>Additional steps for Intel GPUs</b> (click to show)</summary>
|
||||
<summary><b>Additional steps for Intel GPUs and AMD Strix Halo</b> (click to show)</summary>
|
||||
|
||||
A different embedding model must be used on Intel GPUs:
|
||||
|
||||
@ -974,5 +1063,5 @@ charts, tables, and other features.
|
||||
[^6]: See ["Supported Output Formats" type in "Writing Files"](/docs/api/write-options#supported-output-formats)
|
||||
[^7]: See ["Workbook Object"](/docs/csf/book)
|
||||
[^8]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^9]: See [the official ChatQA website](https://chatqa-project.github.io/) for the ChatQA paper and other model details.
|
||||
[^9]: See [the Phi-4 Technical Report](https://arxiv.org/abs/2412.08905) for more details.
|
||||
[^10]: Select ["Windows" `x86_64`](https://conda-forge.org/download/) in the Installation page.
|
||||
|
||||
@ -6,7 +6,7 @@ pagination_next: demos/frontend/index
|
||||
---
|
||||
|
||||
<head>
|
||||
<script src="https://cdn.jsdelivr.net/npm/danfojs@1.1.2/lib/bundle.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/danfojs@1.2.0/lib/bundle.min.js"></script>
|
||||
</head>
|
||||
|
||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
||||
@ -23,8 +23,8 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Platform | Version | Date |
|
||||
|:-------------|:--------|:-----------|
|
||||
| Chromium 131 | `1.1.2` | 2025-01-01 |
|
||||
| Safari 18.2 | `1.1.2` | 2025-01-01 |
|
||||
| Chromium 137 | `1.2.0` | 2025-06-16 |
|
||||
| Safari 18.5 | `1.2.0` | 2025-06-16 |
|
||||
| Konqueror 22 | `1.1.2` | 2025-04-23 |
|
||||
|
||||
:::
|
||||
@ -34,7 +34,7 @@ This demo was tested in the following deployments:
|
||||
The live demos on this page include the DanfoJS browser bundle:
|
||||
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/danfojs@1.1.2/lib/bundle.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/danfojs@1.2.0/lib/bundle.min.js"></script>
|
||||
```
|
||||
|
||||
There are known issues with the documentation generator. If a demo explicitly
|
||||
|
||||
@ -44,14 +44,15 @@ The NodeJS demo was tested in the following environments:
|
||||
|
||||
| NodeJS | TF.js | Date |
|
||||
|:------------|:----------|:-----------|
|
||||
| `22.14.0` | `4.22.0` | 2025-04-21 |
|
||||
| `20.18.0` | `4.22.0` | 2025-04-21 |
|
||||
| `24.13.0` | `4.22.0` | 2026-01-28 |
|
||||
| `22.22.0` | `4.22.0` | 2026-01-28 |
|
||||
| `20.20.0` | `4.22.0` | 2026-01-28 |
|
||||
|
||||
The Kaioken demo was tested in the following environments:
|
||||
|
||||
| Kaioken | TF.js | Date |
|
||||
|:------------|:----------|:-----------|
|
||||
| `0.37.0` | `4.22.0` | 2025-04-21 |
|
||||
| `0.44.3` | `4.22.0` | 2025-11-15 |
|
||||
|
||||
:::
|
||||
|
||||
@ -71,7 +72,7 @@ can be loaded after the TF.js standalone script.
|
||||
<!-- latest version of TF.js -->
|
||||
<script src="https://unpkg.com/@tensorflow/tfjs@latest/dist/tf.min.js"></script>
|
||||
<!-- use version ${current} -->
|
||||
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>`}
|
||||
<script type="text/javascript" src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>`}
|
||||
</CodeBlock>
|
||||
|
||||
#### Frameworks and Bundlers
|
||||
@ -417,7 +418,7 @@ The SheetJS team strongly recommends using Kaioken in projects using TF.js.
|
||||
1) Create a new site.
|
||||
|
||||
```bash
|
||||
npm create vite sheetjs-tfjs-kaioken -- --template vanilla-ts
|
||||
npm create vite sheetjs-tfjs-kaioken -- --template vanilla-ts --no-rolldown --no-interactive
|
||||
cd sheetjs-tfjs-kaioken
|
||||
npm add --save kaioken
|
||||
npm add --save vite-plugin-kaioken -D
|
||||
@ -443,7 +444,14 @@ export default defineConfig({
|
||||
"jsx": "preserve",
|
||||
```
|
||||
|
||||
4) Replace `src/main.ts` with the following codeblock:
|
||||
4) Edit `tsconfig.json` and remove any lines referencing `verbatimModuleSyntax`.
|
||||
When the demo was last tested, the file had the following line:
|
||||
|
||||
```js title="tsconfig.json (remove this line if present)"
|
||||
"verbatimModuleSyntax": true,
|
||||
```
|
||||
|
||||
5) Replace `src/main.ts` with the following codeblock:
|
||||
|
||||
```js title="src/main.ts"
|
||||
import { mount } from "kaioken";
|
||||
@ -453,19 +461,19 @@ const root = document.getElementById("app");
|
||||
mount(App, root!);
|
||||
```
|
||||
|
||||
5) Download [`SheetJSTF.tsx`](pathname:///tfjs/SheetJSTF.tsx) to the `src` directory:
|
||||
6) Download [`SheetJSTF.tsx`](pathname:///tfjs/SheetJSTF.tsx) to the `src` directory:
|
||||
|
||||
```bash
|
||||
curl -L -o src/SheetJSTF.tsx https://docs.sheetjs.com/tfjs/SheetJSTF.tsx
|
||||
```
|
||||
|
||||
6) Install SheetJS and TF.js dependencies:
|
||||
7) Install SheetJS and TF.js dependencies:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @tensorflow/tfjs`}
|
||||
</CodeBlock>
|
||||
|
||||
7) Start the development server:
|
||||
8) Start the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
|
||||
@ -40,12 +40,12 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | JS Engine | Pandas | Python | Date |
|
||||
|:-------------|:----------------|:-------|:-------|:-----------|
|
||||
| `darwin-x64` | Duktape `2.7.0` | 2.2.3 | 3.13.1 | 2025-03-31 |
|
||||
| `darwin-arm` | Duktape `2.7.0` | 2.2.3 | 3.13.2 | 2025-03-30 |
|
||||
| `win11-x64` | Duktape `2.7.0` | 2.2.3 | 3.11.8 | 2024-12-21 |
|
||||
| `win11-arm` | Duktape `2.7.0` | 2.2.3 | 3.13.2 | 2025-02-23 |
|
||||
| `linux-x64` | Duktape `2.7.0` | 1.5.3 | 3.11.7 | 2025-01-01 |
|
||||
| `linux-arm` | Duktape `2.7.0` | 1.5.3 | 3.11.2 | 2025-02-16 |
|
||||
| `darwin-x64` | Duktape `2.7.0` | 3.0.1 | 3.13.7 | 2026-03-07 |
|
||||
| `darwin-arm` | Duktape `2.7.0` | 2.3.3 | 3.9.6 | 2026-01-25 |
|
||||
| `win11-x64` | Duktape `2.7.0` | 3.0.1 | 3.11.9 | 2026-03-08 |
|
||||
| `win11-arm` | Duktape `2.7.0` | 2.2.3 | 3.11.5 | 2026-03-07 |
|
||||
| `linux-x64` | Duktape `2.7.0` | 3.0.1 | 3.13.9 | 2026-03-07 |
|
||||
| `linux-arm` | Duktape `2.7.0` | 2.2.3 | 3.13.5 | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
@ -203,7 +203,7 @@ DataFrame. The DataFrame will be exported to the binary XLSB spreadsheet format.
|
||||
:::note pass
|
||||
|
||||
The Windows build requires Visual Studio with "Desktop development with C++".
|
||||
Commands must be run in a "Native Tools Command Prompt" session.
|
||||
**Commands must be run in a "Native Tools Command Prompt" session.**
|
||||
|
||||
:::
|
||||
|
||||
@ -215,6 +215,14 @@ python3 -m pip install pandas
|
||||
|
||||
:::info pass
|
||||
|
||||
On Windows, Python may be available as `python.exe`:
|
||||
|
||||
```bash
|
||||
python.exe -m pip install pandas
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
On macOS and Linux, the install command may require root access:
|
||||
|
||||
```bash
|
||||
@ -305,15 +313,13 @@ cd ..
|
||||
</TabItem>
|
||||
<TabItem value="win11-x64" label="Windows">
|
||||
|
||||
- Download and extract the source tarball. Commands must be run in WSL `bash`:
|
||||
- Download and extract the source tarball:
|
||||
|
||||
```bash
|
||||
curl -LO https://duktape.org/duktape-2.7.0.tar.xz
|
||||
tar -xJf duktape-2.7.0.tar.xz
|
||||
```
|
||||
|
||||
(Run `bash`, then run the aforementioned commands, then run `exit` to exit WSL)
|
||||
|
||||
- Enter the source folder:
|
||||
|
||||
```bash
|
||||
@ -472,6 +478,17 @@ def eval_file(ctx, path):
|
||||
python3 SheetJSPandas.py pres.numbers
|
||||
```
|
||||
|
||||
:::info pass
|
||||
|
||||
On Windows, Python may be available as `python.exe`:
|
||||
|
||||
```bash
|
||||
python.exe SheetJSPandas.py pres.numbers
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
|
||||
If successful, the script will display DataFrame metadata:
|
||||
|
||||
```
|
||||
@ -525,14 +542,14 @@ The Pandas example requires a few slight changes to work with Polars:
|
||||
|
||||
This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | JS Engine | Polars | Python | Date |
|
||||
|:-------------|:----------------|:--------|:-------|:-----------|
|
||||
| `darwin-x64` | Duktape `2.7.0` | 1.26.0 | 3.13.1 | 2025-03-31 |
|
||||
| `darwin-arm` | Duktape `2.7.0` | 1.26.0 | 3.13.2 | 2025-03-30 |
|
||||
| `win11-x64` | Duktape `2.7.0` | 1.17.1 | 3.11.8 | 2024-12-21 |
|
||||
| `win11-arm` | Duktape `2.7.0` | 1.23.0 | 3.13.2 | 2025-02-23 |
|
||||
| `linux-x64` | Duktape `2.7.0` | 1.18.0 | 3.11.7 | 2025-01-01 |
|
||||
| `linux-arm` | Duktape `2.7.0` | 1.22.0 | 3.11.2 | 2025-02-16 |
|
||||
| Architecture | JS Engine | Polars | Python | Date |
|
||||
|:-------------|:----------------|:-------|:-------|:-----------|
|
||||
| `darwin-x64` | Duktape `2.7.0` | 1.38.1 | 3.13.7 | 2026-03-07 |
|
||||
| `darwin-arm` | Duktape `2.7.0` | 1.36.1 | 3.9.6 | 2026-01-25 |
|
||||
| `win11-x64` | Duktape `2.7.0` | 1.38.1 | 3.11.9 | 2026-03-08 |
|
||||
| `win11-arm` | Duktape `2.7.0` | 1.23.0 | 3.11.5 | 2026-03-07 |
|
||||
| `linux-x64` | Duktape `2.7.0` | 1.38.1 | 3.13.9 | 2026-03-07 |
|
||||
| `linux-arm` | Duktape `2.7.0` | 1.38.1 | 3.13.5 | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
@ -599,10 +616,18 @@ python3 -m pip install polars
|
||||
|
||||
:::info pass
|
||||
|
||||
On Windows, Python may be available as `python.exe`:
|
||||
|
||||
```bash
|
||||
python.exe -m pip install polars
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
On macOS and Linux, the install command may require root access:
|
||||
|
||||
```bash
|
||||
sudo python3 -m pip install pandas
|
||||
sudo python3 -m pip install polars
|
||||
```
|
||||
|
||||
:::
|
||||
@ -631,7 +656,7 @@ It is recommended to use a virtual environment.
|
||||
- Debian and Ubuntu distributions:
|
||||
|
||||
```bash
|
||||
sudo apt-get install python3.11-venv
|
||||
sudo apt-get install python3-venv
|
||||
```
|
||||
|
||||
- `venv` is included in the `python` package in Arch Linux-based platforms.
|
||||
@ -662,6 +687,16 @@ cp ../libduktape.* ../SheetJSPandas.py ../sheetjs.py ../*.js ../*.numbers .
|
||||
python3 SheetJSPandas.py pres.numbers
|
||||
```
|
||||
|
||||
:::info pass
|
||||
|
||||
On Windows, Python may be available as `python.exe`:
|
||||
|
||||
```bash
|
||||
python.exe SheetJSPandas.py pres.numbers
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::note pass
|
||||
|
||||
If the virtual environment was configured in the previous step, run:
|
||||
@ -692,7 +727,7 @@ shape: (5, 2)
|
||||
It will also export the DataFrame to `SheetJSPolars.xlsb`. The file can be
|
||||
inspected with a spreadsheet editor that supports XLSB files.
|
||||
|
||||
[^1]: See ["Other Languages"](/docs/demos/engines/) for more examples.
|
||||
[^1]: See ["JavaScript Engines"](/docs/demos/engines/) for more examples.
|
||||
[^2]: See [`ctypes`](https://docs.python.org/3/library/ctypes.html) in the Python documentation.
|
||||
[^3]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^4]: See ["Workbook Object"](/docs/csf/book)
|
||||
|
||||
@ -360,9 +360,9 @@ export default function SheetJSKaiokenAoO() {
|
||||
{ /* error message */
|
||||
!pres && !loading && ( <tr><td colSpan="2">{error.message}</td></tr> )
|
||||
}
|
||||
</tbody><tfoot><td colSpan={2}>
|
||||
</tbody><tfoot><tr><td colSpan={2}>
|
||||
<button onclick={exportFile}>Export XLSX</button>
|
||||
</td></tfoot></table>);
|
||||
</td></tr></tfoot></table>);
|
||||
}
|
||||
```
|
||||
|
||||
@ -429,9 +429,9 @@ export default function SheetJSKaiokenAoO() {
|
||||
<td>{pres.Index}</td>
|
||||
</tr>))
|
||||
}
|
||||
</tbody><tfoot><td colSpan={2}>
|
||||
</tbody><tfoot><tr><td colSpan={2}>
|
||||
<button onclick={exportFile}>Export XLSX</button>
|
||||
</td></tfoot></table>);
|
||||
</td></tr></tfoot></table>);
|
||||
}
|
||||
```
|
||||
|
||||
@ -457,7 +457,7 @@ This demo was tested in the following environments:
|
||||
1) Create a new site.
|
||||
|
||||
```bash
|
||||
npm create vite@latest sheetjs-kaioken -- --template vanilla-ts
|
||||
npm create vite@latest sheetjs-kaioken -- --template vanilla-ts --no-rolldown --no-interactive
|
||||
cd sheetjs-kaioken
|
||||
npm add --save kaioken
|
||||
npm add --save vite-plugin-kaioken -D
|
||||
@ -518,7 +518,7 @@ The generated site will be placed in the `dist` folder.
|
||||
9) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
npx -y http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
@ -604,7 +604,7 @@ This demo was tested in the following environments:
|
||||
1) Create a new site.
|
||||
|
||||
```bash
|
||||
npm create vite@latest sheetjs-kaioken -- --template vanilla-ts
|
||||
npm create vite@latest sheetjs-kaioken -- --template vanilla-ts --no-rolldown --no-interactive
|
||||
cd sheetjs-kaioken
|
||||
npm add --save kaioken
|
||||
npm add --save vite-plugin-kaioken -D
|
||||
@ -665,7 +665,7 @@ The generated site will be placed in the `dist` folder.
|
||||
9) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
npx -y http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
|
||||
@ -135,7 +135,7 @@ The SheetJS [`read`](/docs/api/parse-options) and [`sheet_to_json`](/docs/api/ut
|
||||
functions simplify state updates. They are best used in the function bodies of
|
||||
`useEffect`[^2] and `useCallback`[^3] hooks.
|
||||
|
||||
A `useEffect` hook can download and update state when a person loads the site:
|
||||
A `useEffect` hook can download and update state when the site is loaded:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
@ -150,12 +150,13 @@ flowchart LR
|
||||
wb --> |wb.Sheets\nselect sheet| ws
|
||||
ws --> |sheet_to_json\n\n| aoo
|
||||
aoo --> |setPres\nfrom `setState`| state
|
||||
linkStyle 1,2,3 color:blue,stroke:blue;
|
||||
```
|
||||
|
||||
<Tabs groupId="lang">
|
||||
<TabItem name="JS" value="JavaScript">
|
||||
|
||||
```js
|
||||
```js title="In a useEffect hook, update state with data from a remote workbook"
|
||||
import { useEffect } from 'react';
|
||||
import { read, utils } from 'xlsx';
|
||||
|
||||
@ -182,7 +183,7 @@ useEffect(() => { (async() => {
|
||||
</TabItem>
|
||||
<TabItem name="TS" value="TypeScript" default>
|
||||
|
||||
```ts
|
||||
```ts title="In a useEffect hook, update state with data from a remote workbook"
|
||||
import { useEffect } from 'react';
|
||||
import { read, utils } from 'xlsx';
|
||||
|
||||
@ -252,9 +253,10 @@ flowchart LR
|
||||
state --> |json_to_sheet\n\n| ws
|
||||
ws --> |book_new\nbook_append_sheet| wb
|
||||
wb --> |writeFile\n\n| file
|
||||
linkStyle 0,1,2 color:blue,stroke:blue;
|
||||
```
|
||||
|
||||
```ts
|
||||
```ts title="Export data from state to a new XLSX workbook"
|
||||
import { useCallback } from 'react';
|
||||
import { utils, writeFile } from 'xlsx';
|
||||
|
||||
@ -332,14 +334,14 @@ This demo was tested in the following environments:
|
||||
|
||||
| ReactJS | ViteJS | Date |
|
||||
|:---------|:--------|:-----------|
|
||||
| `18.3.1` | `6.0.1` | 2024-12-12 |
|
||||
| `19.1.0` | `6.3.5` | 2025-05-11 |
|
||||
|
||||
:::
|
||||
|
||||
1) Create a new site:
|
||||
|
||||
```bash
|
||||
npm create vite@latest sheetjs-react -- --template react
|
||||
npm create vite@latest sheetjs-react -- --template react --no-rolldown --no-interactive
|
||||
```
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
@ -369,7 +371,7 @@ The generated site will be placed in the `dist` folder.
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
npx -y http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
@ -384,23 +386,14 @@ This demo was tested in the following environments:
|
||||
|
||||
| ReactJS | CRA | Date |
|
||||
|:---------|:--------|:-----------|
|
||||
| `18.2.0` | `5.0.1` | 2024-12-12 |
|
||||
| `19.1.0` | `5.1.0` | 2025-05-11 |
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
|
||||
CRA has known compatibility issues with React 19[^5]. CRA no longer receives
|
||||
updates and the ReactJS docs no longer recommend using CRA. For new projects, it
|
||||
is strongly recommended to use ViteJS with the `react` or `react-ts` templates.
|
||||
|
||||
:::
|
||||
|
||||
|
||||
1) Create a new site:
|
||||
|
||||
```bash
|
||||
npx -y create-react-app@5.0.1 --scripts-version=5.0.1 sheetjs-react
|
||||
npx -y create-react-app@5.1.0 sheetjs-react
|
||||
```
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
@ -408,7 +401,7 @@ npx -y create-react-app@5.0.1 --scripts-version=5.0.1 sheetjs-react
|
||||
<CodeBlock language="bash">{`\
|
||||
cd sheetjs-react
|
||||
npm i
|
||||
npm i react@18.2.0 react-dom@18.2.0 web-vitals --save --save-exact
|
||||
npm i react@19.1.0 react-dom@19.1.0 web-vitals --save --save-exact
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npm start`}
|
||||
</CodeBlock>
|
||||
@ -431,7 +424,7 @@ The generated site will be placed in the `build` folder.
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server build
|
||||
npx -y http-server build
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
@ -446,7 +439,7 @@ This demo was tested in the following environments:
|
||||
|
||||
| ReactJS | NextJS | Date |
|
||||
|:---------|:---------|:-----------|
|
||||
| `19.0.0` | `15.1.0` | 2024-12-13 |
|
||||
| `19.1.0` | `15.3.2` | 2025-05-11 |
|
||||
|
||||
:::
|
||||
|
||||
@ -567,7 +560,7 @@ This demo was tested in the following environments:
|
||||
|
||||
| Preact | ViteJS | Date |
|
||||
|:----------|:----------|:-----------|
|
||||
| `10.22.1` | `5.3.3` | 2024-12-17 |
|
||||
| `10.26.6` | `5.4.19` | 2025-05-11 |
|
||||
|
||||
:::
|
||||
|
||||
@ -578,7 +571,12 @@ npm init preact sheetjs-preact
|
||||
```
|
||||
|
||||
This will initiate the project creation process. **Follow the on-screen prompts and
|
||||
press Enter to accept the default options.**
|
||||
press Enter to accept the default options:**
|
||||
|
||||
- `Project language:` JavaScript
|
||||
- `Use router?` No
|
||||
- `Prerender app (SSG)?` No
|
||||
- `Use ESLint?` No
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
|
||||
@ -620,7 +618,7 @@ The generated site will be placed in the `dist` folder.
|
||||
7) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
npx -y http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
@ -641,10 +639,149 @@ The main disadvantage of the Array of Objects approach is the specific nature
|
||||
of the columns. For more general use, passing around an Array of Arrays works.
|
||||
However, this does not handle merge cells[^6] well!
|
||||
|
||||
HTML Tables support elements with `rowspan` and `colspan` attributes.
|
||||
|
||||
#### State
|
||||
|
||||
The state will be the serialized HTML string:
|
||||
|
||||
<Tabs groupId="lang">
|
||||
<TabItem name="JS" value="JavaScript">
|
||||
|
||||
```ts
|
||||
import { useState } from 'react';
|
||||
|
||||
/* the component state is a string */
|
||||
const [__html, setHtml] = useState("");
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem name="TS" value="TypeScript" default>
|
||||
|
||||
```ts
|
||||
import { useState } from 'react';
|
||||
|
||||
/* the component state is a string */
|
||||
const [__html, setHtml] = useState<string>("");
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::info Use of the variable name `__html`
|
||||
|
||||
Examples use the name `__html` due to the design of `dangerouslySetInnerHTML`.
|
||||
|
||||
`dangerouslySetInnerHTML` expects objects of the form `{ __html: "html code" }`.
|
||||
|
||||
For example, the following snippet assumes `html` is the variable name:
|
||||
|
||||
```jsx
|
||||
<div ref={tbl} dangerouslySetInnerHTML={{ __html: html }} />
|
||||
```
|
||||
|
||||
By using the name `__html`, the ES6 shorthand syntax simplifies the code:
|
||||
|
||||
```jsx
|
||||
<div ref={tbl} dangerouslySetInnerHTML={{ __html }} />
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#### Updating State
|
||||
|
||||
The [`sheet_to_html`](/docs/api/utilities/html#html-table-output) function
|
||||
generates HTML that is aware of merges and other worksheet features. ReactJS
|
||||
`dangerouslySetInnerHTML`[^7] prop allows code to set the `innerHTML` attribute,
|
||||
effectively inserting the code into the page.
|
||||
generates HTML that is aware of merges and other worksheet features.
|
||||
|
||||
A `useEffect` hook can download and update state when the site is loaded:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
url[(Remote\nFile)]
|
||||
ab[(Data\nArrayBuffer)]
|
||||
wb(SheetJS\nWorkbook)
|
||||
ws(SheetJS\nWorksheet)
|
||||
html(HTML\nTABLE)
|
||||
state((component\nstate))
|
||||
url --> |fetch\n\n| ab
|
||||
ab --> |read\n\n| wb
|
||||
wb --> |wb.Sheets\nselect sheet| ws
|
||||
ws --> |sheet_to_html\n\n| html
|
||||
html --> |setHtml\nfrom `setState`| state
|
||||
linkStyle 1,2,3 color:blue,stroke:blue;
|
||||
```
|
||||
|
||||
```js title="In a useEffect hook, update state with HTML generated from a remote workbook"
|
||||
import { useEffect } from 'react';
|
||||
import { read, utils } from 'xlsx';
|
||||
|
||||
/* Fetch and update the state once */
|
||||
useEffect(() => { (async() => {
|
||||
/* Download from https://docs.sheetjs.com/pres.numbers */
|
||||
const f = await fetch("https://docs.sheetjs.com/pres.numbers");
|
||||
const ab = await f.arrayBuffer();
|
||||
|
||||
// highlight-start
|
||||
/* parse */
|
||||
const wb = read(ab);
|
||||
|
||||
/* generate HTML TABLE from first worksheet */
|
||||
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
|
||||
const data = utils.sheet_to_html(ws); // generate objects
|
||||
|
||||
/* update state */
|
||||
setHtml(data); // update state
|
||||
// highlight-end
|
||||
})(); }, []);
|
||||
```
|
||||
|
||||
#### Rendering Data
|
||||
|
||||
ReactJS `dangerouslySetInnerHTML`[^7] prop allows code to set the `innerHTML`
|
||||
attribute, effectively inserting the code into the page.
|
||||
|
||||
It is strongly recommended to set the `innerHTML` of a parent `DIV` container.
|
||||
By attaching a `ref`, callbacks will be able to access the live `TABLE` element.
|
||||
|
||||
```jsx title="Example JSX for displaying HTML TABLE code"
|
||||
<div ref={tbl} dangerouslySetInnerHTML={{ __html }} />
|
||||
```
|
||||
|
||||
#### Exporting Data
|
||||
|
||||
The [`writeFile`](/docs/api/write-options) and [`table_to_book`](/docs/api/utilities/html#html-table-input)
|
||||
functions simplify exporting data. They are best used in the function bodies of
|
||||
`useCallback`[^4] hooks attached to button or other elements.
|
||||
|
||||
A callback can generate a local file when a user clicks a button:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
state((component\nstate))
|
||||
wb(SheetJS\nWorkbook)
|
||||
file[(XLSX\nexport)]
|
||||
state --> |table_to_book\n\n| wb
|
||||
wb --> |writeFile\n\n| file
|
||||
linkStyle 0,1 color:blue,stroke:blue;
|
||||
```
|
||||
|
||||
```ts title="Export data from HTML TABLE element to a new XLSX workbook"
|
||||
import { useCallback } from 'react';
|
||||
import { utils, writeFile } from 'xlsx';
|
||||
|
||||
/* get data from live HTML TABLE and export to XLSX */
|
||||
const exportFile = useCallback(() => {
|
||||
/* get live reference to HTML TABLE element */
|
||||
const elt = tbl.current.getElementsByTagName("TABLE")[0];
|
||||
/* generate workbook from element */
|
||||
// highlight-next-line
|
||||
const wb = utils.table_to_book(elt);
|
||||
/* export to XLSX */
|
||||
writeFile(wb, "SheetJSReactAoO.xlsx");
|
||||
}, [pres]);
|
||||
```
|
||||
|
||||
#### Complete Component
|
||||
|
||||
In this example, the component attaches a `ref` to the `DIV` container. During
|
||||
export, the first `TABLE` child element can be parsed with [`table_to_book`](/docs/api/utilities/html#html-table-input) to
|
||||
@ -701,14 +838,14 @@ This demo was tested in the following environments:
|
||||
|
||||
| ReactJS | ViteJS | Date |
|
||||
|:---------|:--------|:-----------|
|
||||
| `18.3.1` | `6.0.1` | 2024-12-13 |
|
||||
| `19.1.0` | `6.3.5` | 2025-05-11 |
|
||||
|
||||
:::
|
||||
|
||||
1) Create a new site:
|
||||
|
||||
```bash
|
||||
npm create vite@latest sheetjs-react -- --template react
|
||||
npm create vite@latest sheetjs-react -- --template react --no-rolldown --no-interactive
|
||||
```
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
@ -738,7 +875,7 @@ The generated site will be placed in the `dist` folder.
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
npx -y http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
@ -753,22 +890,14 @@ This demo was tested in the following environments:
|
||||
|
||||
| ReactJS | CRA | Date |
|
||||
|:---------|:--------|:-----------|
|
||||
| `18.2.0` | `5.0.1` | 2024-12-31 |
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
|
||||
CRA has known compatibility issues with React 19[^5]. CRA no longer receives
|
||||
updates and the ReactJS docs no longer recommend using CRA. For new projects, it
|
||||
is strongly recommended to use ViteJS with the `react` or `react-ts` templates.
|
||||
| `19.1.0` | `5.1.0` | 2025-05-11 |
|
||||
|
||||
:::
|
||||
|
||||
1) Create a new site:
|
||||
|
||||
```bash
|
||||
npx -y create-react-app@5.0.1 --scripts-version=5.0.1 sheetjs-react
|
||||
npx -y create-react-app@5.1.0 sheetjs-react
|
||||
```
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
@ -776,7 +905,7 @@ npx -y create-react-app@5.0.1 --scripts-version=5.0.1 sheetjs-react
|
||||
<CodeBlock language="bash">{`\
|
||||
cd sheetjs-react
|
||||
npm i
|
||||
npm i react@18.2.0 react-dom@18.2.0 web-vitals --save --save-exact
|
||||
npm i react@19.1.0 react-dom@19.1.0 web-vitals --save --save-exact
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npm start`}
|
||||
</CodeBlock>
|
||||
@ -799,7 +928,7 @@ The generated site will be placed in the `build` folder.
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server build
|
||||
npx -y http-server build
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
@ -812,9 +941,9 @@ and test the page.
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Preact | ViteJS | Date |
|
||||
|:----------|:--------|:-----------|
|
||||
| `10.22.1` | `5.3.3` | 2024-12-17 |
|
||||
| Preact | ViteJS | Date |
|
||||
|:----------|:---------|:-----------|
|
||||
| `10.26.6` | `5.4.19` | 2025-05-11 |
|
||||
|
||||
:::
|
||||
|
||||
@ -823,11 +952,15 @@ npm init preact sheetjs-preact
|
||||
```
|
||||
|
||||
This will initiate the project creation process. **Follow the on-screen prompts and
|
||||
press Enter to accept the default options.**
|
||||
press Enter to accept the default options:**
|
||||
|
||||
- `Project language:` JavaScript
|
||||
- `Use router?` No
|
||||
- `Prerender app (SSG)?` No
|
||||
- `Use ESLint?` No
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
cd sheetjs-preact
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
@ -866,7 +999,7 @@ The generated site will be placed in the `dist` folder.
|
||||
7) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
npx -y http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
@ -913,8 +1046,8 @@ const columns = Array.from({ length: range.e.c + 1 }, (_, i) => ({
|
||||
|
||||
## Legacy Deployments
|
||||
|
||||
[The Standalone Scripts](/docs/getting-started/installation/standalone) play nice
|
||||
with legacy deployments that do not use a bundler.
|
||||
[SheetJS Standalone Scripts](/docs/getting-started/installation/standalone) use
|
||||
simple `SCRIPT` tags and work with legacy deployments that do not use a bundler.
|
||||
|
||||
[The legacy demo](pathname:///react/index.html) shows a simple ReactJS component
|
||||
transpiled in the browser using Babel standalone library.
|
||||
|
||||
@ -321,9 +321,9 @@ interface President { Name: string; Index: number };
|
||||
<td>{{row.Index}}</td>
|
||||
</tr>
|
||||
// highlight-end
|
||||
</tbody><tfoot>
|
||||
</tbody><tfoot><tr><td colspan="2">
|
||||
<button (click)="onSave()">Export XLSX</button>
|
||||
</tfoot>
|
||||
</td></tr></tfoot>
|
||||
</table></div>
|
||||
`
|
||||
})
|
||||
@ -379,9 +379,9 @@ interface President { Name: string; Index: number };
|
||||
</tr>
|
||||
}
|
||||
// highlight-end
|
||||
</tbody><tfoot>
|
||||
</tbody><tfoot><tr><td colspan="2">
|
||||
<button (click)="onSave()">Export XLSX</button>
|
||||
</tfoot>
|
||||
</td></tr></tfoot>
|
||||
</table></div>
|
||||
`
|
||||
})
|
||||
@ -425,6 +425,7 @@ This demo was tested in the following environments:
|
||||
|
||||
| Angular | Date |
|
||||
|:----------|:-----------|
|
||||
| `20.2.3` | 2025-09-03 |
|
||||
| `19.0.5` | 2025-01-03 |
|
||||
| `18.2.13` | 2025-01-03 |
|
||||
| `17.3.12` | 2025-01-03 |
|
||||
@ -441,7 +442,7 @@ npx @angular/cli analytics disable -g
|
||||
1) Create a new project:
|
||||
|
||||
```bash
|
||||
npx @angular/cli@19 new --minimal --defaults --no-interactive sheetjs-angular
|
||||
npx @angular/cli@20 new --minimal --defaults --no-interactive sheetjs-angular
|
||||
```
|
||||
|
||||
:::note pass
|
||||
@ -468,8 +469,20 @@ npm start`}
|
||||
3) Open a web browser and access the displayed URL (`http://localhost:4200`)
|
||||
|
||||
4) In the previous `src/app/app.component.ts` code snippet, select the tab for
|
||||
the appropriate version of Angular ("Angular 2-16" or "Angular 17+"), copy the
|
||||
code contents and replace `src/app/app.component.ts` in the project.
|
||||
the appropriate version of Angular ("Angular 2-16" or "Angular 17+") and copy
|
||||
the code. Replace `src/app/app.component.ts` or `src/app/app.ts` in the project.
|
||||
|
||||
For Angular 20+, after replacing `src/app/app.ts`, edit the script and change
|
||||
the exported class name to `App`:
|
||||
|
||||
```ts title="src/app/app.ts (edit highlighted line if file exists)"
|
||||
// ...
|
||||
})
|
||||
// highlight-next-line
|
||||
export class App {
|
||||
rows: President[] = [ { Name: "SheetJS", Index: 0 }];
|
||||
// ...
|
||||
```
|
||||
|
||||
The page will refresh and show a table with an Export button. Click the button
|
||||
and the page will attempt to download `SheetJSAngularAoO.xlsx`. Open the file
|
||||
|
||||
@ -37,12 +37,20 @@ This demo focuses on VueJS concepts. Other demos cover general deployments:
|
||||
[The "Frameworks" section](/docs/getting-started/installation/frameworks) covers
|
||||
installation with Yarn and other package managers.
|
||||
|
||||
The library can be imported directly from JS or JSX code with:
|
||||
In modern sites, the library can be imported directly from JS or JSX code:
|
||||
|
||||
```js
|
||||
import { read, utils, writeFile } from 'xlsx';
|
||||
```
|
||||
|
||||
In projects that use CommonJS, the library can be loaded with `require`:
|
||||
|
||||
```js
|
||||
var XLSX = require("xlsx");
|
||||
```
|
||||
|
||||
["Legacy Deployments"](#legacy-deployments) covers integration strategies for
|
||||
sites that require standalone scripts.
|
||||
|
||||
## Internal State
|
||||
|
||||
@ -51,14 +59,15 @@ depends on the application.
|
||||
|
||||
### Array of Objects
|
||||
|
||||
Typically, some users will create a spreadsheet with source data that should be
|
||||
loaded into the site. This sheet will have known columns.
|
||||
Typically, users will create a spreadsheet with data that should be imported to
|
||||
the site. The data sheets will typically store headers in the first row. In some
|
||||
applications, the data will follow a standardized template.
|
||||
|
||||
#### State
|
||||
|
||||
The example [presidents sheet](https://docs.sheetjs.com/pres.xlsx) has one
|
||||
header row with "Name" and "Index" columns. The natural JS representation is an
|
||||
object for each row, where the keys are specified in the first row:
|
||||
object for each data row, where the values in the first row are used as keys:
|
||||
|
||||
<table>
|
||||
<thead><tr><th>Spreadsheet</th><th>State</th></tr></thead>
|
||||
@ -106,7 +115,8 @@ const pres = ref<any[]>([]);
|
||||
</script>
|
||||
```
|
||||
|
||||
When the spreadsheet header row is known ahead of time, row typing is possible:
|
||||
`ref` is a generic method in TypeScript. If the spreadsheet header row is known
|
||||
ahead of time, each row object can be typed:
|
||||
|
||||
```html
|
||||
<script setup lang="ts">
|
||||
@ -341,28 +351,29 @@ function exportFile() {
|
||||
<td>{{ row.Name }}</td>
|
||||
<td>{{ row.Index }}</td>
|
||||
</tr>
|
||||
</tbody><tfoot><td colSpan={2}>
|
||||
</tbody><tfoot><tr><td colSpan={2}>
|
||||
<button @click="exportFile">Export XLSX</button>
|
||||
</td></tfoot></table>
|
||||
</td></tr></tfoot></table>
|
||||
</template>
|
||||
```
|
||||
|
||||
<details open>
|
||||
<summary><b>How to run the example</b> (click to hide)</summary>
|
||||
|
||||
<Tabs groupId="starter">
|
||||
<TabItem name="vite" value="ViteJS">
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| VueJS | ViteJS | Date |
|
||||
|:---------|:---------|:-----------|
|
||||
| `3.5.13` | `6.1.0` | 2025-02-15 |
|
||||
| VueJS | Deployment | Date |
|
||||
|:---------|:----------------|:-----------|
|
||||
| `3.5.17` | ViteJS `7.0.0` | 2025-06-29 |
|
||||
| `3.5.17` | NuxtJS `3.17.5` | 2025-06-29 |
|
||||
|
||||
:::
|
||||
|
||||
<Tabs groupId="starter">
|
||||
<TabItem name="vite" value="ViteJS">
|
||||
|
||||
1) Create a new site:
|
||||
|
||||
```bash
|
||||
@ -378,7 +389,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npm run dev`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Open a web browser and access the displayed URL (`http://localhost:5173`)
|
||||
3) Access the "Local" URL (typically `http://localhost:5173`) in a web browser.
|
||||
|
||||
4) Replace `src/App.vue` with the `src/SheetJSVueAoO.vue` example.
|
||||
|
||||
@ -397,7 +408,7 @@ The generated site will be placed in the `dist` folder.
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
npx -y http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
@ -406,20 +417,10 @@ and test the page.
|
||||
</TabItem>
|
||||
<TabItem name="nuxt" value="NuxtJS">
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| VueJS | NuxtJS | Date |
|
||||
|:---------|:---------|:-----------|
|
||||
| `3.5.13` | `3.15.0` | 2025-01-02 |
|
||||
|
||||
:::
|
||||
|
||||
1) Create a new site:
|
||||
|
||||
```bash
|
||||
npx nuxi@latest init sheetjs-nuxt --packageManager npm --no-install --no-gitInit
|
||||
npx nuxi@latest init sheetjs-nuxt --packageManager npm --no-install --no-gitInit -M ,
|
||||
```
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
@ -431,7 +432,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npm run dev`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Open a web browser and access the displayed URL (`http://localhost:3000`)
|
||||
3) Access the "Local" URL (typically `http://localhost:3000`) in a web browser.
|
||||
|
||||
4) Replace `app.vue` with the `src/SheetJSVueAoO.vue` example.
|
||||
|
||||
@ -449,7 +450,7 @@ The generated site will be placed in the `dist` folder.
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server .output/public/
|
||||
npx -y http-server .output/public/
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
@ -462,18 +463,19 @@ and test the page.
|
||||
|
||||
### HTML
|
||||
|
||||
The main disadvantage of the Array of Objects approach is the specific nature
|
||||
The main disadvantage of the "Array of Objects" approach is the specific nature
|
||||
of the columns. For more general use, passing around an Array of Arrays works.
|
||||
However, this does not handle merge cells[^5] well!
|
||||
However, this does not handle merged cells[^5] well!
|
||||
|
||||
The [`sheet_to_html`](/docs/api/utilities/html#html-table-output) function
|
||||
generates HTML that is aware of merges and other worksheet features. VueJS
|
||||
`v-html`[^6] attribute allows code to set the `innerHTML` attribute, effectively
|
||||
inserting the code into the page.
|
||||
|
||||
In this example, the component attaches a `ref` to the `DIV` container. During
|
||||
export, the first `TABLE` child element can be parsed with [`table_to_book`](/docs/api/utilities/html#html-table-input) to
|
||||
generate a workbook object.
|
||||
In this example, the component attaches a `ref` to the `DIV` container. When the
|
||||
"Export XLSX" button is clicked, the first `TABLE` child element will be parsed
|
||||
with the [`table_to_book`](/docs/api/utilities/html#html-table-input) method.
|
||||
The generated workbook object will be exported to XLSX using `writeFile`.
|
||||
|
||||
```html title="src/SheetJSVueHTML.vue"
|
||||
<script setup>
|
||||
@ -511,19 +513,20 @@ function exportFile() {
|
||||
<details open>
|
||||
<summary><b>How to run the example</b> (click to hide)</summary>
|
||||
|
||||
<Tabs groupId="starter">
|
||||
<TabItem name="vite" value="ViteJS">
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| VueJS | ViteJS | Date |
|
||||
|:---------|:--------|:-----------|
|
||||
| `3.5.13` | `6.0.7` | 2025-01-02 |
|
||||
| VueJS | Deployment | Date |
|
||||
|:---------|:----------------|:-----------|
|
||||
| `3.5.17` | ViteJS `7.0.0` | 2025-06-29 |
|
||||
| `3.5.17` | NuxtJS `3.17.5` | 2025-06-29 |
|
||||
|
||||
:::
|
||||
|
||||
<Tabs groupId="starter">
|
||||
<TabItem name="vite" value="ViteJS">
|
||||
|
||||
1) Create a new site:
|
||||
|
||||
```bash
|
||||
@ -539,7 +542,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npm run dev`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Open a web browser and access the displayed URL (`http://localhost:5173`)
|
||||
3) Access the "Local" URL (typically `http://localhost:5173`) in a web browser.
|
||||
|
||||
4) Replace `src/App.vue` with the `src/SheetJSVueHTML.vue` example.
|
||||
|
||||
@ -558,7 +561,7 @@ The generated site will be placed in the `dist` folder.
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
npx -y http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
@ -567,20 +570,10 @@ and test the page.
|
||||
</TabItem>
|
||||
<TabItem name="nuxt" value="NuxtJS">
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| VueJS | NuxtJS | Date |
|
||||
|:---------|:---------|:-----------|
|
||||
| `3.5.13` | `3.15.0` | 2025-01-02 |
|
||||
|
||||
:::
|
||||
|
||||
1) Create a new site:
|
||||
|
||||
```bash
|
||||
npx nuxi@latest init sheetjs-nuxt --packageManager npm --no-install --no-gitInit
|
||||
npx nuxi@latest init sheetjs-nuxt --packageManager npm --no-install --no-gitInit -M ,
|
||||
```
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
@ -592,7 +585,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npm run dev`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Open a web browser and access the displayed URL (`http://localhost:3000`)
|
||||
3) Access the "Local" URL (typically `http://localhost:3000`) in a web browser.
|
||||
|
||||
4) Replace `app.vue` with the `src/SheetJSVueHTML.vue` example.
|
||||
|
||||
@ -610,7 +603,7 @@ The generated site will be placed in the `dist` folder.
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server .output/public/
|
||||
npx -y http-server .output/public/
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
|
||||
@ -130,7 +130,7 @@ function exportFile() {
|
||||
<!-- highlight-end -->
|
||||
</tbody><tfoot><tr><td colSpan={2}>
|
||||
<button on:click={exportFile}>Export XLSX</button>
|
||||
</td></tfoot></tr></table>
|
||||
</td></tr></tfoot></table>
|
||||
</main>
|
||||
```
|
||||
|
||||
@ -143,14 +143,14 @@ This demo was tested in the following environments:
|
||||
|
||||
| SvelteJS | ViteJS | Date |
|
||||
|:---------|:---------|:-----------|
|
||||
| `5.25.3` | `6.2.3` | 2025-03-30 |
|
||||
| `5.43.7` | `7.2.2` | 2025-11-15 |
|
||||
|
||||
:::
|
||||
|
||||
1) Create a new project:
|
||||
|
||||
```bash
|
||||
npm create vite@latest sheetjs-svelte -- --template svelte-ts
|
||||
npm create vite@latest sheetjs-svelte -- --template svelte-ts --no-rolldown --no-interactive
|
||||
```
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
@ -245,14 +245,14 @@ This demo was tested in the following environments:
|
||||
|
||||
| SvelteJS | ViteJS | Date |
|
||||
|:---------|:---------|:-----------|
|
||||
| `5.25.3` | `6.2.3` | 2025-03-30 |
|
||||
| `5.43.7` | `7.2.2` | 2025-11-15 |
|
||||
|
||||
:::
|
||||
|
||||
1) Create a new project:
|
||||
|
||||
```bash
|
||||
npm create vite@latest sheetjs-svelte -- --template svelte-ts
|
||||
npm create vite@latest sheetjs-svelte -- --template svelte-ts --no-rolldown --no-interactive
|
||||
```
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
|
||||
@ -53,7 +53,7 @@ can be loaded in the root HTML page (typically `wwwroot/index.html`):
|
||||
|
||||
<CodeBlock language="html">{`\
|
||||
<!-- use version ${current} -->
|
||||
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>`}
|
||||
<script type="text/javascript" src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>`}
|
||||
</CodeBlock>
|
||||
|
||||
#### ECMAScript Module
|
||||
@ -104,7 +104,7 @@ It should be injected at the top of relevant Razor component scripts:
|
||||
|
||||
When exporting a file with the SheetJS `writeFile` method[^2], browser APIs do
|
||||
not provide success or error feedback. As a result, this demo invokes functions
|
||||
using the `InvokeVoidAsync` static method[^3].
|
||||
using the `InvokeVoidAsync` static method[^3].
|
||||
|
||||
The following C# method will invoke the `export_method` method in the browser:
|
||||
|
||||
@ -295,8 +295,8 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | Date |
|
||||
|:-------------|:-----------|
|
||||
| `darwin-x64` | 2025-04-17 |
|
||||
| `darwin-arm` | 2025-04-24 |
|
||||
| `darwin-x64` | 2026-03-07 |
|
||||
| `darwin-arm` | 2026-03-07 |
|
||||
| `win11-x64` | 2025-04-17 |
|
||||
| `win11-arm` | 2025-04-24 |
|
||||
|
||||
|
||||
@ -91,7 +91,7 @@ in the ["API Reference"](/docs/api/) section of the documentation.
|
||||
|
||||
<!-- The SheetJS Standalone script must be loaded before the UI5 bootstrap -->
|
||||
<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>
|
||||
|
||||
|
||||
<!-- UI5 bootstrap script -->
|
||||
<script
|
||||
id="sap-ui-bootstrap"
|
||||
@ -260,7 +260,7 @@ flowchart LR
|
||||
linkStyle 1,2,3 color:blue,stroke:blue;
|
||||
```
|
||||
|
||||
Here is a sample method for exporting data from the UI5 `JSONModel` to XLSX:
|
||||
Here is a sample method for exporting data from the UI5 `JSONModel` to XLSX:
|
||||
|
||||
```js title="Fetch data from JSONModel and export to XLSX"
|
||||
/* get model data and export to XLSX */
|
||||
@ -441,7 +441,7 @@ generated. The `dist` folder in this demo can be deployed on a static host.
|
||||
9) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
npx -y http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
@ -611,7 +611,7 @@ generated. The `dist` folder in this demo can be deployed on a static host.
|
||||
9) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
npx -y http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
|
||||
@ -25,9 +25,9 @@ the shim script must be loaded first:
|
||||
|
||||
<CodeBlock language="html">{`\
|
||||
<!-- SheetJS version ${current} \`shim.min.js\` -->
|
||||
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js"></script>
|
||||
<!-- SheetJS version ${current} \`xlsx.full.min.js\` -->
|
||||
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>
|
||||
<script>
|
||||
/* display SheetJS version */
|
||||
if(typeof console == "object" && console.log) console.log(XLSX.version);
|
||||
@ -211,8 +211,8 @@ This demo was tested in the following environments:
|
||||
|
||||
| KnockoutJS | Date | Live Demo |
|
||||
|:-----------|:-----------|:-----------------------------------------------|
|
||||
| `3.5.0` | 2025-01-08 | [**KO3**](pathname:///knockout/knockout3.html) |
|
||||
| `2.3.0` | 2025-01-08 | [**KO2**](pathname:///knockout/knockout2.html) |
|
||||
| `3.5.0` | 2026-03-06 | [**KO3**](pathname:///knockout/knockout3.html) |
|
||||
| `2.3.0` | 2026-03-06 | [**KO2**](pathname:///knockout/knockout2.html) |
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -41,10 +41,11 @@ This demo was tested in the following environments:
|
||||
|
||||
| ViteJS | Date |
|
||||
|:---------|:-----------|
|
||||
| `6.2.3` | 2025-03-30 |
|
||||
| `5.4.15` | 2025-03-30 |
|
||||
| `4.5.10` | 2025-03-30 |
|
||||
| `3.2.11` | 2025-03-30 |
|
||||
| `7.3.1` | 2026-01-28 |
|
||||
| `6.4.1` | 2026-01-28 |
|
||||
| `5.4.21` | 2026-01-28 |
|
||||
| `4.5.14` | 2026-01-28 |
|
||||
| `3.2.11` | 2026-01-28 |
|
||||
|
||||
:::
|
||||
|
||||
@ -74,7 +75,7 @@ It is strongly recommended to [upgrade to the latest version](/docs/getting-star
|
||||
1) Create a new ViteJS project:
|
||||
|
||||
```bash
|
||||
npm create vite@latest sheetjs-vite -- --template vue-ts
|
||||
npm create vite@latest sheetjs-vite -- --template vue-ts --no-rolldown --no-interactive
|
||||
cd sheetjs-vite
|
||||
npm i
|
||||
```
|
||||
@ -173,7 +174,7 @@ npx vite build
|
||||
7) Verify the new site by running a local web server in the `dist` folder:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
npx -y http-server dist
|
||||
```
|
||||
|
||||
8) Access the displayed URL (typically `http://localhost:8080`) in a web browser
|
||||
|
||||
@ -47,22 +47,25 @@ This demo was tested in the following environments:
|
||||
|
||||
| ESBuild | Date |
|
||||
|:----------|:-----------|
|
||||
| `0.24.2` | 2025-01-07 |
|
||||
| `0.23.1` | 2025-01-07 |
|
||||
| `0.22.0` | 2025-01-07 |
|
||||
| `0.21.5` | 2025-01-07 |
|
||||
| `0.20.2` | 2025-01-07 |
|
||||
| `0.19.12` | 2025-01-07 |
|
||||
| `0.18.20` | 2025-01-07 |
|
||||
| `0.17.19` | 2025-01-07 |
|
||||
| `0.16.17` | 2025-01-07 |
|
||||
| `0.15.18` | 2025-01-07 |
|
||||
| `0.14.54` | 2025-01-07 |
|
||||
| `0.13.15` | 2025-01-07 |
|
||||
| `0.12.29` | 2025-01-07 |
|
||||
| `0.11.23` | 2025-01-07 |
|
||||
| `0.10.2` | 2025-01-07 |
|
||||
| `0.9.7` | 2025-01-07 |
|
||||
| `0.27.2` | 2026-01-28 |
|
||||
| `0.26.0` | 2026-01-28 |
|
||||
| `0.25.12` | 2026-01-28 |
|
||||
| `0.24.2` | 2026-01-28 |
|
||||
| `0.23.1` | 2026-01-28 |
|
||||
| `0.22.0` | 2026-01-28 |
|
||||
| `0.21.5` | 2026-01-28 |
|
||||
| `0.20.2` | 2026-01-28 |
|
||||
| `0.19.12` | 2026-01-28 |
|
||||
| `0.18.20` | 2026-01-28 |
|
||||
| `0.17.19` | 2026-01-28 |
|
||||
| `0.16.17` | 2026-01-28 |
|
||||
| `0.15.18` | 2026-01-28 |
|
||||
| `0.14.54` | 2026-01-28 |
|
||||
| `0.13.15` | 2026-01-28 |
|
||||
| `0.12.29` | 2026-01-28 |
|
||||
| `0.11.23` | 2026-01-28 |
|
||||
| `0.10.2` | 2026-01-28 |
|
||||
| `0.9.7` | 2026-01-28 |
|
||||
|
||||
:::
|
||||
|
||||
@ -90,7 +93,7 @@ Assuming the primary source file is `in.js`, the following command will bundle
|
||||
the script and generate `out.js`:
|
||||
|
||||
```bash
|
||||
npx -y esbuild@0.24.2 in.js --bundle --outfile=out.js
|
||||
npx -y esbuild@0.25.9 in.js --bundle --outfile=out.js
|
||||
```
|
||||
|
||||
### Browser Demo
|
||||
@ -139,13 +142,13 @@ curl -LO https://docs.sheetjs.com/esbuild/esbrowser.js
|
||||
4) Create bundle:
|
||||
|
||||
```bash
|
||||
npx -y esbuild@0.19.8 esbrowser.js --bundle --outfile=esb.browser.js
|
||||
npx -y esbuild@0.25.9 esbrowser.js --bundle --outfile=esb.browser.js
|
||||
```
|
||||
|
||||
5) Start a local HTTP server:
|
||||
|
||||
```bash
|
||||
npx http-server .
|
||||
npx -y http-server .
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser.
|
||||
@ -179,7 +182,7 @@ Assuming the primary source file is `in.js`, the following command will bundle
|
||||
the script for NodeJS and generate `out.js`:
|
||||
|
||||
```bash
|
||||
npx -y esbuild@0.19.8 in.js --bundle --platform=node --outfile=out.js
|
||||
npx -y esbuild@0.25.9 in.js --bundle --platform=node --outfile=out.js
|
||||
```
|
||||
|
||||
### NodeJS Demo
|
||||
@ -228,7 +231,7 @@ curl -LO https://docs.sheetjs.com/esbuild/esbnode.js
|
||||
3) Create bundle:
|
||||
|
||||
```bash
|
||||
npx -y esbuild@0.19.8 esbnode.js --bundle --platform=node --outfile=esb.node.js
|
||||
npx -y esbuild@0.25.9 esbnode.js --bundle --platform=node --outfile=esb.node.js
|
||||
```
|
||||
|
||||
4) Run the bundle:
|
||||
|
||||
@ -39,12 +39,12 @@ which covers SheetJS library usage in more detail.
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Version | Date | Required Workarounds |
|
||||
|:---------|:-----------|:------------------------------------|
|
||||
| `5.97.1` | 2025-01-03 | |
|
||||
| `4.47.0` | 2025-01-03 | |
|
||||
| `3.12.0` | 2025-01-03 | Import `xlsx/dist/xlsx.full.min.js` |
|
||||
| `2.7.0` | 2025-01-03 | Import `xlsx/dist/xlsx.full.min.js` |
|
||||
| Version | Date | Required Workarounds |
|
||||
|:----------|:-----------|:------------------------------------|
|
||||
| `5.104.1` | 2026-01-28 | |
|
||||
| `4.47.0` | 2026-01-28 | |
|
||||
| `3.12.0` | 2026-01-28 | Import `xlsx/dist/xlsx.full.min.js` |
|
||||
| `2.7.0` | 2026-01-28 | Import `xlsx/dist/xlsx.full.min.js` |
|
||||
|
||||
:::
|
||||
|
||||
@ -177,7 +177,7 @@ document.getElementById("xport").addEventListener("click", function() {
|
||||
prez.forEach(function(row) {
|
||||
row.start = row.terms.find(function(term) {
|
||||
return term.type === "prez";
|
||||
}).start
|
||||
}).start;
|
||||
});
|
||||
prez.sort(function(l,r) { return l.start.localeCompare(r.start); });
|
||||
|
||||
@ -322,15 +322,13 @@ npx webpack --mode=production
|
||||
6) Start a local HTTP server:
|
||||
|
||||
```bash
|
||||
npx http-server .
|
||||
npx -y http-server .
|
||||
```
|
||||
|
||||
7) Load the displayed URL (typically `http://localhost:8080/`) in a web browser.
|
||||
|
||||
Click on "Click here to export" to generate a file.
|
||||
|
||||
## Miscellany
|
||||
|
||||
[^1]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^2]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^3]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input)
|
||||
|
||||
@ -34,21 +34,21 @@ This demo was tested in the following environments:
|
||||
|
||||
| Browserify | Date |
|
||||
|:-----------|:-----------|
|
||||
| `17.0.1` | 2025-01-07 |
|
||||
| `16.5.2` | 2025-01-07 |
|
||||
| `15.2.0` | 2025-01-07 |
|
||||
| `14.5.0` | 2025-01-07 |
|
||||
| `13.3.0` | 2025-01-07 |
|
||||
| `12.0.2` | 2025-01-07 |
|
||||
| `11.2.0` | 2025-01-07 |
|
||||
| `10.2.6` | 2025-01-07 |
|
||||
| `9.0.8` | 2025-01-07 |
|
||||
| `8.1.3` | 2025-01-07 |
|
||||
| `7.1.0` | 2025-01-07 |
|
||||
| `6.3.4` | 2025-01-07 |
|
||||
| `5.13.1` | 2025-01-07 |
|
||||
| `4.2.3` | 2025-01-07 |
|
||||
| `3.46.1` | 2025-01-07 |
|
||||
| `17.0.1` | 2026-01-28 |
|
||||
| `16.5.2` | 2026-01-28 |
|
||||
| `15.2.0` | 2026-01-28 |
|
||||
| `14.5.0` | 2026-01-28 |
|
||||
| `13.3.0` | 2026-01-28 |
|
||||
| `12.0.2` | 2026-01-28 |
|
||||
| `11.2.0` | 2026-01-28 |
|
||||
| `10.2.6` | 2026-01-28 |
|
||||
| `9.0.8` | 2026-01-28 |
|
||||
| `8.1.3` | 2026-01-28 |
|
||||
| `7.1.0` | 2026-01-28 |
|
||||
| `6.3.4` | 2026-01-28 |
|
||||
| `5.13.1` | 2026-01-28 |
|
||||
| `4.2.3` | 2026-01-28 |
|
||||
| `3.46.1` | 2026-01-28 |
|
||||
|
||||
:::
|
||||
|
||||
@ -115,7 +115,7 @@ document.getElementById("xport").addEventListener("click", function() {
|
||||
prez.forEach(function(row) {
|
||||
row.start = row.terms.find(function(term) {
|
||||
return term.type === "prez";
|
||||
}).start
|
||||
}).start;
|
||||
});
|
||||
prez.sort(function(l,r) { return l.start.localeCompare(r.start); });
|
||||
|
||||
@ -177,7 +177,7 @@ npm install --save browserify@3.46.1
|
||||
5) Start a local HTTP server:
|
||||
|
||||
```bash
|
||||
npx http-server .
|
||||
npx -y http-server .
|
||||
```
|
||||
|
||||
6) Load the displayed URL (typically `http://localhost:8080/`) in a web browser.
|
||||
|
||||
@ -40,8 +40,8 @@ This demo was tested in the following environments:
|
||||
|
||||
| RequireJS | Date |
|
||||
|:----------|:-----------|
|
||||
| `2.3.7` | 2025-01-07 |
|
||||
| `2.1.22` | 2025-01-07 |
|
||||
| `2.3.7` | 2026-01-25 |
|
||||
| `2.1.22` | 2026-01-25 |
|
||||
|
||||
:::
|
||||
|
||||
@ -209,7 +209,7 @@ uses normal functions and traditional Promise chains.
|
||||
3) Start a local HTTP server:
|
||||
|
||||
```bash
|
||||
npx http-server .
|
||||
npx -y http-server .
|
||||
```
|
||||
|
||||
4) Load the displayed URL (typically `http://localhost:8080/`) in a web browser.
|
||||
|
||||
@ -46,11 +46,11 @@ This demo was tested in the following environments:
|
||||
|
||||
| Version | Platform | Date |
|
||||
|:----------|:---------|:-----------|
|
||||
| `0.19.47` | NodeJS | 2025-01-03 |
|
||||
| `0.20.16` | Browser | 2025-01-03 |
|
||||
| `0.20.19` | NodeJS | 2025-03-03 |
|
||||
| `0.21.6` | NodeJS | 2025-03-03 |
|
||||
| `6.15.1` | NodeJS | 2025-01-03 |
|
||||
| `6.15.1` | NodeJS | 2026-01-28 |
|
||||
| `0.21.6` | NodeJS | 2026-01-28 |
|
||||
| `0.20.19` | NodeJS | 2026-01-28 |
|
||||
| `0.19.47` | NodeJS | 2026-01-28 |
|
||||
| `0.20.16` | Browser | 2026-01-28 |
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -34,10 +34,10 @@ This demo was tested in the following environments:
|
||||
|
||||
| Version | Date |
|
||||
|:---------|:-----------|
|
||||
| `4.29.1` | 2025-01-03 |
|
||||
| `3.29.5` | 2025-01-03 |
|
||||
| `2.79.1` | 2025-01-03 |
|
||||
| `1.32.1` | 2025-01-03 |
|
||||
| `4.57.0` | 2026-01-28 |
|
||||
| `3.29.5` | 2026-01-28 |
|
||||
| `2.79.2` | 2026-01-28 |
|
||||
| `1.32.1` | 2026-01-28 |
|
||||
|
||||
:::
|
||||
|
||||
@ -169,7 +169,7 @@ This step will create `bundle.js`
|
||||
5) Start a local HTTP server:
|
||||
|
||||
```bash
|
||||
npx http-server .
|
||||
npx -y http-server .
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080/`) in a web browser.
|
||||
|
||||
195
docz/docs/03-demos/02-frontend/19-bundler/18-rspack.md
Normal file
195
docz/docs/03-demos/02-frontend/19-bundler/18-rspack.md
Normal file
@ -0,0 +1,195 @@
|
||||
---
|
||||
title: Packing Sheets with Rspack
|
||||
sidebar_label: Rspack
|
||||
pagination_prev: demos/index
|
||||
pagination_next: demos/grid/index
|
||||
sidebar_position: 18
|
||||
---
|
||||
|
||||
import current from '/version.js';
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
[Rspack](https://rspack.rs/) is a fast module bundler for JavaScript.
|
||||
|
||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
||||
data from spreadsheets.
|
||||
|
||||
This demo uses Rspack and SheetJS to export data. We'll explore how to add
|
||||
SheetJS to a site using Rspack and how to export data to spreadsheets.
|
||||
|
||||
:::note pass
|
||||
|
||||
This demo focuses on integration details with the Rspack bundler.
|
||||
|
||||
The demos follow the ["Export Tutorial"](/docs/getting-started/examples/export),
|
||||
which covers SheetJS library usage in more detail.
|
||||
|
||||
:::
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Rspack | Date |
|
||||
|:--------|:-----------|
|
||||
| `1.7.4` | 2026-01-28 |
|
||||
|
||||
:::
|
||||
|
||||
## Integration Details
|
||||
|
||||
[The "Frameworks" section](/docs/getting-started/installation/frameworks) covers
|
||||
installation with Yarn and other package managers.
|
||||
|
||||
After installing the SheetJS module in a Rspack project, `import` statements can
|
||||
load relevant parts of the library.
|
||||
|
||||
Projects that import data will use methods such as `read`[^1] to parse workbooks
|
||||
and `sheet_to_json`[^2] to generate usable data from files. As `sheet_to_json`
|
||||
is part of the `utils` object, the required import is:
|
||||
|
||||
```js
|
||||
import { read, utils } from 'xlsx';
|
||||
```
|
||||
|
||||
Projects that export data will use methods such as `json_to_sheet`[^3] to
|
||||
generate worksheets and `writeFile`[^4] to export files. As `json_to_sheet` is
|
||||
part of the `utils` object, the required import is:
|
||||
|
||||
```js
|
||||
import { utils, writeFile } from 'xlsx';
|
||||
```
|
||||
|
||||
## Complete Example
|
||||
|
||||
This demo follows the [Export Example](/docs/getting-started/examples/export).
|
||||
|
||||
0) Initialize a new project:
|
||||
|
||||
```bash
|
||||
mkdir sheetjs-rspack
|
||||
cd sheetjs-rspack
|
||||
npm init -y
|
||||
```
|
||||
|
||||
1) Install the dependencies using a package manager:
|
||||
|
||||
<Tabs groupId="pm">
|
||||
<TabItem value="npm" label="npm">
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @rspack/core @rspack/cli`}
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="pnpm" label="pnpm">
|
||||
<CodeBlock language="bash">{`\
|
||||
pnpm install --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @rspack/core @rspack/cli`}
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="yarn" label="Yarn" default>
|
||||
<CodeBlock language="bash">{`\
|
||||
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @rspack/core @rspack/cli`}
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
2) Save the following to `src/index.js`:
|
||||
|
||||
```js title="src/index.js"
|
||||
import { utils, writeFileXLSX } from 'xlsx';
|
||||
|
||||
document.getElementById("xport").addEventListener("click", async() => {
|
||||
/* fetch JSON data and parse */
|
||||
const url = "https://docs.sheetjs.com/executive.json";
|
||||
const raw_data = await (await fetch(url)).json();
|
||||
|
||||
/* filter for the Presidents */
|
||||
const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez"));
|
||||
|
||||
/* sort by first presidential term */
|
||||
prez.forEach(row => row.start = row.terms.find(term => term.type === "prez").start);
|
||||
prez.sort((l,r) => l.start.localeCompare(r.start));
|
||||
|
||||
/* flatten objects */
|
||||
const rows = prez.map(row => ({
|
||||
name: row.name.first + " " + row.name.last,
|
||||
birthday: row.bio.birthday
|
||||
}));
|
||||
|
||||
/* generate worksheet and workbook */
|
||||
const worksheet = utils.json_to_sheet(rows);
|
||||
const workbook = utils.book_new();
|
||||
utils.book_append_sheet(workbook, worksheet, "Dates");
|
||||
|
||||
/* fix headers */
|
||||
utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });
|
||||
|
||||
/* calculate column width */
|
||||
const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
|
||||
worksheet["!cols"] = [ { wch: max_width } ];
|
||||
|
||||
/* create an XLSX file and try to save to Presidents.xlsx */
|
||||
writeFileXLSX(workbook, "Presidents.xlsx");
|
||||
});
|
||||
```
|
||||
|
||||
3) Create bundle:
|
||||
|
||||
```bash
|
||||
npx -p @rspack/cli rspack build
|
||||
```
|
||||
|
||||
:::caution pass
|
||||
|
||||
This build may fail with a module error:
|
||||
|
||||
```
|
||||
ERROR in ./src/index.js
|
||||
× Module parse failed:
|
||||
╰─▶ × JavaScript parse error: 'import', and 'export' cannot be used outside of module code
|
||||
```
|
||||
|
||||
Some versions of the `npm` tool create `package.json` files with the option
|
||||
`"type": "commonjs"`. Rspack will fail if that option is specified. Edit
|
||||
`package.json` and remove the property:
|
||||
|
||||
```js title="package.json (remove highlighted line)"
|
||||
"license": "ISC",
|
||||
// highlight-next-line
|
||||
"type": "commonjs",
|
||||
"dependencies": {
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
This command will create the script `dist/main.js`
|
||||
|
||||
4) Create a small HTML page that loads the generated script:
|
||||
|
||||
```html title="index.html"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head></head>
|
||||
<body>
|
||||
<h1>SheetJS Presidents Demo</h1>
|
||||
<button id="xport">Click here to export</button>
|
||||
<script src="dist/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
5) Start a local HTTP server:
|
||||
|
||||
```bash
|
||||
npx -y http-server .
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser.
|
||||
|
||||
Click the "Click here to export" button to generate `Presidents.xlsx`
|
||||
|
||||
[^1]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^2]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^3]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input)
|
||||
[^4]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
||||
@ -34,8 +34,8 @@ This demo was tested in the following environments:
|
||||
|
||||
| Version | Date |
|
||||
|:---------|:-----------|
|
||||
| `2.13.3` | 2024-12-31 |
|
||||
| `1.12.3` | 2024-12-31 |
|
||||
| `2.16.1` | 2026-01-28 |
|
||||
| `1.12.3` | 2026-01-28 |
|
||||
|
||||
:::
|
||||
|
||||
@ -44,7 +44,7 @@ This demo was tested in the following environments:
|
||||
[The "Frameworks" section](/docs/getting-started/installation/frameworks) covers
|
||||
installation with Yarn and other package managers.
|
||||
|
||||
After installing the SheetJS module in a RollupJS project, `import` statements
|
||||
After installing the SheetJS module in a ParcelJS project, `import` statements
|
||||
can load relevant parts of the library:
|
||||
|
||||
```js
|
||||
@ -239,7 +239,7 @@ The production site will be stored in the `dist` folder
|
||||
7) Start a local web server and serve the `dist` folder:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
npx -y http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080/`) in a web browser.
|
||||
|
||||
@ -35,7 +35,7 @@ This demo was tested in the following environments:
|
||||
|
||||
| Version | Date |
|
||||
|:----------|:-----------|
|
||||
| `1.2.246` | 2025-01-07 |
|
||||
| `1.15.11` | 2026-01-28 |
|
||||
|
||||
:::
|
||||
|
||||
@ -63,7 +63,7 @@ part of the `utils` object, the required import is:
|
||||
import { utils, writeFile } from 'xlsx';
|
||||
```
|
||||
|
||||
:::danger pass
|
||||
:::caution pass
|
||||
|
||||
When this demo was tested against recent versions of `@swc/core`, `spack` crashed:
|
||||
|
||||
@ -75,7 +75,8 @@ thread '<unnamed>' panicked at 'cannot access a scoped thread local variable wit
|
||||
|
||||
This bug is known to affect versions `1.3.100`, `1.4.17`, and `1.10.6`.
|
||||
|
||||
Until the bug is fixed, it is strongly recommended to use `@swc/core@1.2.246`.
|
||||
This bug was fixed in version `1.12.1`. It is strongly recommended to upgrade
|
||||
existing projects to use `1.12.1` or to downgrade to `1.2.246`.
|
||||
|
||||
:::
|
||||
|
||||
@ -94,17 +95,17 @@ npm init -y
|
||||
<Tabs groupId="pm">
|
||||
<TabItem value="npm" label="npm">
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz regenerator-runtime @swc/cli @swc/core@1.2.246`}
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz regenerator-runtime @swc/cli @swc/core@1.13.5`}
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="pnpm" label="pnpm">
|
||||
<CodeBlock language="bash">{`\
|
||||
pnpm install --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz regenerator-runtime @swc/cli @swc/core@1.2.246`}
|
||||
pnpm install --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz regenerator-runtime @swc/cli @swc/core@1.13.5`}
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="yarn" label="Yarn" default>
|
||||
<CodeBlock language="bash">{`\
|
||||
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz regenerator-runtime @swc/cli @swc/core@1.2.246`}
|
||||
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz regenerator-runtime @swc/cli @swc/core@1.13.5`}
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
@ -195,7 +196,7 @@ This command will create the script `lib/web.js`
|
||||
6) Start a local HTTP server, then go to `http://localhost:8080/`
|
||||
|
||||
```bash
|
||||
npx http-server .
|
||||
npx -y http-server .
|
||||
```
|
||||
|
||||
Click on "Click here to export" to generate a file.
|
||||
|
||||
@ -62,7 +62,7 @@ This demo was tested in the following environments:
|
||||
|
||||
| Version | Date |
|
||||
|:--------|:-----------|
|
||||
| `3.8.8` | 2025-01-07 |
|
||||
| `3.8.8` | 2026-01-28 |
|
||||
|
||||
:::
|
||||
|
||||
@ -149,7 +149,7 @@ writeFileXLSX(workbook, "Presidents.xlsx");
|
||||
</html>
|
||||
```
|
||||
|
||||
:::note pass
|
||||
:::danger pass
|
||||
|
||||
Unlike other bundlers, Snowpack requires a full page including `HEAD` element.
|
||||
|
||||
@ -164,7 +164,7 @@ npx snowpack@3.8.8 build
|
||||
5) Start a local HTTP server:
|
||||
|
||||
```bash
|
||||
npx http-server build/
|
||||
npx -y http-server build/
|
||||
```
|
||||
|
||||
6) Open a web browser to the displayed URL (typically `http://localhost:8080/`).
|
||||
@ -194,7 +194,7 @@ This demo was tested in the following environments:
|
||||
|
||||
| Version | Date |
|
||||
|:--------|:-----------|
|
||||
| `3.8.0` | 2025-01-07 |
|
||||
| `3.8.0` | 2026-01-28 |
|
||||
|
||||
:::
|
||||
|
||||
@ -290,7 +290,7 @@ npx wmr@3.8.0 build
|
||||
5) Start a local HTTP server:
|
||||
|
||||
```bash
|
||||
npx http-server dist/
|
||||
npx -y http-server dist/
|
||||
```
|
||||
|
||||
6) Open a web browser to the displayed URL (typically `http://localhost:8080/`).
|
||||
|
||||
@ -98,11 +98,40 @@ Each browser demo was tested in the following environments:
|
||||
|
||||
### XMLHttpRequest
|
||||
|
||||
For downloading data, the `arraybuffer` response type generates an `ArrayBuffer`
|
||||
that can be viewed as an `Uint8Array` and fed to the SheetJS `read` method. For
|
||||
legacy browsers, the option `type: "array"` should be specified:
|
||||
`XMLHttpRequest` is a browser API for performing network requests. Files can be
|
||||
downloaded from external sources in `GET` and `POST` requests.
|
||||
|
||||
The `responseType` property controls how `XMLHttpRequest` processes data. The
|
||||
SheetJS [`read`](/docs/api/parse-options/) method accepts a `type` option that
|
||||
specifies the data representation. SheetJS and `XMLHttpRequest` options must be
|
||||
set in tandem.
|
||||
|
||||
In modern browsers, when the response type is `"arraybuffer"`, `XMLHttpRequest`
|
||||
will generate an `ArrayBuffer` of raw data. The SheetJS `read` method directly
|
||||
processes `ArrayBuffer` objects.
|
||||
|
||||
```mermaid
|
||||
---
|
||||
title: XMLHttpRequest + SheetJS in modern browsers
|
||||
---
|
||||
flowchart LR
|
||||
file[(workbook\nfile)]
|
||||
ab[(file bytes\nArrayBuffer)]
|
||||
wb(((SheetJS\nWorkbook)))
|
||||
file --> |XMLHttpRequest\nresponseType="arraybuffer"| ab
|
||||
ab --> |SheetJS read\n\n|wb
|
||||
```
|
||||
|
||||
The following example fetches a file, generates an HTML `TABLE` from the first
|
||||
sheet using the [`sheet_to_html`](/docs/api/utilities/html#html-table-output)
|
||||
method, and inserts the `TABLE` in a `DIV` container:
|
||||
|
||||
```html title="Download and parse files with XMLHttpRequest and SheetJS"
|
||||
<div id="sheetjs-tbl"></div>
|
||||
<script>
|
||||
/* This file will be downloaded and processed */
|
||||
var url = "https://docs.sheetjs.com/pres.numbers";
|
||||
|
||||
```js
|
||||
/* set up an async GET request */
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", url, true);
|
||||
@ -110,11 +139,19 @@ req.responseType = "arraybuffer";
|
||||
|
||||
req.onload = function(e) {
|
||||
/* parse the data when it is received */
|
||||
var data = new Uint8Array(req.response);
|
||||
var workbook = XLSX.read(data, {type:"array"});
|
||||
var workbook = XLSX.read(req.response);
|
||||
|
||||
/* DO SOMETHING WITH workbook HERE */
|
||||
|
||||
/* generate HTML from the first worksheet */
|
||||
var first_sheet = workbook.Sheets[workbook.SheetNames[0]];
|
||||
var table_html = XLSX.utils.sheet_to_html(first_sheet);
|
||||
|
||||
/* add to page */
|
||||
document.getElementById("sheetjs-tbl").innerHTML = table_html;
|
||||
};
|
||||
req.send();
|
||||
</script>
|
||||
```
|
||||
|
||||
<details>
|
||||
@ -135,7 +172,7 @@ function SheetJSXHRDL() {
|
||||
req.responseType = "arraybuffer";
|
||||
req.onload = e => {
|
||||
/* Parse file */
|
||||
const wb = XLSX.read(new Uint8Array(req.response));
|
||||
const wb = XLSX.read(req.response);
|
||||
const ws = wb.Sheets[wb.SheetNames[0]];
|
||||
|
||||
/* Generate HTML */
|
||||
@ -150,6 +187,35 @@ function SheetJSXHRDL() {
|
||||
|
||||
</details>
|
||||
|
||||
In browsers that do not support `ArrayBuffer`, including Internet Explorer and
|
||||
older versions of Firefox, `XMLHttpRequest` will return an array of unsigned
|
||||
bytes. In this case, the `read` method requires the option `type: "array"`:
|
||||
|
||||
```mermaid
|
||||
---
|
||||
title: XMLHttpRequest + SheetJS in browsers lacking ArrayBuffer support
|
||||
---
|
||||
flowchart LR
|
||||
file[(workbook\nfile)]
|
||||
ab[(file bytes\nArray)]
|
||||
wb(((SheetJS\nWorkbook)))
|
||||
file --> |XMLHttpRequest\nresponseType="arraybuffer"| ab
|
||||
ab --> |SheetJS read\ntype="array"|wb
|
||||
```
|
||||
|
||||
```js title="Download and parse files in legacy browsers (snippet)"
|
||||
/* set up an async GET request */
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", url, true);
|
||||
req.responseType = "arraybuffer";
|
||||
|
||||
req.onload = function(e) {
|
||||
/* parse the data when it is received */
|
||||
var workbook = XLSX.read(req.response, {type: "array"});
|
||||
/* DO SOMETHING WITH workbook HERE */
|
||||
};
|
||||
req.send();
|
||||
```
|
||||
|
||||
### fetch
|
||||
|
||||
|
||||
@ -26,8 +26,8 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Drash | Deno | Date |
|
||||
|:--------|:-------|:-----------|
|
||||
| `2.8.1` | 1.44.1 | 2024-12-19 |
|
||||
| `2.8.1` | 2.1.4 | 2024-12-19 |
|
||||
| `2.8.1` | 1.46.0 | 2025-05-21 |
|
||||
| `2.8.1` | 2.3.3 | 2025-05-21 |
|
||||
|
||||
:::
|
||||
|
||||
@ -133,7 +133,7 @@ deno run --allow-net SheetJSDrash.ts
|
||||
Deno 2 requires the `--allow-import` entitlement:
|
||||
|
||||
```bash
|
||||
deno run --allow-net --allow-write --allow-import SheetJSDenoDOM.ts
|
||||
deno run --allow-net --allow-write --allow-import SheetJSDrash.ts
|
||||
```
|
||||
|
||||
:::
|
||||
@ -142,9 +142,10 @@ deno run --allow-net --allow-write --allow-import SheetJSDenoDOM.ts
|
||||
|
||||
4) Open `http://localhost:7262/` in your browser.
|
||||
|
||||
Click "Choose File" and select `pres.numbers`. Then click "Submit"
|
||||
Click "Choose File" and select `pres.numbers` from the Downloads folder.
|
||||
|
||||
The page should show the contents of the file as an HTML table.
|
||||
Click "Submit" to make a request to the Drash server. The response should show
|
||||
the contents of the file as an HTML table.
|
||||
|
||||
5) Open `http://localhost:7262/export` in your browser.
|
||||
|
||||
|
||||
@ -23,9 +23,11 @@ The ["Complete Example"](#complete-example) section includes a complete server.
|
||||
|
||||
This demo was tested in the following deployments:
|
||||
|
||||
| Platform | HonoJS | Date |
|
||||
|:---------------|:---------|:-----------|
|
||||
| BunJS `1.1.40` | `4.6.14` | 2024-12-19 |
|
||||
| Platform | HonoJS | Date |
|
||||
|:---------------|:----------|:-----------|
|
||||
| BunJS `1.2.13` | `2.7.8` | 2025-05-21 |
|
||||
| BunJS `1.2.13` | `3.12.12` | 2025-05-21 |
|
||||
| BunJS `1.2.13` | `4.7.10` | 2025-05-21 |
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -26,8 +26,8 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Platform | ElysiaJS | Date |
|
||||
|:---------------|:---------|:-----------|
|
||||
| BunJS `1.1.40` | `0.8.17` | 2024-12-19 |
|
||||
| BunJS `1.1.40` | `1.1.26` | 2024-12-19 |
|
||||
| BunJS `1.2.13` | `0.8.17` | 2025-05-21 |
|
||||
| BunJS `1.2.13` | `1.3.1` | 2025-05-21 |
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -24,11 +24,12 @@ The ["Complete Example"](#complete-example) section includes a complete server.
|
||||
|
||||
This demo was tested in the following deployments:
|
||||
|
||||
| NestJS | Date |
|
||||
|:----------|:-------------|
|
||||
| `10.4.15` | `2024-12-22` |
|
||||
| `9.4.3` | `2024-12-22` |
|
||||
| `8.4.7` | `2024-12-22` |
|
||||
| NestJS | Date |
|
||||
|:----------|:-----------|
|
||||
| `11.1.1` | 2025-05-21 |
|
||||
| `10.4.17` | 2025-05-21 |
|
||||
| `9.4.3` | 2025-05-21 |
|
||||
| `8.4.7` | 2025-05-21 |
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -25,8 +25,8 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Version | Date |
|
||||
|:---------|:-----------|
|
||||
| `4.29.0` | 2025-01-02 |
|
||||
| `5.2.0` | 2025-01-02 |
|
||||
| `4.29.1` | 2025-09-13 |
|
||||
| `5.6.0` | 2025-09-13 |
|
||||
|
||||
:::
|
||||
|
||||
@ -37,10 +37,10 @@ imported from scripts that use FastifyJS.
|
||||
|
||||
### Exporting Data to Workbooks (GET)
|
||||
|
||||
The SheetJS `write` method[^1] with the option `type: "buffer"` generates NodeJS
|
||||
Buffer objects containing the raw file data.
|
||||
The SheetJS [`write`](/docs/api/write-options) method generates NodeJS `Buffer`
|
||||
objects containing the raw file data (using the option `type: "buffer"`[^1]).
|
||||
|
||||
FastifyJS can directly handle `Buffer` data in `Response#end`
|
||||
FastifyJS can directly handle `Buffer` data in `Response#end`.
|
||||
|
||||
The exported filename can be specified using the `Content-Disposition` header.
|
||||
|
||||
@ -162,7 +162,7 @@ fastify.listen({port: process.env.PORT || 3000}, (err, addr) => { if(err) throw
|
||||
1) Install dependencies:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz fastify@4.29.0 @fastify/multipart@8`}
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz fastify@4.29.1 @fastify/multipart@8`}
|
||||
</CodeBlock>
|
||||
|
||||
2) Start server
|
||||
|
||||
@ -36,12 +36,13 @@ the file can be downloaded or previewed in the browser.
|
||||
|
||||
This demo was tested in the following deployments:
|
||||
|
||||
| Platform | Version | Date |
|
||||
|:-------------|:---------|:-----------|
|
||||
| Chromium 131 | `1.9.0` | 2024-12-22 |
|
||||
| Konqueror 22 | `1.9.0` | 2025-04-23 |
|
||||
| NodeJS 20 | `1.10.0` | 2024-12-22 |
|
||||
| BunJS 1.1 | `1.10.0` | 2024-12-22 |
|
||||
| Platform | Version | Date |
|
||||
|:--------------|:---------|:-----------|
|
||||
| Chromium 136 | `1.9.0` | 2025-05-07 |
|
||||
| Safari 17.5 | `1.9.0` | 2025-05-07 |
|
||||
| Konqueror 22 | `1.9.0` | 2025-05-07 |
|
||||
| NodeJS 24.0.0 | `1.11.0` | 2025-05-07 |
|
||||
| BunJS 1.2.10 | `1.11.0` | 2025-05-07 |
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -130,12 +130,13 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Puppeteer | Date |
|
||||
|:----------|:-----------|
|
||||
| `23.11.1` | 2024-12-31 |
|
||||
| `22.15.0` | 2024-12-31 |
|
||||
| `21.11.0` | 2024-12-31 |
|
||||
| `20.9.0` | 2024-12-31 |
|
||||
| `15.5.0` | 2024-12-31 |
|
||||
| `10.4.0` | 2024-12-31 |
|
||||
| `24.35.0` | 2026-01-21 |
|
||||
| `23.11.1` | 2026-01-21 |
|
||||
| `22.15.0` | 2026-01-21 |
|
||||
| `21.11.0` | 2026-01-21 |
|
||||
| `20.9.0` | 2026-01-21 |
|
||||
| `15.5.0` | 2026-01-21 |
|
||||
| `10.4.0` | 2026-01-21 |
|
||||
|
||||
:::
|
||||
|
||||
@ -145,14 +146,14 @@ This demo was tested in the following deployments:
|
||||
<TabItem value="nodejs" label="NodeJS">
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz puppeteer@23.11.1`}
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz puppeteer@24.9.0`}
|
||||
</CodeBlock>
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="bunjs" label="BunJS">
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
bun install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz puppeteer@23.11.1`}
|
||||
bun install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz puppeteer@24.9.0`}
|
||||
</CodeBlock>
|
||||
|
||||
</TabItem>
|
||||
@ -236,9 +237,9 @@ const { webkit } = require('playwright'); // import desired browser
|
||||
|
||||
This demo was tested in the following deployments:
|
||||
|
||||
| Playwright | Date |
|
||||
|:-----------|:-----------|
|
||||
| `1.49.1` | 2024-12-31 |
|
||||
| Playwright | Browser | Date |
|
||||
|:-----------|:------------|:-----------|
|
||||
| `1.52.0` | Webkit 18.4 | 2025-05-21 |
|
||||
|
||||
:::
|
||||
|
||||
@ -332,9 +333,9 @@ This demo was tested in the following environments:
|
||||
|
||||
| Architecture | PhantomJS | Date |
|
||||
|:-------------|:----------|:-----------|
|
||||
| `darwin-x64` | `2.1.1` | 2025-03-31 |
|
||||
| `win11-x64` | `2.1.1` | 2025-01-19 |
|
||||
| `linux-x64` | `2.1.1` | 2025-01-07 |
|
||||
| `darwin-x64` | `2.1.1` | 2026-03-07 |
|
||||
| `win11-x64` | `2.1.1` | 2026-03-07 |
|
||||
| `linux-x64` | `2.1.1` | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
@ -420,7 +421,7 @@ a different error after assignment:
|
||||
This error is resolved by ignoring SSL errors. The complete command is:
|
||||
|
||||
```bash
|
||||
env OPENSSL_CONF=/dev/null QT_QPA_PLATFORM=phantom ./phantomjs-2.1.1-linux-x86_64/bin/phantomjs --ignore-ssl-errors=true test.js
|
||||
env OPENSSL_CONF=/dev/null QT_QPA_PLATFORM=phantom ./phantomjs-2.1.1-linux-x86_64/bin/phantomjs --ignore-ssl-errors=true SheetJSPhantom.js
|
||||
```
|
||||
|
||||
:::
|
||||
@ -429,4 +430,4 @@ env OPENSSL_CONF=/dev/null QT_QPA_PLATFORM=phantom ./phantomjs-2.1.1-linux-x86_6
|
||||
|
||||
[^1]: See ["Workbook Object"](/docs/csf/book) for more details about the SheetJS workbook object.
|
||||
[^2]: See [`table_to_book` in "HTML" Utilities](/docs/api/utilities/html#create-new-sheet)
|
||||
[^3]: See [`write` in "Writing Files"](/docs/api/write-options)
|
||||
[^3]: See [`write` in "Writing Files"](/docs/api/write-options)
|
||||
|
||||
@ -296,10 +296,9 @@ features to ensure that SheetJS DOM methods can process TABLE elements.
|
||||
|
||||
This demo was tested in the following deployments:
|
||||
|
||||
| CheerioJS | Date |
|
||||
|:--------------|:-----------|
|
||||
| `1.0.0` | 2025-04-24 |
|
||||
| `1.0.0-rc.12` | 2025-04-24 |
|
||||
| CheerioJS | Date |
|
||||
|:----------|:-----------|
|
||||
| `1.2.0` | 2026-01-28 |
|
||||
|
||||
:::
|
||||
|
||||
@ -309,7 +308,7 @@ This demo was tested in the following deployments:
|
||||
1) Install SheetJS and CheerioJS libraries:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz cheerio@1.0.0`}
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz cheerio@1.1.2`}
|
||||
</CodeBlock>
|
||||
|
||||
2) Download [the sample script `SheetJSCheerio.js`](pathname:///dom/SheetJSCheerio.js):
|
||||
@ -375,12 +374,12 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | DenoDOM | Deno | Date |
|
||||
|:-------------|:--------|:-------|:-----------|
|
||||
| `darwin-x64` | 0.1.48 | 2.2.6 | 2025-03-31 |
|
||||
| `darwin-x64` | 0.1.48 | 2.7.4 | 2026-03-07 |
|
||||
| `darwin-arm` | 0.1.48 | 2.2.12 | 2025-04-24 |
|
||||
| `win11-x64` | 0.1.48 | 2.0.4 | 2024-10-30 |
|
||||
| `win11-x64` | 0.1.48 | 2.2.12 | 2025-04-28 |
|
||||
| `win11-arm` | 0.1.48 | 2.2.1 | 2025-02-23 |
|
||||
| `linux-x64` | 0.1.48 | 2.0.5 | 2025-01-10 |
|
||||
| `linux-arm` | 0.1.48 | 2.1.10 | 2025-02-16 |
|
||||
| `linux-x64` | 0.1.48 | 2.7.4 | 2026-03-07 |
|
||||
| `linux-arm` | 0.1.48 | 2.7.4 | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
@ -392,17 +391,17 @@ This demo was tested in the following deployments:
|
||||
2) Run the script with `--allow-net` and `--allow-write` entitlements:
|
||||
|
||||
```bash
|
||||
deno run --allow-net --allow-write SheetJSDenoDOM.ts
|
||||
deno run --allow-net --allow-write --allow-import SheetJSDenoDOM.ts
|
||||
```
|
||||
|
||||
The script will create a file `SheetJSDenoDOM.xlsx` that can be opened.
|
||||
|
||||
:::caution pass
|
||||
:::note pass
|
||||
|
||||
Deno 2 additionally requires the `--allow-import` entitlement:
|
||||
In older versions of Deno, the `--allow-import` flag must be omitted:
|
||||
|
||||
```bash
|
||||
deno run --allow-net --allow-write --allow-import SheetJSDenoDOM.ts
|
||||
deno run --allow-net --allow-write SheetJSDenoDOM.ts
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@ -20,8 +20,8 @@ This demo was tested in the following environments:
|
||||
|
||||
| Browser | Date |
|
||||
|:-------------|:-----------|
|
||||
| Chromium 131 | 2024-12-31 |
|
||||
| Safari 18.2 | 2024-12-31 |
|
||||
| Chromium 136 | 2025-05-21 |
|
||||
| Safari 18.2 | 2025-05-21 |
|
||||
| Konqueror 22 | 2025-04-23 |
|
||||
|
||||
:::
|
||||
|
||||
@ -19,8 +19,8 @@ This demo was tested in the following environments:
|
||||
|
||||
| Browser | Date |
|
||||
|:-------------|:-----------|
|
||||
| Chromium 131 | 2024-12-31 |
|
||||
| Safari 18.2 | 2024-12-31 |
|
||||
| Chromium 136 | 2025-05-21 |
|
||||
| Safari 18.2 | 2025-05-21 |
|
||||
| Konqueror 22 | 2025-04-23 |
|
||||
|
||||
:::
|
||||
|
||||
@ -7,7 +7,7 @@ pagination_next: demos/net/index
|
||||
import current from '/version.js';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
[React Data Grid](https://adazzle.github.io/react-data-grid/) is a data grid
|
||||
[React Data Grid](https://comcast.github.io/react-data-grid/) is a data grid
|
||||
designed for the ReactJS web framework.
|
||||
|
||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
||||
|
||||
@ -8,6 +8,11 @@ sidebar_custom_props:
|
||||
type: native
|
||||
---
|
||||
|
||||
import current from '/version.js';
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
[Lume](https://lume.land/) is a lightweight unopinionated static site generator.
|
||||
It has a rich ecosystem of JavaScript-powered plugins[^1]
|
||||
|
||||
@ -23,8 +28,11 @@ powered by an XLSX spreadsheet.
|
||||
## Integration Details
|
||||
|
||||
The official "Sheets" plugin[^2] uses SheetJS to load data from spreadsheets.
|
||||
Under the hood, the plugin uses the SheetJS `read`[^3] method to parse files and
|
||||
the `sheet_to_json`[^4] method to generate arrays of objects.
|
||||
Under the hood, the plugin uses the following SheetJS methods:
|
||||
|
||||
- [`read`](/docs/api/parse-options) parses spreadsheet files.
|
||||
- [`sheet_to_json`](/docs/api/utilities/array#array-output) generates arrays of
|
||||
objects from worksheet data.
|
||||
|
||||
Lume supports refreshing data during development. The generated static sites
|
||||
include the raw data without referencing the underlying spreadsheet files.
|
||||
@ -113,7 +121,7 @@ named `"VicePresidents"`, then the following snippet would print data from the
|
||||
|
||||
#### File Formats
|
||||
|
||||
As explained in the official plugin documentation[^5], the loader loads XLSX.
|
||||
As explained in the official plugin documentation[^3], the loader loads XLSX.
|
||||
NUMBERS, and CSV files. Other extensions can be added through the `extensions`
|
||||
property in the argument to the `sheets` plugin:
|
||||
|
||||
@ -133,8 +141,9 @@ This demo was tested in the following environments:
|
||||
|
||||
| Lume | Date |
|
||||
|:---------|:-----------|
|
||||
| `1.19.4` | 2025-01-02 |
|
||||
| `2.4.3` | 2025-01-02 |
|
||||
| `1.19.4` | 2025-09-13 |
|
||||
| `2.5.3` | 2025-09-13 |
|
||||
| `3.0.9` | 2025-09-13 |
|
||||
|
||||
This example uses the Nunjucks template format. Lume plugins support additional
|
||||
template formats, including Markdown and JSX.
|
||||
@ -143,26 +152,24 @@ template formats, including Markdown and JSX.
|
||||
|
||||
### Initial Setup
|
||||
|
||||
0) Install Deno[^6]
|
||||
0) Install Deno[^4]
|
||||
|
||||
1) Create a stock site:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="v1" label="v1">
|
||||
|
||||
```bash
|
||||
mkdir -p sheetjs-lume
|
||||
cd sheetjs-lume
|
||||
deno run -Ar https://deno.land/x/lume@v2.4.3/init.ts
|
||||
deno run -Ar https://deno.land/x/lume@v1.19.4/init.ts
|
||||
```
|
||||
|
||||
When prompted, enter the following options. The initialization script has
|
||||
changed over time, so not all questions will be asked.
|
||||
When prompted, enter the following options:
|
||||
|
||||
- `What kind of setup do you want?`: select `Basic + plugins`
|
||||
- `Choose the configuration file format`: select `_config.ts`
|
||||
- `Do you want to install some plugins now?`: select `Yes`
|
||||
- `Select the plugins to install`: select `sheets` and `nunjucks`
|
||||
- `Do you want to setup a CMS?`: select `No` or `Maybe later`
|
||||
|
||||
The project will be configured and modules will be installed.
|
||||
- `Select the plugins to install`: select `sheets` and press <kbd>Enter</kbd>
|
||||
|
||||
:::note pass
|
||||
|
||||
@ -170,6 +177,53 @@ The `nunjucks` plugin was included by default in Lume version 1.
|
||||
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="v2" label="v2">
|
||||
|
||||
```bash
|
||||
mkdir -p sheetjs-lume
|
||||
cd sheetjs-lume
|
||||
deno run -Ar https://deno.land/x/lume@v2.5.3/init.ts
|
||||
```
|
||||
|
||||
When prompted, enter the following options:
|
||||
|
||||
- `What kind of setup do you want?`: select `Basic + plugins`
|
||||
- `Select the plugins to install`: select `sheets` and `nunjucks`
|
||||
- `Do you want to setup a CMS?`: select `No` or `Maybe later`
|
||||
|
||||
:::note pass
|
||||
|
||||
The `nunjucks` plugin is not included by default in Lume version 2.
|
||||
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="v3" label="v3">
|
||||
|
||||
```bash
|
||||
mkdir -p sheetjs-lume
|
||||
cd sheetjs-lume
|
||||
deno run -A https://lume.land/init.ts
|
||||
```
|
||||
|
||||
When prompted, enter the following options:
|
||||
|
||||
- `What kind of setup do you want?`: select `Basic + plugins`
|
||||
- `Select the plugins to install`: select `sheets` and `nunjucks`
|
||||
- `Do you want to setup a CMS?`: select `No` or `Maybe later`
|
||||
|
||||
:::note pass
|
||||
|
||||
The `nunjucks` plugin is not included by default in Lume version 3.
|
||||
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The project will be configured and modules will be installed.
|
||||
|
||||
2) Download https://docs.sheetjs.com/pres.xlsx and place in a `_data` subfolder:
|
||||
|
||||
```bash
|
||||
@ -231,7 +285,7 @@ This will create a static site in the `_site` folder
|
||||
8) Test the generated site by starting a web server:
|
||||
|
||||
```bash
|
||||
npx http-server _site
|
||||
npx -y http-server _site
|
||||
```
|
||||
|
||||
The program will display a URL (typically `http://localhost:8080`). Accessing
|
||||
@ -244,7 +298,5 @@ This site is self-contained and ready for deployment!
|
||||
|
||||
[^1]: See ["Plugins"](https://lume.land/plugins/?status=all) in the Lume documentation
|
||||
[^2]: See ["Sheets"](https://lume.land/plugins/sheets/) in the Lume documentation
|
||||
[^3]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^4]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^5]: See ["Formats"](https://lume.land/plugins/sheets/#formats) in the Lume documentation
|
||||
[^6]: See ["Installation"](https://deno.com/manual/getting_started/installation) in the Deno documentation
|
||||
[^3]: See ["Formats"](https://lume.land/plugins/sheets/#formats) in the Lume documentation
|
||||
[^4]: See ["Installation"](https://docs.deno.com/runtime/getting_started/installation/) in the Deno documentation
|
||||
@ -191,8 +191,8 @@ This demo was tested in the following environments:
|
||||
|
||||
| GatsbyJS | Date |
|
||||
|:---------|:-----------|
|
||||
| `5.14.1` | 2025-01-19 |
|
||||
| `4.25.8` | 2025-01-02 |
|
||||
| `5.15.0` | 2025-09-13 |
|
||||
| `4.25.8` | 2025-09-13 |
|
||||
|
||||
:::
|
||||
|
||||
@ -241,6 +241,7 @@ git clone https://github.com/gatsbyjs/gatsby-starter-default sheetjs-gatsby
|
||||
cd sheetjs-gatsby
|
||||
git checkout 6bc4466090845f20650117b3d27e68e6e46dc8d5
|
||||
npm install
|
||||
mkdir .cache
|
||||
cd ..
|
||||
```
|
||||
|
||||
@ -250,6 +251,7 @@ cd ..
|
||||
|
||||
```bash
|
||||
cd sheetjs-gatsby
|
||||
npm i
|
||||
npm run develop
|
||||
```
|
||||
|
||||
|
||||
@ -204,23 +204,26 @@ This demo was tested in the following environments:
|
||||
|
||||
| `esbuild` | Date |
|
||||
|:----------|:-----------|
|
||||
| `0.24.2` | 2025-01-07 |
|
||||
| `0.23.1` | 2025-01-07 |
|
||||
| `0.22.0` | 2025-01-07 |
|
||||
| `0.21.5` | 2025-01-07 |
|
||||
| `0.20.2` | 2025-01-07 |
|
||||
| `0.19.12` | 2025-01-07 |
|
||||
| `0.18.20` | 2025-01-07 |
|
||||
| `0.17.19` | 2025-01-07 |
|
||||
| `0.16.17` | 2025-01-07 |
|
||||
| `0.15.18` | 2025-01-07 |
|
||||
| `0.14.54` | 2025-01-07 |
|
||||
| `0.13.15` | 2025-01-07 |
|
||||
| `0.12.29` | 2025-01-07 |
|
||||
| `0.11.23` | 2025-01-07 |
|
||||
| `0.10.2` | 2025-01-07 |
|
||||
| `0.9.7` | 2025-01-07 |
|
||||
| `0.9.1` | 2025-01-07 |
|
||||
| `0.27.2` | 2026-01-28 |
|
||||
| `0.26.0` | 2026-01-28 |
|
||||
| `0.25.5` | 2026-01-28 |
|
||||
| `0.24.2` | 2026-01-28 |
|
||||
| `0.23.1` | 2026-01-28 |
|
||||
| `0.22.0` | 2026-01-28 |
|
||||
| `0.21.5` | 2026-01-28 |
|
||||
| `0.20.2` | 2026-01-28 |
|
||||
| `0.19.12` | 2026-01-28 |
|
||||
| `0.18.20` | 2026-01-28 |
|
||||
| `0.17.19` | 2026-01-28 |
|
||||
| `0.16.17` | 2026-01-28 |
|
||||
| `0.15.18` | 2026-01-28 |
|
||||
| `0.14.54` | 2026-01-28 |
|
||||
| `0.13.15` | 2026-01-28 |
|
||||
| `0.12.29` | 2026-01-28 |
|
||||
| `0.11.23` | 2026-01-28 |
|
||||
| `0.10.2` | 2026-01-28 |
|
||||
| `0.9.7` | 2026-01-28 |
|
||||
| `0.9.1` | 2026-01-28 |
|
||||
|
||||
:::
|
||||
|
||||
@ -294,7 +297,7 @@ The final script will be saved to `out.js`
|
||||
7) Start a local web server to host the project folder:
|
||||
|
||||
```bash
|
||||
npx http-server .
|
||||
npx -y http-server .
|
||||
```
|
||||
|
||||
The command will print a list of URLs.
|
||||
|
||||
@ -356,11 +356,12 @@ This demo was tested in the following environments:
|
||||
|
||||
| ViteJS | Date |
|
||||
|:---------|:-----------|
|
||||
| `6.2.3` | 2025-03-30 |
|
||||
| `5.4.15` | 2025-03-30 |
|
||||
| `4.5.10` | 2025-03-30 |
|
||||
| `3.2.11` | 2025-03-30 |
|
||||
| `2.9.18` | 2025-03-30 |
|
||||
| `7.2.2` | 2025-11-15 |
|
||||
| `6.4.1` | 2025-11-15 |
|
||||
| `5.4.21` | 2025-11-15 |
|
||||
| `4.5.14` | 2025-11-15 |
|
||||
| `3.2.11` | 2025-11-15 |
|
||||
| `2.9.18` | 2025-11-15 |
|
||||
|
||||
:::
|
||||
|
||||
@ -376,7 +377,7 @@ major version. For example, `npm create vite@3` will use ViteJS major version 3.
|
||||
:::
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm create vite@5 sheetjs-vite -- --template vue-ts
|
||||
npm create vite@5 sheetjs-vite -- --template vue-ts --no-rolldown --no-interactive
|
||||
cd sheetjs-vite
|
||||
npm i
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
|
||||
@ -430,7 +431,7 @@ Save and refresh the page. A data table should be displayed
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npx http-server dist/
|
||||
npx -y http-server dist/
|
||||
```
|
||||
|
||||
The terminal will display a URL, typically `http://127.0.0.1:8080` . Access
|
||||
@ -506,7 +507,7 @@ Save and refresh the page. A data table should be displayed
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npx http-server dist/
|
||||
npx -y http-server dist/
|
||||
```
|
||||
|
||||
The terminal will display a URL, typically `http://127.0.0.1:8080` . Access
|
||||
@ -594,7 +595,7 @@ const data = utils.sheet_to_json<IPresident>(ws);
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npx http-server dist/
|
||||
npx -y http-server dist/
|
||||
```
|
||||
|
||||
The terminal will display a URL ( `http://127.0.0.1:8080` ). Access that page
|
||||
|
||||
@ -334,7 +334,7 @@ The final site will be placed in the `dist` folder.
|
||||
12) Start a local web server to host the `dist` folder:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
npx -y http-server dist
|
||||
```
|
||||
|
||||
The command will print a list of URLs.
|
||||
|
||||
@ -32,6 +32,7 @@ flowchart LR
|
||||
file --> |.eleventy.js\ncustom parser| buffer
|
||||
buffer --> |.eleventy.js\ncustom parser| aoo
|
||||
aoo --> |index.njk\ntemplate| html
|
||||
linkStyle 1 color:blue,stroke:blue;
|
||||
```
|
||||
|
||||
:::tip No Telemetry
|
||||
@ -114,10 +115,11 @@ accessed using the variable `pres` in a template:
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Eleventy | Date |
|
||||
|:---------|:-----------|
|
||||
| `2.0.1` | 2024-12-23 |
|
||||
| `3.0.0` | 2024-12-23 |
|
||||
| Eleventy | Date |
|
||||
|:----------------|:-----------|
|
||||
| `4.0.0-alpha.6` | 2026-01-28 |
|
||||
| `3.1.2` | 2026-01-28 |
|
||||
| `2.0.1` | 2026-01-28 |
|
||||
|
||||
:::
|
||||
|
||||
@ -212,7 +214,7 @@ Eleventy will place the generated site in the `_site` subfolder.
|
||||
9) Start a web server to host the static site:
|
||||
|
||||
```bash
|
||||
npx http-server _site
|
||||
npx -y http-server _site
|
||||
```
|
||||
|
||||
Open a web browser and access the displayed URL ( `http://localhost:8080` ).
|
||||
|
||||
@ -33,6 +33,9 @@ Content v1 (paired with VueJS 2.x and NuxtJS 2.x)
|
||||
The ["Nuxt Content v2"](#nuxt-content-v2) section explores "transformers" for
|
||||
NuxtJS Content v2 (paired with VueJS 3.x and NuxtJS 3.x)
|
||||
|
||||
The ["Nuxt Content v3"](#nuxt-content-v3) section explores raw ViteJS modules
|
||||
(paired with VueJS 3.x and NuxtJS 3.x)
|
||||
|
||||
:::info pass
|
||||
|
||||
This demo focuses on server-side processing with NuxtJS and VueJS.
|
||||
@ -49,7 +52,8 @@ This demo was tested in the following environments:
|
||||
| Nuxt Content | Nuxt | Date |
|
||||
|:-------------|:-----------|:-----------|
|
||||
| `1.15.1` | `2.18.1` | 2025-04-23 |
|
||||
| `2.13.4` | `3.14.159` | 2024-11-14 |
|
||||
| `2.13.4` | `3.17.2` | 2025-05-12 |
|
||||
| `3.5.1` | `3.17.3` | 2025-05-18 |
|
||||
|
||||
:::
|
||||
|
||||
@ -525,8 +529,8 @@ script files. The module script is expected to export a module configured with
|
||||
- Add the transformer to Nuxt Content in the `content:context` hook
|
||||
|
||||
```js title="sheetmodule.ts (Module)"
|
||||
import { resolve } from 'path'
|
||||
import { defineNuxtModule } from '@nuxt/kit'
|
||||
import { resolve } from 'path';
|
||||
import { defineNuxtModule } from '@nuxt/kit';
|
||||
|
||||
export default defineNuxtModule({
|
||||
/* module setup method */
|
||||
@ -549,7 +553,7 @@ The module must be loaded in `nuxt.config.ts` and added to the `modules` array:
|
||||
|
||||
```ts title="nuxt.config.ts"
|
||||
// highlight-next-line
|
||||
import SheetJSModule from './sheetmodule'
|
||||
import SheetJSModule from './sheetmodule';
|
||||
|
||||
export default defineNuxtConfig({
|
||||
// @ts-ignore
|
||||
@ -606,7 +610,7 @@ from the script setup will be shaped like the return value from the transformer.
|
||||
:::caution pass
|
||||
|
||||
For some older versions, parts of the Nuxt dependency tree did not support
|
||||
NodeJS version 20. If the `yarn install` step fails with a message like
|
||||
NodeJS version 20. If the `pnpm install` step fails with a message like
|
||||
|
||||
```
|
||||
error @nuxt/kit@3.4.1: The engine "node" is incompatible with this module.
|
||||
@ -619,17 +623,18 @@ The recommended solution is to switch to Node 18.
|
||||
1) Create a stock app and install dependencies:
|
||||
|
||||
```bash
|
||||
npx -y nuxi init -t content --packageManager yarn --no-gitInit sheetjs-nc2
|
||||
npx -y nuxi init -t content --packageManager pnpm --no-gitInit sheetjs-nc2 -M ,
|
||||
cd sheetjs-nc2
|
||||
npx -y yarn install
|
||||
npx -y yarn add --dev @types/node
|
||||
npx -y pnpm install
|
||||
npx -y pnpm install @nuxt/content@2 --save
|
||||
npx -y pnpm install @types/node @nuxt/kit --save
|
||||
```
|
||||
|
||||
2) Install the SheetJS library and start the server:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npx -y yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npx -y yarn dev`}
|
||||
npx -y pnpm install --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npx -y pnpm dev`}
|
||||
</CodeBlock>
|
||||
|
||||
|
||||
@ -639,7 +644,7 @@ When the build finishes, the terminal will display a URL like:
|
||||
> Local: http://localhost:3000/
|
||||
```
|
||||
|
||||
The server is listening on that URL. Open the link in a web browser.
|
||||
The server is listening on that URL. Open the link in a web browser.
|
||||
|
||||
3) Download https://docs.sheetjs.com/pres.xlsx and move to the `content` folder.
|
||||
|
||||
@ -649,12 +654,12 @@ curl -L -o content/pres.xlsx https://docs.sheetjs.com/pres.xlsx
|
||||
|
||||
4) Create the transformer. Two files must be saved at the root of the project:
|
||||
|
||||
- [`sheetformer.ts`](https://docs.sheetjs.com/nuxt/3/sheetformer.ts) (raw transformer module)
|
||||
- [`sheetformer.ts`](https://docs.sheetjs.com/nuxt/2/sheetformer.ts) (raw transformer module)
|
||||
- [`sheetmodule.ts`](https://docs.sheetjs.com/nuxt/3/sheetmodule.ts) (Nuxt configuration module)
|
||||
|
||||
```bash
|
||||
curl -O https://docs.sheetjs.com/nuxt/3/sheetformer.ts
|
||||
curl -O https://docs.sheetjs.com/nuxt/3/sheetmodule.ts
|
||||
curl -O https://docs.sheetjs.com/nuxt/2/sheetformer.ts
|
||||
curl -O https://docs.sheetjs.com/nuxt/2/sheetmodule.ts
|
||||
```
|
||||
|
||||
After creating the source files, the module must be added to `nuxt.config.ts`:
|
||||
@ -668,14 +673,13 @@ export default defineNuxtConfig({
|
||||
// @ts-ignore
|
||||
telemetry: false,
|
||||
// highlight-end
|
||||
devtools: { enabled: true },
|
||||
// highlight-start
|
||||
modules: [
|
||||
// highlight-next-line
|
||||
SheetJSModule,
|
||||
'@nuxt/content'
|
||||
],
|
||||
content: {}
|
||||
// highlight-end
|
||||
devtools: { enabled: true },
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
@ -684,33 +688,13 @@ Stop the dev server (<kbd>CTRL</kbd>+<kbd>C</kbd>) and run the following:
|
||||
```bash
|
||||
npx -y nuxi clean
|
||||
npx -y nuxi cleanup
|
||||
npx -y nuxi typecheck
|
||||
npx -y yarn run dev
|
||||
npx -y pnpm run dev
|
||||
```
|
||||
|
||||
Loading `http://localhost:3000/pres` should show some JSON data:
|
||||
|
||||
```json
|
||||
{
|
||||
// ...
|
||||
"data": {
|
||||
"_path": "/pres",
|
||||
// ...
|
||||
"_id": "content:pres.xlsx",
|
||||
"body": [
|
||||
{
|
||||
"name": "Sheet1", // <-- sheet name
|
||||
"data": [ // <-- array of data objects
|
||||
{
|
||||
"Name": "Bill Clinton",
|
||||
"Index": 42
|
||||
},
|
||||
```
|
||||
|
||||
5) Download [`pres.vue`](pathname:///nuxt/3/pres.vue) and save to `pages`:
|
||||
5) Download [`pres.vue`](pathname:///nuxt/2/pres.vue) and save to `app/pages`:
|
||||
|
||||
```bash
|
||||
curl -o pages/pres.vue https://docs.sheetjs.com/nuxt/3/pres.vue
|
||||
curl -o app/pages/pres.vue https://docs.sheetjs.com/nuxt/2/pres.vue
|
||||
```
|
||||
|
||||
Stop the dev server (<kbd>CTRL</kbd>+<kbd>C</kbd>) and run the following:
|
||||
@ -718,24 +702,247 @@ Stop the dev server (<kbd>CTRL</kbd>+<kbd>C</kbd>) and run the following:
|
||||
```bash
|
||||
npx -y nuxi clean
|
||||
npx -y nuxi cleanup
|
||||
npx -y yarn run dev
|
||||
npx -y pnpm run dev
|
||||
```
|
||||
|
||||
The browser should now display an HTML table.
|
||||
6) From the browser window in step 2, access `/pres` from the site. For example,
|
||||
if the URL in step 2 was `http://localhost:3000/`, the new page should be
|
||||
`http://localhost:3000/pres`.
|
||||
|
||||
6) To verify that hot loading works, open `pres.xlsx` from the `content` folder
|
||||
This page should now display an HTML table.
|
||||
|
||||
7) To verify that hot loading works, open `pres.xlsx` from the `content` folder
|
||||
with a spreadsheet editor.
|
||||
|
||||
Set cell `A7` to "SheetJS Dev" and set `B7` to `47`. Save the spreadsheet.
|
||||
|
||||
The page should automatically refresh with the new content.
|
||||
|
||||
8) Stop the server (press <kbd>CTRL</kbd>+<kbd>C</kbd> in the terminal window).
|
||||
|
||||
9) Copy `app/pages/pres.vue` to `app/pages/index.vue`:
|
||||
|
||||
```bash
|
||||
cp app/pages/pres.vue app/pages/index.vue
|
||||
```
|
||||
|
||||
:::info pass
|
||||
|
||||
In older test runs, the Nuxt starter created a default `/` page. The most recent
|
||||
test did not create the index page, resulting in build errors. This step ensures
|
||||
some sort of index page exists.
|
||||
|
||||
:::
|
||||
|
||||
10) Build the static site:
|
||||
|
||||
```bash
|
||||
npx -y pnpm run generate
|
||||
```
|
||||
|
||||
This will create a static site in `.output/public`, which can be served with:
|
||||
|
||||
```bash
|
||||
npx -y http-server .output/public
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) in a web browser.
|
||||
|
||||
To confirm that the spreadsheet data is added to the site, view the page source.
|
||||
|
||||
Searching for `Bill Clinton` reveals the following encoded HTML row:
|
||||
|
||||
```html
|
||||
<tr><td>Bill Clinton</td><td>42</td></tr>
|
||||
```
|
||||
|
||||
## Nuxt Content v3
|
||||
|
||||
:::danger pass
|
||||
|
||||
When this demo was last tested, the official Nuxt Content v3 custom transformers
|
||||
and custom collections examples did not work.
|
||||
|
||||
:::
|
||||
|
||||
[ViteJS modules](/docs/demos/static/vitejs) can be used in Nuxt v3.
|
||||
|
||||
### Installation
|
||||
|
||||
The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be
|
||||
safely imported from `nuxt.config.ts` or transformer or module scripts. As long
|
||||
as the SheetJS modules are not imported in the various `.vue` pages, the library
|
||||
will not be added to the final page bundle!
|
||||
|
||||
### Configuration
|
||||
|
||||
The `vite` property in the NuxtJS config is passed to ViteJS. Plugins and other
|
||||
configuration options can be copied to the object. `vite.config.js` for the
|
||||
[Pure Data Plugin](/docs/demos/static/vitejs#pure-data-plugin) is shown below:
|
||||
|
||||
```js title="vite.config.js (raw ViteJS)"
|
||||
import { readFileSync } from 'fs';
|
||||
import { read, utils } from 'xlsx';
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
export default defineConfig({
|
||||
assetsInclude: ['**/*.xlsx'], // xlsx file should be treated as assets
|
||||
|
||||
plugins: [
|
||||
{ // this plugin handles ?sheetjs tags
|
||||
name: "vite-sheet",
|
||||
transform(_code, id) {
|
||||
if(!id.match(/\?sheetjs$/)) return;
|
||||
var wb = read(readFileSync(id.replace(/\?sheetjs$/, "")));
|
||||
var data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
|
||||
return `export default JSON.parse('${JSON.stringify(data).replace(/\\/g, "\\\\")}')`;
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
The `assetsInclude` and `plugins` properties should be added within the `vite`
|
||||
property in the object passed to `defineNuxtConfig`.
|
||||
|
||||
:::danger pass
|
||||
|
||||
NuxtJS does not properly honor the `?sheetjs` tag! As a result, the transform
|
||||
explicitly tests for the `.xlsx` extension.
|
||||
|
||||
:::
|
||||
|
||||
```ts title="nuxt.config.ts"
|
||||
import { readFileSync } from 'fs';
|
||||
import { read, utils } from 'xlsx';
|
||||
|
||||
export default defineNuxtConfig({
|
||||
// highlight-next-line
|
||||
vite: { // these options are passed to ViteJS
|
||||
assetsInclude: ['**/*.xlsx'], // xlsx file should be treated as assets
|
||||
|
||||
plugins: [
|
||||
{ // this plugin handles .xlsx
|
||||
name: "vite-sheet",
|
||||
transform(_code, id) {
|
||||
if(!id.match(/\.xlsx$/)) return;
|
||||
var wb = read(readFileSync(id.replace(/\?sheetjs$/, "")));
|
||||
var data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
|
||||
return `export default JSON.parse('${JSON.stringify(data).replace(/\\/g, "\\\\")}')`;
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
// ...
|
||||
```
|
||||
|
||||
### Template Use
|
||||
|
||||
Pages can reference spreadsheets using a relative file reference. The ViteJS
|
||||
plugin will transform files with the `.xlsx` extension.
|
||||
|
||||
```js title="Script section of .vue VueJS page"
|
||||
import data from '../../pres.xlsx'; // data is an array of objects
|
||||
```
|
||||
|
||||
In the template, `data` is an array of objects that works with `v-for`[^4]:
|
||||
|
||||
```xml title="Template section of .vue VueJS page"
|
||||
<table>
|
||||
<thead><tr><th>Name</th><th>Index</th></tr></thead><tbody>
|
||||
<!-- loop over the rows of each worksheet -->
|
||||
<tr v-for="row in data" v-bind:key="row.Index">
|
||||
<!-- here `row` is a row object generated from sheet_to_json -->
|
||||
<td>{{ row.Name }}</td>
|
||||
<td>{{ row.Index }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
```
|
||||
|
||||
### Nuxt Content 3 Demo
|
||||
|
||||
1) Create a stock app and install dependencies:
|
||||
|
||||
```bash
|
||||
npx -y nuxi init -t content --packageManager pnpm --no-gitInit sheetjs-nc3 -M ,
|
||||
cd sheetjs-nc3
|
||||
npx -y pnpm install
|
||||
```
|
||||
|
||||
2) Install the SheetJS library and start the server:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npx -y pnpm install --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npx -y pnpm dev`}
|
||||
</CodeBlock>
|
||||
|
||||
When the build finishes, the terminal will display a URL like:
|
||||
|
||||
```
|
||||
> Local: http://localhost:3000/
|
||||
```
|
||||
|
||||
The server is listening on that URL. Open the link in a web browser.
|
||||
|
||||
3) Download https://docs.sheetjs.com/pres.xlsx and move to the root folder:
|
||||
|
||||
```bash
|
||||
curl -o pres.xlsx https://docs.sheetjs.com/pres.xlsx
|
||||
```
|
||||
|
||||
4) Replace `nuxt.config.ts` with the following codeblock:
|
||||
|
||||
```ts title="nuxt.config.ts"
|
||||
import { readFileSync } from 'fs';
|
||||
import { read, utils } from 'xlsx';
|
||||
|
||||
export default defineNuxtConfig({
|
||||
vite: { // these options are passed to ViteJS
|
||||
assetsInclude: ['**/*.xlsx'], // xlsx file should be treated as assets
|
||||
|
||||
plugins: [
|
||||
{ // this plugin handles .xlsx
|
||||
name: "vite-sheet",
|
||||
transform(_code, id) {
|
||||
if(!id.match(/\.xlsx$/)) return;
|
||||
var wb = read(readFileSync(id.replace(/\?sheetjs$/, "")));
|
||||
var data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
|
||||
return `export default JSON.parse('${JSON.stringify(data).replace(/\\/g, "\\\\")}')`;
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
modules: [
|
||||
'@nuxt/content',
|
||||
],
|
||||
devtools: { enabled: true },
|
||||
});
|
||||
```
|
||||
|
||||
5) Create a new file `app.vue` with the following contents:
|
||||
|
||||
```html title="app.vue (create new file)"
|
||||
<script setup>
|
||||
import data from '../../pres.xlsx'
|
||||
</script>
|
||||
<template>
|
||||
<table><thead><tr><th>Name</th><th>Index</th></tr></thead><tbody>
|
||||
<tr v-for="row in data" v-bind:key="row.Index">
|
||||
<td>{{ row.Name }}</td>
|
||||
<td>{{ row.Index }}</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</template>
|
||||
```
|
||||
|
||||
6) Refresh the browser window. This page should now display an HTML table.
|
||||
|
||||
7) Stop the server (press <kbd>CTRL</kbd>+<kbd>C</kbd> in the terminal window).
|
||||
|
||||
8) Build the static site:
|
||||
|
||||
```bash
|
||||
npx -y yarn run generate
|
||||
npx -y pnpm run generate
|
||||
```
|
||||
|
||||
This will create a static site in `.output/public`, which can be served with:
|
||||
|
||||
@ -345,7 +345,7 @@ AstroJS will place the generated site in the `dist` subfolder.
|
||||
9) Start a web server to host the static site:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
npx -y http-server dist
|
||||
```
|
||||
|
||||
Open a web browser and access the displayed URL ( `http://localhost:8080` ).
|
||||
|
||||
@ -241,8 +241,8 @@ This demo was tested in the following environments:
|
||||
|:-----------|:--------------------|:---------|:-------------|:-----------|
|
||||
| Android 34 | Pixel 3a | `0.76.8` | `darwin-arm` | 2025-03-26 |
|
||||
| iOS 18.3 | iPhone 16 Pro | `0.76.8` | `darwin-arm` | 2025-03-26 |
|
||||
| Android 35 | Pixel 9 | `0.76.5` | `win11-x64` | 2024-12-22 |
|
||||
| Android 35 | Pixel 9 | `0.76.5` | `linux-x64` | 2025-01-02 |
|
||||
| Android 35 | Pixel 9 Pro XL | `0.79.2` | `win11-x64` | 2025-06-08 |
|
||||
| Android 36 | Pixel 9 | `0.79.2` | `linux-x64` | 2025-07-06 |
|
||||
|
||||
:::
|
||||
|
||||
@ -259,12 +259,22 @@ Make sure you can run a basic test app on your phone/simulator before continuing
|
||||
<details>
|
||||
<summary><b>Installation Notes</b> (click to show)</summary>
|
||||
|
||||
**Java JDK**
|
||||
|
||||
On the Steam Deck, JDK17 was installed using `pacman`:
|
||||
|
||||
```bash
|
||||
sudo pacman -Syu jdk17-openjdk
|
||||
```
|
||||
|
||||
Debian and Ubuntu require the `openjdk-17-jdk` package:
|
||||
|
||||
```bash
|
||||
sudo apt install openjdk-17-jdk
|
||||
```
|
||||
|
||||
**Android Studio for Linux**
|
||||
|
||||
[The Android Studio tarball](https://developer.android.com/studio) was
|
||||
downloaded and extracted. After extracting:
|
||||
|
||||
@ -276,6 +286,8 @@ cd ./android-studio/bin
|
||||
In Android Studio, select "SDK Manager" and switch to the "SDK Tools" tab. Check
|
||||
"Show Package Details" and install "Android SDK Command-line Tools (latest)".
|
||||
|
||||
**Environment Variables for Linux**
|
||||
|
||||
When this demo was last tested, the following environment variables were used:
|
||||
|
||||
```bash
|
||||
@ -289,7 +301,7 @@ export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
|
||||
1) Create project:
|
||||
|
||||
```bash
|
||||
npx -y @react-native-community/cli@15 init SheetJSRNFetch --version="0.76.8"
|
||||
npx -y @react-native-community/cli@18 init SheetJSRNFetch --version="0.79.2"
|
||||
```
|
||||
|
||||
On macOS, if prompted to install `CocoaPods`, press <kbd>Y</kbd>
|
||||
@ -330,12 +342,47 @@ npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npm i -S https://cdn.sheetjs.com/react-native-tabeller-0.1.0/react-native-tabeller-0.1.0.tgz`}
|
||||
</CodeBlock>
|
||||
|
||||
:::note pass
|
||||
|
||||
In PowerShell, the command may fail with a parameter error:
|
||||
|
||||
```
|
||||
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
|
||||
```
|
||||
|
||||
`curl.exe` must be invoked directly:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
cd SheetJSRNFetch
|
||||
curl.exe -LO https://docs.sheetjs.com/logo.png
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npm i -S https://cdn.sheetjs.com/react-native-tabeller-0.1.0/react-native-tabeller-0.1.0.tgz`}
|
||||
</CodeBlock>
|
||||
|
||||
:::
|
||||
|
||||
3) Download and replace [`App.tsx`](pathname:///reactnative/App.tsx):
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/reactnative/App.tsx
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
In PowerShell, the command may fail with a parameter error:
|
||||
|
||||
```
|
||||
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
|
||||
```
|
||||
|
||||
`curl.exe` must be invoked directly:
|
||||
|
||||
```bash
|
||||
curl.exe -LO https://docs.sheetjs.com/reactnative/App.tsx
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
**Android Testing**
|
||||
|
||||
4) Install or switch to Java 17[^7]
|
||||
@ -355,8 +402,8 @@ the interactive CLI tool:
|
||||
npx react-native start
|
||||
```
|
||||
|
||||
Once the dev server is ready, the terminal will display a few options. Press `a`
|
||||
to run on Android.
|
||||
Once the dev server is ready, the terminal will display a few options. Press
|
||||
<kbd>r</kbd> to relaod the app.
|
||||
|
||||
:::
|
||||
|
||||
@ -578,7 +625,7 @@ reconnect the device before trying again.
|
||||
|
||||
:::info pass
|
||||
|
||||
In some test runs, the app requested for local network access:
|
||||
In some test runs, the app requested for local network access:
|
||||
|
||||
> "SheetJSRNFetch" would like to find and connect to devices on your local network.
|
||||
|
||||
@ -1096,8 +1143,8 @@ This demo was tested in the following environments:
|
||||
|:-----------|:------------------|:---------|:-------------|:-----------|
|
||||
| Android 34 | Pixel 3a | `0.76.5` | `darwin-arm` | 2025-01-05 |
|
||||
| iOS 18.2 | iPhone 16 Pro | `0.76.5` | `darwin-arm` | 2025-01-05 |
|
||||
| Android 35 | Pixel 9 | `0.76.5` | `win11-x64` | 2024-12-22 |
|
||||
| Android 35 | Pixel 9 | `0.76.5` | `linux-x64` | 2025-01-02 |
|
||||
| Android 35 | Pixel 9 Pro XL | `0.76.5` | `win11-x64` | 2025-06-08 |
|
||||
| Android 36 | Pixel 9 | `0.76.5` | `linux-x64` | 2025-07-06 |
|
||||
|
||||
:::
|
||||
|
||||
@ -1128,15 +1175,50 @@ On macOS, if prompted to install `CocoaPods`, press <kbd>Y</kbd>
|
||||
cd SheetJSRN
|
||||
curl -LO https://docs.sheetjs.com/logo.png
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npm i -S react-native-table-component@1.2.2 react-native-document-picker@9.3.1`}
|
||||
npm i -S https://cdn.sheetjs.com/react-native-tabeller-0.1.0/react-native-tabeller-0.1.0.tgz react-native-document-picker@9.3.1`}
|
||||
</CodeBlock>
|
||||
|
||||
:::note pass
|
||||
|
||||
In PowerShell, the command may fail with a parameter error:
|
||||
|
||||
```
|
||||
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
|
||||
```
|
||||
|
||||
`curl.exe` must be invoked directly:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
cd SheetJSRN
|
||||
curl.exe -LO https://docs.sheetjs.com/logo.png
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npm i -S https://cdn.sheetjs.com/react-native-tabeller-0.1.0/react-native-tabeller-0.1.0.tgz react-native-document-picker@9.3.1`}
|
||||
</CodeBlock>
|
||||
|
||||
:::
|
||||
|
||||
3) Download [`index.js`](pathname:///mobile/index.js) and replace:
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/mobile/index.js
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
In PowerShell, the command may fail with a parameter error:
|
||||
|
||||
```
|
||||
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
|
||||
```
|
||||
|
||||
`curl.exe` must be invoked directly:
|
||||
|
||||
```bash
|
||||
curl.exe -LO https://docs.sheetjs.com/mobile/index.js
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
4) Start the Android emulator:
|
||||
|
||||
```bash
|
||||
@ -1147,6 +1229,20 @@ The app should look like the following screenshot:
|
||||
|
||||

|
||||
|
||||
:::info pass
|
||||
|
||||
On Linux, the command may silently stall. It is strongly recommended to launch
|
||||
the interactive CLI tool:
|
||||
|
||||
```bash
|
||||
npx react-native start
|
||||
```
|
||||
|
||||
Once the dev server is ready, the terminal will display a few options. Press
|
||||
<kbd>r</kbd> to relaod the app.
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
|
||||
In some test runs on Windows, the build failed with an error:
|
||||
@ -1192,13 +1288,13 @@ Stop the dev server and close the React Native Metro NodeJS window.
|
||||
Install `react-native-blob-util` dependency:
|
||||
|
||||
```bash
|
||||
npm i -S react-native-blob-util@0.21.2
|
||||
npm i -S react-native-blob-util@0.22.2
|
||||
```
|
||||
|
||||
Add the highlighted lines to `index.js`:
|
||||
|
||||
```js title="index.js"
|
||||
import { Table, Row, Rows, TableWrapper } from 'react-native-table-component';
|
||||
```js title="index.js (add highlighted lines)"
|
||||
import { Table, Row, Rows, TableWrapper } from 'react-native-tabeller';
|
||||
|
||||
// highlight-start
|
||||
import { read, write } from 'xlsx';
|
||||
@ -1246,7 +1342,7 @@ npm i -S react-native-file-access@3.1.1
|
||||
Add the highlighted lines to `index.js`:
|
||||
|
||||
```js title="index.js"
|
||||
import { Table, Row, Rows, TableWrapper } from 'react-native-table-component';
|
||||
import { Table, Row, Rows, TableWrapper } from 'react-native-tabeller';
|
||||
|
||||
// highlight-start
|
||||
import { read, write } from 'xlsx';
|
||||
@ -1313,7 +1409,7 @@ These errors can be ignored.
|
||||
Add the highlighted lines to `index.js`:
|
||||
|
||||
```js title="index.js"
|
||||
import { Table, Row, Rows, TableWrapper } from 'react-native-table-component';
|
||||
import { Table, Row, Rows, TableWrapper } from 'react-native-tabeller';
|
||||
|
||||
// highlight-start
|
||||
import { read, write } from 'xlsx';
|
||||
@ -1687,7 +1783,7 @@ The Numbers app will load the spreadsheet, confirming that the file is valid.
|
||||
[^3]: See ["Array Output" in "Utility Functions"](/docs/api/utilities/array#array-output)
|
||||
[^4]: See ["Array of Arrays Input" in "Utility Functions"](/docs/api/utilities/array#array-of-arrays-input)
|
||||
[^5]: React-Native commit [`5b597b5`](https://github.com/facebook/react-native/commit/5b597b5ff94953accc635ed3090186baeecb3873) added the final piece required for `fetch` support. It is available in official releases starting from `0.72.0`.
|
||||
[^6]: See [the compatibility table](https://github.com/react-native-community/cli) in the CLI project repository to determine which version of `@react-native-community/cli` is required for a given `react-native` version.
|
||||
[^6]: See [the compatibility table](https://github.com/react-native-community/cli/blob/main/README.md#compatibility) in the CLI project repository to determine which version of `@react-native-community/cli` is required for a given `react-native` version.
|
||||
[^7]: When the demo was last tested, the Temurin distribution of Java 17 was installed through the macOS Brew package manager by running `brew install temurin17`. [Direct downloads are available at `adoptium.net`](https://adoptium.net/temurin/releases/?version=17)
|
||||
[^8]: See ["Running On Device"](https://reactnative.dev/docs/running-on-device) in the React Native documentation
|
||||
[^9]: See [`UIFileSharingEnabled`](https://developer.apple.com/documentation/bundleresources/information_property_list/uifilesharingenabled) in the Apple Developer Documentation.
|
||||
|
||||
@ -56,17 +56,17 @@ This demo was tested in the following environments:
|
||||
|
||||
| OS | Device | NS | Date |
|
||||
|:-----------|:--------------------|:---------|:-----------|
|
||||
| Android 30 | NVIDIA Shield | `8.7.2` | 2024-06-09 |
|
||||
| iOS 15.1 | iPad Pro | `8.7.2` | 2024-06-09 |
|
||||
| Android 30 | NVIDIA Shield | `8.9.2` | 2025-05-06 |
|
||||
| iOS 15.1 | iPad Pro | `8.9.2` | 2025-05-06 |
|
||||
|
||||
**Simulators**
|
||||
|
||||
| OS | Device | NS | Dev Platform | Date |
|
||||
|:-----------|:--------------------|:---------|:-------------|:-----------|
|
||||
| Android 34 | Pixel 3a | `8.7.2` | `darwin-arm` | 2024-06-09 |
|
||||
| iOS 17.5 | iPhone SE (3rd gen) | `8.7.2` | `darwin-arm` | 2024-06-09 |
|
||||
| Android 35 | Pixel 9 | `8.8.3` | `win11-x64` | 2024-12-21 |
|
||||
| Android 35 | Pixel 9 | `8.8.3` | `linux-x64` | 2025-01-02 |
|
||||
| Android 35 | Pixel 9 Pro XL | `8.9.2` | `darwin-x64` | 2025-05-06 |
|
||||
| iOS 18.4 | iPhone 16 Pro Max | `8.9.2` | `darwin-x64` | 2025-05-06 |
|
||||
| Android 35 | Pixel 9 | `8.9.2` | `win11-x64` | 2025-06-08 |
|
||||
| Android 36 | Pixel 9 | `8.9.2` | `linux-x64` | 2025-07-06 |
|
||||
|
||||
:::
|
||||
|
||||
@ -78,15 +78,15 @@ NativeScript 8.6.1 split the telemetry into two parts: "usage" and "error". Both
|
||||
must be disabled separately:
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns usage-reporting disable
|
||||
npx -p nativescript ns error-reporting disable
|
||||
npx -y -p nativescript ns usage-reporting disable
|
||||
npx -y -p nativescript ns error-reporting disable
|
||||
```
|
||||
|
||||
To verify telemetry was disabled:
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns usage-reporting status
|
||||
npx -p nativescript ns error-reporting status
|
||||
npx -y -p nativescript ns usage-reporting status
|
||||
npx -y -p nativescript ns error-reporting status
|
||||
```
|
||||
|
||||
:::
|
||||
@ -120,6 +120,22 @@ for accessing data and are subject to change in future platform versions.
|
||||
<details>
|
||||
<summary><b>Technical Details</b> (click to show)</summary>
|
||||
|
||||
**iOS**
|
||||
|
||||
The following key/value pairs must be added to `Info.plist`:
|
||||
|
||||
```xml title="App_Resources/iOS/Info.plist (add highlighted lines)"
|
||||
<dict>
|
||||
<!-- highlight-start -->
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||
<true/>
|
||||
<!-- highlight-end -->
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Android**
|
||||
|
||||
Android security has evolved over the years. In newer Android versions, the
|
||||
@ -265,8 +281,8 @@ const wb = read(ab);
|
||||
0) Disable telemetry:
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns usage-reporting disable
|
||||
npx -p nativescript ns error-reporting disable
|
||||
npx -y -p nativescript ns usage-reporting disable
|
||||
npx -y -p nativescript ns error-reporting disable
|
||||
```
|
||||
|
||||
1) Follow the official Environment Setup instructions[^8].
|
||||
@ -274,14 +290,14 @@ npx -p nativescript ns error-reporting disable
|
||||
:::caution pass
|
||||
|
||||
In previous test runs, NativeScript did not support the latest Android API.
|
||||
The error message from `npx -p nativescript ns doctor android` clearly stated
|
||||
The error message from `npx -y -p nativescript ns doctor android` clearly stated
|
||||
supported versions:
|
||||
|
||||
<pre>
|
||||
<span {...r}>✖</span> No compatible version of the Android SDK Build-tools are installed on your system. You can install any version in the following range: '>=23 <=33'.
|
||||
</pre>
|
||||
|
||||
If NativeScript does not properly supports the latest API level, a previous API
|
||||
If NativeScript does not properly support the latest API level, an older API
|
||||
version should be installed using Android Studio.
|
||||
|
||||
In a previous test run, the following packages were required:
|
||||
@ -290,14 +306,14 @@ In a previous test run, the following packages were required:
|
||||
- `Android SDK Build-Tools` Version `33.0.2`
|
||||
|
||||
It is recommended to install the SDK Platform and corresponding Android SDK
|
||||
Build-Tools for the latest supported API level.ß
|
||||
Build-Tools for the latest supported API level.
|
||||
|
||||
:::
|
||||
|
||||
2) Test the local system configuration for Android development:
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns doctor android
|
||||
npx -y -p nativescript ns doctor android
|
||||
```
|
||||
|
||||
In the last macOS test, the following output was displayed:
|
||||
@ -316,7 +332,7 @@ In the last macOS test, the following output was displayed:
|
||||
<span {...g}>✔</span> Javac is installed and is configured properly.
|
||||
<span {...g}>✔</span> The Java Development Kit (JDK) is installed and is configured properly.
|
||||
<span {...g}>✔</span> Getting NativeScript components versions information...
|
||||
<span {...g}>✔</span> Component nativescript has 8.7.2 version and is up to date.
|
||||
<span {...g}>✔</span> Component nativescript has 8.9.2 version and is up to date.
|
||||
</pre>
|
||||
|
||||
</details>
|
||||
@ -324,7 +340,7 @@ In the last macOS test, the following output was displayed:
|
||||
3) Test the local system configuration for iOS development (macOS only):
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns doctor ios
|
||||
npx -y -p nativescript ns doctor ios
|
||||
```
|
||||
|
||||
In the last macOS test, the following output was displayed:
|
||||
@ -343,9 +359,9 @@ In the last macOS test, the following output was displayed:
|
||||
<span {...g}>✔</span> CocoaPods are configured properly.
|
||||
<span {...g}>✔</span> Your current CocoaPods version is newer than 1.0.0.
|
||||
<span {...g}>✔</span> Python installed and configured correctly.
|
||||
<span {...g}>✔</span> Xcode version 15.4.0 satisfies minimum required version 10.
|
||||
<span {...g}>✔</span> Xcode version 16.3.0 satisfies minimum required version 10.
|
||||
<span {...g}>✔</span> Getting NativeScript components versions information...
|
||||
<span {...g}>✔</span> Component nativescript has 8.7.2 version and is up to date.
|
||||
<span {...g}>✔</span> Component nativescript has 8.9.2 version and is up to date.
|
||||
</pre>
|
||||
|
||||
</details>
|
||||
@ -355,21 +371,21 @@ In the last macOS test, the following output was displayed:
|
||||
4) Create a skeleton NativeScript + Angular app:
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns create SheetJSNS --ng
|
||||
npx -y -p nativescript ns create SheetJSNS --ng
|
||||
```
|
||||
|
||||
5) Launch the app in the android simulator to verify the app:
|
||||
5) Launch the app in the Android simulator to verify the app:
|
||||
|
||||
```bash
|
||||
cd SheetJSNS
|
||||
npx -p nativescript ns run android
|
||||
npx -y -p nativescript ns run android
|
||||
```
|
||||
|
||||
(this may take a while)
|
||||
|
||||
Once the simulator launches and the test app is displayed, end the script by
|
||||
selecting the terminal and pressing <kbd>CTRL</kbd>+<kbd>C</kbd>. On Windows, if
|
||||
prompted to `Terminate batch job`, type `y` and press Enter.
|
||||
prompted to `Terminate batch job`, type <kbd>Y</kbd> and press Enter.
|
||||
|
||||
:::note pass
|
||||
|
||||
@ -381,6 +397,23 @@ Emulator start failed with: No emulator image available for device identifier 'u
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
|
||||
In the most recent test, the build failed with an exception:
|
||||
|
||||
```
|
||||
WARNING: A restricted method in java.lang.System has been called
|
||||
WARNING: java.lang.System::load has been called by net.rubygrapefruit.platform.internal.NativeLibraryLoader in an unnamed module (file:/Users/sheetjs/.gradle/wrapper/dists/gradle-8.7-bin/bhs2wmbdwecv87pi65oeuq5iu/gradle-8.7/lib/native-platform-0.22-milestone-25.jar)
|
||||
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
|
||||
WARNING: Restricted methods will be blocked in a future release unless native access is enabled
|
||||
```
|
||||
|
||||
**The NativeScript Gradle version is incompatible with Java 24!**
|
||||
|
||||
It is strongly recommended to roll back to Java 21.
|
||||
|
||||
:::
|
||||
|
||||
### Add SheetJS
|
||||
|
||||
:::note pass
|
||||
@ -401,16 +434,15 @@ SheetJS version string and adds it to a `version` variable in the component:
|
||||
```ts title="src/app/item/items.component.ts (add highlighted lines)"
|
||||
// highlight-next-line
|
||||
import { version } from 'xlsx';
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
import { Component, NO_ERRORS_SCHEMA, inject } from '@angular/core'
|
||||
|
||||
// ...
|
||||
|
||||
export class ItemsComponent implements OnInit {
|
||||
items: Array<Item>
|
||||
export class ItemsComponent {
|
||||
// highlight-next-line
|
||||
version = `SheetJS - ${version}`;
|
||||
|
||||
constructor(private itemService: ItemService) {}
|
||||
itemService = inject(ItemService)
|
||||
page = inject(Page)
|
||||
// ...
|
||||
```
|
||||
|
||||
@ -428,7 +460,7 @@ in the title of the action bar:
|
||||
9) End the script and relaunch the app in the Android simulator:
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns run android
|
||||
npx -y -p nativescript ns run android
|
||||
```
|
||||
|
||||
The title bar should show the version.
|
||||
@ -449,7 +481,7 @@ The title bar should show the version.
|
||||
<Button text="Export File" (tap)="export()" style="padding: 10px"></Button>
|
||||
</StackLayout>
|
||||
<!-- highlight-end -->
|
||||
<ListView [items]="items">
|
||||
<ListView [items]="itemService.items()">
|
||||
<!-- ... -->
|
||||
</ListView>
|
||||
<!-- highlight-next-line -->
|
||||
@ -458,15 +490,15 @@ The title bar should show the version.
|
||||
|
||||
11) Add the `import` and `export` methods in the component script:
|
||||
|
||||
```ts title="src/app/item/items.component.ts"
|
||||
```ts title="src/app/item/items.component.ts (add highlighted lines)"
|
||||
// highlight-start
|
||||
import { version, utils, read, write } from 'xlsx';
|
||||
import { Dialogs, getFileAccess } from '@nativescript/core';
|
||||
import { Folder, knownFolders, path } from '@nativescript/core/file-system';
|
||||
// highlight-end
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
|
||||
import { Item } from './item'
|
||||
import { Component, NO_ERRORS_SCHEMA, inject } from '@angular/core'
|
||||
import { NativeScriptCommonModule, NativeScriptRouterModule } from '@nativescript/angular'
|
||||
import { Page } from '@nativescript/core'
|
||||
import { ItemService } from './item.service'
|
||||
|
||||
// highlight-start
|
||||
@ -476,19 +508,12 @@ function get_url_for_filename(filename: string): string {
|
||||
}
|
||||
// highlight-end
|
||||
|
||||
@Component({
|
||||
selector: 'ns-items',
|
||||
templateUrl: './items.component.html',
|
||||
})
|
||||
export class ItemsComponent implements OnInit {
|
||||
items: Array<Item>
|
||||
version: string = `SheetJS - ${version}`;
|
||||
// ...
|
||||
|
||||
constructor(private itemService: ItemService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.items = this.itemService.getItems()
|
||||
}
|
||||
export class ItemsComponent {
|
||||
version = `SheetJS - ${version}`;
|
||||
itemService = inject(ItemService)
|
||||
page = inject(Page)
|
||||
|
||||
// highlight-start
|
||||
/* Import button */
|
||||
@ -499,13 +524,14 @@ export class ItemsComponent implements OnInit {
|
||||
async export() {
|
||||
}
|
||||
// highlight-end
|
||||
}
|
||||
|
||||
// ...
|
||||
```
|
||||
|
||||
12) End the script and relaunch the app in the Android simulator:
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns run android
|
||||
npx -y -p nativescript ns run android
|
||||
```
|
||||
|
||||
Two buttons should appear just below the header:
|
||||
@ -534,7 +560,7 @@ Two buttons should appear just below the header:
|
||||
const ws = wb.Sheets[wsname];
|
||||
|
||||
/* update table */
|
||||
this.items = utils.sheet_to_json<Item>(ws);
|
||||
this.itemService.items.set(utils.sheet_to_json(ws));
|
||||
} catch(e) { await Dialogs.alert(e.message); }
|
||||
// highlight-end
|
||||
}
|
||||
@ -547,7 +573,7 @@ Two buttons should appear just below the header:
|
||||
|
||||
try {
|
||||
/* create worksheet from data */
|
||||
const ws = utils.json_to_sheet(this.items);
|
||||
const ws = utils.json_to_sheet(this.itemService.items());
|
||||
|
||||
/* create workbook from worksheet */
|
||||
const wb = utils.book_new();
|
||||
@ -569,7 +595,7 @@ Two buttons should appear just below the header:
|
||||
14) Launch the app in the Android Simulator:
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns run android
|
||||
npx -y -p nativescript ns run android
|
||||
```
|
||||
|
||||
If the app does not automatically launch, manually open the `SheetJSNS` app.
|
||||
@ -585,7 +611,7 @@ adb root
|
||||
adb pull /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls SheetJSNS.xls
|
||||
```
|
||||
|
||||
If the emulator cannot be rooted, the following command works in macOS:
|
||||
If the emulator cannot be rooted, the following workaround should be used:
|
||||
|
||||
```bash
|
||||
adb shell "run-as org.nativescript.SheetJSNS cat /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls" > SheetJSNS.xls
|
||||
@ -611,8 +637,8 @@ $bytes = [Convert]::FromBase64String($b64)
|
||||
After the header row, insert a row and make the following assignments:
|
||||
|
||||
- Set cell `A2` to `0`
|
||||
- Set cell `B2` to `SheetJS` (type `'SheetJS` in the formula bar)
|
||||
- Set cell `C2` to `Library` (type `'Library` in the formula bar)
|
||||
- Set cell `B2` to `SheetJS` (type `'SheetJS` in the formula bar)
|
||||
- Set cell `C2` to `Library` (type `'Library` in the formula bar)
|
||||
|
||||
After making the changes, the worksheet should look like the following:
|
||||
|
||||
@ -620,8 +646,6 @@ After making the changes, the worksheet should look like the following:
|
||||
id | name | role
|
||||
# highlight-next-line
|
||||
0 | SheetJS | Library
|
||||
1 | Ter Stegen | Goalkeeper
|
||||
3 | Piqué | Defender
|
||||
...
|
||||
```
|
||||
|
||||
@ -631,7 +655,7 @@ id | name | role
|
||||
adb push SheetJSNS.xls /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls
|
||||
```
|
||||
|
||||
If the emulator cannot be rooted, the following command works in macOS:
|
||||
If the emulator cannot be rooted, raw byte operations work in macOS and Linux:
|
||||
|
||||
```bash
|
||||
dd if=SheetJSNS.xls | adb shell "run-as org.nativescript.SheetJSNS dd of=/data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls"
|
||||
@ -671,7 +695,7 @@ Scroll down to ["Fetching Files"](#android-device) for Android device testing.
|
||||
20) Launch the app in the iOS Simulator:
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns run ios
|
||||
npx -y -p nativescript ns run ios
|
||||
```
|
||||
|
||||
21) Tap "Export File". A dialog will print where the file was written.
|
||||
@ -681,8 +705,8 @@ npx -p nativescript ns run ios
|
||||
After the header row, insert a row and make the following assignments:
|
||||
|
||||
- Set cell `A2` to `0`
|
||||
- Set cell `B2` to `SheetJS` (type `'SheetJS` in the formula bar)
|
||||
- Set cell `C2` to `Library` (type `'Library` in the formula bar)
|
||||
- Set cell `B2` to `SheetJS` (type `'SheetJS` in the formula bar)
|
||||
- Set cell `C2` to `Library` (type `'Library` in the formula bar)
|
||||
|
||||
After making the changes, the worksheet should look like the following:
|
||||
|
||||
@ -690,8 +714,6 @@ After making the changes, the worksheet should look like the following:
|
||||
id | name | role
|
||||
# highlight-next-line
|
||||
0 | SheetJS | Library
|
||||
1 | Ter Stegen | Goalkeeper
|
||||
3 | Piqué | Defender
|
||||
...
|
||||
```
|
||||
|
||||
@ -704,31 +726,21 @@ The first item in the list will change:
|
||||
|
||||
### Fetching Files
|
||||
|
||||
25) In `src/app/item/items.component.ts`, make `ngOnInit` asynchronous:
|
||||
|
||||
```ts title="src/app/item/items.component.ts (replace existing function)"
|
||||
async ngOnInit(): Promise<void> {
|
||||
this.items = await this.itemService.getItems()
|
||||
}
|
||||
```
|
||||
|
||||
26) Replace `item.service.ts` with the following:
|
||||
25) Replace `item.service.ts` with the following:
|
||||
|
||||
```ts title="src/app/item/item.service.ts"
|
||||
import { Injectable } from '@angular/core'
|
||||
|
||||
import { knownFolders, path, getFileAccess } from '@nativescript/core'
|
||||
import { getFile } from '@nativescript/core/http';
|
||||
import { read, utils } from 'xlsx';
|
||||
|
||||
import { Injectable, signal, effect } from '@angular/core'
|
||||
import { knownFolders, path, getFileAccess } from '@nativescript/core';
|
||||
import { getFile } from '@nativescript/core/http';
|
||||
import { Item } from './item'
|
||||
|
||||
interface IPresident { Name: string; Index: number };
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ItemService {
|
||||
private items: Array<Item>;
|
||||
|
||||
async getItems(): Promise<Array<Item>> {
|
||||
items = signal<Item[]>([]);
|
||||
constructor() { effect(() => { (async() => {
|
||||
/* fetch https://docs.sheetjs.com/pres.xlsx */
|
||||
const temp: string = path.join(knownFolders.temp().path, "pres.xlsx");
|
||||
const ab = await getFile("https://docs.sheetjs.com/pres.xlsx", temp)
|
||||
@ -736,32 +748,33 @@ export class ItemService {
|
||||
const wb = read(await getFileAccess().readBufferAsync(ab.path));
|
||||
/* translate the first worksheet to the required Item type */
|
||||
const data = utils.sheet_to_json<IPresident>(wb.Sheets[wb.SheetNames[0]]);
|
||||
return this.items = data.map((pres, id) => ({id, name: pres.Name, role: ""+pres.Index} as Item));
|
||||
}
|
||||
/* update state */
|
||||
this.items.set(data.map((pres, id) => ({id, name: pres.Name, role: ""+pres.Index} as Item)));
|
||||
})(); }); }
|
||||
|
||||
getItem(id: number): Item {
|
||||
return this.items.filter((item) => item.id === id)[0]
|
||||
return this.items().find((item) => item.id === id)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
27) End the script and relaunch the app in the Android simulator:
|
||||
26) End the script and relaunch the app in the Android simulator:
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns run android
|
||||
npx -y -p nativescript ns run android
|
||||
```
|
||||
|
||||
The app should show Presidential data.
|
||||
|
||||
### Android Device
|
||||
|
||||
28) Connect an Android device using a USB cable.
|
||||
27) Connect an Android device using a USB cable.
|
||||
|
||||
If the device asks to allow USB debugging, tap "Allow".
|
||||
|
||||
29) Close any Android / iOS emulators.
|
||||
28) Close any Android / iOS emulators.
|
||||
|
||||
30) Enable "Legacy External Storage" in the Android app. The manifest is stored
|
||||
29) Enable "Legacy External Storage" in the Android app. The manifest is stored
|
||||
at `App_Resources/Android/src/main/AndroidManifest.xml`:
|
||||
|
||||
```xml title="App_Resources/Android/src/main/AndroidManifest.xml (add highlighted line)"
|
||||
@ -776,13 +789,13 @@ at `App_Resources/Android/src/main/AndroidManifest.xml`:
|
||||
android:hardwareAccelerated="true">
|
||||
```
|
||||
|
||||
31) Install the `@nativescript-community/perms` dependency:
|
||||
30) Install the `@nativescript-community/perms` dependency:
|
||||
|
||||
```bash
|
||||
npm i --save @nativescript-community/perms
|
||||
```
|
||||
|
||||
32) Add the highlighted lines to `items.component.ts`:
|
||||
31) Add the highlighted lines to `items.component.ts`:
|
||||
|
||||
- Import `File` from NativeScript core and `request` from the new dependency:
|
||||
|
||||
@ -815,10 +828,10 @@ import { Component, OnInit } from '@angular/core'
|
||||
} catch(e) { await Dialogs.alert(e.message); }
|
||||
```
|
||||
|
||||
33) Build APK and run on device:
|
||||
32) Build APK and run on device:
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns run android
|
||||
npx -y -p nativescript ns run android
|
||||
```
|
||||
|
||||
If the Android emulators are closed and an Android device is connected, the last
|
||||
@ -839,22 +852,59 @@ file named `SheetJSNS.xls`.
|
||||
|
||||
### iOS Device
|
||||
|
||||
34) Connect an iOS device using a USB cable
|
||||
33) Connect an iOS device using a USB cable
|
||||
|
||||
35) Close any Android / iOS emulators.
|
||||
34) Close any Android / iOS emulators.
|
||||
|
||||
36) Enable developer code signing certificates:
|
||||
35) Enable developer code signing certificates:
|
||||
|
||||
Open `platforms/ios/SheetJSNS.xcodeproj/project.xcworkspace` in Xcode. Select
|
||||
the "Project Navigator" and select the "App" project. In the main view, select
|
||||
"Signing & Capabilities". Under "Signing", select a team in the dropdown menu.
|
||||
the "Project Navigator" and select `SheetJSNS`. In the main view, select the
|
||||
`SheetJSNS` target. Click "Signing & Capabilities". Under "Signing", select a
|
||||
team in the dropdown menu.
|
||||
|
||||
:::caution pass
|
||||
|
||||
When this demo was last tested, Xcode repeatedly crashed.
|
||||
|
||||
The issue was resolved by cleaning the project:
|
||||
|
||||
```bash
|
||||
npx -y -p nativescript ns platform clean ios
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
36) Add the following key/value pairs to `Info.plist`:
|
||||
|
||||
```xml title="App_Resources/iOS/Info.plist (add highlighted lines)"
|
||||
<dict>
|
||||
<!-- highlight-start -->
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||
<true/>
|
||||
<!-- highlight-end -->
|
||||
```
|
||||
|
||||
37) Run on device:
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns run ios
|
||||
npx -y -p nativescript ns run ios
|
||||
```
|
||||
|
||||
:::info pass
|
||||
|
||||
If this is the first time testing an app on a device, the certificate must be
|
||||
trusted on the device:
|
||||
|
||||
Under "Settings" > "General" > "VPN & Device Management", there should be a
|
||||
"Apple Development" certificate in the "DEVELOPER APP" section. Select the
|
||||
certificate and confirm that "SheetJSNS" is listed under "APPS". Tap "Trust ..."
|
||||
and tap "Trust" in the popup.
|
||||
|
||||
:::
|
||||
|
||||
<details open>
|
||||
<summary><b>iOS Device Testing</b> (click to hide)</summary>
|
||||
|
||||
@ -863,8 +913,9 @@ connected to the Internet, a list of Presidents should be displayed.
|
||||
|
||||
Tap "Export File". The app will show an alert. Tap "OK".
|
||||
|
||||
Switch to the "Files" app and open the "Downloads" folder. There should be a new
|
||||
file named `SheetJSNS.xls`.
|
||||
Switch to the "Files" app and repeatedly tap "<". In the "Browse" window, tap
|
||||
"On My iPhone". There should be a new folder named "SheetJSNS". Tap the folder
|
||||
and look for the file named `SheetJSNS.xls`.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@ -53,8 +53,8 @@ This demo was tested in the following environments:
|
||||
|:-----------|:--------------------|:------------------|:-------------|:-----------|
|
||||
| Android 34 | Pixel 3a | `7.1.0` / `7.0.0` | `darwin-arm` | 2025-03-30 |
|
||||
| iOS 18.2 | iPhone 16 Pro Max | `7.1.0` / `7.0.0` | `darwin-arm` | 2025-03-30 |
|
||||
| Android 35 | Pixel 9 | `6.2.0` / `6.0.2` | `win11-x64` | 2024-12-21 |
|
||||
| Android 35 | Pixel 9 | `6.2.0` / `6.0.2` | `linux-x64` | 2025-01-02 |
|
||||
| Android 35 | Pixel 9 Pro XL | `7.3.0` / `7.1.1` | `win11-x64` | 2025-06-08 |
|
||||
| Android 36 | Pixel 9 | `7.4.1` / `7.1.2` | `linux-x64` | 2025-07-06 |
|
||||
|
||||
:::
|
||||
|
||||
@ -63,13 +63,13 @@ This demo was tested in the following environments:
|
||||
Before starting this demo, manually disable telemetry. On Linux and MacOS:
|
||||
|
||||
```bash
|
||||
npx @capacitor/cli telemetry off
|
||||
npx -y @capacitor/cli telemetry off
|
||||
```
|
||||
|
||||
To verify telemetry was disabled:
|
||||
|
||||
```bash
|
||||
npx @capacitor/cli telemetry
|
||||
npx -y @capacitor/cli telemetry
|
||||
```
|
||||
|
||||
:::
|
||||
@ -212,25 +212,29 @@ iOS development is only supported on macOS.
|
||||
|
||||
:::
|
||||
|
||||
<details>
|
||||
<details open>
|
||||
<summary><b>Installation Notes</b> (click to show)</summary>
|
||||
|
||||
For Android development, CapacitorJS requires a Java version compatible with the
|
||||
expected Gradle version. When this demo was tested against CapacitorJS `6.2.0`,
|
||||
Java 20 was required to support Gradle `8.2.1`.
|
||||
expected Gradle version:
|
||||
|
||||
| CapacitorJS | Gradle | Java |
|
||||
|:------------|:---------|:-----|
|
||||
| `6.2.0` | `8.2.1` | 20 |
|
||||
| `7.4.1` | `8.11.1` | 21 |
|
||||
|
||||
</details>
|
||||
|
||||
1) Disable telemetry.
|
||||
|
||||
```bash
|
||||
npx @capacitor/cli telemetry off
|
||||
npx -y @capacitor/cli telemetry off
|
||||
```
|
||||
|
||||
Verify that telemetry is disabled by running
|
||||
|
||||
```bash
|
||||
npx @capacitor/cli telemetry
|
||||
npx -y @capacitor/cli telemetry
|
||||
```
|
||||
|
||||
(it should print `Telemetry is off`)
|
||||
@ -238,7 +242,7 @@ npx @capacitor/cli telemetry
|
||||
2) Create a new Svelte project:
|
||||
|
||||
```bash
|
||||
npm create vite@latest sheetjs-cap -- --template svelte
|
||||
npm create vite@latest sheetjs-cap -- --template svelte --no-rolldown --no-interactive
|
||||
cd sheetjs-cap
|
||||
```
|
||||
|
||||
@ -249,6 +253,22 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npm i --save @capacitor/core @capacitor/cli @capacitor/filesystem`}
|
||||
</CodeBlock>
|
||||
|
||||
:::warning pass
|
||||
|
||||
When this demo was last tested, parts of the official project required ViteJS 6
|
||||
and other parts required ViteJS 7. The install failed.
|
||||
|
||||
**This is a bug in the Svelte integration!**
|
||||
|
||||
Until the bug is fixed, the `--force` option should be used:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz --force
|
||||
npm i --save @capacitor/core @capacitor/cli @capacitor/filesystem --force`}
|
||||
</CodeBlock>
|
||||
|
||||
:::
|
||||
|
||||
4) Create CapacitorJS structure:
|
||||
|
||||
```bash
|
||||
@ -258,14 +278,14 @@ npm run build
|
||||
|
||||
:::note pass
|
||||
|
||||
If prompted to create an Ionic account, type `N` and press <kbd>Enter</kbd>.
|
||||
If prompted to create an Ionic account, Press <kbd>N</kbd> to opt out.
|
||||
|
||||
:::
|
||||
|
||||
5) Download [`src/App.svelte`](pathname:///cap/App.svelte) and replace:
|
||||
|
||||
```bash
|
||||
curl -o src/App.svelte -L https://docs.sheetjs.com/cap/App.svelte
|
||||
curl -o src/App.svelte https://docs.sheetjs.com/cap/App.svelte
|
||||
```
|
||||
|
||||
### Android
|
||||
@ -277,6 +297,22 @@ npm i --save @capacitor/android
|
||||
npx cap add android
|
||||
```
|
||||
|
||||
:::warning pass
|
||||
|
||||
When this demo was last tested, parts of the official project required ViteJS 6
|
||||
and other parts required ViteJS 7. The install failed.
|
||||
|
||||
**This is a bug in the Svelte integration!**
|
||||
|
||||
Until the bug is fixed, the `--force` option should be used:
|
||||
|
||||
```bash
|
||||
npm i --save @capacitor/android --force
|
||||
npx cap add android
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
|
||||
If the wrong Java version is installed, the last command will fail with a
|
||||
@ -530,7 +566,7 @@ error: Provisioning profile "iOS Team Provisioning Profile: com.sheetjs.cap" doe
|
||||
```
|
||||
|
||||
This error was resolved by manually selecting the device as the primary target
|
||||
in the Xcode workspace.
|
||||
in the Xcode workspace.
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -51,15 +51,15 @@ This demo was tested in the following environments:
|
||||
| OS | Device | Dart | Flutter | Date |
|
||||
|:-----------|:------------------|:--------|:---------|:-----------|
|
||||
| Android 34 | NVIDIA Shield | `3.7.2` | `3.29.2` | 2025-03-31 |
|
||||
| iOS 15.6 | iPhone 13 Pro Max | `3.7.2` | `3.29.2` | 2025-03-31 |
|
||||
| iOS 26.3 | iPhone 13 Pro Max | `3.11.1`| `3.41.4` | 2026-03-10 |
|
||||
|
||||
**Simulators**
|
||||
|
||||
| OS | Device | Dart | Flutter | Dev Platform | Date |
|
||||
|:-----------|:------------------|:--------|:---------|:-------------|:-----------|
|
||||
| Android 35 | Pixel 9 Pro XL | `3.7.2` | `3.29.2` | `darwin-x64` | 2025-03-31 |
|
||||
| iOS 18.3 | iPhone 16 Pro Max | `3.7.2` | `3.29.2` | `darwin-x64` | 2025-03-31 |
|
||||
| Android 35 | Pixel 3a | `3.5.0` | `3.24.0` | `win11-x64` | 2024-08-10 |
|
||||
| Android 36 | Pixel Table | `3.11.1` | `3.41.4` | `darwin-arm` | 2026-03-11 |
|
||||
| iOS 18.6 | iPhone 16 Pro Max | `3.11.1`| `3.41.4` | `darwin-arm` | 2026-03-11 |
|
||||
| Android 36 | Pixel 9 Pro XL | `3.7.2` | `3.29.3` | `win11-x64` | 2054-04-28 |
|
||||
|
||||
:::
|
||||
|
||||
@ -244,7 +244,7 @@ Run `flutter doctor` and confirm the following items are checked:
|
||||
<TabItem value="win" label="Windows">
|
||||
|
||||
<pre>
|
||||
<span {...g}>[✓]</span> Android toolchain - develop for Android devices (Android SDK version 35.0.0)
|
||||
<span {...g}>[✓]</span> Android toolchain - develop for Android devices (Android SDK version 35.0.1)
|
||||
</pre>
|
||||
|
||||
</TabItem>
|
||||
@ -260,7 +260,7 @@ Run `flutter doctor` and confirm the following items are checked:
|
||||
On first run, there may be a warning with "Android toolchain":
|
||||
|
||||
```
|
||||
[!] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
|
||||
[!] Android toolchain - develop for Android devices (Android SDK version 35.0.1)
|
||||
! Some Android licenses not accepted. To resolve this, run: flutter doctor
|
||||
--android-licenses
|
||||
```
|
||||
@ -297,6 +297,21 @@ error: Android sdkmanager not found. Update to the latest Android SDK and ensure
|
||||
Android Studio does not install `Android SDK Command-Line Tools` by default. It
|
||||
must be installed manually.
|
||||
|
||||
---
|
||||
To enable Android SDK Command-Line Tools via Android Studio follow this:
|
||||
|
||||
Find SDK manager by searching it in *Search Everywhere*
|
||||

|
||||
|
||||
Select **SDK Tools** from the top tab in the middle panel, then check **Android SDK Command-line Tools (latest)** and
|
||||
click **OK**.
|
||||
|
||||

|
||||
|
||||
A dialog will appear asking to download and install the tools. Click **OK** to continue.
|
||||
|
||||
---
|
||||
|
||||
Assuming the command-line tools are installed
|
||||
|
||||
This was fixed by switching to Java 20, installing `Android SDK 33`, and rolling
|
||||
@ -386,9 +401,9 @@ Pixel_9_Pro_XL_API_35 • Pixel 9 Pro XL API 35 • Google • android
|
||||
There should be at least one `android` emulator:
|
||||
|
||||
```
|
||||
Id • Name • Manufacturer • Platform
|
||||
Id • Name • Manufacturer • Platform
|
||||
|
||||
Pixel_3a_API_35 • Pixel 3a API 35 • Google • android
|
||||
Pixel_9_Pro_XL • Pixel 9 Pro XL • Google • android
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
@ -445,14 +460,43 @@ emulator -avd Pixel_9_Pro_XL_API_35
|
||||
|
||||
:::note pass
|
||||
|
||||
If `emulator` cannot be found, the folder must be added to the system path.
|
||||
|
||||
<Tabs groupId="os">
|
||||
<TabItem value="macos" label="macOS">
|
||||
|
||||
On macOS, `~/Library/Android/sdk/emulator/` is the typical location for the
|
||||
`emulator` binary. If it cannot be found, add the folder to `PATH`:
|
||||
`emulator` binary:
|
||||
|
||||
```bash
|
||||
export PATH="$PATH":~/Library/Android/sdk/emulator
|
||||
emulator -avd Pixel_9_Pro_XL_API_35
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="win" label="Windows">
|
||||
|
||||
The Android SDK folder can be found in the SDK manager in Android Studio. It is
|
||||
typically `%LOCALAPPDATA%\Android\Sdk`.
|
||||
|
||||
If it is not assigned, create a User environment variable named `ANDROID_HOME`
|
||||
with the value set to the Android SDK folder.
|
||||
|
||||
---
|
||||
|
||||
There are three folders within the Android SDK folder that should be added to
|
||||
the User `PATH` environment variable. Each folder holds a different tool:
|
||||
|
||||
| Folder | Command-line Tool |
|
||||
|:------------------------------------------|:------------------|
|
||||
| `%ANDROID_HOME%\emulator` | `emulator` |
|
||||
| `%ANDROID_HOME%\cmdline-tools\latest\bin` | `avdmanager` |
|
||||
| `%ANDROID_HOME%\platform-tools` | `adb` |
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
:::
|
||||
|
||||
</details>
|
||||
@ -502,7 +546,7 @@ Once the app loads, stop the terminal process and close the simulator.
|
||||
5) Install Flutter / Dart dependencies:
|
||||
|
||||
```bash
|
||||
flutter pub add http csv flutter_js
|
||||
flutter pub add http csv flutter_js collection
|
||||
```
|
||||
|
||||
:::info pass
|
||||
@ -526,7 +570,7 @@ As stated, "Developer Mode" must be enabled:
|
||||
3) Reinstall dependencies:
|
||||
|
||||
```bash
|
||||
flutter pub add http csv flutter_js
|
||||
flutter pub add http csv flutter_js collection
|
||||
```
|
||||
|
||||
:::
|
||||
@ -645,6 +689,13 @@ flutter -v -d emulator-5554 run
|
||||
|
||||
</details>
|
||||
|
||||
:::caution pass
|
||||
|
||||
In some test runs on low-power devices, it took 20 seconds for the app to fetch
|
||||
and display data!
|
||||
|
||||
:::
|
||||
|
||||
:::info Troubleshooting
|
||||
|
||||
In some demo runs, the build failed with an Android SDK error:
|
||||
@ -822,7 +873,7 @@ The app may take 30 seconds to load the content.
|
||||
|
||||
### iOS Device
|
||||
|
||||
19) Follow the official "Deploy to physical iOS devices" instructions[^10]
|
||||
19) **Follow the official ["Deploy to physical iOS devices"](https://docs.flutter.dev/platform-integration/ios/setup#set-up-devices) instructions**
|
||||
|
||||
20) Connect the iOS device and verify that `flutter` can find the device:
|
||||
|
||||
@ -852,7 +903,7 @@ Tap "OK" to continue.
|
||||
|
||||
:::info pass
|
||||
|
||||
In some test runs, the app requested for local network access:
|
||||
In some test runs, the app requested for local network access:
|
||||
|
||||
> "Sheetjs Flutter" would like to find and connect to devices on your local network.
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ import current from '/version.js';
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
export const r = {style: {color:"red"}};
|
||||
export const g = {style: {color:"green"}};
|
||||
@ -176,7 +177,7 @@ The demo uses Lynx `<view/>` and `<text/>` elements to display tabular data:
|
||||
{/* Map through each cell in the current row */}
|
||||
{Array.isArray(row) && row.map((cell, cellIndex) => (
|
||||
{/* Cell with dynamic width based on content */}
|
||||
<view
|
||||
<view
|
||||
key={`cell-${rowIndex}-${cellIndex}`} className="Cell"
|
||||
style={{ width: `${widths[cellIndex]}px` }}>
|
||||
{/* Display cell content as text */}
|
||||
@ -257,7 +258,8 @@ curl -o ./src/App.tsx https://docs.sheetjs.com/lynx/App.tsx
|
||||
```bash
|
||||
curl -o ./src/App.css https://docs.sheetjs.com/lynx/App.css
|
||||
```
|
||||
<a name="step5"></a>
|
||||
|
||||
<Link id="step5"/>
|
||||
|
||||
5) Start the development server:
|
||||
|
||||
|
||||
@ -44,7 +44,7 @@ The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be
|
||||
imported from the main or the renderer thread.
|
||||
|
||||
The SheetJS `readFile` and `writeFile` methods will use the Electron `fs` module
|
||||
where available.
|
||||
where available.
|
||||
|
||||
<details>
|
||||
<summary><b>Renderer Configuration</b> (click to show)</summary>
|
||||
@ -57,6 +57,37 @@ Electron 12 and later also require `worldSafeExecuteJavascript: true` and
|
||||
|
||||
</details>
|
||||
|
||||
:::caution pass
|
||||
|
||||
The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone)
|
||||
can be loaded from the renderer thread using a standard `SCRIPT` tag, but it is
|
||||
strongly discouraged.
|
||||
|
||||
[Issue 3314](https://git.sheetjs.com/sheetjs/sheetjs/issues/3314) in the SheetJS
|
||||
CE issue tracker describes the required HTML configuration.
|
||||
|
||||
<details>
|
||||
<summary><b>HTML Configuration</b> (click to show)</summary>
|
||||
|
||||
The following CSP directives should be specified in the `HEAD` block:
|
||||
|
||||
```html
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.sheetjs.com"
|
||||
/>
|
||||
<meta
|
||||
http-equiv="X-Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.sheetjs.com"
|
||||
/>
|
||||
```
|
||||
|
||||
Without these settings, newer Electron versions will not run the scripts.
|
||||
|
||||
</details>
|
||||
|
||||
:::
|
||||
|
||||
### Reading Files
|
||||
|
||||
Electron offers 3 different ways to read files, two of which use Web APIs.
|
||||
@ -207,11 +238,11 @@ This demo was tested in the following environments:
|
||||
|
||||
| OS and Version | Architecture | Electron | Date |
|
||||
|:---------------|:-------------|:---------|:-----------|
|
||||
| macOS 15.3 | `darwin-x64` | `35.1.2` | 2025-03-31 |
|
||||
| macOS 14.5 | `darwin-arm` | `35.1.2` | 2025-03-30 |
|
||||
| macOS 15.7.4 | `darwin-x64` | `40.8.0` | 2026-03-08 |
|
||||
| macOS 14.5 | `darwin-arm` | `35.1.2` | 2025-08-30 |
|
||||
| Windows 11 | `win11-x64` | `33.2.1` | 2025-02-11 |
|
||||
| Windows 11 | `win11-arm` | `33.2.1` | 2025-02-23 |
|
||||
| Linux (HoloOS) | `linux-x64` | `33.2.1` | 2025-01-02 |
|
||||
| Linux (Ubuntu) | `linux-x64` | `35.1.2` | 2025-07-06 |
|
||||
| Linux (Debian) | `linux-arm` | `33.2.1` | 2025-02-16 |
|
||||
|
||||
:::
|
||||
@ -284,6 +315,28 @@ npx -y electron .
|
||||
|
||||
The app will run.
|
||||
|
||||
:::info pass
|
||||
|
||||
In some Linux deployments, the command will fail with a sandbox error:
|
||||
|
||||
```
|
||||
The SUID sandbox helper binary was found, but is not configured correctly. Rather than run without sandboxing I'm aborting now.
|
||||
```
|
||||
|
||||
The workaround is to temporarily disable the sandbox restriction:
|
||||
|
||||
```bash
|
||||
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
|
||||
```
|
||||
|
||||
After testing, the restriction can be re-enabled with a similar command:
|
||||
|
||||
```bash
|
||||
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=1
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
4) To build a standalone app, run the builder:
|
||||
|
||||
```bash
|
||||
|
||||
@ -119,14 +119,14 @@ input.click();
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| OS and Version | Architecture | NW.js | Date | Notes |
|
||||
|:---------------|:-------------|:---------|:-----------|:---------------------|
|
||||
| macOS 15.3.2 | `darwin-x64` | `0.94.0` | 2025-03-31 | |
|
||||
| macOS 14.5 | `darwin-arm` | `0.94.0` | 2025-03-30 | |
|
||||
| Windows 11 | `win11-x64` | `0.94.0` | 2024-12-19 | |
|
||||
| Windows 11 | `win11-arm` | `0.94.0` | 2025-02-23 | |
|
||||
| Linux (HoloOS) | `linux-x64` | `0.89.0` | 2025-01-10 | |
|
||||
| Linux (Debian) | `linux-arm` | `0.60.0` | 2025-02-16 | Unofficial build[^1] |
|
||||
| OS and Version | Architecture | NW.js | Date | Notes |
|
||||
|:---------------|:-------------|:----------|:-----------|:---------------------|
|
||||
| macOS 15.3.2 | `darwin-x64` | `0.94.0` | 2025-03-31 | |
|
||||
| macOS 14.5 | `darwin-arm` | `0.94.0` | 2025-03-30 | |
|
||||
| Windows 11 | `win11-x64` | `0.100.0` | 2025-05-27 | |
|
||||
| Windows 11 | `win11-arm` | `0.94.0` | 2025-02-23 | |
|
||||
| Linux (Ubuntu) | `linux-x64` | `0.101.2` | 2025-07-06 | |
|
||||
| Linux (Debian) | `linux-arm` | `0.60.0` | 2025-02-16 | Unofficial build[^1] |
|
||||
|
||||
:::
|
||||
|
||||
@ -146,7 +146,7 @@ cd sheetjs-nwjs
|
||||
"version": "0.0.0",
|
||||
"main": "index.html",
|
||||
"dependencies": {
|
||||
"nw": "0.94.0",
|
||||
"nw": "0.101.2",
|
||||
"xlsx": "https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz"
|
||||
}
|
||||
}`}
|
||||
@ -167,6 +167,22 @@ In the terminal window, the download can be performed with:
|
||||
curl -LO https://docs.sheetjs.com/nwjs/index.html
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
In PowerShell, the command may fail with a parameter error:
|
||||
|
||||
```
|
||||
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'L'.
|
||||
```
|
||||
|
||||
`curl.exe` must be invoked directly:
|
||||
|
||||
```bash
|
||||
curl.exe -LO https://docs.sheetjs.com/nwjs/index.html
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
3) Install dependencies:
|
||||
|
||||
```bash
|
||||
@ -208,15 +224,20 @@ Unfortunately `nw-builder` will not be able to build a standalone program.
|
||||
5) To build a standalone app, run the builder:
|
||||
|
||||
```bash
|
||||
npx -p nw-builder@4.11.6 nwbuild --mode=build --version=0.94.0 --glob=false --outDir=../out ./
|
||||
npx -p nw-builder@4.13.14 nwbuild --mode=build --version=0.101.2 --glob=false --outDir=../out ./
|
||||
```
|
||||
|
||||
This will generate the standalone app in the `..\out\` folder.
|
||||
|
||||
:::caution pass
|
||||
|
||||
There is a regression in `nw-builder` version `4.12.0`. In local `win11-x64`
|
||||
testing, version `4.11.6` correctly generated the standalone application.
|
||||
There is a regression in `nw-builder` versions `4.12.0` and `4.13.14`.
|
||||
|
||||
In local `win11-x64` testing, `4.11.6` generates the standalone application.
|
||||
|
||||
```bash
|
||||
npx -p nw-builder@4.11.6 nwbuild --mode=build --version=0.101.2 --glob=false --outDir=../out ./
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -54,6 +54,21 @@ platform provides many native features out of the box.
|
||||
|
||||
:::
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| OS and Version | Architecture | Wails | Date |
|
||||
|:---------------|:-------------|:----------|:-----------|
|
||||
| macOS 15.3.2 | `darwin-x64` | `v2.10.1` | 2025-03-31 |
|
||||
| macOS 14.5 | `darwin-arm` | `v2.10.1` | 2025-03-30 |
|
||||
| Windows 11 | `win11-x64` | `v2.10.1` | 2025-05-27 |
|
||||
| Windows 11 | `win11-arm` | `v2.10` | 2025-02-23 |
|
||||
| Linux (HoloOS) | `linux-x64` | `v2.10.2` | 2025-07-06 |
|
||||
| Linux (Debian) | `linux-arm` | `v2.10` | 2025-02-16 |
|
||||
|
||||
:::
|
||||
|
||||
## Integration Details
|
||||
|
||||
The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be
|
||||
@ -291,21 +306,6 @@ async function exportFile(table_element) {
|
||||
|
||||
## Complete Example
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| OS and Version | Architecture | Wails | Date |
|
||||
|:---------------|:-------------|:----------|:-----------|
|
||||
| macOS 15.3.2 | `darwin-x64` | `v2.10.1` | 2025-03-31 |
|
||||
| macOS 14.5 | `darwin-arm` | `v2.10.1` | 2025-03-30 |
|
||||
| Windows 11 | `win11-x64` | `v2.9.2` | 2024-12-21 |
|
||||
| Windows 11 | `win11-arm` | `v2.10` | 2025-02-23 |
|
||||
| Linux (HoloOS) | `linux-x64` | `v2.9.2` | 2025-01-02 |
|
||||
| Linux (Debian) | `linux-arm` | `v2.10` | 2025-02-16 |
|
||||
|
||||
:::
|
||||
|
||||
0) Read the Wails "Getting Started" guide[^14] and install dependencies.
|
||||
|
||||
<details>
|
||||
@ -400,7 +400,11 @@ wails build
|
||||
|
||||
It will print the path to the generated program (typically in `build/bin/`).
|
||||
|
||||
5) Run the generated application.
|
||||
5) Run the generated application:
|
||||
|
||||
| Architecture | Command |
|
||||
|:-------------|:------------------------------------------|
|
||||
| `win11-x64` | `.\build\bin\sheetjs-wails.exe` |
|
||||
|
||||
**Testing**
|
||||
|
||||
|
||||
@ -50,6 +50,21 @@ app to read and write workbooks. The app will look like the screenshots below:
|
||||
|
||||
</td></tr></tbody></table>
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| OS and Version | Architecture | Tauri | Date |
|
||||
|:---------------|:-------------|:----------|:-----------|
|
||||
| macOS 15.3.2 | `darwin-x64` | `v1.6.0` | 2025-03-31 |
|
||||
| macOS 14.5 | `darwin-arm` | `v1.6.0` | 2025-03-30 |
|
||||
| Windows 11 | `win11-x64` | `v1.6.0` | 2025-05-27 |
|
||||
| Windows 11 | `win11-arm` | `v1.6.0` | 2025-02-23 |
|
||||
| Linux (HoloOS) | `linux-x64` | `v1.6.0` | 2025-07-06 |
|
||||
| Linux (Debian) | `linux-arm` | `v1.6.0` | 2025-05-27 |
|
||||
|
||||
:::
|
||||
|
||||
## Integration Details
|
||||
|
||||
The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be
|
||||
@ -347,21 +362,6 @@ function SheetJSExportKaioponent() {
|
||||
|
||||
## Complete Example
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| OS and Version | Architecture | Tauri | Date |
|
||||
|:---------------|:-------------|:----------|:-----------|
|
||||
| macOS 15.3.2 | `darwin-x64` | `v1.6.0` | 2025-03-31 |
|
||||
| macOS 14.5 | `darwin-arm` | `v1.6.0` | 2025-03-30 |
|
||||
| Windows 11 | `win11-x64` | `v1.6.0` | 2024-12-21 |
|
||||
| Windows 11 | `win11-arm` | `v1.6.0` | 2025-02-23 |
|
||||
| Linux (HoloOS) | `linux-x64` | `v1.6.0` | 2025-01-02 |
|
||||
| Linux (Debian) | `linux-arm` | `v1.6.0` | 2025-02-16 |
|
||||
|
||||
:::
|
||||
|
||||
0) Read Tauri "Getting Started" guide and install prerequisites.[^16]
|
||||
|
||||
<details>
|
||||
@ -376,7 +376,7 @@ At a high level, the following software is required for building Tauri apps:
|
||||
The platform configuration can be verified by running:
|
||||
|
||||
```bash
|
||||
npx @tauri-apps/cli info
|
||||
npx @tauri-apps/cli@1 info
|
||||
```
|
||||
|
||||
If required dependencies are installed, the output will show a checkmark next to
|
||||
@ -386,15 +386,15 @@ If required dependencies are installed, the output will show a checkmark next to
|
||||
<span {...g}>[✔]</span> <span style={{...y.style,...B.style}}>Environment</span>
|
||||
{` `}<span {...c}>-</span> <span {...B}>OS</span>: Mac OS 14.5.0 arm64 (X64)
|
||||
{` `}<span {...g}>✔</span> <span {...B}>Xcode Command Line Tools</span>: installed
|
||||
{` `}<span {...g}>✔</span> <span {...B}>rustc</span>: 1.85.1 (4eb161250 2025-03-15)
|
||||
{` `}<span {...g}>✔</span> <span {...B}>cargo</span>: 1.85.1 (d73d2caf9 2024-12-31)
|
||||
{` `}<span {...g}>✔</span> <span {...B}>rustup</span>: 1.28.1 (f9edccde0 2025-03-05)
|
||||
{` `}<span {...g}>✔</span> <span {...B}>rustc</span>: 1.87.0 (17067e9ac 2025-05-09)
|
||||
{` `}<span {...g}>✔</span> <span {...B}>cargo</span>: 1.87.0 (99624be96 2025-05-06)
|
||||
{` `}<span {...g}>✔</span> <span {...B}>rustup</span>: 1.28.2 (e4f3ad6f8 2025-04-28)
|
||||
{` `}<span {...g}>✔</span> <span {...B}>Rust toolchain</span>: stable-aarch64-apple-darwin (default)
|
||||
{` `}<span {...c}>-</span> <span {...B}>node</span>: 20.18.0
|
||||
{` `}<span {...c}>-</span> <span {...B}>pnpm</span>: 9.12.3
|
||||
{` `}<span {...c}>-</span> <span {...B}>npm</span>: 10.8.2
|
||||
{` `}<span {...c}>-</span> <span {...B}>bun</span>: 1.2.7
|
||||
{` `}<span {...c}>-</span> <span {...B}>deno</span>: deno 2.2.6
|
||||
{` `}<span {...c}>-</span> <span {...B}>bun</span>: 1.2.14
|
||||
{` `}<span {...c}>-</span> <span {...B}>deno</span>: deno 2.3.3
|
||||
</pre>
|
||||
|
||||
:::caution pass
|
||||
@ -642,8 +642,9 @@ The following features should be manually verified:
|
||||
|
||||
- When it is loaded, the app will download https://docs.sheetjs.com/pres.numbers
|
||||
and display the data in a table.
|
||||
- Clicking "Save Data" will show a save dialog. After selecting a path and name,
|
||||
the app will write a file. That file can be opened in a spreadsheet editor.
|
||||
- Clicking "Save Data" will show a save dialog. If there is no filename, type
|
||||
`SheetJSTauri.xlsb`. Click "Save". The app will write a file which can be
|
||||
opened in a spreadsheet editor.
|
||||
- Edit the file in a spreadsheet editor, then click "Load Data" and select the
|
||||
edited file. The table will refresh with new contents.
|
||||
|
||||
|
||||
@ -45,6 +45,24 @@ app to read and write workbooks. The app will look like the screenshots below:
|
||||
|
||||
</td></tr></tbody></table>
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| OS and Version | Architecture | Server | Client | Date |
|
||||
|:---------------|:-------------|:---------|:---------|:-----------|
|
||||
| macOS 15.3.2 | `darwin-x64` | `6.0.0` | `6.0.0` | 2025-03-31 |
|
||||
| macOS 14.5 | `darwin-arm` | `6.0.0` | `6.0.0` | 2025-03-30 |
|
||||
| Windows 11 | `win11-x64` | `6.1.0` | `6.1.0` | 2025-05-27 |
|
||||
| Windows 11 | `win11-arm` | `5.6.0` | `5.6.0` | 2025-02-23 |
|
||||
| Linux (HoloOS) | `linux-x64` | `6.1.0` | `6.1.0` | 2025-07-06 |
|
||||
| Linux (Debian) | `linux-arm` | `5.6.0` | `5.6.0` | 2025-02-16 |
|
||||
|
||||
NeutralinoJS on Windows on ARM generates X64 binaries that run using the X64
|
||||
compatibility layer. The binaries are not native ARM64 programs!
|
||||
|
||||
:::
|
||||
|
||||
## Integration Details
|
||||
|
||||
The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone)
|
||||
@ -186,24 +204,6 @@ const save_button_callback = async() => {
|
||||
|
||||
## Complete Example
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| OS and Version | Architecture | Server | Client | Date |
|
||||
|:---------------|:-------------|:---------|:---------|:-----------|
|
||||
| macOS 15.3.2 | `darwin-x64` | `6.0.0` | `6.0.0` | 2025-03-31 |
|
||||
| macOS 14.5 | `darwin-arm` | `6.0.0` | `6.0.0` | 2025-03-30 |
|
||||
| Windows 11 | `win11-x64` | `5.5.0` | `5.5.0` | 2024-12-20 |
|
||||
| Windows 11 | `win11-arm` | `5.6.0` | `5.6.0` | 2025-02-23 |
|
||||
| Linux (HoloOS) | `linux-x64` | `5.5.0` | `5.5.0` | 2025-01-02 |
|
||||
| Linux (Debian) | `linux-arm` | `5.6.0` | `5.6.0` | 2025-02-16 |
|
||||
|
||||
NeutralinoJS on Windows on ARM generates X64 binaries that run using the X64
|
||||
compatibility layer. The binaries are not native ARM64 programs!
|
||||
|
||||
:::
|
||||
|
||||
The app core state will be the HTML table. Reading files will add the table to
|
||||
the window. Writing files will parse the table into a spreadsheet.
|
||||
|
||||
@ -247,6 +247,22 @@ subdirectory in the `sheetjs-neu` folder:
|
||||
curl -L -o resources/js/xlsx.full.min.js https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}
|
||||
</CodeBlock>
|
||||
|
||||
:::note pass
|
||||
|
||||
In PowerShell, the command may fail with a parameter error:
|
||||
|
||||
```
|
||||
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'L'.
|
||||
```
|
||||
|
||||
`curl.exe` must be invoked directly:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
curl.exe -L -o resources/js/xlsx.full.min.js https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}
|
||||
</CodeBlock>
|
||||
|
||||
:::
|
||||
|
||||
3) Add the highlighted line to `neutralino.config.json` in `nativeAllowList`:
|
||||
|
||||
```json title="neutralino.config.json (add highlighted line)"
|
||||
|
||||
@ -46,12 +46,12 @@ This demo was tested in the following environments:
|
||||
|
||||
| OS and Version | Architecture | RN Platform | Date |
|
||||
|:---------------|:-------------|:------------|:-----------|
|
||||
| Windows 11 C++ | `win11-x64` | `v0.75.11` | 2024-12-22 |
|
||||
| Windows 11 C# | `win11-x64` | `v0.75.11` | 2024-12-22 |
|
||||
| Windows 11 C++ | `win11-x64` | `v0.78.8` | 2025-06-08 |
|
||||
| Windows 11 C# | `win11-x64` | `v0.78.8` | 2025-06-08 |
|
||||
| Windows 11 C++ | `win11-arm` | `v0.77.2` | 2025-02-23 |
|
||||
| Windows 11 C# | `win11-arm` | `v0.77.2` | 2025-02-23 |
|
||||
| MacOS 15.3.2 | `darwin-x64` | `v0.76.7` | 2025-03-31 |
|
||||
| MacOS 14.5 | `darwin-arm` | `v0.75.16` | 2024-12-22 |
|
||||
| MacOS 14.5 | `darwin-arm` | `v0.78.3` | 2025-06-14 |
|
||||
|
||||
:::
|
||||
|
||||
@ -432,12 +432,12 @@ not a requirement for this demo.
|
||||
|
||||
### Project Setup
|
||||
|
||||
1) Create a new project using React Native `0.77.1`:
|
||||
1) Create a new project using React Native `0.78.2`:
|
||||
|
||||
```bash
|
||||
npx -y @react-native-community/cli@16 init SheetJSWin --version="0.77.1"
|
||||
npx -y @react-native-community/cli@15 init SheetJSWin --version="0.78.2"
|
||||
cd SheetJSWin
|
||||
npm install --save react-native-windows@0.77.2
|
||||
npm install --save react-native-windows@0.78.8
|
||||
```
|
||||
|
||||
:::info pass
|
||||
@ -500,7 +500,7 @@ npx react-native run-windows --no-telemetry
|
||||
|
||||
When the demo was tested in Windows 11, the run step failed with the message:
|
||||
|
||||
> The Windows SDK version `10.0.19041.0` was not found
|
||||
> The Windows SDK version `10.0.22621.0` was not found
|
||||
|
||||
Specific Windows SDK versions can be installed through Visual Studio Installer.
|
||||
|
||||
@ -530,6 +530,18 @@ When this demo was last tested on Windows 11 ARM, the build failed.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::info pass
|
||||
|
||||
In PowerShell, the command will fail with `msbuild` errors:
|
||||
|
||||
```
|
||||
× Could not find MSBuild with VCTools for Visual Studio 17.11.0 or later. Make sure all required components have been installed
|
||||
```
|
||||
|
||||
**The commands must be run in a "Native Tools Command Prompt"!**
|
||||
|
||||
:::
|
||||
|
||||
### Native Module
|
||||
|
||||
<Tabs groupId="rnwlang">
|
||||
@ -546,7 +558,7 @@ iwr -Uri https://docs.sheetjs.com/reactnative/DocumentPicker.cs -OutFile windows
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="bash" label="WSL Bash">
|
||||
<TabItem value="bash" label="WSL Bash / Command Prompt">
|
||||
|
||||
```bash
|
||||
curl -Lo windows/SheetJSWin/DocumentPicker.cs https://docs.sheetjs.com/reactnative/DocumentPicker.cs
|
||||
@ -583,7 +595,7 @@ iwr -Uri https://docs.sheetjs.com/reactnative/DocumentPicker.h -OutFile windows/
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="bash" label="WSL Bash">
|
||||
<TabItem value="bash" label="WSL Bash / Command Prompt">
|
||||
|
||||
```bash
|
||||
curl -Lo windows/SheetJSWin/DocumentPicker.h https://docs.sheetjs.com/reactnative/DocumentPicker.h
|
||||
@ -619,7 +631,7 @@ iwr -Uri https://docs.sheetjs.com/reactnative/rnw/App.tsx -OutFile App.tsx
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="bash" label="WSL Bash">
|
||||
<TabItem value="bash" label="WSL Bash / Command Prompt">
|
||||
|
||||
```bash
|
||||
rm App.js
|
||||
@ -680,10 +692,10 @@ select `pres.xlsx` . The app will refresh and display the data from the file.
|
||||
|
||||
### Project Setup
|
||||
|
||||
1) Create a new React Native project using React Native `0.76.8`:
|
||||
1) Create a new React Native project using React Native `0.78.2`:
|
||||
|
||||
```bash
|
||||
npx -y @react-native-community/cli init SheetJSmacOS --version 0.76.8
|
||||
npx -y @react-native-community/cli@15 init SheetJSmacOS --version 0.78.2
|
||||
cd SheetJSmacOS
|
||||
```
|
||||
|
||||
@ -1011,9 +1023,9 @@ If there are no instances, the app path can be found in the `DerivedData` folder
|
||||
find ~/Library/Developer/Xcode/DerivedData -name SheetJSmacOS.app | grep Release
|
||||
```
|
||||
|
||||
:::caution pass
|
||||
:::info pass
|
||||
|
||||
During the last test, `xcodebuild` failed. Scrolling through the log reveals:
|
||||
In an older test run, `xcodebuild` failed. Scrolling through the log reveals:
|
||||
|
||||
```
|
||||
Welcome to Metro v0.80.12
|
||||
|
||||
@ -37,12 +37,12 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | Version | NodeJS | Source | Date |
|
||||
|:-------------|:---------------|:----------|:----------|:-----------|
|
||||
| `darwin-x64` | `5.0.0-beta.4` | `14.15.3` | Pre-built | 2025-04-21 |
|
||||
| `darwin-arm` | `4.0.0-rc.6` | `22.14.0` | Compiled | 2025-04-03 |
|
||||
| `win11-x64` | `4.0.0-rc.6` | `14.15.3` | Pre-built | 2024-12-19 |
|
||||
| `darwin-x64` | `5.0.0-beta.4` | `14.15.3` | Pre-built | 2026-01-21 |
|
||||
| `darwin-arm` | `5.0.0-beta.4` | `20.18.0` | Compiled | 2026-03-07 |
|
||||
| `win11-x64` | `5.0.0-beta.4` | `14.15.3` | Pre-built | 2026-03-08 |
|
||||
| `win11-arm` | `4.0.0-rc.6` | `22.14.0` | Compiled | 2025-02-23 |
|
||||
| `linux-x64` | `5.0.0-beta.4` | `14.15.3` | Pre-built | 2025-04-21 |
|
||||
| `linux-arm` | `4.0.0-rc.6` | `22.13.0` | Compiled | 2025-02-15 |
|
||||
| `linux-x64` | `5.0.0-beta.4` | `14.15.3` | Pre-built | 2026-01-18 |
|
||||
| `linux-arm` | `5.0.0-beta.4` | `24.14.0` | Compiled | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -37,12 +37,12 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | Version | NodeJS | Date |
|
||||
|:-------------|:--------|:---------|:-----------|
|
||||
| `darwin-x64` | `5.8.1` | `18.5.0` | 2025-04-21 |
|
||||
| `darwin-arm` | `5.8.1` | `18.5.0` | 2025-02-13 |
|
||||
| `win11-x64` | `5.8.1` | `18.5.0` | 2024-12-19 |
|
||||
| `darwin-x64` | `5.8.1` | `18.5.0` | 2026-01-21 |
|
||||
| `darwin-arm` | `5.8.1` | `18.5.0` | 2026-03-07 |
|
||||
| `win11-x64` | `5.8.1` | `18.5.0` | 2026-03-08 |
|
||||
| `win11-arm` | `5.8.1` | `18.5.0` | 2025-02-23 |
|
||||
| `linux-x64` | `5.8.1` | `18.5.0` | 2025-04-21 |
|
||||
| `linux-arm` | `5.8.1` | `18.5.0` | 2025-02-15 |
|
||||
| `linux-x64` | `5.8.1` | `18.5.0` | 2026-01-18 |
|
||||
| `linux-arm` | `5.8.1` | `18.5.0` | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
@ -78,7 +78,7 @@ When this demo was last tested, `pkg` failed with an error referencing `node20`:
|
||||
> Error! No available node version satisfies 'node20'
|
||||
```
|
||||
|
||||
**`pkg` does not support NodeJS 20 or 22!**
|
||||
**`pkg` does not support NodeJS 20 or 22 or 24!**
|
||||
|
||||
The local NodeJS version must be rolled back to version 18.
|
||||
|
||||
|
||||
@ -30,10 +30,10 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | Version | NodeJS | Date |
|
||||
|:-------------|:--------|:----------|:-----------|
|
||||
| `darwin-x64` | `2.4.4` | `23.11.0` | 2025-04-21 |
|
||||
| `darwin-arm` | `2.4.4` | `22.14.0` | 2025-04-03 |
|
||||
| `win11-x64` | `2.4.4` | `16.20.2` | 2024-12-19 |
|
||||
| `linux-x64` | `2.4.4` | `23.11.0` | 2025-04-21 |
|
||||
| `darwin-x64` | `3.0.0` | `25.8.0` | 2026-03-08 |
|
||||
| `darwin-arm` | `2.4.4` | `23.11.0` | 2025-06-18 |
|
||||
| `win11-x64` | `2.4.4` | `16.20.2` | 2025-05-07 |
|
||||
| `linux-x64` | `3.0.0` | `25.8.0` | 2026-03-08 |
|
||||
| `linux-arm` | `2.4.4` | `23.8.0` | 2025-02-15 |
|
||||
|
||||
:::
|
||||
@ -91,7 +91,7 @@ yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz exit-on-epi
|
||||
<TabItem value="unix" label="Linux/MacOS">
|
||||
|
||||
```bash
|
||||
npx -y boxednode@2.4.4 -s xlsx-cli.js -t xlsx-cli
|
||||
npx -y boxednode@3.0.0 -s xlsx-cli.js -t xlsx-cli
|
||||
```
|
||||
|
||||
:::note pass
|
||||
@ -136,7 +136,7 @@ workload, Python 3.11, and NASM[^2].
|
||||
|
||||
:::caution pass
|
||||
|
||||
When the demo was last tested, the build failed:
|
||||
In some test runs, the build failed:
|
||||
|
||||
```
|
||||
Not an executable Python program
|
||||
@ -168,8 +168,11 @@ When the demo was last tested on Windows, the build failed:
|
||||
error MSB8020: The build tools for Visual Studio 2019 (Platform Toolset = 'v142') cannot be found. To build using the v142 build tools, please install Visual Studio 2019 build tools.
|
||||
```
|
||||
|
||||
This error was fixed by installing the `v142` build tools through the Visual
|
||||
Studio installer.
|
||||
This error was fixed by installing the following components from Visual Studio:
|
||||
|
||||
- `C++/CLI support for v142 build tools`
|
||||
- `MSVC v142 - VS 2019 - C++ x64/x86 build tools`
|
||||
- `MSVC v142 - VS 2019 - C++ x64/x86 Spectre-mitigated libs`
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -158,12 +158,12 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | NodeJS | Date |
|
||||
|:-------------|:----------|:-----------|
|
||||
| `darwin-x64` | `22.14.0` | 2025-04-21 |
|
||||
| `darwin-arm` | `23.8.0` | 2025-02-16 |
|
||||
| `win11-x64` | `22.13.0` | 2025-01-19 |
|
||||
| `darwin-x64` | `24.13.0` | 2026-01-21 |
|
||||
| `darwin-arm` | `24.2.0` | 2025-06-18 |
|
||||
| `win11-x64` | `24.13.0` | 2026-03-08 |
|
||||
| `win11-arm` | `22.14.0` | 2025-02-23 |
|
||||
| `linux-x64` | `22.12.0` | 2025-01-02 |
|
||||
| `linux-arm` | `22.13.0` | 2025-02-16 |
|
||||
| `linux-x64` | `24.11.0` | 2026-03-08 |
|
||||
| `linux-arm` | `24.14.0` | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -79,12 +79,12 @@ This demo was last tested in the following deployments:
|
||||
|
||||
| Architecture | BunJS | Date |
|
||||
|:-------------|:---------|:-----------|
|
||||
| `darwin-x64` | `1.2.10` | 2025-04-21 |
|
||||
| `darwin-arm` | `1.2.8` | 2025-04-03 |
|
||||
| `win11-x64` | `1.1.40` | 2024-12-19 |
|
||||
| `darwin-x64` | `1.3.6` | 2026-01-21 |
|
||||
| `darwin-arm` | `1.3.10` | 2026-03-07 |
|
||||
| `win11-x64` | `1.3.10` | 2026-03-08 |
|
||||
| `win11-arm` | `1.2.3` | 2025-02-23 |
|
||||
| `linux-x64` | `1.1.43` | 2025-01-10 |
|
||||
| `linux-arm` | `1.2.2` | 2025-02-16 |
|
||||
| `linux-x64` | `1.3.10` | 2026-03-08 |
|
||||
| `linux-arm` | `1.3.10` | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -102,12 +102,12 @@ This demo was last tested in the following deployments:
|
||||
|
||||
| Architecture | Deno | Date |
|
||||
|:-------------|:---------|:-----------|
|
||||
| `darwin-x64` | `2.2.11` | 2025-04-21 |
|
||||
| `darwin-arm` | `2.1.10` | 2025-02-13 |
|
||||
| `win11-x64` | `2.1.6` | 2025-01-19 |
|
||||
| `darwin-x64` | `2.6.5` | 2026-01-21 |
|
||||
| `darwin-arm` | `2.7.4` | 2026-03-07 |
|
||||
| `win11-x64` | `2.7.4` | 2026-03-08 |
|
||||
| `win11-arm` | `2.2.1` | 2025-02-23 |
|
||||
| `linux-x64` | `2.1.4` | 2025-01-02 |
|
||||
| `linux-arm` | `2.1.10` | 2025-02-15 |
|
||||
| `linux-x64` | `2.7.4` | 2026-03-08 |
|
||||
| `linux-arm` | `2.7.4` | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ sidebar_label: txiki.js
|
||||
pagination_prev: demos/desktop/index
|
||||
pagination_next: demos/data/index
|
||||
sidebar_custom_props:
|
||||
summary: Compiled apps powered by QuickJS and txiki.js
|
||||
summary: Compiled apps powered by QuickJS and txiki.js
|
||||
---
|
||||
|
||||
import current from '/version.js';
|
||||
@ -88,14 +88,14 @@ console.log(csv);
|
||||
|
||||
This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | TxikiJS | Date |
|
||||
|:-------------|:----------|:-----------|
|
||||
| `darwin-x64` | `24.12.0` | 2025-04-19 |
|
||||
| `darwin-arm` | `24.12.0` | 2025-04-19 |
|
||||
| `win11-x64` | `24.12.0` | 2025-04-19 |
|
||||
| `win11-arm` | `24.12.0` | 2025-04-19 |
|
||||
| `linux-x64` | `24.12.0` | 2025-04-19 |
|
||||
| `linux-arm` | `24.12.0` | 2025-04-19 |
|
||||
| Architecture | Version | Commit | Date |
|
||||
|:-------------|:----------|:----------|:-----------|
|
||||
| `darwin-x64` | `24.12.0` | `793dd9d` | 2026-01-21 |
|
||||
| `darwin-arm` | `24.12.0` | `793dd9d` | 2026-01-18 |
|
||||
| `win11-x64` | `24.12.0` | | 2026-03-08 |
|
||||
| `win11-arm` | `24.12.0` | | 2025-04-19 |
|
||||
| `linux-x64` | `24.12.0` | `65e5595` | 2026-01-18 |
|
||||
| `linux-arm` | `24.12.0` | `65e5595` | 2026-01-21 |
|
||||
|
||||
:::
|
||||
|
||||
@ -133,6 +133,40 @@ cp build/tjs ../
|
||||
cd ..
|
||||
```
|
||||
|
||||
:::caution pass
|
||||
|
||||
In some `linux-x64` test runs, the `make` step failed:
|
||||
|
||||
```
|
||||
make[5]: *** No rule to make target 'all-configured'. Stop.
|
||||
```
|
||||
|
||||
After re-running `make`, the `[ 0%]` line identifies the root cause:
|
||||
|
||||
```text
|
||||
// highlight-next-line
|
||||
[ 0%] Performing build step for 'libffi'
|
||||
[ 1%] Built target sqlite3
|
||||
[ 2%] Built target ffi-test
|
||||
...
|
||||
[ 61%] Built target sqlite-test
|
||||
MAKE x86_64-pc-linux-gnu : 0 * all-configured
|
||||
// highlight-next-line
|
||||
make[5]: *** No rule to make target 'all-configured'. Stop.
|
||||
```
|
||||
|
||||
If the root cause is `libffi`, it is possible to use the system `libffi`. The
|
||||
following commands should be run in the `txiki.js` folder:
|
||||
|
||||
```bash
|
||||
rm -rf build
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release -DUSE_EXTERNAL_FFI=ON
|
||||
cmake --build build -j 8
|
||||
cp build/tjs ../
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="win11-x64" label="Windows">
|
||||
|
||||
|
||||
@ -42,8 +42,8 @@ loaded in NodeJS scripts that use KnexJS.
|
||||
The KnexJS `select` method[^1] creates a `SELECT` query. The return value is a
|
||||
Promise that resolves to an array of objects.
|
||||
|
||||
The SheetJS `json_to_sheet` method[^2] can generate a worksheet object[^3] from
|
||||
the array of objects:
|
||||
The SheetJS [`json_to_sheet`](/docs/api/utilities/array#array-of-objects-input)
|
||||
method can generate a [worksheet object](/docs/csf/sheet) from the array:
|
||||
|
||||
```js
|
||||
const table_name = "Tabeller1"; // name of table
|
||||
@ -55,8 +55,9 @@ const aoo = await knex.select("*").from(table_name);
|
||||
const worksheet = XLSX.utils.json_to_sheet(aoo);
|
||||
```
|
||||
|
||||
A workbook object can be built from the worksheet using utility functions[^4].
|
||||
The workbook can be exported using the SheetJS `writeFile` method[^5]:
|
||||
Using [`book_new` and `book_append_sheet`](/docs/api/utilities/wb), a workbook
|
||||
object can be created. This workbook is typically exported to the filesystem
|
||||
with the [`writeFile`](/docs/api/write-options) method:
|
||||
|
||||
```js
|
||||
/* create a new workbook and add the worksheet */
|
||||
@ -69,10 +70,10 @@ XLSX.writeFile(wb, "SheetJSKnexJSExport.xlsx");
|
||||
|
||||
### Importing Data
|
||||
|
||||
The SheetJS `sheet_to_json` function[^6] takes a worksheet object and generates
|
||||
an array of objects.
|
||||
The SheetJS [`sheet_to_json` function](/docs/api/utilities/array#array-output)
|
||||
accepts a worksheet object and generates an array of objects.
|
||||
|
||||
The KnexJS `insert` method[^7] creates `INSERT` queries. The return value is a
|
||||
The KnexJS `insert` method[^2] creates `INSERT` queries. The return value is a
|
||||
Promise that resolves when the query is executed:
|
||||
|
||||
```js
|
||||
@ -87,8 +88,8 @@ await knex.insert(aoo).into(table_name);
|
||||
|
||||
### Creating a Table
|
||||
|
||||
The KnexJS Schema Builder supports creating tables with `createTable`[^8] and
|
||||
dropping tables with `dropTableIfExists`[^9].
|
||||
The KnexJS Schema Builder supports creating tables with `createTable`[^3] and
|
||||
dropping tables with `dropTableIfExists`[^4].
|
||||
|
||||
The array of objects can be scanned to determine column names and types.
|
||||
|
||||
@ -272,11 +273,6 @@ Older versions of KnexJS do not support the `better-sqlite3` module. The
|
||||
:::
|
||||
|
||||
[^1]: See [`select`](https://knexjs.org/guide/query-builder.html#select) in the KnexJS query builder documentation.
|
||||
[^2]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input)
|
||||
[^3]: See ["Sheet Objects"](/docs/csf/sheet) in "SheetJS Data Model" for more details.
|
||||
[^4]: See ["Workbook Helpers" in "Utilities"](/docs/api/utilities/wb) for details on `book_new` and `book_append_sheet`.
|
||||
[^5]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
||||
[^6]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^7]: See [`insert`](https://knexjs.org/guide/query-builder.html#insert) in the KnexJS query builder documentation.
|
||||
[^8]: See [`createTable`](https://knexjs.org/guide/schema-builder.html#createtable) in the KnexJS Schema Builder documentation.
|
||||
[^9]: See [`dropTableIfExists`](https://knexjs.org/guide/schema-builder.html#droptableifexists) in the KnexJS Schema Builder documentation.
|
||||
[^2]: See [`insert`](https://knexjs.org/guide/query-builder.html#insert) in the KnexJS query builder documentation.
|
||||
[^3]: See [`createTable`](https://knexjs.org/guide/schema-builder.html#createtable) in the KnexJS Schema Builder documentation.
|
||||
[^4]: See [`dropTableIfExists`](https://knexjs.org/guide/schema-builder.html#droptableifexists) in the KnexJS Schema Builder documentation.
|
||||
|
||||
@ -58,8 +58,8 @@ other PostgreSQL libraries.
|
||||
`Client#query` returns a Promise that resolves to a result set. The `rows`
|
||||
property of the result is an array of objects.
|
||||
|
||||
The SheetJS `json_to_sheet` method[^2] can generate a worksheet object[^3] from
|
||||
the array of objects:
|
||||
The SheetJS [`json_to_sheet`](/docs/api/utilities/array#array-of-objects-input)
|
||||
method can generate a [worksheet object](/docs/csf/sheet) from the array:
|
||||
|
||||
```js
|
||||
const table_name = "Tabeller1"; // name of table
|
||||
@ -71,8 +71,8 @@ const res = await client.query(`SELECT * FROM ${table_name}`);
|
||||
const worksheet = XLSX.utils.json_to_sheet(res.rows);
|
||||
```
|
||||
|
||||
A workbook object can be built from the worksheet using utility functions[^4].
|
||||
The workbook can be exported using the SheetJS `writeFile` method[^5]:
|
||||
[Utility functions](/docs/api/utilities/wb) can build a SheetJS workbook object.
|
||||
The workbook can be exported using the [`writeFile`](/docs/api/write-options):
|
||||
|
||||
```js
|
||||
/* create a new workbook and add the worksheet */
|
||||
@ -85,8 +85,8 @@ XLSX.writeFile(wb, "SheetJSPGExport.xlsx");
|
||||
|
||||
### Importing Data
|
||||
|
||||
The SheetJS `sheet_to_json` function[^6] takes a worksheet object and generates
|
||||
an array of objects.
|
||||
The SheetJS [`sheet_to_json` function](/docs/api/utilities/array#array-output)
|
||||
accepts a worksheet object and generates an array of objects.
|
||||
|
||||
Queries must be manually generated from the objects. Assuming the field names
|
||||
in the object match the column headers, a loop can generate `INSERT` queries.
|
||||
@ -101,7 +101,7 @@ INSERT INTO table_name (?) VALUES (?);
|
||||
```
|
||||
|
||||
Queries are generated manually. To help prevent SQL injection vulnerabilities,
|
||||
the `pg-format`[^7] module escapes identifiers and fields.
|
||||
the `pg-format`[^2] module escapes identifiers and fields.
|
||||
|
||||
:::
|
||||
|
||||
@ -308,7 +308,7 @@ sudo -u postgres createuser -P $USER
|
||||
sudo -u postgres psql -c "ALTER USER $USER WITH SUPERUSER;"
|
||||
```
|
||||
|
||||
If running the optional user creation steps above, a PostgreSQL password will be required. [^8]
|
||||
If running the optional user creation steps above, a PostgreSQL password will be required. [^3]
|
||||
|
||||
Run the command to start a local database instance.
|
||||
|
||||
@ -538,10 +538,5 @@ psql SheetJSPG -c 'SELECT * FROM "Presidents";'
|
||||
|
||||
|
||||
[^1]: See [the official `pg` website](https://node-postgres.com/) for more info.
|
||||
[^2]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input)
|
||||
[^3]: See ["Sheet Objects"](/docs/csf/sheet) in "SheetJS Data Model" for more details.
|
||||
[^4]: See ["Workbook Helpers" in "Utilities"](/docs/api/utilities/wb) for details on `book_new` and `book_append_sheet`.
|
||||
[^5]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
||||
[^6]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^7]: The [`pg-format`](https://npm.im/pg-format) package is available on the public NPM registry. Even though the project is marked as deprecated, the official [`pg` website still recommends `pg-format`](https://node-postgres.com/features/queries#parameterized-query:~:text=use%20pg%2Dformat%20package%20for%20handling%20escaping)
|
||||
[^8]: PostgreSQL on Linux uses [SCRAM authentication by default, which requires a password](https://www.postgresql.org/docs/current/auth-password.html)
|
||||
[^2]: The [`pg-format`](https://npm.im/pg-format) package is available on the public NPM registry. Even though the project is marked as deprecated, the official [`pg` website still recommends `pg-format`](https://node-postgres.com/features/queries#parameterized-query:~:text=use%20pg%2Dformat%20package%20for%20handling%20escaping)
|
||||
[^3]: PostgreSQL on Linux uses [SCRAM authentication by default, which requires a password](https://www.postgresql.org/docs/current/auth-password.html)
|
||||
@ -53,8 +53,8 @@ to other MariaDB and MySQL libraries.
|
||||
`Connection#execute` returns a Promise that resolves to a result array. The
|
||||
first entry of the result is an array of objects.
|
||||
|
||||
The SheetJS `json_to_sheet` method[^2] can generate a worksheet object[^3] from
|
||||
the array of objects:
|
||||
The SheetJS [`json_to_sheet`](/docs/api/utilities/array#array-of-objects-input)
|
||||
method can generate a [worksheet object](/docs/csf/sheet) from the array:
|
||||
|
||||
```js
|
||||
const mysql = require("mysql2/promise"), XLSX = require("xlsx");
|
||||
@ -72,8 +72,9 @@ const [rows, fields] = await conn.execute(`SELECT * FROM ${mysql.escapeId(table_
|
||||
const worksheet = XLSX.utils.json_to_sheet(rows);
|
||||
```
|
||||
|
||||
A workbook object can be built from the worksheet using utility functions[^4].
|
||||
The workbook can be exported using the SheetJS `writeFile` method[^5]:
|
||||
Using [`book_new` and `book_append_sheet`](/docs/api/utilities/wb), a workbook
|
||||
object can be created. This workbook is typically exported to the filesystem
|
||||
with the [`writeFile`](/docs/api/write-options) method:
|
||||
|
||||
```js
|
||||
/* create a new workbook and add the worksheet */
|
||||
@ -86,8 +87,8 @@ XLSX.writeFile(wb, "SheetJSMariaDBExport.xlsx");
|
||||
|
||||
### Importing Data
|
||||
|
||||
The SheetJS `sheet_to_json` function[^6] takes a worksheet object and generates
|
||||
an array of objects.
|
||||
The SheetJS [`sheet_to_json` function](/docs/api/utilities/array#array-output)
|
||||
accepts a worksheet object and generates an array of objects.
|
||||
|
||||
Queries must be manually generated from the objects. Assuming the field names
|
||||
in the object match the column headers, a loop can generate `INSERT` queries.
|
||||
@ -102,7 +103,7 @@ INSERT INTO table_name (?) VALUES (?);
|
||||
```
|
||||
|
||||
Queries are generated manually. To help prevent SQL injection vulnerabilities,
|
||||
the undocumented `escapeId` method [^7] escapes identifiers and fields.
|
||||
the undocumented `escapeId` method [^2] escapes identifiers and fields.
|
||||
|
||||
:::
|
||||
|
||||
@ -408,9 +409,4 @@ The output should be consistent with the following table:
|
||||
```
|
||||
|
||||
[^1]: See [the official `mysql2` website](https://sidorares.github.io/node-mysql2/docs) for more info.
|
||||
[^2]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input)
|
||||
[^3]: See ["Sheet Objects"](/docs/csf/sheet) in "SheetJS Data Model" for more details.
|
||||
[^4]: See ["Workbook Helpers" in "Utilities"](/docs/api/utilities/wb) for details on `book_new` and `book_append_sheet`.
|
||||
[^5]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
||||
[^6]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^7]: The `mysql2` connector library `escapeId` method is not mentioned in the documentation but is present in the TypeScript definitions.
|
||||
[^2]: The `mysql2` connector library `escapeId` method is not mentioned in the documentation but is present in the TypeScript definitions.
|
||||
|
||||
@ -12,7 +12,7 @@ import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
[MongoDB](https://mongodb.github.io/node-mongodb-native/) is a document-oriented
|
||||
database engine. [FerretDB](https://www.ferretdb.com/) is a truly open source
|
||||
implementation of the MongoDB wire protocol
|
||||
implementation of the MongoDB wire protocol.
|
||||
|
||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
||||
data from spreadsheets.
|
||||
@ -45,8 +45,10 @@ a row in the table.
|
||||
#### Importing Data
|
||||
|
||||
Data stored in an array of objects can be added to MongoDB Collections using
|
||||
`Collection#insertMany`[^1]. The SheetJS `sheet_to_json` method[^2] can generate
|
||||
data from worksheets:
|
||||
`Collection#insertMany`[^1].
|
||||
|
||||
The SheetJS [`sheet_to_json` method](/docs/api/utilities/array#array-output) can
|
||||
generate data from worksheets:
|
||||
|
||||
```js
|
||||
/* import data from a worksheet to a collection */
|
||||
@ -54,15 +56,15 @@ const aoo = XLSX.utils.sheet_to_json(ws);
|
||||
await collection.insertMany(aoo, {ordered: true});
|
||||
```
|
||||
|
||||
Typically worksheet objects are extracted from workbook objects[^3] generated
|
||||
from the SheetJS `read` or `readFile` methods[^4].
|
||||
Typically worksheets are extracted from [workbook objects](/docs/csf/book) that
|
||||
are created by SheetJS [`read` or `readFile`](/docs/api/parse-options) methods.
|
||||
|
||||
#### Exporting Data
|
||||
|
||||
`Collection#find`[^5] can pull an array of objects from a MongoDB Collection.
|
||||
`Collection#find`[^2] can pull an array of objects from a MongoDB Collection.
|
||||
|
||||
The SheetJS `json_to_sheet` method[^6] can take the result and generate a
|
||||
worksheet object.
|
||||
The SheetJS [`json_to_sheet`](/docs/api/utilities/array#array-of-objects-input)
|
||||
method can take the result and generate a worksheet object.
|
||||
|
||||
:::info pass
|
||||
|
||||
@ -79,13 +81,13 @@ const aoo = await collection.find({}, {projection:{_id:0}}).toArray();
|
||||
const ws = utils.json_to_sheet(aoo);
|
||||
```
|
||||
|
||||
Using `book_new` and `book_append_sheet`[^7], a workbook object can be created.
|
||||
This workbook is typically exported to the filesystem with `writeFile`[^8].
|
||||
Using [`book_new` and `book_append_sheet`](/docs/api/utilities/wb), a workbook
|
||||
object can be created. This workbook is typically exported to the filesystem
|
||||
with the [`writeFile`](/docs/api/write-options) method.
|
||||
|
||||
## Complete Example
|
||||
|
||||
0) Install a MongoDB-compatible server. Options include MongoDB CE[^9] and
|
||||
FerretDB[^10]
|
||||
0) Install a MongoDB-compatible server (MongoDB CE[^3] or FerretDB[^4]).
|
||||
|
||||
1) Start a server on `localhost` (follow official instructions).
|
||||
|
||||
@ -247,12 +249,6 @@ There should be no errors in the terminal. The script will generate the file
|
||||
`SheetJSMongoCRUD.xlsx`. That file can be opened in a spreadsheet editor.
|
||||
|
||||
[^1]: See [`insertMany`](https://mongodb.github.io/node-mongodb-native/5.7/classes/Collection.html#insertMany) in the MongoDB documentation.
|
||||
[^2]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^3]: See ["Workbook Object"](/docs/csf/book)
|
||||
[^4]: See [`read` and `readFile` in "Reading Files"](/docs/api/parse-options)
|
||||
[^5]: See [`find`](https://mongodb.github.io/node-mongodb-native/5.7/classes/Collection.html#find) in the MongoDB documentation.
|
||||
[^6]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input)
|
||||
[^7]: See ["Workbook Helpers" in "Utilities"](/docs/api/utilities/wb) for details on `book_new` and `book_append_sheet`.
|
||||
[^8]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
||||
[^9]: See ["Install MongoDB Community Edition"](https://www.mongodb.com/docs/manual/administration/install-community/#std-label-install-mdb-community-edition) in the MongoDB documentation.
|
||||
[^10]: See ["SQLite Setup with Docker Compose"](https://docs.ferretdb.io/quickstart-guide/docker/#sqlite-setup-with-docker-compose) in the FerretDB documentation.
|
||||
[^2]: See [`find`](https://mongodb.github.io/node-mongodb-native/5.7/classes/Collection.html#find) in the MongoDB documentation.
|
||||
[^3]: See ["Install MongoDB Community Edition"](https://www.mongodb.com/docs/manual/administration/install-community/#std-label-install-mdb-community-edition) in the MongoDB documentation.
|
||||
[^4]: See ["SQLite Setup with Docker Compose"](https://docs.ferretdb.io/quickstart-guide/docker/#sqlite-setup-with-docker-compose) in the FerretDB documentation.
|
||||
@ -29,13 +29,13 @@ This demo was tested in the following environments:
|
||||
|
||||
| PouchDB | Date |
|
||||
|:--------|:----------:|
|
||||
| `9.0.0` | 2025-01-19 |
|
||||
| `8.0.1` | 2025-01-19 |
|
||||
| `7.3.1` | 2025-01-19 |
|
||||
| `6.4.3` | 2025-01-19 |
|
||||
| `5.4.5` | 2025-01-19 |
|
||||
| `4.0.3` | 2025-01-19 |
|
||||
| `3.6.0` | 2025-01-19 |
|
||||
| `9.0.0` | 2026-01-08 |
|
||||
| `8.0.1` | 2026-01-08 |
|
||||
| `7.3.1` | 2026-01-08 |
|
||||
| `6.4.3` | 2026-01-08 |
|
||||
| `5.4.5` | 2026-01-08 |
|
||||
| `4.0.3` | 2026-01-08 |
|
||||
| `3.6.0` | 2026-01-08 |
|
||||
|
||||
:::
|
||||
|
||||
@ -53,20 +53,18 @@ The `PouchDB` constructor returns a `Database` object.
|
||||
#### Importing Data
|
||||
|
||||
`Database#bulkDocs`[^2] is the standard approach for bulk data import. The method
|
||||
accepts "arrays of objects" that can be generated through the SheetJS
|
||||
`sheet_to_json`[^3] method.
|
||||
accepts "arrays of objects" that can be generated using the SheetJS
|
||||
[`sheet_to_json`](/docs/api/utilities/array#array-output) method.
|
||||
|
||||
If rows do not include the `_id` parameter, the database will automatically
|
||||
assign an ID per row. It is strongly recommended to generate the `_id` directly.
|
||||
|
||||
This method starts from a SheetJS workbook object[^4] and uses data from the
|
||||
first sheet. `read` and `readFile`[^5] can generate workbook objects from files.
|
||||
|
||||
```js
|
||||
async function push_first_sheet_to_pouchdb(db, wb, _id_) {
|
||||
/* get first worksheet */
|
||||
const ws = wb.Sheets[wb.SheetNames[0]];
|
||||
This method starts from a SheetJS [worksheet object](/docs/csf/sheet) and uses
|
||||
data from the first sheet. [`read` and `readFile`](/docs/api/parse-options) can
|
||||
generate workbook objects from files.
|
||||
|
||||
```js title="Extract data from a SheetJS worksheet and push to PouchDB"
|
||||
async function push_sheet_to_pouchdb(db, ws, _id_) {
|
||||
/* generate array of objects */
|
||||
const aoo = XLSX.utils.sheet_to_json(ws);
|
||||
|
||||
@ -86,14 +84,15 @@ Existing data can be erased with `Database#destroy`.
|
||||
|
||||
#### Exporting Data
|
||||
|
||||
`Database#allDocs`[^6] is the standard approach for bulk data export. Generated
|
||||
`Database#allDocs`[^3] is the standard approach for bulk data export. Generated
|
||||
row objects have additional `_id` and `_rev` keys that should be removed.
|
||||
|
||||
After removing the PouchDB internal fields, the SheetJS `json_to_sheet`[^7]
|
||||
method can generate a worksheet. Other utility functions[^8] can construct a
|
||||
workbook. The workbook can be exported with the SheetJS `writeFile`[^9] method:
|
||||
The SheetJS [`json_to_sheet`](/docs/api/utilities/array#array-of-objects-input)
|
||||
method can generate a worksheet. [API functions](/docs/api/utilities/wb) can
|
||||
generate a workbook object. The [`writeFile`](/docs/api/write-options) method
|
||||
will attempt to download the generated workbook:
|
||||
|
||||
```js
|
||||
```js title="Extract data from PouchDB and export to XLSX using SheetJS"
|
||||
function export_pouchdb_to_xlsx(db) {
|
||||
/* fetch all rows, including the underlying data */
|
||||
db.allDocs({include_docs: true}, function(err, doc) {
|
||||
@ -171,8 +170,8 @@ cd getting-started-todo-master
|
||||
<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>
|
||||
<button id="xport">Export!</button>
|
||||
<!-- highlight-end -->
|
||||
<section id="todoapp">`}
|
||||
</CodeBlock>
|
||||
<section id="todoapp">
|
||||
`}</CodeBlock>
|
||||
|
||||
3) Near the end of `index.html`, look for a script tag referencing a CDN:
|
||||
|
||||
@ -180,7 +179,7 @@ cd getting-started-todo-master
|
||||
<script src="//cdn.jsdelivr.net/pouchdb/3.2.0/pouchdb.min.js"></script>
|
||||
```
|
||||
|
||||
Upgrade PouchDB by changing the `src` attribute to the production build[^10]:
|
||||
Upgrade PouchDB by changing the `src` attribute to the production build[^4]:
|
||||
|
||||
```html title="index.html (replace line)"
|
||||
<script src="//cdn.jsdelivr.net/npm/pouchdb@8.0.1/dist/pouchdb.min.js"></script>
|
||||
@ -228,7 +227,7 @@ order of todo items in the export matches the list displayed in the webpage.
|
||||
5) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server .
|
||||
npx -y http-server .
|
||||
```
|
||||
|
||||
The command will display a URL (typically `http://localhost:8080`) which can be
|
||||
@ -255,11 +254,5 @@ export named "SheetJSPouch.xlsx"
|
||||
|
||||
[^1]: See ["Setting up PouchDB"](https://pouchdb.com/guides/setup-pouchdb.html) in the PouchDB documentation.
|
||||
[^2]: See ["Create/update a batch of documents"](https://pouchdb.com/api.html#batch_create) in the PouchDB API documentation
|
||||
[^3]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^4]: See ["SheetJS Data Model"](/docs/csf)
|
||||
[^5]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^6]: See ["Fetch a batch of documents"](https://pouchdb.com/api.html#batch_fetch) in the PouchDB API documentation
|
||||
[^7]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input)
|
||||
[^8]: See ["Workbook Helpers" in "Utilities"](/docs/api/utilities/wb) for details on `book_new` and `book_append_sheet`.
|
||||
[^9]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
||||
[^10]: The ["Quick Start" section of "Download"](https://pouchdb.com/download.html#file) in the PouchDB website describes the recommended CDN for PouchDB scripts.
|
||||
[^3]: See ["Fetch a batch of documents"](https://pouchdb.com/api.html#batch_fetch) in the PouchDB API documentation
|
||||
[^4]: The ["Quick Start" section of "Download"](https://pouchdb.com/download.html#file) in the PouchDB website describes the recommended CDN for PouchDB scripts.
|
||||
@ -291,7 +291,7 @@ following screenshot was taken in Chrome 126.0.6478.127:
|
||||
|
||||
This is a browser limitation and no pure JavaScript library can work around the
|
||||
issue. See [Issue #3145](https://git.sheetjs.com/sheetjs/sheetjs/issues/3145) in
|
||||
the SheetJS bug tracker for more details.
|
||||
the SheetJS CE bug tracker for more details.
|
||||
|
||||
:::
|
||||
|
||||
@ -466,15 +466,15 @@ This browser demo was tested in the following environments:
|
||||
|
||||
| Browser | Date |
|
||||
|:-------------|:-----------|
|
||||
| Chromium 131 | 2025-01-07 |
|
||||
| Chromium 142 | 2025-11-15 |
|
||||
|
||||
Some lesser-used browsers do not support File System Access API:
|
||||
|
||||
| Browser | Date |
|
||||
|:-------------|:-----------|
|
||||
| Safari 17.5 | 2025-01-07 |
|
||||
| Safari 26.1 | 2025-11-15 |
|
||||
| Konqueror 22 | 2025-04-23 |
|
||||
| Firefox 133 | 2025-01-07 |
|
||||
| Firefox 139 | 2025-06-20 |
|
||||
|
||||
:::
|
||||
|
||||
@ -836,4 +836,4 @@ Desktop and mobile apps have their own specific APIs covered in separate demos:
|
||||
[^1]: See ["Input Type" in "Reading Files"](/docs/api/parse-options#input-type)
|
||||
[^2]: See ["Supported Output Formats" type in "Writing Files"](/docs/api/write-options#supported-output-formats)
|
||||
[^3]: See ["Buffers and TypedArrays"](https://nodejs.org/api/buffer.html#buffers-and-typedarrays) in the NodeJS documentation.
|
||||
[^4]: See [issue 3145 in the SheetJS bug tracker](https://git.sheetjs.com/sheetjs/sheetjs/issues/3145#issuecomment-11074) for more details. Special thanks to `@sjoenH`!
|
||||
[^4]: See [issue 3145 in the SheetJS CE bug tracker](https://git.sheetjs.com/sheetjs/sheetjs/issues/3145#issuecomment-11074) for more details. Special thanks to `@sjoenH`!
|
||||
@ -11,8 +11,10 @@ simple key-value stores that only support string values and keys.
|
||||
|
||||
This demo covers two common use patterns:
|
||||
|
||||
- "Row Objects" shows a simple convention for loading and storing row objects
|
||||
- "Simple Strings" discusses how to persist and recover a raw Storage
|
||||
- ["Row Objects"](#row-objects) shows a simple convention for loading and
|
||||
storing row objects.
|
||||
- ["Simple Strings"](#simple-strings) discusses how to persist and recover keys
|
||||
and string values.
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
@ -20,8 +22,8 @@ Each browser demo was tested in the following environments:
|
||||
|
||||
| Browser | Date |
|
||||
|:-------------|:-----------|
|
||||
| Chromium 131 | 2024-12-23 |
|
||||
| Safari 18.2 | 2024-12-31 |
|
||||
| Chromium 136 | 2025-05-21 |
|
||||
| Safari 18.2 | 2025-05-21 |
|
||||
| Konqueror 22 | 2025-04-23 |
|
||||
|
||||
:::
|
||||
@ -49,10 +51,13 @@ strings using `JSON.stringify` and store using the row index as a key:
|
||||
|
||||
#### Importing Data
|
||||
|
||||
Starting from a worksheet, the SheetJS `sheet_to_json` method[^1] generates an
|
||||
array of row objects. `localStorage.setItem` will store data in Local Storage:
|
||||
`localStorage.setItem` will store data in Local Storage.
|
||||
|
||||
```js
|
||||
Starting from a worksheet, the SheetJS `sheet_to_json` method[^1] generates an
|
||||
array of row objects. Each object in the array can be saved in the Local Storage
|
||||
using the row index as the key.
|
||||
|
||||
```js title="Store a SheetJS worksheet in Local Storage"
|
||||
function sheet_to_localStorage(worksheet) {
|
||||
const aoo = XLSX.utils.sheet_to_json(worksheet);
|
||||
for(let i = 0; i < aoo.length; ++i) {
|
||||
@ -96,7 +101,7 @@ function localStorage_to_array_of_objects() {
|
||||
The SheetJS `json_to_sheet`[^2] method will create a new worksheet from the
|
||||
array of objects:
|
||||
|
||||
```js
|
||||
```js title="Generate a SheetJS worksheet from records in Local Storage "
|
||||
function localStorage_to_sheet() {
|
||||
const aoo = [];
|
||||
for(let i = 0; i < localStorage.length; ++i) {
|
||||
@ -118,8 +123,8 @@ After saving the exported file, the Local Storage can be inspected in the
|
||||
|
||||
:::caution pass
|
||||
|
||||
This example is for illustration purposes. If array of objects is available, it
|
||||
is strongly recommended to convert that array to a worksheet directly.
|
||||
This example is for illustration purposes. If an array of objects is available,
|
||||
it is strongly recommended to convert that array to a worksheet directly.
|
||||
|
||||
:::
|
||||
|
||||
@ -203,7 +208,7 @@ In modern browsers, `Object.entries` will generate an array of key/value pairs.
|
||||
The SheetJS `aoa_to_sheet`[^3] method will interpret that array as a worksheet
|
||||
with 2 columns (key and value):
|
||||
|
||||
```js
|
||||
```js title="Generate a SheetJS two-column worksheet from Local Storage"
|
||||
function localStorage_to_ws() {
|
||||
const aoa = Object.entries(localStorage);
|
||||
return XLSX.utils.aoa_to_sheet(aoa);
|
||||
@ -216,7 +221,7 @@ In the other direction, the worksheet is assumed to store keys in column A and
|
||||
values in column B. The SheetJS `sheet_to_json`[^1] method, with the option
|
||||
`header: 1`, will generate key/value pairs that can be assigned to a storage:
|
||||
|
||||
```js
|
||||
```js title="Store a SheetJS two-column worksheet in Local Storage"
|
||||
function ws_to_localStorage(ws) {
|
||||
const aoa = XLSX.utils.sheet_to_json(ws, { header: 1 });
|
||||
aoa.forEach(([key, val]) => localStorage.setItem(key, val));
|
||||
|
||||
@ -8,7 +8,7 @@ sidebar_custom_props:
|
||||
|
||||
<head>
|
||||
<script type="text/javascript" src="https://unpkg.com/localforage@1.10.0/dist/localforage.min.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/dexie@4.0.10/dist/dexie.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/dexie@4.0.11/dist/dexie.js"></script>
|
||||
</head>
|
||||
|
||||
:::danger pass
|
||||
@ -43,8 +43,8 @@ This demo was last tested in the following environments:
|
||||
|
||||
| Browser | Date | `localForage` |
|
||||
|:-------------|:-----------|:--------------|
|
||||
| Chromium 131 | 2024-12-31 | `1.10.0` |
|
||||
| Safari 18.2 | 2024-12-31 | `1.10.0` |
|
||||
| Chromium 136 | 2025-05-21 | `1.10.0` |
|
||||
| Safari 18.2 | 2025-05-21 | `1.10.0` |
|
||||
| Konqueror 22 | 2025-04-23 | `1.10.0` |
|
||||
|
||||
:::
|
||||
@ -116,8 +116,8 @@ This demo was last tested in the following environments:
|
||||
|
||||
| Browser | Date | DexieJS |
|
||||
|:-------------|:-----------|:---------|
|
||||
| Chromium 131 | 2024-12-31 | `4.0.10` |
|
||||
| Safari 18.2 | 2024-12-31 | `4.0.10` |
|
||||
| Chromium 136 | 2025-05-21 | `4.0.11` |
|
||||
| Safari 18.2 | 2025-05-21 | `4.0.11` |
|
||||
| Konqueror 22 | 2025-04-23 | `4.0.10` |
|
||||
|
||||
:::
|
||||
|
||||
@ -33,7 +33,7 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Lightning API | Date |
|
||||
|:--------------|:-----------|
|
||||
| `61.0` | 2024-10-06 |
|
||||
| `62.0` | 2025-05-27 |
|
||||
|
||||
:::
|
||||
|
||||
@ -331,7 +331,7 @@ npx @salesforce/cli --version
|
||||
When the demo was last tested, the command printed
|
||||
|
||||
```
|
||||
@salesforce/cli/2.60.13 darwin-arm64 node-v20.18.0
|
||||
@salesforce/cli/2.89.8 win32-x64 node-v24.1.0
|
||||
```
|
||||
|
||||
:::
|
||||
@ -380,7 +380,7 @@ with the following XML:
|
||||
```xml title="force-app\main\default\lwc\sheetComponent\sheetComponent.js-meta.xml (replace highlighted lines)"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>61.0</apiVersion>
|
||||
<apiVersion>62.0</apiVersion>
|
||||
<!-- highlight-start -->
|
||||
<isExposed>true</isExposed>
|
||||
<masterLabel>SheetForce</masterLabel>
|
||||
@ -412,7 +412,7 @@ A) In the Salesforce site, click on the gear icon in the top-right corner of the
|
||||
page and select "Setup" (Setup for current app).
|
||||
|
||||
B) Type "Custom Code" in the left sidebar search box. Expand "Custom Code",
|
||||
expand "Lightning Components" and click "Lightning Components".
|
||||
expand "Lightning Components" and click the inner "Lightning Components".
|
||||
|
||||
:::caution pass
|
||||
|
||||
@ -430,8 +430,8 @@ Click the link to open the page in Salesforce Classic.
|
||||
|
||||
A) Click the "Setup" link in the top-right corner of the page.
|
||||
|
||||
B) Type "Lightning" in the left sidebar search box. Expand "Develop", expand
|
||||
"Lightning Components" and click "Lightning Components".
|
||||
B) Type "Custom Code" in the left sidebar search box. In the section, expand
|
||||
"Lightning Components" and click the inner "Lightning Components".
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
@ -505,7 +505,8 @@ When the "Page Saved" modal is displayed, click "Activate".
|
||||
|
||||
The following options should be set:
|
||||
- Click "Change..." next to "Icon" and pick a memorable icon
|
||||
- Under "Lightning Experience" click "LightningBolt" then "Add page to app"
|
||||
- Under "Lightning Experience" select "LightningBolt" in the left column and
|
||||
click "Add page to app" in the right side
|
||||
|
||||
Click "Save" to activate the page.
|
||||
|
||||
|
||||
@ -24,10 +24,10 @@ This demo was verified by NetSuite consultants in the following deployments:
|
||||
|
||||
| `@NScriptType` | `@NApiVersion` | Date |
|
||||
|:----------------|:---------------|:-----------|
|
||||
| ScheduledScript | 2.1 | 2024-12-06 |
|
||||
| Restlet | 2.1 | 2024-12-06 |
|
||||
| Suitelet | 2.1 | 2024-12-06 |
|
||||
| MapReduceScript | 2.1 | 2024-12-06 |
|
||||
| ScheduledScript | 2.1 | 2025-06-08 |
|
||||
| Restlet | 2.1 | 2025-06-08 |
|
||||
| Suitelet | 2.1 | 2025-06-08 |
|
||||
| MapReduceScript | 2.1 | 2025-06-08 |
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ will be available in the future.
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2024-06-12.
|
||||
This demo was last tested on 2025-05-11.
|
||||
|
||||
:::
|
||||
|
||||
@ -59,7 +59,8 @@ Azure Functions Core Tools (`func`) telemetry is controlled through the
|
||||
<Tabs groupId="os">
|
||||
<TabItem value="unix" label="Linux/MacOS">
|
||||
|
||||
Add the following line to `.profile`, `.bashrc` and `.zshrc`:
|
||||
Add the following line to `.profile`, `.bash_profile`, `.bashrc`, `.zprofile`,
|
||||
`.zshrc`, and any other configuration files:
|
||||
|
||||
```bash
|
||||
export FUNCTIONS_CORE_TOOLS_TELEMETRY_OPTOUT=1
|
||||
@ -131,7 +132,7 @@ Uploaded files can be pulled into `ArrayBuffer` objects.
|
||||
|
||||
This function returns a promise that resolves to an `ArrayBuffer` object:
|
||||
|
||||
```js
|
||||
```js title="Get raw data from an uploaded file"
|
||||
const { Blob } = require('buffer');
|
||||
|
||||
async function get_file_from_request(request, form_field_name) {
|
||||
@ -158,7 +159,7 @@ SheetJS workbook objects[^3] which can be processed with other API functions.
|
||||
For example, a handler can use `sheet_to_csv`[^4] to generate CSV text from
|
||||
user-submitted spreadsheets:
|
||||
|
||||
```js
|
||||
```js title="Function that reads uploaded workbooks and converts to CSV"
|
||||
const { Blob } = require('buffer');
|
||||
const { app } = require('@azure/functions');
|
||||
const XLSX = require('xlsx');
|
||||
@ -194,7 +195,7 @@ The following example generates a sample worksheet using the `aoa_to_sheet`[^6]
|
||||
method, generates a sample workbook using worksheet helper methods[^7], writes
|
||||
the workbook to XLSX format in a Buffer, and sends the Buffer in the response:
|
||||
|
||||
```js
|
||||
```js title="Function that exports data and initiates a download to XLSX"
|
||||
const { app } = require('@azure/functions');
|
||||
const XLSX = require('xlsx');
|
||||
|
||||
@ -299,10 +300,20 @@ Until the bugs are resolved, JavaScript should be preferred over TypeScript.
|
||||
npm start
|
||||
```
|
||||
|
||||
7) While the server is running, open a new terminal window and make a request:
|
||||
The process will display the functions and respective URLs:
|
||||
|
||||
```text title="Expected output"
|
||||
Functions:
|
||||
|
||||
SheetJSAzure: [GET,POST] http://localhost:7071/api/SheetJSAzure
|
||||
(access this URL)------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
```
|
||||
|
||||
7) While the server is running, open a new terminal window and make a GET
|
||||
request to the URL listed in the previous step:
|
||||
|
||||
```bash
|
||||
curl -L http://localhost:7071/api/SheetJSAzure
|
||||
curl http://localhost:7071/api/SheetJSAzure
|
||||
```
|
||||
|
||||
The terminal should display `Hello, world!`
|
||||
@ -333,7 +344,7 @@ npm start
|
||||
make a POST request to the dev server:
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/pres.numbers
|
||||
curl -o pres.numbers https://docs.sheetjs.com/pres.numbers
|
||||
curl -X POST -F "upload=@pres.numbers" http://localhost:7071/api/SheetJSAzure
|
||||
```
|
||||
|
||||
@ -354,19 +365,20 @@ Open in Excel or another spreadsheet editor to confirm the file is valid.
|
||||
|
||||
15) Click "+ Create"
|
||||
|
||||
16) Select the following options:
|
||||
16) In the "Create Function App" screen, click "Consumption" and click "Select".
|
||||
|
||||
- "Select a hosting option": "Consumption"
|
||||
17) In the next screen, select the following options:
|
||||
|
||||
- Type a memorable "Function Name" ("sheetjsazure" when last tested)
|
||||
- Look for the "Function App name" input field and type a memorable function
|
||||
name. When this demo was last tested, the name "sheetjsazure" was chosen.
|
||||
|
||||
- "Operating System": "Windows"
|
||||
|
||||
- "Runtime stack": select `Node.js`
|
||||
|
||||
17) Click "Review + create", then click "Create" to create the function.
|
||||
18) Click "Review + create", then click "Create" to create the function.
|
||||
|
||||
The page will display a status message
|
||||
The page will redirect to a new page. It will display a status message:
|
||||
|
||||
> ... Deployment is in progress
|
||||
|
||||
@ -374,21 +386,19 @@ When the resources are configured, the status will change to
|
||||
|
||||
> Your deployment is complete
|
||||
|
||||
18) Click "Go to Resource".
|
||||
|
||||
19) Take note of the URL from the "Essentials" table.
|
||||
19) Click "Go to Resource".
|
||||
|
||||
#### Deploy to Azure
|
||||
|
||||
20) Sign into Azure:
|
||||
20) Sign into Azure from the command line:
|
||||
|
||||
```
|
||||
```bash
|
||||
az login
|
||||
```
|
||||
|
||||
The login flow resumes in the browser.
|
||||
|
||||
21) Deploy to Azure. Replace `FUNCTION_NAME` with the name from Step 16:
|
||||
21) Deploy to Azure. Replace `FUNCTION_NAME` with the name from Step 17:
|
||||
|
||||
```bash
|
||||
func azure functionapp publish FUNCTION_NAME
|
||||
@ -429,7 +439,7 @@ make a POST request to the production server. Replace `FUNCTION_URL` with the
|
||||
Invoke URL from Step 21:
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/pres.numbers
|
||||
curl -o pres.numbers https://docs.sheetjs.com/pres.numbers
|
||||
curl -X POST -F "upload=@pres.numbers" FUNCTION_URL
|
||||
```
|
||||
|
||||
@ -546,9 +556,9 @@ requests and 2000 write requests per month.
|
||||
|
||||
- "Redundancy": select LRS (Locally-redundant storage)
|
||||
|
||||
5) Click "Review", then click "Create" to create the storage.
|
||||
5) Click "Review + create", then click "Create" to create the storage.
|
||||
|
||||
The page will display a status message
|
||||
The page will redirect to a new page. It will display a status message:
|
||||
|
||||
> ... Deployment is in progress
|
||||
|
||||
@ -596,11 +606,64 @@ npm init -y
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @azure/storage-blob`}
|
||||
</CodeBlock>
|
||||
|
||||
14) Copy the [`SheetJSReadFromAzure.mjs` code block](#downloading-data) and save
|
||||
to `SheetJSReadFromAzure.mjs`.
|
||||
14) Save the following codeblock to `SheetJSReadFromAzure.mjs`:
|
||||
|
||||
15) Copy the [`SheetJSWriteToAzure.mjs` code block](#uploading-data) and save
|
||||
to `SheetJSWriteToAzure.mjs`.
|
||||
```js title="SheetJSReadFromAzure.mjs"
|
||||
import { BlobServiceClient } from "@azure/storage-blob";
|
||||
import { read, utils } from "xlsx";
|
||||
|
||||
/* replace these constants */
|
||||
// highlight-start
|
||||
const connStr = "<REPLACE WITH CONNECTION STRING>";
|
||||
const containerName = "<REPLACE WITH CONTAINER NAME>";
|
||||
// highlight-end
|
||||
|
||||
/* Blob name */
|
||||
const blobName = "SheetJSBloblobber.xlsx";
|
||||
|
||||
/* get a readable stream*/
|
||||
const blobServiceClient = BlobServiceClient.fromConnectionString(connStr);
|
||||
const containerClient = blobServiceClient.getContainerClient(containerName);
|
||||
const blobClient = containerClient.getBlobClient(blobName);
|
||||
const response = (await blobClient.download()).readableStreamBody;
|
||||
|
||||
/* collect data into a Buffer */
|
||||
const bufs = [];
|
||||
for await(const buf of response) bufs.push(buf);
|
||||
const downloaded = Buffer.concat(bufs);
|
||||
|
||||
/* parse downloaded buffer */
|
||||
const wb = read(downloaded);
|
||||
/* print first worksheet */
|
||||
console.log(utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]));
|
||||
```
|
||||
|
||||
15) Save the following codeblock to `SheetJSWriteToAzure.mjs`:
|
||||
|
||||
```js title="SheetJSWriteToAzure.mjs"
|
||||
import { BlobServiceClient } from "@azure/storage-blob";
|
||||
import { write, utils } from "xlsx";
|
||||
|
||||
/* replace these constants */
|
||||
// highlight-start
|
||||
const connStr = "<REPLACE WITH CONNECTION STRING>";
|
||||
const containerName = "<REPLACE WITH CONTAINER NAME>";
|
||||
// highlight-end
|
||||
|
||||
/* Blob name */
|
||||
const blobName = "SheetJSBloblobber.xlsx";
|
||||
|
||||
/* Create a simple workbook and write XLSX to buffer */
|
||||
const ws = utils.aoa_to_sheet(["SheetJS".split(""), [5,4,3,3,7,9,5]]);
|
||||
const wb = utils.book_new(); utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
const buf = write(wb, {type: "buffer", bookType: "xlsx"});
|
||||
|
||||
/* upload buffer */
|
||||
const blobServiceClient = BlobServiceClient.fromConnectionString(connStr);
|
||||
const containerClient = blobServiceClient.getContainerClient(containerName);
|
||||
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
|
||||
const uploadBlobResponse = await blockBlobClient.upload(buf, buf.length);
|
||||
```
|
||||
|
||||
16) Edit both `SheetJSReadFromAzure.mjs` and `SheetJSWriteToAzure.mjs`:
|
||||
|
||||
@ -616,7 +679,7 @@ the buffer to a file named `SheetJSBloblobber.xlsx` on Azure Blob Storage.
|
||||
|
||||
The read demo fetches `SheetJSBloblobber.xlsx` and displays the data.
|
||||
|
||||
```
|
||||
```text title="Data in SheetJSBloblobber.xlsx"
|
||||
| A | B | C | D | E | F | G |
|
||||
---+---|---|---|---|---|---|---|
|
||||
1 | S | h | e | e | t | J | S |
|
||||
@ -641,7 +704,7 @@ node SheetJSReadFromAzure.mjs
|
||||
|
||||
It will fetch the file created in the previous step and display CSV rows.
|
||||
|
||||
```
|
||||
```text title="Expected output"
|
||||
S,h,e,e,t,J,S
|
||||
5,4,3,3,7,9,5
|
||||
```
|
||||
|
||||
@ -8,7 +8,7 @@ pagination_next: demos/extensions/index
|
||||
import current from '/version.js';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
[Deno Deploy](https://dash.deno.com/) offers distributed "Serverless Functions"
|
||||
[Deno Deploy](https://deno.com/deploy) offers distributed "Serverless Functions"
|
||||
powered by Deno.
|
||||
|
||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
||||
@ -22,7 +22,7 @@ types of spreadsheets to HTML tables and CSV rows.
|
||||
|
||||
:::caution pass
|
||||
|
||||
When the demo was last tested, Deno Deploy required a GitHub account.
|
||||
When the demo was last tested, Deno Deploy required a GitHub or Google account.
|
||||
|
||||
:::
|
||||
|
||||
@ -82,9 +82,9 @@ class SheetJSResource extends Drash.Resource {
|
||||
|
||||
## Demo
|
||||
|
||||
0) Create a new GitHub account or sign into an existing account.
|
||||
0) Create a new Github or Google account, or sign into an existing account.
|
||||
|
||||
1) Open the [main Deno Deploy portal](https://dash.deno.com/) in a browser.
|
||||
1) Open the [main Deno Deploy portal](https://console.deno.com/) in a browser.
|
||||
|
||||
2) If the account never signed into Deno Deploy, click "Continue with Github".
|
||||
|
||||
|
||||
@ -111,6 +111,7 @@ const jwt = new google.auth.JWT({
|
||||
key: creds.private_key,
|
||||
scopes: [
|
||||
'https://www.googleapis.com/auth/spreadsheets', // Google Sheets
|
||||
'https://www.googleapis.com/auth/drive', // Google Drive
|
||||
'https://www.googleapis.com/auth/drive.file', // Google Drive
|
||||
]
|
||||
});
|
||||
@ -495,7 +496,7 @@ At this point `wb` is a SheetJS workbook object[^10].
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2024-06-08 using `googleapis` version `140.0.0`.
|
||||
This demo was last tested on 2025-05-14 using `googleapis` version `148.0.0`.
|
||||
The demo uses Sheets v4 and Drive v3 APIs.
|
||||
|
||||
:::
|
||||
@ -551,10 +552,10 @@ be a selection box. Click the `▼` icon to show the modal.
|
||||
|
||||
If the selection box is missing, expand the browser window.
|
||||
|
||||
3) Click "NEW PROJECT" in the top right corner of the modal.
|
||||
3) Click "New project" in the top right corner of the modal.
|
||||
|
||||
4) In the New Project screen, enter "SheetJS Test" in the Project name textbox
|
||||
and select "No organization" in the Location box. Click "CREATE".
|
||||
and select "No organization" in the Location box. Click "Create".
|
||||
|
||||
A notification will confirm that the project was created:
|
||||
|
||||
@ -569,14 +570,13 @@ The goal of this section is to enable Google Sheets API and Google Drive API.
|
||||
|
||||
:::
|
||||
|
||||
5) Open the Project Selector (`▼` icon) and select "SheetJS Test"
|
||||
5) Click "Select a project" and select "SheetJS Test" from the Recent tab.
|
||||
|
||||
6) In the search bar, type "Enabled" and select "Enabled APIs & services". This
|
||||
item will be in the "PRODUCTS & PAGES" part of the search results.
|
||||
6) In the search bar, type "Enabled" and select "Enabled APIs & services".
|
||||
|
||||
#### Enable Google Sheets API
|
||||
|
||||
7) Near the top of the page, click "+ ENABLE APIS AND SERVICES".
|
||||
7) Near the top of the page, click "+ Enable APIs and services".
|
||||
|
||||
8) In the search bar near the middle of the page (not the search bar at the top),
|
||||
type "Sheets" and press <kbd>Enter</kbd>.
|
||||
@ -585,11 +585,11 @@ In the results page, look for "Google Sheets API". Click the card
|
||||
|
||||
9) In the Product Details screen, click the blue "ENABLE" button.
|
||||
|
||||
10) Click the left arrow (`<-`) next to "API/Service details".
|
||||
10) Click the left arrow (`<-`) next to "API/Service Details".
|
||||
|
||||
#### Enable Google Drive API
|
||||
|
||||
11) Near the top of the page, click "+ ENABLE APIS AND SERVICES".
|
||||
11) Near the top of the page, click "+ Enable APIs and services".
|
||||
|
||||
12) In the search bar near the middle of the page (not the search bar at the top),
|
||||
type "Drive" and press <kbd>Enter</kbd>.
|
||||
@ -614,13 +614,13 @@ the top bar.
|
||||
15) Click the Project Selector (`:·` icon) and select "SheetJS Test".
|
||||
|
||||
16) In the search bar, type "Credentials" and select the "Credentials" item with
|
||||
subtitle "APIs & Services". This item will be in the "PRODUCTS & PAGES" group:
|
||||
subtitle "APIs & Services":
|
||||
|
||||

|
||||
|
||||
17) Click "+ CREATE CREDENTIALS". In the dropdown, select "Service Account"
|
||||
17) Click "+ Create credentials". In the dropdown, select "Service account"
|
||||
|
||||
18) Enter "SheetJService" for Service account name. Click "CREATE AND CONTINUE"
|
||||
18) Enter "SheetJService" for Service account name. Click "Create and continue".
|
||||
|
||||
:::note pass
|
||||
|
||||
@ -628,24 +628,24 @@ The Service account ID is generated automatically.
|
||||
|
||||
:::
|
||||
|
||||
19) In Step 2 "Grant this service account access to project", click CONTINUE
|
||||
19) In Step 2 "Grant this service account access to project", click Continue.
|
||||
|
||||
20) In Step 3 click "DONE". You will be taken back to the credentials screen
|
||||
20) In Step 3 click "Done". You will be taken back to the credentials screen
|
||||
|
||||
#### Create JSON Key
|
||||
|
||||
21) Look for "SheetJService" in the "Service Accounts" table and click the email
|
||||
address in the row.
|
||||
|
||||
22) Click "KEYS" in the horizontal bar near the top of the page.
|
||||
22) Click "Keys" in the horizontal bar near the top of the page.
|
||||
|
||||
23) Click "ADD KEY" and select "Create new key" in the dropdown.
|
||||
23) Click "Add key" and select "Create new key" in the dropdown.
|
||||
|
||||
24) In the popup, select the "JSON" radio button and click "CREATE".
|
||||
24) In the popup, select the "JSON" radio button and click "Create".
|
||||
|
||||
The page will download a JSON file. If prompted, allow the download.
|
||||
|
||||
25) Click "CLOSE"
|
||||
25) Click "Close"
|
||||
|
||||
### Create Document
|
||||
|
||||
@ -675,7 +675,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz googlea
|
||||
29) Download [`init.mjs`](pathname:///gsheet/init.mjs):
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/gsheet/init.mjs
|
||||
curl -o init.mjs https://docs.sheetjs.com/gsheet/init.mjs
|
||||
```
|
||||
|
||||
Edit the marked lines near the top of the file:
|
||||
@ -713,11 +713,12 @@ Shared a-long-string-of-characters with YOUR_ACCOUNT@gmail.com
|
||||
The long string of characters after "Created Google Workbook" is the ID. Take
|
||||
note of this ID.
|
||||
|
||||
31) Sign into Google Sheets. A shared document "SheetJS Test" should be
|
||||
displayed in the table. It will be owned by the service account.
|
||||
31) Sign into Google Drive and select "Shared with me" from the left sidebar. A
|
||||
shared document "SheetJS Test" should be displayed in the table. It will be
|
||||
owned by the service account.
|
||||
|
||||
32) Open the shared document from step 31 and confirm that the document has two
|
||||
worksheets named "SheetJS1" and "SheetJS2".
|
||||
32) Click `⋮` next to "SheetJS Test" and select "Open with" > "Google Sheets".
|
||||
Confirm that the document has two worksheets named "SheetJS1" and "SheetJS2".
|
||||
|
||||
Confirm the worksheet data matches the following screenshots:
|
||||
|
||||
@ -786,13 +787,13 @@ NUMBERS file.
|
||||
34) Download the [test file `pres.numbers`](https://docs.sheetjs.com/pres.numbers):
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/pres.numbers
|
||||
curl -o pres.numbers https://docs.sheetjs.com/pres.numbers
|
||||
```
|
||||
|
||||
35) Download [`load.mjs`](pathname:///gsheet/load.mjs):
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/gsheet/load.mjs
|
||||
curl -o load.mjs https://docs.sheetjs.com/gsheet/load.mjs
|
||||
```
|
||||
|
||||
Edit the marked lines near the top of the file:
|
||||
@ -830,7 +831,7 @@ The goal of this section is to export the raw data from Google Sheets to XLSB.
|
||||
38) Download [`dump.mjs`](pathname:///gsheet/dump.mjs):
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/gsheet/dump.mjs
|
||||
curl -o dump.mjs https://docs.sheetjs.com/gsheet/dump.mjs
|
||||
```
|
||||
|
||||
Edit the marked lines near the top of the file:
|
||||
@ -876,7 +877,7 @@ assign a grid of values
|
||||
43) Download [`raw.mjs`](pathname:///gsheet/raw.mjs):
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/gsheet/raw.mjs
|
||||
curl -o raw.mjs https://docs.sheetjs.com/gsheet/raw.mjs
|
||||
```
|
||||
|
||||
Edit the marked lines near the top of the file:
|
||||
|
||||
@ -207,7 +207,7 @@ const wb = XLSX.readFile("SheetJSAirtableTest.xlsb");
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2025-04-21. In the most recent test, free accounts
|
||||
This demo was last tested on 2026-03-15. In the most recent test, free accounts
|
||||
included limited API access.
|
||||
|
||||
:::
|
||||
|
||||
@ -266,7 +266,7 @@ function SheetJSEnregistrez() {
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2024-05-27.
|
||||
This demo was last tested on 2025-05-14.
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -23,9 +23,10 @@ tables with a content script and a background script.
|
||||
|
||||
This demo was tested in the following deployments:
|
||||
|
||||
| Platform | Date |
|
||||
|:-------------|:-----------|
|
||||
| Chromium 131 | 2025-01-02 |
|
||||
| Platform | Version | Date |
|
||||
|:-------------|:--------|:-----------|
|
||||
| Chromium 140 | V3 | 2025-09-13 |
|
||||
| Chromium 137 | V2 | 2025-09-13 |
|
||||
|
||||
:::
|
||||
|
||||
@ -33,8 +34,7 @@ This demo was tested in the following deployments:
|
||||
|
||||
This demo showcases Manifest V2 and Manifest V3 extensions.
|
||||
|
||||
Chrome Web Store will not accept new V2 extensions, but these can be sideloaded
|
||||
using the "Load unpacked" extension option in Developer mode.
|
||||
Chrome 138 and later no longer support Manifest V2 extensions.
|
||||
|
||||
**New Chrome and Chromium Extensions should use Manifest V3!**
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ This demo was tested in the following deployments:
|
||||
|:---------------|:-------------|:-----------|:-----------|
|
||||
| macOS 15.3 | `darwin-x64` | 16.95.4 | 2025-04-17 |
|
||||
| macOS 14.5 | `darwin-arm` | 16.96.1 | 2025-04-24 |
|
||||
| Windows 11 | `win11-x64` | 365 (2501) | 2025-01-19 |
|
||||
| Windows 11 | `win11-x64` | 365 (2506) | 2025-06-17 |
|
||||
| Windows 11 | `win11-arm` | 365 (2503) | 2025-04-24 |
|
||||
|
||||
:::
|
||||
@ -299,7 +299,7 @@ npm run stop
|
||||
npm start
|
||||
```
|
||||
|
||||
4) Activate the Task Pane for the addin (click "Show Task Pane" in the ribbon).
|
||||
4) Activate the Task Pane for the addin (click "Show Task Pane" in the ribbon).
|
||||
|
||||
5) Hover near the top-right corner of the addin and click the `i` icon.
|
||||
|
||||
|
||||
@ -37,9 +37,9 @@ remote file, parses the contents, and writes data to the sheet:
|
||||
|
||||
This demo was tested in the following deployments:
|
||||
|
||||
| Clasp | Date |
|
||||
|:--------|:-----------|
|
||||
| `2.4.2` | 2024-12-31 |
|
||||
| Clasp | Date |
|
||||
|:--------------|:-----------|
|
||||
| `3.0.4-alpha` | 2025-05-21 |
|
||||
|
||||
:::
|
||||
|
||||
@ -112,7 +112,7 @@ the result of setting cell `A1` to the formula `=AOA()`:
|
||||
```js
|
||||
function AOA(url) {
|
||||
return [
|
||||
["Sheet", "JS"],
|
||||
["Sheet", "JS"],
|
||||
[ 72, 62]
|
||||
];
|
||||
}
|
||||
@ -153,6 +153,10 @@ The next page will include the following title:
|
||||
|
||||
3) At the bottom of the screen, click "Continue".
|
||||
|
||||
The next page will include the following title:
|
||||
|
||||
> clasp – The Apps Script CLI wants access to your Google Account
|
||||
|
||||
4) In the next screen, check every box that mentions "Google Apps Script". When
|
||||
the demo was last tested, the following were required:
|
||||
|
||||
@ -183,7 +187,8 @@ Authorization successful.
|
||||
|
||||

|
||||
|
||||
9) Click the gear icon (Project Settings) and copy the Script ID
|
||||
9) Click the gear icon (Project Settings) in the left sidebar. Scroll down to
|
||||
the "IDs" section and copy the Script ID.
|
||||
|
||||
### Cloning the Apps Script
|
||||
|
||||
|
||||
420
docz/docs/03-demos/32-extensions/05-vscode.md
Normal file
420
docz/docs/03-demos/32-extensions/05-vscode.md
Normal file
@ -0,0 +1,420 @@
|
||||
---
|
||||
title: Visualizing Data in VS Code
|
||||
sidebar_label: Visual Studio Code
|
||||
description: View Excel files directly in VS Code. Seamlessly browse spreadsheet data using SheetJS. Navigate between worksheets and pages of data with a responsive interface.
|
||||
pagination_prev: demos/cloud/index
|
||||
pagination_next: demos/bigdata/index
|
||||
sidebar_custom_props:
|
||||
summary: View Excel spreadsheets directly within Visual Studio Code
|
||||
---
|
||||
|
||||
import current from '/version.js';
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
||||
data from spreadsheets.
|
||||
|
||||
[Visual Studio Code](https://code.visualstudio.com) is a popular code editor
|
||||
that supports JavaScript extensions for customizing and enhancing functionality.
|
||||
|
||||
The ["Complete Example"](#complete-example) uses SheetJS in a VS Code extension
|
||||
to view Excel files directly within the editor. The extension leverages the VS
|
||||
Code "WebView API"[^1] and "Custom Editor API"[^2] to display spreadsheet data
|
||||
as HTML tables.
|
||||
|
||||
:::tip pass
|
||||
|
||||
"SheetJS Spreadsheet Viewer" is a sample extension based on this demo. It is
|
||||
available on [Open VSX](https://open-vsx.org/extension/asadbek/sheetjs-demo) and
|
||||
[VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=asadbek.sheetjs-demo)
|
||||
|
||||
[The source code](https://git.sheetjs.com/asadbek064/sheetjs-vscode-extension)
|
||||
is available on the SheetJS Git server. Feedback and contributions are welcome!
|
||||
|
||||
:::
|
||||
|
||||

|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following deployments:
|
||||
|
||||
| Platform | Architecture | Date |
|
||||
|:--------------------------------------------------|:-------------|:-----------|
|
||||
| [VSCodium 1.109.51242](https://vscodium.com/) | `darwin-arm` | 2026-03-05 |
|
||||
| [VS Code 1.110.0](https://code.visualstudio.com/) | `win11-arm` | 2026-03-05 |
|
||||
| [Antigravity 1.19.6](https://antigravity.google/) | `linux-arm` | 2026-03-05 |
|
||||
|
||||
:::
|
||||
|
||||
:::danger Telemetry and Data Exfiltration
|
||||
|
||||
VSCode and many forks embed telemetry and send code to third-party servers.
|
||||
|
||||
For example, Antigravity includes AI features that are powered by Google Gemini
|
||||
and other cloud AI services. These features necessitate code exfiltration.
|
||||
|
||||
**[VSCodium](https://vscodium.com/) does not include AI features or telemetry!**
|
||||
|
||||
:::
|
||||
|
||||
## Integration Details
|
||||
|
||||
The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be
|
||||
imported from any script in the extension.
|
||||
|
||||
:::caution pass
|
||||
|
||||
The SheetJS NodeJS module must be installed as a development dependency. If the
|
||||
module is installed as a normal dependency, the `vsce`[^3] command-line tool
|
||||
will fail to package or publish the extension.
|
||||
|
||||
<Tabs groupId="pm">
|
||||
<TabItem value="npm" label="npm">
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm rm --save xlsx
|
||||
npm i --save-dev https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
|
||||
</CodeBlock>
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="pnpm" label="pnpm">
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
pnpm rm xlsx
|
||||
pnpm install -D https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
|
||||
</CodeBlock>
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="yarn" label="Yarn" default>
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
yarn remove xlsx
|
||||
yarn add -D https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
|
||||
</CodeBlock>
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::
|
||||
|
||||
The core extension APIs are available in the `vscode` package. A TypeScript
|
||||
extension typically uses "glob imports" to load SheetJS and VSCode features:
|
||||
|
||||
```ts title="Importing SheetJS and VSCode features"
|
||||
import * as vscode from 'vscode';
|
||||
import * as XLSX from 'xlsx';
|
||||
```
|
||||
|
||||
## Extension Architecture
|
||||
|
||||
VSCode Extensions for processing custom file types use the Custom Editor API[^2]
|
||||
for lifecycle events. This involves a number of moving parts:
|
||||
|
||||
1) "Custom Document" for managing file metadata
|
||||
|
||||
2) "Custom Editor Provider" for processing file data and generating previews
|
||||
|
||||
3) Registration during extension lifecycle events.
|
||||
|
||||
4) Advertisement of filetype support in extension metadata.
|
||||
|
||||
When a spreadsheet is opened, the extension will use SheetJS methods to parse
|
||||
the raw file and display the data in a HTML table.
|
||||
|
||||
### Custom Documents
|
||||
|
||||
Extensions must provide a class that implements `vscode.CustomDocument`[^4].
|
||||
|
||||
```ts title="Simple CustomDocument"
|
||||
class ExcelDocument implements vscode.CustomDocument {
|
||||
constructor(public readonly uri: vscode.Uri) { }
|
||||
dispose() { }
|
||||
}
|
||||
```
|
||||
|
||||
### Editor Provider
|
||||
|
||||
Extensions that read data should implement `vscode.CustomReadonlyEditorProvider`
|
||||
with a generic parameter for the custom document type.
|
||||
|
||||
The `openCustomDocument` method takes a `vscode.Uri` and is expected to return a
|
||||
new document:
|
||||
|
||||
```ts title="src/extension.ts (snippet)"
|
||||
class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
|
||||
async openCustomDocument(uri: vscode.Uri): Promise<ExcelDocument> {
|
||||
return new ExcelDocument(uri);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Reading Files
|
||||
|
||||
The `FileSystemProvider` API[^5], available at `vscode.workspace.fs`, exposes
|
||||
common filesystem operations including reading raw data from files and watching
|
||||
for changes.
|
||||
|
||||
The `resolveCustomEditor`[^6] method of the `CustomEditorProvider` will be
|
||||
called when a file is opened. The first argument is a `CustomDocument` whose
|
||||
`uri` property points to the location of the file.
|
||||
|
||||
`vscode.workspace.fs.readFile`[^5] returns a promise that resolves to a
|
||||
`Uint8Array` containing the raw binary data. This `Uint8Array` can be passed to
|
||||
the SheetJS [`read`](/docs/api/parse-options) method:
|
||||
|
||||
```ts title="src/extension.ts (snippet)"
|
||||
export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
|
||||
// ...
|
||||
async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<void> {
|
||||
// read the raw bytes from the file
|
||||
const data: Uint8Array = await vscode.workspace.fs.readFile(document.uri);
|
||||
|
||||
// parse the file data
|
||||
const wb: XLSX.WorkBook = XLSX.read(data);
|
||||
|
||||
// At this point, `wb` is a SheetJS Workbook Object
|
||||
// ...
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Previewing Data
|
||||
|
||||
The `resolveCustomEditor`[^6] method of the `CustomEditorProvider` will be
|
||||
called when a file is opened. The second argument is a `WebviewPanel`[^7].
|
||||
|
||||
The `webview.html` nested property of the `WebviewPanel` controls the displayed
|
||||
HTML. Extensions can use SheetJS [API methods](/docs/api/).
|
||||
|
||||
The SheetJS [`sheet_to_html`](/docs/api/utilities/html#html-table-output) method
|
||||
generates a simple HTML table. The following snippet displays the data of the
|
||||
first worksheet:
|
||||
|
||||
```ts title="src/extension.ts (snippet)"
|
||||
export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
|
||||
// ...
|
||||
async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<void> {
|
||||
// ...
|
||||
// continuing from "Reading Files", `wb` is a SheetJS Workbook Object
|
||||
const first_sheet = wb.Sheets[wb.SheetNames[0]];
|
||||
webviewPanel.webview.html = XLSX.utils.sheet_to_html(first_sheet);
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Registration
|
||||
|
||||
The exported `activate` method registers the editor provider. The first argument
|
||||
to `registerCustomEditorProvider` is expected to be a unique name that will be
|
||||
referenced later.
|
||||
|
||||
```ts title="src/extension.ts (snippet)"
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
const provider = vscode.window.registerCustomEditorProvider(
|
||||
'excelViewer.spreadsheet',
|
||||
new ExcelEditorProvider(),
|
||||
{ webviewOptions: { retainContextWhenHidden: true } } // keep webview state when hidden
|
||||
);
|
||||
context.subscriptions.push(provider);
|
||||
}
|
||||
```
|
||||
|
||||
### Filetype Support
|
||||
|
||||
Extensions must announce custom editor file type support in `package.json`.
|
||||
The `selector` property[^8] is expected to include "Glob Pattterns"[^9].
|
||||
|
||||
The demo uses the following `package.json` snippet to announce support for `xls`
|
||||
and `xlsx` spreadsheets:
|
||||
|
||||
```json title="package.json (snippet)"
|
||||
"contributes": {
|
||||
"customEditors": [
|
||||
{
|
||||
// ... other properties including displayName
|
||||
// highlight-start
|
||||
// The viewType must match the first argument of `registerCustomEditorProvider`
|
||||
"viewType": "excelViewer.spreadsheet",
|
||||
"selector": [
|
||||
{ "filenamePattern": "*.xlsx" },
|
||||
{ "filenamePattern": "*.xls" }
|
||||
]
|
||||
// highlight-end
|
||||
}
|
||||
],
|
||||
// ...
|
||||
},
|
||||
```
|
||||
|
||||
### Usage Flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor User
|
||||
participant VSCode as VS Code
|
||||
participant Provider as ExcelEditorProvider
|
||||
participant SheetJS
|
||||
participant WebView
|
||||
|
||||
User->>VSCode: Open .xlsx file
|
||||
VSCode->>Provider: openCustomDocument(uri)
|
||||
Provider-->>VSCode: return ExcelDocument
|
||||
VSCode->>Provider: resolveCustomEditor(document, webviewPanel)
|
||||
Provider->>VSCode: workspace.fs.readFile(document.uri)
|
||||
VSCode-->>Provider: return file data
|
||||
Provider->>SheetJS: XLSX.read(data, options)
|
||||
SheetJS-->>Provider: return workbook
|
||||
Provider->>SheetJS: XLSX.utils.sheet_to_html(sheet)
|
||||
SheetJS-->>Provider: return HTML
|
||||
Provider->>WebView: set webview.html
|
||||
WebView-->>User: Display Excel data
|
||||
```
|
||||
|
||||
## Complete Example
|
||||
|
||||
:::caution pass
|
||||
|
||||
To avoid conflicts with existing extensions, it is strongly recommended to test
|
||||
with a different VSCode fork. For example, VSCode and Antigravity users should
|
||||
install and use VSCodium for extension development.
|
||||
|
||||
:::
|
||||
|
||||
1) Download the [`pres.xlsx`](https://docs.sheetjs.com/pres.xlsx) sample file.
|
||||
|
||||
2) Create a new VS Code extension
|
||||
|
||||
```bash
|
||||
npx --package yo --package generator-code -- yo code
|
||||
```
|
||||
|
||||
When prompted, enter the following options:
|
||||
|
||||
- `What type of extension do you want to create?`: Select `New Extension (TypeScript)` and press <kbd>Enter</kbd>
|
||||
- `What's the name of your extension?`: Type `sheetjs-demo` and press <kbd>Enter</kbd>
|
||||
- `What's the identifier of your extension?`: Press <kbd>Enter</kbd> (use the default `sheetjs-demo`)
|
||||
- `What's the description of your extension?`: Press <kbd>Enter</kbd> (leave blank)
|
||||
- `Initialize a git repository?`: Type `n` and press <kbd>Enter</kbd>
|
||||
- `Which bundler to use?`: Select `webpack` and press <kbd>Enter</kbd>
|
||||
- `Which package manager to use?`: Select `pnpm` and press <kbd>Enter</kbd>
|
||||
|
||||

|
||||
|
||||
3) Install the SheetJS library and start the dev server:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
cd sheetjs-demo
|
||||
pnpm install -D https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
pnpm run watch
|
||||
`}
|
||||
</CodeBlock>
|
||||
|
||||
4) Launch a new window with the VSCode fork and open the `sheetjs-demo` folder.
|
||||
|
||||
5) Save the following codeblock to `src/extension.ts`:
|
||||
|
||||
```ts title="src/extension.ts (replace contents)"
|
||||
import * as vscode from 'vscode';
|
||||
import * as XLSX from 'xlsx';
|
||||
|
||||
class ExcelDocument implements vscode.CustomDocument {
|
||||
constructor(public readonly uri: vscode.Uri) { }
|
||||
dispose() { }
|
||||
}
|
||||
|
||||
class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
|
||||
// This is called when the first time an editor for a given resource is opened
|
||||
async openCustomDocument(uri: vscode.Uri): Promise<ExcelDocument> {
|
||||
return new ExcelDocument(uri);
|
||||
}
|
||||
|
||||
// This is called whenever the user opens a new editor
|
||||
async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<void> {
|
||||
const data: Uint8Array = await vscode.workspace.fs.readFile(document.uri);
|
||||
|
||||
const options: XLSX.ParsingOptions = { cellStyles: true, cellDates: true };
|
||||
const wb: XLSX.WorkBook = XLSX.read(data, options);
|
||||
|
||||
const first_sheet = wb.Sheets[wb.SheetNames[0]];
|
||||
webviewPanel.webview.html = XLSX.utils.sheet_to_html(first_sheet);
|
||||
}
|
||||
}
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
const provider = vscode.window.registerCustomEditorProvider(
|
||||
'excelViewer.spreadsheet',
|
||||
new ExcelEditorProvider(),
|
||||
{ webviewOptions: { retainContextWhenHidden: true } } // keep webview state when hidden
|
||||
);
|
||||
context.subscriptions.push(provider);
|
||||
}
|
||||
export function deactivate() {}
|
||||
```
|
||||
|
||||
6) Add the highlighted lines to the `contributes` section of `package.json`:
|
||||
|
||||
```json title="package.json (add highlighted lines)"
|
||||
"contributes": {
|
||||
// highlight-start
|
||||
"customEditors": [
|
||||
{
|
||||
"viewType": "excelViewer.spreadsheet",
|
||||
"displayName": "SheetJS Demo",
|
||||
"selector": [
|
||||
{ "filenamePattern": "*.xlsx" },
|
||||
{ "filenamePattern": "*.xls" }
|
||||
]
|
||||
}
|
||||
],
|
||||
// highlight-end
|
||||
"commands": [
|
||||
{
|
||||
"command": "sheetjs-demo.helloWorld",
|
||||
"title": "Hello World"
|
||||
}
|
||||
]
|
||||
},
|
||||
```
|
||||
|
||||
7) In the editor, open the Command Palette (Help > "Show All Commands" from the
|
||||
menu), type `Debug: Start` and select `Debug: Start Debugging`.
|
||||
|
||||
This will compile and run the extension in a new Extension Development Host window.
|
||||
|
||||
8) Drag and drop the `pres.xlsx` test file into the new window. If drag and drop
|
||||
is not available, click "Open..." in the Welcome screen and select the file.
|
||||
|
||||
A new `pres.xlsx` tab will show the contents of the file.
|
||||
|
||||
:::info pass
|
||||
|
||||
When this demo was last tested, the default project assumed VSCode version
|
||||
1.109.0 or later. Antigravity 1.19.6 is aligned to VSCode 1.107.0. The default
|
||||
extension will not run in Antigravity.
|
||||
|
||||
This can be fixed by changing the `vscode` field in `package.json`. When this
|
||||
demo was last tested, it was safe to set a minimum version of `^1.100.0`:
|
||||
|
||||
```json title="package.json (change highlighted line)"
|
||||
"engines": {
|
||||
// highlight-next-line
|
||||
"vscode": "^1.100.0"
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
[^1]: See [`Webview API`](https://code.visualstudio.com/api/extension-guides/webview) in the VSCode documentation for more details.
|
||||
[^2]: See [`Custom Editor API`](https://code.visualstudio.com/api/extension-guides/custom-editors) in the VSCode documentation for more details.
|
||||
[^3]: See [`vsce`](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#vsce) in the VSCode documentation for more details.
|
||||
[^4]: See [`CustomDocument`](https://code.visualstudio.com/api/references/vscode-api#CustomDocument) in the VSCode API documentation for more details.
|
||||
[^5]: See [`FileSystemProvider`](https://code.visualstudio.com/api/references/vscode-api#FileSystemProvider) in the VSCode API documentation for more details.
|
||||
[^6]: See [`CustomEditorProvider<T>`](https://code.visualstudio.com/api/references/vscode-api#CustomEditorProvider<T>) in the VSCode API documentation for more details.
|
||||
[^7]: See [`WebviewPanel`](https://code.visualstudio.com/api/references/vscode-api#WebviewPanel) in the VSCode API documentation for more details.
|
||||
[^8]: See [`contributes.customEditors`](https://code.visualstudio.com/api/references/contribution-points#contributes.customEditors) in the VSCode API documentation for more details.
|
||||
[^9]: See ["Glob Patterns Reference"](https://code.visualstudio.com/docs/editor/glob-patterns) in the VSCode documentation for more details.
|
||||
@ -30,7 +30,7 @@ This demo was tested by SheetJS users in the following deployments:
|
||||
| Architecture | Version | Date |
|
||||
|:-------------|:--------|:-----------|
|
||||
| `darwin-x64` | `14.1` | 2025-03-31 |
|
||||
| `win11-x64` | `14.0` | 2024-12-19 |
|
||||
| `win11-x64` | `14.2` | 2025-05-21 |
|
||||
|
||||
:::
|
||||
|
||||
@ -181,12 +181,12 @@ This demo tests the NodeJS external engine and dedicated command line tools.
|
||||
|
||||
### NodeJS Engine
|
||||
|
||||
0) Install NodeJS. When the demo was tested, version `20.19.0` was installed.
|
||||
0) Install NodeJS. When the demo was tested, version `20.19.2` was installed.
|
||||
|
||||
1) Install dependencies in the Home folder (`~` or `$HOME` or `%HOMEPATH%`):
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz zeromq@6.4.0`}
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz zeromq@6.4.2`}
|
||||
</CodeBlock>
|
||||
|
||||
2) Open a new Mathematica Notebook and register NodeJS. When the example was
|
||||
|
||||
@ -53,11 +53,11 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | Version | Date |
|
||||
|:-------------|:------------------|:-----------|
|
||||
| `darwin-x64` | `18.5` (StataNow) | 2025-01-08 |
|
||||
| `darwin-x64` | `18.5` (StataNow) | 2025-06-20 |
|
||||
| `darwin-arm` | `18.5` (StataNow) | 2025-04-24 |
|
||||
| `win11-x64` | `18.5` (StataNow) | 2024-12-19 |
|
||||
| `win11-x64` | `18.5` (StataNow) | 2025-04-28 |
|
||||
| `win11-arm` | `18.5` (StataNow) | 2025-02-23 |
|
||||
| `linux-x64` | `18.5` (StataNow) | 2025-01-09 |
|
||||
| `linux-x64` | `19.5` (StataNow) | 2025-07-06 |
|
||||
|
||||
:::
|
||||
|
||||
@ -203,7 +203,7 @@ import excel "sheetjs.tmp.xlsx", firstrow
|
||||
|
||||
1) Open Stata and run the following command:
|
||||
|
||||
```stata
|
||||
```stata title="Find Stata data directory (run in Stata)"
|
||||
pwd
|
||||
```
|
||||
|
||||
@ -213,7 +213,7 @@ The output will be the default data directory. On macOS this is typically
|
||||
2) Open a terminal window and create a project folder `sheetjs-stata` within the
|
||||
Stata data directory:
|
||||
|
||||
```bash
|
||||
```bash title="Create folder in Stata data directory (run in terminal)"
|
||||
: # `cd` to the Stata data directory
|
||||
cd ~/Documents/Stata
|
||||
mkdir sheetjs-stata
|
||||
@ -252,15 +252,31 @@ bash
|
||||
3) Download [`stplugin.c`](https://www.stata.com/plugins/stplugin.c) and
|
||||
[`stplugin.h`](https://www.stata.com/plugins/stplugin.h) from the Stata website:
|
||||
|
||||
```bash
|
||||
```bash title="Download Stata plugin files (run in terminal)"
|
||||
curl -LO https://www.stata.com/plugins/stplugin.c
|
||||
curl -LO https://www.stata.com/plugins/stplugin.h
|
||||
```
|
||||
|
||||
:::danger pass
|
||||
|
||||
**When this demo was last tested, `stplugin.h` was removed from the website!**
|
||||
|
||||
If the official links do not work, the following files should be used:
|
||||
|
||||
- [`stplugin.c`](pathname:///stata/stplugin.c)
|
||||
- [`stplugin.h`](pathname:///stata/stplugin.h)
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/plugins/stplugin.c
|
||||
curl -LO https://docs.sheetjs.com/plugins/stplugin.h
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
4) Download Duktape. In Windows, the following commands should be run in WSL. In
|
||||
macOS, the commands should be run in the same Terminal session.
|
||||
|
||||
```bash
|
||||
```bash title="Download Duktape (run in terminal)"
|
||||
curl -LO https://duktape.org/duktape-2.7.0.tar.xz
|
||||
tar -xJf duktape-2.7.0.tar.xz
|
||||
mv duktape-2.7.0/src/*.{c,h} .
|
||||
@ -271,7 +287,7 @@ mv duktape-2.7.0/src/*.{c,h} .
|
||||
In Windows, the following commands should be run in WSL. In macOS, the commands
|
||||
should be run in the same Terminal session.
|
||||
|
||||
```bash
|
||||
```bash title="Download plugin source (run in terminal)"
|
||||
curl -LO https://docs.sheetjs.com/stata/cleanfile.c
|
||||
```
|
||||
|
||||
@ -282,7 +298,7 @@ curl -LO https://docs.sheetjs.com/stata/cleanfile.c
|
||||
|
||||
7) Build the plugin:
|
||||
|
||||
```bash
|
||||
```bash title="Build plugin (run in terminal)"
|
||||
gcc -shared -fPIC -DSYSTEM=APPLEMAC stplugin.c duktape.c cleanfile.c -lm -std=c99 -Wall -ocleanfile.plugin
|
||||
```
|
||||
|
||||
@ -313,7 +329,7 @@ cl /LD cleanfile.c stplugin.c duktape.c
|
||||
|
||||
8) Copy the plugin to the Stata data directory:
|
||||
|
||||
```bash
|
||||
```bash title="Copy compiled plugin to Stata data directory (run in terminal)"
|
||||
cp cleanfile.plugin ../
|
||||
```
|
||||
|
||||
@ -338,7 +354,7 @@ copy cleanfile.dll c:\data\cleanfile.plugin
|
||||
|
||||
9) Move to the Stata data directory:
|
||||
|
||||
```bash
|
||||
```bash title="Move to Stata data directory (run in terminal)"
|
||||
cd ..
|
||||
```
|
||||
|
||||
@ -367,7 +383,7 @@ bash
|
||||
In Windows, the following commands should be run in WSL. In macOS, the commands
|
||||
should be run in the same Terminal session.
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
<CodeBlock language="bash" title="Download SheetJS Scripts and files (run in terminal)">{`\
|
||||
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js
|
||||
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
|
||||
curl -LO https://docs.sheetjs.com/pres.numbers`}
|
||||
@ -388,7 +404,7 @@ The screenshot in the introduction shows the result of steps 13 - 19
|
||||
|
||||
13) Run the following command in Stata:
|
||||
|
||||
```stata
|
||||
```stata title="List files in data directory (run in Stata)"
|
||||
dir
|
||||
```
|
||||
|
||||
@ -408,13 +424,13 @@ cd c:\data
|
||||
|
||||
14) Load the `cleanfile` plugin:
|
||||
|
||||
```stata
|
||||
```stata title="Load the new plugin (run in Stata)"
|
||||
program cleanfile, plugin
|
||||
```
|
||||
|
||||
16) Read the `pres.numbers` test file:
|
||||
|
||||
```stata
|
||||
```stata title="Run the plugin (run in Stata)"
|
||||
plugin call cleanfile, "pres.numbers" verbose
|
||||
```
|
||||
|
||||
@ -437,13 +453,13 @@ for more help, see <span {...b}>import excel</span>
|
||||
|
||||
17) Close the plugin:
|
||||
|
||||
```stata
|
||||
```stata title="Close the plugin (run in Stata)"
|
||||
program drop cleanfile
|
||||
```
|
||||
|
||||
18) Clear the current session:
|
||||
|
||||
```stata
|
||||
```stata title="Clear the current session (run in Stata)"
|
||||
clear
|
||||
```
|
||||
|
||||
@ -452,7 +468,7 @@ excel "sheetjs.tmp.xlsx", firstrow</span></code></p></li></ol>
|
||||
|
||||
Alternatively, manually type the command:
|
||||
|
||||
```stata
|
||||
```stata title="Load the file created by the SheetJS plugin (run in Stata)"
|
||||
import excel "sheetjs.tmp.xlsx", firstrow
|
||||
```
|
||||
|
||||
@ -463,67 +479,31 @@ The output will show the import result:
|
||||
(2 vars, 5 obs)
|
||||
</pre>
|
||||
|
||||
20) Open the Data Editor (in Browse or Edit mode) and compare to the screenshot:
|
||||
20) List the dataset:
|
||||
|
||||
```stata
|
||||
browse Name Index
|
||||
```stata title="List the new variables (run in Stata)"
|
||||
list Name Index
|
||||
```
|
||||
|
||||
The result should match the following listing:
|
||||
|
||||
<pre>
|
||||
. list Name Index<br/>
|
||||
{' '}+----------------------+
|
||||
{' '}| Name Index |
|
||||
{' '}|----------------------|
|
||||
{' '}1. | Bill Clinton 42 |
|
||||
{' '}2. | GeorgeW Bush 43 |
|
||||
{' '}3. | Barack Obama 44 |
|
||||
{' '}4. | Donald Trump 45 |
|
||||
{' '}5. | Joseph Biden 46 |
|
||||
{' '}+----------------------+
|
||||
</pre>
|
||||
|
||||
In the Stata GUI, the Data Editor should match the following screenshot:
|
||||
|
||||

|
||||
|
||||
:::info pass
|
||||
|
||||
In the terminal version of Stata, `browse` does not work:
|
||||
|
||||
```
|
||||
. browse Name Index
|
||||
command browse is unrecognized
|
||||
r(199);
|
||||
```
|
||||
|
||||
The `codebook` command will display details.
|
||||
|
||||
<details>
|
||||
<summary><b>Expected Output</b> (click to show)</summary>
|
||||
|
||||
```text title="Expected output for 80-column terminal windows"
|
||||
-------------------------------------------------------------------------------
|
||||
Name Name
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Type: String (str12)
|
||||
|
||||
Unique values: 5 Missing "": 0/5
|
||||
|
||||
Tabulation: Freq. Value
|
||||
1 "Barack Obama"
|
||||
1 "Bill Clinton"
|
||||
1 "Donald Trump"
|
||||
1 "GeorgeW Bush"
|
||||
1 "Joseph Biden"
|
||||
|
||||
Warning: Variable has embedded blanks.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Index Index
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Type: Numeric (byte)
|
||||
|
||||
Range: [42,46] Units: 1
|
||||
Unique values: 5 Missing .: 0/5
|
||||
|
||||
Tabulation: Freq. Value
|
||||
1 42
|
||||
1 43
|
||||
1 44
|
||||
1 45
|
||||
1 46
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
:::
|
||||
|
||||
[^1]: Run `help import excel` in Stata or see ["import excel"](https://www.stata.com/manuals/dimportexcel.pdf) in the Stata documentation.
|
||||
[^2]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
|
||||
@ -30,7 +30,7 @@ This demo was tested by SheetJS users in the following deployments:
|
||||
| Architecture | Version | Date |
|
||||
|:-------------|:--------|:-----------|
|
||||
| `darwin-x64` | R2024b | 2025-03-31 |
|
||||
| `win11-x64` | R2024b | 2024-12-21 |
|
||||
| `win11-x64` | R2024b | 2025-05-10 |
|
||||
|
||||
:::
|
||||
|
||||
@ -234,14 +234,14 @@ run in the macOS Terminal or Windows PowerShell:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz exit-on-epipe commander@2
|
||||
curl -LO https://docs.sheetjs.com/cli/xlsx-cli.js
|
||||
curl -o xlsx-cli.js https://docs.sheetjs.com/cli/xlsx-cli.js
|
||||
npx -y nexe -t 14.15.3 xlsx-cli.js`}
|
||||
</CodeBlock>
|
||||
|
||||
2) Download https://docs.sheetjs.com/pres.numbers to the workspace folder:
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/pres.numbers
|
||||
curl -o pres.numbers https://docs.sheetjs.com/pres.numbers
|
||||
```
|
||||
|
||||
4) Save the following to `SheetJSMATLAB.m` in the workspace folder:
|
||||
|
||||
@ -8,6 +8,8 @@ sidebar_custom_props:
|
||||
---
|
||||
|
||||
import current from '/version.js';
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
[Maple](https://www.maplesoft.com/products/Maple/) is a numeric computing
|
||||
@ -23,7 +25,7 @@ library to read data from spreadsheets and converts to a Maple-friendly format.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
ofile[(workbook\nXLSB file)]
|
||||
ofile[(generic\nworkbook)]
|
||||
nfile[(clean file\nXLSX)]
|
||||
data[[Maple\nTable]]
|
||||
ofile --> |Maple Extension\nSheetJS + Duktape| nfile
|
||||
@ -36,8 +38,8 @@ This demo was tested by SheetJS users in the following deployments:
|
||||
|
||||
| Architecture | Version | Date |
|
||||
|:-------------|:---------|:-----------|
|
||||
| `darwin-x64` | `2024.0` | 2025-01-10 |
|
||||
| `win11-x64` | `2024.0` | 2024-12-19 |
|
||||
| `darwin-x64` | `2025.1` | 2025-06-20 |
|
||||
| `win11-x64` | `2025.1` | 2025-07-17 |
|
||||
|
||||
:::
|
||||
|
||||
@ -60,7 +62,7 @@ and generates clean XLSX files that Maple can import.
|
||||
The extension function ultimately pairs the SheetJS `read`[^2] and `write`[^3]
|
||||
methods to read data from the old file and write a new file:
|
||||
|
||||
```js
|
||||
```js title="Script that will be run by Maple extension"
|
||||
var workbook = XLSX.read(original_file_data, { type: "buffer" });
|
||||
var new_file_data = XLSX.write(workbook, { type: "array", bookType: "xlsx" });
|
||||
```
|
||||
@ -84,6 +86,7 @@ flowchart LR
|
||||
wb --> |SheetJS\n`write`| njbuf
|
||||
njbuf --> |Duktape\nBuffer Ops| nbuf
|
||||
nbuf --> |C\nWrite File| nfile
|
||||
linkStyle 2,3 color:blue,stroke:blue;
|
||||
```
|
||||
|
||||
### C Extensions
|
||||
@ -128,11 +131,25 @@ file, exports data to `sheetjsw.xlsx` and returns the string `"sheetjsw.xlsx"`.
|
||||
|
||||
This can be chained with `Import` from `ExcelTools`:
|
||||
|
||||
```maple
|
||||
```maple title="Sample usage of SheetToXLSX extension"
|
||||
with(ExcelTools);
|
||||
Import(SheetToXLSX("pres.numbers"))
|
||||
```
|
||||
|
||||
<Tabs groupId="triple">
|
||||
<TabItem value="darwin-x64" label="MacOS">
|
||||
|
||||
1) Open a new Terminal window and create the `/tmp/sheetjs-maple` folder:
|
||||
|
||||
```bash
|
||||
cd /tmp
|
||||
mkdir sheetjs-maple
|
||||
cd sheetjs-maple
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="win11-x64" label="Windows">
|
||||
|
||||
0) Install "Windows Subsystem for Linux" (WSL)[^5] and Visual Studio[^6].
|
||||
|
||||
1) Open a new "x64 Native Tools Command Prompt" window and create a project
|
||||
@ -144,20 +161,40 @@ mkdir sheetjs-maple
|
||||
cd sheetjs-maple
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
2) Copy the headers and `lib` files from the Maple folder to the project folder.
|
||||
The headers will be placed in the `extern/include/` folder in the Maple folder.
|
||||
The `lib` files are placed in a platform-specific `bin` folder.
|
||||
|
||||
The following commands apply to x64 versions of Windows:
|
||||
<Tabs groupId="triple">
|
||||
<TabItem value="darwin-x64" label="MacOS">
|
||||
|
||||
In macOS, the "Maple folder" is located in `/Library/Frameworks`:
|
||||
|
||||
```bash
|
||||
cp /Library/Frameworks/Maple.framework/Versions/2025/extern/include/*.h .
|
||||
cp /Library/Frameworks/Maple.framework/Versions/2025/bin.APPLE_UNIVERSAL_OSX/*.so .
|
||||
cp /Library/Frameworks/Maple.framework/Versions/2025/bin.APPLE_UNIVERSAL_OSX/*.dylib .
|
||||
```
|
||||
|
||||
3) Observe that macOS does not need a "Linux Subsystem" and move to Step 4.
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="win11-x64" label="Windows">
|
||||
|
||||
```powershell
|
||||
copy "C:\Program Files\Maple 2024\extern\include\"*.h .
|
||||
copy "c:\Program Files\Maple 2024\bin.x86_64_WINDOWS"\*.lib .
|
||||
copy "C:\Program Files\Maple 2025\extern\include\"*.h .
|
||||
copy "C:\Program Files\Maple 2025\bin.x86_64_WINDOWS"\*.lib .
|
||||
```
|
||||
|
||||
3) Run `bash` to enter WSL
|
||||
|
||||
4) Within WSL, install Duktape:
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
4) Install Duktape:
|
||||
|
||||
```bash
|
||||
curl -LO https://duktape.org/duktape-2.7.0.tar.xz
|
||||
@ -165,7 +202,7 @@ tar -xJf duktape-2.7.0.tar.xz
|
||||
mv duktape-2.7.0/src/*.{c,h} .
|
||||
```
|
||||
|
||||
5) Still within WSL, download SheetJS scripts and the test file.
|
||||
5) Download SheetJS scripts and the test file.
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js
|
||||
@ -173,12 +210,26 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
|
||||
curl -LO https://docs.sheetjs.com/pres.numbers`}
|
||||
</CodeBlock>
|
||||
|
||||
6) Still within WSL, download the extension C code
|
||||
6) Download the extension C code
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/maple/sheetjs-maple.c
|
||||
```
|
||||
|
||||
<Tabs groupId="triple">
|
||||
<TabItem value="darwin-x64" label="MacOS">
|
||||
|
||||
7) Observe that macOS does not need a "Linux Subsystem" and move to Step 8.
|
||||
|
||||
8) Build the extension library:
|
||||
|
||||
```powershell
|
||||
gcc -shared -fPIC duktape.c sheetjs-maple.c -lm -std=c99 -Wall -o libsheetjs-maple.so -L. -lmaplec
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="win11-x64" label="Windows">
|
||||
|
||||
7) Exit WSL by running `exit`. The window will return to the command prompt.
|
||||
|
||||
8) Build the extension DLL:
|
||||
@ -187,14 +238,30 @@ curl -LO https://docs.sheetjs.com/maple/sheetjs-maple.c
|
||||
cl -Gz sheetjs-maple.c duktape.c /EHsc -link -dll -out:sheetjs-maple.dll maplec.lib
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
9) Close and re-open Maple, then create a new Maple Worksheet or Document
|
||||
|
||||
10) Run the following command in Maple to change the working directory:
|
||||
|
||||
<Tabs groupId="triple">
|
||||
<TabItem value="darwin-x64" label="MacOS">
|
||||
|
||||
```maple
|
||||
currentdir("/tmp/sheetjs-maple");
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="win11-x64" label="Windows">
|
||||
|
||||
```maple
|
||||
currentdir("c:\\sheetjs-maple");
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
11) Load the `SheetToXLSX` method from the extension:
|
||||
|
||||
```maple
|
||||
|
||||
@ -28,7 +28,7 @@ This demo was tested by SheetJS users in the following deployments:
|
||||
| Architecture | Ghidra | Date |
|
||||
|:-------------|:----------|:-----------|
|
||||
| `darwin-x64` | `11.13.1` | 2025-04-17 |
|
||||
| `darwin-arm` | `11.13.1` | 2025-03-17 |
|
||||
| `darwin-arm` | `11.13.1` | 2025-10-19 |
|
||||
|
||||
:::
|
||||
|
||||
@ -255,14 +255,15 @@ Rows will be generated for each block and the final dataset will be exported.
|
||||
|
||||
### System Setup
|
||||
|
||||
0) Install Ghidra, Xcode, and Apple Numbers.
|
||||
0) Install Java, Ghidra, Xcode, and Apple Numbers.
|
||||
|
||||
<details>
|
||||
<summary><b>Installation Notes</b> (click to show)</summary>
|
||||
|
||||
On macOS, Ghidra was installed using Homebrew:
|
||||
When this demo was last tested, Java and Ghidra were installed using Homebrew:
|
||||
|
||||
```bash
|
||||
brew install zulu@21
|
||||
brew install --cask ghidra
|
||||
```
|
||||
|
||||
@ -344,7 +345,7 @@ If prompted, enter the path to the JDK installation. On macOS, JDK installations
|
||||
are typically stored in `/Library/Java/JavaVirtualMachines`. The required path
|
||||
is the `/Contents/Home/` folder within the specific JDK installation.
|
||||
|
||||
When this demo was last tested, Zulu JDK 21 was installed with Homebrew:
|
||||
When this demo was last tested, Zulu JDK 21 was installed with Homebrew:
|
||||
|
||||
```bash
|
||||
brew install --cask zulu@21
|
||||
|
||||
@ -180,25 +180,25 @@ be reported to the Bun project for further diagnosis.
|
||||
|
||||
This demo was tested in the following deployments:
|
||||
|
||||
| Node Version | Date | Node Status when tested |
|
||||
|:-------------|:-----------|:------------------------|
|
||||
| `0.12.18` | 2025-04-24 | End-of-Life |
|
||||
| `4.9.1` | 2025-04-24 | End-of-Life |
|
||||
| `6.17.1` | 2025-04-24 | End-of-Life |
|
||||
| `8.17.0` | 2025-04-24 | End-of-Life |
|
||||
| `10.24.1` | 2025-04-24 | End-of-Life |
|
||||
| `12.22.12` | 2025-04-24 | End-of-Life |
|
||||
| `14.15.5` | 2025-04-24 | End-of-Life |
|
||||
| `16.20.2` | 2025-04-24 | End-of-Life |
|
||||
| `18.20.8` | 2025-04-24 | Maintenance LTS |
|
||||
| `20.18.0` | 2025-04-24 | Active LTS |
|
||||
| `22.14.0` | 2025-04-24 | Current |
|
||||
| Platform | Date | Status when tested |
|
||||
|:------------------|:-----------|:-------------------|
|
||||
| NodeJS `0.12.18` | 2025-11-15 | End-of-Life |
|
||||
| NodeJS `4.9.1` | 2025-11-15 | End-of-Life |
|
||||
| NodeJS `6.17.1` | 2025-11-15 | End-of-Life |
|
||||
| NodeJS `8.17.0` | 2025-11-15 | End-of-Life |
|
||||
| NodeJS `10.24.1` | 2025-11-15 | End-of-Life |
|
||||
| NodeJS `12.22.12` | 2025-11-15 | End-of-Life |
|
||||
| NodeJS `14.21.3` | 2025-11-15 | End-of-Life |
|
||||
| NodeJS `16.20.2` | 2025-11-15 | End-of-Life |
|
||||
| NodeJS `18.20.8` | 2025-11-15 | End-of-Life |
|
||||
| NodeJS `20.18.0` | 2025-11-15 | Maintenance LTS |
|
||||
| NodeJS `22.21.1` | 2025-11-15 | Active LTS |
|
||||
| NodeJS `24.11.1` | 2025-11-15 | Current |
|
||||
| BunJS `1.3.2` | 2025-11-15 | Current |
|
||||
|
||||
While streaming methods work in End-of-Life versions of NodeJS, production
|
||||
deployments should upgrade to a Current or LTS version of NodeJS.
|
||||
|
||||
This demo was also tested against BunJS `1.2.10` on 2025-04-24.
|
||||
|
||||
:::
|
||||
|
||||
1) Install the [NodeJS module](/docs/getting-started/installation/nodejs)
|
||||
|
||||
@ -193,18 +193,18 @@ Each browser demo was tested in the following environments:
|
||||
|
||||
| Browser | Date | Comments |
|
||||
|:-------------|:-----------|:----------------------------------------|
|
||||
| Chromium 131 | 2024-12-31 | |
|
||||
| Edge 131 | 2024-12-31 | |
|
||||
| Safari 17.5 | 2024-12-31 | File System Access API is not supported |
|
||||
| Brave 1.63 | 2024-12-31 | File System Access API is not supported |
|
||||
| Chromium 136 | 2025-05-27 | |
|
||||
| Edge 135 | 2025-05-27 | |
|
||||
| Safari 17.1 | 2025-05-27 | File System Access API is not supported |
|
||||
| Brave 1.78 | 2025-05-27 | File System Access API is not supported |
|
||||
| Konqueror 22 | 2025-04-23 | File System Access API is not supported |
|
||||
| Firefox 133 | 2024-12-31 | File System Access API is not supported |
|
||||
| Firefox 138 | 2025-05-27 | File System Access API is not supported |
|
||||
|
||||
:::
|
||||
|
||||
### Downloading a Remote File
|
||||
|
||||
:::note fetch in Web Workers
|
||||
:::note `fetch` in Web Workers
|
||||
|
||||
`fetch` was enabled in Web Workers in Chrome 42 and Safari 10.3
|
||||
|
||||
@ -400,7 +400,7 @@ self.addEventListener('message', async(e) => {
|
||||
|
||||
### User-Submitted File
|
||||
|
||||
:::note FileReaderSync
|
||||
:::note `FileReaderSync`
|
||||
|
||||
Typically `FileReader` is used in the main browser context. In Web Workers, the
|
||||
synchronous version `FileReaderSync` is more efficient.
|
||||
|
||||
@ -128,12 +128,12 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | Version | Date |
|
||||
|:-------------|:--------|:-----------|
|
||||
| `darwin-x64` | `2.7.0` | 2025-03-31 |
|
||||
| `darwin-arm` | `2.7.0` | 2025-02-13 |
|
||||
| `win11-x64` | `2.7.0` | 2024-12-20 |
|
||||
| `darwin-x64` | `2.7.0` | 2026-01-21 |
|
||||
| `darwin-arm` | `2.7.0` | 2026-03-07 |
|
||||
| `win11-x64` | `2.7.0` | 2025-04-28 |
|
||||
| `win11-arm` | `2.7.0` | 2025-02-23 |
|
||||
| `linux-x64` | `2.7.0` | 2025-04-21 |
|
||||
| `linux-arm` | `2.7.0` | 2025-02-15 |
|
||||
| `linux-arm` | `2.7.0` | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
@ -145,7 +145,8 @@ The [flow diagram is displayed after the example steps](#flow-diagram)
|
||||
:::note pass
|
||||
|
||||
The Windows build requires Visual Studio with "Desktop development with C++".
|
||||
Commands must be run in a "Native Tools Command Prompt" session.
|
||||
|
||||
**Commands must be run in a "Native Tools Command Prompt" session.**
|
||||
|
||||
:::
|
||||
|
||||
@ -405,10 +406,10 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | Version | PHP | Date |
|
||||
|:-------------|:--------|:---------|:-----------|
|
||||
| `darwin-x64` | `2.7.0` | `8.4.2` | 2025-03-31 |
|
||||
| `darwin-arm` | `2.7.0` | `8.4.4` | 2025-02-25 |
|
||||
| `darwin-x64` | `2.7.0` | `8.4.11` | 2026-01-21 |
|
||||
| `darwin-arm` | `2.7.0` | `8.4.8` | 2026-01-23 |
|
||||
| `linux-x64` | `2.7.0` | `8.3.6` | 2025-04-21 |
|
||||
| `linux-arm` | `2.7.0` | `8.2.26` | 2025-02-15 |
|
||||
| `linux-arm` | `2.7.0` | `8.4.16` | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
@ -547,10 +548,12 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | Version | Python | Date |
|
||||
|:-------------|:--------|:---------|:-----------|
|
||||
| `darwin-x64` | `2.7.0` | `3.13.1` | 2025-03-31 |
|
||||
| `darwin-arm` | `2.7.0` | `3.12.3` | 2025-03-30 |
|
||||
| `darwin-x64` | `2.7.0` | `3.13.7` | 2026-01-21 |
|
||||
| `darwin-arm` | `2.7.0` | `3.12.3` | 2026-01-23 |
|
||||
| `win11-x64` | `2.7.0` | `3.11.9` | 2026-02-02 |
|
||||
| `win11-arm` | `2.7.0` | `3.11.9` | 2026-02-02 |
|
||||
| `linux-x64` | `2.7.0` | `3.12.3` | 2025-04-21 |
|
||||
| `linux-arm` | `2.7.0` | `3.11.2` | 2025-02-15 |
|
||||
| `linux-arm` | `2.7.0` | `3.13.5` | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
@ -558,6 +561,9 @@ This demo was tested in the following deployments:
|
||||
|
||||
1) Build the Duktape shared library:
|
||||
|
||||
<Tabs groupId="triple">
|
||||
<TabItem value="darwin-x64" label="MacOS">
|
||||
|
||||
```bash
|
||||
curl -LO https://duktape.org/duktape-2.7.0.tar.xz
|
||||
tar -xJf duktape-2.7.0.tar.xz
|
||||
@ -566,18 +572,92 @@ make -f Makefile.sharedlibrary
|
||||
cd ..
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="linux-x64" label="Linux">
|
||||
|
||||
```bash
|
||||
curl -LO https://duktape.org/duktape-2.7.0.tar.xz
|
||||
tar -xJf duktape-2.7.0.tar.xz
|
||||
cd duktape-2.7.0
|
||||
make -f Makefile.sharedlibrary
|
||||
cd ..
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="win11-x64" label="Windows">
|
||||
|
||||
- Download and extract the source tarball:
|
||||
|
||||
```bash
|
||||
curl -LO https://duktape.org/duktape-2.7.0.tar.xz
|
||||
tar -xJf duktape-2.7.0.tar.xz
|
||||
```
|
||||
|
||||
- Enter the source folder:
|
||||
|
||||
```bash
|
||||
cd duktape-2.7.0
|
||||
```
|
||||
|
||||
- Edit `src\duk_config.h` and add the highlighted lines to the end of the file:
|
||||
|
||||
```c title="src\duk_config.h (add highlighted lines to end of file)"
|
||||
#endif /* DUK_CONFIG_H_INCLUDED */
|
||||
|
||||
// highlight-start
|
||||
#define DUK_EXTERNAL_DECL extern __declspec(dllexport)
|
||||
#define DUK_EXTERNAL __declspec(dllexport)
|
||||
// highlight-end
|
||||
```
|
||||
|
||||
- Build the Duktape DLL:
|
||||
|
||||
```cmd
|
||||
cl /O2 /W3 /Isrc /LD /DDUK_SINGLE_FILE /DDUK_F_DLL_BUILD /DDUK_F_WINDOWS /DDUK_COMPILING_DUKTAPE src\\duktape.c
|
||||
```
|
||||
|
||||
- Move up to the parent directory:
|
||||
|
||||
```bash
|
||||
cd ..
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
2) Copy the shared library to the current folder. When the demo was last tested,
|
||||
the shared library file name differed by platform:
|
||||
|
||||
| OS | name |
|
||||
|:-------|:--------------------------|
|
||||
| Darwin | `libduktape.207.20700.so` |
|
||||
| Linux | `libduktape.so.207.20700` |
|
||||
| OS | name |
|
||||
|:--------|:--------------------------|
|
||||
| Darwin | `libduktape.207.20700.so` |
|
||||
| Linux | `libduktape.so.207.20700` |
|
||||
| Windows | `duktape.dll` |
|
||||
|
||||
<Tabs groupId="triple">
|
||||
<TabItem value="darwin-x64" label="MacOS">
|
||||
|
||||
```bash
|
||||
cp duktape-*/libduktape.* .
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="linux-x64" label="Linux">
|
||||
|
||||
```bash
|
||||
cp duktape-*/libduktape.* .
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="win11-x64" label="Windows">
|
||||
|
||||
```cmd
|
||||
copy duktape-2.7.0\duktape.dll .
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
3) Download the SheetJS Standalone script, shim script and test file. Move all
|
||||
three files to the project directory:
|
||||
|
||||
@ -630,6 +710,38 @@ The name of the library is `libduktape.so.207.20700`:
|
||||
lib = "libduktape.so.207.20700"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="win11-x64" label="Windows">
|
||||
|
||||
The name of the library is `duktape.dll`:
|
||||
|
||||
```python title="SheetJSDuk.py (change highlighted line)"
|
||||
# highlight-next-line
|
||||
lib = ".\\duktape.dll"
|
||||
```
|
||||
|
||||
In addition, the following changes must be made:
|
||||
|
||||
- `str_to_c` must be defined as follows:
|
||||
|
||||
```python title="SheetJSDuk.py (replace str_to_c function)"
|
||||
def str_to_c(s):
|
||||
if type(s) == bytes:
|
||||
b = s
|
||||
else:
|
||||
b = s.encode("utf8")
|
||||
return [c_char_p(b), len(b)]
|
||||
```
|
||||
|
||||
- `eval_file` must `open` with mode `rb`:
|
||||
|
||||
```python title="SheetJSDuk.py (edit highlighted line)"
|
||||
def eval_file(ctx, path):
|
||||
# highlight-next-line
|
||||
with open(path, "rb") as f:
|
||||
code = f.read()
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@ -670,6 +782,16 @@ The name of the library is `libduktape.so.207.20700`:
|
||||
```python title="SheetJSDuk.py (change highlighted line)"
|
||||
# highlight-next-line
|
||||
lib = "./libduktape.so.207.20700"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="win11-x64" label="Windows">
|
||||
|
||||
The name of the library is `duktape.dll`:
|
||||
|
||||
```python title="SheetJSDuk.py (change highlighted line)"
|
||||
# highlight-next-line
|
||||
lib = ".\\duktape.dll"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
@ -692,7 +814,7 @@ The main Duktape code can be added to the Zig build pipeline.
|
||||
|
||||
:::note pass
|
||||
|
||||
The following explanation was verified against Zig 0.12.0.
|
||||
The following explanation was verified against Zig 0.14.0.
|
||||
|
||||
:::
|
||||
|
||||
@ -710,7 +832,7 @@ folder must be added to the include path list:
|
||||
```
|
||||
|
||||
The `duktape.c` source file must be added to the build sequence. For Zig version
|
||||
0.12.0, Duktape must be compiled with flags `-std=c99 -fno-sanitize=undefined`
|
||||
0.14.0, Duktape must be compiled with flags `-std=c99 -fno-sanitize=undefined`
|
||||
and linked against `libc` and `libm`:
|
||||
|
||||
```zig title="build.zig"
|
||||
@ -784,12 +906,12 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | Version | Zig | Date |
|
||||
|:-------------|:--------|:---------|:-----------|
|
||||
| `darwin-x64` | `2.7.0` | `0.14.0` | 2025-03-31 |
|
||||
| `darwin-arm` | `2.7.0` | `0.13.0` | 2025-02-13 |
|
||||
| `win11-x64` | `2.7.0` | `0.13.0` | 2024-12-20 |
|
||||
| `darwin-x64` | `2.7.0` | `0.15.2` | 2026-01-20 |
|
||||
| `darwin-arm` | `2.7.0` | `0.15.2` | 2026-01-20 |
|
||||
| `win11-x64` | `2.7.0` | `0.14.0` | 2025-04-28 |
|
||||
| `win11-arm` | `2.7.0` | `0.13.0` | 2025-02-23 |
|
||||
| `linux-x64` | `2.7.0` | `0.14.0` | 2025-04-21 |
|
||||
| `linux-arm` | `2.7.0` | `0.13.0` | 2025-02-15 |
|
||||
| `linux-arm` | `2.7.0` | `0.15.2` | 2026-03-07 |
|
||||
|
||||
On Windows, due to incompatibilities between WSL and PowerShell, some commands
|
||||
must be run in WSL Bash.
|
||||
@ -812,15 +934,15 @@ the project folder.
|
||||
For X64 Mac:
|
||||
|
||||
```bash
|
||||
curl -LO https://ziglang.org/download/0.14.0/zig-macos-x86_64-0.14.0.tar.xz
|
||||
tar -xzf zig-macos-*.tar.xz
|
||||
curl -LO https://ziglang.org/download/0.15.2/zig-x86_64-macos-0.15.2.tar.xz
|
||||
tar -xzf zig-*.tar.xz
|
||||
```
|
||||
|
||||
For ARM64 Mac:
|
||||
|
||||
```bash
|
||||
curl -LO https://ziglang.org/download/0.13.0/zig-macos-aarch64-0.13.0.tar.xz
|
||||
tar -xzf zig-macos-*.tar.xz
|
||||
curl -LO https://ziglang.org/download/0.15.2/zig-aarch64-macos-0.15.2.tar.xz
|
||||
tar -xzf zig-*.tar.xz
|
||||
```
|
||||
|
||||
|
||||
@ -838,9 +960,9 @@ tar -xf zig-linux-*.tar
|
||||
For AArch64 Linux:
|
||||
|
||||
```bash
|
||||
curl -LO https://ziglang.org/download/0.13.0/zig-linux-aarch64-0.13.0.tar.xz
|
||||
xz -d zig-linux-*.tar.xz
|
||||
tar -xf zig-linux-*.tar
|
||||
curl -LO https://ziglang.org/download/0.15.2/zig-aarch64-linux-0.15.2.tar.xz
|
||||
xz -d zig-*.tar.xz
|
||||
tar -xf zig-*.tar
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
@ -855,8 +977,8 @@ The following commands should be run within WSL bash.
|
||||
For X64 Windows:
|
||||
|
||||
```bash
|
||||
curl -LO https://ziglang.org/download/0.13.0/zig-windows-x86_64-0.13.0.zip
|
||||
unzip zig-windows-x86_64-0.13.0.zip
|
||||
curl -LO https://ziglang.org/download/0.14.0/zig-windows-x86_64-0.14.0.zip
|
||||
unzip zig-windows-x86_64-0.14.0.zip
|
||||
```
|
||||
|
||||
For ARM64 Windows:
|
||||
@ -1017,10 +1139,10 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | Version | Date |
|
||||
|:-------------|:--------|:-----------|
|
||||
| `darwin-x64` | `2.2.0` | 2025-03-31 |
|
||||
| `darwin-arm` | `2.2.0` | 2025-03-30 |
|
||||
| `darwin-x64` | `2.2.0` | 2026-01-21 |
|
||||
| `darwin-arm` | `2.2.0` | 2026-03-07 |
|
||||
| `linux-x64` | `2.2.0` | 2025-04-21 |
|
||||
| `linux-arm` | `2.2.0` | 2025-02-15 |
|
||||
| `linux-arm` | `2.2.0` | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
@ -1112,11 +1234,39 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | Version | Date |
|
||||
|:-------------|:--------|:-----------|
|
||||
| `darwin-x64` | `2.2.1` | 2025-03-31 |
|
||||
| `darwin-arm` | `2.2.1` | 2025-03-31 |
|
||||
| `win11-x64` | `2.2.1` | 2025-04-17 |
|
||||
| `linux-x64` | `2.2.1` | 2025-04-18 |
|
||||
| `linux-arm` | `2.2.1` | 2025-04-18 |
|
||||
| `darwin-x64` | `2.2.1` | 2026-01-21 |
|
||||
| `darwin-arm` | `2.2.1` | 2026-03-07 |
|
||||
| `win11-x64` | `2.2.1` | 2026-02-02 |
|
||||
| `win11-arm` | `2.2.1` | 2026-02-02 |
|
||||
| `linux-x64` | `2.2.1` | 2026-01-08 |
|
||||
| `linux-arm` | `2.2.1` | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
|
||||
The `ducc` crate cannot compile Duktape from source in Windows on ARM, so the
|
||||
x64 Rust toolchain must be used through the X64 compatibility layer.
|
||||
|
||||
<details>
|
||||
<summary><b>Windows on ARM steps</b> (click to show)</summary>
|
||||
|
||||
The following commands switch to the X64 toolchain:
|
||||
|
||||
```pwsh
|
||||
rustup toolchain install stable-x86_64-pc-windows-msvc --force-non-host
|
||||
rustup default stable-x86_64-pc-windows-msvc --force-non-host
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
The following command switches back to the native toolchain:
|
||||
|
||||
```pwsh
|
||||
rustup default stable
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
:::
|
||||
|
||||
@ -1181,7 +1331,7 @@ cargo add ducc base64
|
||||
6) Build and run the app:
|
||||
|
||||
```bash
|
||||
cargo run pres.numbers
|
||||
cargo run -- pres.numbers
|
||||
```
|
||||
|
||||
If the program succeeded, the CSV contents will be printed to console and the
|
||||
|
||||
@ -148,8 +148,8 @@ This demo was tested in the following deployments:
|
||||
|:--------------|:-------------|:--------------|:-----------------|:-----------|
|
||||
| `13.7.5` | `darwin-x64` | macOS 15.3.2 | `clang 16.0.0` | 2025-03-31 |
|
||||
| `13.5.92` | `darwin-arm` | macOS 14.5 | `clang 16.0.0` | 2025-02-15 |
|
||||
| `12.7.130` | `win11-x64` | Windows 11 | `CL 19.42.34435` | 2024-12-20 |
|
||||
| `12.7.130` | `linux-x64` | HoloOS 3.6.20 | `gcc 13.2.1` | 2025-01-02 |
|
||||
| `13.8.124` | `win11-x64` | Windows 11 | `CL 19.43.34810` | 2025-05-11 |
|
||||
| `13.5.92` | `linux-x64` | Ubuntu 24.04 | `gcc 13.3.0` | 2025-06-16 |
|
||||
| `13.5.92` | `linux-arm` | Debian 12 | `gcc 12.2.0` | 2025-02-15 |
|
||||
|
||||
:::
|
||||
@ -184,7 +184,7 @@ cd /usr/local/lib
|
||||
|
||||
:::note pass
|
||||
|
||||
If this step throws a permission error, run the following commands:
|
||||
If this step throws an error, run the following commands to fix permissions:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /usr/local/lib
|
||||
@ -204,13 +204,15 @@ installation steps.
|
||||
Using the installer tool, the "Desktop development with C++" workload must be
|
||||
installed. In the sidebar, verify the following components are checked:
|
||||
|
||||
- "C++ ATL for latest ... build tools" (`v143` when last tested)
|
||||
- "C++ MFC for latest ... build tools" (`v143` when last tested)
|
||||
- "C++ ATL for latest ... build tools (x86 & x64)" (`v143` when last tested)
|
||||
- "C++ ATL for latest ... build tools with Spectre Mitigations (x86 & x64)" (`v143` when last tested)
|
||||
- "C++ MFC for latest ... build tools (x86 & x64)" (`v143` when last tested)
|
||||
- "C++ MFC for latest ... build tools with Spectre Mitigations (x86 & x64)" (`v143` when last tested)
|
||||
|
||||
In the "Individual components" tab, search for "Windows 11 SDK" and verify that
|
||||
"Windows 11 SDK (10.0.22621.0)" is checked.
|
||||
"Windows 11 SDK (10.0.26100.0)" is checked.
|
||||
|
||||
**Even though newer SDKs exist, Windows 11 SDK 10.0.22621.0 must be installed!**
|
||||
**Even though newer SDKs may exist, V8 expects specific Windows SDK versions!**
|
||||
|
||||
Click "Modify" and allow the installer to finish.
|
||||
|
||||
@ -222,7 +224,7 @@ The SDK debugging tools must be installed after the SDK is installed.
|
||||
available, search for "Installed apps".
|
||||
|
||||
2) When the setting panel opens, scroll down to "Windows Software Development
|
||||
Kit - Windows 10.0.22621" and click "Modify".
|
||||
Kit - Windows 10.0.26100" and click "Modify".
|
||||
|
||||
3) In the new window, select "Change" and click "Next"
|
||||
|
||||
@ -266,13 +268,12 @@ sudo chmod 777 /usr/local/lib
|
||||
</TabItem>
|
||||
<TabItem value="win" label="Windows">
|
||||
|
||||
[The bundle](https://storage.googleapis.com/chrome-infra/depot_tools.zip) is a
|
||||
ZIP file that should be downloaded and extracted.
|
||||
|
||||
The demo was last tested on a NTFS-formatted drive (mounted at `C:\`). The ZIP
|
||||
was extracted to `C:\src\depot_tools`.
|
||||
|
||||
After extracting, verify that the `depot_tools` folder is not read-only.
|
||||
```bash
|
||||
cd c:\
|
||||
mkdir src
|
||||
cd src
|
||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
@ -334,7 +335,22 @@ gclient
|
||||
gclient
|
||||
```
|
||||
|
||||
:::caution pass
|
||||
:::info Troubleshooting
|
||||
|
||||
In test runs on fresh machines, `gclient` failed with the following message:
|
||||
|
||||
```
|
||||
Error: client not configured; see 'gclient config'
|
||||
```
|
||||
|
||||
This was fixed by setting `user.name` and `user.email` in the Git configuration:
|
||||
|
||||
```bash
|
||||
git config --global user.name "John Doe"
|
||||
git config --global user.email "jdoe@email.com"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
`gclient` may throw errors related to `git` and permissions issues:
|
||||
|
||||
@ -349,9 +365,7 @@ To add an exception for this directory, call:
|
||||
These issues are related to the exFAT file system. They were resolved by running
|
||||
the recommended commands and re-running `gclient`.
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
---
|
||||
|
||||
There may be errors pertaining to `gitconfig`:
|
||||
|
||||
@ -435,11 +449,11 @@ The recommended fix is to delete the referenced folder and re-run `gclient sync`
|
||||
</Tabs>
|
||||
|
||||
|
||||
5) Checkout the desired version. The following command pulls `13.7.5`:
|
||||
5) Checkout the desired version. The following command pulls `13.8.124`:
|
||||
|
||||
|
||||
```bash
|
||||
git checkout tags/13.7.5 -b sample
|
||||
git checkout tags/13.8.124 -b sample
|
||||
```
|
||||
|
||||
:::caution pass
|
||||
@ -447,14 +461,14 @@ git checkout tags/13.7.5 -b sample
|
||||
The official documentation recommends:
|
||||
|
||||
```bash
|
||||
git checkout refs/tags/13.7.5 -b sample -t
|
||||
git checkout refs/tags/13.8.124 -b sample -t
|
||||
```
|
||||
|
||||
This command failed in local testing:
|
||||
|
||||
```
|
||||
E:\v8\v8>git checkout refs/tags/13.7.5 -b sample -t
|
||||
fatal: cannot set up tracking information; starting point 'refs/tags/13.7.5' is not a branch
|
||||
E:\v8\v8>git checkout refs/tags/13.8.124 -b sample -t
|
||||
fatal: cannot set up tracking information; starting point 'refs/tags/13.8.124' is not a branch
|
||||
```
|
||||
|
||||
:::
|
||||
@ -475,7 +489,7 @@ ninja -C out.gn/x64.release.sample v8_monolith
|
||||
|
||||
**This may not work in newer Python releases due to a breaking change!**
|
||||
|
||||
Python 3.13 removed the `pipes` module from the standard library[^9]. `v8gen.py`
|
||||
Python 3.13 removed the `pipes` module from the standard library[^7]. `v8gen.py`
|
||||
will fail on newer Python releases with the following traceback:
|
||||
|
||||
```
|
||||
@ -511,6 +525,18 @@ ninja -C out.gn/arm64.release.sample v8_monolith
|
||||
|
||||
```bash
|
||||
tools/dev/v8gen.py x64.release.sample
|
||||
```
|
||||
|
||||
Append the following lines to `out.gn/x64.release.sample/args.gn`:
|
||||
|
||||
```text title="out.gn/x64.release.sample/args.gn (add to file)"
|
||||
is_clang = false
|
||||
treat_warnings_as_errors = false
|
||||
```
|
||||
|
||||
Run the build:
|
||||
|
||||
```bash
|
||||
ninja -C out.gn/x64.release.sample v8_monolith
|
||||
```
|
||||
|
||||
@ -643,6 +669,24 @@ python3 tools\dev\v8gen.py -vv x64.release.sample
|
||||
ninja -C out.gn\x64.release.sample v8_monolith
|
||||
```
|
||||
|
||||
:::info pass
|
||||
|
||||
If the expected Windows SDK version is missing or the debugging tools are not
|
||||
installed, the build will fail with an error referencing `include`:
|
||||
|
||||
```
|
||||
Exception: Path "C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um" from environment variable "include" does not exist. Make sure the necessary SDK is installed.
|
||||
```
|
||||
|
||||
In the error message, the expected Windows SDK version is listed in the path.
|
||||
For example, in the aforementioned message, `10.0.26100.0` is the SDK version.
|
||||
|
||||
The expected version of the Windows SDK should be installed from Visual Studio
|
||||
Installer. After installing the SDK, the corresponding SDK debugging tools
|
||||
should be installed using the procedure from Step 0.
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
|
||||
In local testing, the build sometimes failed with a `dbghelp.dll` error:
|
||||
@ -744,7 +788,7 @@ ld: multiple errors: unknown file type in '/Users/sheetjs/dev/v8/v8/out.gn/x64.r
|
||||
```bash
|
||||
g++ -I. -Iinclude samples/hello-world.cc -o hello_world -fno-rtti -lv8_monolith \
|
||||
-lv8_libbase -lv8_libplatform -ldl -Lout.gn/x64.release.sample/obj/ -pthread \
|
||||
-std=c++17 -DV8_COMPRESS_POINTERS=1 -DV8_ENABLE_SANDBOX
|
||||
-std=c++20 -DV8_COMPRESS_POINTERS=1 -DV8_ENABLE_SANDBOX
|
||||
./hello_world
|
||||
```
|
||||
|
||||
@ -762,10 +806,32 @@ g++ -I. -Iinclude samples/hello-world.cc -o hello_world -fno-rtti -lv8_monolith
|
||||
<TabItem value="win11-x64" label="Windows">
|
||||
|
||||
```bash
|
||||
cl /I. /Iinclude samples/hello-world.cc /GR- v8_monolith.lib Advapi32.lib Winmm.lib Dbghelp.lib /std:c++17 /DV8_COMPRESS_POINTERS=1 /DV8_ENABLE_SANDBOX /link /out:hello_world.exe /LIBPATH:out.gn\x64.release.sample\obj\
|
||||
cl /I. /Iinclude samples/hello-world.cc /GR- v8_monolith.lib Advapi32.lib Winmm.lib Dbghelp.lib /std:c++20 /DV8_COMPRESS_POINTERS=1 /DV8_ENABLE_SANDBOX /link /out:hello_world.exe /LIBPATH:out.gn\x64.release.sample\obj\
|
||||
.\hello_world.exe
|
||||
```
|
||||
|
||||
:::caution pass
|
||||
|
||||
When this demo was last tested, the build failed with a `C++` standard error:
|
||||
|
||||
```
|
||||
c:\v8\v8\include\v8config.h(13): fatal error C1189: #error: "C++20 or later required."
|
||||
```
|
||||
|
||||
The `/std:c++20` option sets the `C++` standard in use. The workaround is to
|
||||
suppress the broken version check:
|
||||
|
||||
```c++ title="include\v8config.h (edit highlighted line)"
|
||||
#if __cplusplus <= 201703L
|
||||
// highlight-next-line
|
||||
//#error "C++20 or later required."
|
||||
#endif
|
||||
```
|
||||
|
||||
After suppressing the error, re-run the build commands.
|
||||
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@ -901,7 +967,7 @@ g++ -I. -Iinclude hello-world.cc -o hello_world -fno-rtti -lv8_monolith \
|
||||
<TabItem value="win" label="Windows">
|
||||
|
||||
```bash
|
||||
cl /MT /I..\v8\v8\ /I..\v8\v8\include hello-world.cc /GR- v8_monolith.lib Advapi32.lib Winmm.lib Dbghelp.lib /std:c++17 /DV8_COMPRESS_POINTERS=1 /DV8_ENABLE_SANDBOX /link /out:hello_world.exe /LIBPATH:..\v8\v8\out.gn\x64.release.sample\obj\
|
||||
cl /MT /I..\v8\v8\ /I..\v8\v8\include hello-world.cc /GR- v8_monolith.lib Advapi32.lib Winmm.lib Dbghelp.lib /std:c++20 /DV8_COMPRESS_POINTERS=1 /DV8_ENABLE_SANDBOX /link /out:hello_world.exe /LIBPATH:..\v8\v8\out.gn\x64.release.sample\obj\
|
||||
.\hello_world.exe
|
||||
```
|
||||
|
||||
@ -974,7 +1040,7 @@ g++ -I. -Iinclude sheetjs.v8.cc -o sheetjs.v8 -fno-rtti -lv8_monolith \
|
||||
<TabItem value="win" label="Windows">
|
||||
|
||||
```bash
|
||||
cl /MT /I..\v8\v8\ /I..\v8\v8\include sheetjs.v8.cc /GR- v8_monolith.lib Advapi32.lib Winmm.lib Dbghelp.lib /std:c++17 /DV8_COMPRESS_POINTERS=1 /DV8_ENABLE_SANDBOX /link /out:sheetjs.v8.exe /LIBPATH:..\v8\v8\out.gn\x64.release.sample\obj\
|
||||
cl /MT /I..\v8\v8\ /I..\v8\v8\include sheetjs.v8.cc /GR- v8_monolith.lib Advapi32.lib Winmm.lib Dbghelp.lib /std:c++20 /DV8_COMPRESS_POINTERS=1 /DV8_ENABLE_SANDBOX /link /out:sheetjs.v8.exe /LIBPATH:..\v8\v8\out.gn\x64.release.sample\obj\
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
@ -1012,18 +1078,14 @@ may not work on every platform.
|
||||
The `v8` crate[^6] provides binary builds and straightforward bindings. The Rust
|
||||
code is similar to the C++ code.
|
||||
|
||||
Pulling data from an `ArrayBuffer` back into Rust involves an unsafe operation:
|
||||
Pulling data from an `ArrayBuffer` back into Rust involves an unsafe conversion
|
||||
from a raw pointer and byte length to `Vec<u8>`:
|
||||
|
||||
```rust
|
||||
/* assuming JS code returns an ArrayBuffer, copy result to a Vec<u8> */
|
||||
fn eval_code_ab(scope: &mut v8::HandleScope, code: &str) -> Vec<u8> {
|
||||
let source = v8::String::new(scope, code).unwrap();
|
||||
let script = v8::Script::compile(scope, source, None).unwrap();
|
||||
let result: v8::Local<v8::ArrayBuffer> = script.run(scope).unwrap().try_into().unwrap();
|
||||
/* In C++, `Data` returns a pointer. Collecting data into Vec<u8> is unsafe */
|
||||
```rust title="Pull ArrayBuffer data from V8 to Rust vector of bytes"
|
||||
fn pull_ab_to_vecu8(ab: v8::Local<v8::ArrayBuffer>) -> Vec<u8> {
|
||||
unsafe { return std::slice::from_raw_parts_mut(
|
||||
result.data().unwrap().cast::<u8>().as_ptr(),
|
||||
result.byte_length()
|
||||
ab.data().unwrap().cast::<u8>().as_ptr(),
|
||||
ab.byte_length()
|
||||
).to_vec(); }
|
||||
}
|
||||
```
|
||||
@ -1034,11 +1096,12 @@ This demo was last tested in the following deployments:
|
||||
|
||||
| Architecture | V8 Crate | Date |
|
||||
|:-------------|:----------|:-----------|
|
||||
| `darwin-x64` | `136.0.0` | 2025-04-21 |
|
||||
| `darwin-x64` | `146.3.0` | 2026-03-08 |
|
||||
| `darwin-arm` | `134.3.0` | 2025-02-13 |
|
||||
| `win11-x64` | `130.0.2` | 2024-12-20 |
|
||||
| `linux-x64` | `130.0.7` | 2025-01-09 |
|
||||
| `linux-arm` | `134.4.0` | 2025-02-15 |
|
||||
| `win11-x64` | `137.1.0` | 2025-05-11 |
|
||||
| `win11-arm` | `145.0.0` | 2026-02-02 |
|
||||
| `linux-x64` | `142.2.0` | 2026-01-08 |
|
||||
| `linux-arm` | `146.3.0` | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
@ -1070,21 +1133,53 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
|
||||
curl -LO https://docs.sheetjs.com/pres.numbers`}
|
||||
</CodeBlock>
|
||||
|
||||
:::note pass
|
||||
|
||||
In PowerShell, the command may fail with a parameter error:
|
||||
|
||||
```
|
||||
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
|
||||
```
|
||||
|
||||
`curl.exe` must be invoked directly:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
|
||||
curl.exe -LO https://docs.sheetjs.com/pres.numbers`}
|
||||
</CodeBlock>
|
||||
|
||||
:::
|
||||
|
||||
4) Download [`main.rs`](pathname:///v8/main.rs) and replace `src/main.rs`:
|
||||
|
||||
```bash
|
||||
curl -L -o src/main.rs https://docs.sheetjs.com/v8/main.rs
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
In PowerShell, the command may fail with a parameter error:
|
||||
|
||||
```
|
||||
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
|
||||
```
|
||||
|
||||
`curl.exe` must be invoked directly:
|
||||
|
||||
```bash
|
||||
curl.exe -L -o src/main.rs https://docs.sheetjs.com/v8/main.rs
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::info pass
|
||||
|
||||
There was a breaking change in version `0.102.0` affecting `v8::Context::new`.
|
||||
When targeting older versions of the crate, remove the second argument:
|
||||
There were multiple breaking changes in the `v8` crate. This example was tested
|
||||
against version `142.2.0`.
|
||||
|
||||
```rust title="src/main.rs"
|
||||
let context = v8::Context::new(handle_scope); // v8 <= 0.101.0
|
||||
//let context = v8::Context::new(handle_scope, Default::default()); // v8 >= 0.102.0
|
||||
```
|
||||
Older versions of this demo script were designed for older `v8` versions. They
|
||||
are available in the source repo for the documentation. Please reach out to the
|
||||
[SheetJS chat](https://sheetjs.com/chat) for more details.
|
||||
|
||||
:::
|
||||
|
||||
@ -1118,10 +1213,29 @@ This demo was last tested in the following deployments:
|
||||
| Architecture | V8 Version | Javet | Java | Date |
|
||||
|:-------------|:--------------|:--------|:----------|:-----------|
|
||||
| `darwin-x64` | `13.2.152.16` | `4.1.1` | `24.0.1` | 2025-04-21 |
|
||||
| `darwin-arm` | `13.2.152.16` | `4.1.1` | `17.0.14` | 2025-03-30 |
|
||||
| `win11-x64` | `12.6.228.13` | `3.1.3` | `21.0.5` | 2024-12-20 |
|
||||
| `linux-x64` | `13.2.152.16` | `4.1.1` | `21.0.6` | 2025-04-21 |
|
||||
| `linux-arm` | `13.2.152.16` | `4.1.1` | `17.0.14` | 2025-02-16 |
|
||||
| `darwin-arm` | `13.2.152.16` | `4.1.1` | `17.0.14` | 2026-03-04 |
|
||||
| `win11-x64` | `13.2.152.16` | `4.1.1` | `17.0.12` | 2026-03-04 |
|
||||
| `win11-arm` | `13.2.152.16` | `4.1.1` | `25.0.2` | 2026-03-04 |
|
||||
| `linux-x64` | `13.2.152.16` | `4.1.1` | `21.0.10` | 2026-02-04 |
|
||||
| `linux-arm` | `13.2.152.16` | `4.1.1` | `17.0.18` | 2026-02-04 |
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
|
||||
Javet does not provide a pre-built JAR for Windows on ARM. This demo was tested
|
||||
using the X64 compatibility layer.
|
||||
|
||||
<details>
|
||||
<summary><b>Windows on ARM steps</b> (click to show)</summary>
|
||||
|
||||
Windows on ARM defaults to ARM64 JRE/JDK. A proper x64 JDK must be installed and
|
||||
`JAVA_HOME` must point to the x64 version.
|
||||
|
||||
[Direct downloads are available at `adoptium.net`](https://adoptium.net/temurin/releases/).
|
||||
The Windows x64 JDK release should be downloaded and installed.
|
||||
|
||||
</details>
|
||||
|
||||
:::
|
||||
|
||||
@ -1176,9 +1290,27 @@ curl -LO https://repo1.maven.org/maven2/com/caoccao/javet/javet-v8-linux-arm64/4
|
||||
<TabItem value="win" label="Windows">
|
||||
|
||||
```bash
|
||||
curl -LO https://repo1.maven.org/maven2/com/caoccao/javet/javet/3.1.3/javet-3.1.3.jar
|
||||
curl -LO https://repo1.maven.org/maven2/com/caoccao/javet/javet/4.1.1/javet-4.1.1.jar
|
||||
curl -LO https://repo1.maven.org/maven2/com/caoccao/javet/javet-v8-windows-x86_64/4.1.1/javet-v8-windows-x86_64-4.1.1.jar
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
In PowerShell, the command may fail with a parameter error:
|
||||
|
||||
```
|
||||
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
|
||||
```
|
||||
|
||||
`curl.exe` must be invoked directly:
|
||||
|
||||
```bash
|
||||
curl.exe -LO https://repo1.maven.org/maven2/com/caoccao/javet/javet/4.1.1/javet-4.1.1.jar
|
||||
curl.exe -LO https://repo1.maven.org/maven2/com/caoccao/javet/javet-v8-windows-x86_64/4.1.1/javet-v8-windows-x86_64-4.1.1.jar
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@ -1195,12 +1327,45 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
|
||||
curl -LO https://docs.sheetjs.com/pres.xlsx`}
|
||||
</CodeBlock>
|
||||
|
||||
:::note pass
|
||||
|
||||
In PowerShell, the command may fail with a parameter error:
|
||||
|
||||
```
|
||||
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
|
||||
```
|
||||
|
||||
`curl.exe` must be invoked directly:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
|
||||
curl.exe -LO https://docs.sheetjs.com/pres.xlsx`}
|
||||
</CodeBlock>
|
||||
|
||||
:::
|
||||
|
||||
4) Download [`SheetJSJavet.java`](pathname:///v8/SheetJSJavet.java):
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/v8/SheetJSJavet.java
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
In PowerShell, the command may fail with a parameter error:
|
||||
|
||||
```
|
||||
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
|
||||
```
|
||||
|
||||
`curl.exe` must be invoked directly:
|
||||
|
||||
```bash
|
||||
curl.exe -LO https://docs.sheetjs.com/v8/SheetJSJavet.java
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
5) Build and run the Java application:
|
||||
|
||||
<Tabs groupId="os">
|
||||
@ -1245,8 +1410,8 @@ java -cp ".:javet-4.1.1.jar:javet-v8-linux-arm64-4.1.1.jar" SheetJSJavet pres.xl
|
||||
<TabItem value="win" label="Windows">
|
||||
|
||||
```bash
|
||||
javac -cp ".;javet-3.1.3.jar" SheetJSJavet.java
|
||||
java -cp ".;javet-3.1.3.jar" SheetJSJavet pres.xlsx
|
||||
javac -cp ".;javet-4.1.1.jar;javet-v8-windows-x86_64-4.1.1.jar" SheetJSJavet.java
|
||||
java -cp ".;javet-4.1.1.jar;javet-v8-windows-x86_64-4.1.1.jar" SheetJSJavet pres.xlsx
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
@ -1280,12 +1445,12 @@ This demo was last tested in the following deployments:
|
||||
|
||||
| Architecture | V8 Version | Date |
|
||||
|:-------------|:--------------|:-----------|
|
||||
| `darwin-x64` | `13.3.415.23` | 2025-03-31 |
|
||||
| `darwin-arm` | `13.3.415.23` | 2025-03-31 |
|
||||
| `win11-x64` | `12.3.219.12` | 2024-12-20 |
|
||||
| `darwin-x64` | `13.3.415.23` | 2026-03-06 |
|
||||
| `darwin-arm` | `13.3.415.23` | 2026-03-06 |
|
||||
| `win11-x64` | `13.3.415.23` | 2025-05-11 |
|
||||
| `win11-arm` | `12.3.219.12` | 2025-02-23 |
|
||||
| `linux-x64` | `12.3.219.12` | 2025-01-10 |
|
||||
| `linux-arm` | `12.3.219.12` | 2025-02-16 |
|
||||
| `linux-x64` | `12.3.219.12` | 2026-03-06 |
|
||||
| `linux-arm` | `13.3.415.23` | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
@ -1328,7 +1493,7 @@ Click "OK" in each window (3 windows) and restart your computer.
|
||||
<details>
|
||||
<summary><b>Installation Notes</b> (click to show)</summary>
|
||||
|
||||
For macOS x64 and ARM64, install the `dotnet-sdk` Cask with Homebrew:
|
||||
For macOS x64 and ARM64, the `dotnet-sdk` cask can be installed with Homebrew:
|
||||
|
||||
```bash
|
||||
brew install --cask dotnet-sdk
|
||||
@ -1376,6 +1541,23 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
|
||||
curl -LO https://docs.sheetjs.com/pres.xlsx`}
|
||||
</CodeBlock>
|
||||
|
||||
:::note pass
|
||||
|
||||
In PowerShell, the command may fail with a parameter error:
|
||||
|
||||
```
|
||||
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
|
||||
```
|
||||
|
||||
`curl.exe` must be invoked directly:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
|
||||
curl.exe -LO https://docs.sheetjs.com/pres.xlsx`}
|
||||
</CodeBlock>
|
||||
|
||||
:::
|
||||
|
||||
6) Replace `Program.cs` with the following:
|
||||
|
||||
```csharp title="Program.cs"
|
||||
@ -1404,7 +1586,7 @@ var xlsb = (ITypedArray<byte>)engine.Evaluate("XLSX.write(wb, {bookType: 'xlsb',
|
||||
File.WriteAllBytes("SheetJSClearScript.xlsb", xlsb.ToArray());
|
||||
```
|
||||
|
||||
After saving, run the program and pass the test file name as an argument:
|
||||
7) Run the program, passing the test file name as an argument:
|
||||
|
||||
```bash
|
||||
dotnet run pres.xlsx
|
||||
@ -1416,16 +1598,15 @@ opened in a spreadsheet editor.
|
||||
|
||||
### Python
|
||||
|
||||
[`pyv8`](https://code.google.com/archive/p/pyv8/) is a Python wrapper for V8.
|
||||
|
||||
The `stpyv8` package[^7] is an actively-maintained fork with binary wheels.
|
||||
The [`mini-racer`](https://bpcreech.com/PyMiniRacer/) V8 wrapper package has
|
||||
precompiled wheels for all major platforms.
|
||||
|
||||
:::caution pass
|
||||
|
||||
When this demo was last tested, there was no direct conversion between Python
|
||||
`bytes` and JavaScript `ArrayBuffer` data.
|
||||
|
||||
This is a known issue[^8]. The current recommendation is Base64 strings.
|
||||
This is a known issue. The current recommendation is Base64 strings.
|
||||
|
||||
:::
|
||||
|
||||
@ -1436,25 +1617,26 @@ the `base64` type[^5].
|
||||
|
||||
_Reading Files_
|
||||
|
||||
It is recommended to create a global context with a special method that handles
|
||||
file reading from Python. The `read_file` helper in the following snippet will
|
||||
read bytes from `sheetjs.xlsx` and generate a Base64 string:
|
||||
The file data can be read in Python and encoded as Base64. The `set_object_item`
|
||||
method on the internal context can assign to properties of the global object.
|
||||
|
||||
`mini-racer` does not expose a dedicated API to reference the global object.
|
||||
The standard approach is to evaluate `this` in the JavaScript engine:
|
||||
|
||||
```py
|
||||
from base64 import b64encode;
|
||||
from STPyV8 import JSContext, JSClass;
|
||||
from py_mini_racer import MiniRacer;
|
||||
|
||||
# Create context with methods for file i/o
|
||||
class Base64Context(JSClass):
|
||||
def read_file(self, path):
|
||||
with open(path, "rb") as f:
|
||||
data = f.read();
|
||||
return b64encode(data).decode("ascii");
|
||||
globals = Base64Context();
|
||||
with open("sheetjs.xlsx", "rb") as f:
|
||||
file_data = b64encode(f.read()).decode("ascii");
|
||||
|
||||
# The JSContext starts and cleans up the V8 engine
|
||||
with JSContext(globals) as ctxt:
|
||||
print(ctxt.eval("read_file('sheetjs.xlsx')")); # read base64 data and print
|
||||
# Create context and obtain a handle to `this`
|
||||
ctx = MiniRacer();
|
||||
global_scope = ctx.eval("this");
|
||||
|
||||
# assign to the `fileData` global property and parse
|
||||
ctx._ctx.set_object_item(global_scope, "fileData", file_data);
|
||||
ctx.eval("var wb = XLSX.read(fileData, {type:'base64'});");
|
||||
```
|
||||
|
||||
_Writing Files_
|
||||
@ -1464,14 +1646,14 @@ decoded and written to file from Python:
|
||||
|
||||
```py
|
||||
from base64 import b64decode;
|
||||
from STPyV8 import JSContext;
|
||||
from py_mini_racer import MiniRacer;
|
||||
|
||||
# The JSContext starts and cleans up the V8 engine
|
||||
with JSContext() as ctxt:
|
||||
# ... initialization and workbook creation ...
|
||||
xlsb = ctxt.eval("XLSX.write(wb, {type: 'base64', bookType: 'xlsb'})");
|
||||
with open("SheetJSSTPyV8.xlsb", "wb") as f:
|
||||
f.write(b64decode(xlsb));
|
||||
ctx = MiniRacer();
|
||||
# ... initialization and workbook creation ...
|
||||
xlsb = ctx.eval("XLSX.write(wb, {type: 'base64', bookType: 'xlsb'})");
|
||||
with open("SheetJSMiniRacer.xlsb", "wb") as f:
|
||||
f.write(b64decode(xlsb));
|
||||
ctx.close();
|
||||
```
|
||||
|
||||
#### Python Demo
|
||||
@ -1482,44 +1664,28 @@ This demo was last tested in the following deployments:
|
||||
|
||||
| Architecture | V8 Version | Python | Date |
|
||||
|:-------------|:--------------|:---------|:-----------|
|
||||
| `darwin-x64` | `13.1.201.22` | `3.13.1` | 2025-03-31 |
|
||||
| `darwin-arm` | `13.1.201.22` | `3.13.2` | 2025-04-24 |
|
||||
| `darwin-x64` | `14.4` | `3.13.7` | 2026-03-04 |
|
||||
| `darwin-arm` | `14.4` | `3.14.3` | 2026-03-04 |
|
||||
| `win11-x64` | `14.4` | `3.11.9` | 2026-03-05 |
|
||||
| `win11-arm` | `14.4` | `3.11.9` | 2026-03-05 |
|
||||
| `linux-x64` | `14.4` | `3.13.9` | 2026-03-04 |
|
||||
| `linux-arm` | `14.4` | `3.13.5` | 2026-03-04 |
|
||||
|
||||
:::
|
||||
|
||||
0) Make a new folder for the project:
|
||||
|
||||
```bash
|
||||
mkdir sheetjs-stpyv8
|
||||
cd sheetjs-stpyv8
|
||||
mkdir sheetjs-miniracer
|
||||
cd sheetjs-miniracer
|
||||
```
|
||||
|
||||
1) Install `stpyv8`:
|
||||
1) Install `mini-racer`:
|
||||
|
||||
```bash
|
||||
pip install stpyv8
|
||||
pip install mini-racer
|
||||
```
|
||||
|
||||
:::caution pass
|
||||
|
||||
The install may fail with a `externally-managed-environment` error:
|
||||
|
||||
```
|
||||
error: externally-managed-environment
|
||||
|
||||
× This environment is externally managed
|
||||
```
|
||||
|
||||
The wheel can be downloaded and forcefully installed. The following commands
|
||||
download and install version `13.0.245.16` for Python `3.13` on `darwin-arm`:
|
||||
|
||||
```bash
|
||||
curl -LO https://github.com/cloudflare/stpyv8/releases/download/v13.1.201.22/stpyv8-13.1.201.22-cp313-cp313-macosx_14_0_arm64.whl
|
||||
sudo python -m pip install --upgrade stpyv8-13.1.201.22-cp313-cp313-macosx_14_0_arm64.whl --break-system-packages
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
2) Download the SheetJS standalone script and test file. Move both files to the
|
||||
project directory:
|
||||
|
||||
@ -1533,20 +1699,20 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
|
||||
curl -LO https://docs.sheetjs.com/pres.xlsx`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Download [`sheetjs-stpyv8.py`](pathname:///v8/sheetjs-stpyv8.py):
|
||||
3) Download [`sheetjs-mini-racer.py`](pathname:///v8/sheetjs-mini-racer.py):
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/v8/sheetjs-stpyv8.py
|
||||
curl -LO https://docs.sheetjs.com/v8/sheetjs-mini-racer.py
|
||||
```
|
||||
|
||||
4) Run the script and pass `pres.xlsx` as the first argument:
|
||||
|
||||
```bash
|
||||
python sheetjs-stpyv8.py pres.xlsx
|
||||
python sheetjs-mini-racer.py pres.xlsx
|
||||
```
|
||||
|
||||
The script will display CSV rows from the first worksheet. It will also create
|
||||
`SheetJSSTPyV8.xlsb`, a workbook that can be opened with a spreadsheet editor.
|
||||
`SheetJSMiniRacer.xlsb`, a workbook that can be opened with a spreadsheet editor.
|
||||
|
||||
## Snapshots
|
||||
|
||||
@ -1572,11 +1738,11 @@ This demo was last tested in the following deployments:
|
||||
|
||||
| Architecture | V8 Version | Crate | Date |
|
||||
|:-------------|:--------------|:----------|:-----------|
|
||||
| `darwin-x64` | `13.5.212.10` | `136.0.0` | 2025-04-21 |
|
||||
| `darwin-x64` | `13.5.212.10` | `136.0.0` | 2026-03-08 |
|
||||
| `darwin-arm` | `13.5.212.10` | `136.0.0` | 2025-04-24 |
|
||||
| `win11-x64` | `12.6.228.3` | `0.92.0` | 2024-12-20 |
|
||||
| `linux-x64` | `12.6.228.3` | `0.92.0` | 2025-01-02 |
|
||||
| `linux-arm` | `13.4.114.9` | `134.4.0` | 2025-02-15 |
|
||||
| `win11-x64` | `13.5.212.10` | `136.0.0` | 2025-05-11 |
|
||||
| `linux-x64` | `13.5.212.10` | `136.0.0` | 2025-06-16 |
|
||||
| `linux-arm` | `13.5.212.10` | `136.0.0` | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
@ -1675,6 +1841,4 @@ mv target/release/sheet2csv.exe .
|
||||
[^4]: See [`write` in "Writing Files"](/docs/api/write-options)
|
||||
[^5]: See ["Supported Output Formats" type in "Writing Files"](/docs/api/write-options#supported-output-formats)
|
||||
[^6]: The project does not have an official website. The [official Rust crate](https://crates.io/crates/v8) is hosted on `crates.io`.
|
||||
[^7]: The project does not have a separate website. The source repository is hosted on [GitHub](https://github.com/cloudflare/stpyv8)
|
||||
[^8]: According to a maintainer, [typed arrays were not supported in the original `pyv8` project](https://github.com/cloudflare/stpyv8/issues/104#issuecomment-2059125389)
|
||||
[^9]: `pipes` and other modules were removed from the standard library in Python 3.13 as part of ["PEP 594"](https://docs.python.org/3/whatsnew/3.13.html#whatsnew313-pep594).
|
||||
[^7]: `pipes` and other modules were removed from the standard library in Python 3.13 as part of ["PEP 594"](https://docs.python.org/3/whatsnew/3.13.html#whatsnew313-pep594).
|
||||
@ -30,22 +30,23 @@ This demo was tested in the following deployments:
|
||||
|
||||
| OpenJDK | Rhino | Date |
|
||||
|:--------|:---------|:-----------|
|
||||
| 23.0.1 | `1.7.15` | 2025-01-10 |
|
||||
| 22.0.2 | `1.7.15` | 2025-01-10 |
|
||||
| 21.0.5 | `1.7.15` | 2025-01-10 |
|
||||
| 20.0.2 | `1.7.15` | 2025-01-10 |
|
||||
| 19.0.2 | `1.7.15` | 2025-01-10 |
|
||||
| 18.0.2 | `1.7.15` | 2025-01-10 |
|
||||
| 17.0.13 | `1.7.15` | 2025-01-10 |
|
||||
| 16.0.2 | `1.7.15` | 2025-01-10 |
|
||||
| 15.0.2 | `1.7.15` | 2025-01-10 |
|
||||
| 14.0.2 | `1.7.15` | 2025-01-10 |
|
||||
| 13.0.2 | `1.7.15` | 2025-01-10 |
|
||||
| 12.0.2 | `1.7.15` | 2025-01-10 |
|
||||
| 11.0.25 | `1.7.15` | 2025-01-10 |
|
||||
| 10.0.2 | `1.7.15` | 2025-01-10 |
|
||||
| 9.0.4 | `1.7.15` | 2025-01-10 |
|
||||
| 1.8.0 | `1.7.15` | 2025-01-10 |
|
||||
| 24.0.1 | `1.7.15` | 2025-05-06 |
|
||||
| 23.0.2 | `1.7.15` | 2025-05-06 |
|
||||
| 22.0.2 | `1.7.15` | 2025-05-06 |
|
||||
| 21.0.7 | `1.7.15` | 2025-05-06 |
|
||||
| 20.0.2 | `1.7.15` | 2025-05-06 |
|
||||
| 19.0.2 | `1.7.15` | 2025-05-06 |
|
||||
| 18.0.2 | `1.7.15` | 2025-05-06 |
|
||||
| 17.0.15 | `1.7.15` | 2025-05-06 |
|
||||
| 16.0.1 | `1.7.15` | 2025-05-06 |
|
||||
| 15.0.10 | `1.7.15` | 2025-05-06 |
|
||||
| 14.0.2 | `1.7.15` | 2025-05-06 |
|
||||
| 13.0.2 | `1.7.15` | 2025-05-06 |
|
||||
| 12.0.1 | `1.7.15` | 2025-05-06 |
|
||||
| 11.0.27 | `1.7.15` | 2025-05-06 |
|
||||
| 10 | `1.7.15` | 2025-05-06 |
|
||||
| 9.0.4 | `1.7.15` | 2025-05-06 |
|
||||
| 1.8.0 | `1.7.15` | 2025-05-06 |
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -32,28 +32,28 @@ Swift on MacOS supports JavaScriptCore without additional dependencies.
|
||||
|
||||
| Architecture | Swift | Date |
|
||||
|:-------------|:--------|:-----------|
|
||||
| `darwin-x64` | `6.1` | 2025-04-21 |
|
||||
| `darwin-arm` | `6.1` | 2025-04-21 |
|
||||
| `darwin-x64` | `6.1.2` | 2026-03-04 |
|
||||
| `darwin-arm` | `6.0.3` | 2026-03-04 |
|
||||
|
||||
[**C / C++ Compiled from Source**](#c)
|
||||
|
||||
JavaScriptCore can be built from source and linked in C / C++ programs.
|
||||
|
||||
| Architecture | Version | Date |
|
||||
|:-------------|:-----------------|:-----------|
|
||||
| `darwin-x64` | `7620.2.4.111.7` | 2025-04-21 |
|
||||
| `darwin-arm` | `7620.2.4.111.7` | 2025-04-21 |
|
||||
| `linux-x64` | `7620.2.4.111.7` | 2025-04-21 |
|
||||
| `linux-arm` | `7620.2.4.111.7` | 2025-04-21 |
|
||||
| Architecture | Version | Date |
|
||||
|:-------------|:------------------|:-----------|
|
||||
| `darwin-x64` | `7623.1.14.14.11` | 2026-03-04 |
|
||||
| `darwin-arm` | `7623.1.14.14.11` | 2026-03-04 |
|
||||
| `linux-x64` | `7623.1.14.14.11` | 2026-03-04 |
|
||||
| `linux-arm` | `7623.1.14.14.11` | 2026-03-04 |
|
||||
|
||||
[**Swift Compiled from Source**](#swift-c)
|
||||
|
||||
Swift compiler can link against libraries built from the JavaScriptCore source.
|
||||
|
||||
| Architecture | Version | Date |
|
||||
|:-------------|:-----------------|:-----------|
|
||||
| `linux-x64` | `7620.2.4.111.7` | 2025-04-21 |
|
||||
| `linux-arm` | `7620.2.4.111.7` | 2025-04-21 |
|
||||
| Architecture | Version | Date |
|
||||
|:-------------|:------------------|:-----------|
|
||||
| `linux-x64` | `7623.1.14.14.11` | 2026-03-04 |
|
||||
| `linux-arm` | `7623.1.14.14.11` | 2026-03-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -445,7 +445,7 @@ sudo pacman -Syu base-devel cmake ruby icu glibc linux-api-headers
|
||||
On Debian and Ubuntu, dependencies should be installed with `apt`:
|
||||
|
||||
```bash
|
||||
sudo apt-get install build-essential cmake ruby
|
||||
sudo apt-get install build-essential cmake ruby libicu-dev
|
||||
```
|
||||
|
||||
</details>
|
||||
@ -457,12 +457,12 @@ mkdir sheetjs-jsc
|
||||
cd sheetjs-jsc
|
||||
```
|
||||
|
||||
2) Clone the WebKit repository and switch to the `WebKit-7620.2.4.111.7` tag:
|
||||
2) Clone the WebKit repository and switch to the `WebKit-7623.1.14.14.11` tag:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/WebKit/WebKit.git WebKit
|
||||
cd WebKit
|
||||
git checkout WebKit-7620.2.4.111.7
|
||||
git checkout WebKit-7623.1.14.14.11
|
||||
cd ..
|
||||
```
|
||||
|
||||
@ -473,19 +473,36 @@ cd ..
|
||||
|
||||
```bash
|
||||
cd WebKit
|
||||
env CFLAGS="-Wno-error=all -Wno-deprecated-declarations" CXXFLAGS="-Wno-error=all -Wno-deprecated-declarations" LDFLAGS="-framework Foundation" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error=all -DENABLE_STATIC_JSC=ON -DCMAKE_C_FLAGS=\"-Wno-error=all -Wno-deprecated-declarations\" -DCMAKE_CXX_FLAGS=\"-Wno-error=all -Wno-deprecated-declarations\"" --make-args="-Wno-error=all -Wno-deprecated-declarations"
|
||||
env CFLAGS="-Wno-error=all -Wno-deprecated-declarations" CXXFLAGS="-Wno-error=all -Wno-deprecated-declarations" LDFLAGS="-framework Foundation" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error=all -DENABLE_STATIC_JSC=ON -DCMAKE_C_FLAGS=\"-Wno-error=all -Wno-deprecated-declarations\" -DCMAKE_CXX_FLAGS=\"-Wno-error=all -Wno-deprecated-declarations\"" --make-args="-Wno-error=all -Wno-deprecated-declarations" --no-jit --no-webassembly
|
||||
cd ..
|
||||
```
|
||||
|
||||
:::note pass
|
||||
:::caution pass
|
||||
|
||||
In some test runs on ARM64 macOS, JIT elicited runtime errors and WebAssembly
|
||||
elicited compile-time errors. WebAssembly and JIT should be disabled:
|
||||
In some test runs, there were test compile errors:
|
||||
|
||||
```
|
||||
WebKit/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp:42:10: fatal error: 'wtf/darwin/DispatchExtras.h' file not found
|
||||
42 | #include <wtf/darwin/DispatchExtras.h>
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
1 error generated.
|
||||
```
|
||||
|
||||
The referenced file must be patched to assume `MACH_EXCEPTIONS` is not defined.
|
||||
There are a number of pre-processor directives:
|
||||
|
||||
```c
|
||||
#if HAVE(MACH_EXCEPTIONS)
|
||||
#include <wtf/darwin/DispatchExtras.h>
|
||||
#endif
|
||||
```
|
||||
|
||||
Each pre-processor block must be removed.
|
||||
|
||||
This can be automated with a simple Perl command:
|
||||
|
||||
```bash
|
||||
cd WebKit
|
||||
env CFLAGS="-Wno-error=all -Wno-deprecated-declarations" CXXFLAGS="-Wno-error=all -Wno-deprecated-declarations" LDFLAGS="-framework Foundation" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error=all -DENABLE_STATIC_JSC=ON -DCMAKE_C_FLAGS=\"-Wno-error=all -Wno-deprecated-declarations\" -DCMAKE_CXX_FLAGS=\"-Wno-error=all -Wno-deprecated-declarations\"" --make-args="-Wno-error=all -Wno-deprecated-declarations" --no-jit --no-webassembly
|
||||
cd ..
|
||||
perl -0777 -i -pe 's/#if HAVE\(MACH_EXCEPTIONS\).*?#endif\n*/\n/gs' "Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp"
|
||||
```
|
||||
|
||||
:::
|
||||
@ -545,7 +562,7 @@ The `#include` should be changed to a relative directive:
|
||||
|
||||
```bash
|
||||
cd WebKit
|
||||
env CFLAGS="-Wno-error=all -Wno-error=volatile-register-var -Wno-dangling-reference" CXXFLAGS="-Wno-error=all -Wno-error=volatile-register-var -Wno-dangling-reference" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error=all -Wno-error=volatile-register-var -DENABLE_STATIC_JSC=ON -DUSE_THIN_ARCHIVES=OFF -DCMAKE_C_FLAGS=\"-Wno-error=all -Wno-error=volatile-register-var -Wno-dangling-reference\" -DCMAKE_CXX_FLAGS=\"-Wno-error=all -Wno-error=volatile-register-var \"" --make-args="-j1 -Wno-error=all -Wno-error=volatile-register-var " -j1
|
||||
env CFLAGS="-Wno-error=all -Wno-error=volatile-register-var -Wno-dangling-reference" CXXFLAGS="-Wno-error=all -Wno-error=volatile-register-var -Wno-dangling-reference" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error=all -Wno-error=volatile-register-var -DENABLE_STATIC_JSC=ON -DUSE_THIN_ARCHIVES=OFF" --make-args="-j1 -Wno-error=all -Wno-error=volatile-register-var" -j1 --no-jit --no-webassembly
|
||||
cd ..
|
||||
```
|
||||
|
||||
@ -585,17 +602,10 @@ The error can be suppressed with preprocessor directives around the definition:
|
||||
T* prev() const { return static_cast<T*>(PtrTraits::unwrap(m_prev)); }
|
||||
```
|
||||
|
||||
After patching the header, JSC must be built without WebAssembly or JIT support:
|
||||
|
||||
```bash
|
||||
cd WebKit
|
||||
env CFLAGS="-Wno-error=all -Wno-error=volatile-register-var -Wno-dangling-reference" CXXFLAGS="-Wno-error=all -Wno-error=volatile-register-var -Wno-dangling-reference" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error=all -Wno-error=volatile-register-var -DENABLE_STATIC_JSC=ON -DUSE_THIN_ARCHIVES=OFF -DCMAKE_C_FLAGS=\"-Wno-error=all -Wno-error=volatile-register-var -Wno-dangling-reference\" -DCMAKE_CXX_FLAGS=\"-Wno-error=all -Wno-error=volatile-register-var \"" --make-args="-j1 -Wno-error=all -Wno-error=volatile-register-var " -j1 --no-jit --no-webassembly
|
||||
cd ..
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
:::note pass
|
||||
|
||||
In some test runs, there was a register error:
|
||||
|
||||
@ -884,7 +894,7 @@ pub struct JSString {
|
||||
_marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
|
||||
}
|
||||
// highlight-next-line
|
||||
type JSStringRef = *mut JSContext;
|
||||
type JSStringRef = *mut JSString;
|
||||
```
|
||||
|
||||
**Function Declaration**
|
||||
@ -898,9 +908,10 @@ JSStringRef JSStringCreateWithUTF8CString(const char * string);
|
||||
The equivalent Rust declaration must be defined in an `extern "C"` block:
|
||||
|
||||
```rust title="JSStringCreateWithUTF8CString Rust declaration"
|
||||
use libc::c_char;
|
||||
unsafe extern "C" {
|
||||
// JSStringRef JSStringCreateWithUTF8CString(const char * string);
|
||||
pub unsafe fn JSStringCreateWithUTF8CString(string: *const u8) -> JSStringRef;
|
||||
pub unsafe fn JSStringCreateWithUTF8CString(string: *const c_char) -> JSStringRef;
|
||||
}
|
||||
```
|
||||
|
||||
@ -940,8 +951,10 @@ The demo makes a safe wrapper to perform the unsafe waltz in one line:
|
||||
pub struct JSC;
|
||||
impl JSC {
|
||||
pub fn JSStringCreateWithUTF8CString(str: &str) -> JSStringRef { unsafe {
|
||||
// highlight-next-line
|
||||
JSStringCreateWithUTF8CString(std::ffi::CString::new(str.as_bytes()).unwrap().as_ptr() as *const u8)
|
||||
// highlight-start
|
||||
let cstr = std::ffi::CString::new(str).unwrap();
|
||||
JSStringCreateWithUTF8CString(cstr.as_ptr())
|
||||
// highlight-end
|
||||
} }
|
||||
}
|
||||
```
|
||||
@ -954,11 +967,24 @@ This demo was last tested in the following deployments:
|
||||
|
||||
| Architecture | Date |
|
||||
|:-------------|:-----------|
|
||||
| `darwin-x64` | 2025-03-31 |
|
||||
| `darwin-arm` | 2025-03-30 |
|
||||
| `darwin-x64` | 2026-03-04 |
|
||||
| `darwin-arm` | 2026-03-04 |
|
||||
| `linux-x64` | 2026-03-04 |
|
||||
| `linux-arm` | 2026-03-04 |
|
||||
|
||||
:::
|
||||
|
||||
<Tabs groupId="triple">
|
||||
<TabItem value="darwin-x64" label="MacOS">
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="linux-x64" label="Linux">
|
||||
|
||||
0) Follow the entire ["C" demo](#c). The library will be used in Rust.
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
1) Create a new project:
|
||||
|
||||
```bash
|
||||
@ -999,7 +1025,13 @@ curl -L -o src/main.rs https://docs.sheetjs.com/jsc/main.rs
|
||||
curl -LO https://docs.sheetjs.com/jsc/build.rs
|
||||
```
|
||||
|
||||
6) Build and run the app:
|
||||
6) Install the `libc` crate:
|
||||
|
||||
```bash
|
||||
cargo add libc
|
||||
```
|
||||
|
||||
7) Build and run the app:
|
||||
|
||||
```bash
|
||||
cargo run pres.numbers
|
||||
|
||||
@ -163,12 +163,12 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | Jint | Date |
|
||||
|:-------------|:--------|:-----------|
|
||||
| `darwin-x64` | `4.2.1` | 2025-03-31 |
|
||||
| `darwin-arm` | `4.2.0` | 2025-02-13 |
|
||||
| `win11-x64` | `4.1.0` | 2024-12-20 |
|
||||
| `darwin-x64` | `4.5.0` | 2026-01-21 |
|
||||
| `darwin-arm` | `4.5.0` | 2026-01-23 |
|
||||
| `win11-x64` | `4.2.2` | 2026-04-28 |
|
||||
| `win11-arm` | `4.2.0` | 2025-02-23 |
|
||||
| `linux-x64` | `4.1.0` | 2025-01-09 |
|
||||
| `linux-arm` | `4.2.0` | 2025-02-15 |
|
||||
| `linux-x64` | `4.2.2` | 2025-06-16 |
|
||||
| `linux-arm` | `4.5.0` | 2026-03-07 |
|
||||
|
||||
:::
|
||||
|
||||
@ -248,7 +248,7 @@ dotnet run
|
||||
|
||||
```bash
|
||||
dotnet nuget add source https://www.myget.org/F/jint/api/v3/index.json
|
||||
dotnet add package Jint --version 4.2.1
|
||||
dotnet add package Jint --version 4.5.0
|
||||
```
|
||||
|
||||
To verify Jint is installed, replace `Program.cs` with the following:
|
||||
@ -283,6 +283,25 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
|
||||
curl -LO https://docs.sheetjs.com/pres.xlsx`}
|
||||
</CodeBlock>
|
||||
|
||||
:::caution pass
|
||||
|
||||
PowerShell `curl` is incompatible with the official `curl` program. The command
|
||||
may fail with a parameter error:
|
||||
|
||||
```
|
||||
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
|
||||
```
|
||||
|
||||
`curl.exe` must be used instead:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js
|
||||
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
|
||||
curl.exe -LO https://docs.sheetjs.com/pres.xlsx`}
|
||||
</CodeBlock>
|
||||
|
||||
:::
|
||||
|
||||
6) Replace `Program.cs` with the following:
|
||||
|
||||
```csharp title="Program.cs"
|
||||
@ -499,7 +518,7 @@ cp bin/Release/net*/linux-arm64/publish/SheetJSJint .
|
||||
For Windows 11 x64, the RID is `win-x64` and the command is:
|
||||
|
||||
```powershell
|
||||
copy .\bin\Release\net9.0\win-x64\publish\SheetJSJint.exe .
|
||||
copy .\bin\Release\net*\win-x64\publish\SheetJSJint.exe .
|
||||
```
|
||||
|
||||
:::caution pass
|
||||
@ -513,7 +532,7 @@ The system cannot find the path specified.
|
||||
The correct command was
|
||||
|
||||
```powershell
|
||||
copy .\bin\x64\Release\net9.0\win-x64\publish\SheetJSJint.exe .
|
||||
copy .\bin\x64\Release\net*\win-x64\publish\SheetJSJint.exe .
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user