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 + + + + + + + + +
SheetJS
1234567
+ + + +``` + +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 + + + + + + + + +
SheetJS
1234567
+ + + +``` + +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 + + + + + + + + +
SheetJS
1234567
+ + + +``` + +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"}); +``` + + + +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/SUMMARY.md b/misc/docs/SUMMARY.md index 2f9372a..186a8ab 100644 --- a/misc/docs/SUMMARY.md +++ b/misc/docs/SUMMARY.md @@ -4,11 +4,18 @@ - [Getting Started](README.md#getting-started) * [Installation](README.md#installation) * [Usage](README.md#usage) - + [The Zen of SheetJS](README.md#the-zen-of-sheetjs) + * [The Zen of SheetJS](README.md#the-zen-of-sheetjs) * [JS Ecosystem Demos](README.md#js-ecosystem-demos) -- [Parsing Workbooks](README.md#parsing-workbooks) - * [Parsing Examples](README.md#parsing-examples) - * [Streaming Read](README.md#streaming-read) +- [Acquiring and Extracting Data](README.md#acquiring-and-extracting-data) + * [Parsing Workbooks](README.md#parsing-workbooks) + + [API](README.md#api) + + [Examples](README.md#examples) + * [Processing JSON and JS Data](README.md#processing-json-and-js-data) + + [API](README.md#api-1) + + [Examples](README.md#examples-1) + * [Processing HTML Tables](README.md#processing-html-tables) + + [API](README.md#api-2) + + [Examples](README.md#examples-2) - [Working with the Workbook](README.md#working-with-the-workbook) * [Parsing and Writing Examples](README.md#parsing-and-writing-examples) - [Writing Workbooks](README.md#writing-workbooks) diff --git a/modules/59_vba.js b/modules/59_vba.js new file mode 100644 index 0000000..5102ba5 --- /dev/null +++ b/modules/59_vba.js @@ -0,0 +1,21 @@ +var CT_VBA = "application/vnd.ms-office.vbaProject"; +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, 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"]; diff --git a/modules/59_vba.ts b/modules/59_vba.ts new file mode 100644 index 0000000..2fc9575 --- /dev/null +++ b/modules/59_vba.ts @@ -0,0 +1,24 @@ +import * as CFBModule from 'cfb'; +type CFBType = typeof CFBModule; +declare var CFB: CFBType; + +var CT_VBA = "application/vnd.ms-office.vbaProject"; +function make_vba_xls(cfb: CFBModule.CFB$Container) { + 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: CFBModule.CFB$Container, vba: CFBModule.CFB$Container): 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); + }); +} + +var VBAFMTS: string[] = [ "xlsb", "xlsm", "xlam", "biff8", "xla" ]; diff --git a/modules/64_ftab.js b/modules/64_ftab.js new file mode 100644 index 0000000..ac7c719 --- /dev/null +++ b/modules/64_ftab.js @@ -0,0 +1,1133 @@ +var Cetab = { + 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" +}; +var Ftab = { + 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 = { + 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 +}; diff --git a/modules/64_ftab.ts b/modules/64_ftab.ts new file mode 100644 index 0000000..6102ade --- /dev/null +++ b/modules/64_ftab.ts @@ -0,0 +1,1138 @@ +/* [MS-XLS] 2.5.198.4 */ +var Cetab: {[id: number]: string} = { + 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' +}; + +/* [MS-XLS] 2.5.198.17 */ +/* [MS-XLSB] 2.5.97.10 */ +var Ftab: {[id: number]: string} = { + 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' +}; +var FtabArgc: {[id: number]: number} = { + 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 +}; diff --git a/modules/Makefile b/modules/Makefile index 52a0cf4..11d0314 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -2,10 +2,12 @@ LIBFILES=$(wildcard src/*.ts) TSFILES=$(wildcard *.ts) ENTRIES=$(subst .ts,.js,$(TSFILES)) +BAREJS=04_base64.js 59_vba.js 64_ftab.js + .PHONY: all all: $(ENTRIES) -04_base64.js: 04_base64.ts $(LIBFILES) +$(BAREJS): %.js: %.ts $(LIBFILES) npx esbuild $< --outfile=$@ --platform=browser --target=es5 83_numbers.js: 83_numbers.ts $(LIBFILES)