diff --git a/.spelling b/.spelling index 8945f34..57fe27a 100644 --- a/.spelling +++ b/.spelling @@ -120,6 +120,7 @@ ActiveX Airtable AlaSQL AngularJS +AppleScript ArrayBuffer Auth BOM @@ -203,6 +204,7 @@ MVC MVVM MacOS MariaDB +Mathematica Meridiem MongoDB MySQL @@ -220,6 +222,7 @@ Northwind Nunjucks Nuxt NuxtJS +OSA PPI PhantomJS PhoneGap @@ -307,6 +310,7 @@ embeddable encodings esbuild filesystem +frontmatter globals iOS iWork diff --git a/docz/docs/03-demos/01-frontend/02-vue.md b/docz/docs/03-demos/01-frontend/02-vue.md index 1a5366b..7b1e40c 100644 --- a/docz/docs/03-demos/01-frontend/02-vue.md +++ b/docz/docs/03-demos/01-frontend/02-vue.md @@ -15,7 +15,7 @@ Other demos cover general VueJS deployments, including: - [Static Site Generation powered by NuxtJS](/docs/demos/static/nuxtjs) - [iOS and Android applications powered by Quasar](/docs/demos/mobile/quasar) - [Desktop application powered by Tauri](/docs/demos/desktop/tauri) -- [`vue3-table-lite` UI component](/docs/demos/grid#vue3-table-lite) +- [`vue3-table-lite` UI component](/docs/demos/grid/vtl) ## Installation @@ -232,8 +232,8 @@ generate column headings and for indexing into the row objects. The safest approach is to use an array of arrays for state and to generate column objects that map to A1-Style column headers. -The [`vue3-table-lite` demo](/docs/demos/grid#rows-and-columns-bindings) generates rows -and columns objects with the following structure: +The [`vue3-table-lite` demo](/docs/demos/grid/vtl#rows-and-columns-bindings) +generates rows and columns objects with the following structure: ```js /* rows are generated with a simple array of arrays */ diff --git a/docz/docs/03-demos/02-grid/12-vtl.md b/docz/docs/03-demos/02-grid/12-vtl.md new file mode 100644 index 0000000..351e7ee --- /dev/null +++ b/docz/docs/03-demos/02-grid/12-vtl.md @@ -0,0 +1,124 @@ +--- +title: vue3-table-lite +pagination_prev: demos/frontend/index +pagination_next: demos/net/index +--- + +:::note + +This demo was tested against `vue3-table-lite 1.2.4`, VueJS `3.2.47`, ViteJS +4.3.1, and `@vitejs/plugin-vue` 4.1.0 on 2023 April 24 + +::: + + +The demo creates a site that looks like the screenshot below: + +![vue3-table-lite screenshot](pathname:///vtl/vtl1.png) + +## Integration Details + +#### Rows and Columns Bindings + +`vue3-table-lite` presents two attribute bindings: an array of column metadata +(`columns`) and an array of objects representing the displayed data (`rows`). +Typically both are `ref` objects: + + +```html + + + +``` + +These can be mutated through the `value` property in VueJS lifecycle methods: + +```ts +import { onMounted } from "vue"; +onMounted(() => { + columns.value = [ { field: "name", label: "Names" }]; + rows.value = [ { name: "SheetJS" }, { name: "VueJS" } ]; +}) +``` + +The most generic data representation is an array of arrays. To sate the grid, +columns must be objects whose `field` property is the index converted to string: + +```js +import { ref } from "vue"; +import { utils } from 'xlsx'; + +/* generate row and column data */ +function ws_to_vtl(ws) { + /* create an array of arrays */ + const rows = utils.sheet_to_json(ws, { header: 1 }); + + /* create column array */ + const range = utils.decode_range(ws["!ref"]||"A1"); + const columns = Array.from({ length: range.e.c + 1 }, (_, i) => ({ + field: String(i), // vtl will access row["0"], row["1"], etc + label: utils.encode_col(i), // the column labels will be A, B, etc + })); + + return { rows, columns }; +} + +const rows = ref([]); +const columns = ref([]); + +/* update refs */ +function update_refs(ws) { + const data = ws_to_vtl(ws); + rows.value = data.rows; + columns.value = data.columns; +} +``` + +In the other direction, a worksheet can be generated with `aoa_to_sheet`: + +```js +import { utils } from 'xlsx'; + +const rows = ref([]); + +function vtl_to_ws(rows) { + return utils.aoa_to_sheet(rows.value); +} +``` + +## Demo + +1) Create a new ViteJS App using the VueJS + TypeScript template: + +```bash +npm create vite@latest sheetjs-vtl -- --template vue-ts +cd sheetjs-vtl +``` + +2) Install dependencies: + +```bash +npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz vue3-table-lite@1.2.4 +``` + +3) Download [`src/App.vue`](pathname:///vtl/App.vue) and replace the contents: + +```bash +curl -L -o src/App.vue https://docs.sheetjs.com/vtl/App.vue +``` + +4) run `npm run dev`. When you load the page in the browser, it will try to + fetch and load the data. diff --git a/docz/docs/03-demos/02-grid/index.md b/docz/docs/03-demos/02-grid/index.md index 124ab4c..67ddfa7 100644 --- a/docz/docs/03-demos/02-grid/index.md +++ b/docz/docs/03-demos/02-grid/index.md @@ -217,122 +217,7 @@ npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz @mui/x-data-grid @e -:::note - -This demo was tested against `vue3-table-lite 1.2.4`, VueJS `3.2.37`, ViteJS -3.0.7, and `@vitejs/plugin-vue` 3.0.3 on 2022 August 18 - -::: - -#### VueJS Demo - -
Complete Example (click to show) - -1) Create a new ViteJS App using the VueJS + TypeScript template: - -```bash -npm create vite@latest sheetjs-vue -- --template vue-ts -cd sheetjs-vue -``` - -2) Install dependencies: - -```bash -npm i -npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz vue3-table-lite -``` - -3) Download [`src/App.vue`](pathname:///vtl/App.vue) and replace the contents: - -```bash -curl -L -o src/App.vue https://docs.sheetjs.com/vtl/App.vue -``` - -4) run `npm run dev`. When you load the page in the browser, it will try to - fetch and load the data. - -
- -#### Rows and Columns Bindings - -`vue3-table-lite` presents two attribute bindings: an array of column metadata -(`columns`) and an array of objects representing the displayed data (`rows`). -Typically both are `ref` objects: - - -```html - - - -``` - -These can be mutated through the `value` property in VueJS lifecycle methods: - -```ts -import { onMounted } from "vue"; -onMounted(() => { - columns.value = [ { field: "name", label: "Names" }]; - rows.value = [ { name: "SheetJS" }, { name: "VueJS" } ]; -}) -``` - -The most generic data representation is an array of arrays. To sate the grid, -columns must be objects whose `field` property is the index converted to string: - -```js -import { ref } from "vue"; -import { utils } from 'xlsx'; - -/* generate row and column data */ -function ws_to_vte(ws) { - /* create an array of arrays */ - const rows = utils.sheet_to_json(ws, { header: 1 }); - - /* create column array */ - const range = utils.decode_range(ws["!ref"]||"A1"); - const columns = Array.from({ length: range.e.c + 1 }, (_, i) => ({ - field: String(i), // VTE will access row["0"], row["1"], etc - label: utils.encode_col(i), // the column labels will be A, B, etc - })); - - return { rows, columns }; -} - -const rows = ref([]); -const columns = ref([]); - -/* update refs */ -function update_refs(ws) { - const data = ws_to_vte(ws); - rows.value = data.rows; - columns.value = data.columns; -} -``` - -In the other direction, a worksheet can be generated with `aoa_to_sheet`: - -```js -import { utils } from 'xlsx'; - -const rows = ref([]); - -function vte_to_ws(rows) { - return utils.aoa_to_sheet(rows.value); -} -``` +**[The exposition has been moved to a separate page.](/docs/demos/grid/vtl)** ## Standard HTML Tables diff --git a/docz/docs/03-demos/04-static/10-astro.md b/docz/docs/03-demos/04-static/10-astro.md index 891dca1..040a770 100644 --- a/docz/docs/03-demos/04-static/10-astro.md +++ b/docz/docs/03-demos/04-static/10-astro.md @@ -248,28 +248,4 @@ npx http-server dist Open a web browser and access the displayed URL (usually http://localhost:8080). View the page source and confirm that no JS was added to the page. It only -contains the content from the file in an HTML table: - -```html - - - -

Presidents

- - - - - - - - - - - - - - - -
NameIndex
Bill Clinton42
GeorgeW Bush43
Barack Obama44
Donald Trump45
Joseph Biden46
- -``` \ No newline at end of file +contains the content from the file in an HTML table. diff --git a/docz/docs/03-demos/05-mobile/01-reactnative.md b/docz/docs/03-demos/05-mobile/01-reactnative.md index eb4aa04..e64267f 100644 --- a/docz/docs/03-demos/05-mobile/01-reactnative.md +++ b/docz/docs/03-demos/05-mobile/01-reactnative.md @@ -28,6 +28,148 @@ The "Complete Example" creates an app that looks like the screenshots below: +["Fetching Remote Data"](#fetching-remote-data) uses the built-in `fetch` to +download and parse remote workbook files. + +["Native Libraries"](#native-libraries) uses native libraries to read and write +files in the local device. + +:::caution + +**Before reading this demo, follow the official React Native CLI Guide!** + +Development Environment Guide: + +Follow the instructions for iOS (requires macOS) and for Android. They will +cover installation and system configuration. You should be able to build and run +a sample app in the Android and the iOS (if applicable) simulators. + +::: + +## Fetching Remote Data + +:::info + +React Native `0.72.0` will support binary data with `fetch`. For older versions, +[a native library](#native-libraries) can provide support. + +::: + + +React Native 0.72.0 will support binary data with `fetch`: + +```js +/* fetch data into an ArrayBuffer */ +const ab = await (await fetch("https://sheetjs.com/pres.numbers")).arrayBuffer(); +/* parse data */ +const wb = XLSX.read(ab); +``` + +### Fetch Demo + +The following demo uses `react-native-table-component` to display the first +worksheet in a simple table. + +:::note + +This demo was tested on an Intel Mac on 2023 April 24 with RN `0.72.0-rc.1`. + +The iOS simulator runs iOS 16.2 on an iPhone SE (3rd generation). + +::: + +1) Create project: + +```bash +npx react-native init SheetJSRNFetch --version="0.72.0-rc.1" +``` + +2) Install shared dependencies: + +```bash +cd SheetJSRNFetch +curl -LO https://oss.sheetjs.com/assets/img/logo.png +npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz +npm i -S react-native-table-component@1.2.0 @types/react-native-table-component +``` + +Refresh iOS project by running `pod install` from the `ios` subfolder: + +```bash +cd ios; pod install; cd .. +``` + +3) Download [`App.tsx`](pathname:///reactnative/App.tsx) and replace: + +```bash +curl -LO https://docs.sheetjs.com/reactnative/App.tsx +``` + +**iOS Testing** + +Start the iOS emulator: + +```bash +npx react-native run-ios +``` + +When opened, the app should look like the "Before" screenshot below. After +tapping "Import data from a spreadsheet", the app should show new data: + + + + +
BeforeAfter
+ +![before screenshot](pathname:///reactnative/iosfetch1.png) + + + +![after screenshot](pathname:///reactnative/iosfetch2.png) + +
+ +**Android Testing** + +Start the Android emulator: + +```bash +npx react-native run-android +``` + +:::note + +When this demo was last tested, the simulator failed with the message + +> Unable to load script. Make sure you're either Running Metro ... + +The workaround is to launch Metro directly: + +```bash +npx react-native start +``` + +Press `a` in the terminal window and Metro will try to reload the app. + +::: + + +When opened, the app should look like the "Before" screenshot below. After +tapping "Import data from a spreadsheet", the app should show new data: + + + + +
BeforeAfter
+ +![before screenshot](pathname:///reactnative/andfetch1.png) + + + +![after screenshot](pathname:///reactnative/andfetch2.png) + +
+ ## Native Libraries @@ -312,17 +454,9 @@ are not covered here. This example tries to separate the library-specific functions. -0) **Follow the official React Native CLI Guide!** - -Development Environment Guide: - -Follow the instructions for iOS and for Android. They will cover installation -and system configuration. By the end, you should be able to run the sample app -in the Android and the iOS simulators. - 1) Create project: -``` +```bash npx react-native init SheetJSRN --version="0.67.2" ``` @@ -332,7 +466,7 @@ npx react-native init SheetJSRN --version="0.67.2" cd SheetJSRN curl -LO https://oss.sheetjs.com/assets/img/logo.png npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz -npm i -S react-native-table-component react-native-document-picker +npm i -S react-native-table-component@1.2.0 react-native-document-picker ``` Refresh iOS project by running `pod install` from the `ios` subfolder: diff --git a/docz/docs/03-demos/index.md b/docz/docs/03-demos/index.md index 08219ca..00ccea6 100644 --- a/docz/docs/03-demos/index.md +++ b/docz/docs/03-demos/index.md @@ -36,7 +36,7 @@ run in the web browser, demos will include interactive examples. - [`x-spreadsheet`](/docs/demos/grid/xs) - [`react-data-grid`](/docs/demos/grid/rdg) - [`glide-data-grid`](/docs/demos/grid/gdg) -- [`vue3-table-lite`](/docs/demos/grid#vue3-table-lite) +- [`vue3-table-lite`](/docs/demos/grid/vtl) - [`angular-ui-grid`](/docs/demos/grid#angular-ui-grid) - [`material ui`](/docs/demos/grid#material-ui-table) diff --git a/docz/docs/06-solutions/05-output.md b/docz/docs/06-solutions/05-output.md index 60c1824..158e840 100644 --- a/docz/docs/06-solutions/05-output.md +++ b/docz/docs/06-solutions/05-output.md @@ -644,7 +644,7 @@ export default function App() { -[`vue3-table-lite`](/docs/demos/grid#vue3-table-lite) is a VueJS 3 data table. +[`vue3-table-lite`](/docs/demos/grid/vtl) is a VueJS 3 data table. diff --git a/docz/docs/07-csf/07-features/03-dates.md b/docz/docs/07-csf/07-features/03-dates.md index 9da3943..5b4cbe7 100644 --- a/docz/docs/07-csf/07-features/03-dates.md +++ b/docz/docs/07-csf/07-features/03-dates.md @@ -162,11 +162,11 @@ The default behavior for all parsers is to generate number cells. Passing the `cellDates` to true will force the parsers to store dates: ```js -// cell A1 will be { t: 'n', v: 44721 } -var wb_sans_date = XLSX.read("6/9/2022", {type:"binary"}); +// cell A1 will be { t: 'n', v: 54337 } +var wb_sans_date = XLSX.read("10/6/2048", {type:"binary"}); -// cell A1 will be { t: 'd', v: } -var wb_with_date = XLSX.read("6/9/2022", {type:"binary", cellDates: true}); +// cell A1 will be { t: 'd', v: } +var wb_with_date = XLSX.read("10/6/2048", {type:"binary", cellDates: true}); ``` When writing, date cells are automatically translated back to numeric cells diff --git a/docz/docs/09-miscellany/05-contributing.md b/docz/docs/09-miscellany/05-contributing.md index 422fc68..bb30018 100644 --- a/docz/docs/09-miscellany/05-contributing.md +++ b/docz/docs/09-miscellany/05-contributing.md @@ -262,28 +262,28 @@ git checkout -- . ### Reproduce official builds 4) Run `git log` and search for the commit that matches a particular release -version. For example, version `0.19.1` can be found with: +version. For example, version `0.19.3` can be found with: ```bash -git log | grep -B4 "version bump 0.19.1" +git log | grep -B4 "version bump 0.19.3" ``` The output should look like: ```bash -$ git log | grep -B4 "version bump 0.19.1" +$ git log | grep -B4 "version bump 0.19.3" # highlight-next-line -commit 51a861900092bfc01b2fa9960d4c932dcbeb6925 <-- this is the commit hash +commit 333e4e40f9c5603bd22a811f54c61c20bc9e17ab <-- this is the commit hash Author: SheetJS -Date: Thu Nov 17 04:35:34 2022 -0500 +Date: Mon Apr 17 23:39:28 2023 -0400 - version bump 0.19.1 + version bump 0.19.3 ``` 5) Switch to that commit: ```bash -git checkout 51a861900092bfc01b2fa9960d4c932dcbeb6925 +git checkout 333e4e40f9c5603bd22a811f54c61c20bc9e17ab ``` 6) Run the full build sequence @@ -301,14 +301,14 @@ The local checksum for the browser script can be computed with: ```bash $ md5sum dist/xlsx.full.min.js -00b46a9f2d30ddc69780ab8049d6809e dist/xlsx.full.min.js +f5c73b5ddc4b431c909d11c2e1d7a8e0 dist/xlsx.full.min.js ``` The checksum for the CDN version can be computed with: ```bash -$ curl -L https://cdn.sheetjs.com/xlsx-0.19.1/package/dist/xlsx.full.min.js | md5sum - -00b46a9f2d30ddc69780ab8049d6809e - +$ curl -L https://cdn.sheetjs.com/xlsx-0.19.3/package/dist/xlsx.full.min.js | md5sum - +f5c73b5ddc4b431c909d11c2e1d7a8e0 - ``` The two hashes should match. diff --git a/docz/static/reactnative/App.tsx b/docz/static/reactnative/App.tsx new file mode 100644 index 0000000..0ca7a25 --- /dev/null +++ b/docz/static/reactnative/App.tsx @@ -0,0 +1,73 @@ +/* sheetjs (C) SheetJS -- https://sheetjs.com */ + +import React, { useState, useCallback } from 'react'; +import { StyleSheet, Text, Button, Alert, Image, ScrollView } from 'react-native'; +import { Table, Row, Rows, TableWrapper } from 'react-native-table-component'; +import { read, utils, WorkSheet } from 'xlsx'; + +const make_width = (ws: WorkSheet): number[] => { + const aoa = utils.sheet_to_json(ws, {header:1}), res: number[] = []; + aoa.forEach((r) => { r.forEach((c, C) => { res[C] = Math.max(res[C]||60, String(c).length * 10); }); }); + for(let C = 0; C < res.length; ++C) if(!res[C]) res[C] = 60; + return res; +}; + +function App(): JSX.Element { + const [data, setData] = useState([ + "SheetJS".split(""), + [5,4,3,3,7,9,5], + [8,6,7,5,3,0,9] + ]); + const [widths, setWidths] = useState(Array.from({length:7}, () => 20)); + + const importFile = useCallback(async() => { + try { + const ab = await (await fetch("https://sheetjs.com/pres.numbers")).arrayBuffer(); + const wb = read(ab); + + /* convert first worksheet to AOA */ + const wsname = wb.SheetNames[0]; + const ws = wb.Sheets[wsname]; + const data = utils.sheet_to_json(ws, {header:1}); + /* update state */ + setData(data); + setWidths(make_width(ws)); + } catch(err) { + Alert.alert("importFile Error", "Error " + ((err as any).message || err)); + } + }, []); + + return ( + + +   SheetJS × React Native +