diff --git a/.spelling b/.spelling
index 5721ffa..300f8b1 100644
--- a/.spelling
+++ b/.spelling
@@ -148,6 +148,7 @@ storages
- demos/extendscript/README.md
Photoshop
+InDesign
minifier
- demos/function/README.md
diff --git a/README.md b/README.md
index cbf21a1..80226dd 100644
--- a/README.md
+++ b/README.md
@@ -40,11 +40,18 @@ port calculations to web apps; automate common spreadsheet tasks, and much more!
- [Getting Started](#getting-started)
* [Installation](#installation)
* [Usage](#usage)
- + [The Zen of SheetJS](#the-zen-of-sheetjs)
+ * [The Zen of SheetJS](#the-zen-of-sheetjs)
* [JS Ecosystem Demos](#js-ecosystem-demos)
-- [Parsing Workbooks](#parsing-workbooks)
- * [Parsing Examples](#parsing-examples)
- * [Streaming Read](#streaming-read)
+- [Acquiring and Extracting Data](#acquiring-and-extracting-data)
+ * [Parsing Workbooks](#parsing-workbooks)
+ + [API](#api)
+ + [Examples](#examples)
+ * [Processing JSON and JS Data](#processing-json-and-js-data)
+ + [API](#api-1)
+ + [Examples](#examples-1)
+ * [Processing HTML Tables](#processing-html-tables)
+ + [API](#api-2)
+ + [Examples](#examples-2)
- [Working with the Workbook](#working-with-the-workbook)
* [Parsing and Writing Examples](#parsing-and-writing-examples)
- [Writing Workbooks](#writing-workbooks)
@@ -114,7 +121,8 @@ port calculations to web apps; automate common spreadsheet tasks, and much more!
### Installation
-In the browser, just add a script tag:
+The complete browser standalone build is saved to `dist/xlsx.full.min.js` and
+can be directly added to a page with a `script` tag:
```html
@@ -130,7 +138,7 @@ In the browser, just add a script tag:
| `CDNjs` | |
| `packd` | |
-`unpkg` makes the latest version available at:
+For example, `unpkg` makes the latest version available at:
```html
@@ -138,33 +146,8 @@ In the browser, just add a script tag:
-
-With [npm](https://www.npmjs.org/package/xlsx):
-
-```bash
-$ npm install xlsx
-```
-
-With [bower](https://bower.io/search/?q=js-xlsx):
-
-```bash
-$ bower install js-xlsx
-```
-
- Optional features (click to show)
-
-The node version automatically requires modules for additional features. Some
-of these modules are rather large in size and are only needed in special
-circumstances, so they do not ship with the core. For browser use, they must
-be included directly:
-
-```html
-
-
-```
-
-An appropriate version for each dependency is included in the dist/ directory.
+ Browser builds (click to show)
The complete single-file version is generated at `dist/xlsx.full.min.js`
@@ -186,8 +169,30 @@ be configured to remove support with `resolve.alias`:
+
+With [npm](https://www.npmjs.org/package/xlsx):
+
+```bash
+$ npm install xlsx
+```
+
+With [bower](https://bower.io/search/?q=js-xlsx):
+
+```bash
+$ bower install js-xlsx
+```
+
+`dist/xlsx.extendscript.js` is an ExtendScript build for Photoshop and InDesign
+that is included in the `npm` package. It can be directly referenced with a
+`#include` directive:
+
+```extendscript
+#include "xlsx.extendscript.js"
+```
+
+
- ECMAScript 3 Compatibility (click to show)
+ Internet Explorer and ECMAScript 3 Compatibility (click to show)
For broad compatibility with JavaScript engines, the library is written using
ECMAScript 3 language dialect as well as some ES5 features like `Array#forEach`.
@@ -241,8 +246,8 @@ var table_elt = document.getElementById("my-table-id");
var workbook = XLSX.utils.table_to_book(table_elt);
// Process Data (add a new row)
-var worksheet = workbook.Sheets["Sheet1"];
-XLSX.utils.sheet_add_aoa([["Created "+new Date().toISOString()}]], {origin:-1});
+var ws = workbook.Sheets["Sheet1"];
+XLSX.utils.sheet_add_aoa(ws, [["Created "+new Date().toISOString()]], {origin:-1});
// Package and Release Data (`writeFile` tries to write and save an XLSB file)
XLSX.writeFile(workbook, "Report.xlsb");
@@ -250,7 +255,8 @@ XLSX.writeFile(workbook, "Report.xlsb");
This library tries to simplify steps 2 and 4 with functions to extract useful
data from spreadsheet files (`read` / `readFile`) and generate new spreadsheet
-files from data (`write` / `writeFile`).
+files from data (`write` / `writeFile`). Additional utility functions like
+`table_to_book` work with other common data sources like HTML tables.
This documentation and various demo projects cover a number of common scenarios
and approaches for steps 1 and 5.
@@ -258,8 +264,210 @@ and approaches for steps 1 and 5.
Utility functions help with step 3.
-#### The Zen of SheetJS
+### The Zen of SheetJS
+_Data processing should fit in any workflow_
+
+The library does not impose a separate lifecycle. It fits nicely in websites
+and apps built using any framework. The plain JS data objects play nice with
+Web Workers and future APIs.
+
+["Acquiring and Extracting Data"](#acquiring-and-extracting-data) describes
+solutions for common data import scenarios.
+
+["Writing Workbooks"](#writing-workbooks) describes solutions for common data
+export scenarios involving actual spreadsheet files.
+
+["Utility Functions"](#utility-functions) details utility functions for
+translating JSON Arrays and other common JS structures into worksheet objects.
+
+_JavaScript is a powerful language for data processing_
+
+The ["Common Spreadsheet Format"](#common-spreadsheet-format) is a simple object
+representation of the core concepts of a workbook. The various functions in the
+library provide low-level tools for working with the object.
+
+For friendly JS processing, there are utility functions for converting parts of
+a worksheet to/from an Array of Arrays. The following example combines powerful
+JS Array methods with a network request library to download data, select the
+information we want and create a workbook file:
+
+
+ Get Data from a JSON Endpoint and Generate a Workbook (click to show)
+
+The goal is to generate a XLSB workbook of US President names and birthdays.
+
+**Acquire Data**
+
+_Raw Data_
+
+ has the desired
+data. For example, John Adams:
+
+```js
+{
+ "id": { /* (data omitted) */ },
+ "name": {
+ "first": "John", // <-- first name
+ "last": "Adams" // <-- last name
+ },
+ "bio": {
+ "birthday": "1735-10-19", // <-- birthday
+ "gender": "M"
+ },
+ "terms": [
+ { "type": "viceprez", /* (other fields omitted) */ },
+ { "type": "viceprez", /* (other fields omitted) */ },
+ { "type": "prez", /* (other fields omitted) */ } // <-- look for "prez"
+ ]
+}
+```
+
+_Filtering for Presidents_
+
+The dataset includes Aaron Burr, a Vice President who was never President!
+
+`Array#filter` creates a new array with the desired rows. A President served
+at least one term with `type` set to `"prez"`. To test if a particular row has
+at least one `"prez"` term, `Array#some` is another native JS function. The
+complete filter would be:
+
+```js
+const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez"));
+```
+
+_Lining up the data_
+
+For this example, the name will be the first name combined with the last name
+(`row.name.first + " " + row.name.last`) and the birthday will be the subfield
+`row.bio.birthday`. Using `Array#map`, the dataset can be massaged in one call:
+
+```js
+const rows = prez.map(row => ({
+ name: row.name.first + " " + row.name.last,
+ birthday: row.bio.birthday
+}));
+```
+
+The result is an array of "simple" objects with no nesting:
+
+```js
+[
+ { name: "George Washington", birthday: "1732-02-22" },
+ { name: "John Adams", birthday: "1735-10-19" },
+ // ... one row per President
+]
+```
+
+**Extract Data**
+
+With the cleaned dataset, `XLSX.utils.json_to_sheet` generates a worksheet:
+
+```js
+const worksheet = XLSX.utils.json_to_sheet(rows);
+```
+
+`XLSX.utils.book_new` creates a new workbook and `XLSX.utils.book_append_sheet`
+appends a worksheet to the workbook. The new worksheet will be called "Dates":
+
+```js
+const workbook = XLSX.utils.book_new();
+XLSX.utils.book_append_sheet(workbook, worksheet, "Dates");
+```
+
+**Process Data**
+
+_Fixing headers_
+
+By default, `json_to_sheet` creates a worksheet with a header row. In this case,
+the headers come from the JS object keys: "name" and "birthday".
+
+The headers are in cells A1 and B1. `XLSX.utils.sheet_add_aoa` can write text
+values to the existing worksheet starting at cell A1:
+
+```js
+XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });
+```
+
+_Fixing Column Widths_
+
+Some of the names are longer than the default column width. Column widths are
+set by [setting the `"!cols"` worksheet property](#row-and-column-properties).
+
+The following line sets the width of column A to approximately 10 characters:
+
+```js
+worksheet["!cols"] = [ { wch: 10 } ]; // set column A width to 10 characters
+```
+
+One `Array#reduce` call over `rows` can calculate the maximum width:
+
+```js
+const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
+worksheet["!cols"] = [ { wch: max_width } ];
+```
+
+Note: If the starting point was a file or HTML table, `XLSX.utils.sheet_to_json`
+will generate an array of JS objects.
+
+**Package and Release Data**
+
+`XLSX.writeFile` creates a spreadsheet file and tries to write it to the system.
+In the browser, it will try to prompt the user to download the file. In NodeJS,
+it will write to the local directory.
+
+```js
+XLSX.writeFile(workbook, "Presidents.xlsx");
+```
+
+**Complete Example**
+
+```js
+// Uncomment the next line for use in NodeJS:
+// const XLSX = require("xlsx"), axios = require("axios");
+
+(async() => {
+ /* fetch JSON data and parse */
+ const url = "https://theunitedstates.io/congress-legislators/executive.json";
+ const raw_data = (await axios(url, {responseType: "json"})).data;
+
+ /* filter for the Presidents */
+ const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez"));
+
+ /* flatten objects */
+ const rows = prez.map(row => ({
+ name: row.name.first + " " + row.name.last,
+ birthday: row.bio.birthday
+ }));
+
+ /* generate worksheet and workbook */
+ const worksheet = XLSX.utils.json_to_sheet(rows);
+ const workbook = XLSX.utils.book_new();
+ XLSX.utils.book_append_sheet(workbook, worksheet, "Dates");
+
+ /* fix headers */
+ XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });
+
+ /* calculate column width */
+ const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
+ worksheet["!cols"] = [ { wch: max_width } ];
+
+ /* create an XLSX file and try to save to Presidents.xlsx */
+ XLSX.writeFile(workbook, "Presidents.xlsx");
+})();
+```
+
+For use in the web browser, assuming the snippet is saved to `snippet.js`,
+script tags should be used to include the `axios` and `xlsx` standalone builds:
+
+```html
+
+
+
+```
+
+
+
_File formats are implementation details_
@@ -269,37 +477,8 @@ The parser covers a wide gamut of common spreadsheet file formats to ensure that
The writer supports a number of common output formats for broad compatibility
with the data ecosystem.
-
-_Data processing should fit in any workflow_
-
-The library does not impose a separate lifecycle. It fits nicely in websites
-and apps built using any framework. The plain JS data objects play nice with
-Web Workers and future APIs.
-
-["Parsing Workbooks"](#parsing-workbooks) describes solutions for common data
-import scenarios involving actual spreadsheet files.
-
-["Writing Workbooks"](#writing-workbooks) describes solutions for common data
-export scenarios involving actual spreadsheet files.
-
-["Utility Functions"](#utility-functions) details utility functions for
-translating JSON Arrays and other common JS structures into worksheet objects.
-
-
-_JavaScript is a powerful language for data processing_
-
-The ["Common Spreadsheet Format"](#common-spreadsheet-format) is a simple object
-representation of the core concepts of a workbook. The various functions in the
-library provide low-level tools for working with the object.
-
-For friendly JS processing, there are utility functions for converting parts of
-a worksheet to/from an Array of Arrays. For example, summing columns from an
-array of arrays can be implemented in a single Array reduce operation:
-
-```js
-var aoa = XLSX.utils.sheet_to_json(worksheet, {header: 1});
-var sum_of_column_B = aoa.reduce((acc, row) => acc + (+row[1]||0), 0);
-```
+To the greatest extent possible, data processing code should not have to worry
+about the specific file formats involved.
### JS Ecosystem Demos
@@ -342,85 +521,175 @@ The [`demos` directory](demos/) includes sample projects for:
Other examples are included in the [showcase](demos/showcase/).
-## Parsing Workbooks
+## Acquiring and Extracting Data
-For parsing, the first step is to read the file. This involves acquiring the
-data and feeding it into the library. Here are a few common scenarios:
+### Parsing Workbooks
-
- nodejs read a file (click to show)
+#### API
-`readFile` is only available in server environments. Browsers have no API for
-reading arbitrary files given a path, so another strategy must be used.
+_Extract data from spreadsheet bytes_
```js
-if(typeof require !== 'undefined') XLSX = require('xlsx');
-var workbook = XLSX.readFile('test.xlsx');
-/* DO SOMETHING WITH workbook HERE */
+var workbook = XLSX.read(data, opts);
+```
+
+The `read` method can extract data from spreadsheet bytes stored in a JS string,
+"binary string", NodeJS buffer or typed array (`Uint8Array` or `ArrayBuffer`).
+
+
+_Read spreadsheet bytes from a local file and extract data_
+
+```js
+var workbook = XLSX.readFile(filename, opts);
+```
+
+The `readFile` method attempts to read a spreadsheet file at the supplied path.
+Browsers generally do not allow reading files in this way (it is deemed a
+security risk), and attempts to read files in this way will throw an error.
+
+The second `opts` argument is optional. ["Parsing Options"](#parsing-options)
+covers the supported properties and behaviors.
+
+#### Examples
+
+Here are a few common scenarios (click on each subtitle to see the code):
+
+
+ Local file in a NodeJS server (click to show)
+
+`readFile` uses `fs.readFileSync` under the hood:
+
+```js
+var XLSX = require("xlsx");
+
+var workbook = XLSX.readFile("test.xlsx");
+```
+
+For Node ESM, the `readFile` helper is not enabled. Instead, `fs.readFileSync`
+should be used to read the file data as a `Buffer` for use with `XLSX.read`:
+
+```js
+import { readFileSync } from "fs";
+import { read } from "xlsx/xlsx.mjs";
+
+const buf = readFileSync("test.xlsx");
+/* buf is a Buffer */
+const workbook = read(buf);
```
- Photoshop ExtendScript read a file (click to show)
+ User-submitted file in a web page ("Drag-and-Drop") (click to show)
-`readFile` wraps the `File` logic in Photoshop and other ExtendScript targets.
-The specified path should be an absolute path:
+For modern websites targeting Chrome 76+, `File#arrayBuffer` is recommended:
```js
-#include "xlsx.extendscript.js"
-/* Read test.xlsx from the Documents folder */
-var workbook = XLSX.readFile(Folder.myDocuments + '/' + 'test.xlsx');
-/* DO SOMETHING WITH workbook HERE */
+// XLSX is a global from the standalone script
+
+async function handleDropAsync(e) {
+ e.stopPropagation(); e.preventDefault();
+ const f = e.dataTransfer.files[0];
+ /* f is a File */
+ const data = await f.arrayBuffer();
+ /* data is an ArrayBuffer */
+ const workbook = XLSX.read(data);
+
+ /* DO SOMETHING WITH workbook HERE */
+}
+drop_dom_element.addEventListener("drop", handleDropAsync, false);
```
-The [`extendscript` demo](demos/extendscript/) includes a more complex example.
+For maximal compatibility, the `FileReader` API should be used:
+
+```js
+function handleDrop(e) {
+ e.stopPropagation(); e.preventDefault();
+ var f = e.dataTransfer.files[0];
+ /* f is a File */
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ var data = e.target.result;
+ /* reader.readAsArrayBuffer(file) -> data will be an ArrayBuffer */
+ var workbook = XLSX.read(data);
+
+ /* DO SOMETHING WITH workbook HERE */
+ };
+ reader.readAsArrayBuffer(f);
+}
+drop_dom_element.addEventListener("drop", handleDrop, false);
+```
+
+ demonstrates the FileReader technique.
- Browser read TABLE element from page (click to show)
+ User-submitted file with an HTML INPUT element (click to show)
-The `table_to_book` and `table_to_sheet` utility functions take a DOM TABLE
-element and iterate through the child nodes.
+Starting with an HTML INPUT element with `type="file"`:
-```js
-var workbook = XLSX.utils.table_to_book(document.getElementById('tableau'));
-/* DO SOMETHING WITH workbook HERE */
+```html
+
```
-Multiple tables on a web page can be converted to individual worksheets:
+For modern websites targeting Chrome 76+, `Blob#arrayBuffer` is recommended:
```js
-/* create new workbook */
-var workbook = XLSX.utils.book_new();
+// XLSX is a global from the standalone script
-/* convert table 'table1' to worksheet named "Sheet1" */
-var ws1 = XLSX.utils.table_to_sheet(document.getElementById('table1'));
-XLSX.utils.book_append_sheet(workbook, ws1, "Sheet1");
+async function handleFileAsync(e) {
+ const file = e.target.files[0];
+ const data = await file.arrayBuffer();
+ /* data is an ArrayBuffer */
+ const workbook = XLSX.read(data);
-/* convert table 'table2' to worksheet named "Sheet2" */
-var ws2 = XLSX.utils.table_to_sheet(document.getElementById('table2'));
-XLSX.utils.book_append_sheet(workbook, ws2, "Sheet2");
-
-/* workbook now has 2 worksheets */
+ /* DO SOMETHING WITH workbook HERE */
+}
+input_dom_element.addEventListener("change", handleFileAsync, false);
```
-Alternatively, the HTML code can be extracted and parsed:
+For broader support (including IE10+), the `FileReader` approach is recommended:
```js
-var htmlstr = document.getElementById('tableau').outerHTML;
-var workbook = XLSX.read(htmlstr, {type:'string'});
+function handleFile(e) {
+ var file = e.target.files[0];
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ var data = e.target.result;
+ /* reader.readAsArrayBuffer(file) -> data will be an ArrayBuffer */
+ var workbook = XLSX.read(e.target.result);
+
+ /* DO SOMETHING WITH workbook HERE */
+ };
+ reader.readAsArrayBuffer(file);
+}
+input_dom_element.addEventListener("change", handleFile, false);
```
+The [`oldie` demo](demos/oldie/) shows an IE-compatible fallback scenario.
+
- Browser download file (ajax) (click to show)
+ Fetching a file in the web browser ("Ajax") (click to show)
-Note: for a more complete example that works in older browsers, check the demo
-at . The [`xhr` demo](demos/xhr/)
-includes more examples with `XMLHttpRequest` and `fetch`.
+For modern websites targeting Chrome 42+, `fetch` is recommended:
+
+```js
+// XLSX is a global from the standalone script
+
+(async() => {
+ const url = "http://oss.sheetjs.com/test_files/formula_stress_test.xlsx";
+ const data = await (await fetch(url)).arrayBuffer();
+ /* data is an ArrayBuffer */
+ const workbook = XLSX.read(data);
+
+ /* DO SOMETHING WITH workbook HERE */
+})();
+```
+
+For broader support, the `XMLHttpRequest` approach is recommended:
```js
var url = "http://oss.sheetjs.com/test_files/formula_stress_test.xlsx";
@@ -434,148 +703,199 @@ req.onload = function(e) {
var workbook = XLSX.read(req.response);
/* DO SOMETHING WITH workbook HERE */
-}
+};
req.send();
```
+The [`xhr` demo](demos/xhr/) includes a longer discussion and more examples.
+
+ shows fallback approaches for IE6+.
+
- Browser drag-and-drop (click to show)
+ Local file in a PhotoShop or InDesign plugin (click to show)
-For modern browsers, `Blob#arrayBuffer` can read data from files:
+`readFile` wraps the `File` logic in Photoshop and other ExtendScript targets.
+The specified path should be an absolute path:
```js
-async function handleDropAsync(e) {
- e.stopPropagation(); e.preventDefault();
- const f = evt.dataTransfer.files[0];
- const data = await f.arrayBuffer();
- const workbook = XLSX.read(data);
+#include "xlsx.extendscript.js"
- /* DO SOMETHING WITH workbook HERE */
-}
-drop_dom_element.addEventListener('drop', handleDropAsync, false);
+/* Read test.xlsx from the Documents folder */
+var workbook = XLSX.readFile(Folder.myDocuments + "/test.xlsx");
```
-For maximal compatibility, the `FileReader` API should be used:
+The [`extendscript` demo](demos/extendscript/) includes a more complex example.
+
+
+
+
+ Local file in an Electron app (click to show)
+
+`readFile` can be used in the renderer process:
```js
-function handleDrop(e) {
- e.stopPropagation(); e.preventDefault();
- var f = e.dataTransfer.files[0];
- var reader = new FileReader();
- reader.onload = function(e) {
- var workbook = XLSX.read(e.target.result);
+/* From the renderer process */
+var XLSX = require("xlsx");
+
+var workbook = XLSX.readFile(path);
+```
+
+Electron APIs have changed over time. The [`electron` demo](demos/electron/)
+shows a complete example and details the required version-specific settings.
+
+
+
+
+ Local file in a mobile app with React Native (click to show)
+
+The [`react` demo](demos/react) includes a sample React Native app.
+
+Since React Native does not provide a way to read files from the filesystem, a
+third-party library must be used. The following libraries have been tested:
+
+- [`react-native-file-access`](https://npm.im/react-native-file-access)
+
+The `base64` encoding returns strings compatible with the `base64` type:
+
+```js
+import XLSX from "xlsx";
+import { FileSystem } from "react-native-file-access";
+
+const b64 = await FileSystem.readFile(path, "base64");
+/* b64 is a base64 string */
+const workbook = XLSX.read(b64, {type: "base64"});
+```
+
+- [`react-native-fs`](https://npm.im/react-native-fs)
+
+The `ascii` encoding returns binary strings compatible with the `binary` type:
+
+```js
+import XLSX from "xlsx";
+import { readFile } from "react-native-fs";
+
+const bstr = await readFile(path, "ascii");
+/* bstr is a binary string */
+const workbook = XLSX.read(bstr, {type: "binary"});
+```
+
+
+
+
+ NodeJS Server File Uploads (click to show)
+
+`read` can accept a NodeJS buffer. `readFile` can read files generated by a
+HTTP POST request body parser like [`formidable`](https://npm.im/formidable):
+
+```js
+const XLSX = require("xlsx");
+const http = require("http");
+const formidable = require("formidable");
+
+const server = http.createServer((req, res) => {
+ const form = new formidable.IncomingForm();
+ form.parse(req, (err, fields, files) => {
+ /* grab the first file */
+ const f = Object.entries(files)[0][1];
+ const path = f.filepath;
+ const workbook = XLSX.readFile(path);
/* DO SOMETHING WITH workbook HERE */
- };
- reader.readAsArrayBuffer(f);
-}
-drop_dom_element.addEventListener('drop', handleDrop, false);
+ });
+}).listen(process.env.PORT || 7262);
```
+The [`server` demo](demos/server) has more advanced examples.
+
- Browser file upload form element (click to show)
+ Download files in a NodeJS process (click to show)
-Data from file input elements can be processed using the same APIs as in the
-drag-and-drop example.
-
-Using `Blob#arrayBuffer`:
+Node 17.5 and 18.0 have native support for fetch:
```js
-async function handleFileAsync(e) {
- const file = e.target.files[0];
- const data = await file.arrayBuffer();
- const workbook = XLSX.read(data);
+const XLSX = require("xlsx");
+
+const data = await (await fetch(url)).arrayBuffer();
+/* data is an ArrayBuffer */
+const workbook = XLSX.read(data);
+```
+
+For broader compatibility, third-party modules are recommended.
+
+[`request`](https://npm.im/request) requires a `null` encoding to yield Buffers:
+
+```js
+var XLSX = require("xlsx");
+var request = require("request");
+
+request({url: url, encoding: null}, function(err, resp, body) {
+ var workbook = XLSX.read(body);
/* DO SOMETHING WITH workbook HERE */
-}
-input_dom_element.addEventListener('change', handleFileAsync, false);
+});
```
-Using `FileReader`:
+[`axios`](https://npm.im/axios) works the same way in browser and in NodeJS:
```js
-function handleFile(e) {
- var files = e.target.files, f = files[0];
- var reader = new FileReader();
- reader.onload = function(e) {
- var workbook = XLSX.read(e.target.result);
+const XLSX = require("xlsx");
+const axios = require("axios");
+
+(async() => {
+ const res = await axios.get(url, {responseType: "arraybuffer"});
+ /* res.data is a Buffer */
+ const workbook = XLSX.read(res.data);
+
+ /* DO SOMETHING WITH workbook HERE */
+})();
+```
+
+
+
+
+ Download files in an Electron app (click to show)
+
+The `net` module in the main process can make HTTP/HTTPS requests to external
+resources. Responses should be manually concatenated using `Buffer.concat`:
+
+```js
+const XLSX = require("xlsx");
+const { net } = require("electron");
+
+const req = net.request(url);
+req.on("response", (res) => {
+ const bufs = []; // this array will collect all of the buffers
+ res.on("data", (chunk) => { bufs.push(chunk); });
+ res.on("end", () => {
+ const workbook = XLSX.read(Buffer.concat(bufs));
/* DO SOMETHING WITH workbook HERE */
- };
- reader.readAsArrayBuffer(f);
-}
-input_dom_element.addEventListener('change', handleFile, false);
+ });
+});
+req.end();
```
-The [`oldie` demo](demos/oldie/) shows an IE-compatible fallback scenario.
-
-More specialized cases, including mobile app file processing, are covered in the
-[included demos](demos/)
-
-### Parsing Examples
-
-- HTML5 File API / Base64 Text / Web Workers
-
-Note that older versions of IE do not support HTML5 File API, so the Base64 mode
-is used for testing.
-
- Get Base64 encoding on OSX / Windows (click to show)
-
-On OSX you can get the Base64 encoding with:
-
-```bash
-$ certutil -encode target_file target_file.b64
-```
-
-(note: You have to open the file and remove the header and footer lines)
-
-
-
-- XMLHttpRequest
-
-### Streaming Read
-
-
- Why is there no Streaming Read API? (click to show)
-
-The most common and interesting formats (XLS, XLSX/M, XLSB, ODS) are ultimately
-ZIP or CFB containers of files. Neither format puts the directory structure at
-the beginning of the file: ZIP files place the Central Directory records at the
-end of the logical file, while CFB files can place the storage info anywhere in
-the file! As a result, to properly handle these formats, a streaming function
-would have to buffer the entire file before commencing. That belies the
-expectations of streaming, so we do not provide any streaming read API.
-
-
+ Readable Streams in NodeJS (click to show)
When dealing with Readable Streams, the easiest approach is to buffer the stream
-and process the whole thing at the end. This can be done with a temporary file
-or by explicitly concatenating the stream:
-
-
- Explicitly concatenating streams (click to show)
+and process the whole thing at the end:
```js
-var fs = require('fs');
-var XLSX = require('xlsx');
-function process_RS(stream/*:ReadStream*/, cb/*:(wb:Workbook)=>void*/)/*:void*/{
+var fs = require("fs");
+var XLSX = require("xlsx");
+
+function process_RS(stream, cb) {
var buffers = [];
- stream.on('data', function(data) { buffers.push(data); });
- stream.on('end', function() {
+ stream.on("data", function(data) { buffers.push(data); });
+ stream.on("end", function() {
var buffer = Buffer.concat(buffers);
var workbook = XLSX.read(buffer, {type:"buffer"});
@@ -585,31 +905,227 @@ function process_RS(stream/*:ReadStream*/, cb/*:(wb:Workbook)=>void*/)/*:void*/{
}
```
-More robust solutions are available using modules like `concat-stream`.
+
+
+
+ ReadableStream in the browser (click to show)
+
+When dealing with `ReadableStream`, the easiest approach is to buffer the stream
+and process the whole thing at the end:
+
+```js
+// XLSX is a global from the standalone script
+
+async function process_RS(stream) {
+ /* collect data */
+ const buffers = [];
+ const reader = stream.getReader();
+ for(;;) {
+ const res = await reader.read();
+ if(res.value) buffers.push(res.value);
+ if(res.done) break;
+ }
+
+ /* concat */
+ const out = new Uint8Array(buffers.reduce((acc, v) => acc + v.length, 0));
+
+ let off = 0;
+ for(const u8 of arr) {
+ out.set(u8, off);
+ off += u8.length;
+ }
+
+ return out;
+}
+
+const data = await process_RS(stream);
+/* data is Uint8Array */
+const workbook = XLSX.read(data);
+```
+
+
+
+More detailed examples are covered in the [included demos](demos/)
+
+
+### Processing JSON and JS Data
+
+JSON and JS data tend to represent single worksheets. This section will use a
+few utility functions to generate workbooks:
+
+_Create a new Worksheet_
+
+```js
+var workbook = XLSX.utils.book_new();
+```
+
+The `book_new` utility function creates an empty workbook with no worksheets.
+
+
+_Append a Worksheet to a Workbook_
+
+```js
+XLSX.utils.book_append_sheet(workbook, worksheet, sheet_name);
+```
+
+The `book_append_sheet` utility function appends a worksheet to the workbook.
+The third argument specifies the desired worksheet name. Multiple worksheets can
+be added to a workbook by calling the function multiple times.
+
+
+#### API
+
+_Create a worksheet from an array of arrays of JS values_
+
+```js
+var worksheet = XLSX.utils.aoa_to_sheet(aoa, opts);
+```
+
+The `aoa_to_sheet` utility function walks an "array of arrays" in row-major
+order, generating a worksheet object. The following snippet generates a sheet
+with cell `A1` set to the string `A1`, cell `B1` set to `B2`, etc:
+
+```js
+var worksheet = XLSX.utils.aoa_to_sheet([
+ ["A1", "B1", "C1"],
+ ["A2", "B2", "C2"],
+ ["A3", "B3", "C3"]
+])
+```
+
+["Array of Arrays Input"](#array-of-arrays-input) describes the function and the
+optional `opts` argument in more detail.
+
+
+_Create a worksheet from an array of JS objects_
+
+```js
+var worksheet = XLSX.utils.json_to_sheet(jsa, opts);
+```
+
+The `json_to_sheet` utility function walks an array of JS objects in order,
+generating a worksheet object. By default, it will generate a header row and
+one row per object in the array. The optional `opts` argument has settings to
+control the column order and header output.
+
+["Array of Objects Input"](#array-of-arrays-input) describes the function and
+the optional `opts` argument in more detail.
+
+#### Examples
+
+["Zen of SheetJS"](#the-zen-of-sheetjs) contains a detailed example "Get Data
+from a JSON Endpoint and Generate a Workbook"
+
+The [`database` demo](/demos/database/) includes examples of working with
+databases and query results.
+
+### Processing HTML Tables
+
+#### API
+
+_Create a worksheet by scraping an HTML TABLE in the page_
+
+```js
+var worksheet = XLSX.utils.table_to_sheet(dom_element, opts);
+```
+
+The `table_to_sheet` utility function takes a DOM TABLE element and iterates
+through the rows to generate a worksheet. The `opts` argument is optional.
+["HTML Table Input"](#html-table-input) describes the function in more detail.
+
+
+
+_Create a workbook by scraping an HTML TABLE in the page_
+
+```js
+var workbook = XLSX.utils.table_to_book(dom_element, opts);
+```
+
+The `table_to_book` utility function follows the same logic as `table_to_sheet`.
+After generating a worksheet, it creates a blank workbook and appends the
+spreadsheet.
+
+The options argument supports the same options as `table_to_sheet`, with the
+addition of a `sheet` property to control the worksheet name. If the property
+is missing or no options are specified, the default name `Sheet1` is used.
+
+#### Examples
+
+Here are a few common scenarios (click on each subtitle to see the code):
+
+
+ HTML TABLE element in a webpage (click to show)
+
+```html
+
+
+
+
+
+
+
Sheet
JS
+
12345
67
+
+
+
+
+```
+
+Multiple tables on a web page can be converted to individual worksheets:
+
+```js
+/* create new workbook */
+var workbook = XLSX.utils.book_new();
+
+/* convert table "table1" to worksheet named "Sheet1" */
+var sheet1 = XLSX.utils.table_to_sheet(document.getElementById("table1"));
+XLSX.utils.book_append_sheet(workbook, sheet1, "Sheet1");
+
+/* convert table "table2" to worksheet named "Sheet2" */
+var sheet2 = XLSX.utils.table_to_sheet(document.getElementById("table2"));
+XLSX.utils.book_append_sheet(workbook, sheet2, "Sheet2");
+
+/* workbook now has 2 worksheets */
+```
+
+Alternatively, the HTML code can be extracted and parsed:
+
+```js
+var htmlstr = document.getElementById("tableau").outerHTML;
+var workbook = XLSX.read(htmlstr, {type:"string"});
+```
- Writing to filesystem first (click to show)
+ Chrome/Chromium Extension (click to show)
-This example uses [`tempfile`](https://npm.im/tempfile) to generate file names:
+The [`chrome` demo](demos/chrome/) shows a complete example and details the
+required permissions and other settings.
+
+In an extension, it is recommended to generate the workbook in a content script
+and pass the object back to the extension:
```js
-var fs = require('fs'), tempfile = require('tempfile');
-var XLSX = require('xlsx');
-function process_RS(stream/*:ReadStream*/, cb/*:(wb:Workbook)=>void*/)/*:void*/{
- var fname = tempfile('.sheetjs');
- console.log(fname);
- var ostream = fs.createWriteStream(fname);
- stream.pipe(ostream);
- ostream.on('finish', function() {
- var workbook = XLSX.readFile(fname);
- fs.unlinkSync(fname);
-
- /* DO SOMETHING WITH workbook IN THE CALLBACK */
- cb(workbook);
- });
-}
+/* in the worker script */
+chrome.runtime.onMessage.addListener(function(msg, sender, cb) {
+ /* pass a message like { sheetjs: true } from the extension to scrape */
+ if(!msg || !msg.sheetjs) return;
+ /* create a new workbook */
+ var workbook = XLSX.utils.book_new();
+ /* loop through each table element */
+ var tables = document.getElementsByTagName("table")
+ for(var i = 0; i < tables.length; ++i) {
+ var worksheet = XLSX.utils.table_to_sheet(tables[i]);
+ XLSX.utils.book_append_sheet(workbook, worksheet, "Table" + i);
+ }
+ /* pass back to the extension */
+ return cb(workbook);
+});
```
diff --git a/bits/59_vba.js b/bits/59_vba.js
index 3f69886..5102ba5 100644
--- a/bits/59_vba.js
+++ b/bits/59_vba.js
@@ -1,21 +1,21 @@
var CT_VBA = "application/vnd.ms-office.vbaProject";
-function make_vba_xls(cfb/*:CFBContainer*/) {
- var newcfb = CFB.utils.cfb_new({root:"R"});
- cfb.FullPaths.forEach(function(p, i) {
- if(p.slice(-1) === "/" || !p.match(/_VBA_PROJECT_CUR/)) return;
- var newpath = p.replace(/^[^\/]*/,"R").replace(/\/_VBA_PROJECT_CUR\u0000*/, "");
- CFB.utils.cfb_add(newcfb, newpath, cfb.FileIndex[i].content);
- });
- return CFB.write(newcfb);
+function make_vba_xls(cfb) {
+ var newcfb = CFB.utils.cfb_new({ root: "R" });
+ cfb.FullPaths.forEach(function(p, i) {
+ if (p.slice(-1) === "/" || !p.match(/_VBA_PROJECT_CUR/))
+ return;
+ var newpath = p.replace(/^[^\/]*/, "R").replace(/\/_VBA_PROJECT_CUR\u0000*/, "");
+ CFB.utils.cfb_add(newcfb, newpath, cfb.FileIndex[i].content);
+ });
+ return CFB.write(newcfb);
}
-
-function fill_vba_xls(cfb/*:CFBContainer*/, vba/*:CFBContainer*/)/*:void*/ {
- vba.FullPaths.forEach(function(p, i) {
- if(i == 0) return;
- var newpath = p.replace(/[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
- if(newpath.slice(-1) !== "/") CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content);
- });
+function fill_vba_xls(cfb, vba) {
+ vba.FullPaths.forEach(function(p, i) {
+ if (i == 0)
+ return;
+ var newpath = p.replace(/[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
+ if (newpath.slice(-1) !== "/")
+ CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content);
+ });
}
-
-var VBAFMTS = [ "xlsb", "xlsm", "xlam", "biff8", "xla" ];
-
+var VBAFMTS = ["xlsb", "xlsm", "xlam", "biff8", "xla"];
diff --git a/bits/62_fxls.js b/bits/62_fxls.js
index 61551a8..eb56dc0 100644
--- a/bits/62_fxls.js
+++ b/bits/62_fxls.js
@@ -869,7 +869,8 @@ function stringify_formula(formula/*Array*/, range, cell/*:any*/, supbooks,
nameidx = (f[1][2]/*:any*/);
var lbl = (supbooks.names||[])[nameidx-1] || (supbooks[0]||[])[nameidx];
var name = lbl ? lbl.Name : "SH33TJSNAME" + String(nameidx);
- if(name in XLSXFutureFunctions) name = XLSXFutureFunctions[name];
+ /* [MS-XLSB] 2.5.97.10 Ftab -- last verified 20220204 */
+ if(name && name.slice(0,6) == "_xlfn.") name = name.slice(6);
stack.push(name);
break;
diff --git a/bits/64_ftab.js b/bits/64_ftab.js
index bb3fa0b..ac7c719 100644
--- a/bits/64_ftab.js
+++ b/bits/64_ftab.js
@@ -1,1272 +1,1133 @@
-/* [MS-XLS] 2.5.198.4 */
var Cetab = {
- /*::[*/0x0000/*::]*/: 'BEEP',
- /*::[*/0x0001/*::]*/: 'OPEN',
- /*::[*/0x0002/*::]*/: 'OPEN.LINKS',
- /*::[*/0x0003/*::]*/: 'CLOSE.ALL',
- /*::[*/0x0004/*::]*/: 'SAVE',
- /*::[*/0x0005/*::]*/: 'SAVE.AS',
- /*::[*/0x0006/*::]*/: 'FILE.DELETE',
- /*::[*/0x0007/*::]*/: 'PAGE.SETUP',
- /*::[*/0x0008/*::]*/: 'PRINT',
- /*::[*/0x0009/*::]*/: 'PRINTER.SETUP',
- /*::[*/0x000A/*::]*/: 'QUIT',
- /*::[*/0x000B/*::]*/: 'NEW.WINDOW',
- /*::[*/0x000C/*::]*/: 'ARRANGE.ALL',
- /*::[*/0x000D/*::]*/: 'WINDOW.SIZE',
- /*::[*/0x000E/*::]*/: 'WINDOW.MOVE',
- /*::[*/0x000F/*::]*/: 'FULL',
- /*::[*/0x0010/*::]*/: 'CLOSE',
- /*::[*/0x0011/*::]*/: 'RUN',
- /*::[*/0x0016/*::]*/: 'SET.PRINT.AREA',
- /*::[*/0x0017/*::]*/: 'SET.PRINT.TITLES',
- /*::[*/0x0018/*::]*/: 'SET.PAGE.BREAK',
- /*::[*/0x0019/*::]*/: 'REMOVE.PAGE.BREAK',
- /*::[*/0x001A/*::]*/: 'FONT',
- /*::[*/0x001B/*::]*/: 'DISPLAY',
- /*::[*/0x001C/*::]*/: 'PROTECT.DOCUMENT',
- /*::[*/0x001D/*::]*/: 'PRECISION',
- /*::[*/0x001E/*::]*/: 'A1.R1C1',
- /*::[*/0x001F/*::]*/: 'CALCULATE.NOW',
- /*::[*/0x0020/*::]*/: 'CALCULATION',
- /*::[*/0x0022/*::]*/: 'DATA.FIND',
- /*::[*/0x0023/*::]*/: 'EXTRACT',
- /*::[*/0x0024/*::]*/: 'DATA.DELETE',
- /*::[*/0x0025/*::]*/: 'SET.DATABASE',
- /*::[*/0x0026/*::]*/: 'SET.CRITERIA',
- /*::[*/0x0027/*::]*/: 'SORT',
- /*::[*/0x0028/*::]*/: 'DATA.SERIES',
- /*::[*/0x0029/*::]*/: 'TABLE',
- /*::[*/0x002A/*::]*/: 'FORMAT.NUMBER',
- /*::[*/0x002B/*::]*/: 'ALIGNMENT',
- /*::[*/0x002C/*::]*/: 'STYLE',
- /*::[*/0x002D/*::]*/: 'BORDER',
- /*::[*/0x002E/*::]*/: 'CELL.PROTECTION',
- /*::[*/0x002F/*::]*/: 'COLUMN.WIDTH',
- /*::[*/0x0030/*::]*/: 'UNDO',
- /*::[*/0x0031/*::]*/: 'CUT',
- /*::[*/0x0032/*::]*/: 'COPY',
- /*::[*/0x0033/*::]*/: 'PASTE',
- /*::[*/0x0034/*::]*/: 'CLEAR',
- /*::[*/0x0035/*::]*/: 'PASTE.SPECIAL',
- /*::[*/0x0036/*::]*/: 'EDIT.DELETE',
- /*::[*/0x0037/*::]*/: 'INSERT',
- /*::[*/0x0038/*::]*/: 'FILL.RIGHT',
- /*::[*/0x0039/*::]*/: 'FILL.DOWN',
- /*::[*/0x003D/*::]*/: 'DEFINE.NAME',
- /*::[*/0x003E/*::]*/: 'CREATE.NAMES',
- /*::[*/0x003F/*::]*/: 'FORMULA.GOTO',
- /*::[*/0x0040/*::]*/: 'FORMULA.FIND',
- /*::[*/0x0041/*::]*/: 'SELECT.LAST.CELL',
- /*::[*/0x0042/*::]*/: 'SHOW.ACTIVE.CELL',
- /*::[*/0x0043/*::]*/: 'GALLERY.AREA',
- /*::[*/0x0044/*::]*/: 'GALLERY.BAR',
- /*::[*/0x0045/*::]*/: 'GALLERY.COLUMN',
- /*::[*/0x0046/*::]*/: 'GALLERY.LINE',
- /*::[*/0x0047/*::]*/: 'GALLERY.PIE',
- /*::[*/0x0048/*::]*/: 'GALLERY.SCATTER',
- /*::[*/0x0049/*::]*/: 'COMBINATION',
- /*::[*/0x004A/*::]*/: 'PREFERRED',
- /*::[*/0x004B/*::]*/: 'ADD.OVERLAY',
- /*::[*/0x004C/*::]*/: 'GRIDLINES',
- /*::[*/0x004D/*::]*/: 'SET.PREFERRED',
- /*::[*/0x004E/*::]*/: 'AXES',
- /*::[*/0x004F/*::]*/: 'LEGEND',
- /*::[*/0x0050/*::]*/: 'ATTACH.TEXT',
- /*::[*/0x0051/*::]*/: 'ADD.ARROW',
- /*::[*/0x0052/*::]*/: 'SELECT.CHART',
- /*::[*/0x0053/*::]*/: 'SELECT.PLOT.AREA',
- /*::[*/0x0054/*::]*/: 'PATTERNS',
- /*::[*/0x0055/*::]*/: 'MAIN.CHART',
- /*::[*/0x0056/*::]*/: 'OVERLAY',
- /*::[*/0x0057/*::]*/: 'SCALE',
- /*::[*/0x0058/*::]*/: 'FORMAT.LEGEND',
- /*::[*/0x0059/*::]*/: 'FORMAT.TEXT',
- /*::[*/0x005A/*::]*/: 'EDIT.REPEAT',
- /*::[*/0x005B/*::]*/: 'PARSE',
- /*::[*/0x005C/*::]*/: 'JUSTIFY',
- /*::[*/0x005D/*::]*/: 'HIDE',
- /*::[*/0x005E/*::]*/: 'UNHIDE',
- /*::[*/0x005F/*::]*/: 'WORKSPACE',
- /*::[*/0x0060/*::]*/: 'FORMULA',
- /*::[*/0x0061/*::]*/: 'FORMULA.FILL',
- /*::[*/0x0062/*::]*/: 'FORMULA.ARRAY',
- /*::[*/0x0063/*::]*/: 'DATA.FIND.NEXT',
- /*::[*/0x0064/*::]*/: 'DATA.FIND.PREV',
- /*::[*/0x0065/*::]*/: 'FORMULA.FIND.NEXT',
- /*::[*/0x0066/*::]*/: 'FORMULA.FIND.PREV',
- /*::[*/0x0067/*::]*/: 'ACTIVATE',
- /*::[*/0x0068/*::]*/: 'ACTIVATE.NEXT',
- /*::[*/0x0069/*::]*/: 'ACTIVATE.PREV',
- /*::[*/0x006A/*::]*/: 'UNLOCKED.NEXT',
- /*::[*/0x006B/*::]*/: 'UNLOCKED.PREV',
- /*::[*/0x006C/*::]*/: 'COPY.PICTURE',
- /*::[*/0x006D/*::]*/: 'SELECT',
- /*::[*/0x006E/*::]*/: 'DELETE.NAME',
- /*::[*/0x006F/*::]*/: 'DELETE.FORMAT',
- /*::[*/0x0070/*::]*/: 'VLINE',
- /*::[*/0x0071/*::]*/: 'HLINE',
- /*::[*/0x0072/*::]*/: 'VPAGE',
- /*::[*/0x0073/*::]*/: 'HPAGE',
- /*::[*/0x0074/*::]*/: 'VSCROLL',
- /*::[*/0x0075/*::]*/: 'HSCROLL',
- /*::[*/0x0076/*::]*/: 'ALERT',
- /*::[*/0x0077/*::]*/: 'NEW',
- /*::[*/0x0078/*::]*/: 'CANCEL.COPY',
- /*::[*/0x0079/*::]*/: 'SHOW.CLIPBOARD',
- /*::[*/0x007A/*::]*/: 'MESSAGE',
- /*::[*/0x007C/*::]*/: 'PASTE.LINK',
- /*::[*/0x007D/*::]*/: 'APP.ACTIVATE',
- /*::[*/0x007E/*::]*/: 'DELETE.ARROW',
- /*::[*/0x007F/*::]*/: 'ROW.HEIGHT',
- /*::[*/0x0080/*::]*/: 'FORMAT.MOVE',
- /*::[*/0x0081/*::]*/: 'FORMAT.SIZE',
- /*::[*/0x0082/*::]*/: 'FORMULA.REPLACE',
- /*::[*/0x0083/*::]*/: 'SEND.KEYS',
- /*::[*/0x0084/*::]*/: 'SELECT.SPECIAL',
- /*::[*/0x0085/*::]*/: 'APPLY.NAMES',
- /*::[*/0x0086/*::]*/: 'REPLACE.FONT',
- /*::[*/0x0087/*::]*/: 'FREEZE.PANES',
- /*::[*/0x0088/*::]*/: 'SHOW.INFO',
- /*::[*/0x0089/*::]*/: 'SPLIT',
- /*::[*/0x008A/*::]*/: 'ON.WINDOW',
- /*::[*/0x008B/*::]*/: 'ON.DATA',
- /*::[*/0x008C/*::]*/: 'DISABLE.INPUT',
- /*::[*/0x008E/*::]*/: 'OUTLINE',
- /*::[*/0x008F/*::]*/: 'LIST.NAMES',
- /*::[*/0x0090/*::]*/: 'FILE.CLOSE',
- /*::[*/0x0091/*::]*/: 'SAVE.WORKBOOK',
- /*::[*/0x0092/*::]*/: 'DATA.FORM',
- /*::[*/0x0093/*::]*/: 'COPY.CHART',
- /*::[*/0x0094/*::]*/: 'ON.TIME',
- /*::[*/0x0095/*::]*/: 'WAIT',
- /*::[*/0x0096/*::]*/: 'FORMAT.FONT',
- /*::[*/0x0097/*::]*/: 'FILL.UP',
- /*::[*/0x0098/*::]*/: 'FILL.LEFT',
- /*::[*/0x0099/*::]*/: 'DELETE.OVERLAY',
- /*::[*/0x009B/*::]*/: 'SHORT.MENUS',
- /*::[*/0x009F/*::]*/: 'SET.UPDATE.STATUS',
- /*::[*/0x00A1/*::]*/: 'COLOR.PALETTE',
- /*::[*/0x00A2/*::]*/: 'DELETE.STYLE',
- /*::[*/0x00A3/*::]*/: 'WINDOW.RESTORE',
- /*::[*/0x00A4/*::]*/: 'WINDOW.MAXIMIZE',
- /*::[*/0x00A6/*::]*/: 'CHANGE.LINK',
- /*::[*/0x00A7/*::]*/: 'CALCULATE.DOCUMENT',
- /*::[*/0x00A8/*::]*/: 'ON.KEY',
- /*::[*/0x00A9/*::]*/: 'APP.RESTORE',
- /*::[*/0x00AA/*::]*/: 'APP.MOVE',
- /*::[*/0x00AB/*::]*/: 'APP.SIZE',
- /*::[*/0x00AC/*::]*/: 'APP.MINIMIZE',
- /*::[*/0x00AD/*::]*/: 'APP.MAXIMIZE',
- /*::[*/0x00AE/*::]*/: 'BRING.TO.FRONT',
- /*::[*/0x00AF/*::]*/: 'SEND.TO.BACK',
- /*::[*/0x00B9/*::]*/: 'MAIN.CHART.TYPE',
- /*::[*/0x00BA/*::]*/: 'OVERLAY.CHART.TYPE',
- /*::[*/0x00BB/*::]*/: 'SELECT.END',
- /*::[*/0x00BC/*::]*/: 'OPEN.MAIL',
- /*::[*/0x00BD/*::]*/: 'SEND.MAIL',
- /*::[*/0x00BE/*::]*/: 'STANDARD.FONT',
- /*::[*/0x00BF/*::]*/: 'CONSOLIDATE',
- /*::[*/0x00C0/*::]*/: 'SORT.SPECIAL',
- /*::[*/0x00C1/*::]*/: 'GALLERY.3D.AREA',
- /*::[*/0x00C2/*::]*/: 'GALLERY.3D.COLUMN',
- /*::[*/0x00C3/*::]*/: 'GALLERY.3D.LINE',
- /*::[*/0x00C4/*::]*/: 'GALLERY.3D.PIE',
- /*::[*/0x00C5/*::]*/: 'VIEW.3D',
- /*::[*/0x00C6/*::]*/: 'GOAL.SEEK',
- /*::[*/0x00C7/*::]*/: 'WORKGROUP',
- /*::[*/0x00C8/*::]*/: 'FILL.GROUP',
- /*::[*/0x00C9/*::]*/: 'UPDATE.LINK',
- /*::[*/0x00CA/*::]*/: 'PROMOTE',
- /*::[*/0x00CB/*::]*/: 'DEMOTE',
- /*::[*/0x00CC/*::]*/: 'SHOW.DETAIL',
- /*::[*/0x00CE/*::]*/: 'UNGROUP',
- /*::[*/0x00CF/*::]*/: 'OBJECT.PROPERTIES',
- /*::[*/0x00D0/*::]*/: 'SAVE.NEW.OBJECT',
- /*::[*/0x00D1/*::]*/: 'SHARE',
- /*::[*/0x00D2/*::]*/: 'SHARE.NAME',
- /*::[*/0x00D3/*::]*/: 'DUPLICATE',
- /*::[*/0x00D4/*::]*/: 'APPLY.STYLE',
- /*::[*/0x00D5/*::]*/: 'ASSIGN.TO.OBJECT',
- /*::[*/0x00D6/*::]*/: 'OBJECT.PROTECTION',
- /*::[*/0x00D7/*::]*/: 'HIDE.OBJECT',
- /*::[*/0x00D8/*::]*/: 'SET.EXTRACT',
- /*::[*/0x00D9/*::]*/: 'CREATE.PUBLISHER',
- /*::[*/0x00DA/*::]*/: 'SUBSCRIBE.TO',
- /*::[*/0x00DB/*::]*/: 'ATTRIBUTES',
- /*::[*/0x00DC/*::]*/: 'SHOW.TOOLBAR',
- /*::[*/0x00DE/*::]*/: 'PRINT.PREVIEW',
- /*::[*/0x00DF/*::]*/: 'EDIT.COLOR',
- /*::[*/0x00E0/*::]*/: 'SHOW.LEVELS',
- /*::[*/0x00E1/*::]*/: 'FORMAT.MAIN',
- /*::[*/0x00E2/*::]*/: 'FORMAT.OVERLAY',
- /*::[*/0x00E3/*::]*/: 'ON.RECALC',
- /*::[*/0x00E4/*::]*/: 'EDIT.SERIES',
- /*::[*/0x00E5/*::]*/: 'DEFINE.STYLE',
- /*::[*/0x00F0/*::]*/: 'LINE.PRINT',
- /*::[*/0x00F3/*::]*/: 'ENTER.DATA',
- /*::[*/0x00F9/*::]*/: 'GALLERY.RADAR',
- /*::[*/0x00FA/*::]*/: 'MERGE.STYLES',
- /*::[*/0x00FB/*::]*/: 'EDITION.OPTIONS',
- /*::[*/0x00FC/*::]*/: 'PASTE.PICTURE',
- /*::[*/0x00FD/*::]*/: 'PASTE.PICTURE.LINK',
- /*::[*/0x00FE/*::]*/: 'SPELLING',
- /*::[*/0x0100/*::]*/: 'ZOOM',
- /*::[*/0x0103/*::]*/: 'INSERT.OBJECT',
- /*::[*/0x0104/*::]*/: 'WINDOW.MINIMIZE',
- /*::[*/0x0109/*::]*/: 'SOUND.NOTE',
- /*::[*/0x010A/*::]*/: 'SOUND.PLAY',
- /*::[*/0x010B/*::]*/: 'FORMAT.SHAPE',
- /*::[*/0x010C/*::]*/: 'EXTEND.POLYGON',
- /*::[*/0x010D/*::]*/: 'FORMAT.AUTO',
- /*::[*/0x0110/*::]*/: 'GALLERY.3D.BAR',
- /*::[*/0x0111/*::]*/: 'GALLERY.3D.SURFACE',
- /*::[*/0x0112/*::]*/: 'FILL.AUTO',
- /*::[*/0x0114/*::]*/: 'CUSTOMIZE.TOOLBAR',
- /*::[*/0x0115/*::]*/: 'ADD.TOOL',
- /*::[*/0x0116/*::]*/: 'EDIT.OBJECT',
- /*::[*/0x0117/*::]*/: 'ON.DOUBLECLICK',
- /*::[*/0x0118/*::]*/: 'ON.ENTRY',
- /*::[*/0x0119/*::]*/: 'WORKBOOK.ADD',
- /*::[*/0x011A/*::]*/: 'WORKBOOK.MOVE',
- /*::[*/0x011B/*::]*/: 'WORKBOOK.COPY',
- /*::[*/0x011C/*::]*/: 'WORKBOOK.OPTIONS',
- /*::[*/0x011D/*::]*/: 'SAVE.WORKSPACE',
- /*::[*/0x0120/*::]*/: 'CHART.WIZARD',
- /*::[*/0x0121/*::]*/: 'DELETE.TOOL',
- /*::[*/0x0122/*::]*/: 'MOVE.TOOL',
- /*::[*/0x0123/*::]*/: 'WORKBOOK.SELECT',
- /*::[*/0x0124/*::]*/: 'WORKBOOK.ACTIVATE',
- /*::[*/0x0125/*::]*/: 'ASSIGN.TO.TOOL',
- /*::[*/0x0127/*::]*/: 'COPY.TOOL',
- /*::[*/0x0128/*::]*/: 'RESET.TOOL',
- /*::[*/0x0129/*::]*/: 'CONSTRAIN.NUMERIC',
- /*::[*/0x012A/*::]*/: 'PASTE.TOOL',
- /*::[*/0x012E/*::]*/: 'WORKBOOK.NEW',
- /*::[*/0x0131/*::]*/: 'SCENARIO.CELLS',
- /*::[*/0x0132/*::]*/: 'SCENARIO.DELETE',
- /*::[*/0x0133/*::]*/: 'SCENARIO.ADD',
- /*::[*/0x0134/*::]*/: 'SCENARIO.EDIT',
- /*::[*/0x0135/*::]*/: 'SCENARIO.SHOW',
- /*::[*/0x0136/*::]*/: 'SCENARIO.SHOW.NEXT',
- /*::[*/0x0137/*::]*/: 'SCENARIO.SUMMARY',
- /*::[*/0x0138/*::]*/: 'PIVOT.TABLE.WIZARD',
- /*::[*/0x0139/*::]*/: 'PIVOT.FIELD.PROPERTIES',
- /*::[*/0x013A/*::]*/: 'PIVOT.FIELD',
- /*::[*/0x013B/*::]*/: 'PIVOT.ITEM',
- /*::[*/0x013C/*::]*/: 'PIVOT.ADD.FIELDS',
- /*::[*/0x013E/*::]*/: 'OPTIONS.CALCULATION',
- /*::[*/0x013F/*::]*/: 'OPTIONS.EDIT',
- /*::[*/0x0140/*::]*/: 'OPTIONS.VIEW',
- /*::[*/0x0141/*::]*/: 'ADDIN.MANAGER',
- /*::[*/0x0142/*::]*/: 'MENU.EDITOR',
- /*::[*/0x0143/*::]*/: 'ATTACH.TOOLBARS',
- /*::[*/0x0144/*::]*/: 'VBAActivate',
- /*::[*/0x0145/*::]*/: 'OPTIONS.CHART',
- /*::[*/0x0148/*::]*/: 'VBA.INSERT.FILE',
- /*::[*/0x014A/*::]*/: 'VBA.PROCEDURE.DEFINITION',
- /*::[*/0x0150/*::]*/: 'ROUTING.SLIP',
- /*::[*/0x0152/*::]*/: 'ROUTE.DOCUMENT',
- /*::[*/0x0153/*::]*/: 'MAIL.LOGON',
- /*::[*/0x0156/*::]*/: 'INSERT.PICTURE',
- /*::[*/0x0157/*::]*/: 'EDIT.TOOL',
- /*::[*/0x0158/*::]*/: 'GALLERY.DOUGHNUT',
- /*::[*/0x015E/*::]*/: 'CHART.TREND',
- /*::[*/0x0160/*::]*/: 'PIVOT.ITEM.PROPERTIES',
- /*::[*/0x0162/*::]*/: 'WORKBOOK.INSERT',
- /*::[*/0x0163/*::]*/: 'OPTIONS.TRANSITION',
- /*::[*/0x0164/*::]*/: 'OPTIONS.GENERAL',
- /*::[*/0x0172/*::]*/: 'FILTER.ADVANCED',
- /*::[*/0x0175/*::]*/: 'MAIL.ADD.MAILER',
- /*::[*/0x0176/*::]*/: 'MAIL.DELETE.MAILER',
- /*::[*/0x0177/*::]*/: 'MAIL.REPLY',
- /*::[*/0x0178/*::]*/: 'MAIL.REPLY.ALL',
- /*::[*/0x0179/*::]*/: 'MAIL.FORWARD',
- /*::[*/0x017A/*::]*/: 'MAIL.NEXT.LETTER',
- /*::[*/0x017B/*::]*/: 'DATA.LABEL',
- /*::[*/0x017C/*::]*/: 'INSERT.TITLE',
- /*::[*/0x017D/*::]*/: 'FONT.PROPERTIES',
- /*::[*/0x017E/*::]*/: 'MACRO.OPTIONS',
- /*::[*/0x017F/*::]*/: 'WORKBOOK.HIDE',
- /*::[*/0x0180/*::]*/: 'WORKBOOK.UNHIDE',
- /*::[*/0x0181/*::]*/: 'WORKBOOK.DELETE',
- /*::[*/0x0182/*::]*/: 'WORKBOOK.NAME',
- /*::[*/0x0184/*::]*/: 'GALLERY.CUSTOM',
- /*::[*/0x0186/*::]*/: 'ADD.CHART.AUTOFORMAT',
- /*::[*/0x0187/*::]*/: 'DELETE.CHART.AUTOFORMAT',
- /*::[*/0x0188/*::]*/: 'CHART.ADD.DATA',
- /*::[*/0x0189/*::]*/: 'AUTO.OUTLINE',
- /*::[*/0x018A/*::]*/: 'TAB.ORDER',
- /*::[*/0x018B/*::]*/: 'SHOW.DIALOG',
- /*::[*/0x018C/*::]*/: 'SELECT.ALL',
- /*::[*/0x018D/*::]*/: 'UNGROUP.SHEETS',
- /*::[*/0x018E/*::]*/: 'SUBTOTAL.CREATE',
- /*::[*/0x018F/*::]*/: 'SUBTOTAL.REMOVE',
- /*::[*/0x0190/*::]*/: 'RENAME.OBJECT',
- /*::[*/0x019C/*::]*/: 'WORKBOOK.SCROLL',
- /*::[*/0x019D/*::]*/: 'WORKBOOK.NEXT',
- /*::[*/0x019E/*::]*/: 'WORKBOOK.PREV',
- /*::[*/0x019F/*::]*/: 'WORKBOOK.TAB.SPLIT',
- /*::[*/0x01A0/*::]*/: 'FULL.SCREEN',
- /*::[*/0x01A1/*::]*/: 'WORKBOOK.PROTECT',
- /*::[*/0x01A4/*::]*/: 'SCROLLBAR.PROPERTIES',
- /*::[*/0x01A5/*::]*/: 'PIVOT.SHOW.PAGES',
- /*::[*/0x01A6/*::]*/: 'TEXT.TO.COLUMNS',
- /*::[*/0x01A7/*::]*/: 'FORMAT.CHARTTYPE',
- /*::[*/0x01A8/*::]*/: 'LINK.FORMAT',
- /*::[*/0x01A9/*::]*/: 'TRACER.DISPLAY',
- /*::[*/0x01AE/*::]*/: 'TRACER.NAVIGATE',
- /*::[*/0x01AF/*::]*/: 'TRACER.CLEAR',
- /*::[*/0x01B0/*::]*/: 'TRACER.ERROR',
- /*::[*/0x01B1/*::]*/: 'PIVOT.FIELD.GROUP',
- /*::[*/0x01B2/*::]*/: 'PIVOT.FIELD.UNGROUP',
- /*::[*/0x01B3/*::]*/: 'CHECKBOX.PROPERTIES',
- /*::[*/0x01B4/*::]*/: 'LABEL.PROPERTIES',
- /*::[*/0x01B5/*::]*/: 'LISTBOX.PROPERTIES',
- /*::[*/0x01B6/*::]*/: 'EDITBOX.PROPERTIES',
- /*::[*/0x01B7/*::]*/: 'PIVOT.REFRESH',
- /*::[*/0x01B8/*::]*/: 'LINK.COMBO',
- /*::[*/0x01B9/*::]*/: 'OPEN.TEXT',
- /*::[*/0x01BA/*::]*/: 'HIDE.DIALOG',
- /*::[*/0x01BB/*::]*/: 'SET.DIALOG.FOCUS',
- /*::[*/0x01BC/*::]*/: 'ENABLE.OBJECT',
- /*::[*/0x01BD/*::]*/: 'PUSHBUTTON.PROPERTIES',
- /*::[*/0x01BE/*::]*/: 'SET.DIALOG.DEFAULT',
- /*::[*/0x01BF/*::]*/: 'FILTER',
- /*::[*/0x01C0/*::]*/: 'FILTER.SHOW.ALL',
- /*::[*/0x01C1/*::]*/: 'CLEAR.OUTLINE',
- /*::[*/0x01C2/*::]*/: 'FUNCTION.WIZARD',
- /*::[*/0x01C3/*::]*/: 'ADD.LIST.ITEM',
- /*::[*/0x01C4/*::]*/: 'SET.LIST.ITEM',
- /*::[*/0x01C5/*::]*/: 'REMOVE.LIST.ITEM',
- /*::[*/0x01C6/*::]*/: 'SELECT.LIST.ITEM',
- /*::[*/0x01C7/*::]*/: 'SET.CONTROL.VALUE',
- /*::[*/0x01C8/*::]*/: 'SAVE.COPY.AS',
- /*::[*/0x01CA/*::]*/: 'OPTIONS.LISTS.ADD',
- /*::[*/0x01CB/*::]*/: 'OPTIONS.LISTS.DELETE',
- /*::[*/0x01CC/*::]*/: 'SERIES.AXES',
- /*::[*/0x01CD/*::]*/: 'SERIES.X',
- /*::[*/0x01CE/*::]*/: 'SERIES.Y',
- /*::[*/0x01CF/*::]*/: 'ERRORBAR.X',
- /*::[*/0x01D0/*::]*/: 'ERRORBAR.Y',
- /*::[*/0x01D1/*::]*/: 'FORMAT.CHART',
- /*::[*/0x01D2/*::]*/: 'SERIES.ORDER',
- /*::[*/0x01D3/*::]*/: 'MAIL.LOGOFF',
- /*::[*/0x01D4/*::]*/: 'CLEAR.ROUTING.SLIP',
- /*::[*/0x01D5/*::]*/: 'APP.ACTIVATE.MICROSOFT',
- /*::[*/0x01D6/*::]*/: 'MAIL.EDIT.MAILER',
- /*::[*/0x01D7/*::]*/: 'ON.SHEET',
- /*::[*/0x01D8/*::]*/: 'STANDARD.WIDTH',
- /*::[*/0x01D9/*::]*/: 'SCENARIO.MERGE',
- /*::[*/0x01DA/*::]*/: 'SUMMARY.INFO',
- /*::[*/0x01DB/*::]*/: 'FIND.FILE',
- /*::[*/0x01DC/*::]*/: 'ACTIVE.CELL.FONT',
- /*::[*/0x01DD/*::]*/: 'ENABLE.TIPWIZARD',
- /*::[*/0x01DE/*::]*/: 'VBA.MAKE.ADDIN',
- /*::[*/0x01E0/*::]*/: 'INSERTDATATABLE',
- /*::[*/0x01E1/*::]*/: 'WORKGROUP.OPTIONS',
- /*::[*/0x01E2/*::]*/: 'MAIL.SEND.MAILER',
- /*::[*/0x01E5/*::]*/: 'AUTOCORRECT',
- /*::[*/0x01E9/*::]*/: 'POST.DOCUMENT',
- /*::[*/0x01EB/*::]*/: 'PICKLIST',
- /*::[*/0x01ED/*::]*/: 'VIEW.SHOW',
- /*::[*/0x01EE/*::]*/: 'VIEW.DEFINE',
- /*::[*/0x01EF/*::]*/: 'VIEW.DELETE',
- /*::[*/0x01FD/*::]*/: 'SHEET.BACKGROUND',
- /*::[*/0x01FE/*::]*/: 'INSERT.MAP.OBJECT',
- /*::[*/0x01FF/*::]*/: 'OPTIONS.MENONO',
- /*::[*/0x0205/*::]*/: 'MSOCHECKS',
- /*::[*/0x0206/*::]*/: 'NORMAL',
- /*::[*/0x0207/*::]*/: 'LAYOUT',
- /*::[*/0x0208/*::]*/: 'RM.PRINT.AREA',
- /*::[*/0x0209/*::]*/: 'CLEAR.PRINT.AREA',
- /*::[*/0x020A/*::]*/: 'ADD.PRINT.AREA',
- /*::[*/0x020B/*::]*/: 'MOVE.BRK',
- /*::[*/0x0221/*::]*/: 'HIDECURR.NOTE',
- /*::[*/0x0222/*::]*/: 'HIDEALL.NOTES',
- /*::[*/0x0223/*::]*/: 'DELETE.NOTE',
- /*::[*/0x0224/*::]*/: 'TRAVERSE.NOTES',
- /*::[*/0x0225/*::]*/: 'ACTIVATE.NOTES',
- /*::[*/0x026C/*::]*/: 'PROTECT.REVISIONS',
- /*::[*/0x026D/*::]*/: 'UNPROTECT.REVISIONS',
- /*::[*/0x0287/*::]*/: 'OPTIONS.ME',
- /*::[*/0x028D/*::]*/: 'WEB.PUBLISH',
- /*::[*/0x029B/*::]*/: 'NEWWEBQUERY',
- /*::[*/0x02A1/*::]*/: 'PIVOT.TABLE.CHART',
- /*::[*/0x02F1/*::]*/: 'OPTIONS.SAVE',
- /*::[*/0x02F3/*::]*/: 'OPTIONS.SPELL',
- /*::[*/0x0328/*::]*/: 'HIDEALL.INKANNOTS'
+ 0: "BEEP",
+ 1: "OPEN",
+ 2: "OPEN.LINKS",
+ 3: "CLOSE.ALL",
+ 4: "SAVE",
+ 5: "SAVE.AS",
+ 6: "FILE.DELETE",
+ 7: "PAGE.SETUP",
+ 8: "PRINT",
+ 9: "PRINTER.SETUP",
+ 10: "QUIT",
+ 11: "NEW.WINDOW",
+ 12: "ARRANGE.ALL",
+ 13: "WINDOW.SIZE",
+ 14: "WINDOW.MOVE",
+ 15: "FULL",
+ 16: "CLOSE",
+ 17: "RUN",
+ 22: "SET.PRINT.AREA",
+ 23: "SET.PRINT.TITLES",
+ 24: "SET.PAGE.BREAK",
+ 25: "REMOVE.PAGE.BREAK",
+ 26: "FONT",
+ 27: "DISPLAY",
+ 28: "PROTECT.DOCUMENT",
+ 29: "PRECISION",
+ 30: "A1.R1C1",
+ 31: "CALCULATE.NOW",
+ 32: "CALCULATION",
+ 34: "DATA.FIND",
+ 35: "EXTRACT",
+ 36: "DATA.DELETE",
+ 37: "SET.DATABASE",
+ 38: "SET.CRITERIA",
+ 39: "SORT",
+ 40: "DATA.SERIES",
+ 41: "TABLE",
+ 42: "FORMAT.NUMBER",
+ 43: "ALIGNMENT",
+ 44: "STYLE",
+ 45: "BORDER",
+ 46: "CELL.PROTECTION",
+ 47: "COLUMN.WIDTH",
+ 48: "UNDO",
+ 49: "CUT",
+ 50: "COPY",
+ 51: "PASTE",
+ 52: "CLEAR",
+ 53: "PASTE.SPECIAL",
+ 54: "EDIT.DELETE",
+ 55: "INSERT",
+ 56: "FILL.RIGHT",
+ 57: "FILL.DOWN",
+ 61: "DEFINE.NAME",
+ 62: "CREATE.NAMES",
+ 63: "FORMULA.GOTO",
+ 64: "FORMULA.FIND",
+ 65: "SELECT.LAST.CELL",
+ 66: "SHOW.ACTIVE.CELL",
+ 67: "GALLERY.AREA",
+ 68: "GALLERY.BAR",
+ 69: "GALLERY.COLUMN",
+ 70: "GALLERY.LINE",
+ 71: "GALLERY.PIE",
+ 72: "GALLERY.SCATTER",
+ 73: "COMBINATION",
+ 74: "PREFERRED",
+ 75: "ADD.OVERLAY",
+ 76: "GRIDLINES",
+ 77: "SET.PREFERRED",
+ 78: "AXES",
+ 79: "LEGEND",
+ 80: "ATTACH.TEXT",
+ 81: "ADD.ARROW",
+ 82: "SELECT.CHART",
+ 83: "SELECT.PLOT.AREA",
+ 84: "PATTERNS",
+ 85: "MAIN.CHART",
+ 86: "OVERLAY",
+ 87: "SCALE",
+ 88: "FORMAT.LEGEND",
+ 89: "FORMAT.TEXT",
+ 90: "EDIT.REPEAT",
+ 91: "PARSE",
+ 92: "JUSTIFY",
+ 93: "HIDE",
+ 94: "UNHIDE",
+ 95: "WORKSPACE",
+ 96: "FORMULA",
+ 97: "FORMULA.FILL",
+ 98: "FORMULA.ARRAY",
+ 99: "DATA.FIND.NEXT",
+ 100: "DATA.FIND.PREV",
+ 101: "FORMULA.FIND.NEXT",
+ 102: "FORMULA.FIND.PREV",
+ 103: "ACTIVATE",
+ 104: "ACTIVATE.NEXT",
+ 105: "ACTIVATE.PREV",
+ 106: "UNLOCKED.NEXT",
+ 107: "UNLOCKED.PREV",
+ 108: "COPY.PICTURE",
+ 109: "SELECT",
+ 110: "DELETE.NAME",
+ 111: "DELETE.FORMAT",
+ 112: "VLINE",
+ 113: "HLINE",
+ 114: "VPAGE",
+ 115: "HPAGE",
+ 116: "VSCROLL",
+ 117: "HSCROLL",
+ 118: "ALERT",
+ 119: "NEW",
+ 120: "CANCEL.COPY",
+ 121: "SHOW.CLIPBOARD",
+ 122: "MESSAGE",
+ 124: "PASTE.LINK",
+ 125: "APP.ACTIVATE",
+ 126: "DELETE.ARROW",
+ 127: "ROW.HEIGHT",
+ 128: "FORMAT.MOVE",
+ 129: "FORMAT.SIZE",
+ 130: "FORMULA.REPLACE",
+ 131: "SEND.KEYS",
+ 132: "SELECT.SPECIAL",
+ 133: "APPLY.NAMES",
+ 134: "REPLACE.FONT",
+ 135: "FREEZE.PANES",
+ 136: "SHOW.INFO",
+ 137: "SPLIT",
+ 138: "ON.WINDOW",
+ 139: "ON.DATA",
+ 140: "DISABLE.INPUT",
+ 142: "OUTLINE",
+ 143: "LIST.NAMES",
+ 144: "FILE.CLOSE",
+ 145: "SAVE.WORKBOOK",
+ 146: "DATA.FORM",
+ 147: "COPY.CHART",
+ 148: "ON.TIME",
+ 149: "WAIT",
+ 150: "FORMAT.FONT",
+ 151: "FILL.UP",
+ 152: "FILL.LEFT",
+ 153: "DELETE.OVERLAY",
+ 155: "SHORT.MENUS",
+ 159: "SET.UPDATE.STATUS",
+ 161: "COLOR.PALETTE",
+ 162: "DELETE.STYLE",
+ 163: "WINDOW.RESTORE",
+ 164: "WINDOW.MAXIMIZE",
+ 166: "CHANGE.LINK",
+ 167: "CALCULATE.DOCUMENT",
+ 168: "ON.KEY",
+ 169: "APP.RESTORE",
+ 170: "APP.MOVE",
+ 171: "APP.SIZE",
+ 172: "APP.MINIMIZE",
+ 173: "APP.MAXIMIZE",
+ 174: "BRING.TO.FRONT",
+ 175: "SEND.TO.BACK",
+ 185: "MAIN.CHART.TYPE",
+ 186: "OVERLAY.CHART.TYPE",
+ 187: "SELECT.END",
+ 188: "OPEN.MAIL",
+ 189: "SEND.MAIL",
+ 190: "STANDARD.FONT",
+ 191: "CONSOLIDATE",
+ 192: "SORT.SPECIAL",
+ 193: "GALLERY.3D.AREA",
+ 194: "GALLERY.3D.COLUMN",
+ 195: "GALLERY.3D.LINE",
+ 196: "GALLERY.3D.PIE",
+ 197: "VIEW.3D",
+ 198: "GOAL.SEEK",
+ 199: "WORKGROUP",
+ 200: "FILL.GROUP",
+ 201: "UPDATE.LINK",
+ 202: "PROMOTE",
+ 203: "DEMOTE",
+ 204: "SHOW.DETAIL",
+ 206: "UNGROUP",
+ 207: "OBJECT.PROPERTIES",
+ 208: "SAVE.NEW.OBJECT",
+ 209: "SHARE",
+ 210: "SHARE.NAME",
+ 211: "DUPLICATE",
+ 212: "APPLY.STYLE",
+ 213: "ASSIGN.TO.OBJECT",
+ 214: "OBJECT.PROTECTION",
+ 215: "HIDE.OBJECT",
+ 216: "SET.EXTRACT",
+ 217: "CREATE.PUBLISHER",
+ 218: "SUBSCRIBE.TO",
+ 219: "ATTRIBUTES",
+ 220: "SHOW.TOOLBAR",
+ 222: "PRINT.PREVIEW",
+ 223: "EDIT.COLOR",
+ 224: "SHOW.LEVELS",
+ 225: "FORMAT.MAIN",
+ 226: "FORMAT.OVERLAY",
+ 227: "ON.RECALC",
+ 228: "EDIT.SERIES",
+ 229: "DEFINE.STYLE",
+ 240: "LINE.PRINT",
+ 243: "ENTER.DATA",
+ 249: "GALLERY.RADAR",
+ 250: "MERGE.STYLES",
+ 251: "EDITION.OPTIONS",
+ 252: "PASTE.PICTURE",
+ 253: "PASTE.PICTURE.LINK",
+ 254: "SPELLING",
+ 256: "ZOOM",
+ 259: "INSERT.OBJECT",
+ 260: "WINDOW.MINIMIZE",
+ 265: "SOUND.NOTE",
+ 266: "SOUND.PLAY",
+ 267: "FORMAT.SHAPE",
+ 268: "EXTEND.POLYGON",
+ 269: "FORMAT.AUTO",
+ 272: "GALLERY.3D.BAR",
+ 273: "GALLERY.3D.SURFACE",
+ 274: "FILL.AUTO",
+ 276: "CUSTOMIZE.TOOLBAR",
+ 277: "ADD.TOOL",
+ 278: "EDIT.OBJECT",
+ 279: "ON.DOUBLECLICK",
+ 280: "ON.ENTRY",
+ 281: "WORKBOOK.ADD",
+ 282: "WORKBOOK.MOVE",
+ 283: "WORKBOOK.COPY",
+ 284: "WORKBOOK.OPTIONS",
+ 285: "SAVE.WORKSPACE",
+ 288: "CHART.WIZARD",
+ 289: "DELETE.TOOL",
+ 290: "MOVE.TOOL",
+ 291: "WORKBOOK.SELECT",
+ 292: "WORKBOOK.ACTIVATE",
+ 293: "ASSIGN.TO.TOOL",
+ 295: "COPY.TOOL",
+ 296: "RESET.TOOL",
+ 297: "CONSTRAIN.NUMERIC",
+ 298: "PASTE.TOOL",
+ 302: "WORKBOOK.NEW",
+ 305: "SCENARIO.CELLS",
+ 306: "SCENARIO.DELETE",
+ 307: "SCENARIO.ADD",
+ 308: "SCENARIO.EDIT",
+ 309: "SCENARIO.SHOW",
+ 310: "SCENARIO.SHOW.NEXT",
+ 311: "SCENARIO.SUMMARY",
+ 312: "PIVOT.TABLE.WIZARD",
+ 313: "PIVOT.FIELD.PROPERTIES",
+ 314: "PIVOT.FIELD",
+ 315: "PIVOT.ITEM",
+ 316: "PIVOT.ADD.FIELDS",
+ 318: "OPTIONS.CALCULATION",
+ 319: "OPTIONS.EDIT",
+ 320: "OPTIONS.VIEW",
+ 321: "ADDIN.MANAGER",
+ 322: "MENU.EDITOR",
+ 323: "ATTACH.TOOLBARS",
+ 324: "VBAActivate",
+ 325: "OPTIONS.CHART",
+ 328: "VBA.INSERT.FILE",
+ 330: "VBA.PROCEDURE.DEFINITION",
+ 336: "ROUTING.SLIP",
+ 338: "ROUTE.DOCUMENT",
+ 339: "MAIL.LOGON",
+ 342: "INSERT.PICTURE",
+ 343: "EDIT.TOOL",
+ 344: "GALLERY.DOUGHNUT",
+ 350: "CHART.TREND",
+ 352: "PIVOT.ITEM.PROPERTIES",
+ 354: "WORKBOOK.INSERT",
+ 355: "OPTIONS.TRANSITION",
+ 356: "OPTIONS.GENERAL",
+ 370: "FILTER.ADVANCED",
+ 373: "MAIL.ADD.MAILER",
+ 374: "MAIL.DELETE.MAILER",
+ 375: "MAIL.REPLY",
+ 376: "MAIL.REPLY.ALL",
+ 377: "MAIL.FORWARD",
+ 378: "MAIL.NEXT.LETTER",
+ 379: "DATA.LABEL",
+ 380: "INSERT.TITLE",
+ 381: "FONT.PROPERTIES",
+ 382: "MACRO.OPTIONS",
+ 383: "WORKBOOK.HIDE",
+ 384: "WORKBOOK.UNHIDE",
+ 385: "WORKBOOK.DELETE",
+ 386: "WORKBOOK.NAME",
+ 388: "GALLERY.CUSTOM",
+ 390: "ADD.CHART.AUTOFORMAT",
+ 391: "DELETE.CHART.AUTOFORMAT",
+ 392: "CHART.ADD.DATA",
+ 393: "AUTO.OUTLINE",
+ 394: "TAB.ORDER",
+ 395: "SHOW.DIALOG",
+ 396: "SELECT.ALL",
+ 397: "UNGROUP.SHEETS",
+ 398: "SUBTOTAL.CREATE",
+ 399: "SUBTOTAL.REMOVE",
+ 400: "RENAME.OBJECT",
+ 412: "WORKBOOK.SCROLL",
+ 413: "WORKBOOK.NEXT",
+ 414: "WORKBOOK.PREV",
+ 415: "WORKBOOK.TAB.SPLIT",
+ 416: "FULL.SCREEN",
+ 417: "WORKBOOK.PROTECT",
+ 420: "SCROLLBAR.PROPERTIES",
+ 421: "PIVOT.SHOW.PAGES",
+ 422: "TEXT.TO.COLUMNS",
+ 423: "FORMAT.CHARTTYPE",
+ 424: "LINK.FORMAT",
+ 425: "TRACER.DISPLAY",
+ 430: "TRACER.NAVIGATE",
+ 431: "TRACER.CLEAR",
+ 432: "TRACER.ERROR",
+ 433: "PIVOT.FIELD.GROUP",
+ 434: "PIVOT.FIELD.UNGROUP",
+ 435: "CHECKBOX.PROPERTIES",
+ 436: "LABEL.PROPERTIES",
+ 437: "LISTBOX.PROPERTIES",
+ 438: "EDITBOX.PROPERTIES",
+ 439: "PIVOT.REFRESH",
+ 440: "LINK.COMBO",
+ 441: "OPEN.TEXT",
+ 442: "HIDE.DIALOG",
+ 443: "SET.DIALOG.FOCUS",
+ 444: "ENABLE.OBJECT",
+ 445: "PUSHBUTTON.PROPERTIES",
+ 446: "SET.DIALOG.DEFAULT",
+ 447: "FILTER",
+ 448: "FILTER.SHOW.ALL",
+ 449: "CLEAR.OUTLINE",
+ 450: "FUNCTION.WIZARD",
+ 451: "ADD.LIST.ITEM",
+ 452: "SET.LIST.ITEM",
+ 453: "REMOVE.LIST.ITEM",
+ 454: "SELECT.LIST.ITEM",
+ 455: "SET.CONTROL.VALUE",
+ 456: "SAVE.COPY.AS",
+ 458: "OPTIONS.LISTS.ADD",
+ 459: "OPTIONS.LISTS.DELETE",
+ 460: "SERIES.AXES",
+ 461: "SERIES.X",
+ 462: "SERIES.Y",
+ 463: "ERRORBAR.X",
+ 464: "ERRORBAR.Y",
+ 465: "FORMAT.CHART",
+ 466: "SERIES.ORDER",
+ 467: "MAIL.LOGOFF",
+ 468: "CLEAR.ROUTING.SLIP",
+ 469: "APP.ACTIVATE.MICROSOFT",
+ 470: "MAIL.EDIT.MAILER",
+ 471: "ON.SHEET",
+ 472: "STANDARD.WIDTH",
+ 473: "SCENARIO.MERGE",
+ 474: "SUMMARY.INFO",
+ 475: "FIND.FILE",
+ 476: "ACTIVE.CELL.FONT",
+ 477: "ENABLE.TIPWIZARD",
+ 478: "VBA.MAKE.ADDIN",
+ 480: "INSERTDATATABLE",
+ 481: "WORKGROUP.OPTIONS",
+ 482: "MAIL.SEND.MAILER",
+ 485: "AUTOCORRECT",
+ 489: "POST.DOCUMENT",
+ 491: "PICKLIST",
+ 493: "VIEW.SHOW",
+ 494: "VIEW.DEFINE",
+ 495: "VIEW.DELETE",
+ 509: "SHEET.BACKGROUND",
+ 510: "INSERT.MAP.OBJECT",
+ 511: "OPTIONS.MENONO",
+ 517: "MSOCHECKS",
+ 518: "NORMAL",
+ 519: "LAYOUT",
+ 520: "RM.PRINT.AREA",
+ 521: "CLEAR.PRINT.AREA",
+ 522: "ADD.PRINT.AREA",
+ 523: "MOVE.BRK",
+ 545: "HIDECURR.NOTE",
+ 546: "HIDEALL.NOTES",
+ 547: "DELETE.NOTE",
+ 548: "TRAVERSE.NOTES",
+ 549: "ACTIVATE.NOTES",
+ 620: "PROTECT.REVISIONS",
+ 621: "UNPROTECT.REVISIONS",
+ 647: "OPTIONS.ME",
+ 653: "WEB.PUBLISH",
+ 667: "NEWWEBQUERY",
+ 673: "PIVOT.TABLE.CHART",
+ 753: "OPTIONS.SAVE",
+ 755: "OPTIONS.SPELL",
+ 808: "HIDEALL.INKANNOTS"
};
-
-/* [MS-XLS] 2.5.198.17 */
-/* [MS-XLSB] 2.5.97.10 */
var Ftab = {
- /*::[*/0x0000/*::]*/: 'COUNT',
- /*::[*/0x0001/*::]*/: 'IF',
- /*::[*/0x0002/*::]*/: 'ISNA',
- /*::[*/0x0003/*::]*/: 'ISERROR',
- /*::[*/0x0004/*::]*/: 'SUM',
- /*::[*/0x0005/*::]*/: 'AVERAGE',
- /*::[*/0x0006/*::]*/: 'MIN',
- /*::[*/0x0007/*::]*/: 'MAX',
- /*::[*/0x0008/*::]*/: 'ROW',
- /*::[*/0x0009/*::]*/: 'COLUMN',
- /*::[*/0x000A/*::]*/: 'NA',
- /*::[*/0x000B/*::]*/: 'NPV',
- /*::[*/0x000C/*::]*/: 'STDEV',
- /*::[*/0x000D/*::]*/: 'DOLLAR',
- /*::[*/0x000E/*::]*/: 'FIXED',
- /*::[*/0x000F/*::]*/: 'SIN',
- /*::[*/0x0010/*::]*/: 'COS',
- /*::[*/0x0011/*::]*/: 'TAN',
- /*::[*/0x0012/*::]*/: 'ATAN',
- /*::[*/0x0013/*::]*/: 'PI',
- /*::[*/0x0014/*::]*/: 'SQRT',
- /*::[*/0x0015/*::]*/: 'EXP',
- /*::[*/0x0016/*::]*/: 'LN',
- /*::[*/0x0017/*::]*/: 'LOG10',
- /*::[*/0x0018/*::]*/: 'ABS',
- /*::[*/0x0019/*::]*/: 'INT',
- /*::[*/0x001A/*::]*/: 'SIGN',
- /*::[*/0x001B/*::]*/: 'ROUND',
- /*::[*/0x001C/*::]*/: 'LOOKUP',
- /*::[*/0x001D/*::]*/: 'INDEX',
- /*::[*/0x001E/*::]*/: 'REPT',
- /*::[*/0x001F/*::]*/: 'MID',
- /*::[*/0x0020/*::]*/: 'LEN',
- /*::[*/0x0021/*::]*/: 'VALUE',
- /*::[*/0x0022/*::]*/: 'TRUE',
- /*::[*/0x0023/*::]*/: 'FALSE',
- /*::[*/0x0024/*::]*/: 'AND',
- /*::[*/0x0025/*::]*/: 'OR',
- /*::[*/0x0026/*::]*/: 'NOT',
- /*::[*/0x0027/*::]*/: 'MOD',
- /*::[*/0x0028/*::]*/: 'DCOUNT',
- /*::[*/0x0029/*::]*/: 'DSUM',
- /*::[*/0x002A/*::]*/: 'DAVERAGE',
- /*::[*/0x002B/*::]*/: 'DMIN',
- /*::[*/0x002C/*::]*/: 'DMAX',
- /*::[*/0x002D/*::]*/: 'DSTDEV',
- /*::[*/0x002E/*::]*/: 'VAR',
- /*::[*/0x002F/*::]*/: 'DVAR',
- /*::[*/0x0030/*::]*/: 'TEXT',
- /*::[*/0x0031/*::]*/: 'LINEST',
- /*::[*/0x0032/*::]*/: 'TREND',
- /*::[*/0x0033/*::]*/: 'LOGEST',
- /*::[*/0x0034/*::]*/: 'GROWTH',
- /*::[*/0x0035/*::]*/: 'GOTO',
- /*::[*/0x0036/*::]*/: 'HALT',
- /*::[*/0x0037/*::]*/: 'RETURN',
- /*::[*/0x0038/*::]*/: 'PV',
- /*::[*/0x0039/*::]*/: 'FV',
- /*::[*/0x003A/*::]*/: 'NPER',
- /*::[*/0x003B/*::]*/: 'PMT',
- /*::[*/0x003C/*::]*/: 'RATE',
- /*::[*/0x003D/*::]*/: 'MIRR',
- /*::[*/0x003E/*::]*/: 'IRR',
- /*::[*/0x003F/*::]*/: 'RAND',
- /*::[*/0x0040/*::]*/: 'MATCH',
- /*::[*/0x0041/*::]*/: 'DATE',
- /*::[*/0x0042/*::]*/: 'TIME',
- /*::[*/0x0043/*::]*/: 'DAY',
- /*::[*/0x0044/*::]*/: 'MONTH',
- /*::[*/0x0045/*::]*/: 'YEAR',
- /*::[*/0x0046/*::]*/: 'WEEKDAY',
- /*::[*/0x0047/*::]*/: 'HOUR',
- /*::[*/0x0048/*::]*/: 'MINUTE',
- /*::[*/0x0049/*::]*/: 'SECOND',
- /*::[*/0x004A/*::]*/: 'NOW',
- /*::[*/0x004B/*::]*/: 'AREAS',
- /*::[*/0x004C/*::]*/: 'ROWS',
- /*::[*/0x004D/*::]*/: 'COLUMNS',
- /*::[*/0x004E/*::]*/: 'OFFSET',
- /*::[*/0x004F/*::]*/: 'ABSREF',
- /*::[*/0x0050/*::]*/: 'RELREF',
- /*::[*/0x0051/*::]*/: 'ARGUMENT',
- /*::[*/0x0052/*::]*/: 'SEARCH',
- /*::[*/0x0053/*::]*/: 'TRANSPOSE',
- /*::[*/0x0054/*::]*/: 'ERROR',
- /*::[*/0x0055/*::]*/: 'STEP',
- /*::[*/0x0056/*::]*/: 'TYPE',
- /*::[*/0x0057/*::]*/: 'ECHO',
- /*::[*/0x0058/*::]*/: 'SET.NAME',
- /*::[*/0x0059/*::]*/: 'CALLER',
- /*::[*/0x005A/*::]*/: 'DEREF',
- /*::[*/0x005B/*::]*/: 'WINDOWS',
- /*::[*/0x005C/*::]*/: 'SERIES',
- /*::[*/0x005D/*::]*/: 'DOCUMENTS',
- /*::[*/0x005E/*::]*/: 'ACTIVE.CELL',
- /*::[*/0x005F/*::]*/: 'SELECTION',
- /*::[*/0x0060/*::]*/: 'RESULT',
- /*::[*/0x0061/*::]*/: 'ATAN2',
- /*::[*/0x0062/*::]*/: 'ASIN',
- /*::[*/0x0063/*::]*/: 'ACOS',
- /*::[*/0x0064/*::]*/: 'CHOOSE',
- /*::[*/0x0065/*::]*/: 'HLOOKUP',
- /*::[*/0x0066/*::]*/: 'VLOOKUP',
- /*::[*/0x0067/*::]*/: 'LINKS',
- /*::[*/0x0068/*::]*/: 'INPUT',
- /*::[*/0x0069/*::]*/: 'ISREF',
- /*::[*/0x006A/*::]*/: 'GET.FORMULA',
- /*::[*/0x006B/*::]*/: 'GET.NAME',
- /*::[*/0x006C/*::]*/: 'SET.VALUE',
- /*::[*/0x006D/*::]*/: 'LOG',
- /*::[*/0x006E/*::]*/: 'EXEC',
- /*::[*/0x006F/*::]*/: 'CHAR',
- /*::[*/0x0070/*::]*/: 'LOWER',
- /*::[*/0x0071/*::]*/: 'UPPER',
- /*::[*/0x0072/*::]*/: 'PROPER',
- /*::[*/0x0073/*::]*/: 'LEFT',
- /*::[*/0x0074/*::]*/: 'RIGHT',
- /*::[*/0x0075/*::]*/: 'EXACT',
- /*::[*/0x0076/*::]*/: 'TRIM',
- /*::[*/0x0077/*::]*/: 'REPLACE',
- /*::[*/0x0078/*::]*/: 'SUBSTITUTE',
- /*::[*/0x0079/*::]*/: 'CODE',
- /*::[*/0x007A/*::]*/: 'NAMES',
- /*::[*/0x007B/*::]*/: 'DIRECTORY',
- /*::[*/0x007C/*::]*/: 'FIND',
- /*::[*/0x007D/*::]*/: 'CELL',
- /*::[*/0x007E/*::]*/: 'ISERR',
- /*::[*/0x007F/*::]*/: 'ISTEXT',
- /*::[*/0x0080/*::]*/: 'ISNUMBER',
- /*::[*/0x0081/*::]*/: 'ISBLANK',
- /*::[*/0x0082/*::]*/: 'T',
- /*::[*/0x0083/*::]*/: 'N',
- /*::[*/0x0084/*::]*/: 'FOPEN',
- /*::[*/0x0085/*::]*/: 'FCLOSE',
- /*::[*/0x0086/*::]*/: 'FSIZE',
- /*::[*/0x0087/*::]*/: 'FREADLN',
- /*::[*/0x0088/*::]*/: 'FREAD',
- /*::[*/0x0089/*::]*/: 'FWRITELN',
- /*::[*/0x008A/*::]*/: 'FWRITE',
- /*::[*/0x008B/*::]*/: 'FPOS',
- /*::[*/0x008C/*::]*/: 'DATEVALUE',
- /*::[*/0x008D/*::]*/: 'TIMEVALUE',
- /*::[*/0x008E/*::]*/: 'SLN',
- /*::[*/0x008F/*::]*/: 'SYD',
- /*::[*/0x0090/*::]*/: 'DDB',
- /*::[*/0x0091/*::]*/: 'GET.DEF',
- /*::[*/0x0092/*::]*/: 'REFTEXT',
- /*::[*/0x0093/*::]*/: 'TEXTREF',
- /*::[*/0x0094/*::]*/: 'INDIRECT',
- /*::[*/0x0095/*::]*/: 'REGISTER',
- /*::[*/0x0096/*::]*/: 'CALL',
- /*::[*/0x0097/*::]*/: 'ADD.BAR',
- /*::[*/0x0098/*::]*/: 'ADD.MENU',
- /*::[*/0x0099/*::]*/: 'ADD.COMMAND',
- /*::[*/0x009A/*::]*/: 'ENABLE.COMMAND',
- /*::[*/0x009B/*::]*/: 'CHECK.COMMAND',
- /*::[*/0x009C/*::]*/: 'RENAME.COMMAND',
- /*::[*/0x009D/*::]*/: 'SHOW.BAR',
- /*::[*/0x009E/*::]*/: 'DELETE.MENU',
- /*::[*/0x009F/*::]*/: 'DELETE.COMMAND',
- /*::[*/0x00A0/*::]*/: 'GET.CHART.ITEM',
- /*::[*/0x00A1/*::]*/: 'DIALOG.BOX',
- /*::[*/0x00A2/*::]*/: 'CLEAN',
- /*::[*/0x00A3/*::]*/: 'MDETERM',
- /*::[*/0x00A4/*::]*/: 'MINVERSE',
- /*::[*/0x00A5/*::]*/: 'MMULT',
- /*::[*/0x00A6/*::]*/: 'FILES',
- /*::[*/0x00A7/*::]*/: 'IPMT',
- /*::[*/0x00A8/*::]*/: 'PPMT',
- /*::[*/0x00A9/*::]*/: 'COUNTA',
- /*::[*/0x00AA/*::]*/: 'CANCEL.KEY',
- /*::[*/0x00AB/*::]*/: 'FOR',
- /*::[*/0x00AC/*::]*/: 'WHILE',
- /*::[*/0x00AD/*::]*/: 'BREAK',
- /*::[*/0x00AE/*::]*/: 'NEXT',
- /*::[*/0x00AF/*::]*/: 'INITIATE',
- /*::[*/0x00B0/*::]*/: 'REQUEST',
- /*::[*/0x00B1/*::]*/: 'POKE',
- /*::[*/0x00B2/*::]*/: 'EXECUTE',
- /*::[*/0x00B3/*::]*/: 'TERMINATE',
- /*::[*/0x00B4/*::]*/: 'RESTART',
- /*::[*/0x00B5/*::]*/: 'HELP',
- /*::[*/0x00B6/*::]*/: 'GET.BAR',
- /*::[*/0x00B7/*::]*/: 'PRODUCT',
- /*::[*/0x00B8/*::]*/: 'FACT',
- /*::[*/0x00B9/*::]*/: 'GET.CELL',
- /*::[*/0x00BA/*::]*/: 'GET.WORKSPACE',
- /*::[*/0x00BB/*::]*/: 'GET.WINDOW',
- /*::[*/0x00BC/*::]*/: 'GET.DOCUMENT',
- /*::[*/0x00BD/*::]*/: 'DPRODUCT',
- /*::[*/0x00BE/*::]*/: 'ISNONTEXT',
- /*::[*/0x00BF/*::]*/: 'GET.NOTE',
- /*::[*/0x00C0/*::]*/: 'NOTE',
- /*::[*/0x00C1/*::]*/: 'STDEVP',
- /*::[*/0x00C2/*::]*/: 'VARP',
- /*::[*/0x00C3/*::]*/: 'DSTDEVP',
- /*::[*/0x00C4/*::]*/: 'DVARP',
- /*::[*/0x00C5/*::]*/: 'TRUNC',
- /*::[*/0x00C6/*::]*/: 'ISLOGICAL',
- /*::[*/0x00C7/*::]*/: 'DCOUNTA',
- /*::[*/0x00C8/*::]*/: 'DELETE.BAR',
- /*::[*/0x00C9/*::]*/: 'UNREGISTER',
- /*::[*/0x00CC/*::]*/: 'USDOLLAR',
- /*::[*/0x00CD/*::]*/: 'FINDB',
- /*::[*/0x00CE/*::]*/: 'SEARCHB',
- /*::[*/0x00CF/*::]*/: 'REPLACEB',
- /*::[*/0x00D0/*::]*/: 'LEFTB',
- /*::[*/0x00D1/*::]*/: 'RIGHTB',
- /*::[*/0x00D2/*::]*/: 'MIDB',
- /*::[*/0x00D3/*::]*/: 'LENB',
- /*::[*/0x00D4/*::]*/: 'ROUNDUP',
- /*::[*/0x00D5/*::]*/: 'ROUNDDOWN',
- /*::[*/0x00D6/*::]*/: 'ASC',
- /*::[*/0x00D7/*::]*/: 'DBCS',
- /*::[*/0x00D8/*::]*/: 'RANK',
- /*::[*/0x00DB/*::]*/: 'ADDRESS',
- /*::[*/0x00DC/*::]*/: 'DAYS360',
- /*::[*/0x00DD/*::]*/: 'TODAY',
- /*::[*/0x00DE/*::]*/: 'VDB',
- /*::[*/0x00DF/*::]*/: 'ELSE',
- /*::[*/0x00E0/*::]*/: 'ELSE.IF',
- /*::[*/0x00E1/*::]*/: 'END.IF',
- /*::[*/0x00E2/*::]*/: 'FOR.CELL',
- /*::[*/0x00E3/*::]*/: 'MEDIAN',
- /*::[*/0x00E4/*::]*/: 'SUMPRODUCT',
- /*::[*/0x00E5/*::]*/: 'SINH',
- /*::[*/0x00E6/*::]*/: 'COSH',
- /*::[*/0x00E7/*::]*/: 'TANH',
- /*::[*/0x00E8/*::]*/: 'ASINH',
- /*::[*/0x00E9/*::]*/: 'ACOSH',
- /*::[*/0x00EA/*::]*/: 'ATANH',
- /*::[*/0x00EB/*::]*/: 'DGET',
- /*::[*/0x00EC/*::]*/: 'CREATE.OBJECT',
- /*::[*/0x00ED/*::]*/: 'VOLATILE',
- /*::[*/0x00EE/*::]*/: 'LAST.ERROR',
- /*::[*/0x00EF/*::]*/: 'CUSTOM.UNDO',
- /*::[*/0x00F0/*::]*/: 'CUSTOM.REPEAT',
- /*::[*/0x00F1/*::]*/: 'FORMULA.CONVERT',
- /*::[*/0x00F2/*::]*/: 'GET.LINK.INFO',
- /*::[*/0x00F3/*::]*/: 'TEXT.BOX',
- /*::[*/0x00F4/*::]*/: 'INFO',
- /*::[*/0x00F5/*::]*/: 'GROUP',
- /*::[*/0x00F6/*::]*/: 'GET.OBJECT',
- /*::[*/0x00F7/*::]*/: 'DB',
- /*::[*/0x00F8/*::]*/: 'PAUSE',
- /*::[*/0x00FB/*::]*/: 'RESUME',
- /*::[*/0x00FC/*::]*/: 'FREQUENCY',
- /*::[*/0x00FD/*::]*/: 'ADD.TOOLBAR',
- /*::[*/0x00FE/*::]*/: 'DELETE.TOOLBAR',
- /*::[*/0x00FF/*::]*/: 'User',
- /*::[*/0x0100/*::]*/: 'RESET.TOOLBAR',
- /*::[*/0x0101/*::]*/: 'EVALUATE',
- /*::[*/0x0102/*::]*/: 'GET.TOOLBAR',
- /*::[*/0x0103/*::]*/: 'GET.TOOL',
- /*::[*/0x0104/*::]*/: 'SPELLING.CHECK',
- /*::[*/0x0105/*::]*/: 'ERROR.TYPE',
- /*::[*/0x0106/*::]*/: 'APP.TITLE',
- /*::[*/0x0107/*::]*/: 'WINDOW.TITLE',
- /*::[*/0x0108/*::]*/: 'SAVE.TOOLBAR',
- /*::[*/0x0109/*::]*/: 'ENABLE.TOOL',
- /*::[*/0x010A/*::]*/: 'PRESS.TOOL',
- /*::[*/0x010B/*::]*/: 'REGISTER.ID',
- /*::[*/0x010C/*::]*/: 'GET.WORKBOOK',
- /*::[*/0x010D/*::]*/: 'AVEDEV',
- /*::[*/0x010E/*::]*/: 'BETADIST',
- /*::[*/0x010F/*::]*/: 'GAMMALN',
- /*::[*/0x0110/*::]*/: 'BETAINV',
- /*::[*/0x0111/*::]*/: 'BINOMDIST',
- /*::[*/0x0112/*::]*/: 'CHIDIST',
- /*::[*/0x0113/*::]*/: 'CHIINV',
- /*::[*/0x0114/*::]*/: 'COMBIN',
- /*::[*/0x0115/*::]*/: 'CONFIDENCE',
- /*::[*/0x0116/*::]*/: 'CRITBINOM',
- /*::[*/0x0117/*::]*/: 'EVEN',
- /*::[*/0x0118/*::]*/: 'EXPONDIST',
- /*::[*/0x0119/*::]*/: 'FDIST',
- /*::[*/0x011A/*::]*/: 'FINV',
- /*::[*/0x011B/*::]*/: 'FISHER',
- /*::[*/0x011C/*::]*/: 'FISHERINV',
- /*::[*/0x011D/*::]*/: 'FLOOR',
- /*::[*/0x011E/*::]*/: 'GAMMADIST',
- /*::[*/0x011F/*::]*/: 'GAMMAINV',
- /*::[*/0x0120/*::]*/: 'CEILING',
- /*::[*/0x0121/*::]*/: 'HYPGEOMDIST',
- /*::[*/0x0122/*::]*/: 'LOGNORMDIST',
- /*::[*/0x0123/*::]*/: 'LOGINV',
- /*::[*/0x0124/*::]*/: 'NEGBINOMDIST',
- /*::[*/0x0125/*::]*/: 'NORMDIST',
- /*::[*/0x0126/*::]*/: 'NORMSDIST',
- /*::[*/0x0127/*::]*/: 'NORMINV',
- /*::[*/0x0128/*::]*/: 'NORMSINV',
- /*::[*/0x0129/*::]*/: 'STANDARDIZE',
- /*::[*/0x012A/*::]*/: 'ODD',
- /*::[*/0x012B/*::]*/: 'PERMUT',
- /*::[*/0x012C/*::]*/: 'POISSON',
- /*::[*/0x012D/*::]*/: 'TDIST',
- /*::[*/0x012E/*::]*/: 'WEIBULL',
- /*::[*/0x012F/*::]*/: 'SUMXMY2',
- /*::[*/0x0130/*::]*/: 'SUMX2MY2',
- /*::[*/0x0131/*::]*/: 'SUMX2PY2',
- /*::[*/0x0132/*::]*/: 'CHITEST',
- /*::[*/0x0133/*::]*/: 'CORREL',
- /*::[*/0x0134/*::]*/: 'COVAR',
- /*::[*/0x0135/*::]*/: 'FORECAST',
- /*::[*/0x0136/*::]*/: 'FTEST',
- /*::[*/0x0137/*::]*/: 'INTERCEPT',
- /*::[*/0x0138/*::]*/: 'PEARSON',
- /*::[*/0x0139/*::]*/: 'RSQ',
- /*::[*/0x013A/*::]*/: 'STEYX',
- /*::[*/0x013B/*::]*/: 'SLOPE',
- /*::[*/0x013C/*::]*/: 'TTEST',
- /*::[*/0x013D/*::]*/: 'PROB',
- /*::[*/0x013E/*::]*/: 'DEVSQ',
- /*::[*/0x013F/*::]*/: 'GEOMEAN',
- /*::[*/0x0140/*::]*/: 'HARMEAN',
- /*::[*/0x0141/*::]*/: 'SUMSQ',
- /*::[*/0x0142/*::]*/: 'KURT',
- /*::[*/0x0143/*::]*/: 'SKEW',
- /*::[*/0x0144/*::]*/: 'ZTEST',
- /*::[*/0x0145/*::]*/: 'LARGE',
- /*::[*/0x0146/*::]*/: 'SMALL',
- /*::[*/0x0147/*::]*/: 'QUARTILE',
- /*::[*/0x0148/*::]*/: 'PERCENTILE',
- /*::[*/0x0149/*::]*/: 'PERCENTRANK',
- /*::[*/0x014A/*::]*/: 'MODE',
- /*::[*/0x014B/*::]*/: 'TRIMMEAN',
- /*::[*/0x014C/*::]*/: 'TINV',
- /*::[*/0x014E/*::]*/: 'MOVIE.COMMAND',
- /*::[*/0x014F/*::]*/: 'GET.MOVIE',
- /*::[*/0x0150/*::]*/: 'CONCATENATE',
- /*::[*/0x0151/*::]*/: 'POWER',
- /*::[*/0x0152/*::]*/: 'PIVOT.ADD.DATA',
- /*::[*/0x0153/*::]*/: 'GET.PIVOT.TABLE',
- /*::[*/0x0154/*::]*/: 'GET.PIVOT.FIELD',
- /*::[*/0x0155/*::]*/: 'GET.PIVOT.ITEM',
- /*::[*/0x0156/*::]*/: 'RADIANS',
- /*::[*/0x0157/*::]*/: 'DEGREES',
- /*::[*/0x0158/*::]*/: 'SUBTOTAL',
- /*::[*/0x0159/*::]*/: 'SUMIF',
- /*::[*/0x015A/*::]*/: 'COUNTIF',
- /*::[*/0x015B/*::]*/: 'COUNTBLANK',
- /*::[*/0x015C/*::]*/: 'SCENARIO.GET',
- /*::[*/0x015D/*::]*/: 'OPTIONS.LISTS.GET',
- /*::[*/0x015E/*::]*/: 'ISPMT',
- /*::[*/0x015F/*::]*/: 'DATEDIF',
- /*::[*/0x0160/*::]*/: 'DATESTRING',
- /*::[*/0x0161/*::]*/: 'NUMBERSTRING',
- /*::[*/0x0162/*::]*/: 'ROMAN',
- /*::[*/0x0163/*::]*/: 'OPEN.DIALOG',
- /*::[*/0x0164/*::]*/: 'SAVE.DIALOG',
- /*::[*/0x0165/*::]*/: 'VIEW.GET',
- /*::[*/0x0166/*::]*/: 'GETPIVOTDATA',
- /*::[*/0x0167/*::]*/: 'HYPERLINK',
- /*::[*/0x0168/*::]*/: 'PHONETIC',
- /*::[*/0x0169/*::]*/: 'AVERAGEA',
- /*::[*/0x016A/*::]*/: 'MAXA',
- /*::[*/0x016B/*::]*/: 'MINA',
- /*::[*/0x016C/*::]*/: 'STDEVPA',
- /*::[*/0x016D/*::]*/: 'VARPA',
- /*::[*/0x016E/*::]*/: 'STDEVA',
- /*::[*/0x016F/*::]*/: 'VARA',
- /*::[*/0x0170/*::]*/: 'BAHTTEXT',
- /*::[*/0x0171/*::]*/: 'THAIDAYOFWEEK',
- /*::[*/0x0172/*::]*/: 'THAIDIGIT',
- /*::[*/0x0173/*::]*/: 'THAIMONTHOFYEAR',
- /*::[*/0x0174/*::]*/: 'THAINUMSOUND',
- /*::[*/0x0175/*::]*/: 'THAINUMSTRING',
- /*::[*/0x0176/*::]*/: 'THAISTRINGLENGTH',
- /*::[*/0x0177/*::]*/: 'ISTHAIDIGIT',
- /*::[*/0x0178/*::]*/: 'ROUNDBAHTDOWN',
- /*::[*/0x0179/*::]*/: 'ROUNDBAHTUP',
- /*::[*/0x017A/*::]*/: 'THAIYEAR',
- /*::[*/0x017B/*::]*/: 'RTD',
-
- /*::[*/0x017C/*::]*/: 'CUBEVALUE',
- /*::[*/0x017D/*::]*/: 'CUBEMEMBER',
- /*::[*/0x017E/*::]*/: 'CUBEMEMBERPROPERTY',
- /*::[*/0x017F/*::]*/: 'CUBERANKEDMEMBER',
- /*::[*/0x0180/*::]*/: 'HEX2BIN',
- /*::[*/0x0181/*::]*/: 'HEX2DEC',
- /*::[*/0x0182/*::]*/: 'HEX2OCT',
- /*::[*/0x0183/*::]*/: 'DEC2BIN',
- /*::[*/0x0184/*::]*/: 'DEC2HEX',
- /*::[*/0x0185/*::]*/: 'DEC2OCT',
- /*::[*/0x0186/*::]*/: 'OCT2BIN',
- /*::[*/0x0187/*::]*/: 'OCT2HEX',
- /*::[*/0x0188/*::]*/: 'OCT2DEC',
- /*::[*/0x0189/*::]*/: 'BIN2DEC',
- /*::[*/0x018A/*::]*/: 'BIN2OCT',
- /*::[*/0x018B/*::]*/: 'BIN2HEX',
- /*::[*/0x018C/*::]*/: 'IMSUB',
- /*::[*/0x018D/*::]*/: 'IMDIV',
- /*::[*/0x018E/*::]*/: 'IMPOWER',
- /*::[*/0x018F/*::]*/: 'IMABS',
- /*::[*/0x0190/*::]*/: 'IMSQRT',
- /*::[*/0x0191/*::]*/: 'IMLN',
- /*::[*/0x0192/*::]*/: 'IMLOG2',
- /*::[*/0x0193/*::]*/: 'IMLOG10',
- /*::[*/0x0194/*::]*/: 'IMSIN',
- /*::[*/0x0195/*::]*/: 'IMCOS',
- /*::[*/0x0196/*::]*/: 'IMEXP',
- /*::[*/0x0197/*::]*/: 'IMARGUMENT',
- /*::[*/0x0198/*::]*/: 'IMCONJUGATE',
- /*::[*/0x0199/*::]*/: 'IMAGINARY',
- /*::[*/0x019A/*::]*/: 'IMREAL',
- /*::[*/0x019B/*::]*/: 'COMPLEX',
- /*::[*/0x019C/*::]*/: 'IMSUM',
- /*::[*/0x019D/*::]*/: 'IMPRODUCT',
- /*::[*/0x019E/*::]*/: 'SERIESSUM',
- /*::[*/0x019F/*::]*/: 'FACTDOUBLE',
- /*::[*/0x01A0/*::]*/: 'SQRTPI',
- /*::[*/0x01A1/*::]*/: 'QUOTIENT',
- /*::[*/0x01A2/*::]*/: 'DELTA',
- /*::[*/0x01A3/*::]*/: 'GESTEP',
- /*::[*/0x01A4/*::]*/: 'ISEVEN',
- /*::[*/0x01A5/*::]*/: 'ISODD',
- /*::[*/0x01A6/*::]*/: 'MROUND',
- /*::[*/0x01A7/*::]*/: 'ERF',
- /*::[*/0x01A8/*::]*/: 'ERFC',
- /*::[*/0x01A9/*::]*/: 'BESSELJ',
- /*::[*/0x01AA/*::]*/: 'BESSELK',
- /*::[*/0x01AB/*::]*/: 'BESSELY',
- /*::[*/0x01AC/*::]*/: 'BESSELI',
- /*::[*/0x01AD/*::]*/: 'XIRR',
- /*::[*/0x01AE/*::]*/: 'XNPV',
- /*::[*/0x01AF/*::]*/: 'PRICEMAT',
- /*::[*/0x01B0/*::]*/: 'YIELDMAT',
- /*::[*/0x01B1/*::]*/: 'INTRATE',
- /*::[*/0x01B2/*::]*/: 'RECEIVED',
- /*::[*/0x01B3/*::]*/: 'DISC',
- /*::[*/0x01B4/*::]*/: 'PRICEDISC',
- /*::[*/0x01B5/*::]*/: 'YIELDDISC',
- /*::[*/0x01B6/*::]*/: 'TBILLEQ',
- /*::[*/0x01B7/*::]*/: 'TBILLPRICE',
- /*::[*/0x01B8/*::]*/: 'TBILLYIELD',
- /*::[*/0x01B9/*::]*/: 'PRICE',
- /*::[*/0x01BA/*::]*/: 'YIELD',
- /*::[*/0x01BB/*::]*/: 'DOLLARDE',
- /*::[*/0x01BC/*::]*/: 'DOLLARFR',
- /*::[*/0x01BD/*::]*/: 'NOMINAL',
- /*::[*/0x01BE/*::]*/: 'EFFECT',
- /*::[*/0x01BF/*::]*/: 'CUMPRINC',
- /*::[*/0x01C0/*::]*/: 'CUMIPMT',
- /*::[*/0x01C1/*::]*/: 'EDATE',
- /*::[*/0x01C2/*::]*/: 'EOMONTH',
- /*::[*/0x01C3/*::]*/: 'YEARFRAC',
- /*::[*/0x01C4/*::]*/: 'COUPDAYBS',
- /*::[*/0x01C5/*::]*/: 'COUPDAYS',
- /*::[*/0x01C6/*::]*/: 'COUPDAYSNC',
- /*::[*/0x01C7/*::]*/: 'COUPNCD',
- /*::[*/0x01C8/*::]*/: 'COUPNUM',
- /*::[*/0x01C9/*::]*/: 'COUPPCD',
- /*::[*/0x01CA/*::]*/: 'DURATION',
- /*::[*/0x01CB/*::]*/: 'MDURATION',
- /*::[*/0x01CC/*::]*/: 'ODDLPRICE',
- /*::[*/0x01CD/*::]*/: 'ODDLYIELD',
- /*::[*/0x01CE/*::]*/: 'ODDFPRICE',
- /*::[*/0x01CF/*::]*/: 'ODDFYIELD',
- /*::[*/0x01D0/*::]*/: 'RANDBETWEEN',
- /*::[*/0x01D1/*::]*/: 'WEEKNUM',
- /*::[*/0x01D2/*::]*/: 'AMORDEGRC',
- /*::[*/0x01D3/*::]*/: 'AMORLINC',
- /*::[*/0x01D4/*::]*/: 'CONVERT',
- /*::[*/0x02D4/*::]*/: 'SHEETJS',
- /*::[*/0x01D5/*::]*/: 'ACCRINT',
- /*::[*/0x01D6/*::]*/: 'ACCRINTM',
- /*::[*/0x01D7/*::]*/: 'WORKDAY',
- /*::[*/0x01D8/*::]*/: 'NETWORKDAYS',
- /*::[*/0x01D9/*::]*/: 'GCD',
- /*::[*/0x01DA/*::]*/: 'MULTINOMIAL',
- /*::[*/0x01DB/*::]*/: 'LCM',
- /*::[*/0x01DC/*::]*/: 'FVSCHEDULE',
- /*::[*/0x01DD/*::]*/: 'CUBEKPIMEMBER',
- /*::[*/0x01DE/*::]*/: 'CUBESET',
- /*::[*/0x01DF/*::]*/: 'CUBESETCOUNT',
- /*::[*/0x01E0/*::]*/: 'IFERROR',
- /*::[*/0x01E1/*::]*/: 'COUNTIFS',
- /*::[*/0x01E2/*::]*/: 'SUMIFS',
- /*::[*/0x01E3/*::]*/: 'AVERAGEIF',
- /*::[*/0x01E4/*::]*/: 'AVERAGEIFS'
+ 0: "COUNT",
+ 1: "IF",
+ 2: "ISNA",
+ 3: "ISERROR",
+ 4: "SUM",
+ 5: "AVERAGE",
+ 6: "MIN",
+ 7: "MAX",
+ 8: "ROW",
+ 9: "COLUMN",
+ 10: "NA",
+ 11: "NPV",
+ 12: "STDEV",
+ 13: "DOLLAR",
+ 14: "FIXED",
+ 15: "SIN",
+ 16: "COS",
+ 17: "TAN",
+ 18: "ATAN",
+ 19: "PI",
+ 20: "SQRT",
+ 21: "EXP",
+ 22: "LN",
+ 23: "LOG10",
+ 24: "ABS",
+ 25: "INT",
+ 26: "SIGN",
+ 27: "ROUND",
+ 28: "LOOKUP",
+ 29: "INDEX",
+ 30: "REPT",
+ 31: "MID",
+ 32: "LEN",
+ 33: "VALUE",
+ 34: "TRUE",
+ 35: "FALSE",
+ 36: "AND",
+ 37: "OR",
+ 38: "NOT",
+ 39: "MOD",
+ 40: "DCOUNT",
+ 41: "DSUM",
+ 42: "DAVERAGE",
+ 43: "DMIN",
+ 44: "DMAX",
+ 45: "DSTDEV",
+ 46: "VAR",
+ 47: "DVAR",
+ 48: "TEXT",
+ 49: "LINEST",
+ 50: "TREND",
+ 51: "LOGEST",
+ 52: "GROWTH",
+ 53: "GOTO",
+ 54: "HALT",
+ 55: "RETURN",
+ 56: "PV",
+ 57: "FV",
+ 58: "NPER",
+ 59: "PMT",
+ 60: "RATE",
+ 61: "MIRR",
+ 62: "IRR",
+ 63: "RAND",
+ 64: "MATCH",
+ 65: "DATE",
+ 66: "TIME",
+ 67: "DAY",
+ 68: "MONTH",
+ 69: "YEAR",
+ 70: "WEEKDAY",
+ 71: "HOUR",
+ 72: "MINUTE",
+ 73: "SECOND",
+ 74: "NOW",
+ 75: "AREAS",
+ 76: "ROWS",
+ 77: "COLUMNS",
+ 78: "OFFSET",
+ 79: "ABSREF",
+ 80: "RELREF",
+ 81: "ARGUMENT",
+ 82: "SEARCH",
+ 83: "TRANSPOSE",
+ 84: "ERROR",
+ 85: "STEP",
+ 86: "TYPE",
+ 87: "ECHO",
+ 88: "SET.NAME",
+ 89: "CALLER",
+ 90: "DEREF",
+ 91: "WINDOWS",
+ 92: "SERIES",
+ 93: "DOCUMENTS",
+ 94: "ACTIVE.CELL",
+ 95: "SELECTION",
+ 96: "RESULT",
+ 97: "ATAN2",
+ 98: "ASIN",
+ 99: "ACOS",
+ 100: "CHOOSE",
+ 101: "HLOOKUP",
+ 102: "VLOOKUP",
+ 103: "LINKS",
+ 104: "INPUT",
+ 105: "ISREF",
+ 106: "GET.FORMULA",
+ 107: "GET.NAME",
+ 108: "SET.VALUE",
+ 109: "LOG",
+ 110: "EXEC",
+ 111: "CHAR",
+ 112: "LOWER",
+ 113: "UPPER",
+ 114: "PROPER",
+ 115: "LEFT",
+ 116: "RIGHT",
+ 117: "EXACT",
+ 118: "TRIM",
+ 119: "REPLACE",
+ 120: "SUBSTITUTE",
+ 121: "CODE",
+ 122: "NAMES",
+ 123: "DIRECTORY",
+ 124: "FIND",
+ 125: "CELL",
+ 126: "ISERR",
+ 127: "ISTEXT",
+ 128: "ISNUMBER",
+ 129: "ISBLANK",
+ 130: "T",
+ 131: "N",
+ 132: "FOPEN",
+ 133: "FCLOSE",
+ 134: "FSIZE",
+ 135: "FREADLN",
+ 136: "FREAD",
+ 137: "FWRITELN",
+ 138: "FWRITE",
+ 139: "FPOS",
+ 140: "DATEVALUE",
+ 141: "TIMEVALUE",
+ 142: "SLN",
+ 143: "SYD",
+ 144: "DDB",
+ 145: "GET.DEF",
+ 146: "REFTEXT",
+ 147: "TEXTREF",
+ 148: "INDIRECT",
+ 149: "REGISTER",
+ 150: "CALL",
+ 151: "ADD.BAR",
+ 152: "ADD.MENU",
+ 153: "ADD.COMMAND",
+ 154: "ENABLE.COMMAND",
+ 155: "CHECK.COMMAND",
+ 156: "RENAME.COMMAND",
+ 157: "SHOW.BAR",
+ 158: "DELETE.MENU",
+ 159: "DELETE.COMMAND",
+ 160: "GET.CHART.ITEM",
+ 161: "DIALOG.BOX",
+ 162: "CLEAN",
+ 163: "MDETERM",
+ 164: "MINVERSE",
+ 165: "MMULT",
+ 166: "FILES",
+ 167: "IPMT",
+ 168: "PPMT",
+ 169: "COUNTA",
+ 170: "CANCEL.KEY",
+ 171: "FOR",
+ 172: "WHILE",
+ 173: "BREAK",
+ 174: "NEXT",
+ 175: "INITIATE",
+ 176: "REQUEST",
+ 177: "POKE",
+ 178: "EXECUTE",
+ 179: "TERMINATE",
+ 180: "RESTART",
+ 181: "HELP",
+ 182: "GET.BAR",
+ 183: "PRODUCT",
+ 184: "FACT",
+ 185: "GET.CELL",
+ 186: "GET.WORKSPACE",
+ 187: "GET.WINDOW",
+ 188: "GET.DOCUMENT",
+ 189: "DPRODUCT",
+ 190: "ISNONTEXT",
+ 191: "GET.NOTE",
+ 192: "NOTE",
+ 193: "STDEVP",
+ 194: "VARP",
+ 195: "DSTDEVP",
+ 196: "DVARP",
+ 197: "TRUNC",
+ 198: "ISLOGICAL",
+ 199: "DCOUNTA",
+ 200: "DELETE.BAR",
+ 201: "UNREGISTER",
+ 204: "USDOLLAR",
+ 205: "FINDB",
+ 206: "SEARCHB",
+ 207: "REPLACEB",
+ 208: "LEFTB",
+ 209: "RIGHTB",
+ 210: "MIDB",
+ 211: "LENB",
+ 212: "ROUNDUP",
+ 213: "ROUNDDOWN",
+ 214: "ASC",
+ 215: "DBCS",
+ 216: "RANK",
+ 219: "ADDRESS",
+ 220: "DAYS360",
+ 221: "TODAY",
+ 222: "VDB",
+ 223: "ELSE",
+ 224: "ELSE.IF",
+ 225: "END.IF",
+ 226: "FOR.CELL",
+ 227: "MEDIAN",
+ 228: "SUMPRODUCT",
+ 229: "SINH",
+ 230: "COSH",
+ 231: "TANH",
+ 232: "ASINH",
+ 233: "ACOSH",
+ 234: "ATANH",
+ 235: "DGET",
+ 236: "CREATE.OBJECT",
+ 237: "VOLATILE",
+ 238: "LAST.ERROR",
+ 239: "CUSTOM.UNDO",
+ 240: "CUSTOM.REPEAT",
+ 241: "FORMULA.CONVERT",
+ 242: "GET.LINK.INFO",
+ 243: "TEXT.BOX",
+ 244: "INFO",
+ 245: "GROUP",
+ 246: "GET.OBJECT",
+ 247: "DB",
+ 248: "PAUSE",
+ 251: "RESUME",
+ 252: "FREQUENCY",
+ 253: "ADD.TOOLBAR",
+ 254: "DELETE.TOOLBAR",
+ 255: "User",
+ 256: "RESET.TOOLBAR",
+ 257: "EVALUATE",
+ 258: "GET.TOOLBAR",
+ 259: "GET.TOOL",
+ 260: "SPELLING.CHECK",
+ 261: "ERROR.TYPE",
+ 262: "APP.TITLE",
+ 263: "WINDOW.TITLE",
+ 264: "SAVE.TOOLBAR",
+ 265: "ENABLE.TOOL",
+ 266: "PRESS.TOOL",
+ 267: "REGISTER.ID",
+ 268: "GET.WORKBOOK",
+ 269: "AVEDEV",
+ 270: "BETADIST",
+ 271: "GAMMALN",
+ 272: "BETAINV",
+ 273: "BINOMDIST",
+ 274: "CHIDIST",
+ 275: "CHIINV",
+ 276: "COMBIN",
+ 277: "CONFIDENCE",
+ 278: "CRITBINOM",
+ 279: "EVEN",
+ 280: "EXPONDIST",
+ 281: "FDIST",
+ 282: "FINV",
+ 283: "FISHER",
+ 284: "FISHERINV",
+ 285: "FLOOR",
+ 286: "GAMMADIST",
+ 287: "GAMMAINV",
+ 288: "CEILING",
+ 289: "HYPGEOMDIST",
+ 290: "LOGNORMDIST",
+ 291: "LOGINV",
+ 292: "NEGBINOMDIST",
+ 293: "NORMDIST",
+ 294: "NORMSDIST",
+ 295: "NORMINV",
+ 296: "NORMSINV",
+ 297: "STANDARDIZE",
+ 298: "ODD",
+ 299: "PERMUT",
+ 300: "POISSON",
+ 301: "TDIST",
+ 302: "WEIBULL",
+ 303: "SUMXMY2",
+ 304: "SUMX2MY2",
+ 305: "SUMX2PY2",
+ 306: "CHITEST",
+ 307: "CORREL",
+ 308: "COVAR",
+ 309: "FORECAST",
+ 310: "FTEST",
+ 311: "INTERCEPT",
+ 312: "PEARSON",
+ 313: "RSQ",
+ 314: "STEYX",
+ 315: "SLOPE",
+ 316: "TTEST",
+ 317: "PROB",
+ 318: "DEVSQ",
+ 319: "GEOMEAN",
+ 320: "HARMEAN",
+ 321: "SUMSQ",
+ 322: "KURT",
+ 323: "SKEW",
+ 324: "ZTEST",
+ 325: "LARGE",
+ 326: "SMALL",
+ 327: "QUARTILE",
+ 328: "PERCENTILE",
+ 329: "PERCENTRANK",
+ 330: "MODE",
+ 331: "TRIMMEAN",
+ 332: "TINV",
+ 334: "MOVIE.COMMAND",
+ 335: "GET.MOVIE",
+ 336: "CONCATENATE",
+ 337: "POWER",
+ 338: "PIVOT.ADD.DATA",
+ 339: "GET.PIVOT.TABLE",
+ 340: "GET.PIVOT.FIELD",
+ 341: "GET.PIVOT.ITEM",
+ 342: "RADIANS",
+ 343: "DEGREES",
+ 344: "SUBTOTAL",
+ 345: "SUMIF",
+ 346: "COUNTIF",
+ 347: "COUNTBLANK",
+ 348: "SCENARIO.GET",
+ 349: "OPTIONS.LISTS.GET",
+ 350: "ISPMT",
+ 351: "DATEDIF",
+ 352: "DATESTRING",
+ 353: "NUMBERSTRING",
+ 354: "ROMAN",
+ 355: "OPEN.DIALOG",
+ 356: "SAVE.DIALOG",
+ 357: "VIEW.GET",
+ 358: "GETPIVOTDATA",
+ 359: "HYPERLINK",
+ 360: "PHONETIC",
+ 361: "AVERAGEA",
+ 362: "MAXA",
+ 363: "MINA",
+ 364: "STDEVPA",
+ 365: "VARPA",
+ 366: "STDEVA",
+ 367: "VARA",
+ 368: "BAHTTEXT",
+ 369: "THAIDAYOFWEEK",
+ 370: "THAIDIGIT",
+ 371: "THAIMONTHOFYEAR",
+ 372: "THAINUMSOUND",
+ 373: "THAINUMSTRING",
+ 374: "THAISTRINGLENGTH",
+ 375: "ISTHAIDIGIT",
+ 376: "ROUNDBAHTDOWN",
+ 377: "ROUNDBAHTUP",
+ 378: "THAIYEAR",
+ 379: "RTD",
+ 380: "CUBEVALUE",
+ 381: "CUBEMEMBER",
+ 382: "CUBEMEMBERPROPERTY",
+ 383: "CUBERANKEDMEMBER",
+ 384: "HEX2BIN",
+ 385: "HEX2DEC",
+ 386: "HEX2OCT",
+ 387: "DEC2BIN",
+ 388: "DEC2HEX",
+ 389: "DEC2OCT",
+ 390: "OCT2BIN",
+ 391: "OCT2HEX",
+ 392: "OCT2DEC",
+ 393: "BIN2DEC",
+ 394: "BIN2OCT",
+ 395: "BIN2HEX",
+ 396: "IMSUB",
+ 397: "IMDIV",
+ 398: "IMPOWER",
+ 399: "IMABS",
+ 400: "IMSQRT",
+ 401: "IMLN",
+ 402: "IMLOG2",
+ 403: "IMLOG10",
+ 404: "IMSIN",
+ 405: "IMCOS",
+ 406: "IMEXP",
+ 407: "IMARGUMENT",
+ 408: "IMCONJUGATE",
+ 409: "IMAGINARY",
+ 410: "IMREAL",
+ 411: "COMPLEX",
+ 412: "IMSUM",
+ 413: "IMPRODUCT",
+ 414: "SERIESSUM",
+ 415: "FACTDOUBLE",
+ 416: "SQRTPI",
+ 417: "QUOTIENT",
+ 418: "DELTA",
+ 419: "GESTEP",
+ 420: "ISEVEN",
+ 421: "ISODD",
+ 422: "MROUND",
+ 423: "ERF",
+ 424: "ERFC",
+ 425: "BESSELJ",
+ 426: "BESSELK",
+ 427: "BESSELY",
+ 428: "BESSELI",
+ 429: "XIRR",
+ 430: "XNPV",
+ 431: "PRICEMAT",
+ 432: "YIELDMAT",
+ 433: "INTRATE",
+ 434: "RECEIVED",
+ 435: "DISC",
+ 436: "PRICEDISC",
+ 437: "YIELDDISC",
+ 438: "TBILLEQ",
+ 439: "TBILLPRICE",
+ 440: "TBILLYIELD",
+ 441: "PRICE",
+ 442: "YIELD",
+ 443: "DOLLARDE",
+ 444: "DOLLARFR",
+ 445: "NOMINAL",
+ 446: "EFFECT",
+ 447: "CUMPRINC",
+ 448: "CUMIPMT",
+ 449: "EDATE",
+ 450: "EOMONTH",
+ 451: "YEARFRAC",
+ 452: "COUPDAYBS",
+ 453: "COUPDAYS",
+ 454: "COUPDAYSNC",
+ 455: "COUPNCD",
+ 456: "COUPNUM",
+ 457: "COUPPCD",
+ 458: "DURATION",
+ 459: "MDURATION",
+ 460: "ODDLPRICE",
+ 461: "ODDLYIELD",
+ 462: "ODDFPRICE",
+ 463: "ODDFYIELD",
+ 464: "RANDBETWEEN",
+ 465: "WEEKNUM",
+ 466: "AMORDEGRC",
+ 467: "AMORLINC",
+ 468: "CONVERT",
+ 724: "SHEETJS",
+ 469: "ACCRINT",
+ 470: "ACCRINTM",
+ 471: "WORKDAY",
+ 472: "NETWORKDAYS",
+ 473: "GCD",
+ 474: "MULTINOMIAL",
+ 475: "LCM",
+ 476: "FVSCHEDULE",
+ 477: "CUBEKPIMEMBER",
+ 478: "CUBESET",
+ 479: "CUBESETCOUNT",
+ 480: "IFERROR",
+ 481: "COUNTIFS",
+ 482: "SUMIFS",
+ 483: "AVERAGEIF",
+ 484: "AVERAGEIFS"
};
var FtabArgc = {
- /*::[*/0x0002/*::]*/: 1, /* ISNA */
- /*::[*/0x0003/*::]*/: 1, /* ISERROR */
- /*::[*/0x000A/*::]*/: 0, /* NA */
- /*::[*/0x000F/*::]*/: 1, /* SIN */
- /*::[*/0x0010/*::]*/: 1, /* COS */
- /*::[*/0x0011/*::]*/: 1, /* TAN */
- /*::[*/0x0012/*::]*/: 1, /* ATAN */
- /*::[*/0x0013/*::]*/: 0, /* PI */
- /*::[*/0x0014/*::]*/: 1, /* SQRT */
- /*::[*/0x0015/*::]*/: 1, /* EXP */
- /*::[*/0x0016/*::]*/: 1, /* LN */
- /*::[*/0x0017/*::]*/: 1, /* LOG10 */
- /*::[*/0x0018/*::]*/: 1, /* ABS */
- /*::[*/0x0019/*::]*/: 1, /* INT */
- /*::[*/0x001A/*::]*/: 1, /* SIGN */
- /*::[*/0x001B/*::]*/: 2, /* ROUND */
- /*::[*/0x001E/*::]*/: 2, /* REPT */
- /*::[*/0x001F/*::]*/: 3, /* MID */
- /*::[*/0x0020/*::]*/: 1, /* LEN */
- /*::[*/0x0021/*::]*/: 1, /* VALUE */
- /*::[*/0x0022/*::]*/: 0, /* TRUE */
- /*::[*/0x0023/*::]*/: 0, /* FALSE */
- /*::[*/0x0026/*::]*/: 1, /* NOT */
- /*::[*/0x0027/*::]*/: 2, /* MOD */
- /*::[*/0x0028/*::]*/: 3, /* DCOUNT */
- /*::[*/0x0029/*::]*/: 3, /* DSUM */
- /*::[*/0x002A/*::]*/: 3, /* DAVERAGE */
- /*::[*/0x002B/*::]*/: 3, /* DMIN */
- /*::[*/0x002C/*::]*/: 3, /* DMAX */
- /*::[*/0x002D/*::]*/: 3, /* DSTDEV */
- /*::[*/0x002F/*::]*/: 3, /* DVAR */
- /*::[*/0x0030/*::]*/: 2, /* TEXT */
- /*::[*/0x0035/*::]*/: 1, /* GOTO */
- /*::[*/0x003D/*::]*/: 3, /* MIRR */
- /*::[*/0x003F/*::]*/: 0, /* RAND */
- /*::[*/0x0041/*::]*/: 3, /* DATE */
- /*::[*/0x0042/*::]*/: 3, /* TIME */
- /*::[*/0x0043/*::]*/: 1, /* DAY */
- /*::[*/0x0044/*::]*/: 1, /* MONTH */
- /*::[*/0x0045/*::]*/: 1, /* YEAR */
- /*::[*/0x0046/*::]*/: 1, /* WEEKDAY */
- /*::[*/0x0047/*::]*/: 1, /* HOUR */
- /*::[*/0x0048/*::]*/: 1, /* MINUTE */
- /*::[*/0x0049/*::]*/: 1, /* SECOND */
- /*::[*/0x004A/*::]*/: 0, /* NOW */
- /*::[*/0x004B/*::]*/: 1, /* AREAS */
- /*::[*/0x004C/*::]*/: 1, /* ROWS */
- /*::[*/0x004D/*::]*/: 1, /* COLUMNS */
- /*::[*/0x004F/*::]*/: 2, /* ABSREF */
- /*::[*/0x0050/*::]*/: 2, /* RELREF */
- /*::[*/0x0053/*::]*/: 1, /* TRANSPOSE */
- /*::[*/0x0055/*::]*/: 0, /* STEP */
- /*::[*/0x0056/*::]*/: 1, /* TYPE */
- /*::[*/0x0059/*::]*/: 0, /* CALLER */
- /*::[*/0x005A/*::]*/: 1, /* DEREF */
- /*::[*/0x005E/*::]*/: 0, /* ACTIVE.CELL */
- /*::[*/0x005F/*::]*/: 0, /* SELECTION */
- /*::[*/0x0061/*::]*/: 2, /* ATAN2 */
- /*::[*/0x0062/*::]*/: 1, /* ASIN */
- /*::[*/0x0063/*::]*/: 1, /* ACOS */
- /*::[*/0x0065/*::]*/: 3, /* HLOOKUP */
- /*::[*/0x0066/*::]*/: 3, /* VLOOKUP */
- /*::[*/0x0069/*::]*/: 1, /* ISREF */
- /*::[*/0x006A/*::]*/: 1, /* GET.FORMULA */
- /*::[*/0x006C/*::]*/: 2, /* SET.VALUE */
- /*::[*/0x006F/*::]*/: 1, /* CHAR */
- /*::[*/0x0070/*::]*/: 1, /* LOWER */
- /*::[*/0x0071/*::]*/: 1, /* UPPER */
- /*::[*/0x0072/*::]*/: 1, /* PROPER */
- /*::[*/0x0075/*::]*/: 2, /* EXACT */
- /*::[*/0x0076/*::]*/: 1, /* TRIM */
- /*::[*/0x0077/*::]*/: 4, /* REPLACE */
- /*::[*/0x0079/*::]*/: 1, /* CODE */
- /*::[*/0x007E/*::]*/: 1, /* ISERR */
- /*::[*/0x007F/*::]*/: 1, /* ISTEXT */
- /*::[*/0x0080/*::]*/: 1, /* ISNUMBER */
- /*::[*/0x0081/*::]*/: 1, /* ISBLANK */
- /*::[*/0x0082/*::]*/: 1, /* T */
- /*::[*/0x0083/*::]*/: 1, /* N */
- /*::[*/0x0085/*::]*/: 1, /* FCLOSE */
- /*::[*/0x0086/*::]*/: 1, /* FSIZE */
- /*::[*/0x0087/*::]*/: 1, /* FREADLN */
- /*::[*/0x0088/*::]*/: 2, /* FREAD */
- /*::[*/0x0089/*::]*/: 2, /* FWRITELN */
- /*::[*/0x008A/*::]*/: 2, /* FWRITE */
- /*::[*/0x008C/*::]*/: 1, /* DATEVALUE */
- /*::[*/0x008D/*::]*/: 1, /* TIMEVALUE */
- /*::[*/0x008E/*::]*/: 3, /* SLN */
- /*::[*/0x008F/*::]*/: 4, /* SYD */
- /*::[*/0x0090/*::]*/: 4, /* DDB */
- /*::[*/0x00A1/*::]*/: 1, /* DIALOG.BOX */
- /*::[*/0x00A2/*::]*/: 1, /* CLEAN */
- /*::[*/0x00A3/*::]*/: 1, /* MDETERM */
- /*::[*/0x00A4/*::]*/: 1, /* MINVERSE */
- /*::[*/0x00A5/*::]*/: 2, /* MMULT */
- /*::[*/0x00AC/*::]*/: 1, /* WHILE */
- /*::[*/0x00AF/*::]*/: 2, /* INITIATE */
- /*::[*/0x00B0/*::]*/: 2, /* REQUEST */
- /*::[*/0x00B1/*::]*/: 3, /* POKE */
- /*::[*/0x00B2/*::]*/: 2, /* EXECUTE */
- /*::[*/0x00B3/*::]*/: 1, /* TERMINATE */
- /*::[*/0x00B8/*::]*/: 1, /* FACT */
- /*::[*/0x00BA/*::]*/: 1, /* GET.WORKSPACE */
- /*::[*/0x00BD/*::]*/: 3, /* DPRODUCT */
- /*::[*/0x00BE/*::]*/: 1, /* ISNONTEXT */
- /*::[*/0x00C3/*::]*/: 3, /* DSTDEVP */
- /*::[*/0x00C4/*::]*/: 3, /* DVARP */
- /*::[*/0x00C5/*::]*/: 1, /* TRUNC */
- /*::[*/0x00C6/*::]*/: 1, /* ISLOGICAL */
- /*::[*/0x00C7/*::]*/: 3, /* DCOUNTA */
- /*::[*/0x00C9/*::]*/: 1, /* UNREGISTER */
- /*::[*/0x00CF/*::]*/: 4, /* REPLACEB */
- /*::[*/0x00D2/*::]*/: 3, /* MIDB */
- /*::[*/0x00D3/*::]*/: 1, /* LENB */
- /*::[*/0x00D4/*::]*/: 2, /* ROUNDUP */
- /*::[*/0x00D5/*::]*/: 2, /* ROUNDDOWN */
- /*::[*/0x00D6/*::]*/: 1, /* ASC */
- /*::[*/0x00D7/*::]*/: 1, /* DBCS */
- /*::[*/0x00E1/*::]*/: 0, /* END.IF */
- /*::[*/0x00E5/*::]*/: 1, /* SINH */
- /*::[*/0x00E6/*::]*/: 1, /* COSH */
- /*::[*/0x00E7/*::]*/: 1, /* TANH */
- /*::[*/0x00E8/*::]*/: 1, /* ASINH */
- /*::[*/0x00E9/*::]*/: 1, /* ACOSH */
- /*::[*/0x00EA/*::]*/: 1, /* ATANH */
- /*::[*/0x00EB/*::]*/: 3, /* DGET */
- /*::[*/0x00F4/*::]*/: 1, /* INFO */
- /*::[*/0x00F7/*::]*/: 4, /* DB */
- /*::[*/0x00FC/*::]*/: 2, /* FREQUENCY */
- /*::[*/0x0101/*::]*/: 1, /* EVALUATE */
- /*::[*/0x0105/*::]*/: 1, /* ERROR.TYPE */
- /*::[*/0x010F/*::]*/: 1, /* GAMMALN */
- /*::[*/0x0111/*::]*/: 4, /* BINOMDIST */
- /*::[*/0x0112/*::]*/: 2, /* CHIDIST */
- /*::[*/0x0113/*::]*/: 2, /* CHIINV */
- /*::[*/0x0114/*::]*/: 2, /* COMBIN */
- /*::[*/0x0115/*::]*/: 3, /* CONFIDENCE */
- /*::[*/0x0116/*::]*/: 3, /* CRITBINOM */
- /*::[*/0x0117/*::]*/: 1, /* EVEN */
- /*::[*/0x0118/*::]*/: 3, /* EXPONDIST */
- /*::[*/0x0119/*::]*/: 3, /* FDIST */
- /*::[*/0x011A/*::]*/: 3, /* FINV */
- /*::[*/0x011B/*::]*/: 1, /* FISHER */
- /*::[*/0x011C/*::]*/: 1, /* FISHERINV */
- /*::[*/0x011D/*::]*/: 2, /* FLOOR */
- /*::[*/0x011E/*::]*/: 4, /* GAMMADIST */
- /*::[*/0x011F/*::]*/: 3, /* GAMMAINV */
- /*::[*/0x0120/*::]*/: 2, /* CEILING */
- /*::[*/0x0121/*::]*/: 4, /* HYPGEOMDIST */
- /*::[*/0x0122/*::]*/: 3, /* LOGNORMDIST */
- /*::[*/0x0123/*::]*/: 3, /* LOGINV */
- /*::[*/0x0124/*::]*/: 3, /* NEGBINOMDIST */
- /*::[*/0x0125/*::]*/: 4, /* NORMDIST */
- /*::[*/0x0126/*::]*/: 1, /* NORMSDIST */
- /*::[*/0x0127/*::]*/: 3, /* NORMINV */
- /*::[*/0x0128/*::]*/: 1, /* NORMSINV */
- /*::[*/0x0129/*::]*/: 3, /* STANDARDIZE */
- /*::[*/0x012A/*::]*/: 1, /* ODD */
- /*::[*/0x012B/*::]*/: 2, /* PERMUT */
- /*::[*/0x012C/*::]*/: 3, /* POISSON */
- /*::[*/0x012D/*::]*/: 3, /* TDIST */
- /*::[*/0x012E/*::]*/: 4, /* WEIBULL */
- /*::[*/0x012F/*::]*/: 2, /* SUMXMY2 */
- /*::[*/0x0130/*::]*/: 2, /* SUMX2MY2 */
- /*::[*/0x0131/*::]*/: 2, /* SUMX2PY2 */
- /*::[*/0x0132/*::]*/: 2, /* CHITEST */
- /*::[*/0x0133/*::]*/: 2, /* CORREL */
- /*::[*/0x0134/*::]*/: 2, /* COVAR */
- /*::[*/0x0135/*::]*/: 3, /* FORECAST */
- /*::[*/0x0136/*::]*/: 2, /* FTEST */
- /*::[*/0x0137/*::]*/: 2, /* INTERCEPT */
- /*::[*/0x0138/*::]*/: 2, /* PEARSON */
- /*::[*/0x0139/*::]*/: 2, /* RSQ */
- /*::[*/0x013A/*::]*/: 2, /* STEYX */
- /*::[*/0x013B/*::]*/: 2, /* SLOPE */
- /*::[*/0x013C/*::]*/: 4, /* TTEST */
- /*::[*/0x0145/*::]*/: 2, /* LARGE */
- /*::[*/0x0146/*::]*/: 2, /* SMALL */
- /*::[*/0x0147/*::]*/: 2, /* QUARTILE */
- /*::[*/0x0148/*::]*/: 2, /* PERCENTILE */
- /*::[*/0x014B/*::]*/: 2, /* TRIMMEAN */
- /*::[*/0x014C/*::]*/: 2, /* TINV */
- /*::[*/0x0151/*::]*/: 2, /* POWER */
- /*::[*/0x0156/*::]*/: 1, /* RADIANS */
- /*::[*/0x0157/*::]*/: 1, /* DEGREES */
- /*::[*/0x015A/*::]*/: 2, /* COUNTIF */
- /*::[*/0x015B/*::]*/: 1, /* COUNTBLANK */
- /*::[*/0x015E/*::]*/: 4, /* ISPMT */
- /*::[*/0x015F/*::]*/: 3, /* DATEDIF */
- /*::[*/0x0160/*::]*/: 1, /* DATESTRING */
- /*::[*/0x0161/*::]*/: 2, /* NUMBERSTRING */
- /*::[*/0x0168/*::]*/: 1, /* PHONETIC */
- /*::[*/0x0170/*::]*/: 1, /* BAHTTEXT */
- /*::[*/0x0171/*::]*/: 1, /* THAIDAYOFWEEK */
- /*::[*/0x0172/*::]*/: 1, /* THAIDIGIT */
- /*::[*/0x0173/*::]*/: 1, /* THAIMONTHOFYEAR */
- /*::[*/0x0174/*::]*/: 1, /* THAINUMSOUND */
- /*::[*/0x0175/*::]*/: 1, /* THAINUMSTRING */
- /*::[*/0x0176/*::]*/: 1, /* THAISTRINGLENGTH */
- /*::[*/0x0177/*::]*/: 1, /* ISTHAIDIGIT */
- /*::[*/0x0178/*::]*/: 1, /* ROUNDBAHTDOWN */
- /*::[*/0x0179/*::]*/: 1, /* ROUNDBAHTUP */
- /*::[*/0x017A/*::]*/: 1, /* THAIYEAR */
- /*::[*/0x017E/*::]*/: 3, /* CUBEMEMBERPROPERTY */
- /*::[*/0x0181/*::]*/: 1, /* HEX2DEC */
- /*::[*/0x0188/*::]*/: 1, /* OCT2DEC */
- /*::[*/0x0189/*::]*/: 1, /* BIN2DEC */
- /*::[*/0x018C/*::]*/: 2, /* IMSUB */
- /*::[*/0x018D/*::]*/: 2, /* IMDIV */
- /*::[*/0x018E/*::]*/: 2, /* IMPOWER */
- /*::[*/0x018F/*::]*/: 1, /* IMABS */
- /*::[*/0x0190/*::]*/: 1, /* IMSQRT */
- /*::[*/0x0191/*::]*/: 1, /* IMLN */
- /*::[*/0x0192/*::]*/: 1, /* IMLOG2 */
- /*::[*/0x0193/*::]*/: 1, /* IMLOG10 */
- /*::[*/0x0194/*::]*/: 1, /* IMSIN */
- /*::[*/0x0195/*::]*/: 1, /* IMCOS */
- /*::[*/0x0196/*::]*/: 1, /* IMEXP */
- /*::[*/0x0197/*::]*/: 1, /* IMARGUMENT */
- /*::[*/0x0198/*::]*/: 1, /* IMCONJUGATE */
- /*::[*/0x0199/*::]*/: 1, /* IMAGINARY */
- /*::[*/0x019A/*::]*/: 1, /* IMREAL */
- /*::[*/0x019E/*::]*/: 4, /* SERIESSUM */
- /*::[*/0x019F/*::]*/: 1, /* FACTDOUBLE */
- /*::[*/0x01A0/*::]*/: 1, /* SQRTPI */
- /*::[*/0x01A1/*::]*/: 2, /* QUOTIENT */
- /*::[*/0x01A4/*::]*/: 1, /* ISEVEN */
- /*::[*/0x01A5/*::]*/: 1, /* ISODD */
- /*::[*/0x01A6/*::]*/: 2, /* MROUND */
- /*::[*/0x01A8/*::]*/: 1, /* ERFC */
- /*::[*/0x01A9/*::]*/: 2, /* BESSELJ */
- /*::[*/0x01AA/*::]*/: 2, /* BESSELK */
- /*::[*/0x01AB/*::]*/: 2, /* BESSELY */
- /*::[*/0x01AC/*::]*/: 2, /* BESSELI */
- /*::[*/0x01AE/*::]*/: 3, /* XNPV */
- /*::[*/0x01B6/*::]*/: 3, /* TBILLEQ */
- /*::[*/0x01B7/*::]*/: 3, /* TBILLPRICE */
- /*::[*/0x01B8/*::]*/: 3, /* TBILLYIELD */
- /*::[*/0x01BB/*::]*/: 2, /* DOLLARDE */
- /*::[*/0x01BC/*::]*/: 2, /* DOLLARFR */
- /*::[*/0x01BD/*::]*/: 2, /* NOMINAL */
- /*::[*/0x01BE/*::]*/: 2, /* EFFECT */
- /*::[*/0x01BF/*::]*/: 6, /* CUMPRINC */
- /*::[*/0x01C0/*::]*/: 6, /* CUMIPMT */
- /*::[*/0x01C1/*::]*/: 2, /* EDATE */
- /*::[*/0x01C2/*::]*/: 2, /* EOMONTH */
- /*::[*/0x01D0/*::]*/: 2, /* RANDBETWEEN */
- /*::[*/0x01D4/*::]*/: 3, /* CONVERT */
- /*::[*/0x01DC/*::]*/: 2, /* FVSCHEDULE */
- /*::[*/0x01DF/*::]*/: 1, /* CUBESETCOUNT */
- /*::[*/0x01E0/*::]*/: 2, /* IFERROR */
- /*::[*/0xFFFF/*::]*/: 0
+ 2: 1,
+ 3: 1,
+ 10: 0,
+ 15: 1,
+ 16: 1,
+ 17: 1,
+ 18: 1,
+ 19: 0,
+ 20: 1,
+ 21: 1,
+ 22: 1,
+ 23: 1,
+ 24: 1,
+ 25: 1,
+ 26: 1,
+ 27: 2,
+ 30: 2,
+ 31: 3,
+ 32: 1,
+ 33: 1,
+ 34: 0,
+ 35: 0,
+ 38: 1,
+ 39: 2,
+ 40: 3,
+ 41: 3,
+ 42: 3,
+ 43: 3,
+ 44: 3,
+ 45: 3,
+ 47: 3,
+ 48: 2,
+ 53: 1,
+ 61: 3,
+ 63: 0,
+ 65: 3,
+ 66: 3,
+ 67: 1,
+ 68: 1,
+ 69: 1,
+ 70: 1,
+ 71: 1,
+ 72: 1,
+ 73: 1,
+ 74: 0,
+ 75: 1,
+ 76: 1,
+ 77: 1,
+ 79: 2,
+ 80: 2,
+ 83: 1,
+ 85: 0,
+ 86: 1,
+ 89: 0,
+ 90: 1,
+ 94: 0,
+ 95: 0,
+ 97: 2,
+ 98: 1,
+ 99: 1,
+ 101: 3,
+ 102: 3,
+ 105: 1,
+ 106: 1,
+ 108: 2,
+ 111: 1,
+ 112: 1,
+ 113: 1,
+ 114: 1,
+ 117: 2,
+ 118: 1,
+ 119: 4,
+ 121: 1,
+ 126: 1,
+ 127: 1,
+ 128: 1,
+ 129: 1,
+ 130: 1,
+ 131: 1,
+ 133: 1,
+ 134: 1,
+ 135: 1,
+ 136: 2,
+ 137: 2,
+ 138: 2,
+ 140: 1,
+ 141: 1,
+ 142: 3,
+ 143: 4,
+ 144: 4,
+ 161: 1,
+ 162: 1,
+ 163: 1,
+ 164: 1,
+ 165: 2,
+ 172: 1,
+ 175: 2,
+ 176: 2,
+ 177: 3,
+ 178: 2,
+ 179: 1,
+ 184: 1,
+ 186: 1,
+ 189: 3,
+ 190: 1,
+ 195: 3,
+ 196: 3,
+ 197: 1,
+ 198: 1,
+ 199: 3,
+ 201: 1,
+ 207: 4,
+ 210: 3,
+ 211: 1,
+ 212: 2,
+ 213: 2,
+ 214: 1,
+ 215: 1,
+ 225: 0,
+ 229: 1,
+ 230: 1,
+ 231: 1,
+ 232: 1,
+ 233: 1,
+ 234: 1,
+ 235: 3,
+ 244: 1,
+ 247: 4,
+ 252: 2,
+ 257: 1,
+ 261: 1,
+ 271: 1,
+ 273: 4,
+ 274: 2,
+ 275: 2,
+ 276: 2,
+ 277: 3,
+ 278: 3,
+ 279: 1,
+ 280: 3,
+ 281: 3,
+ 282: 3,
+ 283: 1,
+ 284: 1,
+ 285: 2,
+ 286: 4,
+ 287: 3,
+ 288: 2,
+ 289: 4,
+ 290: 3,
+ 291: 3,
+ 292: 3,
+ 293: 4,
+ 294: 1,
+ 295: 3,
+ 296: 1,
+ 297: 3,
+ 298: 1,
+ 299: 2,
+ 300: 3,
+ 301: 3,
+ 302: 4,
+ 303: 2,
+ 304: 2,
+ 305: 2,
+ 306: 2,
+ 307: 2,
+ 308: 2,
+ 309: 3,
+ 310: 2,
+ 311: 2,
+ 312: 2,
+ 313: 2,
+ 314: 2,
+ 315: 2,
+ 316: 4,
+ 325: 2,
+ 326: 2,
+ 327: 2,
+ 328: 2,
+ 331: 2,
+ 332: 2,
+ 337: 2,
+ 342: 1,
+ 343: 1,
+ 346: 2,
+ 347: 1,
+ 350: 4,
+ 351: 3,
+ 352: 1,
+ 353: 2,
+ 360: 1,
+ 368: 1,
+ 369: 1,
+ 370: 1,
+ 371: 1,
+ 372: 1,
+ 373: 1,
+ 374: 1,
+ 375: 1,
+ 376: 1,
+ 377: 1,
+ 378: 1,
+ 382: 3,
+ 385: 1,
+ 392: 1,
+ 393: 1,
+ 396: 2,
+ 397: 2,
+ 398: 2,
+ 399: 1,
+ 400: 1,
+ 401: 1,
+ 402: 1,
+ 403: 1,
+ 404: 1,
+ 405: 1,
+ 406: 1,
+ 407: 1,
+ 408: 1,
+ 409: 1,
+ 410: 1,
+ 414: 4,
+ 415: 1,
+ 416: 1,
+ 417: 2,
+ 420: 1,
+ 421: 1,
+ 422: 2,
+ 424: 1,
+ 425: 2,
+ 426: 2,
+ 427: 2,
+ 428: 2,
+ 430: 3,
+ 438: 3,
+ 439: 3,
+ 440: 3,
+ 443: 2,
+ 444: 2,
+ 445: 2,
+ 446: 2,
+ 447: 6,
+ 448: 6,
+ 449: 2,
+ 450: 2,
+ 464: 2,
+ 468: 3,
+ 476: 2,
+ 479: 1,
+ 480: 2,
+ 65535: 0
};
-/* [MS-XLSX] 2.2.3 Functions */
-/* [MS-XLSB] 2.5.97.10 Ftab */
-var XLSXFutureFunctions = {
- "_xlfn.ACOT": "ACOT",
- "_xlfn.ACOTH": "ACOTH",
- "_xlfn.AGGREGATE": "AGGREGATE",
- "_xlfn.ARABIC": "ARABIC",
- "_xlfn.AVERAGEIF": "AVERAGEIF",
- "_xlfn.AVERAGEIFS": "AVERAGEIFS",
- "_xlfn.BASE": "BASE",
- "_xlfn.BETA.DIST": "BETA.DIST",
- "_xlfn.BETA.INV": "BETA.INV",
- "_xlfn.BINOM.DIST": "BINOM.DIST",
- "_xlfn.BINOM.DIST.RANGE": "BINOM.DIST.RANGE",
- "_xlfn.BINOM.INV": "BINOM.INV",
- "_xlfn.BITAND": "BITAND",
- "_xlfn.BITLSHIFT": "BITLSHIFT",
- "_xlfn.BITOR": "BITOR",
- "_xlfn.BITRSHIFT": "BITRSHIFT",
- "_xlfn.BITXOR": "BITXOR",
- "_xlfn.CEILING.MATH": "CEILING.MATH",
- "_xlfn.CEILING.PRECISE": "CEILING.PRECISE",
- "_xlfn.CHISQ.DIST": "CHISQ.DIST",
- "_xlfn.CHISQ.DIST.RT": "CHISQ.DIST.RT",
- "_xlfn.CHISQ.INV": "CHISQ.INV",
- "_xlfn.CHISQ.INV.RT": "CHISQ.INV.RT",
- "_xlfn.CHISQ.TEST": "CHISQ.TEST",
- "_xlfn.COMBINA": "COMBINA",
- "_xlfn.CONCAT": "CONCAT",
- "_xlfn.CONFIDENCE.NORM": "CONFIDENCE.NORM",
- "_xlfn.CONFIDENCE.T": "CONFIDENCE.T",
- "_xlfn.COT": "COT",
- "_xlfn.COTH": "COTH",
- "_xlfn.COUNTIFS": "COUNTIFS",
- "_xlfn.COVARIANCE.P": "COVARIANCE.P",
- "_xlfn.COVARIANCE.S": "COVARIANCE.S",
- "_xlfn.CSC": "CSC",
- "_xlfn.CSCH": "CSCH",
- "_xlfn.DAYS": "DAYS",
- "_xlfn.DECIMAL": "DECIMAL",
- "_xlfn.ECMA.CEILING": "ECMA.CEILING",
- "_xlfn.ERF.PRECISE": "ERF.PRECISE",
- "_xlfn.ERFC.PRECISE": "ERFC.PRECISE",
- "_xlfn.EXPON.DIST": "EXPON.DIST",
- "_xlfn.F.DIST": "F.DIST",
- "_xlfn.F.DIST.RT": "F.DIST.RT",
- "_xlfn.F.INV": "F.INV",
- "_xlfn.F.INV.RT": "F.INV.RT",
- "_xlfn.F.TEST": "F.TEST",
- "_xlfn.FILTERXML": "FILTERXML",
- "_xlfn.FLOOR.MATH": "FLOOR.MATH",
- "_xlfn.FLOOR.PRECISE": "FLOOR.PRECISE",
- "_xlfn.FORECAST.ETS": "FORECAST.ETS",
- "_xlfn.FORECAST.ETS.CONFINT": "FORECAST.ETS.CONFINT",
- "_xlfn.FORECAST.ETS.SEASONALITY": "FORECAST.ETS.SEASONALITY",
- "_xlfn.FORECAST.ETS.STAT": "FORECAST.ETS.STAT",
- "_xlfn.FORECAST.LINEAR": "FORECAST.LINEAR",
- "_xlfn.FORMULATEXT": "FORMULATEXT",
- "_xlfn.GAMMA": "GAMMA",
- "_xlfn.GAMMA.DIST": "GAMMA.DIST",
- "_xlfn.GAMMA.INV": "GAMMA.INV",
- "_xlfn.GAMMALN.PRECISE": "GAMMALN.PRECISE",
- "_xlfn.GAUSS": "GAUSS",
- "_xlfn.HYPGEOM.DIST": "HYPGEOM.DIST",
- "_xlfn.IFERROR": "IFERROR",
- "_xlfn.IFNA": "IFNA",
- "_xlfn.IFS": "IFS",
- "_xlfn.IMCOSH": "IMCOSH",
- "_xlfn.IMCOT": "IMCOT",
- "_xlfn.IMCSC": "IMCSC",
- "_xlfn.IMCSCH": "IMCSCH",
- "_xlfn.IMSEC": "IMSEC",
- "_xlfn.IMSECH": "IMSECH",
- "_xlfn.IMSINH": "IMSINH",
- "_xlfn.IMTAN": "IMTAN",
- "_xlfn.ISFORMULA": "ISFORMULA",
- "_xlfn.ISO.CEILING": "ISO.CEILING",
- "_xlfn.ISOWEEKNUM": "ISOWEEKNUM",
- "_xlfn.LOGNORM.DIST": "LOGNORM.DIST",
- "_xlfn.LOGNORM.INV": "LOGNORM.INV",
- "_xlfn.MAXIFS": "MAXIFS",
- "_xlfn.MINIFS": "MINIFS",
- "_xlfn.MODE.MULT": "MODE.MULT",
- "_xlfn.MODE.SNGL": "MODE.SNGL",
- "_xlfn.MUNIT": "MUNIT",
- "_xlfn.NEGBINOM.DIST": "NEGBINOM.DIST",
- "_xlfn.NETWORKDAYS.INTL": "NETWORKDAYS.INTL",
- "_xlfn.NIGBINOM": "NIGBINOM",
- "_xlfn.NORM.DIST": "NORM.DIST",
- "_xlfn.NORM.INV": "NORM.INV",
- "_xlfn.NORM.S.DIST": "NORM.S.DIST",
- "_xlfn.NORM.S.INV": "NORM.S.INV",
- "_xlfn.NUMBERVALUE": "NUMBERVALUE",
- "_xlfn.PDURATION": "PDURATION",
- "_xlfn.PERCENTILE.EXC": "PERCENTILE.EXC",
- "_xlfn.PERCENTILE.INC": "PERCENTILE.INC",
- "_xlfn.PERCENTRANK.EXC": "PERCENTRANK.EXC",
- "_xlfn.PERCENTRANK.INC": "PERCENTRANK.INC",
- "_xlfn.PERMUTATIONA": "PERMUTATIONA",
- "_xlfn.PHI": "PHI",
- "_xlfn.POISSON.DIST": "POISSON.DIST",
- "_xlfn.QUARTILE.EXC": "QUARTILE.EXC",
- "_xlfn.QUARTILE.INC": "QUARTILE.INC",
- "_xlfn.QUERYSTRING": "QUERYSTRING",
- "_xlfn.RANK.AVG": "RANK.AVG",
- "_xlfn.RANK.EQ": "RANK.EQ",
- "_xlfn.RRI": "RRI",
- "_xlfn.SEC": "SEC",
- "_xlfn.SECH": "SECH",
- "_xlfn.SHEET": "SHEET",
- "_xlfn.SHEETS": "SHEETS",
- "_xlfn.SKEW.P": "SKEW.P",
- "_xlfn.STDEV.P": "STDEV.P",
- "_xlfn.STDEV.S": "STDEV.S",
- "_xlfn.SUMIFS": "SUMIFS",
- "_xlfn.SWITCH": "SWITCH",
- "_xlfn.T.DIST": "T.DIST",
- "_xlfn.T.DIST.2T": "T.DIST.2T",
- "_xlfn.T.DIST.RT": "T.DIST.RT",
- "_xlfn.T.INV": "T.INV",
- "_xlfn.T.INV.2T": "T.INV.2T",
- "_xlfn.T.TEST": "T.TEST",
- "_xlfn.TEXTJOIN": "TEXTJOIN",
- "_xlfn.UNICHAR": "UNICHAR",
- "_xlfn.UNICODE": "UNICODE",
- "_xlfn.VAR.P": "VAR.P",
- "_xlfn.VAR.S": "VAR.S",
- "_xlfn.WEBSERVICE": "WEBSERVICE",
- "_xlfn.WEIBULL.DIST": "WEIBULL.DIST",
- "_xlfn.WORKDAY.INTL": "WORKDAY.INTL",
- "_xlfn.XOR": "XOR",
- "_xlfn.Z.TEST": "Z.TEST"
-};
-
diff --git a/bits/83_numbers.js b/bits/83_numbers.js
old mode 100755
new mode 100644
diff --git a/demos/chrome/content.js b/demos/chrome/content.js
index 556efe9..493614e 100644
--- a/demos/chrome/content.js
+++ b/demos/chrome/content.js
@@ -7,7 +7,7 @@ document.addEventListener('mousedown', function(mouse) {
});
chrome.runtime.onMessage.addListener(function(msg, sender, cb) {
- if(!msg && !msg['Sheet']) return;
+ if(!msg || !msg['Sheet']) return;
if(msg.Sheet == "JS") {
var elt = document.elementFromPoint(coords[0], coords[1]);
while(elt != null) {
diff --git a/demos/oldie/README.md b/demos/oldie/README.md
index 02ede9d..472f17f 100644
--- a/demos/oldie/README.md
+++ b/demos/oldie/README.md
@@ -1,10 +1,33 @@
# Internet Explorer
-Despite the efforts to deprecate the pertinent operating systems, IE is still
-very popular, required for various government and corporate websites throughout
-the world. The modern upload and download strategies are not available in older
-versions of IE, but there are alternative approaches.
+The modern upload and download strategies are not available in older versions of
+IE, but there are approaches using older technologies like ActiveX and Flash.
+
+ Live Demos (click to show)
+
+ uses XMLHttpRequest to download test
+files and convert to CSV.
+
+ demonstrates reading files with `FileReader`.
+
+Older versions of IE do not support HTML5 File API but do support Base64.
+
+On OSX you can get the Base64 encoding with:
+
+```bash
+$ certutil -encode target_file target_file.b64
+```
+
+(note: You have to open the file and remove the header and footer lines)
+
+
## Upload Strategies
@@ -14,14 +37,14 @@ IE10 and IE11 support the standard HTML5 FileReader API:
```js
function handle_fr(e) {
- var files = e.target.files, f = files[0];
- var reader = new FileReader();
- reader.onload = function(e) {
- var data = new Uint8Array(e.target.result);
- var wb = XLSX.read(data, {type: 'array'});
- process_wb(wb);
- };
- reader.readAsArrayBuffer(f);
+ var files = e.target.files, f = files[0];
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ var data = new Uint8Array(e.target.result);
+ var wb = XLSX.read(data, {type: 'array'});
+ process_wb(wb);
+ };
+ reader.readAsArrayBuffer(f);
}
input_dom_element.addEventListener('change', handle_fr, false);
```
@@ -36,12 +59,12 @@ should be called from a file input `onchange` event:
```js
var input_dom_element = document.getElementById("file");
function handle_ie() {
- /* get data from selected file */
- var path = input_dom_element.value;
- var bstr = IE_LoadFile(path);
- /* read workbook */
- var wb = XLSX.read(bstr, {type: 'binary'});
- /* DO SOMETHING WITH workbook HERE */
+ /* get data from selected file */
+ var path = input_dom_element.value;
+ var bstr = IE_LoadFile(path);
+ /* read workbook */
+ var wb = XLSX.read(bstr, {type: 'binary'});
+ /* DO SOMETHING WITH workbook HERE */
}
input_dom_element.attachEvent('onchange', handle_ie);
```
@@ -105,10 +128,10 @@ to a Base64 string and passing to the library:
```js
Downloadify.create(element_id, {
- /* the demo includes the other options required by Downloadify */
- filename: "test.xlsx",
- data: function() { return XLSX.write(wb, {bookType:"xlsx", type:'base64'}); },
- dataType: 'base64'
+ /* the demo includes the other options required by Downloadify */
+ filename: "test.xlsx",
+ data: function() { return XLSX.write(wb, {bookType:"xlsx", type:'base64'}); },
+ dataType: 'base64'
});
```
diff --git a/demos/react/README.md b/demos/react/README.md
index 060b3bc..5320a8b 100644
--- a/demos/react/README.md
+++ b/demos/react/README.md
@@ -13,7 +13,7 @@ The library can also be imported directly from JSX code with:
import XLSX from 'xlsx';
```
-This demo shows a simple React component transpiled in the browser using the babel
+This demo shows a simple React component transpiled in the browser using Babel
standalone library. Since there is no standard React table model, this demo
settles on the array of arrays approach.
@@ -77,45 +77,29 @@ function make_cols(refstr/*:string*/) {
Reproducing the full project is straightforward:
```bash
-# see native.sh
-react-native init SheetJS
-cd SheetJS
-npm i -S xlsx react react-native react-native-table-component react-native-fs
-cp ../react-native.js index.js
-react-native link
+$ make native # build the project
+$ make ios # build and run the iOS demo
+$ make android # build and run the android demo
```
-`react-native-table-component` draws the data table. `react-native-fs` reads
-and write files on devices. The app will prompt before reading and after
-writing data. The printed location will be:
+The app will prompt before reading and after writing data. The printed location
+depends on the environment:
- android: path in the device filesystem
- iOS simulator: local path to file
- iOS device: a path accessible from iTunes App Documents view
-`react-native-fs` supports `"ascii"` encoding for `readFile` and `writeFile`.
-In practice, that encoding uses binary strings compatible with `"binary"` type:
+Components used in the demo:
+- [`react-native-table-component`](https://npm.im/react-native-table-component)
+- [`react-native-file-access`](https://npm.im/react-native-file-access)
-```js
-import { writeFile, readFile } from 'react-native-fs';
-
-/* read a workbook */
-readFile(file, 'ascii').then((res) => {
- const workbook = XLSX.read(res, {type:'binary'});
- /* DO SOMETHING WITH workbook HERE */
-});
-
-/* write a workbook */
-const wbout = XLSX.write(wb, {type:'binary', bookType:"xlsx"});
-writeFile(file, wbout, 'ascii').then((r)=>{/* :) */}).catch((e)=>{/* :( */});
-```
+React Native does not provide a native component for reading and writing files.
+The sample script <`react-native.js`> uses `react-native-file-access` and has
+notes for integrations with `react-native-fetch-blob` and `react-native-fs`.
Note: for real app deployments, the `UIFileSharingEnabled` flag must be manually
set in the iOS project `Info.plist` file.
-To run the React Native demo, run either `make ios` or `make android` while
-connected to a device or emulator.
-
#### Server-Rendered React Components with Next.js
The demo uses the same component code as the in-browser version, but the build
diff --git a/demos/react/native.sh b/demos/react/native.sh
index 82ba882..d9e4cb4 100755
--- a/demos/react/native.sh
+++ b/demos/react/native.sh
@@ -1,11 +1,17 @@
#!/bin/bash
# xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
-if [ ! -e SheetJS ]; then
- react-native init --version="0.62.2" SheetJS
- cd SheetJS
- npm i -S xlsx react-native-table-component react-native-fs
- cd -
-fi
+
+# Create starter project
+if [ ! -e SheetJS ]; then react-native init SheetJS --version="0.67.2"; fi
+
+# Install dependencies
+cd SheetJS; npm i -S xlsx react-native-table-component; cd -
+
+cd SheetJS; npm i -S react-native-file-access@2.x; cd -
+# cd SheetJS; npm i -S react-native-fs; cd -
+# cd SheetJS; npm i -S react-native-fetch-blob; cd -
+
+# Copy demo assets
if [ ! -e SheetJS/logo.png ]; then
curl -O http://oss.sheetjs.com/assets/img/logo.png
mv logo.png SheetJS/logo.png
@@ -16,6 +22,6 @@ if [ -e SheetJS/index.ios.js ]; then
else
cp react-native.js SheetJS/index.js
fi
-cd SheetJS;
-RNFB_ANDROID_PERMISSIONS=true react-native link
-cd -;
+
+# Link
+cd SheetJS; RNFB_ANDROID_PERMISSIONS=true react-native link; cd -
diff --git a/demos/react/react-native.js b/demos/react/react-native.js
index ef2d933..c29eae6 100644
--- a/demos/react/react-native.js
+++ b/demos/react/react-native.js
@@ -14,12 +14,69 @@ import {
} from 'react-native';
import { Table, Row, Rows, TableWrapper } from 'react-native-table-component';
+// react-native-file-access
+var Base64 = function() {
+ var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+ return {
+ encode: function(input) {
+ var o = "";
+ var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
+ for (var i = 0; i < input.length; ) {
+ c1 = input.charCodeAt(i++);
+ e1 = c1 >> 2;
+ c2 = input.charCodeAt(i++);
+ e2 = (c1 & 3) << 4 | c2 >> 4;
+ c3 = input.charCodeAt(i++);
+ e3 = (c2 & 15) << 2 | c3 >> 6;
+ e4 = c3 & 63;
+ if (isNaN(c2)) {
+ e3 = e4 = 64;
+ } else if (isNaN(c3)) {
+ e4 = 64;
+ }
+ o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4);
+ }
+ return o;
+ },
+ decode: function(input) {
+ var o = "";
+ var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
+ input = input.replace(/[^\w\+\/\=]/g, "");
+ for (var i = 0; i < input.length; ) {
+ e1 = map.indexOf(input.charAt(i++));
+ e2 = map.indexOf(input.charAt(i++));
+ c1 = e1 << 2 | e2 >> 4;
+ o += String.fromCharCode(c1);
+ e3 = map.indexOf(input.charAt(i++));
+ c2 = (e2 & 15) << 4 | e3 >> 2;
+ if (e3 !== 64) {
+ o += String.fromCharCode(c2);
+ }
+ e4 = map.indexOf(input.charAt(i++));
+ c3 = (e3 & 3) << 6 | e4;
+ if (e4 !== 64) {
+ o += String.fromCharCode(c3);
+ }
+ }
+ return o;
+ }
+ };
+}();
+
+import { Dirs, FileSystem } from 'react-native-file-access';
+const DDP = Dirs.DocumentDir + "/";
+const readFile = (path, enc) => FileSystem.readFile(path, "base64");
+const writeFile = (path, data, enc) => FileSystem.writeFile(path, data, "base64");
+const input = res => Base64.decode(res);
+const output = str => Base64.encode(str);
+
// react-native-fs
+/*
import { writeFile, readFile, DocumentDirectoryPath } from 'react-native-fs';
const DDP = DocumentDirectoryPath + "/";
const input = res => res;
const output = str => str;
-
+*/
// react-native-fetch-blob
/*
import RNFetchBlob from 'react-native-fetch-blob';
@@ -36,7 +93,7 @@ export default class SheetJS extends Component {
constructor(props) {
super(props);
this.state = {
- data: [[1,2,3],[4,5,6]],
+ data: [[2,3,4],[3,4,5]],
widthArr: [60, 60, 60],
cols: make_cols("A1:C2")
};
diff --git a/docbits/10_install.md b/docbits/10_install.md
index b6bc764..53ebf20 100644
--- a/docbits/10_install.md
+++ b/docbits/10_install.md
@@ -2,7 +2,8 @@
### Installation
-In the browser, just add a script tag:
+The complete browser standalone build is saved to `dist/xlsx.full.min.js` and
+can be directly added to a page with a `script` tag:
```html
@@ -18,7 +19,7 @@ In the browser, just add a script tag:
| `CDNjs` | |
| `packd` | |
-`unpkg` makes the latest version available at:
+For example, `unpkg` makes the latest version available at:
```html
@@ -26,33 +27,8 @@ In the browser, just add a script tag:
-
-With [npm](https://www.npmjs.org/package/xlsx):
-
-```bash
-$ npm install xlsx
-```
-
-With [bower](https://bower.io/search/?q=js-xlsx):
-
-```bash
-$ bower install js-xlsx
-```
-
- Optional features (click to show)
-
-The node version automatically requires modules for additional features. Some
-of these modules are rather large in size and are only needed in special
-circumstances, so they do not ship with the core. For browser use, they must
-be included directly:
-
-```html
-
-
-```
-
-An appropriate version for each dependency is included in the dist/ directory.
+ Browser builds (click to show)
The complete single-file version is generated at `dist/xlsx.full.min.js`
@@ -74,8 +50,30 @@ be configured to remove support with `resolve.alias`:
+
+With [npm](https://www.npmjs.org/package/xlsx):
+
+```bash
+$ npm install xlsx
+```
+
+With [bower](https://bower.io/search/?q=js-xlsx):
+
+```bash
+$ bower install js-xlsx
+```
+
+`dist/xlsx.extendscript.js` is an ExtendScript build for Photoshop and InDesign
+that is included in the `npm` package. It can be directly referenced with a
+`#include` directive:
+
+```extendscript
+#include "xlsx.extendscript.js"
+```
+
+
- ECMAScript 3 Compatibility (click to show)
+ Internet Explorer and ECMAScript 3 Compatibility (click to show)
For broad compatibility with JavaScript engines, the library is written using
ECMAScript 3 language dialect as well as some ES5 features like `Array#forEach`.
diff --git a/docbits/13_usage.md b/docbits/13_usage.md
index c0263d6..979cdf4 100644
--- a/docbits/13_usage.md
+++ b/docbits/13_usage.md
@@ -31,8 +31,8 @@ var table_elt = document.getElementById("my-table-id");
var workbook = XLSX.utils.table_to_book(table_elt);
// Process Data (add a new row)
-var worksheet = workbook.Sheets["Sheet1"];
-XLSX.utils.sheet_add_aoa([["Created "+new Date().toISOString()}]], {origin:-1});
+var ws = workbook.Sheets["Sheet1"];
+XLSX.utils.sheet_add_aoa(ws, [["Created "+new Date().toISOString()]], {origin:-1});
// Package and Release Data (`writeFile` tries to write and save an XLSB file)
XLSX.writeFile(workbook, "Report.xlsb");
@@ -40,7 +40,8 @@ XLSX.writeFile(workbook, "Report.xlsb");
This library tries to simplify steps 2 and 4 with functions to extract useful
data from spreadsheet files (`read` / `readFile`) and generate new spreadsheet
-files from data (`write` / `writeFile`).
+files from data (`write` / `writeFile`). Additional utility functions like
+`table_to_book` work with other common data sources like HTML tables.
This documentation and various demo projects cover a number of common scenarios
and approaches for steps 1 and 5.
@@ -48,8 +49,210 @@ and approaches for steps 1 and 5.
Utility functions help with step 3.
-#### The Zen of SheetJS
+### The Zen of SheetJS
+_Data processing should fit in any workflow_
+
+The library does not impose a separate lifecycle. It fits nicely in websites
+and apps built using any framework. The plain JS data objects play nice with
+Web Workers and future APIs.
+
+["Acquiring and Extracting Data"](#acquiring-and-extracting-data) describes
+solutions for common data import scenarios.
+
+["Writing Workbooks"](#writing-workbooks) describes solutions for common data
+export scenarios involving actual spreadsheet files.
+
+["Utility Functions"](#utility-functions) details utility functions for
+translating JSON Arrays and other common JS structures into worksheet objects.
+
+_JavaScript is a powerful language for data processing_
+
+The ["Common Spreadsheet Format"](#common-spreadsheet-format) is a simple object
+representation of the core concepts of a workbook. The various functions in the
+library provide low-level tools for working with the object.
+
+For friendly JS processing, there are utility functions for converting parts of
+a worksheet to/from an Array of Arrays. The following example combines powerful
+JS Array methods with a network request library to download data, select the
+information we want and create a workbook file:
+
+
+ Get Data from a JSON Endpoint and Generate a Workbook (click to show)
+
+The goal is to generate a XLSB workbook of US President names and birthdays.
+
+**Acquire Data**
+
+_Raw Data_
+
+ has the desired
+data. For example, John Adams:
+
+```js
+{
+ "id": { /* (data omitted) */ },
+ "name": {
+ "first": "John", // <-- first name
+ "last": "Adams" // <-- last name
+ },
+ "bio": {
+ "birthday": "1735-10-19", // <-- birthday
+ "gender": "M"
+ },
+ "terms": [
+ { "type": "viceprez", /* (other fields omitted) */ },
+ { "type": "viceprez", /* (other fields omitted) */ },
+ { "type": "prez", /* (other fields omitted) */ } // <-- look for "prez"
+ ]
+}
+```
+
+_Filtering for Presidents_
+
+The dataset includes Aaron Burr, a Vice President who was never President!
+
+`Array#filter` creates a new array with the desired rows. A President served
+at least one term with `type` set to `"prez"`. To test if a particular row has
+at least one `"prez"` term, `Array#some` is another native JS function. The
+complete filter would be:
+
+```js
+const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez"));
+```
+
+_Lining up the data_
+
+For this example, the name will be the first name combined with the last name
+(`row.name.first + " " + row.name.last`) and the birthday will be the subfield
+`row.bio.birthday`. Using `Array#map`, the dataset can be massaged in one call:
+
+```js
+const rows = prez.map(row => ({
+ name: row.name.first + " " + row.name.last,
+ birthday: row.bio.birthday
+}));
+```
+
+The result is an array of "simple" objects with no nesting:
+
+```js
+[
+ { name: "George Washington", birthday: "1732-02-22" },
+ { name: "John Adams", birthday: "1735-10-19" },
+ // ... one row per President
+]
+```
+
+**Extract Data**
+
+With the cleaned dataset, `XLSX.utils.json_to_sheet` generates a worksheet:
+
+```js
+const worksheet = XLSX.utils.json_to_sheet(rows);
+```
+
+`XLSX.utils.book_new` creates a new workbook and `XLSX.utils.book_append_sheet`
+appends a worksheet to the workbook. The new worksheet will be called "Dates":
+
+```js
+const workbook = XLSX.utils.book_new();
+XLSX.utils.book_append_sheet(workbook, worksheet, "Dates");
+```
+
+**Process Data**
+
+_Fixing headers_
+
+By default, `json_to_sheet` creates a worksheet with a header row. In this case,
+the headers come from the JS object keys: "name" and "birthday".
+
+The headers are in cells A1 and B1. `XLSX.utils.sheet_add_aoa` can write text
+values to the existing worksheet starting at cell A1:
+
+```js
+XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });
+```
+
+_Fixing Column Widths_
+
+Some of the names are longer than the default column width. Column widths are
+set by [setting the `"!cols"` worksheet property](#row-and-column-properties).
+
+The following line sets the width of column A to approximately 10 characters:
+
+```js
+worksheet["!cols"] = [ { wch: 10 } ]; // set column A width to 10 characters
+```
+
+One `Array#reduce` call over `rows` can calculate the maximum width:
+
+```js
+const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
+worksheet["!cols"] = [ { wch: max_width } ];
+```
+
+Note: If the starting point was a file or HTML table, `XLSX.utils.sheet_to_json`
+will generate an array of JS objects.
+
+**Package and Release Data**
+
+`XLSX.writeFile` creates a spreadsheet file and tries to write it to the system.
+In the browser, it will try to prompt the user to download the file. In NodeJS,
+it will write to the local directory.
+
+```js
+XLSX.writeFile(workbook, "Presidents.xlsx");
+```
+
+**Complete Example**
+
+```js
+// Uncomment the next line for use in NodeJS:
+// const XLSX = require("xlsx"), axios = require("axios");
+
+(async() => {
+ /* fetch JSON data and parse */
+ const url = "https://theunitedstates.io/congress-legislators/executive.json";
+ const raw_data = (await axios(url, {responseType: "json"})).data;
+
+ /* filter for the Presidents */
+ const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez"));
+
+ /* flatten objects */
+ const rows = prez.map(row => ({
+ name: row.name.first + " " + row.name.last,
+ birthday: row.bio.birthday
+ }));
+
+ /* generate worksheet and workbook */
+ const worksheet = XLSX.utils.json_to_sheet(rows);
+ const workbook = XLSX.utils.book_new();
+ XLSX.utils.book_append_sheet(workbook, worksheet, "Dates");
+
+ /* fix headers */
+ XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });
+
+ /* calculate column width */
+ const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
+ worksheet["!cols"] = [ { wch: max_width } ];
+
+ /* create an XLSX file and try to save to Presidents.xlsx */
+ XLSX.writeFile(workbook, "Presidents.xlsx");
+})();
+```
+
+For use in the web browser, assuming the snippet is saved to `snippet.js`,
+script tags should be used to include the `axios` and `xlsx` standalone builds:
+
+```html
+
+
+
+```
+
+
+
_File formats are implementation details_
@@ -59,36 +262,7 @@ The parser covers a wide gamut of common spreadsheet file formats to ensure that
The writer supports a number of common output formats for broad compatibility
with the data ecosystem.
-
-_Data processing should fit in any workflow_
-
-The library does not impose a separate lifecycle. It fits nicely in websites
-and apps built using any framework. The plain JS data objects play nice with
-Web Workers and future APIs.
-
-["Parsing Workbooks"](#parsing-workbooks) describes solutions for common data
-import scenarios involving actual spreadsheet files.
-
-["Writing Workbooks"](#writing-workbooks) describes solutions for common data
-export scenarios involving actual spreadsheet files.
-
-["Utility Functions"](#utility-functions) details utility functions for
-translating JSON Arrays and other common JS structures into worksheet objects.
-
-
-_JavaScript is a powerful language for data processing_
-
-The ["Common Spreadsheet Format"](#common-spreadsheet-format) is a simple object
-representation of the core concepts of a workbook. The various functions in the
-library provide low-level tools for working with the object.
-
-For friendly JS processing, there are utility functions for converting parts of
-a worksheet to/from an Array of Arrays. For example, summing columns from an
-array of arrays can be implemented in a single Array reduce operation:
-
-```js
-var aoa = XLSX.utils.sheet_to_json(worksheet, {header: 1});
-var sum_of_column_B = aoa.reduce((acc, row) => acc + (+row[1]||0), 0);
-```
+To the greatest extent possible, data processing code should not have to worry
+about the specific file formats involved.
diff --git a/docbits/20_import.md b/docbits/20_import.md
index c310a35..5c0bbac 100644
--- a/docbits/20_import.md
+++ b/docbits/20_import.md
@@ -1,82 +1,172 @@
-## Parsing Workbooks
+## Acquiring and Extracting Data
-For parsing, the first step is to read the file. This involves acquiring the
-data and feeding it into the library. Here are a few common scenarios:
+### Parsing Workbooks
-
- nodejs read a file (click to show)
+#### API
-`readFile` is only available in server environments. Browsers have no API for
-reading arbitrary files given a path, so another strategy must be used.
+_Extract data from spreadsheet bytes_
```js
-if(typeof require !== 'undefined') XLSX = require('xlsx');
-var workbook = XLSX.readFile('test.xlsx');
-/* DO SOMETHING WITH workbook HERE */
+var workbook = XLSX.read(data, opts);
+```
+
+The `read` method can extract data from spreadsheet bytes stored in a JS string,
+"binary string", NodeJS buffer or typed array (`Uint8Array` or `ArrayBuffer`).
+
+
+_Read spreadsheet bytes from a local file and extract data_
+
+```js
+var workbook = XLSX.readFile(filename, opts);
+```
+
+The `readFile` method attempts to read a spreadsheet file at the supplied path.
+Browsers generally do not allow reading files in this way (it is deemed a
+security risk), and attempts to read files in this way will throw an error.
+
+The second `opts` argument is optional. ["Parsing Options"](#parsing-options)
+covers the supported properties and behaviors.
+
+#### Examples
+
+Here are a few common scenarios (click on each subtitle to see the code):
+
+
+ Local file in a NodeJS server (click to show)
+
+`readFile` uses `fs.readFileSync` under the hood:
+
+```js
+var XLSX = require("xlsx");
+
+var workbook = XLSX.readFile("test.xlsx");
+```
+
+For Node ESM, the `readFile` helper is not enabled. Instead, `fs.readFileSync`
+should be used to read the file data as a `Buffer` for use with `XLSX.read`:
+
+```js
+import { readFileSync } from "fs";
+import { read } from "xlsx/xlsx.mjs";
+
+const buf = readFileSync("test.xlsx");
+/* buf is a Buffer */
+const workbook = read(buf);
```
- Photoshop ExtendScript read a file (click to show)
+ User-submitted file in a web page ("Drag-and-Drop") (click to show)
-`readFile` wraps the `File` logic in Photoshop and other ExtendScript targets.
-The specified path should be an absolute path:
+For modern websites targeting Chrome 76+, `File#arrayBuffer` is recommended:
```js
-#include "xlsx.extendscript.js"
-/* Read test.xlsx from the Documents folder */
-var workbook = XLSX.readFile(Folder.myDocuments + '/' + 'test.xlsx');
-/* DO SOMETHING WITH workbook HERE */
+// XLSX is a global from the standalone script
+
+async function handleDropAsync(e) {
+ e.stopPropagation(); e.preventDefault();
+ const f = e.dataTransfer.files[0];
+ /* f is a File */
+ const data = await f.arrayBuffer();
+ /* data is an ArrayBuffer */
+ const workbook = XLSX.read(data);
+
+ /* DO SOMETHING WITH workbook HERE */
+}
+drop_dom_element.addEventListener("drop", handleDropAsync, false);
```
-The [`extendscript` demo](demos/extendscript/) includes a more complex example.
+For maximal compatibility, the `FileReader` API should be used:
+
+```js
+function handleDrop(e) {
+ e.stopPropagation(); e.preventDefault();
+ var f = e.dataTransfer.files[0];
+ /* f is a File */
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ var data = e.target.result;
+ /* reader.readAsArrayBuffer(file) -> data will be an ArrayBuffer */
+ var workbook = XLSX.read(data);
+
+ /* DO SOMETHING WITH workbook HERE */
+ };
+ reader.readAsArrayBuffer(f);
+}
+drop_dom_element.addEventListener("drop", handleDrop, false);
+```
+
+ demonstrates the FileReader technique.
- Browser read TABLE element from page (click to show)
+ User-submitted file with an HTML INPUT element (click to show)
-The `table_to_book` and `table_to_sheet` utility functions take a DOM TABLE
-element and iterate through the child nodes.
+Starting with an HTML INPUT element with `type="file"`:
-```js
-var workbook = XLSX.utils.table_to_book(document.getElementById('tableau'));
-/* DO SOMETHING WITH workbook HERE */
+```html
+
```
-Multiple tables on a web page can be converted to individual worksheets:
+For modern websites targeting Chrome 76+, `Blob#arrayBuffer` is recommended:
```js
-/* create new workbook */
-var workbook = XLSX.utils.book_new();
+// XLSX is a global from the standalone script
-/* convert table 'table1' to worksheet named "Sheet1" */
-var ws1 = XLSX.utils.table_to_sheet(document.getElementById('table1'));
-XLSX.utils.book_append_sheet(workbook, ws1, "Sheet1");
+async function handleFileAsync(e) {
+ const file = e.target.files[0];
+ const data = await file.arrayBuffer();
+ /* data is an ArrayBuffer */
+ const workbook = XLSX.read(data);
-/* convert table 'table2' to worksheet named "Sheet2" */
-var ws2 = XLSX.utils.table_to_sheet(document.getElementById('table2'));
-XLSX.utils.book_append_sheet(workbook, ws2, "Sheet2");
-
-/* workbook now has 2 worksheets */
+ /* DO SOMETHING WITH workbook HERE */
+}
+input_dom_element.addEventListener("change", handleFileAsync, false);
```
-Alternatively, the HTML code can be extracted and parsed:
+For broader support (including IE10+), the `FileReader` approach is recommended:
```js
-var htmlstr = document.getElementById('tableau').outerHTML;
-var workbook = XLSX.read(htmlstr, {type:'string'});
+function handleFile(e) {
+ var file = e.target.files[0];
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ var data = e.target.result;
+ /* reader.readAsArrayBuffer(file) -> data will be an ArrayBuffer */
+ var workbook = XLSX.read(e.target.result);
+
+ /* DO SOMETHING WITH workbook HERE */
+ };
+ reader.readAsArrayBuffer(file);
+}
+input_dom_element.addEventListener("change", handleFile, false);
```
+The [`oldie` demo](demos/oldie/) shows an IE-compatible fallback scenario.
+
- Browser download file (ajax) (click to show)
+ Fetching a file in the web browser ("Ajax") (click to show)
-Note: for a more complete example that works in older browsers, check the demo
-at . The [`xhr` demo](demos/xhr/)
-includes more examples with `XMLHttpRequest` and `fetch`.
+For modern websites targeting Chrome 42+, `fetch` is recommended:
+
+```js
+// XLSX is a global from the standalone script
+
+(async() => {
+ const url = "http://oss.sheetjs.com/test_files/formula_stress_test.xlsx";
+ const data = await (await fetch(url)).arrayBuffer();
+ /* data is an ArrayBuffer */
+ const workbook = XLSX.read(data);
+
+ /* DO SOMETHING WITH workbook HERE */
+})();
+```
+
+For broader support, the `XMLHttpRequest` approach is recommended:
```js
var url = "http://oss.sheetjs.com/test_files/formula_stress_test.xlsx";
@@ -90,116 +180,248 @@ req.onload = function(e) {
var workbook = XLSX.read(req.response);
/* DO SOMETHING WITH workbook HERE */
-}
+};
req.send();
```
+The [`xhr` demo](demos/xhr/) includes a longer discussion and more examples.
+
+ shows fallback approaches for IE6+.
+
- Browser drag-and-drop (click to show)
+ Local file in a PhotoShop or InDesign plugin (click to show)
-For modern browsers, `Blob#arrayBuffer` can read data from files:
+`readFile` wraps the `File` logic in Photoshop and other ExtendScript targets.
+The specified path should be an absolute path:
```js
-async function handleDropAsync(e) {
- e.stopPropagation(); e.preventDefault();
- const f = evt.dataTransfer.files[0];
- const data = await f.arrayBuffer();
- const workbook = XLSX.read(data);
+#include "xlsx.extendscript.js"
- /* DO SOMETHING WITH workbook HERE */
-}
-drop_dom_element.addEventListener('drop', handleDropAsync, false);
+/* Read test.xlsx from the Documents folder */
+var workbook = XLSX.readFile(Folder.myDocuments + "/test.xlsx");
```
-For maximal compatibility, the `FileReader` API should be used:
+The [`extendscript` demo](demos/extendscript/) includes a more complex example.
+
+
+
+
+ Local file in an Electron app (click to show)
+
+`readFile` can be used in the renderer process:
```js
-function handleDrop(e) {
- e.stopPropagation(); e.preventDefault();
- var f = e.dataTransfer.files[0];
- var reader = new FileReader();
- reader.onload = function(e) {
- var workbook = XLSX.read(e.target.result);
+/* From the renderer process */
+var XLSX = require("xlsx");
+
+var workbook = XLSX.readFile(path);
+```
+
+Electron APIs have changed over time. The [`electron` demo](demos/electron/)
+shows a complete example and details the required version-specific settings.
+
+
+
+
+ Local file in a mobile app with React Native (click to show)
+
+The [`react` demo](demos/react) includes a sample React Native app.
+
+Since React Native does not provide a way to read files from the filesystem, a
+third-party library must be used. The following libraries have been tested:
+
+- [`react-native-file-access`](https://npm.im/react-native-file-access)
+
+The `base64` encoding returns strings compatible with the `base64` type:
+
+```js
+import XLSX from "xlsx";
+import { FileSystem } from "react-native-file-access";
+
+const b64 = await FileSystem.readFile(path, "base64");
+/* b64 is a base64 string */
+const workbook = XLSX.read(b64, {type: "base64"});
+```
+
+- [`react-native-fs`](https://npm.im/react-native-fs)
+
+The `ascii` encoding returns binary strings compatible with the `binary` type:
+
+```js
+import XLSX from "xlsx";
+import { readFile } from "react-native-fs";
+
+const bstr = await readFile(path, "ascii");
+/* bstr is a binary string */
+const workbook = XLSX.read(bstr, {type: "binary"});
+```
+
+
+
+
+ NodeJS Server File Uploads (click to show)
+
+`read` can accept a NodeJS buffer. `readFile` can read files generated by a
+HTTP POST request body parser like [`formidable`](https://npm.im/formidable):
+
+```js
+const XLSX = require("xlsx");
+const http = require("http");
+const formidable = require("formidable");
+
+const server = http.createServer((req, res) => {
+ const form = new formidable.IncomingForm();
+ form.parse(req, (err, fields, files) => {
+ /* grab the first file */
+ const f = Object.entries(files)[0][1];
+ const path = f.filepath;
+ const workbook = XLSX.readFile(path);
/* DO SOMETHING WITH workbook HERE */
- };
- reader.readAsArrayBuffer(f);
-}
-drop_dom_element.addEventListener('drop', handleDrop, false);
+ });
+}).listen(process.env.PORT || 7262);
```
+The [`server` demo](demos/server) has more advanced examples.
+
- Browser file upload form element (click to show)
+ Download files in a NodeJS process (click to show)
-Data from file input elements can be processed using the same APIs as in the
-drag-and-drop example.
-
-Using `Blob#arrayBuffer`:
+Node 17.5 and 18.0 have native support for fetch:
```js
-async function handleFileAsync(e) {
- const file = e.target.files[0];
- const data = await file.arrayBuffer();
- const workbook = XLSX.read(data);
+const XLSX = require("xlsx");
+
+const data = await (await fetch(url)).arrayBuffer();
+/* data is an ArrayBuffer */
+const workbook = XLSX.read(data);
+```
+
+For broader compatibility, third-party modules are recommended.
+
+[`request`](https://npm.im/request) requires a `null` encoding to yield Buffers:
+
+```js
+var XLSX = require("xlsx");
+var request = require("request");
+
+request({url: url, encoding: null}, function(err, resp, body) {
+ var workbook = XLSX.read(body);
/* DO SOMETHING WITH workbook HERE */
-}
-input_dom_element.addEventListener('change', handleFileAsync, false);
+});
```
-Using `FileReader`:
+[`axios`](https://npm.im/axios) works the same way in browser and in NodeJS:
```js
-function handleFile(e) {
- var files = e.target.files, f = files[0];
- var reader = new FileReader();
- reader.onload = function(e) {
- var workbook = XLSX.read(e.target.result);
+const XLSX = require("xlsx");
+const axios = require("axios");
- /* DO SOMETHING WITH workbook HERE */
- };
- reader.readAsArrayBuffer(f);
-}
-input_dom_element.addEventListener('change', handleFile, false);
+(async() => {
+ const res = await axios.get(url, {responseType: "arraybuffer"});
+ /* res.data is a Buffer */
+ const workbook = XLSX.read(res.data);
+
+ /* DO SOMETHING WITH workbook HERE */
+})();
```
-The [`oldie` demo](demos/oldie/) shows an IE-compatible fallback scenario.
-
-More specialized cases, including mobile app file processing, are covered in the
-[included demos](demos/)
-
-### Parsing Examples
-
-- HTML5 File API / Base64 Text / Web Workers
-
-Note that older versions of IE do not support HTML5 File API, so the Base64 mode
-is used for testing.
-
- Get Base64 encoding on OSX / Windows (click to show)
+ Download files in an Electron app (click to show)
-On OSX you can get the Base64 encoding with:
+The `net` module in the main process can make HTTP/HTTPS requests to external
+resources. Responses should be manually concatenated using `Buffer.concat`:
-```bash
-$ {
+ const bufs = []; // this array will collect all of the buffers
+ res.on("data", (chunk) => { bufs.push(chunk); });
+ res.on("end", () => {
+ const workbook = XLSX.read(Buffer.concat(bufs));
+
+ /* DO SOMETHING WITH workbook HERE */
+ });
+});
+req.end();
```
-On Windows XP and up you can get the Base64 encoding using `certutil`:
-
-```cmd
-> certutil -encode target_file target_file.b64
-```
-
-(note: You have to open the file and remove the header and footer lines)
-
-- XMLHttpRequest
+
+ Readable Streams in NodeJS (click to show)
+
+When dealing with Readable Streams, the easiest approach is to buffer the stream
+and process the whole thing at the end:
+
+```js
+var fs = require("fs");
+var XLSX = require("xlsx");
+
+function process_RS(stream, cb) {
+ var buffers = [];
+ stream.on("data", function(data) { buffers.push(data); });
+ stream.on("end", function() {
+ var buffer = Buffer.concat(buffers);
+ var workbook = XLSX.read(buffer, {type:"buffer"});
+
+ /* DO SOMETHING WITH workbook IN THE CALLBACK */
+ cb(workbook);
+ });
+}
+```
+
+
+
+
+ ReadableStream in the browser (click to show)
+
+When dealing with `ReadableStream`, the easiest approach is to buffer the stream
+and process the whole thing at the end:
+
+```js
+// XLSX is a global from the standalone script
+
+async function process_RS(stream) {
+ /* collect data */
+ const buffers = [];
+ const reader = stream.getReader();
+ for(;;) {
+ const res = await reader.read();
+ if(res.value) buffers.push(res.value);
+ if(res.done) break;
+ }
+
+ /* concat */
+ const out = new Uint8Array(buffers.reduce((acc, v) => acc + v.length, 0));
+
+ let off = 0;
+ for(const u8 of arr) {
+ out.set(u8, off);
+ off += u8.length;
+ }
+
+ return out;
+}
+
+const data = await process_RS(stream);
+/* data is Uint8Array */
+const workbook = XLSX.read(data);
+```
+
+
+
+More detailed examples are covered in the [included demos](demos/)
+
diff --git a/docbits/21_readstream.md b/docbits/21_readstream.md
deleted file mode 100644
index a31176d..0000000
--- a/docbits/21_readstream.md
+++ /dev/null
@@ -1,67 +0,0 @@
-### Streaming Read
-
-
- Why is there no Streaming Read API? (click to show)
-
-The most common and interesting formats (XLS, XLSX/M, XLSB, ODS) are ultimately
-ZIP or CFB containers of files. Neither format puts the directory structure at
-the beginning of the file: ZIP files place the Central Directory records at the
-end of the logical file, while CFB files can place the storage info anywhere in
-the file! As a result, to properly handle these formats, a streaming function
-would have to buffer the entire file before commencing. That belies the
-expectations of streaming, so we do not provide any streaming read API.
-
-
-
-When dealing with Readable Streams, the easiest approach is to buffer the stream
-and process the whole thing at the end. This can be done with a temporary file
-or by explicitly concatenating the stream:
-
-
- Explicitly concatenating streams (click to show)
-
-```js
-var fs = require('fs');
-var XLSX = require('xlsx');
-function process_RS(stream/*:ReadStream*/, cb/*:(wb:Workbook)=>void*/)/*:void*/{
- var buffers = [];
- stream.on('data', function(data) { buffers.push(data); });
- stream.on('end', function() {
- var buffer = Buffer.concat(buffers);
- var workbook = XLSX.read(buffer, {type:"buffer"});
-
- /* DO SOMETHING WITH workbook IN THE CALLBACK */
- cb(workbook);
- });
-}
-```
-
-More robust solutions are available using modules like `concat-stream`.
-
-
-
-
- Writing to filesystem first (click to show)
-
-This example uses [`tempfile`](https://npm.im/tempfile) to generate file names:
-
-```js
-var fs = require('fs'), tempfile = require('tempfile');
-var XLSX = require('xlsx');
-function process_RS(stream/*:ReadStream*/, cb/*:(wb:Workbook)=>void*/)/*:void*/{
- var fname = tempfile('.sheetjs');
- console.log(fname);
- var ostream = fs.createWriteStream(fname);
- stream.pipe(ostream);
- ostream.on('finish', function() {
- var workbook = XLSX.readFile(fname);
- fs.unlinkSync(fname);
-
- /* DO SOMETHING WITH workbook IN THE CALLBACK */
- cb(workbook);
- });
-}
-```
-
-
-
diff --git a/docbits/22_ingress.md b/docbits/22_ingress.md
new file mode 100644
index 0000000..14550ce
--- /dev/null
+++ b/docbits/22_ingress.md
@@ -0,0 +1,182 @@
+### Processing JSON and JS Data
+
+JSON and JS data tend to represent single worksheets. This section will use a
+few utility functions to generate workbooks:
+
+_Create a new Worksheet_
+
+```js
+var workbook = XLSX.utils.book_new();
+```
+
+The `book_new` utility function creates an empty workbook with no worksheets.
+
+
+_Append a Worksheet to a Workbook_
+
+```js
+XLSX.utils.book_append_sheet(workbook, worksheet, sheet_name);
+```
+
+The `book_append_sheet` utility function appends a worksheet to the workbook.
+The third argument specifies the desired worksheet name. Multiple worksheets can
+be added to a workbook by calling the function multiple times.
+
+
+#### API
+
+_Create a worksheet from an array of arrays of JS values_
+
+```js
+var worksheet = XLSX.utils.aoa_to_sheet(aoa, opts);
+```
+
+The `aoa_to_sheet` utility function walks an "array of arrays" in row-major
+order, generating a worksheet object. The following snippet generates a sheet
+with cell `A1` set to the string `A1`, cell `B1` set to `B2`, etc:
+
+```js
+var worksheet = XLSX.utils.aoa_to_sheet([
+ ["A1", "B1", "C1"],
+ ["A2", "B2", "C2"],
+ ["A3", "B3", "C3"]
+])
+```
+
+["Array of Arrays Input"](#array-of-arrays-input) describes the function and the
+optional `opts` argument in more detail.
+
+
+_Create a worksheet from an array of JS objects_
+
+```js
+var worksheet = XLSX.utils.json_to_sheet(jsa, opts);
+```
+
+The `json_to_sheet` utility function walks an array of JS objects in order,
+generating a worksheet object. By default, it will generate a header row and
+one row per object in the array. The optional `opts` argument has settings to
+control the column order and header output.
+
+["Array of Objects Input"](#array-of-arrays-input) describes the function and
+the optional `opts` argument in more detail.
+
+#### Examples
+
+["Zen of SheetJS"](#the-zen-of-sheetjs) contains a detailed example "Get Data
+from a JSON Endpoint and Generate a Workbook"
+
+The [`database` demo](/demos/database/) includes examples of working with
+databases and query results.
+
+### Processing HTML Tables
+
+#### API
+
+_Create a worksheet by scraping an HTML TABLE in the page_
+
+```js
+var worksheet = XLSX.utils.table_to_sheet(dom_element, opts);
+```
+
+The `table_to_sheet` utility function takes a DOM TABLE element and iterates
+through the rows to generate a worksheet. The `opts` argument is optional.
+["HTML Table Input"](#html-table-input) describes the function in more detail.
+
+
+
+_Create a workbook by scraping an HTML TABLE in the page_
+
+```js
+var workbook = XLSX.utils.table_to_book(dom_element, opts);
+```
+
+The `table_to_book` utility function follows the same logic as `table_to_sheet`.
+After generating a worksheet, it creates a blank workbook and appends the
+spreadsheet.
+
+The options argument supports the same options as `table_to_sheet`, with the
+addition of a `sheet` property to control the worksheet name. If the property
+is missing or no options are specified, the default name `Sheet1` is used.
+
+#### Examples
+
+Here are a few common scenarios (click on each subtitle to see the code):
+
+
+ HTML TABLE element in a webpage (click to show)
+
+```html
+
+
+
+
+
+
+
Sheet
JS
+
12345
67
+
+
+
+
+```
+
+Multiple tables on a web page can be converted to individual worksheets:
+
+```js
+/* create new workbook */
+var workbook = XLSX.utils.book_new();
+
+/* convert table "table1" to worksheet named "Sheet1" */
+var sheet1 = XLSX.utils.table_to_sheet(document.getElementById("table1"));
+XLSX.utils.book_append_sheet(workbook, sheet1, "Sheet1");
+
+/* convert table "table2" to worksheet named "Sheet2" */
+var sheet2 = XLSX.utils.table_to_sheet(document.getElementById("table2"));
+XLSX.utils.book_append_sheet(workbook, sheet2, "Sheet2");
+
+/* workbook now has 2 worksheets */
+```
+
+Alternatively, the HTML code can be extracted and parsed:
+
+```js
+var htmlstr = document.getElementById("tableau").outerHTML;
+var workbook = XLSX.read(htmlstr, {type:"string"});
+```
+
+
+
+
+ Chrome/Chromium Extension (click to show)
+
+The [`chrome` demo](demos/chrome/) shows a complete example and details the
+required permissions and other settings.
+
+In an extension, it is recommended to generate the workbook in a content script
+and pass the object back to the extension:
+
+```js
+/* in the worker script */
+chrome.runtime.onMessage.addListener(function(msg, sender, cb) {
+ /* pass a message like { sheetjs: true } from the extension to scrape */
+ if(!msg || !msg.sheetjs) return;
+ /* create a new workbook */
+ var workbook = XLSX.utils.book_new();
+ /* loop through each table element */
+ var tables = document.getElementsByTagName("table")
+ for(var i = 0; i < tables.length; ++i) {
+ var worksheet = XLSX.utils.table_to_sheet(tables[i]);
+ XLSX.utils.book_append_sheet(workbook, worksheet, "Table" + i);
+ }
+ /* pass back to the extension */
+ return cb(workbook);
+});
+```
+
+
+
diff --git a/misc/docs/README.md b/misc/docs/README.md
index c168ab1..cb54f59 100644
--- a/misc/docs/README.md
+++ b/misc/docs/README.md
@@ -36,11 +36,18 @@ port calculations to web apps; automate common spreadsheet tasks, and much more!
- [Getting Started](#getting-started)
* [Installation](#installation)
* [Usage](#usage)
- + [The Zen of SheetJS](#the-zen-of-sheetjs)
+ * [The Zen of SheetJS](#the-zen-of-sheetjs)
* [JS Ecosystem Demos](#js-ecosystem-demos)
-- [Parsing Workbooks](#parsing-workbooks)
- * [Parsing Examples](#parsing-examples)
- * [Streaming Read](#streaming-read)
+- [Acquiring and Extracting Data](#acquiring-and-extracting-data)
+ * [Parsing Workbooks](#parsing-workbooks)
+ + [API](#api)
+ + [Examples](#examples)
+ * [Processing JSON and JS Data](#processing-json-and-js-data)
+ + [API](#api-1)
+ + [Examples](#examples-1)
+ * [Processing HTML Tables](#processing-html-tables)
+ + [API](#api-2)
+ + [Examples](#examples-2)
- [Working with the Workbook](#working-with-the-workbook)
* [Parsing and Writing Examples](#parsing-and-writing-examples)
- [Writing Workbooks](#writing-workbooks)
@@ -109,7 +116,8 @@ port calculations to web apps; automate common spreadsheet tasks, and much more!
### Installation
-In the browser, just add a script tag:
+The complete browser standalone build is saved to `dist/xlsx.full.min.js` and
+can be directly added to a page with a `script` tag:
```html
@@ -123,7 +131,7 @@ In the browser, just add a script tag:
| `CDNjs` | |
| `packd` | |
-`unpkg` makes the latest version available at:
+For example, `unpkg` makes the latest version available at:
```html
@@ -131,31 +139,6 @@ In the browser, just add a script tag:
-With [npm](https://www.npmjs.org/package/xlsx):
-
-```bash
-$ npm install xlsx
-```
-
-With [bower](https://bower.io/search/?q=js-xlsx):
-
-```bash
-$ bower install js-xlsx
-```
-
-
-The node version automatically requires modules for additional features. Some
-of these modules are rather large in size and are only needed in special
-circumstances, so they do not ship with the core. For browser use, they must
-be included directly:
-
-```html
-
-
-```
-
-An appropriate version for each dependency is included in the dist/ directory.
-
The complete single-file version is generated at `dist/xlsx.full.min.js`
A slimmer build is generated at `dist/xlsx.mini.min.js`. Compared to full build:
@@ -176,6 +159,28 @@ be configured to remove support with `resolve.alias`:
+With [npm](https://www.npmjs.org/package/xlsx):
+
+```bash
+$ npm install xlsx
+```
+
+With [bower](https://bower.io/search/?q=js-xlsx):
+
+```bash
+$ bower install js-xlsx
+```
+
+`dist/xlsx.extendscript.js` is an ExtendScript build for Photoshop and InDesign
+that is included in the `npm` package. It can be directly referenced with a
+`#include` directive:
+
+```extendscript
+#include "xlsx.extendscript.js"
+```
+
+
+
For broad compatibility with JavaScript engines, the library is written using
ECMAScript 3 language dialect as well as some ES5 features like `Array#forEach`.
Older browsers require shims to provide missing functions.
@@ -227,8 +232,8 @@ var table_elt = document.getElementById("my-table-id");
var workbook = XLSX.utils.table_to_book(table_elt);
// Process Data (add a new row)
-var worksheet = workbook.Sheets["Sheet1"];
-XLSX.utils.sheet_add_aoa([["Created "+new Date().toISOString()}]], {origin:-1});
+var ws = workbook.Sheets["Sheet1"];
+XLSX.utils.sheet_add_aoa(ws, [["Created "+new Date().toISOString()]], {origin:-1});
// Package and Release Data (`writeFile` tries to write and save an XLSB file)
XLSX.writeFile(workbook, "Report.xlsb");
@@ -236,7 +241,8 @@ XLSX.writeFile(workbook, "Report.xlsb");
This library tries to simplify steps 2 and 4 with functions to extract useful
data from spreadsheet files (`read` / `readFile`) and generate new spreadsheet
-files from data (`write` / `writeFile`).
+files from data (`write` / `writeFile`). Additional utility functions like
+`table_to_book` work with other common data sources like HTML tables.
This documentation and various demo projects cover a number of common scenarios
and approaches for steps 1 and 5.
@@ -244,7 +250,206 @@ and approaches for steps 1 and 5.
Utility functions help with step 3.
-#### The Zen of SheetJS
+### The Zen of SheetJS
+
+_Data processing should fit in any workflow_
+
+The library does not impose a separate lifecycle. It fits nicely in websites
+and apps built using any framework. The plain JS data objects play nice with
+Web Workers and future APIs.
+
+["Acquiring and Extracting Data"](#acquiring-and-extracting-data) describes
+solutions for common data import scenarios.
+
+["Writing Workbooks"](#writing-workbooks) describes solutions for common data
+export scenarios involving actual spreadsheet files.
+
+["Utility Functions"](#utility-functions) details utility functions for
+translating JSON Arrays and other common JS structures into worksheet objects.
+
+_JavaScript is a powerful language for data processing_
+
+The ["Common Spreadsheet Format"](#common-spreadsheet-format) is a simple object
+representation of the core concepts of a workbook. The various functions in the
+library provide low-level tools for working with the object.
+
+For friendly JS processing, there are utility functions for converting parts of
+a worksheet to/from an Array of Arrays. The following example combines powerful
+JS Array methods with a network request library to download data, select the
+information we want and create a workbook file:
+
+
+The goal is to generate a XLSB workbook of US President names and birthdays.
+
+**Acquire Data**
+
+_Raw Data_
+
+ has the desired
+data. For example, John Adams:
+
+```js
+{
+ "id": { /* (data omitted) */ },
+ "name": {
+ "first": "John", // <-- first name
+ "last": "Adams" // <-- last name
+ },
+ "bio": {
+ "birthday": "1735-10-19", // <-- birthday
+ "gender": "M"
+ },
+ "terms": [
+ { "type": "viceprez", /* (other fields omitted) */ },
+ { "type": "viceprez", /* (other fields omitted) */ },
+ { "type": "prez", /* (other fields omitted) */ } // <-- look for "prez"
+ ]
+}
+```
+
+_Filtering for Presidents_
+
+The dataset includes Aaron Burr, a Vice President who was never President!
+
+`Array#filter` creates a new array with the desired rows. A President served
+at least one term with `type` set to `"prez"`. To test if a particular row has
+at least one `"prez"` term, `Array#some` is another native JS function. The
+complete filter would be:
+
+```js
+const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez"));
+```
+
+_Lining up the data_
+
+For this example, the name will be the first name combined with the last name
+(`row.name.first + " " + row.name.last`) and the birthday will be the subfield
+`row.bio.birthday`. Using `Array#map`, the dataset can be massaged in one call:
+
+```js
+const rows = prez.map(row => ({
+ name: row.name.first + " " + row.name.last,
+ birthday: row.bio.birthday
+}));
+```
+
+The result is an array of "simple" objects with no nesting:
+
+```js
+[
+ { name: "George Washington", birthday: "1732-02-22" },
+ { name: "John Adams", birthday: "1735-10-19" },
+ // ... one row per President
+]
+```
+
+**Extract Data**
+
+With the cleaned dataset, `XLSX.utils.json_to_sheet` generates a worksheet:
+
+```js
+const worksheet = XLSX.utils.json_to_sheet(rows);
+```
+
+`XLSX.utils.book_new` creates a new workbook and `XLSX.utils.book_append_sheet`
+appends a worksheet to the workbook. The new worksheet will be called "Dates":
+
+```js
+const workbook = XLSX.utils.book_new();
+XLSX.utils.book_append_sheet(workbook, worksheet, "Dates");
+```
+
+**Process Data**
+
+_Fixing headers_
+
+By default, `json_to_sheet` creates a worksheet with a header row. In this case,
+the headers come from the JS object keys: "name" and "birthday".
+
+The headers are in cells A1 and B1. `XLSX.utils.sheet_add_aoa` can write text
+values to the existing worksheet starting at cell A1:
+
+```js
+XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });
+```
+
+_Fixing Column Widths_
+
+Some of the names are longer than the default column width. Column widths are
+set by [setting the `"!cols"` worksheet property](#row-and-column-properties).
+
+The following line sets the width of column A to approximately 10 characters:
+
+```js
+worksheet["!cols"] = [ { wch: 10 } ]; // set column A width to 10 characters
+```
+
+One `Array#reduce` call over `rows` can calculate the maximum width:
+
+```js
+const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
+worksheet["!cols"] = [ { wch: max_width } ];
+```
+
+Note: If the starting point was a file or HTML table, `XLSX.utils.sheet_to_json`
+will generate an array of JS objects.
+
+**Package and Release Data**
+
+`XLSX.writeFile` creates a spreadsheet file and tries to write it to the system.
+In the browser, it will try to prompt the user to download the file. In NodeJS,
+it will write to the local directory.
+
+```js
+XLSX.writeFile(workbook, "Presidents.xlsx");
+```
+
+**Complete Example**
+
+```js
+// Uncomment the next line for use in NodeJS:
+// const XLSX = require("xlsx"), axios = require("axios");
+
+(async() => {
+ /* fetch JSON data and parse */
+ const url = "https://theunitedstates.io/congress-legislators/executive.json";
+ const raw_data = (await axios(url, {responseType: "json"})).data;
+
+ /* filter for the Presidents */
+ const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez"));
+
+ /* flatten objects */
+ const rows = prez.map(row => ({
+ name: row.name.first + " " + row.name.last,
+ birthday: row.bio.birthday
+ }));
+
+ /* generate worksheet and workbook */
+ const worksheet = XLSX.utils.json_to_sheet(rows);
+ const workbook = XLSX.utils.book_new();
+ XLSX.utils.book_append_sheet(workbook, worksheet, "Dates");
+
+ /* fix headers */
+ XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });
+
+ /* calculate column width */
+ const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
+ worksheet["!cols"] = [ { wch: max_width } ];
+
+ /* create an XLSX file and try to save to Presidents.xlsx */
+ XLSX.writeFile(workbook, "Presidents.xlsx");
+})();
+```
+
+For use in the web browser, assuming the snippet is saved to `snippet.js`,
+script tags should be used to include the `axios` and `xlsx` standalone builds:
+
+```html
+
+
+
+```
+
_File formats are implementation details_
@@ -255,37 +460,8 @@ The parser covers a wide gamut of common spreadsheet file formats to ensure that
The writer supports a number of common output formats for broad compatibility
with the data ecosystem.
-
-_Data processing should fit in any workflow_
-
-The library does not impose a separate lifecycle. It fits nicely in websites
-and apps built using any framework. The plain JS data objects play nice with
-Web Workers and future APIs.
-
-["Parsing Workbooks"](#parsing-workbooks) describes solutions for common data
-import scenarios involving actual spreadsheet files.
-
-["Writing Workbooks"](#writing-workbooks) describes solutions for common data
-export scenarios involving actual spreadsheet files.
-
-["Utility Functions"](#utility-functions) details utility functions for
-translating JSON Arrays and other common JS structures into worksheet objects.
-
-
-_JavaScript is a powerful language for data processing_
-
-The ["Common Spreadsheet Format"](#common-spreadsheet-format) is a simple object
-representation of the core concepts of a workbook. The various functions in the
-library provide low-level tools for working with the object.
-
-For friendly JS processing, there are utility functions for converting parts of
-a worksheet to/from an Array of Arrays. For example, summing columns from an
-array of arrays can be implemented in a single Array reduce operation:
-
-```js
-var aoa = XLSX.utils.sheet_to_json(worksheet, {header: 1});
-var sum_of_column_B = aoa.reduce((acc, row) => acc + (+row[1]||0), 0);
-```
+To the greatest extent possible, data processing code should not have to worry
+about the specific file formats involved.
### JS Ecosystem Demos
@@ -328,74 +504,164 @@ The [`demos` directory](demos/) includes sample projects for:
Other examples are included in the [showcase](demos/showcase/).
-## Parsing Workbooks
+## Acquiring and Extracting Data
-For parsing, the first step is to read the file. This involves acquiring the
-data and feeding it into the library. Here are a few common scenarios:
+### Parsing Workbooks
+#### API
-`readFile` is only available in server environments. Browsers have no API for
-reading arbitrary files given a path, so another strategy must be used.
+_Extract data from spreadsheet bytes_
```js
-if(typeof require !== 'undefined') XLSX = require('xlsx');
-var workbook = XLSX.readFile('test.xlsx');
-/* DO SOMETHING WITH workbook HERE */
+var workbook = XLSX.read(data, opts);
+```
+
+The `read` method can extract data from spreadsheet bytes stored in a JS string,
+"binary string", NodeJS buffer or typed array (`Uint8Array` or `ArrayBuffer`).
+
+
+_Read spreadsheet bytes from a local file and extract data_
+
+```js
+var workbook = XLSX.readFile(filename, opts);
+```
+
+The `readFile` method attempts to read a spreadsheet file at the supplied path.
+Browsers generally do not allow reading files in this way (it is deemed a
+security risk), and attempts to read files in this way will throw an error.
+
+The second `opts` argument is optional. ["Parsing Options"](#parsing-options)
+covers the supported properties and behaviors.
+
+#### Examples
+
+Here are a few common scenarios (click on each subtitle to see the code):
+
+
+`readFile` uses `fs.readFileSync` under the hood:
+
+```js
+var XLSX = require("xlsx");
+
+var workbook = XLSX.readFile("test.xlsx");
+```
+
+For Node ESM, the `readFile` helper is not enabled. Instead, `fs.readFileSync`
+should be used to read the file data as a `Buffer` for use with `XLSX.read`:
+
+```js
+import { readFileSync } from "fs";
+import { read } from "xlsx/xlsx.mjs";
+
+const buf = readFileSync("test.xlsx");
+/* buf is a Buffer */
+const workbook = read(buf);
```
-`readFile` wraps the `File` logic in Photoshop and other ExtendScript targets.
-The specified path should be an absolute path:
+For modern websites targeting Chrome 76+, `File#arrayBuffer` is recommended:
```js
-#include "xlsx.extendscript.js"
-/* Read test.xlsx from the Documents folder */
-var workbook = XLSX.readFile(Folder.myDocuments + '/' + 'test.xlsx');
-/* DO SOMETHING WITH workbook HERE */
+// XLSX is a global from the standalone script
+
+async function handleDropAsync(e) {
+ e.stopPropagation(); e.preventDefault();
+ const f = e.dataTransfer.files[0];
+ /* f is a File */
+ const data = await f.arrayBuffer();
+ /* data is an ArrayBuffer */
+ const workbook = XLSX.read(data);
+
+ /* DO SOMETHING WITH workbook HERE */
+}
+drop_dom_element.addEventListener("drop", handleDropAsync, false);
```
-The [`extendscript` demo](demos/extendscript/) includes a more complex example.
-
-
-
-The `table_to_book` and `table_to_sheet` utility functions take a DOM TABLE
-element and iterate through the child nodes.
+For maximal compatibility, the `FileReader` API should be used:
```js
-var workbook = XLSX.utils.table_to_book(document.getElementById('tableau'));
-/* DO SOMETHING WITH workbook HERE */
+function handleDrop(e) {
+ e.stopPropagation(); e.preventDefault();
+ var f = e.dataTransfer.files[0];
+ /* f is a File */
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ var data = e.target.result;
+ /* reader.readAsArrayBuffer(file) -> data will be an ArrayBuffer */
+ var workbook = XLSX.read(data);
+
+ /* DO SOMETHING WITH workbook HERE */
+ };
+ reader.readAsArrayBuffer(f);
+}
+drop_dom_element.addEventListener("drop", handleDrop, false);
```
-Multiple tables on a web page can be converted to individual worksheets:
+ demonstrates the FileReader technique.
+
+
+
+Starting with an HTML INPUT element with `type="file"`:
+
+```html
+
+```
+
+For modern websites targeting Chrome 76+, `Blob#arrayBuffer` is recommended:
```js
-/* create new workbook */
-var workbook = XLSX.utils.book_new();
+// XLSX is a global from the standalone script
-/* convert table 'table1' to worksheet named "Sheet1" */
-var ws1 = XLSX.utils.table_to_sheet(document.getElementById('table1'));
-XLSX.utils.book_append_sheet(workbook, ws1, "Sheet1");
+async function handleFileAsync(e) {
+ const file = e.target.files[0];
+ const data = await file.arrayBuffer();
+ /* data is an ArrayBuffer */
+ const workbook = XLSX.read(data);
-/* convert table 'table2' to worksheet named "Sheet2" */
-var ws2 = XLSX.utils.table_to_sheet(document.getElementById('table2'));
-XLSX.utils.book_append_sheet(workbook, ws2, "Sheet2");
-
-/* workbook now has 2 worksheets */
+ /* DO SOMETHING WITH workbook HERE */
+}
+input_dom_element.addEventListener("change", handleFileAsync, false);
```
-Alternatively, the HTML code can be extracted and parsed:
+For broader support (including IE10+), the `FileReader` approach is recommended:
```js
-var htmlstr = document.getElementById('tableau').outerHTML;
-var workbook = XLSX.read(htmlstr, {type:'string'});
+function handleFile(e) {
+ var file = e.target.files[0];
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ var data = e.target.result;
+ /* reader.readAsArrayBuffer(file) -> data will be an ArrayBuffer */
+ var workbook = XLSX.read(e.target.result);
+
+ /* DO SOMETHING WITH workbook HERE */
+ };
+ reader.readAsArrayBuffer(file);
+}
+input_dom_element.addEventListener("change", handleFile, false);
```
+The [`oldie` demo](demos/oldie/) shows an IE-compatible fallback scenario.
-Note: for a more complete example that works in older browsers, check the demo
-at . The [`xhr` demo](demos/xhr/)
-includes more examples with `XMLHttpRequest` and `fetch`.
+
+For modern websites targeting Chrome 42+, `fetch` is recommended:
+
+```js
+// XLSX is a global from the standalone script
+
+(async() => {
+ const url = "http://oss.sheetjs.com/test_files/formula_stress_test.xlsx";
+ const data = await (await fetch(url)).arrayBuffer();
+ /* data is an ArrayBuffer */
+ const workbook = XLSX.read(data);
+
+ /* DO SOMETHING WITH workbook HERE */
+})();
+```
+
+For broader support, the `XMLHttpRequest` approach is recommended:
```js
var url = "http://oss.sheetjs.com/test_files/formula_stress_test.xlsx";
@@ -409,133 +675,178 @@ req.onload = function(e) {
var workbook = XLSX.read(req.response);
/* DO SOMETHING WITH workbook HERE */
-}
+};
req.send();
```
+The [`xhr` demo](demos/xhr/) includes a longer discussion and more examples.
+
+ shows fallback approaches for IE6+.
-For modern browsers, `Blob#arrayBuffer` can read data from files:
+
+`readFile` wraps the `File` logic in Photoshop and other ExtendScript targets.
+The specified path should be an absolute path:
```js
-async function handleDropAsync(e) {
- e.stopPropagation(); e.preventDefault();
- const f = evt.dataTransfer.files[0];
- const data = await f.arrayBuffer();
- const workbook = XLSX.read(data);
+#include "xlsx.extendscript.js"
- /* DO SOMETHING WITH workbook HERE */
-}
-drop_dom_element.addEventListener('drop', handleDropAsync, false);
+/* Read test.xlsx from the Documents folder */
+var workbook = XLSX.readFile(Folder.myDocuments + "/test.xlsx");
```
-For maximal compatibility, the `FileReader` API should be used:
+The [`extendscript` demo](demos/extendscript/) includes a more complex example.
+
+
+
+`readFile` can be used in the renderer process:
```js
-function handleDrop(e) {
- e.stopPropagation(); e.preventDefault();
- var f = e.dataTransfer.files[0];
- var reader = new FileReader();
- reader.onload = function(e) {
- var workbook = XLSX.read(e.target.result);
+/* From the renderer process */
+var XLSX = require("xlsx");
+
+var workbook = XLSX.readFile(path);
+```
+
+Electron APIs have changed over time. The [`electron` demo](demos/electron/)
+shows a complete example and details the required version-specific settings.
+
+
+
+The [`react` demo](demos/react) includes a sample React Native app.
+
+Since React Native does not provide a way to read files from the filesystem, a
+third-party library must be used. The following libraries have been tested:
+
+- [`react-native-file-access`](https://npm.im/react-native-file-access)
+
+The `base64` encoding returns strings compatible with the `base64` type:
+
+```js
+import XLSX from "xlsx";
+import { FileSystem } from "react-native-file-access";
+
+const b64 = await FileSystem.readFile(path, "base64");
+/* b64 is a base64 string */
+const workbook = XLSX.read(b64, {type: "base64"});
+```
+
+- [`react-native-fs`](https://npm.im/react-native-fs)
+
+The `ascii` encoding returns binary strings compatible with the `binary` type:
+
+```js
+import XLSX from "xlsx";
+import { readFile } from "react-native-fs";
+
+const bstr = await readFile(path, "ascii");
+/* bstr is a binary string */
+const workbook = XLSX.read(bstr, {type: "binary"});
+```
+
+
+
+`read` can accept a NodeJS buffer. `readFile` can read files generated by a
+HTTP POST request body parser like [`formidable`](https://npm.im/formidable):
+
+```js
+const XLSX = require("xlsx");
+const http = require("http");
+const formidable = require("formidable");
+
+const server = http.createServer((req, res) => {
+ const form = new formidable.IncomingForm();
+ form.parse(req, (err, fields, files) => {
+ /* grab the first file */
+ const f = Object.entries(files)[0][1];
+ const path = f.filepath;
+ const workbook = XLSX.readFile(path);
/* DO SOMETHING WITH workbook HERE */
- };
- reader.readAsArrayBuffer(f);
-}
-drop_dom_element.addEventListener('drop', handleDrop, false);
+ });
+}).listen(process.env.PORT || 7262);
```
+The [`server` demo](demos/server) has more advanced examples.
-Data from file input elements can be processed using the same APIs as in the
-drag-and-drop example.
-Using `Blob#arrayBuffer`:
+Node 17.5 and 18.0 have native support for fetch:
```js
-async function handleFileAsync(e) {
- const file = e.target.files[0];
- const data = await file.arrayBuffer();
- const workbook = XLSX.read(data);
+const XLSX = require("xlsx");
+
+const data = await (await fetch(url)).arrayBuffer();
+/* data is an ArrayBuffer */
+const workbook = XLSX.read(data);
+```
+
+For broader compatibility, third-party modules are recommended.
+
+[`request`](https://npm.im/request) requires a `null` encoding to yield Buffers:
+
+```js
+var XLSX = require("xlsx");
+var request = require("request");
+
+request({url: url, encoding: null}, function(err, resp, body) {
+ var workbook = XLSX.read(body);
/* DO SOMETHING WITH workbook HERE */
-}
-input_dom_element.addEventListener('change', handleFileAsync, false);
+});
```
-Using `FileReader`:
+[`axios`](https://npm.im/axios) works the same way in browser and in NodeJS:
```js
-function handleFile(e) {
- var files = e.target.files, f = files[0];
- var reader = new FileReader();
- reader.onload = function(e) {
- var workbook = XLSX.read(e.target.result);
+const XLSX = require("xlsx");
+const axios = require("axios");
+
+(async() => {
+ const res = await axios.get(url, {responseType: "arraybuffer"});
+ /* res.data is a Buffer */
+ const workbook = XLSX.read(res.data);
+
+ /* DO SOMETHING WITH workbook HERE */
+})();
+```
+
+
+
+The `net` module in the main process can make HTTP/HTTPS requests to external
+resources. Responses should be manually concatenated using `Buffer.concat`:
+
+```js
+const XLSX = require("xlsx");
+const { net } = require("electron");
+
+const req = net.request(url);
+req.on("response", (res) => {
+ const bufs = []; // this array will collect all of the buffers
+ res.on("data", (chunk) => { bufs.push(chunk); });
+ res.on("end", () => {
+ const workbook = XLSX.read(Buffer.concat(bufs));
/* DO SOMETHING WITH workbook HERE */
- };
- reader.readAsArrayBuffer(f);
-}
-input_dom_element.addEventListener('change', handleFile, false);
+ });
+});
+req.end();
```
-The [`oldie` demo](demos/oldie/) shows an IE-compatible fallback scenario.
-
-
-More specialized cases, including mobile app file processing, are covered in the
-[included demos](demos/)
-
-### Parsing Examples
-
-- HTML5 File API / Base64 Text / Web Workers
-
-Note that older versions of IE do not support HTML5 File API, so the Base64 mode
-is used for testing.
-
-
-On OSX you can get the Base64 encoding with:
-
-```bash
-$ certutil -encode target_file target_file.b64
-```
-
-(note: You have to open the file and remove the header and footer lines)
-
-
-- XMLHttpRequest
-
-### Streaming Read
-
-
-The most common and interesting formats (XLS, XLSX/M, XLSB, ODS) are ultimately
-ZIP or CFB containers of files. Neither format puts the directory structure at
-the beginning of the file: ZIP files place the Central Directory records at the
-end of the logical file, while CFB files can place the storage info anywhere in
-the file! As a result, to properly handle these formats, a streaming function
-would have to buffer the entire file before commencing. That belies the
-expectations of streaming, so we do not provide any streaming read API.
When dealing with Readable Streams, the easiest approach is to buffer the stream
-and process the whole thing at the end. This can be done with a temporary file
-or by explicitly concatenating the stream:
-
+and process the whole thing at the end:
```js
-var fs = require('fs');
-var XLSX = require('xlsx');
-function process_RS(stream/*:ReadStream*/, cb/*:(wb:Workbook)=>void*/)/*:void*/{
+var fs = require("fs");
+var XLSX = require("xlsx");
+
+function process_RS(stream, cb) {
var buffers = [];
- stream.on('data', function(data) { buffers.push(data); });
- stream.on('end', function() {
+ stream.on("data", function(data) { buffers.push(data); });
+ stream.on("end", function() {
var buffer = Buffer.concat(buffers);
var workbook = XLSX.read(buffer, {type:"buffer"});
@@ -545,28 +856,218 @@ function process_RS(stream/*:ReadStream*/, cb/*:(wb:Workbook)=>void*/)/*:void*/{
}
```
-More robust solutions are available using modules like `concat-stream`.
-
-This example uses [`tempfile`](https://npm.im/tempfile) to generate file names:
+When dealing with `ReadableStream`, the easiest approach is to buffer the stream
+and process the whole thing at the end:
```js
-var fs = require('fs'), tempfile = require('tempfile');
-var XLSX = require('xlsx');
-function process_RS(stream/*:ReadStream*/, cb/*:(wb:Workbook)=>void*/)/*:void*/{
- var fname = tempfile('.sheetjs');
- console.log(fname);
- var ostream = fs.createWriteStream(fname);
- stream.pipe(ostream);
- ostream.on('finish', function() {
- var workbook = XLSX.readFile(fname);
- fs.unlinkSync(fname);
+// XLSX is a global from the standalone script
- /* DO SOMETHING WITH workbook IN THE CALLBACK */
- cb(workbook);
- });
+async function process_RS(stream) {
+ /* collect data */
+ const buffers = [];
+ const reader = stream.getReader();
+ for(;;) {
+ const res = await reader.read();
+ if(res.value) buffers.push(res.value);
+ if(res.done) break;
+ }
+
+ /* concat */
+ const out = new Uint8Array(buffers.reduce((acc, v) => acc + v.length, 0));
+
+ let off = 0;
+ for(const u8 of arr) {
+ out.set(u8, off);
+ off += u8.length;
+ }
+
+ return out;
}
+
+const data = await process_RS(stream);
+/* data is Uint8Array */
+const workbook = XLSX.read(data);
+```
+
+
+More detailed examples are covered in the [included demos](demos/)
+
+
+### Processing JSON and JS Data
+
+JSON and JS data tend to represent single worksheets. This section will use a
+few utility functions to generate workbooks:
+
+_Create a new Worksheet_
+
+```js
+var workbook = XLSX.utils.book_new();
+```
+
+The `book_new` utility function creates an empty workbook with no worksheets.
+
+
+_Append a Worksheet to a Workbook_
+
+```js
+XLSX.utils.book_append_sheet(workbook, worksheet, sheet_name);
+```
+
+The `book_append_sheet` utility function appends a worksheet to the workbook.
+The third argument specifies the desired worksheet name. Multiple worksheets can
+be added to a workbook by calling the function multiple times.
+
+
+#### API
+
+_Create a worksheet from an array of arrays of JS values_
+
+```js
+var worksheet = XLSX.utils.aoa_to_sheet(aoa, opts);
+```
+
+The `aoa_to_sheet` utility function walks an "array of arrays" in row-major
+order, generating a worksheet object. The following snippet generates a sheet
+with cell `A1` set to the string `A1`, cell `B1` set to `B2`, etc:
+
+```js
+var worksheet = XLSX.utils.aoa_to_sheet([
+ ["A1", "B1", "C1"],
+ ["A2", "B2", "C2"],
+ ["A3", "B3", "C3"]
+])
+```
+
+["Array of Arrays Input"](#array-of-arrays-input) describes the function and the
+optional `opts` argument in more detail.
+
+
+_Create a worksheet from an array of JS objects_
+
+```js
+var worksheet = XLSX.utils.json_to_sheet(jsa, opts);
+```
+
+The `json_to_sheet` utility function walks an array of JS objects in order,
+generating a worksheet object. By default, it will generate a header row and
+one row per object in the array. The optional `opts` argument has settings to
+control the column order and header output.
+
+["Array of Objects Input"](#array-of-arrays-input) describes the function and
+the optional `opts` argument in more detail.
+
+#### Examples
+
+["Zen of SheetJS"](#the-zen-of-sheetjs) contains a detailed example "Get Data
+from a JSON Endpoint and Generate a Workbook"
+
+The [`database` demo](/demos/database/) includes examples of working with
+databases and query results.
+
+### Processing HTML Tables
+
+#### API
+
+_Create a worksheet by scraping an HTML TABLE in the page_
+
+```js
+var worksheet = XLSX.utils.table_to_sheet(dom_element, opts);
+```
+
+The `table_to_sheet` utility function takes a DOM TABLE element and iterates
+through the rows to generate a worksheet. The `opts` argument is optional.
+["HTML Table Input"](#html-table-input) describes the function in more detail.
+
+
+
+_Create a workbook by scraping an HTML TABLE in the page_
+
+```js
+var workbook = XLSX.utils.table_to_book(dom_element, opts);
+```
+
+The `table_to_book` utility function follows the same logic as `table_to_sheet`.
+After generating a worksheet, it creates a blank workbook and appends the
+spreadsheet.
+
+The options argument supports the same options as `table_to_sheet`, with the
+addition of a `sheet` property to control the worksheet name. If the property
+is missing or no options are specified, the default name `Sheet1` is used.
+
+#### Examples
+
+Here are a few common scenarios (click on each subtitle to see the code):
+
+
+```html
+
+
+
+
+
+