diff --git a/docz/docs/03-demos/06-desktop/09-cli.md b/docz/docs/03-demos/06-desktop/09-cli.md
index b982f2c..8db5c89 100644
--- a/docz/docs/03-demos/06-desktop/09-cli.md
+++ b/docz/docs/03-demos/06-desktop/09-cli.md
@@ -44,7 +44,7 @@ This demo was tested in the following deployments:
|:-------------|:--------|:------------|:-----------|
| `darwin-x64` | `5.8.1` | `18.5.0` | 2023-05-08 |
| `darwin-arm` | `5.8.1` | `18.5.0` | 2023-09-25 |
-| `win10-x64` | `5.8.1` | `18.5.0` | 2023-05-08 |
+| `win10-x64` | `5.8.1` | `18.5.0` | 2023-10-09 |
| `win11-arm` | `5.8.1` | `18.5.0` | 2023-09-25 |
| `linux-x64` | `5.8.1` | `18.5.0` | 2023-05-08 |
| `linux-arm` | `5.8.1` | `18.5.0` | 2023-09-25 |
@@ -55,7 +55,7 @@ This demo was tested in the following deployments:
|:-------------|:-------------|:------------|:-----------|
| `darwin-x64` | `4.0.0-rc.2` | `14.15.3` | 2023-05-08 |
| `darwin-arm` | `4.0.0-rc.2` | `20.7.0` | 2023-09-25 |
-| `win10-x64` | `4.0.0-rc.2` | `14.15.3` | 2023-05-08 |
+| `win10-x64` | `4.0.0-rc.2` | `14.15.3` | 2023-10-09 |
| `win11-arm` | `4.0.0-rc.2` | `18.17.1` | 2023-09-25 |
| `linux-x64` | `4.0.0-rc.2` | `14.15.3` | 2023-05-08 |
| `linux-arm` | `4.0.0-rc.2` | `20.7.0` | 2023-09-25 |
@@ -66,7 +66,7 @@ This demo was tested in the following deployments:
|:-------------|:--------|:------------|:-----------|
| `darwin-x64` | `2.0.1` | `20.1.0` | 2023-05-08 |
| `darwin-arm` | `2.1.1` | `20.7.0` | 2023-09-25 |
-| `win10-x64` | `2.1.1` | `16.20.2` | 2023-08-27 |
+| `win10-x64` | `2.1.2` | `16.20.2` | 2023-10-09 |
| `linux-x64` | `2.0.1` | `20.1.0` | 2023-05-08 |
| `linux-arm` | `2.1.1` | `20.7.0` | 2023-09-25 |
@@ -161,7 +161,7 @@ npx boxednode@2.1.1 -s xlsx-cli.js -t xlsx-cli
+. plugin call cleanfile, "pres.numbers" verbose{'\n'}
+Worksheet 0 Name: Sheet1{'\n'}
+Name,Index{'\n'}
+Bill Clinton,42{'\n'}
+GeorgeW Bush,43{'\n'}
+Barack Obama,44{'\n'}
+Donald Trump,45{'\n'}
+Joseph Biden,46{'\n'}
+{'\n'}
+Saved to `sheetjs.tmp.xlsx`{'\n'}
+import excel "sheetjs.tmp.xlsx", firstrow will read the first sheet and use headers{'\n'}
+for more help, see import excel
+
+
+17) Close the plugin:
+
+```stata
+program drop cleanfile
+```
+
+18) Clear the current session:
+
+```stata
+clear
+```
+
+19) In the result of Step 16, click the link on import
+excel "sheetjs.tmp.xlsx", firstrow
+. import excel "sheetjs.tmp.xlsx", firstrow{'\n'}
+(2 vars, 5 obs)
+
+
+20) Open the Data Editor (in Browse or Edit mode) and compare to the screenshot:
+
+
+
+[^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)
+[^3]: See [`write` in "Writing Files"](/docs/api/write-options)
\ No newline at end of file
diff --git a/docz/docs/03-demos/37-bigdata/02-worker.md b/docz/docs/03-demos/37-bigdata/02-worker.md
index 25b808e..d9fdef9 100644
--- a/docz/docs/03-demos/37-bigdata/02-worker.md
+++ b/docz/docs/03-demos/37-bigdata/02-worker.md
@@ -194,7 +194,7 @@ Each browser demo was tested in the following environments:
| Edge 116 | 2023-09-02 | |
| Safari 16.6 | 2023-09-02 | File System Access API is not supported |
| Brave 1.57 | 2023-09-02 | File System Access API is not supported |
-| Firefox 113 | 2023-05-22 | File System Access API is not supported |
+| Firefox 118 | 2023-10-09 | File System Access API is not supported |
:::
diff --git a/docz/docs/03-demos/42-engines/02-v8.md b/docz/docs/03-demos/42-engines/02-v8.md
index 1260798..682557f 100644
--- a/docz/docs/03-demos/42-engines/02-v8.md
+++ b/docz/docs/03-demos/42-engines/02-v8.md
@@ -787,7 +787,7 @@ This demo was last tested in the following deployments:
|:-------------|:---------|:-----------|
| `darwin-x64` | `0.75.1` | 2023-08-26 |
| `darwin-arm` | `0.73.0` | 2023-06-05 |
-| `win10-x64` | `0.71.2` | 2023-05-23 |
+| `win10-x64` | `0.79.2` | 2023-10-09 |
| `linux-x64` | `0.71.2` | 2023-05-23 |
| `linux-arm` | `0.75.1` | 2023-08-30 |
diff --git a/docz/docs/03-demos/42-engines/08-quickjs.md b/docz/docs/03-demos/42-engines/08-quickjs.md
index 439dc5e..8cbc6f3 100644
--- a/docz/docs/03-demos/42-engines/08-quickjs.md
+++ b/docz/docs/03-demos/42-engines/08-quickjs.md
@@ -264,7 +264,7 @@ This demo was tested in the following deployments:
|:-------------|:-----------|:-----------|
| `darwin-x64` | `2788d71` | 2023-07-24 |
| `darwin-arm` | `2788d71` | 2023-06-05 |
-| `win10-x64` | `2788d71` | 2023-07-24 |
+| `win10-x64` | `2788d71` | 2023-10-09 |
| `win11-arm` | `2788d71` | 2023-09-25 |
| `linux-x64` | `2788d71` | 2023-06-02 |
| `linux-arm` | `2788d71` | 2023-08-29 |
diff --git a/docz/docs/03-demos/index.md b/docz/docs/03-demos/index.md
index 7925768..af80d75 100644
--- a/docz/docs/03-demos/index.md
+++ b/docz/docs/03-demos/index.md
@@ -82,6 +82,10 @@ in the [issue tracker](https://git.sheetjs.com/sheetjs/docs.sheetjs.com/issues)
- [`Chrome and Chromium Extensions`](/docs/demos/extensions/chromium)
- [`Google Sheets + Apps Script`](/docs/demos/extensions/gsheet)
- [`AppleScript and OSA`](/docs/demos/extensions/osa)
+- [`Mathematica`](/docs/demos/extensions/mathematica)
+- [`MATLAB`](/docs/demos/extensions/matlab)
+- [`Stata`](/docs/demos/extensions/stata)
+- [`Maple`](/docs/demos/extensions/maple)
### Cloud Platforms
diff --git a/docz/docs/09-miscellany/02-errors.md b/docz/docs/09-miscellany/02-errors.md
index c0d2cf2..f6c6141 100644
--- a/docz/docs/09-miscellany/02-errors.md
+++ b/docz/docs/09-miscellany/02-errors.md
@@ -443,6 +443,16 @@ function add_to_sheet(sheet, cell) {
+#### Some decimal values are rounded
+
+Excel appears to round values in certain cases. It is suspected that the XLSX
+parser handles 15 decimal digits of precision. This results in inaccuracies such
+as `7581185.559999999` rounding to `7581185.56` and `7581185.5599999903`
+rounding to `7581185.55999999`.
+
+See [Issue 3003](https://git.sheetjs.com/sheetjs/sheetjs/issues/3003) in the
+main SheetJS CE repo for details.
+
#### Corrupt files
Third-party build tools and frameworks may post-process SheetJS scripts. The
diff --git a/docz/static/cli/Cargo.toml b/docz/static/cli/Cargo.toml
index 4a269ed..b7649ff 100644
--- a/docz/static/cli/Cargo.toml
+++ b/docz/static/cli/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
-v8 = "0.75.1"
+v8 = "0.79.2"
[[bin]]
name = "sheet2csv"
diff --git a/docz/static/stata/cleanfile.c b/docz/static/stata/cleanfile.c
new file mode 100644
index 0000000..517c97c
--- /dev/null
+++ b/docz/static/stata/cleanfile.c
@@ -0,0 +1,131 @@
+#include "stplugin.h"
+#include "duktape.h"
+
+#define DOIT(cmd) duk_eval_string_noresult(ctx, cmd);
+
+#define FAIL_DUK(cmd) { \
+ const char *errmsg = duk_safe_to_string(ctx, -1); \
+ duk_destroy_heap(ctx); \
+ snprintf(failbuf, 255, "error in %s: %s", cmd, errmsg); \
+ SF_error(failbuf); \
+ return NULL; \
+}
+
+#define FAIL_LOAD { \
+ duk_push_undefined(ctx); \
+ SF_error("Error in load_file"); \
+ return 1; \
+}
+
+static char *read_file(const char *filename, size_t *sz) {
+ FILE *f = fopen(filename, "rb");
+ if(!f) return NULL;
+ long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f); fseek(f, 0, SEEK_SET); }
+ char *buf = (char *)malloc(fsize * sizeof(char));
+ *sz = fread((void *) buf, 1, fsize, f);
+ fclose(f);
+ return buf;
+}
+
+static duk_int_t eval_file(duk_context *ctx, const char *filename) {
+ size_t len; char *buf = read_file(filename, &len);
+ if(!buf) FAIL_LOAD
+
+ duk_push_lstring(ctx, (const char *)buf, (duk_size_t)len);
+ duk_int_t retval = duk_peval(ctx);
+ duk_pop(ctx);
+ return retval;
+}
+
+static duk_int_t load_file(duk_context *ctx, const char *filename, const char *var) {
+ size_t len; char *buf = read_file(filename, &len);
+ if(!buf) FAIL_LOAD
+
+ duk_push_external_buffer(ctx);
+ duk_config_buffer(ctx, -1, buf, len);
+ duk_put_global_string(ctx, var);
+ return 0;
+}
+
+static duk_int_t save_file(duk_context *ctx, const char *filename, const char *var) {
+ duk_get_global_string(ctx, var);
+ duk_size_t sz;
+ char *buf = (char *)duk_get_buffer_data(ctx, -1, &sz);
+
+ if(!buf) return 1;
+ FILE *f = fopen(filename, "wb"); fwrite(buf, 1, sz, f); fclose(f);
+ return 0;
+}
+
+STDLL stata_call(int argc, char *argv[])
+{
+ duk_int_t res = 0;
+ char failbuf[255];
+
+ /* initialize duktape */
+ duk_context *ctx = duk_create_heap_default();
+ /* duktape does not expose a standard "global" by default */
+ DOIT("var global = (function(){ return this; }).call(null);")
+
+ /* load SheetJS library */
+ res = eval_file(ctx, "shim.min.js");
+ if(res != 0) FAIL_DUK("shim load")
+ res = eval_file(ctx, "xlsx.full.min.js");
+ if(res != 0) FAIL_DUK("library load")
+
+ /* print SheetJS version number */
+ //duk_eval_string(ctx, "XLSX.version");
+ //char verbuf[255];
+ //snprintf(verbuf, 255, "SheetJS library version: %s\n", duk_get_string(ctx, -1));
+ //SF_display(verbuf);
+
+ /* read file */
+ res = load_file(ctx, argv[0], "buf");
+ if(res != 0) FAIL_DUK("file load")
+
+ /* parse workbook */
+ DOIT("wb = XLSX.read(buf.slice(0, buf.length), {type:'buffer'});");
+
+ /* print CSV */
+ duk_eval_string(ctx, "wb.SheetNames.length");
+ duk_uint_t wscnt = duk_get_uint(ctx, -1);
+ duk_pop(ctx);
+
+ /* if argument 2 is "verbose", print CSV contents */
+ if(argc>1 && !strncmp(argv[1], "verbose", 7)) for(uint32_t wsidx = 0; wsidx < wscnt; ++wsidx) {
+ /* select n-th worksheet */
+ char wsbuf[80];
+ snprintf(wsbuf, 80, "ws = wb.Sheets[wsname = wb.SheetNames[%d]]", wsidx); \
+ DOIT(wsbuf);
+
+ duk_eval_string(ctx, "wsname");
+ char namebuf[60];
+ snprintf(namebuf, 60, "Worksheet %d Name: %s\n", wsidx, duk_get_string(ctx, -1));
+ duk_pop(ctx);
+ SF_display(namebuf);
+
+ /* convert to CSV */
+ duk_eval_string(ctx, "XLSX.utils.sheet_to_csv(ws)");
+ const char *csv = duk_get_string(ctx, -1);
+
+ /* print each row in a separate line */
+ char *tok = strtok(csv, "\n");
+ while(tok != NULL) {
+ SF_display(tok);
+ SF_display("\n");
+ tok = strtok(NULL, "\n");
+ }
+ duk_pop(ctx);
+ }
+
+ /* write to sheetjs.tmp.xlsx */
+ DOIT("newbuf = (XLSX.write(wb, {type:'array', bookType:'xlsx'}));");\
+ res = save_file(ctx, "sheetjs.tmp.xlsx", "newbuf");\
+ if(res != 0) FAIL_DUK("save sheetjsw.xlsx")
+
+ SF_display("\n");
+ SF_display("Saved to `sheetjs.tmp.xlsx`\n");
+ SF_display("{stata import excel \"sheetjs.tmp.xlsx\", firstrow} will read the first sheet and use headers\n");
+ SF_display("for more help, see {help import excel}\n");
+ return(0) ;
+}
diff --git a/docz/static/stata/commands.png b/docz/static/stata/commands.png
new file mode 100644
index 0000000..311ce41
Binary files /dev/null and b/docz/static/stata/commands.png differ
diff --git a/docz/static/stata/data-editor.png b/docz/static/stata/data-editor.png
new file mode 100644
index 0000000..454bf7e
Binary files /dev/null and b/docz/static/stata/data-editor.png differ