forked from sheetjs/docs.sheetjs.com
		
	quick
This commit is contained in:
		
							parent
							
								
									3e30d569c2
								
							
						
					
					
						commit
						01d7333f44
					
				| @ -55,19 +55,19 @@ For existing projects, the easiest approach is to uninstall and reinstall: | ||||
|   <TabItem value="npm" label="npm"> | ||||
| <pre><code parentName="pre" {...{"className": "language-bash"}}>{`\ | ||||
| npm rm --save xlsx | ||||
| npm i --save file:vendor/xlsx-${current}.tgz`} | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | ||||
| </code></pre> | ||||
|   </TabItem> | ||||
|   <TabItem value="pnpm" label="pnpm"> | ||||
| <pre><code parentName="pre" {...{"className": "language-bash"}}>{`\ | ||||
| pnpm rm xlsx | ||||
| pnpm install file:vendor/xlsx-${current}.tgz`} | ||||
| pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | ||||
| </code></pre> | ||||
|   </TabItem> | ||||
|   <TabItem value="yarn" label="Yarn" default> | ||||
| <pre><code parentName="pre" {...{"className": "language-bash"}}>{`\ | ||||
| yarn remove xlsx | ||||
| yarn add file:vendor/xlsx-${current}.tgz`} | ||||
| yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | ||||
| </code></pre> | ||||
|   </TabItem> | ||||
| </Tabs> | ||||
|  | ||||
| @ -114,6 +114,39 @@ function exportFile() { | ||||
| </main> | ||||
| ``` | ||||
| 
 | ||||
| <details open><summary><b>How to run the example</b> (click to show)</summary> | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| This demo was last run on 2023 March 08 using `svelte@3.55.1`.  When running | ||||
| `npm create`, the package `create-vite@4.1.0` was installed. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| 1) Run `npm create vite@latest sheetjs-svelte -- --template svelte-ts`. | ||||
| 
 | ||||
| 2) Install the SheetJS dependency and start the dev server: | ||||
| 
 | ||||
| ```bash | ||||
| cd sheetjs-svelte | ||||
| npm install | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz | ||||
| npm run dev | ||||
| ``` | ||||
| 
 | ||||
| 3) Open a web browser and access the displayed URL (`http://localhost:5173`) | ||||
| 
 | ||||
| 4) Replace `src/App.svelte` with the `src/SheetJSSvelteAoO.svelte` example. | ||||
| 
 | ||||
| The page will refresh and show a table with an Export button.  Click the button | ||||
| and the page will attempt to download `SheetJSSvelteAoA.xlsx`. There may be a | ||||
| delay since Vite will try to optimize the SheetJS library on the fly. | ||||
| 
 | ||||
| 5) Build the site with `npm run build`, then test with `npx http-server dist`. | ||||
| Access `http://localhost:8080` with a web browser to test the bundled site. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ### HTML | ||||
| 
 | ||||
| The main disadvantage of the Array of Objects approach is the specific nature | ||||
| @ -158,3 +191,36 @@ function exportFile() { | ||||
|   <!-- highlight-end --> | ||||
| </main> | ||||
| ``` | ||||
| 
 | ||||
| <details open><summary><b>How to run the example</b> (click to show)</summary> | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| This demo was last run on 2023 March 08 using `svelte@3.55.1`.  When running | ||||
| `npm create`, the package `create-vite@4.1.0` was installed. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| 1) Run `npm create vite@latest sheetjs-svelte -- --template svelte-ts`. | ||||
| 
 | ||||
| 2) Install the SheetJS dependency and start the dev server: | ||||
| 
 | ||||
| ```bash | ||||
| cd sheetjs-svelte | ||||
| npm install | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz | ||||
| npm run dev | ||||
| ``` | ||||
| 
 | ||||
| 3) Open a web browser and access the displayed URL (`http://localhost:5173`) | ||||
| 
 | ||||
| 4) Replace `src/App.svelte` with the `src/SheetJSSvelteHTML.svelte` example. | ||||
| 
 | ||||
| The page will refresh and show a table with an Export button.  Click the button | ||||
| and the page will attempt to download `SheetJSSvelteHTML.xlsx`. There may be a | ||||
| delay since Vite will try to optimize the SheetJS library on the fly. | ||||
| 
 | ||||
| 5) Build the site with `npm run build`, then test with `npx http-server dist`. | ||||
| Access `http://localhost:8080` with a web browser to test the bundled site. | ||||
| 
 | ||||
| </details> | ||||
|  | ||||
| @ -29,7 +29,7 @@ features like scrolling may not work as expected. | ||||
| function SheetJSXSpread() { | ||||
|   const [url, setUrl] = React.useState("https://sheetjs.com/pres.numbers"); | ||||
|   const [done, setDone] = React.useState(false); | ||||
|   const ref = React.useRef(); | ||||
|   const ref = React.useRef(); // ref to DIV container | ||||
|   const set_url = React.useCallback((evt) => setUrl(evt.target.value)); | ||||
| 
 | ||||
|   return ( <> | ||||
| @ -43,7 +43,7 @@ function SheetJSXSpread() { | ||||
|         x_spreadsheet(ref.current).loadData(stox(wb)); | ||||
|         setDone(true); | ||||
|       }}><b>Fetch!</b></button> | ||||
|     </>)} | ||||
|     </> )} | ||||
|   </> ); | ||||
| } | ||||
| ``` | ||||
|  | ||||
							
								
								
									
										137
									
								
								docz/docs/03-demos/02-grid/02-cdg.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										137
									
								
								docz/docs/03-demos/02-grid/02-cdg.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,137 @@ | ||||
| --- | ||||
| title: Canvas Datagrid | ||||
| pagination_prev: demos/frontend/index | ||||
| pagination_next: demos/net/index | ||||
| --- | ||||
| 
 | ||||
| <head> | ||||
|   <script src="https://unpkg.com/canvas-datagrid/dist/canvas-datagrid.js"></script> | ||||
| </head> | ||||
| 
 | ||||
| After extensive testing, `canvas-datagrid` stood out as a high-performance grid | ||||
| with a straightforward API. | ||||
| 
 | ||||
| [Click here for a live standalone integration demo.](pathname:///cdg/) | ||||
| 
 | ||||
| ## Live Demo | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| Due to CSS conflicts between the data grid and the documentation generator, | ||||
| features like scrolling may not work as expected. | ||||
| 
 | ||||
| [The linked demo uses a simple HTML page.](pathname:///cdg/) | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| ```jsx live | ||||
| function SheetJSCDG() { | ||||
|   const [url, setUrl] = React.useState("https://sheetjs.com/pres.numbers"); | ||||
|   const [done, setDone] = React.useState(false); | ||||
|   const ref = React.useRef(); // ref to DIV container | ||||
|   const set_url = React.useCallback((evt) => setUrl(evt.target.value)); | ||||
|   const [cdg, setCdg] = React.useState(null); // reference to grid object | ||||
| 
 | ||||
|   return ( <> | ||||
|     <div height={300} width={300} ref={ref}/> | ||||
|     {!done && ( <> | ||||
|       <b>URL: </b><input type="text" value={url} onChange={set_url} size="50"/> | ||||
|       <br/><button onClick={async() => { | ||||
|         /* fetch and parse workbook */ | ||||
|         const wb = XLSX.read(await (await fetch(url)).arrayBuffer()); | ||||
|         const ws = wb.Sheets[wb.SheetNames[0]]; | ||||
|         const data = XLSX.utils.sheet_to_json(ws, { header:1 }); | ||||
| 
 | ||||
|         /* set up grid and load data */ | ||||
|         if(!cdg) setCdg(canvasDatagrid({ parentNode: ref.current, data })); | ||||
|         else cdg.data = data; | ||||
|         setDone(true); | ||||
|       }}><b>Fetch!</b></button> | ||||
|     </> )} | ||||
|   </> ); | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ## Integration Details | ||||
| 
 | ||||
| #### Obtaining the Library | ||||
| 
 | ||||
| The `canvas-datagrid` NodeJS packages include a minified script that can be | ||||
| directly inserted as a script tag.  The unpkg CDN also serves this script: | ||||
| 
 | ||||
| ```html | ||||
| <script src="https://unpkg.com/canvas-datagrid/dist/canvas-datagrid.js"></script> | ||||
| ``` | ||||
| 
 | ||||
| #### Previewing Data | ||||
| 
 | ||||
| The HTML document needs a container element: | ||||
| 
 | ||||
| ```html | ||||
| <div id="gridctr"></div> | ||||
| ``` | ||||
| 
 | ||||
| Grid initialization is a one-liner: | ||||
| 
 | ||||
| ```js | ||||
| var grid = canvasDatagrid({ | ||||
|   parentNode: document.getElementById('gridctr'), | ||||
|   data: [] | ||||
| }); | ||||
| ``` | ||||
| 
 | ||||
| For large data sets, it's necessary to constrain the size of the grid. | ||||
| 
 | ||||
| ```js | ||||
| grid.style.height = '100%'; | ||||
| grid.style.width = '100%'; | ||||
| ``` | ||||
| 
 | ||||
| Once the workbook is read and the worksheet is selected, assigning the data | ||||
| variable automatically updates the view: | ||||
| 
 | ||||
| ```js | ||||
| grid.data = XLSX.utils.sheet_to_json(ws, {header:1}); | ||||
| ``` | ||||
| 
 | ||||
| This demo previews the first worksheet. | ||||
| 
 | ||||
| #### Editing | ||||
| 
 | ||||
| `canvas-datagrid` handles the entire edit cycle.  No intervention is necessary. | ||||
| 
 | ||||
| #### Saving Data | ||||
| 
 | ||||
| `grid.data` is immediately readable and can be converted back to a worksheet. | ||||
| Some versions return an array-like object without the length, so a little bit of | ||||
| preparation may be needed: | ||||
| 
 | ||||
| ```js | ||||
| /* converts an array of array-like objects into an array of arrays */ | ||||
| function prep(arr) { | ||||
|   var out = []; | ||||
|   for(var i = 0; i < arr.length; ++i) { | ||||
|     if(!arr[i]) continue; | ||||
|     if(Array.isArray(arr[i])) { out[i] = arr[i]; continue }; | ||||
|     var o = new Array(); | ||||
|     Object.keys(arr[i]).forEach(function(k) { o[+k] = arr[i][k] }); | ||||
|     out[i] = o; | ||||
|   } | ||||
|   return out; | ||||
| } | ||||
| 
 | ||||
| /* build worksheet from the grid data */ | ||||
| var ws = XLSX.utils.aoa_to_sheet(prep(grid.data)); | ||||
| 
 | ||||
| /* build up workbook */ | ||||
| var wb = XLSX.utils.book_new(); | ||||
| XLSX.utils.book_append_sheet(wb, ws, 'SheetJS'); | ||||
| 
 | ||||
| /* generate download */ | ||||
| XLSX.writeFile(wb, "SheetJS.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| #### Additional Features | ||||
| 
 | ||||
| This demo barely scratches the surface.  The underlying grid component includes | ||||
| many additional features that work with [SheetJS Pro](https://sheetjs.com/pro). | ||||
| @ -34,101 +34,16 @@ With a familiar UI, `x-spreadsheet` is an excellent choice for a modern editor. | ||||
| 
 | ||||
| [Click here for a live integration demo.](pathname:///xspreadsheet/) | ||||
| 
 | ||||
| [The exposition has been moved to a separate page.](/docs/demos/grid/xs) | ||||
| **[The exposition has been moved to a separate page.](/docs/demos/grid/xs)** | ||||
| 
 | ||||
| ### Canvas DataGrid | ||||
| ### Canvas Datagrid | ||||
| 
 | ||||
| After extensive testing, [`canvas-datagrid`](https://canvas-datagrid.js.org/demo.html) | ||||
| stood out as a very high-performance grid with an incredibly simple API. | ||||
| After extensive testing, `canvas-datagrid` stood out as a high-performance grid | ||||
| with a straightforward API. | ||||
| 
 | ||||
| [Click here for a live integration demo.](pathname:///cdg/index.html) | ||||
| 
 | ||||
| <details><summary><b>Full Exposition</b> (click to show)</summary> | ||||
| 
 | ||||
| **Obtaining the Library** | ||||
| 
 | ||||
| The `canvas-datagrid` NodeJS packages include a minified script that can be | ||||
| directly inserted as a script tag.  The unpkg CDN also serves this script: | ||||
| 
 | ||||
| ```html | ||||
| <script src="https://unpkg.com/canvas-datagrid/dist/canvas-datagrid.js"></script> | ||||
| ``` | ||||
| 
 | ||||
| **Previewing Data** | ||||
| 
 | ||||
| The HTML document needs a container element: | ||||
| 
 | ||||
| ```html | ||||
| <div id="gridctr"></div> | ||||
| ``` | ||||
| 
 | ||||
| Grid initialization is a one-liner: | ||||
| 
 | ||||
| ```js | ||||
| var grid = canvasDatagrid({ | ||||
|   parentNode: document.getElementById('gridctr'), | ||||
|   data: [] | ||||
| }); | ||||
| ``` | ||||
| 
 | ||||
| For large data sets, it's necessary to constrain the size of the grid. | ||||
| 
 | ||||
| ```js | ||||
| grid.style.height = '100%'; | ||||
| grid.style.width = '100%'; | ||||
| ``` | ||||
| 
 | ||||
| Once the workbook is read and the worksheet is selected, assigning the data | ||||
| variable automatically updates the view: | ||||
| 
 | ||||
| ```js | ||||
| grid.data = XLSX.utils.sheet_to_json(ws, {header:1}); | ||||
| ``` | ||||
| 
 | ||||
| This demo previews the first worksheet. | ||||
| 
 | ||||
| **Editing** | ||||
| 
 | ||||
| `canvas-datagrid` handles the entire edit cycle.  No intervention is necessary. | ||||
| 
 | ||||
| **Saving Data** | ||||
| 
 | ||||
| `grid.data` is immediately readable and can be converted back to a worksheet. | ||||
| Some versions return an array-like object without the length, so a little bit of | ||||
| preparation may be needed: | ||||
| 
 | ||||
| ```js | ||||
| /* converts an array of array-like objects into an array of arrays */ | ||||
| function prep(arr) { | ||||
|   var out = []; | ||||
|   for(var i = 0; i < arr.length; ++i) { | ||||
|     if(!arr[i]) continue; | ||||
|     if(Array.isArray(arr[i])) { out[i] = arr[i]; continue }; | ||||
|     var o = new Array(); | ||||
|     Object.keys(arr[i]).forEach(function(k) { o[+k] = arr[i][k] }); | ||||
|     out[i] = o; | ||||
|   } | ||||
|   return out; | ||||
| } | ||||
| 
 | ||||
| /* build worksheet from the grid data */ | ||||
| var ws = XLSX.utils.aoa_to_sheet(prep(grid.data)); | ||||
| 
 | ||||
| /* build up workbook */ | ||||
| var wb = XLSX.utils.book_new(); | ||||
| XLSX.utils.book_append_sheet(wb, ws, 'SheetJS'); | ||||
| 
 | ||||
| /* generate download */ | ||||
| XLSX.writeFile(wb, "SheetJS.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| **Additional Features** | ||||
| 
 | ||||
| This demo barely scratches the surface.  The underlying grid component includes | ||||
| many additional features including massive data streaming, sorting and styling. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| **[The exposition has been moved to a separate page.](/docs/demos/grid/cdg)** | ||||
| 
 | ||||
| ### Tabulator | ||||
| 
 | ||||
|  | ||||
| @ -13,6 +13,15 @@ work as-is in WebSQL. | ||||
| 
 | ||||
| The public demo <https://sheetjs.com/sql> generates a database from workbook. | ||||
| 
 | ||||
| :::caution | ||||
| 
 | ||||
| WebSQL is only supported in Chromium-based browsers including Chrome. | ||||
| 
 | ||||
| Safari historically supported WebSQL but Safari 13 dropped support.  Legacy | ||||
| browsers including Internet Explorer and Firefox never added support. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| ## WebSQL Details | ||||
| 
 | ||||
| Importing data from spreadsheets is straightforward using the `generate_sql` | ||||
|  | ||||
							
								
								
									
										211
									
								
								docz/docs/03-demos/12-engines/08_quickjs.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										211
									
								
								docz/docs/03-demos/12-engines/08_quickjs.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,211 @@ | ||||
| --- | ||||
| title: C + QuickJS | ||||
| pagination_prev: demos/bigdata/index | ||||
| pagination_next: solutions/input | ||||
| --- | ||||
| 
 | ||||
| QuickJS is an embeddable JS engine written in C.  It provides a separate set of | ||||
| functions for interacting with the filesystem and the global object.  It can run | ||||
| the standalone browser scripts. | ||||
| 
 | ||||
| ## Integration Details | ||||
| 
 | ||||
| _Initialize QuickJS_ | ||||
| 
 | ||||
| QuickJS provides a `global` object through `JS_GetGlobalObject`: | ||||
| 
 | ||||
| ```c | ||||
| /* initialize */ | ||||
| JSRuntime *rt = JS_NewRuntime(); | ||||
| JSContext *ctx = JS_NewContext(rt); | ||||
| 
 | ||||
| /* obtain reference to global object */ | ||||
| JSValue global = JS_GetGlobalObject(ctx); | ||||
| 
 | ||||
| /* DO WORK HERE */ | ||||
| 
 | ||||
| /* free after use */ | ||||
| JS_FreeValue(ctx, global); | ||||
| 
 | ||||
| /* cleanup */ | ||||
| JS_FreeContext(ctx); | ||||
| JS_FreeRuntime(rt); | ||||
| ``` | ||||
| 
 | ||||
| :::warning | ||||
| 
 | ||||
| All values must be freed with `JS_FreeValue` before calling `JS_FreeContext`! | ||||
| 
 | ||||
| `JS_IsException` should be used for validation. | ||||
| 
 | ||||
| Cleanup and validation code is omitted from the discussion.  The integration | ||||
| example shows structured validation and controlled memory usage. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| _Load SheetJS Scripts_ | ||||
| 
 | ||||
| The main library can be loaded by reading the script from the file system and | ||||
| evaluating in the QuickJS context: | ||||
| 
 | ||||
| ```c | ||||
| 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); fsee  (f, 0, SEEK_SET); } | ||||
|   char *buf = (char *)malloc(fsize * sizeof(char)); | ||||
|   *sz = fread((void *) buf, 1, fsize, f); | ||||
|   fclose(f); | ||||
|   return buf; | ||||
| } | ||||
| 
 | ||||
| // ... | ||||
|   /* load library */ | ||||
|   { | ||||
|     size_t len; char *buf = read_file("xlsx.full.min.js", &len); | ||||
|     JS_Eval(ctx, buf, len, "<input>", 0); | ||||
|     free(buf); | ||||
|   } | ||||
| ``` | ||||
| 
 | ||||
| To confirm the library is loaded, `XLSX.version` can be inspected: | ||||
| 
 | ||||
| ```c | ||||
| /* obtain reference to the XLSX object */ | ||||
| JSValue XLSX = JS_GetPropertyStr(ctx, global, "XLSX"); | ||||
| 
 | ||||
| /* print version */ | ||||
| JSValue version = JS_GetPropertyStr(ctx, XLSX, "version"); | ||||
| size_t vlen; const char *vers = JS_ToCStringLen(ctx, &vlen, version); | ||||
| printf("Version: %s\n", vers); | ||||
| ``` | ||||
| 
 | ||||
| ### Reading Files | ||||
| 
 | ||||
| `JS_NewArrayBuffer` can generate an `ArrayBuffer` from a C byte array. The | ||||
| function signature expects `uint8_t *` instead of `char *`: | ||||
| 
 | ||||
| ```c | ||||
| /* read file */ | ||||
| size_t dlen; uint8_t * dbuf = (uint8_t *)read_file("pres.numbers", &dlen); | ||||
| 
 | ||||
| /* load data into array buffer */ | ||||
| JSValue ab = JS_NewArrayBuffer(ctx, dbuf, dlen, NULL, NULL, 0); | ||||
| 
 | ||||
| /* obtain reference to the XLSX object */ | ||||
| JSValue XLSX = JS_GetPropertyStr(ctx, global, "XLSX"); | ||||
| 
 | ||||
| /* call XLSX.read(ab) */ | ||||
| JSValue XLSX_read = JS_GetPropertyStr(ctx, XLSX, "read"); | ||||
| JSValue args[] = { ab }; | ||||
| JSValue wb = JS_Call(ctx, XLSX_read, XLSX, 1, args); | ||||
| ``` | ||||
| 
 | ||||
| ## Complete Example | ||||
| 
 | ||||
| The "Integration Example" covers a traditional integration in a C application, | ||||
| while the "CLI Test" demonstrates other concepts using the `quickjs` CLI tool. | ||||
| 
 | ||||
| ### Integration Example | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| This demo was last tested on 2023 March 11 against QuickJS commit `2788d71` on | ||||
| a Intel Mac. `gcc -v` printed: | ||||
| 
 | ||||
| ``` | ||||
| Apple clang version 14.0.0 (clang-1400.0.29.202) | ||||
| Target: x86_64-apple-darwin21.6.0 | ||||
| ``` | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| 0) Build `libquickjs.a`: | ||||
| 
 | ||||
| ```bash | ||||
| git clone --depth=1 https://github.com/bellard/quickjs | ||||
| cd quickjs | ||||
| git checkout 2788d71 | ||||
| make | ||||
| cd .. | ||||
| ``` | ||||
| 
 | ||||
| 1) Copy `libquickjs.a` and `quickjs.h` into the working directory: | ||||
| 
 | ||||
| ```bash | ||||
| cp quickjs/libquickjs.a . | ||||
| cp quickjs/quickjs.h . | ||||
| ``` | ||||
| 
 | ||||
| 2) Download [`sheetjs.quick.c`](pathname:///quickjs/sheetjs.quick.c): | ||||
| 
 | ||||
| ```bash | ||||
| curl -LO https://docs.sheetjs.com/quickjs/sheetjs.quick.c | ||||
| ``` | ||||
| 
 | ||||
| 3) Build the sample application: | ||||
| 
 | ||||
| ```bash | ||||
| gcc -o sheetjs.quick -Wall -lm libquickjs.a sheetjs.quick.c | ||||
| ``` | ||||
| 
 | ||||
| This program tries to parse the file specified by the first argument | ||||
| 
 | ||||
| 4) Download the standalone script and test file: | ||||
| 
 | ||||
| <ul> | ||||
| <li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li> | ||||
| <li><a href="https://sheetjs.com/pres.numbers">pres.numbers</a></li> | ||||
| </ul> | ||||
| 
 | ||||
| ```bash | ||||
| curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js | ||||
| curl -LO https://sheetjs.com/pres.numbers | ||||
| ``` | ||||
| 
 | ||||
| 5) Run the test program: | ||||
| 
 | ||||
| ``` | ||||
| ./sheetjs.quick pres.numbers | ||||
| ``` | ||||
| 
 | ||||
| If successful, the program will print the library version number, file size, | ||||
| first worksheet name, and the contents of the first sheet as CSV rows. | ||||
| 
 | ||||
| 
 | ||||
| ### CLI Test | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| This demo was last tested on 2023 March 11 against QuickJS `2021-03-27`. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| 0) Ensure `quickjs` command line utility is installed | ||||
| 
 | ||||
| 1) Download the standalone script and the test file: | ||||
| 
 | ||||
| <ul> | ||||
| <li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li> | ||||
| <li><a href="https://sheetjs.com/pres.numbers">pres.numbers</a></li> | ||||
| </ul> | ||||
| 
 | ||||
| ```bash | ||||
| curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js | ||||
| curl -LO https://sheetjs.com/pres.numbers | ||||
| ``` | ||||
| 
 | ||||
| 2) Download [`SheetJSQuick.js`](pathname:///quickjs/SheetJSQuick.js) | ||||
| 
 | ||||
| ```bash | ||||
| curl -LO https://docs.sheetjs.com/quickjs/SheetJSQuick.js | ||||
| ``` | ||||
| 
 | ||||
| 3) Test the program: | ||||
| 
 | ||||
| ```bash | ||||
| quickjs SheetJSQuick.js | ||||
| ``` | ||||
| 
 | ||||
| If successful, the script will generate `SheetJSQuick.xlsx`. | ||||
| 
 | ||||
| @ -246,57 +246,7 @@ QuickJS is an embeddable JS engine written in C.  It provides a separate set of | ||||
| functions for interacting with the filesystem and the global object.  It can run | ||||
| the standalone browser scripts. | ||||
| 
 | ||||
| <details><summary><b>Complete Example</b> (click to show)</summary> | ||||
| 
 | ||||
| 0) Ensure `quickjs` command line utility is installed | ||||
| 
 | ||||
| 1) Download the standalone script, the shim and the test file: | ||||
| 
 | ||||
| <ul> | ||||
| <li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li> | ||||
| <li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js`}>shim.min.js</a></li> | ||||
| <li><a href="https://sheetjs.com/pres.numbers">pres.numbers</a></li> | ||||
| </ul> | ||||
| 
 | ||||
| 2) Save the following script to `SheetJSQuick.js`: | ||||
| 
 | ||||
| ```js title="SheetJSQuick.js" | ||||
| /* sheetjs (C) 2013-present  SheetJS -- https://sheetjs.com */ | ||||
| /* load XLSX */ | ||||
| import * as std from "std"; | ||||
| globalThis.global = globalThis; | ||||
| std.loadScript("xlsx.full.min.js"); | ||||
| 
 | ||||
| /* read contents of file */ | ||||
| var rh = std.open("pres.numbers", "rb"); | ||||
| rh.seek(0, std.SEEK_END); | ||||
| var sz = rh.tell(); | ||||
| var ab = new ArrayBuffer(sz); | ||||
| rh.seek(); | ||||
| rh.read(ab, 0, sz); | ||||
| rh.close(); | ||||
| 
 | ||||
| /* parse file */ | ||||
| var wb = XLSX.read(ab); | ||||
| 
 | ||||
| /* write XLSX */ | ||||
| var out = XLSX.write(wb, {bookType: "xlsx", type: "array"}); | ||||
| 
 | ||||
| /* write contents to file */ | ||||
| var wh = std.open("SheetJSQuick.xlsx", "wb"); | ||||
| wh.write(out, 0, out.byteLength); | ||||
| wh.close(); | ||||
| ``` | ||||
| 
 | ||||
| 3) Test the program: | ||||
| 
 | ||||
| ```bash | ||||
| quickjs SheetJSQuick.js | ||||
| ``` | ||||
| 
 | ||||
| If successful, the script will generate `SheetJSQuick.xlsx`. | ||||
| 
 | ||||
| </details> | ||||
| This demo has been moved [to a dedicated page](/docs/demos/engines/quickjs). | ||||
| 
 | ||||
| 
 | ||||
| ### Rhino | ||||
|  | ||||
| @ -32,7 +32,7 @@ run in the web browser, demos will include interactive examples. | ||||
| 
 | ||||
| ### Front-End UI Components | ||||
| 
 | ||||
| - [`canvas-datagrid`](/docs/demos/grid#canvas-datagrid) | ||||
| - [`canvas-datagrid`](/docs/demos/grid/cdg) | ||||
| - [`x-spreadsheet`](/docs/demos/grid/xs) | ||||
| - [`react-data-grid`](/docs/demos/grid#react-data-grid) | ||||
| - [`glide-data-grid`](/docs/demos/grid#glide-data-grid) | ||||
|  | ||||
| @ -737,9 +737,8 @@ function Tabeller(props) { | ||||
|   /* fetch and update the workbook with an effect */ | ||||
|   React.useEffect(() => { (async() => { | ||||
|     /* fetch and parse workbook -- see the fetch example for details */ | ||||
|     const wb = XLSX.read(await (await fetch("sheetjs.xlsx")).arrayBuffer()); | ||||
|     setWorkbook(wb); | ||||
|   })(); }); | ||||
|     setWorkbook(XLSX.read(await (await fetch("sheetjs.xlsx")).arrayBuffer())); | ||||
|   })(); }, []); | ||||
| 
 | ||||
|   return workbook.SheetNames.map(name => ( <> | ||||
|     <h3>name</h3> | ||||
|  | ||||
							
								
								
									
										25
									
								
								docz/static/quickjs/SheetJSQuick.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										25
									
								
								docz/static/quickjs/SheetJSQuick.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| /* sheetjs (C) 2013-present  SheetJS -- https://sheetjs.com */ | ||||
| /* load XLSX */ | ||||
| import * as std from "std"; | ||||
| globalThis.global = globalThis; | ||||
| std.loadScript("xlsx.full.min.js"); | ||||
| 
 | ||||
| /* read contents of file */ | ||||
| var rh = std.open("pres.numbers", "rb"); | ||||
| rh.seek(0, std.SEEK_END); | ||||
| var sz = rh.tell(); | ||||
| var ab = new ArrayBuffer(sz); | ||||
| rh.seek(); | ||||
| rh.read(ab, 0, sz); | ||||
| rh.close(); | ||||
| 
 | ||||
| /* parse file */ | ||||
| var wb = XLSX.read(ab); | ||||
| 
 | ||||
| /* write XLSX */ | ||||
| var out = XLSX.write(wb, {bookType: "xlsx", type: "array"}); | ||||
| 
 | ||||
| /* write contents to file */ | ||||
| var wh = std.open("SheetJSQuick.xlsx", "wb"); | ||||
| wh.write(out, 0, out.byteLength); | ||||
| wh.close(); | ||||
							
								
								
									
										120
									
								
								docz/static/quickjs/sheetjs.quick.c
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										120
									
								
								docz/static/quickjs/sheetjs.quick.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,120 @@ | ||||
| #include <stdio.h> | ||||
| #include <stddef.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include "quickjs.h" | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| #define CLEANUP(v) { JS_FreeContext(ctx); JS_FreeRuntime(rt); return v; } | ||||
| #define FREE(v) JS_FreeValue(ctx, v); | ||||
| #define VALIDATE(v) { if(JS_IsException(v)) CLEANUP(1) } | ||||
| #define VALINIT(xx,vv) \ | ||||
|   JSValue xx = vv;\ | ||||
| 	VALIDATE(xx) | ||||
| #define VALPROP(xx,vv,pp) VALINIT(xx, JS_GetPropertyStr(ctx, vv, pp)) | ||||
| 
 | ||||
| int main(int argc, char *argv[]) { | ||||
| 	JSRuntime *rt = JS_NewRuntime(); | ||||
| 	JSContext *ctx = JS_NewContext(rt); | ||||
| 
 | ||||
| 	/* load library */ | ||||
| 	{ | ||||
| 		size_t len; char * buf = read_file("xlsx.full.min.js", &len); | ||||
| 		VALIDATE(JS_Eval(ctx, buf, len, "<input>", 0)) | ||||
| 		free(buf); | ||||
| 	} | ||||
| 
 | ||||
| 	VALINIT(global, JS_GetGlobalObject(ctx)) | ||||
| 	VALPROP(XLSX, global, "XLSX"); | ||||
| 	FREE(global) | ||||
| 
 | ||||
| 	/* print version */ | ||||
| 	{ | ||||
| 		VALPROP(version, XLSX, "version") | ||||
| 		size_t vlen; const char *vers = JS_ToCStringLen(ctx, &vlen, version); | ||||
| 		printf("Version: %s\n", vers); | ||||
| 		FREE(version) | ||||
| 	} | ||||
| 
 | ||||
| 	/* parse workbook */ | ||||
| 	JSValue wb; | ||||
| 	{ | ||||
| 		/* read file */ | ||||
| 		size_t dlen; uint8_t * dbuf = (uint8_t *)read_file(argv[1], &dlen); | ||||
| 
 | ||||
| 		/* load data into array buffer */ | ||||
| 		JSValue ab = JS_NewArrayBuffer(ctx, dbuf, dlen, NULL, NULL, 0); | ||||
| 		{ | ||||
| 			VALPROP(byteLen, ab, "byteLength") | ||||
| 			uint32_t byteLength; JS_ToUint32(ctx, &byteLength, byteLen); | ||||
| 			FREE(byteLen) | ||||
| 			printf("Size: %d\n", byteLength); | ||||
| 		} | ||||
| 
 | ||||
| 		/* call XLSX.read(ab) */ | ||||
| 		{ | ||||
| 			VALPROP(XLSX_read, XLSX, "read"); | ||||
| 			JSValue args[] = { ab }; | ||||
| 			wb = JS_Call(ctx, XLSX_read, XLSX, 1, args); | ||||
| 			FREE(XLSX_read) | ||||
| 		} | ||||
| 
 | ||||
| 		/* cleanup */ | ||||
| 		FREE(ab) | ||||
| 		free(dbuf); | ||||
| 	} | ||||
| 
 | ||||
| 	/* print CSV of first worksheet */ | ||||
| 	{ | ||||
| 		/* get first worksheet */ | ||||
| 		JSValue ws; | ||||
| 		{ | ||||
| 			/* get name of first sheet */ | ||||
| 			const char *wsname; | ||||
| 			{ | ||||
| 				JSValue SheetNames = JS_GetPropertyStr(ctx, wb, "SheetNames"); | ||||
| 				JSValue Sheet1 = JS_GetPropertyStr(ctx, SheetNames, "0"); | ||||
| 				size_t wslen; wsname = JS_ToCStringLen(ctx, &wslen, Sheet1); | ||||
| 				FREE(Sheet1) | ||||
| 				FREE(SheetNames) | ||||
| 			} | ||||
| 			printf("Worksheet Name: %s\n", wsname); | ||||
| 
 | ||||
| 			/* get worksheet object */ | ||||
| 			{ | ||||
| 				VALPROP(Sheets, wb, "Sheets"); | ||||
| 				ws = JS_GetPropertyStr(ctx, Sheets, wsname); | ||||
| 				FREE(Sheets) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		/* print CSV */ | ||||
| 		{ | ||||
| 			VALPROP(utils, XLSX, "utils") | ||||
| 			VALPROP(sheet_to_csv, utils, "sheet_to_csv") | ||||
| 			JSValue args[] = { ws }; | ||||
| 			JSValue csv = JS_Call(ctx, sheet_to_csv, utils, 1, args); | ||||
| 			FREE(sheet_to_csv) | ||||
| 			FREE(utils) | ||||
| 			size_t csvlen; const char *csvstr = JS_ToCStringLen(ctx, &csvlen, csv); | ||||
| 			printf("%s\n", csvstr); | ||||
| 			FREE(csv) | ||||
| 		} | ||||
| 
 | ||||
| 		FREE(ws) | ||||
| 	} | ||||
| 
 | ||||
| 	FREE(wb) | ||||
| 	FREE(XLSX) | ||||
| 	CLEANUP(0) | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user