From 8f9512b2173fd4a88ba68932c46e3b96dacefc4a Mon Sep 17 00:00:00 2001 From: SheetJS Date: Sun, 19 Nov 2023 00:23:07 -0500 Subject: [PATCH] ng17 --- docz/docs/03-demos/01-frontend/03-angular.md | 425 ++++++++++++++++-- .../docs/03-demos/01-frontend/07-angularjs.md | 198 +++++--- docz/docs/03-demos/06-desktop/04-tauri.md | 82 ++-- docz/docs/03-demos/07-data/26-redis.md | 10 +- docz/docs/03-demos/09-cloud/02-netsuite.md | 2 +- docz/docs/03-demos/index.md | 2 +- docz/static/dta/dta.min.js | 2 +- 7 files changed, 587 insertions(+), 134 deletions(-) diff --git a/docz/docs/03-demos/01-frontend/03-angular.md b/docz/docs/03-demos/01-frontend/03-angular.md index da55c7d..ddf5d98 100644 --- a/docz/docs/03-demos/01-frontend/03-angular.md +++ b/docz/docs/03-demos/01-frontend/03-angular.md @@ -1,5 +1,7 @@ --- -title: Angular +title: Sheets in Angular Sites +sidebar_label: Angular +description: Build interactive websites with Angular. Seamlessly integrate spreadsheets into your app using SheetJS. Bring Excel-powered workflows and data to the modern web. pagination_prev: demos/index pagination_next: demos/grid/index sidebar_position: 3 @@ -10,18 +12,24 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; -Angular is a JS library for building user interfaces. +Angular is a JS library for building user interfaces.[^1] -This demo tries to cover common Angular data flow ideas and strategies. Angular -and TypeScript familiarity is assumed. +[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing +data from spreadsheets. -**SheetJS plays nice with each version of Angular**. +This demo uses Angular and SheetJS to process and generate spreadsheets. We'll +explore how to load SheetJS in Angular projects and compare common state models +and data flow strategies. -Other demos cover general Angular deployments, including: +:::note pass + +This demo focuses on Angular concepts. Other demos cover general deployments: - [iOS and Android applications powered by NativeScript](/docs/demos/mobile/nativescript) - [iOS and Android applications powered by Ionic](/docs/demos/mobile/ionic) +::: + :::caution pass Angular tooling uses native NodeJS modules. There are a number of issues when @@ -61,31 +69,33 @@ import { read, utils, writeFile } from 'xlsx'; The various SheetJS APIs work with various data shapes. The preferred state depends on the application. +:::warning pass + +Angular 17 broke backwards compatibility with projects using Angular 2 - 16. + +**Despite the Angular turmoil, SheetJS plays nice with each version of Angular**. + +When relevant, code snippets for Angular 17 and Angular 2 - 16 are included. The +"Angular 2-16" and "Angular 17+" tabs change the displayed code blocks + +::: + ### 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. For example, our -[presidents sheet](https://sheetjs.com/pres.xlsx) has "Name" / "Index" columns: +loaded into the site. This sheet will have known columns. + +#### State + +The example [presidents sheet](https://sheetjs.com/pres.xlsx) has one header row +with "Name" and "Index" columns. The natural JS representation is an object for +each row, using the values in the first rows as keys: + +
SpreadsheetState
![`pres.xlsx` data](pathname:///pres.png) -This naturally maps to an array of typed objects, as in the TS example below: - -```ts -import { read, utils } from 'xlsx'; - -interface President { - Name: string; - Index: number; -} - -const f = await (await fetch("https://sheetjs.com/pres.xlsx")).arrayBuffer(); -const wb = read(f); -const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]); -console.log(data); -``` - -`data` will be an array of objects: + ```js [ @@ -97,8 +107,199 @@ console.log(data); ] ``` -A component will typically loop over the data using `*ngFor`. The following -example generates a TABLE with a row for each President: +
+ +This data is typically stored as an array of objects in the component class: + +```ts +import { Component } from '@angular/core'; + +@Component({ /* ... component configuration options ... */ }) +export class AppComponent { + /* the component state is an array of objects */ + // highlight-next-line + rows: any[] = [ { Name: "SheetJS", Index: 0 }]; +} +``` + +When the spreadsheet header row is known ahead of time, row typing is possible: + +```ts +import { Component } from '@angular/core'; + +interface President { + Name: string; + Index: number; +} + +@Component({ /* ... component configuration options ... */ }) +export class AppComponent { + /* the component state is an array of presidents */ + // highlight-next-line + rows: President[] = [ { Name: "SheetJS", Index: 0 }]; +} +``` + +:::caution pass + +The types are informative. They do not enforce that worksheets include the named +columns. A runtime data validation library should be used to verify the dataset. + +When the file header is not known in advance, `any` should be used. + +::: + +#### Updating State + +The SheetJS [`read`](/docs/api/parse-options) and [`sheet_to_json`](/docs/api/utilities/array#array-output) +functions simplify state updates. They are best used in the function bodies of +`ngOnInit`[^2] and event handlers. + +A `ngOnInit` method can download and update state when a person loads the site: + +```mermaid +flowchart LR + url[(Remote\nFile)] + ab[(Data\nArrayBuffer)] + wb(SheetJS\nWorkbook) + ws(SheetJS\nWorksheet) + aoo(array of\nobjects) + state((component\nstate)) + url --> |fetch\n\n| ab + ab --> |read\n\n| wb + wb --> |wb.Sheets\nselect sheet| ws + ws --> |sheet_to_json\n\n| aoo + aoo --> |setPres\nfrom `setState`| state +``` + +```ts +import { Component } from '@angular/core'; +import { read, utils } from 'xlsx'; + +interface President { Name: string; Index: number }; + +@Component({ /* ... component configuration options ... */ }) +export class AppComponent { + rows: President[] = [ { Name: "SheetJS", Index: 0 }]; + ngOnInit(): void { (async() => { + /* Download from https://sheetjs.com/pres.numbers */ + const f = await fetch("https://sheetjs.com/pres.numbers"); + const ab = await f.arrayBuffer(); + + // highlight-start + /* parse workbook */ + const wb = read(ab); + + /* generate array of objects from first worksheet */ + const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet + const data = utils.sheet_to_json(ws); // generate objects + + /* update data */ + this.rows = data; + // highlight-end + })(); } +} +``` + +#### Rendering Data + +Components typically render HTML tables from arrays of objects. The `` table +row elements are typically generated by mapping over the state array, as shown +in the example template. + +:::caution pass + +Angular 2 - 16 recommended using `ngFor`[^3]. Angular 17 no longer supports the +storied syntax, instead opting for a `@for` block reminiscent of JavaScript[^4]. + +::: + + + + +```html title="Example Template for displaying arrays of objects (Angular 2-16)" +
+ + +// highlight-start + + + + +// highlight-end + +
NameIndex
{{row.Name}}{{row.Index}}
+``` + +
+ + +```html title="Example Template for displaying arrays of objects (Angular 17+)" +
+ + +// highlight-start + @for(row of rows; track $index) { + + + } +// highlight-end + +
NameIndex
{{row.Name}}{{row.Index}}
+``` + +
+
+ +#### Exporting Data + +The [`writeFile`](/docs/api/write-options) and [`json_to_sheet`](/docs/api/utilities/array#array-of-objects-input) +functions simplify exporting data. They are best used in the function bodies of +event handlers 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)) + ws(SheetJS\nWorksheet) + wb(SheetJS\nWorkbook) + file[(XLSX\nexport)] + state --> |json_to_sheet\n\n| ws + ws --> |book_new\nbook_append_sheet| wb + wb --> |writeFile\n\n| file +``` + +```ts title="src/app/app.component.ts" +import { Component } from '@angular/core'; +import { utils, writeFileXLSX } from 'xlsx'; + +interface President { Name: string; Index: number }; + +@Component({ /* ... component configuration options ... */ }) +export class AppComponent { + rows: President[] = [ { Name: "SheetJS", Index: 0 }]; + /* get state data and export to XLSX */ + onSave(): void { + /* generate worksheet from state */ + // highlight-next-line + const ws = utils.json_to_sheet(this.rows); + /* create workbook and append worksheet */ + const wb = utils.book_new(); + utils.book_append_sheet(wb, ws, "Data"); + /* export to XLSX */ + writeFileXLSX(wb, "SheetJSAngularAoO.xlsx"); + } +} +``` + +#### Complete Component + +This complete component example fetches a test file and displays the contents in +a HTML table. When the export button is clicked, a callback will export a file: + + + ```ts title="src/app/app.component.ts" import { Component } from '@angular/core'; @@ -152,11 +353,72 @@ export class AppComponent { } ``` + + + +```ts title="src/app/app.component.ts" +import { Component } from '@angular/core'; +import { read, utils, writeFileXLSX } from 'xlsx'; + +interface President { Name: string; Index: number }; + +@Component({ + selector: 'app-root', + standalone: true, + template: ` +
+ + +// highlight-start + @for(row of rows; track $index) { + + + + + } +// highlight-end + + + +
NameIndex
{{row.Name}}{{row.Index}}
+` +}) +export class AppComponent { + // highlight-next-line + rows: President[] = [ { Name: "SheetJS", Index: 0 }]; + ngOnInit(): void { (async() => { + /* Download from https://sheetjs.com/pres.numbers */ + const f = await fetch("https://sheetjs.com/pres.numbers"); + const ab = await f.arrayBuffer(); + + /* parse workbook */ + // highlight-next-line + const wb = read(ab); + + /* update data */ + // highlight-next-line + this.rows = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]); + + })(); } + /* get state data and export to XLSX */ + onSave(): void { + // highlight-next-line + const ws = utils.json_to_sheet(this.rows); + const wb = utils.book_new(); + utils.book_append_sheet(wb, ws, "Data"); + writeFileXLSX(wb, "SheetJSAngularAoO.xlsx"); + } +} +``` + +
+
+
How to run the example (click to show) -:::note +:::note Tested Deployments -This demo was last run on 2023-10-22 using Angular CLI `16.2.7` +This demo was last run on 2023-11-18 using Angular 17.0.3 and CLI `17.0.1` ::: @@ -169,7 +431,7 @@ npx @angular/cli analytics disable -g 1) Create a new project: ```bash -npx @angular/cli@16.2.7 new --minimal --defaults --no-interactive sheetjs-angular +npx @angular/cli@17.0.1 new --minimal --defaults --no-interactive sheetjs-angular ``` 2) Install the SheetJS dependency and start the dev server: @@ -184,7 +446,9 @@ npm start`} 3) Open a web browser and access the displayed URL (`http://localhost:4200`) -4) Replace `src/app/app.component.ts` with the previous code snippet. +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 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 @@ -198,10 +462,23 @@ npm run build To test the generated site, start a web server: + + + ```bash npx -y http-server dist/sheetjs-angular/ ``` + + + +```bash +npx -y http-server dist/sheetjs-angular/browser/ +``` + + + + Access `http://localhost:8080` with a web browser to test the bundled site.
@@ -215,7 +492,10 @@ However, this does not handle merge cells well! The `sheet_to_html` function generates HTML that is aware of merges and other worksheet features. The generated HTML does not contain any ` ``` -The HTML table can be directly exported with `XLSX.utils.table_to_book`: +The HTML table can be directly exported with [`table_to_book`](/docs/api/utilities/html#html-table-input): ```js $scope.exportSheetJS = function() { @@ -291,11 +362,10 @@ app.controller('sheetjs', function($scope, $http) { XLSX.writeFile(wb, "SheetJSAngularJSHTML.xlsx"); }; $http({ - method:'GET', url:'https://sheetjs.com/pres.xlsx', - responseType:'arraybuffer' + method:'GET', responseType:'arraybuffer' }).then(function(data) { - var wb = XLSX.read(data.data, {type:"array"}); + var wb = XLSX.read(data.data); $scope.data = XLSX.utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]); }, function(err) { console.log(err); }); }); @@ -308,3 +378,7 @@ app.controller('sheetjs', function($scope, $http) { URL with a web browser (typically `http://localhost:8080`) + +[^1]: See [`$http`](https://docs.angularjs.org/api/ng/service/$http) in the AngularJS documentation. +[^2]: See ["Workbook Object"](/docs/csf/book) +[^3]: See ["Creating Directives"](https://docs.angularjs.org/guide/directive#creating-a-directive-that-manipulates-the-dom) in the AngularJS documentation. \ No newline at end of file diff --git a/docz/docs/03-demos/06-desktop/04-tauri.md b/docz/docs/03-demos/06-desktop/04-tauri.md index b1620ad..b5969c9 100644 --- a/docz/docs/03-demos/06-desktop/04-tauri.md +++ b/docz/docs/03-demos/06-desktop/04-tauri.md @@ -257,7 +257,7 @@ This demo was tested in the following environments: | OS and Version | Arch | Tauri | Date | |:---------------|:-----|:---------|:-----------| -| macOS 13.5.1 | x64 | `v1.5.0` | 2023-09-30 | +| macOS 14.1.1 | x64 | `v1.5.6` | 2023-11-17 | | macOS 14.0 | ARM | `v1.5.2` | 2023-10-18 | | Windows 10 | x64 | `v1.5.0` | 2023-10-01 | | Windows 11 | ARM | `v1.4.1` | 2023-09-26 | @@ -287,14 +287,15 @@ If required dependencies are installed, the output will show a checkmark next to ``` [✔] Environment - - OS: Mac OS 13.5.1 X64 + - OS: Mac OS 14.1.1 X64 ✔ Xcode Command Line Tools: installed - ✔ rustc: 1.72.1 (d5c2e9c34 2023-09-13) - ✔ Cargo: 1.72.1 (103a7ff2e 2023-08-15) - ✔ rustup: 1.26.0+1046 (d4c684485 2023-08-30) + ✔ rustc: 1.74.0 (79e9716c9 2023-11-13) + ✔ cargo: 1.74.0 (ecb9851af 2023-10-18) + ✔ rustup: 1.26.0+198 (393e187b7 2023-11-16) ✔ Rust toolchain: stable-x86_64-apple-darwin (default) - - node: 16.20.2 - - npm: 8.19.4 + - node: 20.9.0 + - npm: 10.1.0 + - bun: 1.0.2 ``` :::caution pass @@ -309,17 +310,9 @@ build step will correctly detect the platform architecture. 1) Create a new Tauri app: ```bash -npm create tauri-app +npm create tauri-app@latest -- -m npm -t vue-ts SheetJSTauri -y ``` -When prompted: - -- Project Name: `SheetJSTauri` -- Choose which language to use for your frontend: `TypeScript / JavaScript` -- Choose your package manager: `npm` -- Choose your UI template: `Vue` -- Choose your UI flavor: `TypeScript` - 2) Enter the directory and install dependencies: {`\ @@ -378,17 +371,7 @@ At the end, it will print the path to the generated installer. :::info pass -During the last Linux test, the build had failed with an error: - -``` -'openssl/opensslv.h' file not found -``` - -This error was resolved installing OpenSSL. On Arch Linux and HoloOS: - -```bash -sudo pacman -S openssl -``` +If the build fails, see ["Troubleshooting"](#troubleshooting) for more details. ::: @@ -428,6 +411,51 @@ The following features should be manually verified: - Edit the file in a spreadsheet editor, then click "Load Data" and select the edited file. The table will refresh with new contents. +#### Troubleshooting + +:::note pass + +During the last Linux test, the build failed with the following error message: + +``` +'openssl/opensslv.h' file not found +``` + +This error was resolved installing OpenSSL. On Arch Linux and HoloOS: + +```bash +sudo pacman -S openssl +``` + +::: + +:::note pass + +During the last macOS test, the build failed with the following error message: + +``` + Error failed to bundle project: error running bundle_dmg.sh +``` + +The root cause of the error can be discovered by running + +```bash +npm run tauri build -- --verbose +``` + +The most recent test failed with a message: + +``` +execution error: Not authorized to send Apple events to Finder +``` + +This error was resolved by allowing Terminal to control Finder. + +In the "System Settings" app, select "Privacy & Security" in the left column and +select "Automation" in the body. Look for "Terminal", expand the section, and enable "Finder". + +::: + [^1]: See ["Security"](https://tauri.app/v1/references/architecture/security#allowing-api) in the Tauri documentation [^2]: See [`FsAllowlistConfig`](https://tauri.app/v1/api/config/#fsallowlistconfig) in the Tauri documentation [^3]: See [`DialogAllowlistConfig`](https://tauri.app/v1/api/config/#dialogallowlistconfig) in the Tauri documentation diff --git a/docz/docs/03-demos/07-data/26-redis.md b/docz/docs/03-demos/07-data/26-redis.md index bae4bef..ead32df 100644 --- a/docz/docs/03-demos/07-data/26-redis.md +++ b/docz/docs/03-demos/07-data/26-redis.md @@ -208,10 +208,10 @@ const aoa = [ ["Hash"], [key] ].concat(Object.entries(values)); ## Complete Example -:::note +:::note Tested Deployments -This demo was last tested on 2023 August 22 with Redis 7.2.0, Redis connector -module 4.6.7 and NodeJS 20.5.1. +This demo was last tested on 2023 November 18 with Redis 7.2.3, Redis connector +module 4.6.10 and NodeJS 20.9.0. ::: @@ -225,7 +225,7 @@ this demo also requires NodeJS version 18 or later. 0) Set up and start a local Redis server. -:::note +:::note pass This demo was last tested on macOS. Redis was installed with: @@ -254,7 +254,7 @@ curl -LO https://docs.sheetjs.com/nosql/SheetJSRedisTest.mjs 2) Install dependencies: {`\ -npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz redis@4.6.7`} +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz redis@4.6.10`} 3) Run the test script: diff --git a/docz/docs/03-demos/09-cloud/02-netsuite.md b/docz/docs/03-demos/09-cloud/02-netsuite.md index 0bc9f48..dd0d10c 100644 --- a/docz/docs/03-demos/09-cloud/02-netsuite.md +++ b/docz/docs/03-demos/09-cloud/02-netsuite.md @@ -27,7 +27,7 @@ This demo was verified by NetSuite consultants in the following deployments: | ScheduledScript | 2.1 | 2023-08-18 | | Restlet | 2.1 | 2023-10-05 | | Suitelet | 2.1 | 2023-10-27 | -| MapReduceScript | 2.1 | 2023-07-31 | +| MapReduceScript | 2.1 | 2023-11-16 | ::: diff --git a/docz/docs/03-demos/index.md b/docz/docs/03-demos/index.md index 11a0b76..ea89fb9 100644 --- a/docz/docs/03-demos/index.md +++ b/docz/docs/03-demos/index.md @@ -33,7 +33,7 @@ in the [issue tracker](https://git.sheetjs.com/sheetjs/docs.sheetjs.com/issues) - [`React`](/docs/demos/frontend/react) - [`Svelte`](/docs/demos/frontend/svelte) - [`VueJS`](/docs/demos/frontend/vue) -- [`Angular.JS`](/docs/demos/frontend/angularjs) +- [`AngularJS`](/docs/demos/frontend/angularjs) - [`Dojo`](/docs/demos/frontend/legacy#dojo-toolkit) - [`Knockout`](/docs/demos/frontend/legacy#knockoutjs) diff --git a/docz/static/dta/dta.min.js b/docz/static/dta/dta.min.js index 6d47997..e7ffc1c 100644 --- a/docz/static/dta/dta.min.js +++ b/docz/static/dta/dta.min.js @@ -1,2 +1,2 @@ -var DTA=(()=>{var O=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var K=Object.getOwnPropertyNames;var J=Object.prototype.hasOwnProperty;var j=r=>O(r,"__esModule",{value:!0});var q=(r,t)=>{for(var s in t)O(r,s,{get:t[s],enumerable:!0})},z=(r,t,s,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let c of K(t))!J.call(r,c)&&(s||c!=="default")&&O(r,c,{get:()=>t[c],enumerable:!(e=I(t,c))||e.enumerable});return r};var H=(r=>(t,s)=>r&&r.get(t)||(s=z(j({}),t,1),r&&r.set(t,s),s))(typeof WeakMap!="undefined"?new WeakMap:0);var re={};q(re,{parse:()=>te,set_utils:()=>Q});var k;function Q(r){k=r}function W(r){return new DataView(r.buffer,r.byteOffset,r.byteLength)}function i(r,t){return r.str.slice(r.ptr,r.ptr+t.length)!=t?!1:(r.ptr+=t.length,!0)}function X(r,t){let s=r.str.indexOf(t,r.ptr);if(s==-1)throw new Error(`Expected ${t} after offset ${r.ptr}`);r.ptr=s+t.length}function p(r,t){let s=r.str.indexOf(t,r.ptr);if(s==-1)throw new Error(`Expected ${t} after offset ${r.ptr}`);let e=r.raw.slice(r.ptr,s),c={ptr:0,raw:e,str:r.str.slice(r.ptr,s),dv:W(e)};return r.ptr=s+t.length,c}function F(r,t){r.ptr+=8;let s=r.dv.getFloat64(r.ptr-8,t);return s>8988e304?null:s}function R(r,t){r.ptr+=4;let s=r.dv.getFloat32(r.ptr-4,t);return s>1701e35?null:s}function g(r,t){return r.ptr+=4,r.dv.getUint32(r.ptr-4,t)}function V(r,t){r.ptr+=4;let s=r.dv.getInt32(r.ptr-4,t);return s>2147483620?null:s}function P(r,t){return r.ptr+=2,r.dv.getUint16(r.ptr-2,t)}function C(r,t){r.ptr+=2;let s=r.dv.getInt16(r.ptr-2,t);return s>32740?null:s}function x(r){return r.raw[r.ptr++]}function G(r){let t=r.raw[r.ptr++];return t=t<128?t:t-256,t>100?null:t}var Y=["117","118"];function Z(r){let t="Not a DTA file",s=new TextDecoder("latin1").decode(r),e={ptr:0,raw:r,str:s,dv:W(r)},c=118,n=!0,b=0,S=0,$=0,D=0,M="",A="",T=[],d=[],h=[];if(!i(e,""))throw t;{if(!i(e,"
"))throw t;{if(!i(e,""))throw t;let o=p(e,"");if(Y.indexOf(o.str)==-1)throw`Unsupported DTA ${o.str} file`;c=+o.str}{if(!i(e,""))throw t;let o=p(e,"");switch(o.str){case"MSF":n=!1;break;case"LSF":n=!0;break;default:throw`Unsupported byteorder ${o.str}`}}{if(!i(e,""))throw t;let o=p(e,"");b=P(o,n)}{if(!i(e,""))throw t;let o=p(e,"");if(c==117)S=$=g(o,n);else{let a=g(o,n),l=g(o,n);S=n?($=a)+(D=l)*Math.pow(2,32):($=l)+(D=a)*Math.pow(2,32)}S>1e6&&console.error("More than 1 million observations -- extra rows will be dropped")}{if(!i(e,""),a=c>=118?2:1,l=a==1?x(o):P(o,n);if(l+a!=o.str.length)throw`Expected string length ${l} but actual length was ${o.str.length-a}`;l>0&&(M=new TextDecoder().decode(o.raw.slice(a)))}{if(!i(e,""))throw t;let o=p(e,""),a=x(o);if(a+1!=o.str.length)throw`Expected string length ${a} but actual length was ${o.str.length-1}`;a>0&&(A=o.str.slice(1))}if(!i(e,"
"))throw t}{if(!i(e,""))throw t;X(e,"")}let f=0;{if(!i(e,""))throw t;let o=p(e,"");if(o.raw.length!=2*b)throw`Expected variable_types length ${b*2}, found ${o.raw.length}`;for(;o.ptr=1&&a<=2045)f+=a;else switch(a){case 32768:f+=8;break;case 65526:f+=8;break;case 65527:f+=4;break;case 65528:f+=4;break;case 65529:f+=2;break;case 65530:f+=1;break;default:throw`Unsupported field type ${a}`}}}{if(!i(e,""))throw t;let o=p(e,""),a=c>=118?129:33;if(o.raw.length!=a*b)throw`Expected variable_types length ${b*a}, found ${o.raw.length}`;for(;o.ptr"))throw t;let o=p(e,"");if(o.raw.length!=2*b+2)throw`Expected sortlist length ${b*2+2}, found ${o.raw.length}`}{if(!i(e,""))throw t;let o=p(e,""),a=c>=118?57:49;if(o.raw.length!=a*b)throw`Expected formats length ${b*a}, found ${o.raw.length}`;for(;o.ptr"))throw t;let o=c>=118?129:33,a=p(e,"")}{if(!i(e,""))throw t;let o=c>=118?321:81,a=p(e,"")}{if(!i(e,""))throw t;for(;e.str.slice(e.ptr,e.ptr+4)=="";){e.ptr+=4;let o=g(e,n);if(e.ptr+=o,!i(e,""))throw t}if(!i(e,""))throw t}let _=k.aoa_to_sheet([d],{dense:!0});var U=[];{if(!i(e,""))throw t;for(let o=0;o=1&&u<=2045){let w=new TextDecoder().decode(e.raw.slice(e.ptr,e.ptr+u));w=w.replace(/\x00[\s\S]*/,""),a[l]=w,e.ptr+=u}else switch(u){case 65526:a[l]=F(e,n);break;case 65527:a[l]=R(e,n);break;case 65528:a[l]=V(e,n);break;case 65529:a[l]=C(e,n);break;case 65530:a[l]=G(e);break;case 32768:a[l]="##SheetJStrL##",U.push([o+1,l,e.raw.slice(e.ptr,e.ptr+8)]),e.ptr+=8;break;default:throw`Unsupported field type ${u} for ${d[l]}`}}k.sheet_add_aoa(_,[a],{origin:-1,sheetStubs:!0})}if(!i(e,""))throw t}{if(!i(e,""))throw t;let o=[];for(;e.raw[e.ptr]==71;){if(!i(e,"GSO"))throw t;let a=g(e,n),l=0;if(c==117)l=g(e,n);else{let v=g(e,n),m=g(e,n);l=n?v+m*Math.pow(2,32):m+v*Math.pow(2,32),l>1e6&&console.error("More than 1 million observations -- data will be dropped")}let u=x(e),w=g(e,n);o[l]||(o[l]=[]);let y="";u==129?(y=new TextDecoder("latin1").decode(e.raw.slice(e.ptr,e.ptr+w)),e.ptr+=w):(y=new TextDecoder("latin1").decode(e.raw.slice(e.ptr,e.ptr+w)).replace(/\x00$/,""),e.ptr+=w),o[l][a]=y}if(!i(e,""))throw t;U.forEach(([a,l,u])=>{let w=W(u),y=0,v=0;switch(c){case 117:y=w.getUint32(0,n),v=w.getUint32(4,n);break;case 118:case 120:{y=w.getUint16(0,n);let m=w.getUint16(2,n),E=w.getUint32(4,n);v=n?m+E*65536:E+m*2**32}break;case 119:case 121:{let m=w.getUint16(0,n),E=u[2];y=n?m+(E<<16):E+(m<<8);let B=u[3],L=w.getUint32(4,n);v=n?B+L*256:L+B*2**32}}_["!data"][a][l].v=o[v][y]})}{if(!i(e,""))throw t;let o=p(e,"")}if(!i(e,"
"))throw t;let N=k.book_new();return k.book_append_sheet(N,_,"Sheet1"),N}function ee(r){let t=r[0];switch(t){case 102:case 112:throw`Unsupported DTA ${t} file`;case 103:case 104:case 105:case 108:case 110:case 111:case 113:case 114:case 115:break;default:throw new Error("Not a DTA file")}let s={ptr:1,raw:r,str:"",dv:W(r)},e=!0,c=0,n=0,b="",S="",$=[],D=[],M=[];{let d=x(s);switch(d){case 1:e=!1;break;case 2:e=!0;break;default:throw`DTA ${t} Unexpected byteorder ${d}`}let h=x(s);if(h!=1)throw`DTA ${t} Unexpected filetype ${h}`;s.ptr++,c=P(s,e),n=g(s,e),s.ptr+=t>=108?81:32,t>=105&&(s.ptr+=18)}{let d=0;for(d=0;d=110?33:9;for(d=0;d=114?49:t>=105?12:7;for(d=0;d=110?33:9)*c}if(s.ptr+=(t>=106?81:32)*c,t>=105)for(;s.ptr=111?g:P)(s,e);if(d==0&&h==0)break;s.ptr+=h}let A=k.aoa_to_sheet([D],{dense:!0});for(let d=0;d=111&&_>=1&&_<=244){let U=new TextDecoder().decode(s.raw.slice(s.ptr,s.ptr+_));U=U.replace(/\x00[\s\S]*/,""),h[f]=U,s.ptr+=_}else switch(_){case 251:case 98:h[f]=G(s);break;case 252:case 105:h[f]=C(s,e);break;case 253:case 108:h[f]=V(s,e);break;case 254:case 102:h[f]=R(s,e);break;case 255:case 100:h[f]=F(s,e);break;default:throw`Unsupported field type ${_} for ${D[f]}`}}k.sheet_add_aoa(A,[h],{origin:-1,sheetStubs:!0})}let T=k.book_new();return k.book_append_sheet(T,A,"Sheet1"),T}function te(r){if(r[0]>=102&&r[0]<=115)return ee(r);if(r[0]===60)return Z(r);throw new Error("Not a DTA file")}return H(re);})(); +var DTA=(()=>{var O=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var K=Object.getOwnPropertyNames;var J=Object.prototype.hasOwnProperty;var j=r=>O(r,"__esModule",{value:!0});var q=(r,t)=>{for(var s in t)O(r,s,{get:t[s],enumerable:!0})},z=(r,t,s,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let c of K(t))!J.call(r,c)&&(s||c!=="default")&&O(r,c,{get:()=>t[c],enumerable:!(e=I(t,c))||e.enumerable});return r};var H=(r=>(t,s)=>r&&r.get(t)||(s=z(j({}),t,1),r&&r.set(t,s),s))(typeof WeakMap!="undefined"?new WeakMap:0);var re={};q(re,{parse:()=>te,set_utils:()=>Q});var x;function Q(r){x=r}function W(r){return new DataView(r.buffer,r.byteOffset,r.byteLength)}function i(r,t){return r.str.slice(r.ptr,r.ptr+t.length)!=t?!1:(r.ptr+=t.length,!0)}function X(r,t){let s=r.str.indexOf(t,r.ptr);if(s==-1)throw new Error(`Expected ${t} after offset ${r.ptr}`);r.ptr=s+t.length}function u(r,t){let s=r.str.indexOf(t,r.ptr);if(s==-1)throw new Error(`Expected ${t} after offset ${r.ptr}`);let e=r.raw.slice(r.ptr,s),c={ptr:0,raw:e,str:r.str.slice(r.ptr,s),dv:W(e)};return r.ptr=s+t.length,c}function L(r,t){r.ptr+=8;let s=r.dv.getFloat64(r.ptr-8,t);return s>8988e304?null:s}function R(r,t){r.ptr+=4;let s=r.dv.getFloat32(r.ptr-4,t);return s>1701e35?null:s}function _(r,t){return r.ptr+=4,r.dv.getUint32(r.ptr-4,t)}function V(r,t){r.ptr+=4;let s=r.dv.getInt32(r.ptr-4,t);return s>2147483620?null:s}function P(r,t){return r.ptr+=2,r.dv.getUint16(r.ptr-2,t)}function C(r,t){r.ptr+=2;let s=r.dv.getInt16(r.ptr-2,t);return s>32740?null:s}function $(r){return r.raw[r.ptr++]}function G(r){let t=r.raw[r.ptr++];return t=t<128?t:t-256,t>100?null:t}var Y=["117","118","119","120","121"];function Z(r){let t="Not a DTA file",s=new TextDecoder("latin1").decode(r),e={ptr:0,raw:r,str:s,dv:W(r)},c=118,n=!0,g=0,U=0,D=0,S=0,M="",A="",T=[],f=[],w=[];if(!i(e,""))throw t;{if(!i(e,"
"))throw t;{if(!i(e,""))throw t;let o=u(e,"");if(Y.indexOf(o.str)==-1)throw`Unsupported DTA ${o.str} file`;c=+o.str}{if(!i(e,""))throw t;let o=u(e,"");switch(o.str){case"MSF":n=!1;break;case"LSF":n=!0;break;default:throw`Unsupported byteorder ${o.str}`}}{if(!i(e,""))throw t;let o=u(e,"");g=P(o,n)}{if(!i(e,""))throw t;let o=u(e,"");if(c==117)U=D=_(o,n);else{let a=_(o,n),l=_(o,n);U=n?(D=a)+(S=l)*Math.pow(2,32):(D=l)+(S=a)*Math.pow(2,32)}U>1e6&&console.error("More than 1 million observations -- extra rows will be dropped")}{if(!i(e,""),a=c>=118?2:1,l=a==1?$(o):P(o,n);if(l+a!=o.str.length)throw`Expected string length ${l} but actual length was ${o.str.length-a}`;l>0&&(M=new TextDecoder().decode(o.raw.slice(a)))}{if(!i(e,""))throw t;let o=u(e,""),a=$(o);if(a+1!=o.str.length)throw`Expected string length ${a} but actual length was ${o.str.length-1}`;a>0&&(A=o.str.slice(1))}if(!i(e,"
"))throw t}{if(!i(e,""))throw t;X(e,"")}let d=0;{if(!i(e,""))throw t;let o=u(e,"");if(o.raw.length!=2*g)throw`Expected variable_types length ${g*2}, found ${o.raw.length}`;for(;o.ptr=1&&a<=2045)d+=a;else switch(a){case 32768:d+=8;break;case 65525:d+=0;break;case 65526:d+=8;break;case 65527:d+=4;break;case 65528:d+=4;break;case 65529:d+=2;break;case 65530:d+=1;break;default:throw`Unsupported field type ${a}`}}}{if(!i(e,""))throw t;let o=u(e,""),a=c>=118?129:33;if(o.raw.length!=a*g)throw`Expected variable_types length ${g*a}, found ${o.raw.length}`;for(;o.ptr"))throw t;let o=u(e,"");if(o.raw.length!=(2*g+2)*(c==119||c==121?2:1))throw`Expected sortlist length ${g*2+2}, found ${o.raw.length}`}{if(!i(e,""))throw t;let o=u(e,""),a=c>=118?57:49;if(o.raw.length!=a*g)throw`Expected formats length ${g*a}, found ${o.raw.length}`;for(;o.ptr"))throw t;let o=c>=118?129:33,a=u(e,"")}{if(!i(e,""))throw t;let o=c>=118?321:81,a=u(e,"")}{if(!i(e,""))throw t;for(;e.str.slice(e.ptr,e.ptr+4)=="";){e.ptr+=4;let o=_(e,n);if(e.ptr+=o,!i(e,""))throw t}if(!i(e,""))throw t}let p=x.aoa_to_sheet([f],{dense:!0});var k=[];{if(!i(e,""))throw t;for(let o=0;o=1&&b<=2045){let h=new TextDecoder().decode(e.raw.slice(e.ptr,e.ptr+b));h=h.replace(/\x00[\s\S]*/,""),a[l]=h,e.ptr+=b}else switch(b){case 65525:e.ptr+=0;break;case 65526:a[l]=L(e,n);break;case 65527:a[l]=R(e,n);break;case 65528:a[l]=V(e,n);break;case 65529:a[l]=C(e,n);break;case 65530:a[l]=G(e);break;case 32768:a[l]="##SheetJStrL##",k.push([o+1,l,e.raw.slice(e.ptr,e.ptr+8)]),e.ptr+=8;break;default:throw`Unsupported field type ${b} for ${f[l]}`}}x.sheet_add_aoa(p,[a],{origin:-1,sheetStubs:!0})}if(!i(e,""))throw t}{if(!i(e,""))throw t;let o=[];for(;e.raw[e.ptr]==71;){if(!i(e,"GSO"))throw t;let a=_(e,n),l=0;if(c==117)l=_(e,n);else{let v=_(e,n),m=_(e,n);l=n?v+m*Math.pow(2,32):m+v*Math.pow(2,32),l>1e6&&console.error("More than 1 million observations -- data will be dropped")}let b=$(e),h=_(e,n);o[l]||(o[l]=[]);let y="";b==129?(y=new TextDecoder("latin1").decode(e.raw.slice(e.ptr,e.ptr+h)),e.ptr+=h):(y=new TextDecoder("latin1").decode(e.raw.slice(e.ptr,e.ptr+h)).replace(/\x00$/,""),e.ptr+=h),o[l][a]=y}if(!i(e,""))throw t;k.forEach(([a,l,b])=>{let h=W(b),y=0,v=0;switch(c){case 117:y=h.getUint32(0,n),v=h.getUint32(4,n);break;case 118:case 120:{y=h.getUint16(0,n);let m=h.getUint16(2,n),E=h.getUint32(4,n);v=n?m+E*65536:E+m*2**32}break;case 119:case 121:{let m=h.getUint16(0,n),E=b[2];y=n?m+(E<<16):E+(m<<8);let N=b[3],B=h.getUint32(4,n);v=n?N+B*256:B+N*2**32}}p["!data"][a][l].v=o[v][y]})}{if(!i(e,""))throw t;let o=u(e,"")}if(!i(e,"
"))throw t;let F=x.book_new();return x.book_append_sheet(F,p,"Sheet1"),F}function ee(r){let t=r[0];switch(t){case 102:case 103:case 104:case 105:case 108:case 110:case 111:case 112:case 113:case 114:case 115:break;default:throw new Error("Not a DTA file")}let s={ptr:1,raw:r,str:"",dv:W(r)},e=!0,c=0,n=0,g="",U="",D=[],S=[],M=[];{let f=$(s);switch(f){case 1:e=!1;break;case 2:e=!0;break;default:throw`DTA ${t} Unexpected byteorder ${f}`}let w=$(s);if(w!=1)throw`DTA ${t} Unexpected filetype ${w}`;s.ptr++,c=P(s,e),n=_(s,e),s.ptr+=t>=108?81:t>=103?32:30,t>=105&&(s.ptr+=18)}{let f=0;for(f=0;f=110?33:9;for(f=0;f=114?49:t>=105?12:7;for(f=0;f=110?33:9)*c}if(s.ptr+=(t>=106?81:32)*c,t>=105)for(;s.ptr=111?_:P)(s,e);if(f==0&&w==0)break;s.ptr+=w}let A=x.aoa_to_sheet([S],{dense:!0});for(let f=0;f=111&&p>=1&&p<=244){let k=new TextDecoder().decode(s.raw.slice(s.ptr,s.ptr+p));k=k.replace(/\x00[\s\S]*/,""),w[d]=k,s.ptr+=p}else if(t<=110&&p>=128){let k=new TextDecoder().decode(s.raw.slice(s.ptr,s.ptr+p-127));k=k.replace(/\x00[\s\S]*/,""),w[d]=k,s.ptr+=p-127}else switch(p){case 251:case 98:w[d]=G(s);break;case 252:case 105:w[d]=C(s,e);break;case 253:case 108:w[d]=V(s,e);break;case 254:case 102:w[d]=R(s,e);break;case 255:case 100:w[d]=L(s,e);break;default:throw`Unsupported field type ${p} for ${S[d]}`}}x.sheet_add_aoa(A,[w],{origin:-1,sheetStubs:!0})}let T=x.book_new();return x.book_append_sheet(T,A,"Sheet1"),T}function te(r){if(r[0]>=102&&r[0]<=115)return ee(r);if(r[0]===60)return Z(r);throw new Error("Not a DTA file")}return H(re);})(); //# sourceMappingURL=dta.min.js.map