Compare commits

..

2 Commits

Author SHA1 Message Date
Nandan V
79a49b61f5 suggested fixes + support for custom date format 2021-10-06 21:02:14 -04:00
Nandan V
0a169a78d2 fuzzydate strict date option regex 2021-08-13 13:08:30 -05:00
669 changed files with 83054 additions and 2515421 deletions

@ -1,12 +0,0 @@
{
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2020
},
"plugins": [
"tree-shaking"
],
"rules": {
"tree-shaking/no-side-effects-in-initialization": 2
}
}

@ -11,10 +11,8 @@
"comma-dangle": [ 2, "never" ],
"curly": 0,
"no-bitwise": 0,
"no-cond-assign": 1,
"no-console": 0,
"no-control-regex": 0,
"no-unused-vars": 1,
"no-empty": 0,
"no-trailing-spaces": 2,
"no-use-before-define": [ 1, {

@ -17,6 +17,7 @@
.*/xlsx.mini.js
.*/xlsx.mini.flow.js
.*/xlsxworker.js
.*/jszip.js
.*/tests/.*
.*/demos/.*

16
.fossaignore Normal file

@ -0,0 +1,16 @@
bits/
demos/
dist/
docbits/
misc/
node_modules/
types/
tests/
test_files
*.md
*.json
*.log
*.sh
.DS_Store
.Trashes

4
.gitattributes vendored

@ -1,3 +1,4 @@
*.*s linguist-documentation
*.html linguist-documentation
*.md text eol=lf
@ -8,10 +9,7 @@ xlsx*.js text eol=lf
docbits/* linguist-documentation
dist/* linguist-generated=true binary
*.mjs linguist-generated=true binary
xlsx.js linguist-generated=true binary
xlsxworker.js linguist-generated=true binary
tests/core.js linguist-generated=true binary
tests/fixtures.js linguist-generated=true binary
test.mjs lingust-generated=false binary=false text eol=lf

@ -1,20 +0,0 @@
name: 'Tests: Bun'
on: [pull_request, push]
jobs:
# misc test
misc:
name: 'misc (with codepage)'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: antongolub/action-setup-bun@v1
- uses: ljharb/actions/node/install@main
with:
node-version: '16.'
- run: sudo curl -Lo /usr/bin/rooster https://github.com/SheetJS/rooster/releases/download/v0.2.0/rooster-v0.2.0-linux-amd64
- run: sudo chmod a+x /usr/bin/rooster
- run: make init
- run: 'cd test_files; make all; cd -'
- run: 'env FMTS=misc bun hotcross.mjs'

@ -1,39 +0,0 @@
name: 'Tests: deno 1.x'
on: [pull_request, push]
jobs:
# full test
full:
name: 'full (with codepage)'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: denoland/setup-deno@main
with:
deno-version: v1.x
- uses: ljharb/actions/node/install@main
with:
node-version: '16.'
- run: sudo curl -Lo /usr/bin/rooster https://github.com/SheetJS/rooster/releases/download/v0.2.0/rooster-v0.2.0-linux-amd64
- run: sudo chmod a+x /usr/bin/rooster
- run: make init
- run: 'cd test_files; make all; cd -'
- run: deno test --allow-env --allow-read --allow-write --config misc/test.deno.jsonc test.ts
# full test (no codepage)
fullnocp:
name: 'full (no codepage)'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: denoland/setup-deno@main
with:
deno-version: v1.x
- uses: ljharb/actions/node/install@main
with:
node-version: '16.'
- run: sudo curl -Lo /usr/bin/rooster https://github.com/SheetJS/rooster/releases/download/v0.2.0/rooster-v0.2.0-linux-amd64
- run: sudo chmod a+x /usr/bin/rooster
- run: make init
- run: 'cd test_files; make all; cd -'
- run: deno test --allow-env --allow-read --allow-write --config misc/test.deno.jsonc testnocp.ts

@ -77,12 +77,9 @@ jobs:
name: 'nvm install ${{ matrix.node-version }} && npm install'
with:
node-version: ${{ matrix.node-version }}
- run: sudo curl -Lo /usr/bin/rooster https://github.com/SheetJS/rooster/releases/download/v0.2.0/rooster-v0.2.0-linux-amd64
- run: sudo chmod a+x /usr/bin/rooster
- run: make init
- run: 'cd test_files; make all; cd -'
- run: npm run tests-only
- run: 'cd packages/ssf; npm install; npm run tests-only; cd -'
node:
name: 'node 4+'

@ -30,12 +30,9 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
skip-ls-check: true
- run: sudo curl -Lo /usr/bin/rooster https://github.com/SheetJS/rooster/releases/download/v0.2.0/rooster-v0.2.0-linux-amd64
- run: sudo chmod a+x /usr/bin/rooster
- run: make init
- run: 'cd test_files; make all; cd -'
- run: npm run tests-only
#- run: 'cd packages/ssf; npm run tests-only; cd -'
node:
name: 'io.js'

@ -12,8 +12,6 @@ jobs:
name: 'nvm install lts/* && npm install'
with:
node-version: 'lts/*'
- run: sudo curl -Lo /usr/bin/rooster https://github.com/SheetJS/rooster/releases/download/v0.2.0/rooster-v0.2.0-linux-amd64
- run: sudo chmod a+x /usr/bin/rooster
- run: make init
- run: 'cd test_files; make all; cd -'
- run: npm run pretest

@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
outputs:
stable: ${{ steps.set-matrix.outputs.requireds }}
# unstable: ${{ steps.set-matrix.outputs.optionals }}
unstable: ${{ steps.set-matrix.outputs.optionals }}
steps:
- uses: ljharb/actions/node/matrix@main
id: set-matrix
@ -46,43 +46,37 @@ jobs:
node-version: ${{ matrix.node-version }}
cache-node-modules-key: node_modules-${{ github.workflow }}-${{ github.action }}-${{ github.run_id }}
skip-ls-check: true
- run: sudo curl -Lo /usr/bin/rooster https://github.com/SheetJS/rooster/releases/download/v0.2.0/rooster-v0.2.0-linux-amd64
- run: sudo chmod a+x /usr/bin/rooster
- run: make init
- run: 'cd test_files; make all; cd -'
- run: npm run tests-only
#- run: 'cd packages/ssf; npm run tests-only; cd -'
# unstable:
# needs: [matrix, stable]
# name: 'unstable minors'
# continue-on-error: true
# if: ${{ !github.head_ref || !startsWith(github.head_ref, 'renovate') }}
# runs-on: ubuntu-latest
unstable:
needs: [matrix, stable]
name: 'unstable minors'
continue-on-error: true
if: ${{ !github.head_ref || !startsWith(github.head_ref, 'renovate') }}
runs-on: ubuntu-latest
# strategy:
# fail-fast: false
# matrix:
# node-version: ${{ fromJson(needs.matrix.outputs.unstable) }}
#
# steps:
# - uses: actions/checkout@v2
# - uses: ljharb/actions/node/install@main
# name: 'nvm install ${{ matrix.node-version }} && npm install'
# with:
# node-version: ${{ matrix.node-version }}
# cache-node-modules-key: node_modules-${{ github.workflow }}-${{ github.action }}-${{ github.run_id }}
# skip-ls-check: true
# - run: sudo curl -Lo /usr/bin/rooster https://github.com/SheetJS/rooster/releases/download/v0.2.0/rooster-v0.2.0-linux-amd64
# - run: sudo chmod a+x /usr/bin/rooster
# - run: make init
# - run: 'cd test_files; make all; cd -'
# - run: npm run tests-only
strategy:
fail-fast: false
matrix:
node-version: ${{ fromJson(needs.matrix.outputs.unstable) }}
steps:
- uses: actions/checkout@v2
- uses: ljharb/actions/node/install@main
name: 'nvm install ${{ matrix.node-version }} && npm install'
with:
node-version: ${{ matrix.node-version }}
cache-node-modules-key: node_modules-${{ github.workflow }}-${{ github.action }}-${{ github.run_id }}
skip-ls-check: true
- run: make init
- run: 'cd test_files; make all; cd -'
- run: npm run tests-only
node:
name: 'node 0.x'
# needs: [stable, unstable]
needs: [stable]
needs: [stable, unstable]
runs-on: ubuntu-latest
steps:
- run: 'echo tests completed'

12
.gitignore vendored

@ -4,7 +4,6 @@ package-lock.json
_book/
misc/coverage.html
misc/prof.js
misc/*.[sS][vV][gG]
v8.log
tmp
*.[tT][xX][tT]
@ -14,25 +13,18 @@ tmp
*.[pP][mM][dD]*
*.[pP][dD][fF]
*.[sS][lL][kK]
*.[sS][yY][lL][kK]
*.socialcalc
*.[xX][lL][sSwWcCaAtTmMrR]
*.[xX][lL][sSwWcCaAtTmM]
*.[xX][lL][sSaAtT][xXmMbB]
*.[oO][dD][sS]
*.[fF][oO][dD][sS]
*.[xX][mM][lL]
*.[xX][lL][mM][lL]
*.[uU][oO][sS]
*.[wW][kKqQbB][sS1234567890]
*.[wW][kKqQbB][S1234567890]
*.[qQ][pP][wW]
*.[fF][mM][3tT]
*.[bB][iI][fF][fF][23458]
*.[rR][tT][fF]
*.[eE][tT]
*.[eE][tT][hH]
*.[nN][uU][mM][bB][eE][rR][sS]
*.[mM][oO][dD]
*.[dD][tT][aA]
*.123
*.htm
*.html

3
.gitmodules vendored

@ -0,0 +1,3 @@
[submodule "test_files"]
path = test_files
url = https://github.com/SheetJS/test_files

@ -1,5 +1,4 @@
test_files/
modules/
packages/
.github/
tests/files/
@ -8,10 +7,8 @@ index.html
misc/
node_modules
*.tgz
*.jsx
_book
book.json
v8.log
tmp
*.[tT][xX][tT]
*.[cC][sS][vV]
@ -20,24 +17,18 @@ tmp
*.[pP][mM][dD]*
*.[pP][dD][fF]
*.[sS][lL][kK]
*.[sS][yY][lL][kK]
*.socialcalc
*.[xX][lL][sSwWcCaAtTmMrR]
*.[xX][lL][sSwWcCaAtTmM]
*.[xX][lL][sSaAtT][xXmMbB]
*.[oO][dD][sS]
*.[fF][oO][dD][sS]
*.[xX][mM][lL]
*.[xX][lL][mM][lL]
*.[uU][oO][sS]
*.[wW][kKqQbB][S1234567890]
*.[qQ][pP][wW]
*.[fF][mM][3tT]
*.[bB][iI][fF][fF][23458]
*.[rR][tT][fF]
*.[eE][tT]
*.[eE][tT][hH]
*.[nN][uU][mM][bB][eE][rR][sS]
*.[mM][oO][dD]
*.123
*.htm
*.html
@ -50,9 +41,7 @@ tmp
.spelling
.eslintignore
.eslintrc
.eslintmjs
.jshintrc
xlsx.mini.js
CONTRIBUTING.md
Makefile
make.cmd
@ -61,11 +50,6 @@ make.cmd
xlsworker.js
shim.js
test.js
test.mjs
test.ts
test.mts
testnocp.ts
testbun.mjs
.jscs.json
.gitmodules
.travis.yml

@ -1,6 +1,5 @@
# xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com
SheetJS
sheetjs
js-xlsx
xls
xlsb
@ -16,7 +15,6 @@ OData
OpenDocument
OpenFormula
PivotTable
PivotTables
Quattro
SpreadsheetML
Unhide
@ -36,48 +34,29 @@ tooltips
Browserify
CDNjs
CommonJS
Deno
Ethercalc
ExtendScript
InDesign
IndexedDB
JavaScriptCore
LocalStorage
NestJS
NPM
Nuxt
PhantomJS
Photoshop
Nuxt.js
Redis
RequireJS
Rollup
SessionStorage
SQLite
SystemJS
Vite
VueJS
WebKit
WebSQL
WK_
iOS
iWork
nodejs
node.js
npm
unpkg
webpack
weex
# Other terms
1.x
2.x
3.x
4.x
5.x
6.x
7.x
8.x
9.x
ActiveX
APIs
ArrayBuffer
@ -87,7 +66,6 @@ FileReader
JS
NoSQL
README
UTF-8
UTF-16
VBScript
XHR
@ -95,36 +73,30 @@ XMLHttpRequest
bundler
bundlers
cleanroom
codepage
config
customizable
datagrid
dataset
deduplication
destructuring
embeddable
encodings
filesystem
globals
javascript
lifecycle
metadata
natively
pre-built
pre-generated
prepend
prepended
programmatically
repo
runtime
serverless
submodule
transpiled
utils
node.js
commonjs
async
uncheck
vendoring
- demos/altjs/README.md
ChakraCore
@ -159,7 +131,6 @@ storages
- demos/extendscript/README.md
Photoshop
InDesign
minifier
- demos/function/README.md

@ -4,161 +4,6 @@ This log is intended to keep track of backwards-incompatible changes, including
but not limited to API changes and file location changes. Minor behavioral
changes may not be included if they are not expected to break existing code.
* Sheet Visibility for ODS / FODS (h/t @edemaine)
* HTML DOM ingress support formulae (`data-f`)
* Proper handling of XLSX encoded entities (h/t @inreoh)
## v0.20.3
* Correct parsing of NUMBERS and ODS merge cells (h/t @s-ashwin)
* More precise treatment of infinite and NaN values
* XLML Streaming Write
* Parse `Int8Array` objects (for compatibility with JS engines in Java)
* CSV Export only quote leading ID (h/t @lako12)
## v0.20.2
* Reworked parsing methods to avoid slow regexes (CVE-2024-22363)
* HTML properly encode data-v attribute
* SYLK read and write error cells
## v0.20.1
* `init` use packaged test files to work around GitHub breaking changes
* SSF date code rounding to 15 decimal digits (h/t @davidtamaki)
* `sheet_to_json` force UTC interpretation for formatted strings (h/t @Blanay)
* QPW extract result of string formula
* XLSX parse non-compliant merge cell expressions
* NUMBERS correctly handle rows omitted from official exports
* DBF parse empty logical field (h/t @Roman91)
* `dense` option added to types
* package.json add mini and core scripts to export map (h/t @stof)
## v0.20.0
* Use UTC interpretation of Date objects for date cells (potentially breaking)
* API functions support UTC and local time value interpretations
* Export `NaN` values to `#NUM!` and infinite values to `#DIV/0!`
## v0.19.3
* XLSX Ensure comment address is valid (h/t @slonser)
* Enforce Excel worksheet name restrictions
* Fixed "Prototype Pollution" vulnerability (CVE-2023-30533)
## v0.19.2
* XLSX proper decoding of hyperlinks (h/t @tw-yaxu)
* XLSX ignore unexpected attributes in rich text (h/t @colin4)
* `sheet_to_json` type fix (h/t @chsdwn)
## v0.19.1
* Fixed types issue in strict mode (h/t @younes-io)
* Numbers 12.2 parsing skip ActivityStream.iwa
## v0.19.0
* XLSX export hyperlinks compatible with google sheets (h/t Evan Bovie)
* NUMBERS export multiple sheets, full worksheet range
* formalized `dense` mode
## v0.18.12
* `package.json` added types in `exports` structure
* uncapped NUMBERS single-sheet single-table export
* DBF export records using supported codepages
## v0.18.11
* Base64 input ignore data URI wrapper
* Parse ZIP files that use ZIP64 extended information field
* More precise handling of time-only values
* Threaded Comment fallback text for older Excel
## v0.18.10
* `exports` field in package.json to satiate ViteJS and newer tooling
* JSC (Safari / Bun) perf, see <https://bugs.webkit.org/show_bug.cgi?id=243148>
* workbook `bookType` property to denote the origin format when parsed from file
* XLSX force export of stub cells with number formats when `sheetStubs` is set
## v0.18.9
* XLSX / ODS write defined names
* sync defined names to AutoFilter setting on export
* 1904 date system setting properly roundtripped
* ODS read/write number formats
## v0.18.8
* Plaintext parsing of dateless meridien time values (`1:23:45 PM`)
* Legacy format (SYLK / WK# / Multiplan) minutiae
## v0.18.7
* Normalized handling of `\r` and `\n` newline characters
## v0.18.6
* Removed all npm dependencies
* Auto-correct bad Google Sheets format `d.m`
* NUMBERS write merge cells, cells up to column "ALL"
## v0.18.5
* Enabled `sideEffects: false` in package.json
* Basic NUMBERS write support
## v0.18.4
* CSV output omits trailing record separator
* Properly terminate NodeJS Streams
* DBF preserve column types on import and use when applicable on export
## v0.18.3
* Removed references to `require` and `process` in browser builds
## v0.18.2
* Hotfix for unicode processing of XLSX exports
## v0.18.1
* Removed Node ESM build script and folded into standard ESM build
* Removed undocumented aliases including `make_formulae` and `get_formulae`
## v0.18.0
* Browser scripts only expose `XLSX` variable
* Module no longer ships with `dist/jszip.js` browser script
## v0.17.4
* CLI script moved to `xlsx-cli` package
## v0.17.3
* `window.XLSX` explicit assignment to satiate LWC
* CSV Proper formatting of errors
* HTML emit data-\* attributes
## v0.17.2
* Browser and Node optional ESM support
* DSV correct handling of bare quotes (h/t @bgamrat)
## v0.17.1
* `XLSB` writer uses short cell form when viable
## 0.17.0:
* mini build includes ODS parse/write support
* DBF explicitly cap worksheet to 1<<20 rows
* XLS throw errors on truncated records
## v0.16.2
* Disabled `PRN` parsing by default (better support for CSV without delimeters)

@ -4,17 +4,17 @@ The SheetJS Libraries should be free and clear to use in your projects. In
order to maintain that, every contributor must be vigilant.
There have been many projects in the past that have been very lax regarding
licensing. We are of the opinion that those are ticking timebombs and that no
commercial product should depend on them.
licensing, and we are of the opinion that those are ticking timebombs and that
no commercial product should depend on them.
# Required Reading
These are pretty short reads and emphasize the importance of proper licensing:
- https://github.com/jazzband/tablib/issues/114 (discussion of other tools)
- https://github.com/kennethreitz/tablib/issues/114 (discussion of other tools)
- https://web.archive.org/web/20120615223756/http://www.codinghorror.com/blog/2007/04/pick-a-license-any-license.html
- http://www.codinghorror.com/blog/2007/04/pick-a-license-any-license.html
# Raising Issues
@ -30,9 +30,10 @@ inbox is self-hosted.
# Opening Pull Requests
[Squash commits](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History)
before opening a pull request, If the pull request addresses documentation or
demos, add `[ci skip]` in the body or title of the commit message to skip tests.
Before opening a pull request, [squash all commits into
one](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History). If the pull
request addresses documentation or demos, add `[ci skip]` in the body or title
of your commit message to skip Travis checks.
# Pre-Contribution Checklist
@ -56,8 +57,8 @@ issue. If it is a particularly high-priority issue, please drop an email to
Keep these in mind as you work:
- Your contributions are your original work. Take note of any resources you
consult in the process. Be extra careful not to use unlicensed code on the
Internet or code generated by a large language model or other AI tool.
consult in the process (and be extra careful not to use unlicensed code on
the internet.
- You are working on your own time. Unless they explicitly grant permission,
your employer may be the ultimate owner of your IP

194
Makefile

@ -1,7 +1,7 @@
SHELL=/bin/bash
LIB=xlsx
FMT=xlsx xlsm xlsb ods xls xml misc full
REQS=
REQS=jszip.js
ADDONS=dist/cpexcel.js
AUXTARGETS=
CMDS=bin/xlsx.njs
@ -9,28 +9,22 @@ HTMLLINT=index.html
MINITGT=xlsx.mini.js
MINIFLOW=xlsx.mini.flow.js
MINIDEPS=$(shell cat misc/mini.lst)
ESMJSTGT=xlsx.mjs
ESMJSDEPS=$(shell cat misc/mjs.lst)
MINIDEPS=$(shell cat mini.lst)
ULIB=$(shell echo $(LIB) | tr a-z A-Z)
DEPS=$(sort $(wildcard bits/*.js))
TSBITS=$(patsubst modules/%,bits/%,$(wildcard modules/[0-9][0-9]_*.js))
MTSBITS=$(patsubst modules/%,misc/%,$(wildcard modules/[0-9][0-9]_*.js))
TARGET=$(LIB).js
FLOWTARGET=$(LIB).flow.js
FLOWAUX=$(patsubst %.js,%.flow.js,$(AUXTARGETS))
AUXSCPTS=xlsxworker.js
FLOWTGTS=$(TARGET) $(AUXTARGETS) $(AUXSCPTS) $(MINITGT)
UGLIFYOPTS=--support-ie8 -m
CLOSURE=/usr/local/lib/node_modules/google-closure-compiler/compiler.jar
# CLOSURE=/usr/local/lib/node_modules/google-closure-compiler/compiler.jar
## Main Targets
.PHONY: all
all: $(TARGET) $(AUXTARGETS) $(AUXSCPTS) $(MINITGT) $(ESMJSTGT) ## Build library and auxiliary scripts
all: $(TARGET) $(AUXTARGETS) $(AUXSCPTS) $(MINITGT) ## Build library and auxiliary scripts
$(FLOWTGTS): %.js : %.flow.js
node -e 'process.stdout.write(require("fs").readFileSync("$<","utf8").replace(/^[ \t]*\/\*[:#][^*]*\*\/\s*(\n)?/gm,"").replace(/\/\*[:#][^*]*\*\//gm,""))' > $@
@ -41,25 +35,15 @@ $(FLOWTARGET): $(DEPS)
$(MINIFLOW): $(MINIDEPS)
cat $^ | tr -d '\15\32' > $@
$(ESMJSTGT): $(ESMJSDEPS)
cat $^ | tr -d '\15\32' > $@
bits/01_version.js: package.json
echo "$(ULIB).version = '"`grep version package.json | awk '{gsub(/[^0-9a-z\.-]/,"",$$2); print $$2}'`"';" > $@
#bits/18_cfb.js: node_modules/cfb/xlscfb.flow.js
# cp $^ $@
$(TSBITS): bits/%: modules/%
bits/18_cfb.js: node_modules/cfb/xlscfb.flow.js
cp $^ $@
$(MTSBITS): misc/%: modules/%
cp $^ $@
.PHONY: clean
clean: ## Remove targets and build artifacts
rm -f $(TARGET) $(FLOWTARGET) $(ESMJSTGT) $(MINITGT) $(MINIFLOW)
rm -f $(TARGET) $(FLOWTARGET)
.PHONY: clean-data
clean-data:
@ -67,57 +51,50 @@ clean-data:
.PHONY: init
init: ## Initial setup for development
rm -rf test_files
if [ ! -e test_files.zip ]; then curl -LO https://test-files.sheetjs.com/test_files.zip; fi
unzip test_files.zip
git submodule init
git submodule update
#git submodule foreach git pull origin master
git submodule foreach make
mkdir -p tmp
DISTHDR=misc/suppress_export.js
.PHONY: dist
dist: dist-deps $(TARGET) bower.json ## Prepare JS files for distribution
mkdir -p dist
<$(TARGET) sed "s/require('stream')/{}/g;s/require('....*')/undefined/g" > dist/$(TARGET)
cp LICENSE dist/
uglifyjs shim.js $(UGLIFYOPTS) -o dist/shim.min.js --preamble "$$(head -n 1 bits/00_header.js)"
@#
<$(TARGET) sed "s/require('.*')/undefined/g;s/ process / undefined /g;s/process.versions/({})/g" > dist/$(TARGET)
<$(MINITGT) sed "s/require('.*')/undefined/g;s/ process / undefined /g;s/process.versions/({})/g" > dist/$(MINITGT)
@# core
uglifyjs $(REQS) dist/$(TARGET) $(UGLIFYOPTS) -o dist/$(LIB).core.min.js --source-map dist/$(LIB).core.min.map --preamble "$$(head -n 1 bits/00_header.js)"
uglifyjs $(DISTHDR) dist/$(TARGET) $(UGLIFYOPTS) -o dist/$(LIB).min.js --source-map dist/$(LIB).min.map --preamble "$$(head -n 1 bits/00_header.js)"
misc/strip_sourcemap.sh dist/$(LIB).min.js
uglifyjs $(DISTHDR) $(REQS) dist/$(TARGET) $(UGLIFYOPTS) -o dist/$(LIB).core.min.js --source-map dist/$(LIB).core.min.map --preamble "$$(head -n 1 bits/00_header.js)"
misc/strip_sourcemap.sh dist/$(LIB).core.min.js
@# full
#cat <(head -n 1 bits/00_header.js) $(DISTHDR) $(REQS) $(ADDONS) dist/$(TARGET) $(AUXTARGETS) > dist/$(LIB).full.js
uglifyjs $(DISTHDR) $(REQS) $(ADDONS) dist/$(TARGET) $(AUXTARGETS) $(UGLIFYOPTS) -o dist/$(LIB).full.min.js --source-map dist/$(LIB).full.min.map --preamble "$$(head -n 1 bits/00_header.js)"
uglifyjs $(DISTHDR) $(MINITGT) $(UGLIFYOPTS) -o dist/$(LIB).mini.min.js --source-map dist/$(LIB).mini.min.map --preamble "$$(head -n 1 bits/00_header.js)"
misc/strip_sourcemap.sh dist/$(LIB).full.min.js
@# mini
uglifyjs dist/$(MINITGT) $(UGLIFYOPTS) -o dist/$(LIB).mini.min.js --source-map dist/$(LIB).mini.min.map --preamble "$$(head -n 1 bits/00_header.js)"
misc/strip_sourcemap.sh dist/$(LIB).mini.min.js
@# extendscript
cat <(printf '\xEF\xBB\xBF') <(head -n 1 bits/00_header.js) shim.js $(DISTHDR) $(REQS) dist/$(TARGET) > dist/$(LIB).extendscript.js
@# zahl
cp modules/xlsx.zahl.js modules/xlsx.zahl.mjs dist/
@#
rm dist/$(TARGET) dist/$(MINITGT)
cat <(head -n 1 bits/00_header.js) shim.js $(DISTHDR) $(REQS) dist/$(TARGET) > dist/$(LIB).extendscript.js
.PHONY: dist-deps
dist-deps: ## Copy dependencies for distribution
mkdir -p dist
cp node_modules/codepage/dist/cpexcel.full.js dist/cpexcel.js
cp jszip.js dist/jszip.js
.PHONY: aux
aux: $(AUXTARGETS)
BYTEFILEC=dist/xlsx.{full,core,mini}.min.js xlsx.mjs
BYTEFILER=dist/xlsx.extendscript.js
BYTEFILE=dist/xlsx.min.js dist/xlsx.{core,full,mini}.min.js dist/xlsx.extendscript.js
.PHONY: bytes
bytes: ## Display minified and gzipped file sizes
@for i in $(BYTEFILEC); do npx printj "%-30s %7d %10d" $$i $$(wc -c < $$i) $$(gzip --best --stdout $$i | wc -c); done
@for i in $(BYTEFILER); do npx printj "%-30s %7d" $$i $$(wc -c < $$i); done
@npx printj "%-30s %10d" "treeshake" "$$(npx -y esbuild@0.14.14 --bundle misc/import.js | wc -c)"
for i in $(BYTEFILE); do printj "%-30s %7d %10d" $$i $$(wc -c < $$i) $$(gzip --best --stdout $$i | wc -c); done
.PHONY: graph
graph: formats.png legend.png ## Rebuild format conversion graph
formats.png: formats.dot
circo -Tpng -o$@ $<
legend.png: misc/legend.dot
dot -Tpng -o$@ $<
.PHONY: git
git: ## show version string
@echo "$$(node -pe 'require("./package.json").version')"
.PHONY: nexe
nexe: xlsx.exe ## Build nexe standalone executable
@ -139,60 +116,11 @@ test mocha: test.js ## Run test suite
#* To run tests for one format, make test_<fmt>
#* To run the core test suite, make test_misc
.PHONY: testdot
testdot: test.js ## Run test suite using dot reporter
mocha -R dot -t 30000
.PHONY: test-esm
test-esm: test.mjs ## Run Node ESM test suite
npx -y mocha@9 -R spec -t 30000 $<
test.ts: test.mts
node -pe 'var data = fs.readFileSync("'$<'", "utf8"); data.split("\n").map(function(l) { return l.replace(/^describe\((.*?)function\(\)/, "Deno.test($$1async function(t)").replace(/\b(?:it|describe)\((.*?)function\(\)/g, "await t.step($$1async function(t)").replace("assert.ok", "assert.assert"); }).join("\n")' > $@
.PHONY: test-bun
test-bun: test.test.mjs ## Run Bun test suite
bun test $<
.PHONY: test-deno
test-deno: test.ts ## Run Deno test suite
deno test --check --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $<
.PHONY: test-denocp
test-denocp: testnocp.ts ## Run Deno test suite (without codepage)
deno test --check --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $<
TESTFMT=$(patsubst %,test_%,$(FMT))
.PHONY: $(TESTFMT)
$(TESTFMT): test_%:
FMTS=$* make test
TESTFMT=$(patsubst %,testdot_%,$(FMT))
.PHONY: $(TESTFMT)
$(TESTFMT): testdot_%:
FMTS=$* make testdot
TESTESMFMT=$(patsubst %,test-esm_%,$(FMT))
.PHONY: $(TESTESMFMT)
$(TESTESMFMT): test-esm_%:
FMTS=$* make test-esm
TESTDENOFMT=$(patsubst %,test-deno_%,$(FMT))
.PHONY: $(TESTDENOFMT)
$(TESTDENOFMT): test-deno_%:
FMTS=$* make test-deno
TESTDENOCPFMT=$(patsubst %,test-denocp_%,$(FMT))
.PHONY: $(TESTDENOCPFMT)
$(TESTDENOCPFMT): test-denocp_%:
FMTS=$* make test-denocp
TESTBUNFMT=$(patsubst %,test-bun_%,$(FMT))
.PHONY: $(TESTBUNFMT)
$(TESTBUNFMT): test-bun_%:
FMTS=$* make test-bun
.PHONY: travis
travis: ## Run test suite with minimal output
mocha -R dot -t 30000
@ -203,7 +131,48 @@ ctest: ## Build browser test fixtures
.PHONY: ctestserv
ctestserv: ## Start a test server on port 8000
@cd tests && python -mSimpleHTTPServer || python3 -mhttp.server || npx -y http-server -p 8000 .
@cd tests && python -mSimpleHTTPServer
## Demos
DEMOS=angular angular-new browserify requirejs rollup systemjs webpack
DEMOTGTS=$(patsubst %,demo-%,$(DEMOS))
.PHONY: demos
demos: $(DEMOTGTS)
.PHONY: demo-angular
demo-angular: ## Run angular demo build
#make -C demos/angular
@echo "start a local server and go to demos/angular/angular.html"
.PHONY: demo-angular-new
demo-angular-new: ## Run angular 2 demo build
make -C demos/angular2
@echo "go to demos/angular/angular.html and run 'ng serve'"
.PHONY: demo-browserify
demo-browserify: ## Run browserify demo build
make -C demos/browserify
@echo "start a local server and go to demos/browserify/browserify.html"
.PHONY: demo-webpack
demo-webpack: ## Run webpack demo build
make -C demos/webpack
@echo "start a local server and go to demos/webpack/webpack.html"
.PHONY: demo-requirejs
demo-requirejs: ## Run requirejs demo build
make -C demos/requirejs
@echo "start a local server and go to demos/requirejs/requirejs.html"
.PHONY: demo-rollup
demo-rollup: ## Run rollup demo build
make -C demos/rollup
@echo "start a local server and go to demos/rollup/rollup.html"
.PHONY: demo-systemjs
demo-systemjs: ## Run systemjs demo build
make -C demos/systemjs
## Code Checking
@ -212,17 +181,17 @@ fullint: lint mdlint ## Run all checks (removed: old-lint, tslint, flow)
.PHONY: lint
lint: $(TARGET) $(AUXTARGETS) ## Run eslint checks
@./node_modules/.bin/eslint --ext .js,.njs,.json,.html,.htm $(FLOWTARGET) $(AUXTARGETS) $(CMDS) $(HTMLLINT) package.json bower.json
@if [ -x "$(CLOSURE)" ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi
@./node_modules/.bin/eslint --ext .js,.njs,.json,.html,.htm $(TARGET) $(AUXTARGETS) $(CMDS) $(HTMLLINT) package.json bower.json
if [ -n "$(CLOSURE-)" ] && [ -e "${CLOSURE}" ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi
.PHONY: old-lint
old-lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks
@./node_modules/.bin/jscs $(TARGET) $(AUXTARGETS) test.js
@./node_modules/.bin/jshint --show-non-errors $(TARGET) $(AUXTARGETS)
@./node_modules/.bin/jshint --show-non-errors $(CMDS)
@./node_modules/.bin/jshint --show-non-errors package.json bower.json test.js
@./node_modules/.bin/jshint --show-non-errors --extract=always $(HTMLLINT)
@if [ -x "$(CLOSURE)" ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi
@./node_modules/.bin/jscs $(TARGET) $(AUXTARGETS) test.js
if [ -e $(CLOSURE) ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi
.PHONY: tslint
tslint: $(TARGET) ## Run typescript checks
@ -234,10 +203,6 @@ tslint: $(TARGET) ## Run typescript checks
flow: lint ## Run flow checker
@./node_modules/.bin/flow check --all --show-all-errors --include-warnings
.PHONY: mjslint
mjslint: $(ESMJSTGT) ## Lint the ESM build
@npx eslint -c .eslintmjs $<
.PHONY: cov
cov: misc/coverage.html ## Run coverage test
@ -254,7 +219,22 @@ misc/coverage.html: $(TARGET) test.js
coveralls: ## Coverage Test + Send to coveralls.io
mocha --require blanket --reporter mocha-lcov-reporter -t 30000 | node ./node_modules/coveralls/bin/coveralls.js
MDLINT=README.md
READEPS=$(sort $(wildcard docbits/*.md))
README.md: $(READEPS)
awk 'FNR==1{p=0}/#/{p=1}p' $^ | tr -d '\15\32' > $@
.PHONY: readme
readme: README.md ## Update README Table of Contents
markdown-toc -i README.md
.PHONY: book
book: readme graph ## Update summary for documentation
printf "# Summary\n\n- [xlsx](README.md#sheetjs-js-xlsx)\n" > misc/docs/SUMMARY.md
markdown-toc README.md | sed 's/(#/(README.md#/g'>> misc/docs/SUMMARY.md
<README.md grep -vE "(details|summary)>" > misc/docs/README.md
DEMOMDS=$(sort $(wildcard demos/*/README.md))
MDLINT=$(DEMOMDS) $(READEPS) demos/README.md
.PHONY: mdlint
mdlint: $(MDLINT) ## Check markdown documents
./node_modules/.bin/alex $^

2921
README.md

File diff suppressed because it is too large Load Diff

@ -5,21 +5,8 @@
var n = "xlsx";
var X = require('../');
try { X = require('../xlsx.flow'); } catch(e) {}
try { require('exit-on-epipe'); } catch(e) {}
var fs = require('fs'), program;
try { program = require('commander'); } catch(e) {
[
"The `xlsx` command line tool is deprecated in favor of `xlsx-cli`.",
"",
"For new versions of node, we recommend using `npx`:",
" $ npx xlsx-cli --help",
"",
"For older versions of node, explicitly install `xlsx-cli` globally:",
" $ npm i -g xlsx-cli",
" $ xlsx-cli --help"
].forEach(function(m) { console.error(m); });
process.exit(1);
}
require('exit-on-epipe');
var fs = require('fs'), program = require('commander');
program
.version(X.version)
.usage('[options] <file> [sheetname]')
@ -37,14 +24,12 @@ program
.option('-Y, --ods', 'emit ODS to <sheetname> or <file>.ods')
.option('-8, --xls', 'emit XLS to <sheetname> or <file>.xls (BIFF8)')
.option('-5, --biff5','emit XLS to <sheetname> or <file>.xls (BIFF5)')
.option('-4, --biff4','emit XLS to <sheetname> or <file>.xls (BIFF4)')
.option('-3, --biff3','emit XLS to <sheetname> or <file>.xls (BIFF3)')
//.option('-4, --biff4','emit XLS to <sheetname> or <file>.xls (BIFF4)')
//.option('-3, --biff3','emit XLS to <sheetname> or <file>.xls (BIFF3)')
.option('-2, --biff2','emit XLS to <sheetname> or <file>.xls (BIFF2)')
.option('-i, --xla', 'emit XLA to <sheetname> or <file>.xla')
.option('-6, --xlml', 'emit SSML to <sheetname> or <file>.xls (2003 XML)')
.option('-T, --fods', 'emit FODS to <sheetname> or <file>.fods (Flat ODS)')
.option('--wk3', 'emit WK3 to <sheetname> or <file>.txt (Lotus WK3)')
.option('--numbers', 'emit NUMBERS to <sheetname> or <file>.numbers')
.option('-S, --formulae', 'emit list of values and formulae')
.option('-j, --json', 'emit formatted JSON (all fields text)')
@ -58,7 +43,6 @@ program
.option('-E, --eth', 'emit ETH to <sheetname> or <file>.eth (Ethercalc)')
.option('-t, --txt', 'emit TXT to <sheetname> or <file>.txt (UTF-8 TSV)')
.option('-r, --rtf', 'emit RTF to <sheetname> or <file>.txt (Table RTF)')
.option('--wk1', 'emit WK1 to <sheetname> or <file>.txt (Lotus WK1)')
.option('-z, --dump', 'dump internal representation as JSON')
.option('--props', 'dump workbook properties as CSV')
@ -91,10 +75,8 @@ var workbook_formats = [
['xls', 'xls', 'xls'],
['xla', 'xla', 'xla'],
['biff5', 'biff5', 'xls'],
['numbers', 'numbers', 'numbers'],
['ods', 'ods', 'ods'],
['fods', 'fods', 'fods'],
['wk3', 'wk3', 'wk3']
['fods', 'fods', 'fods']
];
var wb_formats_2 = [
['xlml', 'xlml', 'xls']
@ -131,7 +113,6 @@ function wb_fmt() {
seen = true;
opts.cellFormula = true;
opts.cellNF = true;
opts.xlfn = true;
if(program.output) sheetname = program.output;
}
function isfmt(m/*:string*/)/*:boolean*/ {
@ -156,7 +137,6 @@ if(program.all) {
opts.cellStyles = true;
opts.sheetStubs = true;
opts.cellDates = true;
wopts.cellFormula = true;
wopts.cellStyles = true;
wopts.sheetStubs = true;
wopts.bookVBA = true;
@ -194,10 +174,6 @@ if(program.props) {
/* full workbook formats */
workbook_formats.forEach(function(m) { if(program[m[0]] || isfmt(m[0])) {
wopts.bookType = m[1];
if(wopts.bookType == "numbers") try {
var XLSX_ZAHL = require("../dist/xlsx.zahl");
wopts.numbers = XLSX_ZAHL;
} catch(e) {}
if(wb) X.writeFile(wb, program.output || sheetname || ((filename || "") + "." + m[2]), wopts);
process.exit(0);
} });
@ -240,7 +216,6 @@ if(!program.quiet && !program.book) console.error(target_sheet);
['rtf', '.rtf'],
['txt', '.txt'],
['dbf', '.dbf'],
['wk1', '.wk1'],
['dif', '.dif']
].forEach(function(m) { if(program[m[0]] || isfmt(m[1])) {
wopts.bookType = m[0];
@ -281,7 +256,7 @@ switch(true) {
default:
if(!program.book) {
var stream = X.stream.to_csv(ws, {FS:program.fieldSep||",", RS:program.rowSep||"\n"});
var stream = X.stream.to_csv(ws, {FS:program.fieldSep, RS:program.rowSep});
if(program.output) stream.pipe(fs.createWriteStream(program.output));
else stream.pipe(process.stdout);
} else doit(function(ws) { return X.utils.sheet_to_csv(ws,{FS:program.fieldSep, RS:program.rowSep}); });

@ -1,6 +1,6 @@
/*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*exported XLSX */
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false, Set:false, Float32Array:false */
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
function make_xlsx_lib(XLSX){

@ -1 +1 @@
XLSX.version = '0.20.3';
XLSX.version = '0.17.0';

@ -1,31 +1,37 @@
var current_codepage = 1200, current_ansi = 1252;
/*:: declare var cptable:any; */
/*global cptable:true, window */
var $cptable;
if(typeof module !== "undefined" && typeof require !== 'undefined') {
if(typeof cptable === 'undefined') {
if(typeof global !== 'undefined') global.cptable = require('./dist/cpexcel.js');
else if(typeof window !== 'undefined') window.cptable = require('./dist/cpexcel.js');
}
}
var VALID_ANSI = [ 874, 932, 936, 949, 950, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 10000 ];
var VALID_ANSI = [ 874, 932, 936, 949, 950 ];
for(var i = 0; i <= 8; ++i) VALID_ANSI.push(1250 + i);
/* ECMA-376 Part I 18.4.1 charset to codepage mapping */
var CS2CP = ({
0: 1252, /* ANSI */
1: 65001, /* DEFAULT */
2: 65001, /* SYMBOL */
77: 10000, /* MAC */
128: 932, /* SHIFTJIS */
129: 949, /* HANGUL */
130: 1361, /* JOHAB */
134: 936, /* GB2312 */
136: 950, /* CHINESEBIG5 */
161: 1253, /* GREEK */
162: 1254, /* TURKISH */
163: 1258, /* VIETNAMESE */
177: 1255, /* HEBREW */
178: 1256, /* ARABIC */
186: 1257, /* BALTIC */
204: 1251, /* RUSSIAN */
222: 874, /* THAI */
238: 1250, /* EASTEUROPE */
255: 1252, /* OEM */
69: 6969 /* MISC */
/*::[*/0/*::]*/: 1252, /* ANSI */
/*::[*/1/*::]*/: 65001, /* DEFAULT */
/*::[*/2/*::]*/: 65001, /* SYMBOL */
/*::[*/77/*::]*/: 10000, /* MAC */
/*::[*/128/*::]*/: 932, /* SHIFTJIS */
/*::[*/129/*::]*/: 949, /* HANGUL */
/*::[*/130/*::]*/: 1361, /* JOHAB */
/*::[*/134/*::]*/: 936, /* GB2312 */
/*::[*/136/*::]*/: 950, /* CHINESEBIG5 */
/*::[*/161/*::]*/: 1253, /* GREEK */
/*::[*/162/*::]*/: 1254, /* TURKISH */
/*::[*/163/*::]*/: 1258, /* VIETNAMESE */
/*::[*/177/*::]*/: 1255, /* HEBREW */
/*::[*/178/*::]*/: 1256, /* ARABIC */
/*::[*/186/*::]*/: 1257, /* BALTIC */
/*::[*/204/*::]*/: 1251, /* RUSSIAN */
/*::[*/222/*::]*/: 874, /* THAI */
/*::[*/238/*::]*/: 1250, /* EASTEUROPE */
/*::[*/255/*::]*/: 1252, /* OEM */
/*::[*/69/*::]*/: 6969 /* MISC */
}/*:any*/);
var set_ansi = function(cp/*:number*/) { if(VALID_ANSI.indexOf(cp) == -1) return; current_ansi = CS2CP[0] = cp; };
@ -41,11 +47,6 @@ function utf16leread(data/*:string*/)/*:string*/ {
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i) + (data.charCodeAt(2*i+1)<<8));
return o.join("");
}
function utf16lereadu(data/*:Uint8Array*/)/*:string*/ {
var o/*:Array<string>*/ = [];
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data[2*i] + (data[2*i+1]<<8));
return o.join("");
}
function utf16beread(data/*:string*/)/*:string*/ {
var o/*:Array<string>*/ = [];
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i+1) + (data.charCodeAt(2*i)<<8));
@ -62,20 +63,17 @@ var debom = function(data/*:string*/)/*:string*/ {
var _getchar = function _gc1(x/*:number*/)/*:string*/ { return String.fromCharCode(x); };
var _getansi = function _ga1(x/*:number*/)/*:string*/ { return String.fromCharCode(x); };
function set_cptable(cptable) {
$cptable = cptable;
if(typeof cptable !== 'undefined') {
set_cp = function(cp/*:number*/) { current_codepage = cp; set_ansi(cp); };
debom = function(data/*:string*/) {
if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return $cptable.utils.decode(1200, char_codes(data.slice(2))); }
if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.slice(2))); }
return data;
};
_getchar = function _gc2(x/*:number*/)/*:string*/ {
if(current_codepage === 1200) return String.fromCharCode(x);
return $cptable.utils.decode(current_codepage, [x&255,x>>8])[0];
return cptable.utils.decode(current_codepage, [x&255,x>>8])[0];
};
_getansi = function _ga2(x/*:number*/)/*:string*/ {
return $cptable.utils.decode(current_ansi, [x])[0];
return cptable.utils.decode(current_ansi, [x])[0];
};
cpdoit();
}

@ -1,94 +1,44 @@
var Base64_map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
function Base64_encode(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 += Base64_map.charAt(e1) + Base64_map.charAt(e2) + Base64_map.charAt(e3) + Base64_map.charAt(e4);
}
return o;
}
function Base64_encode_pass(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++);
if (c1 > 255)
c1 = 95;
e1 = c1 >> 2;
c2 = input.charCodeAt(i++);
if (c2 > 255)
c2 = 95;
e2 = (c1 & 3) << 4 | c2 >> 4;
c3 = input.charCodeAt(i++);
if (c3 > 255)
c3 = 95;
e3 = (c2 & 15) << 2 | c3 >> 6;
e4 = c3 & 63;
if (isNaN(c2)) {
e3 = e4 = 64;
} else if (isNaN(c3)) {
e4 = 64;
}
o += Base64_map.charAt(e1) + Base64_map.charAt(e2) + Base64_map.charAt(e3) + Base64_map.charAt(e4);
}
return o;
}
function Base64_encode_arr(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[i++];
e1 = c1 >> 2;
c2 = input[i++];
e2 = (c1 & 3) << 4 | c2 >> 4;
c3 = input[i++];
e3 = (c2 & 15) << 2 | c3 >> 6;
e4 = c3 & 63;
if (isNaN(c2)) {
e3 = e4 = 64;
} else if (isNaN(c3)) {
e4 = 64;
}
o += Base64_map.charAt(e1) + Base64_map.charAt(e2) + Base64_map.charAt(e3) + Base64_map.charAt(e4);
}
return o;
}
function Base64_decode(input) {
var o = "";
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
if (input.slice(0, 5) == "data:") {
var i = input.slice(0, 1024).indexOf(";base64,");
if (i > -1)
input = input.slice(i + 8);
}
input = input.replace(/[^\w\+\/\=]/g, "");
for (var i = 0; i < input.length; ) {
e1 = Base64_map.indexOf(input.charAt(i++));
e2 = Base64_map.indexOf(input.charAt(i++));
c1 = e1 << 2 | e2 >> 4;
o += String.fromCharCode(c1);
e3 = Base64_map.indexOf(input.charAt(i++));
c2 = (e2 & 15) << 4 | e3 >> 2;
if (e3 !== 64) {
o += String.fromCharCode(c2);
}
e4 = Base64_map.indexOf(input.charAt(i++));
c3 = (e3 & 3) << 6 | e4;
if (e4 !== 64) {
o += String.fromCharCode(c3);
}
}
return o;
}
var Base64 = (function make_b64(){
var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
return {
encode: function(input/*:string*/)/*:string*/ {
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 b64_decode(input/*:string*/)/*:string*/ {
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;
}
};
})();

@ -1,33 +1,26 @@
var has_buf = /*#__PURE__*/(function() { return typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.node; })();
var has_buf = (typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.node);
var Buffer_from = /*#__PURE__*/(function() {
if(typeof Buffer !== 'undefined') {
var nbfs = !Buffer.from;
if(!nbfs) try { Buffer.from("foo", "utf8"); } catch(e) { nbfs = true; }
return nbfs ? function(buf, enc) { return (enc) ? new Buffer(buf, enc) : new Buffer(buf); } : Buffer.from.bind(Buffer);
}
return function() {};
})();
var buf_utf16le = /*#__PURE__*/(function() {
if(typeof Buffer === 'undefined') return false;
var x = Buffer_from([65,0]);
if(!x) return false;
var o = x.toString("utf16le");
return o.length == 1;
})();
var Buffer_from = /*::(*/function(){}/*:: :any)*/;
if(typeof Buffer !== 'undefined') {
var nbfs = !Buffer.from;
if(!nbfs) try { Buffer.from("foo", "utf8"); } catch(e) { nbfs = true; }
Buffer_from = nbfs ? function(buf, enc) { return (enc) ? new Buffer(buf, enc) : new Buffer(buf); } : Buffer.from.bind(Buffer);
// $FlowIgnore
if(!Buffer.alloc) Buffer.alloc = function(n) { return new Buffer(n); };
// $FlowIgnore
if(!Buffer.allocUnsafe) Buffer.allocUnsafe = function(n) { return new Buffer(n); };
}
function new_raw_buf(len/*:number*/) {
/* jshint -W056 */
if(has_buf) return Buffer.alloc ? Buffer.alloc(len) : new Buffer(len);
return typeof Uint8Array != "undefined" ? new Uint8Array(len) : new Array(len);
return has_buf ? Buffer.alloc(len) : new Array(len);
/* jshint +W056 */
}
function new_unsafe_buf(len/*:number*/) {
/* jshint -W056 */
if(has_buf) return Buffer.allocUnsafe ? Buffer.allocUnsafe(len) : new Buffer(len);
return typeof Uint8Array != "undefined" ? new Uint8Array(len) : new Array(len);
return has_buf ? Buffer.allocUnsafe(len) : new Array(len);
/* jshint +W056 */
}
@ -62,53 +55,6 @@ function ab2a(data/*:ArrayBuffer|Uint8Array*/)/*:Array<number>*/ {
return o;
}
var bconcat = has_buf ? function(bufs) { return Buffer.concat(bufs.map(function(buf) { return Buffer.isBuffer(buf) ? buf : Buffer_from(buf); })); } : function(bufs) {
if(typeof Uint8Array !== "undefined") {
var i = 0, maxlen = 0;
for(i = 0; i < bufs.length; ++i) maxlen += bufs[i].length;
var o = new Uint8Array(maxlen);
var len = 0;
for(i = 0, maxlen = 0; i < bufs.length; maxlen += len, ++i) {
len = bufs[i].length;
if(bufs[i] instanceof Uint8Array) o.set(bufs[i], maxlen);
else if(typeof bufs[i] == "string") o.set(new Uint8Array(s2a(bufs[i])), maxlen);
else o.set(new Uint8Array(bufs[i]), maxlen);
}
return o;
}
return [].concat.apply([], bufs.map(function(buf) { return Array.isArray(buf) ? buf : [].slice.call(buf); }));
};
function utf8decode(content/*:string*/) {
var out = [], widx = 0, L = content.length + 250;
var o = new_raw_buf(content.length + 255);
for(var ridx = 0; ridx < content.length; ++ridx) {
var c = content.charCodeAt(ridx);
if(c < 0x80) o[widx++] = c;
else if(c < 0x800) {
o[widx++] = (192|((c>>6)&31));
o[widx++] = (128|(c&63));
} else if(c >= 0xD800 && c < 0xE000) {
c = (c&1023)+64;
var d = content.charCodeAt(++ridx)&1023;
o[widx++] = (240|((c>>8)&7));
o[widx++] = (128|((c>>2)&63));
o[widx++] = (128|((d>>6)&15)|((c&3)<<4));
o[widx++] = (128|(d&63));
} else {
o[widx++] = (224|((c>>12)&15));
o[widx++] = (128|((c>>6)&63));
o[widx++] = (128|(c&63));
}
if(widx > L) {
out.push(o.slice(0, widx));
widx = 0;
o = new_raw_buf(65535);
L = 65530;
}
}
out.push(o.slice(0, widx));
return bconcat(out);
}
var bconcat = function(bufs) { return [].concat.apply([], bufs); };
var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/g;

@ -15,4 +15,5 @@ type EvertArrType = {[string]:Array<string>};
type StringConv = {(string):string};
type WriteObjStrFactory = {from_sheet(ws:Worksheet, o:any, wb:?Workbook):string};
*/

@ -1,15 +1,21 @@
/* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */
/*jshint -W041 */
var SSF/*:SSFModule*/ = ({}/*:any*/);
var make_ssf = function make_ssf(SSF/*:SSFModule*/){
SSF.version = '0.11.2';
function _strrev(x/*:string*/)/*:string*/ { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; }
function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; }
function pad0(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
function pad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v;return t.length>=d?t:fill(' ',d-t.length)+t;}
function rpad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);}
function pad0r1(v/*:any*/,d/*:number*/)/*:string*/{var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;}
function pad0r2(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
var p2_32 = /*#__PURE__*/Math.pow(2,32);
var p2_32 = Math.pow(2,32);
function pad0r(v/*:any*/,d/*:number*/)/*:string*/{if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); }
/* yes, in 2022 this is still faster than string compare */
function SSF_isgeneral(s/*:string*/, i/*:?number*/)/*:boolean*/ { i = i || 0; return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; }
function isgeneral(s/*:string*/, i/*:?number*/)/*:boolean*/ { i = i || 0; return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; }
/*::
type SSF_write_num = {(type:string, fmt:string, val:number):string};
*/
var days/*:Array<Array<string> >*/ = [
['Sun', 'Sunday'],
['Mon', 'Monday'],
@ -33,8 +39,7 @@ var months/*:Array<Array<string> >*/ = [
['N', 'Nov', 'November'],
['D', 'Dec', 'December']
];
function SSF_init_table(t/*:any*/) {
if(!t) t = {};
function init_table(t/*:any*/) {
t[0]= 'General';
t[1]= '0';
t[2]= '0.00';
@ -64,96 +69,66 @@ function SSF_init_table(t/*:any*/) {
t[48]= '##0.0E+0';
t[49]= '@';
t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "';
return t;
}
/* repeated to satiate webpack */
var table_fmt = {
0: 'General',
1: '0',
2: '0.00',
3: '#,##0',
4: '#,##0.00',
9: '0%',
10: '0.00%',
11: '0.00E+00',
12: '# ?/?',
13: '# ??/??',
14: 'm/d/yy',
15: 'd-mmm-yy',
16: 'd-mmm',
17: 'mmm-yy',
18: 'h:mm AM/PM',
19: 'h:mm:ss AM/PM',
20: 'h:mm',
21: 'h:mm:ss',
22: 'm/d/yy h:mm',
37: '#,##0 ;(#,##0)',
38: '#,##0 ;[Red](#,##0)',
39: '#,##0.00;(#,##0.00)',
40: '#,##0.00;[Red](#,##0.00)',
45: 'mm:ss',
46: '[h]:mm:ss',
47: 'mmss.0',
48: '##0.0E+0',
49: '@',
56: '"上午/下午 "hh"時"mm"分"ss"秒 "'
};
var table_fmt = {};
init_table(table_fmt);
/* Defaults determined by systematically testing in Excel 2019 */
/* These formats appear to default to other formats in the table */
var SSF_default_map = {
5: 37, 6: 38, 7: 39, 8: 40, // 5 -> 37 ... 8 -> 40
var default_map/*:Array<number>*/ = [];
var defi = 0;
23: 0, 24: 0, 25: 0, 26: 0, // 23 -> 0 ... 26 -> 0
// 5 -> 37 ... 8 -> 40
for(defi = 5; defi <= 8; ++defi) default_map[defi] = 32 + defi;
27: 14, 28: 14, 29: 14, 30: 14, 31: 14, // 27 -> 14 ... 31 -> 14
// 23 -> 0 ... 26 -> 0
for(defi = 23; defi <= 26; ++defi) default_map[defi] = 0;
50: 14, 51: 14, 52: 14, 53: 14, 54: 14, // 50 -> 14 ... 58 -> 14
55: 14, 56: 14, 57: 14, 58: 14,
59: 1, 60: 2, 61: 3, 62: 4, // 59 -> 1 ... 62 -> 4
// 27 -> 14 ... 31 -> 14
for(defi = 27; defi <= 31; ++defi) default_map[defi] = 14;
// 50 -> 14 ... 58 -> 14
for(defi = 50; defi <= 58; ++defi) default_map[defi] = 14;
67: 9, 68: 10, // 67 -> 9 ... 68 -> 10
69: 12, 70: 13, 71: 14, // 69 -> 12 ... 71 -> 14
72: 14, 73: 15, 74: 16, 75: 17, // 72 -> 14 ... 75 -> 17
76: 20, 77: 21, 78: 22, // 76 -> 20 ... 78 -> 22
79: 45, 80: 46, 81: 47, // 79 -> 45 ... 81 -> 47
82: 0 // 82 -> 0 ... 65536 -> 0 (omitted)
};
// 59 -> 1 ... 62 -> 4
for(defi = 59; defi <= 62; ++defi) default_map[defi] = defi - 58;
// 67 -> 9 ... 68 -> 10
for(defi = 67; defi <= 68; ++defi) default_map[defi] = defi - 58;
// 72 -> 14 ... 75 -> 17
for(defi = 72; defi <= 75; ++defi) default_map[defi] = defi - 58;
// 69 -> 12 ... 71 -> 14
for(defi = 67; defi <= 68; ++defi) default_map[defi] = defi - 57;
// 76 -> 20 ... 78 -> 22
for(defi = 76; defi <= 78; ++defi) default_map[defi] = defi - 56;
// 79 -> 45 ... 81 -> 47
for(defi = 79; defi <= 81; ++defi) default_map[defi] = defi - 34;
// 82 -> 0 ... 65536 -> 0 (omitted)
/* These formats technically refer to Accounting formats with no equivalent */
var SSF_default_str = {
// 5 -- Currency, 0 decimal, black negative
5: '"$"#,##0_);\\("$"#,##0\\)',
63: '"$"#,##0_);\\("$"#,##0\\)',
var default_str/*:Array<string>*/ = [];
// 6 -- Currency, 0 decimal, red negative
6: '"$"#,##0_);[Red]\\("$"#,##0\\)',
64: '"$"#,##0_);[Red]\\("$"#,##0\\)',
// 5 -- Currency, 0 decimal, black negative
default_str[5] = default_str[63] = '"$"#,##0_);\\("$"#,##0\\)';
// 6 -- Currency, 0 decimal, red negative
default_str[6] = default_str[64] = '"$"#,##0_);[Red]\\("$"#,##0\\)';
// 7 -- Currency, 2 decimal, black negative
default_str[7] = default_str[65] = '"$"#,##0.00_);\\("$"#,##0.00\\)';
// 8 -- Currency, 2 decimal, red negative
default_str[8] = default_str[66] = '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)';
// 7 -- Currency, 2 decimal, black negative
7: '"$"#,##0.00_);\\("$"#,##0.00\\)',
65: '"$"#,##0.00_);\\("$"#,##0.00\\)',
// 8 -- Currency, 2 decimal, red negative
8: '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
66: '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
// 41 -- Accounting, 0 decimal, No Symbol
41: '_(* #,##0_);_(* \\(#,##0\\);_(* "-"_);_(@_)',
// 42 -- Accounting, 0 decimal, $ Symbol
42: '_("$"* #,##0_);_("$"* \\(#,##0\\);_("$"* "-"_);_(@_)',
// 43 -- Accounting, 2 decimal, No Symbol
43: '_(* #,##0.00_);_(* \\(#,##0.00\\);_(* "-"??_);_(@_)',
// 44 -- Accounting, 2 decimal, $ Symbol
44: '_("$"* #,##0.00_);_("$"* \\(#,##0.00\\);_("$"* "-"??_);_(@_)'
};
function SSF_frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
// 41 -- Accounting, 0 decimal, No Symbol
default_str[41] = '_(* #,##0_);_(* \\(#,##0\\);_(* "-"_);_(@_)';
// 42 -- Accounting, 0 decimal, $ Symbol
default_str[42] = '_("$"* #,##0_);_("$"* \\(#,##0\\);_("$"* "-"_);_(@_)';
// 43 -- Accounting, 2 decimal, No Symbol
default_str[43] = '_(* #,##0.00_);_(* \\(#,##0.00\\);_(* "-"??_);_(@_)';
// 44 -- Accounting, 2 decimal, $ Symbol
default_str[44] = '_("$"* #,##0.00_);_("$"* \\(#,##0.00\\);_("$"* "-"??_);_(@_)';
function frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
var sgn = x < 0 ? -1 : 1;
var B = x * sgn;
var P_2 = 0, P_1 = 1, P = 0;
@ -173,20 +148,8 @@ function SSF_frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number
var q = Math.floor(sgn * P/Q);
return [q, sgn*P - q*Q, Q];
}
function SSF_normalize_xl_unsafe(v/*:number*/)/*:number*/ {
var s = v.toPrecision(16);
if(s.indexOf("e") > -1) {
var m = s.slice(0, s.indexOf("e"));
m = m.indexOf(".") > -1 ? m.slice(0, (m.slice(0,2) == "0." ? 17 : 16)) : (m.slice(0,15) + fill("0", m.length - 15));
return m + s.slice(s.indexOf("e"));
}
var n = s.indexOf(".") > -1 ? s.slice(0, (s.slice(0,2) == "0." ? 17 : 16)) : (s.slice(0,15) + fill("0", s.length - 15));
return Number(n);
}
function SSF_parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
function parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
if(v > 2958465 || v < 0) return null;
v = SSF_normalize_xl_unsafe(v);
var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
var dout=[];
var out={D:date, T:time, u:86400*(v-date)-time,y:0,m:0,d:0,H:0,M:0,S:0,q:0};
@ -206,7 +169,7 @@ function SSF_parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
dow = d.getDay();
if(date < 60) dow = (dow + 6) % 7;
if(b2) dow = SSF_fix_hijri(d, dout);
if(b2) dow = fix_hijri(d, dout);
}
out.y = dout[0]; out.m = dout[1]; out.d = dout[2];
out.S = time % 60; time = Math.floor(time / 60);
@ -215,45 +178,64 @@ function SSF_parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
out.q = dow;
return out;
}
SSF.parse_date_code = parse_date_code;
var basedate = new Date(1899, 11, 31, 0, 0, 0);
var dnthresh = basedate.getTime();
var base1904 = new Date(1900, 2, 1, 0, 0, 0);
function datenum_local(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
var epoch = v.getTime();
if(date1904) epoch -= 1461*24*60*60*1000;
else if(v >= base1904) epoch += 24*60*60*1000;
return (epoch - (dnthresh + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
}
/* The longest 32-bit integer text is "-4294967296", exactly 11 chars */
function general_fmt_int(v/*:number*/)/*:string*/ { return v.toString(10); }
SSF._general_int = general_fmt_int;
/* ECMA-376 18.8.30 numFmt*/
/* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
/* exponent >= -9 and <= 9 */
function SSF_strip_decimal(o/*:string*/)/*:string*/ {
return (o.indexOf(".") == -1) ? o : o.replace(/(?:\.0*|(\.\d*[1-9])0+)$/, "$1");
}
var general_fmt_num = (function make_general_fmt_num() {
var trailing_zeroes_and_decimal = /(?:\.0*|(\.\d*[1-9])0+)$/;
function strip_decimal(o/*:string*/)/*:string*/ {
return (o.indexOf(".") == -1) ? o : o.replace(trailing_zeroes_and_decimal, "$1");
}
/* General Exponential always shows 2 digits exp and trims the mantissa */
function SSF_normalize_exp(o/*:string*/)/*:string*/ {
if(o.indexOf("E") == -1) return o;
return o.replace(/(?:\.0*|(\.\d*[1-9])0+)[Ee]/,"$1E").replace(/(E[+-])(\d)$/,"$10$2");
}
/* General Exponential always shows 2 digits exp and trims the mantissa */
var mantissa_zeroes_and_decimal = /(?:\.0*|(\.\d*[1-9])0+)[Ee]/;
var exp_with_single_digit = /(E[+-])(\d)$/;
function normalize_exp(o/*:string*/)/*:string*/ {
if(o.indexOf("E") == -1) return o;
return o.replace(mantissa_zeroes_and_decimal,"$1E").replace(exp_with_single_digit,"$10$2");
}
/* exponent >= -9 and <= 9 */
function SSF_small_exp(v/*:number*/)/*:string*/ {
var w = (v<0?12:11);
var o = SSF_strip_decimal(v.toFixed(12)); if(o.length <= w) return o;
o = v.toPrecision(10); if(o.length <= w) return o;
return v.toExponential(5);
}
/* exponent >= -9 and <= 9 */
function small_exp(v/*:number*/)/*:string*/ {
var w = (v<0?12:11);
var o = strip_decimal(v.toFixed(12)); if(o.length <= w) return o;
o = v.toPrecision(10); if(o.length <= w) return o;
return v.toExponential(5);
}
/* exponent >= 11 or <= -10 likely exponential */
function SSF_large_exp(v/*:number*/)/*:string*/ {
var o = SSF_strip_decimal(v.toFixed(11));
return (o.length > (v<0?12:11) || o === "0" || o === "-0") ? v.toPrecision(6) : o;
}
/* exponent >= 11 or <= -10 likely exponential */
function large_exp(v/*:number*/)/*:string*/ {
var o = strip_decimal(v.toFixed(11));
return (o.length > (v<0?12:11) || o === "0" || o === "-0") ? v.toPrecision(6) : o;
}
function SSF_general_num(v/*:number*/)/*:string*/ {
if(!isFinite(v)) return isNaN(v) ? "#NUM!" : "#DIV/0!";
var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
function general_fmt_num_base(v/*:number*/)/*:string*/ {
var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
else if(Math.abs(V) <= 9) o = SSF_small_exp(v);
else if(V === 10) o = v.toFixed(10).substr(0,12);
else o = SSF_large_exp(v);
if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
else if(Math.abs(V) <= 9) o = small_exp(v);
else if(V === 10) o = v.toFixed(10).substr(0,12);
else o = large_exp(v);
return SSF_strip_decimal(SSF_normalize_exp(o.toUpperCase()));
}
return strip_decimal(normalize_exp(o.toUpperCase()));
}
return general_fmt_num_base;
})();
SSF._general_num = general_fmt_num;
/*
"General" rules:
@ -262,23 +244,22 @@ function SSF_general_num(v/*:number*/)/*:string*/ {
- "up to 11 characters" displayed for numbers
- Default date format (code 14) used for Dates
The longest 32-bit integer text is "-2147483648", exactly 11 chars
TODO: technically the display depends on the width of the cell
*/
function SSF_general(v/*:any*/, opts/*:any*/) {
function general_fmt(v/*:any*/, opts/*:any*/) {
switch(typeof v) {
case 'string': return v;
case 'boolean': return v ? "TRUE" : "FALSE";
case 'number': return (v|0) === v ? v.toString(10) : SSF_general_num(v);
case 'number': return (v|0) === v ? v.toString(10) : general_fmt_num(v);
case 'undefined': return "";
case 'object':
if(v == null) return "";
if(v instanceof Date) return SSF_format(14, datenum(v, opts && opts.date1904), opts);
if(v instanceof Date) return format(14, datenum_local(v, opts && opts.date1904), opts);
}
throw new Error("unsupported value in General format: " + v);
}
function SSF_fix_hijri(date/*:Date*/, o/*:[number, number, number]*/) {
SSF._general = general_fmt;
function fix_hijri(date/*:Date*/, o/*:[number, number, number]*/) {
/* TODO: properly adjust y/m/d and */
o[0] -= 581;
var dow = date.getDay();
@ -286,7 +267,8 @@ function SSF_fix_hijri(date/*:Date*/, o/*:[number, number, number]*/) {
return dow;
}
//var THAI_DIGITS = "\u0E50\u0E51\u0E52\u0E53\u0E54\u0E55\u0E56\u0E57\u0E58\u0E59".split("");
function SSF_write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*:string*/ {
/*jshint -W086 */
function write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*:string*/ {
var o="", ss=0, tt=0, y = val.y, out, outl = 0;
switch(type) {
case 98: /* 'b' buddhist year */
@ -341,7 +323,7 @@ function SSF_write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*
switch(fmt) {
case '[h]': case '[hh]': out = val.D*24+val.H; break;
case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+(ss0 == 0 ? Math.round(val.S+val.u) : val.S); break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
default: throw 'bad abstime format: ' + fmt;
} outl = fmt.length === 3 ? 1 : 2; break;
case 101: /* 'e' era */
@ -350,9 +332,6 @@ function SSF_write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*
var outstr = outl > 0 ? pad0(out, outl) : "";
return outstr;
}
/*jshint -W086 */
/*jshint +W086 */
function commaify(s/*:string*/)/*:string*/ {
var w = 3;
@ -361,18 +340,17 @@ function commaify(s/*:string*/)/*:string*/ {
for(; j!=s.length; j+=w) o+=(o.length > 0 ? "," : "") + s.substr(j,w);
return o;
}
var write_num/*:SSF_write_num*/ = (function make_write_num(){
var pct1 = /%/g;
function write_num_pct(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
}
function write_num_cm(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
var idx = fmt.length - 1;
while(fmt.charCodeAt(idx-1) === 44) --idx;
return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
}
function write_num_exp(fmt/*:string*/, val/*:number*/)/*:string*/{
var o/*:string*/;
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
@ -409,7 +387,7 @@ function write_num_f2(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:s
return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
}
var dec1 = /^#*0*\.([0#]+)/;
var closeparen = /\)[^)]*[0#]/;
var closeparen = /\).*[0#]/;
var phone = /\(###\) ###\\?-####/;
function hashq(str/*:string*/)/*:string*/ {
var o = "", cc;
@ -481,7 +459,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
var oa = "";
if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
ri = Math.min(/*::String(*/r[4]/*::)*/.length,7);
ff = SSF_frac(aval, Math.pow(10,ri)-1, false);
ff = frac(aval, Math.pow(10,ri)-1, false);
o = "" + sign;
oa = write_num("n", /*::String(*/r[1]/*::)*/, ff[1]);
if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
@ -493,7 +471,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
}
if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
ri = Math.min(Math.max(r[1].length, r[4].length),7);
ff = SSF_frac(aval, Math.pow(10,ri)-1, true);
ff = frac(aval, Math.pow(10,ri)-1, true);
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
}
if((r = fmt.match(/^[#0?]+$/))) {
@ -601,7 +579,7 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
var oa = "";
if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
ri = Math.min(/*::String(*/r[4]/*::)*/.length,7);
ff = SSF_frac(aval, Math.pow(10,ri)-1, false);
ff = frac(aval, Math.pow(10,ri)-1, false);
o = "" + sign;
oa = write_num("n", /*::String(*/r[1]/*::)*/, ff[1]);
if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
@ -613,7 +591,7 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
}
if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
ri = Math.min(Math.max(r[1].length, r[4].length),7);
ff = SSF_frac(aval, Math.pow(10,ri)-1, true);
ff = frac(aval, Math.pow(10,ri)-1, true);
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
}
if((r = fmt.match(/^[#0?]+$/))) {
@ -639,10 +617,10 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
}
throw new Error("unsupported format |" + fmt + "|");
}
function write_num(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
return function write_num(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
return (val|0) === val ? write_num_int(type, fmt, val) : write_num_flt(type, fmt, val);
}
function SSF_split_fmt(fmt/*:string*/)/*:Array<string>*/ {
};})();
function split_fmt(fmt/*:string*/)/*:Array<string>*/ {
var out/*:Array<string>*/ = [];
var in_str = false/*, cc*/;
for(var i = 0, j = 0; i < fmt.length; ++i) switch((/*cc=*/fmt.charCodeAt(i))) {
@ -658,13 +636,13 @@ function SSF_split_fmt(fmt/*:string*/)/*:Array<string>*/ {
if(in_str === true) throw new Error("Format |" + fmt + "| unterminated string ");
return out;
}
var SSF_abstime = /\[[HhMmSs\u0E0A\u0E19\u0E17]*\]/;
SSF._split = split_fmt;
var abstime = /\[[HhMmSs\u0E0A\u0E19\u0E17]*\]/;
function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
var i = 0, /*cc = 0,*/ c = "", o = "";
while(i < fmt.length) {
switch((c = fmt.charAt(i))) {
case 'G': if(SSF_isgeneral(fmt, i)) i+= 6; i++; break;
case 'G': if(isgeneral(fmt, i)) i+= 6; i++; break;
case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;){/*empty*/} ++i; break;
case '\\': i+=2; break;
case '_': i+=2; break;
@ -683,7 +661,7 @@ function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
case '[':
o = c;
while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
if(o.match(SSF_abstime)) return true;
if(o.match(abstime)) return true;
break;
case '.':
/* falls through */
@ -701,7 +679,7 @@ function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
}
return false;
}
SSF.is_date = fmt_is_date;
function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
var out = [], o = "", i = 0, c = "", lst='t', dt, j, cc;
var hr='H';
@ -709,7 +687,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
while(i < fmt.length) {
switch((c = fmt.charAt(i))) {
case 'G': /* General */
if(!SSF_isgeneral(fmt, i)) throw new Error('unrecognized character ' + c + ' in ' +fmt);
if(!isgeneral(fmt, i)) throw new Error('unrecognized character ' + c + ' in ' +fmt);
out[out.length] = {t:'G', v:'General'}; i+=7; break;
case '"': /* Literal text */
for(o="";(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) o += String.fromCharCode(cc);
@ -721,7 +699,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
out[out.length] = {t:'T', v:v}; ++i; break;
case 'B': case 'b':
if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") {
if(dt==null) { dt=SSF_parse_date_code(v, opts, fmt.charAt(i+1) === "2"); if(dt==null) return ""; }
if(dt==null) { dt=parse_date_code(v, opts, fmt.charAt(i+1) === "2"); if(dt==null) return ""; }
out[out.length] = {t:'X', v:fmt.substr(i,2)}; lst = c; i+=2; break;
}
/* falls through */
@ -730,15 +708,15 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
/* falls through */
case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g':
if(v < 0) return "";
if(dt==null) { dt=SSF_parse_date_code(v, opts); if(dt==null) return ""; }
if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
o = c; while(++i < fmt.length && fmt.charAt(i).toLowerCase() === c) o+=c;
if(c === 'm' && lst.toLowerCase() === 'h') c = 'M';
if(c === 'h') c = hr;
out[out.length] = {t:c, v:o}; lst = c; break;
case 'A': case 'a': case '上':
var q={t:c, v:c};
if(dt==null) dt=SSF_parse_date_code(v, opts);
if(fmt.substr(i, 3).toUpperCase() === "A/P") { if(dt!=null) q.v = dt.H >= 12 ? fmt.charAt(i+2) : c; q.t = 'T'; hr='h';i+=3;}
if(dt==null) dt=parse_date_code(v, opts);
if(fmt.substr(i, 3).toUpperCase() === "A/P") { if(dt!=null) q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;}
else if(fmt.substr(i,5).toUpperCase() === "AM/PM") { if(dt!=null) q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; }
else if(fmt.substr(i,5).toUpperCase() === "上午/下午") { if(dt!=null) q.v = dt.H >= 12 ? "下午" : "上午"; q.t = 'T'; i+=5; hr='h'; }
else { q.t = "t"; ++i; }
@ -748,8 +726,8 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
o = c;
while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
if(o.slice(-1) !== ']') throw 'unterminated "[" block: |' + o + '|';
if(o.match(SSF_abstime)) {
if(dt==null) { dt=SSF_parse_date_code(v, opts); if(dt==null) return ""; }
if(o.match(abstime)) {
if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
out[out.length] = {t:'Z', v:o.toLowerCase()};
lst = o.charAt(1);
} else if(o.indexOf("$") > -1) {
@ -789,11 +767,10 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
switch(out[i].t) {
case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
case 's':
if((ssm=out[i].v.match(/\.0+$/))) { ss0=Math.max(ss0,ssm[0].length-1); bt = 4;}
if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
if(bt < 3) bt = 3;
/* falls through */
case 'd': case 'y': case 'e': lst=out[i].t; break;
case 'M': lst=out[i].t; if(bt < 2) bt = 2; break;
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
case 'X': /*if(out[i].v === "B2");*/
break;
@ -803,29 +780,19 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
}
}
/* time rounding depends on presence of minute / second / usec fields */
var _dt;
switch(bt) {
case 0: break;
case 1:
case 2:
case 3:
/*::if(!dt) break;*/
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
if(dt.H >= 24) { dt.H = 0; ++dt.D; _dt = SSF_parse_date_code(dt.D); _dt.u = dt.u; _dt.S = dt.S; _dt.M = dt.M; _dt.H = dt.H; dt = _dt; }
break;
case 4:
switch(ss0) {
case 1: dt.u = Math.round(dt.u * 10)/10; break;
case 2: dt.u = Math.round(dt.u * 100)/100; break;
case 3: dt.u = Math.round(dt.u * 1000)/1000; break;
}
if(dt.u >= 1) { dt.u = 0; ++dt.S; }
case 2:
/*::if(!dt) break;*/
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
if(dt.H >= 24) { dt.H = 0; ++dt.D; _dt = SSF_parse_date_code(dt.D); _dt.u = dt.u; _dt.S = dt.S; _dt.M = dt.M; _dt.H = dt.H; dt = _dt; }
break;
}
@ -837,7 +804,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
case 'X': out[i].v = ""; out[i].t = ";"; break;
case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'b': case 'Z':
/*::if(!dt) throw "unreachable"; */
out[i].v = SSF_write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
out[i].t = 't'; break;
case 'n': case '?':
jj = i+1;
@ -852,7 +819,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
}
nstr += out[i].v;
i = jj-1; break;
case 'G': out[i].t = 't'; out[i].v = SSF_general(v,opts); break;
case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
}
}
var vv = "", myv, ostr;
@ -920,7 +887,8 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
for(i=0; i !== out.length; ++i) if(out[i] != null) retval += out[i].v;
return retval;
}
SSF._eval = eval_fmt;
var cfregex = /\[[=<>]/;
var cfregex2 = /\[(=|>[=]?|<[>=]?)(-?\d+(?:\.\d*)?)\]/;
function chkcond(v, rr) {
if(rr == null) return false;
@ -936,13 +904,11 @@ function chkcond(v, rr) {
return false;
}
function choose_fmt(f/*:string*/, v/*:any*/) {
var fmt = SSF_split_fmt(f);
var fmt = split_fmt(f);
var l = fmt.length, lat = fmt[l-1].indexOf("@");
if(l<4 && lat>-1) --l;
if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
/* NOTE: most spreadsheet software do not support NaN or infinities */
if(typeof v === "number" && !isFinite(v)) v = 0;
switch(fmt.length) {
case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
@ -951,14 +917,14 @@ function choose_fmt(f/*:string*/, v/*:any*/) {
}
var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2];
if(fmt[0].indexOf("[") === -1 && fmt[1].indexOf("[") === -1) return [l, ff];
if(fmt[0].match(/\[[=<>]/) != null || fmt[1].match(/\[[=<>]/) != null) {
if(fmt[0].match(cfregex) != null || fmt[1].match(cfregex) != null) {
var m1 = fmt[0].match(cfregex2);
var m2 = fmt[1].match(cfregex2);
return chkcond(v, m1) ? [l, fmt[0]] : chkcond(v, m2) ? [l, fmt[1]] : [l, fmt[m1 != null && m2 != null ? 2 : 1]];
}
return [l, ff];
}
function SSF_format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
function format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
if(o == null) o = {};
var sfmt = "";
switch(typeof fmt) {
@ -969,21 +935,19 @@ function SSF_format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
case "number":
if(fmt == 14 && o.dateNF) sfmt = o.dateNF;
else sfmt = (o.table != null ? (o.table/*:any*/) : table_fmt)[fmt];
if(sfmt == null) sfmt = (o.table && o.table[SSF_default_map[fmt]]) || table_fmt[SSF_default_map[fmt]];
if(sfmt == null) sfmt = SSF_default_str[fmt] || "General";
if(sfmt == null) sfmt = (o.table && o.table[default_map[fmt]]) || table_fmt[default_map[fmt]];
if(sfmt == null) sfmt = default_str[fmt] || "General";
break;
}
if(SSF_isgeneral(sfmt,0)) return SSF_general(v, o);
if(v instanceof Date) v = datenum(v, o.date1904);
if(isgeneral(sfmt,0)) return general_fmt(v, o);
if(v instanceof Date) v = datenum_local(v, o.date1904);
var f = choose_fmt(sfmt, v);
if(SSF_isgeneral(f[1])) return SSF_general(v, o);
if(isgeneral(f[1])) return general_fmt(v, o);
if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
else if(v === "" || v == null) return "";
else if(isNaN(v) && f[1].indexOf("0") > -1) return "#NUM!";
else if(!isFinite(v) && f[1].indexOf("0") > -1) return "#DIV/0!";
return eval_fmt(f[1], v, o, f[0]);
}
function SSF_load(fmt/*:string*/, idx/*:?number*/)/*:number*/ {
function load_entry(fmt/*:string*/, idx/*:?number*/)/*:number*/ {
if(typeof idx != 'number') {
idx = +idx || -1;
/*::if(typeof idx != 'number') return 0x188; */
@ -999,22 +963,14 @@ function SSF_load(fmt/*:string*/, idx/*:?number*/)/*:number*/ {
table_fmt[idx] = fmt;
return idx;
}
function SSF_load_table(tbl/*:SSFTable*/)/*:void*/ {
SSF.load = load_entry;
SSF._table = table_fmt;
SSF.get_table = function get_table()/*:SSFTable*/ { return table_fmt; };
SSF.load_table = function load_table(tbl/*:SSFTable*/)/*:void*/ {
for(var i=0; i!=0x0188; ++i)
if(tbl[i] !== undefined) SSF_load(tbl[i], i);
}
function make_ssf() {
table_fmt = SSF_init_table();
}
var SSF = {
format: SSF_format,
load: SSF_load,
_table: table_fmt,
load_table: SSF_load_table,
parse_date_code: SSF_parse_date_code,
is_date: fmt_is_date,
get_table: function get_table() { return SSF._table = table_fmt; }
if(tbl[i] !== undefined) load_entry(tbl[i], i);
};
SSF.init_table = init_table;
SSF.format = format;
};
make_ssf(SSF);

@ -1,3 +1,23 @@
/* map from xlml named formats to SSF TODO: localize */
var XLMLFormatMap/*{[string]:string}*/ = ({
"General Number": "General",
"General Date": SSF._table[22],
"Long Date": "dddd, mmmm dd, yyyy",
"Medium Date": SSF._table[15],
"Short Date": SSF._table[14],
"Long Time": SSF._table[19],
"Medium Time": SSF._table[18],
"Short Time": SSF._table[20],
"Currency": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
"Fixed": SSF._table[2],
"Standard": SSF._table[4],
"Percent": SSF._table[10],
"Scientific": SSF._table[11],
"Yes/No": '"Yes";"Yes";"No";@',
"True/False": '"True";"True";"False";@',
"On/Off": '"Yes";"Yes";"No";@'
}/*:any*/);
var SSFImplicit/*{[number]:string}*/ = ({
"5": '"$"#,##0_);\\("$"#,##0\\)',
"6": '"$"#,##0_);[Red]\\("$"#,##0\\)',
@ -41,9 +61,8 @@ var SSFImplicit/*{[number]:string}*/ = ({
/* dateNF parse TODO: move to SSF */
var dateNFregex = /[dD]+|[mM]+|[yYeE]+|[Hh]+|[Ss]+/g;
function dateNF_regex(dateNF/*:string|number*/)/*:RegExp*/ {
var fmt = typeof dateNF == "number" ? table_fmt[dateNF] : dateNF;
var fmt = typeof dateNF == "number" ? SSF._table[dateNF] : dateNF;
fmt = fmt.replace(dateNFregex, "(\\d+)");
dateNFregex.lastIndex = 0;
return new RegExp("^" + fmt + "$");
}
function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/*:string*/ {
@ -56,7 +75,6 @@ function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/
case 'm': if(H >= 0) M = v; else m = v; break;
}
});
dateNFregex.lastIndex = 0;
if(S >= 0 && M == -1 && m >= 0) { M = m; m = -1; }
var datestr = (("" + (Y>=0?Y: new Date().getFullYear())).slice(-4) + "-" + ("00" + (m>=1?m:1)).slice(-2) + "-" + ("00" + (d>=1?d:1)).slice(-2));
if(datestr.length == 7) datestr = "0" + datestr;
@ -67,12 +85,3 @@ function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/
return datestr + "T" + timestr;
}
/* table of bad formats written by third-party tools */
var bad_formats = {
"d.m": "d\\.m" // Issue #2571 Google Sheets writes invalid format 'd.m', correct format is 'd"."m' or 'd\\.m'
};
function SSF__load(fmt, idx) {
return SSF_load(bad_formats[fmt] || fmt, idx);
}

@ -1,4 +1,6 @@
var DO_NOT_EXPORT_CFB = true;
/*::
declare var Base64:any;
declare var ReadShift:any;
declare var CheckField:any;
declare var prep_blob:any;
@ -14,7 +16,6 @@ declare var has_buf:boolean;
declare var new_buf:any;
declare var new_raw_buf:any;
declare var new_unsafe_buf:any;
declare var Buffer_from:any;
*/
/* cfb.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
@ -23,6 +24,7 @@ declare var Buffer_from:any;
/*global Uint8Array:false, Uint16Array:false */
/*::
declare var DO_NOT_EXPORT_CFB:?boolean;
type SectorEntry = {
name?:string;
nodes?:Array<number>;
@ -39,12 +41,16 @@ type CFBFiles = {[n:string]:CFBEntry};
/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*exported CRC32 */
var CRC32 = /*#__PURE__*/(function() {
var CRC32 = {};
var CRC32;
(function (factory) {
/*jshint ignore:start */
/*eslint-disable */
factory(CRC32 = {});
/*eslint-enable */
/*jshint ignore:end */
}(function(CRC32) {
CRC32.version = '1.2.0';
/*::
type CRC32TableType = Array<number> | Int32Array;
*/
/* see perf/crc32table.js */
/*global Int32Array */
function signed_crc_table()/*:any*/ {
var c = 0, table/*:Array<number>*/ = new Array(256);
@ -65,77 +71,78 @@ function signed_crc_table()/*:any*/ {
return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table;
}
var T0 = signed_crc_table();
function slice_by_16_tables(T) {
var c = 0, v = 0, n = 0, table/*:Array<number>*/ = typeof Int32Array !== 'undefined' ? new Int32Array(4096) : new Array(4096) ;
for(n = 0; n != 256; ++n) table[n] = T[n];
for(n = 0; n != 256; ++n) {
v = T[n];
for(c = 256 + n; c < 4096; c += 256) v = table[c] = (v >>> 8) ^ T[v & 0xFF];
var T = signed_crc_table();
function crc32_bstr(bstr/*:string*/, seed/*:number*/)/*:number*/ {
var C = seed ^ -1, L = bstr.length - 1;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
}
var out = [];
for(n = 1; n != 16; ++n) out[n - 1] = typeof Int32Array !== 'undefined' && typeof table.subarray == "function" ? table.subarray(n * 256, n * 256 + 256) : table.slice(n * 256, n * 256 + 256);
return out;
}
var TT = slice_by_16_tables(T0);
var T1 = TT[0], T2 = TT[1], T3 = TT[2], T4 = TT[3], T5 = TT[4];
var T6 = TT[5], T7 = TT[6], T8 = TT[7], T9 = TT[8], Ta = TT[9];
var Tb = TT[10], Tc = TT[11], Td = TT[12], Te = TT[13], Tf = TT[14];
function crc32_bstr(bstr/*:string*/, seed/*:?number*/)/*:number*/ {
var C = seed/*:: ? 0 : 0 */ ^ -1;
for(var i = 0, L = bstr.length; i < L;) C = (C>>>8) ^ T0[(C^bstr.charCodeAt(i++))&0xFF];
return ~C;
if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF];
return C ^ -1;
}
function crc32_buf(B/*:Uint8Array|Array<number>*/, seed/*:number*/)/*:number*/ {
var C = seed/*:: ? 0 : 0 */ ^ -1, L = B.length - 15, i = 0;
for(; i < L;) C =
Tf[B[i++] ^ (C & 255)] ^
Te[B[i++] ^ ((C >> 8) & 255)] ^
Td[B[i++] ^ ((C >> 16) & 255)] ^
Tc[B[i++] ^ (C >>> 24)] ^
Tb[B[i++]] ^ Ta[B[i++]] ^ T9[B[i++]] ^ T8[B[i++]] ^
T7[B[i++]] ^ T6[B[i++]] ^ T5[B[i++]] ^ T4[B[i++]] ^
T3[B[i++]] ^ T2[B[i++]] ^ T1[B[i++]] ^ T0[B[i++]];
L += 15;
while(i < L) C = (C>>>8) ^ T0[(C^B[i++])&0xFF];
return ~C;
function crc32_buf(buf/*:Uint8Array|Array<number>*/, seed/*:number*/)/*:number*/ {
if(buf.length > 10000) return crc32_buf_8(buf, seed);
var C = seed ^ -1, L = buf.length - 3;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
}
while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
return C ^ -1;
}
function crc32_buf_8(buf/*:Uint8Array|Array<number>*/, seed/*:number*/)/*:number*/ {
var C = seed ^ -1, L = buf.length - 7;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
}
while(i < L+7) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
return C ^ -1;
}
function crc32_str(str/*:string*/, seed/*:number*/)/*:number*/ {
var C = seed ^ -1;
for(var i = 0, L = str.length, c = 0, d = 0; i < L;) {
for(var i = 0, L=str.length, c, d; i < L;) {
c = str.charCodeAt(i++);
if(c < 0x80) {
C = (C>>>8) ^ T0[(C^c)&0xFF];
C = (C>>>8) ^ T[(C ^ c)&0xFF];
} else if(c < 0x800) {
C = (C>>>8) ^ T0[(C ^ (192|((c>>6)&31)))&0xFF];
C = (C>>>8) ^ T0[(C ^ (128|(c&63)))&0xFF];
C = (C>>>8) ^ T[(C ^ (192|((c>>6)&31)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF];
} else if(c >= 0xD800 && c < 0xE000) {
c = (c&1023)+64; d = str.charCodeAt(i++)&1023;
C = (C>>>8) ^ T0[(C ^ (240|((c>>8)&7)))&0xFF];
C = (C>>>8) ^ T0[(C ^ (128|((c>>2)&63)))&0xFF];
C = (C>>>8) ^ T0[(C ^ (128|((d>>6)&15)|((c&3)<<4)))&0xFF];
C = (C>>>8) ^ T0[(C ^ (128|(d&63)))&0xFF];
C = (C>>>8) ^ T[(C ^ (240|((c>>8)&7)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|((c>>2)&63)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|((d>>6)&15)|((c&3)<<4)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|(d&63)))&0xFF];
} else {
C = (C>>>8) ^ T0[(C ^ (224|((c>>12)&15)))&0xFF];
C = (C>>>8) ^ T0[(C ^ (128|((c>>6)&63)))&0xFF];
C = (C>>>8) ^ T0[(C ^ (128|(c&63)))&0xFF];
C = (C>>>8) ^ T[(C ^ (224|((c>>12)&15)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|((c>>6)&63)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF];
}
}
return ~C;
return C ^ -1;
}
CRC32.table = T0;
CRC32.table = T;
CRC32.bstr = crc32_bstr;
CRC32.buf = crc32_buf;
CRC32.str = crc32_str;
return CRC32;
})();
}));
/* [MS-CFB] v20171201 */
var CFB = /*#__PURE__*/(function _CFB(){
var CFB = (function _CFB(){
var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
exports.version = '1.2.2';
exports.version = '1.1.4';
/* [MS-CFB] 2.6.4 */
function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
var L = l.split("/"), R = r.split("/");
@ -213,15 +220,8 @@ function parse_extra_field(blob/*:CFBlob*/)/*:any*/ {
if(flags & 4) p.ctime = blob.read_shift(4);
}
if(p.mtime) p.mt = new Date(p.mtime*1000);
} break;
/* ZIP64 Extended Information Field */
case 0x0001: {
var sz1 = blob.read_shift(4), sz2 = blob.read_shift(4);
p.usz = (sz2 * Math.pow(2,32) + sz1);
sz1 = blob.read_shift(4); sz2 = blob.read_shift(4);
p.csz = (sz2 * Math.pow(2,32) + sz1);
// NOTE: volume fields are skipped
} break;
}
break;
}
blob.l = tgt;
o[type] = p;
@ -229,10 +229,9 @@ function parse_extra_field(blob/*:CFBlob*/)/*:any*/ {
return o;
}
var fs/*:: = require('fs'); */;
function get_fs() { return fs || (fs = _fs); }
function get_fs() { return fs || (fs = require('fs')); }
function parse(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/ {
if(file[0] == 0x50 && file[1] == 0x4b) return parse_zip(file, options);
if((file[0] | 0x20) == 0x6d && (file[1]|0x20) == 0x69) return parse_mad(file, options);
if(file.length < 512) throw new Error("CFB file size " + file.length + " < 512");
var mver = 3;
var ssz = 512;
@ -308,7 +307,7 @@ sleuth_fat(difat_start, difat_sec_cnt, sectors, ssz, fat_addrs);
/** Chains */
var sector_list/*:SectorList*/ = make_sector_list(sectors, dir_start, fat_addrs, ssz);
if(dir_start < sector_list.length) sector_list[dir_start].name = "!Directory";
sector_list[dir_start].name = "!Directory";
if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
sector_list[fat_addrs[0]].name = "!FAT";
sector_list.fat_addrs = fat_addrs;
@ -442,7 +441,7 @@ function sleuth_fat(idx/*:number*/, cnt/*:number*/, sectors/*:Array<RawBytes>*/,
if((q = __readInt32LE(sector,i*4)) === ENDOFCHAIN) break;
fat_addrs.push(q);
}
if(cnt >= 1) sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs);
sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs);
}
}
@ -554,13 +553,9 @@ function read_file(filename/*:string*/, options/*:CFBReadOpts*/) {
}
function read(blob/*:RawBytes|string*/, options/*:CFBReadOpts*/) {
var type = options && options.type;
if(!type) {
if(has_buf && Buffer.isBuffer(blob)) type = "buffer";
}
switch(type || "base64") {
switch(options && options.type || "base64") {
case "file": /*:: if(typeof blob !== 'string') throw "Must pass a filename when type='file'"; */return read_file(blob, options);
case "base64": /*:: if(typeof blob !== 'string') throw "Must pass a base64-encoded binary string when type='file'"; */return parse(s2a(Base64_decode(blob)), options);
case "base64": /*:: if(typeof blob !== 'string') throw "Must pass a base64-encoded binary string when type='file'"; */return parse(s2a(Base64.decode(blob)), options);
case "binary": /*:: if(typeof blob !== 'string') throw "Must pass a binary string when type='file'"; */return parse(s2a(blob), options);
}
return parse(/*::typeof blob == 'string' ? new Buffer(blob, 'utf-8') : */blob, options);
@ -607,34 +602,22 @@ function rebuild_cfb(cfb/*:CFBContainer*/, f/*:?boolean*/)/*:void*/ {
if(!gc && !f) return;
var now = new Date(1987, 1, 19), j = 0;
// Track which names exist
var fullPaths = Object.create ? Object.create(null) : {};
var data/*:Array<[string, CFBEntry]>*/ = [];
for(i = 0; i < cfb.FullPaths.length; ++i) {
fullPaths[cfb.FullPaths[i]] = true;
if(cfb.FileIndex[i].type === 0) continue;
data.push([cfb.FullPaths[i], cfb.FileIndex[i]]);
}
for(i = 0; i < data.length; ++i) {
var dad = dirname(data[i][0]);
s = fullPaths[dad];
while(!s) {
while(dirname(dad) && !fullPaths[dirname(dad)]) dad = dirname(dad);
data.push([dad, ({
name: filename(dad).replace("/",""),
type: 1,
clsid: HEADER_CLSID,
ct: now, mt: now,
content: null
}/*:any*/)]);
// Add name to set
fullPaths[dad] = true;
dad = dirname(data[i][0]);
s = fullPaths[dad];
}
s = false;
for(j = 0; j < data.length; ++j) if(data[j][0] === dad) s = true;
if(!s) data.push([dad, ({
name: filename(dad).replace("/",""),
type: 1,
clsid: HEADER_CLSID,
ct: now, mt: now,
content: null
}/*:any*/)]);
}
data.sort(function(x,y) { return namecmp(x[0], y[0]); });
@ -667,20 +650,16 @@ function rebuild_cfb(cfb/*:CFBContainer*/, f/*:?boolean*/)/*:void*/ {
}
function _write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes|string*/ {
function _write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes*/ {
var _opts = options || {};
/* MAD is order-sensitive, skip rebuild and sort */
if(_opts.fileType == 'mad') return write_mad(cfb, _opts);
rebuild_cfb(cfb);
switch(_opts.fileType) {
case 'zip': return write_zip(cfb, _opts);
//case 'mad': return write_mad(cfb, _opts);
}
if(_opts.fileType == 'zip') return write_zip(cfb, _opts);
var L = (function(cfb/*:CFBContainer*/)/*:Array<number>*/{
var mini_size = 0, fat_size = 0;
for(var i = 0; i < cfb.FileIndex.length; ++i) {
var file = cfb.FileIndex[i];
if(!file.content) continue;
/*:: if(file.content == null) throw new Error("unreachable"); */
var flen = file.content.length;
if(flen > 0){
if(flen < 0x1000) mini_size += (flen + 0x3F) >> 6;
@ -771,10 +750,6 @@ function _write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes|strin
file = cfb.FileIndex[i];
if(i === 0) file.start = file.size ? file.start - 1 : ENDOFCHAIN;
var _nm/*:string*/ = (i === 0 && _opts.root) || file.name;
if(_nm.length > 31) {
console.error("Name " + _nm + " will be truncated to " + _nm.slice(0,31));
_nm = _nm.slice(0, 31);
}
flen = 2*(_nm.length+1);
o.write_shift(64, _nm, "utf16le");
o.write_shift(2, flen);
@ -796,36 +771,19 @@ function _write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes|strin
/*:: if(!file.content) throw new Error("unreachable"); */
if(file.size >= 0x1000) {
o.l = (file.start+1) << 9;
if (has_buf && Buffer.isBuffer(file.content)) {
file.content.copy(o, o.l, 0, file.size);
// o is a 0-filled Buffer so just set next offset
o.l += (file.size + 511) & -512;
} else {
for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]);
for(; j & 0x1FF; ++j) o.write_shift(1, 0);
}
for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]);
for(; j & 0x1FF; ++j) o.write_shift(1, 0);
}
}
for(i = 1; i < cfb.FileIndex.length; ++i) {
file = cfb.FileIndex[i];
/*:: if(!file.content) throw new Error("unreachable"); */
if(file.size > 0 && file.size < 0x1000) {
if (has_buf && Buffer.isBuffer(file.content)) {
file.content.copy(o, o.l, 0, file.size);
// o is a 0-filled Buffer so just set next offset
o.l += (file.size + 63) & -64;
} else {
for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]);
for(; j & 0x3F; ++j) o.write_shift(1, 0);
}
for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]);
for(; j & 0x3F; ++j) o.write_shift(1, 0);
}
}
if (has_buf) {
o.l = o.length;
} else {
// When using Buffer, already 0-filled
while(o.l < o.length) o.write_shift(1, 0);
}
while(o.l < o.length) o.write_shift(1, 0);
return o;
}
/* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */
@ -889,13 +847,10 @@ function a2s(o/*:RawBytes*/)/*:string*/ {
function write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes|string*/ {
var o = _write(cfb, options);
switch(options && options.type || "buffer") {
switch(options && options.type) {
case "file": get_fs(); fs.writeFileSync(options.filename, (o/*:any*/)); return o;
case "binary": return typeof o == "string" ? o : a2s(o);
case "base64": return Base64_encode(typeof o == "string" ? o : a2s(o));
case "buffer": if(has_buf) return Buffer.isBuffer(o) ? o : Buffer_from(o);
/* falls through */
case "array": return typeof o == "string" ? s2a(o) : o;
case "binary": return a2s(o);
case "base64": return Base64.encode(a2s(o));
}
return o;
}
@ -965,38 +920,6 @@ function read_bits_n(buf, bl, n) {
return v & f;
}
/* helpers for unaligned bit writes */
function write_bits_3(buf, bl, v) { var w = bl & 7, h = bl >>> 3;
if(w <= 5) buf[h] |= (v & 7) << w;
else {
buf[h] |= (v << w) & 0xFF;
buf[h+1] = (v&7) >> (8-w);
}
return bl + 3;
}
function write_bits_1(buf, bl, v) {
var w = bl & 7, h = bl >>> 3;
v = (v&1) << w;
buf[h] |= v;
return bl + 1;
}
function write_bits_8(buf, bl, v) {
var w = bl & 7, h = bl >>> 3;
v <<= w;
buf[h] |= v & 0xFF; v >>>= 8;
buf[h+1] = v;
return bl + 8;
}
function write_bits_16(buf, bl, v) {
var w = bl & 7, h = bl >>> 3;
v <<= w;
buf[h] |= v & 0xFF; v >>>= 8;
buf[h+1] = v & 0xFF;
buf[h+2] = v >>> 8;
return bl + 16;
}
/* until ArrayBuffer#realloc is a thing, fake a realloc */
function realloc(b, sz/*:number*/) {
var L = b.length, M = 2*L > sz ? 2*L : sz + 5, i = 0;
@ -1010,7 +933,7 @@ function realloc(b, sz/*:number*/) {
} else if(use_typed_arrays) {
var a = new Uint8Array(M);
if(a.set) a.set(b);
else for(; i < L; ++i) a[i] = b[i];
else for(; i < b.length; ++i) a[i] = b[i];
return a;
}
b.length = M;
@ -1022,7 +945,30 @@ function zero_fill_array(n) {
var o = new Array(n);
for(var i = 0; i < n; ++i) o[i] = 0;
return o;
}
}var _deflate = (function() {
var _deflateRaw = (function() {
return function deflateRaw(data, out) {
var boff = 0;
while(boff < data.length) {
var L = Math.min(0xFFFF, data.length - boff);
var h = boff + L == data.length;
/* TODO: this is only type 0 stored */
out.write_shift(1, +h);
out.write_shift(2, L);
out.write_shift(2, (~L) & 0xFFFF);
while(L-- > 0) out[out.l++] = data[boff++];
}
return out.l;
};
})();
return function(data) {
var buf = new_buf(50+Math.floor(data.length*1.1));
var off = _deflateRaw(data, buf);
return buf.slice(0, off);
};
})();
/* modified inflate function also moves original read head */
/* build tree (used for literals and lengths) */
function build_tree(clens, cmap, MAX/*:number*/)/*:number*/ {
@ -1062,7 +1008,6 @@ function build_tree(clens, cmap, MAX/*:number*/)/*:number*/ {
return maxlen;
}
/* Fixed Huffman */
var fix_lmap = use_typed_arrays ? new Uint16Array(512) : zero_fill_array(512);
var fix_dmap = use_typed_arrays ? new Uint16Array(32) : zero_fill_array(32);
if(!use_typed_arrays) {
@ -1082,125 +1027,8 @@ if(!use_typed_arrays) {
for(; i<=279; i++) clens.push(7);
for(; i<=287; i++) clens.push(8);
build_tree(clens, fix_lmap, 288);
})();var _deflateRaw = /*#__PURE__*/(function _deflateRawIIFE() {
var DST_LN_RE = use_typed_arrays ? new Uint8Array(0x8000) : [];
var j = 0, k = 0;
for(; j < DST_LN.length - 1; ++j) {
for(; k < DST_LN[j+1]; ++k) DST_LN_RE[k] = j;
}
for(;k < 32768; ++k) DST_LN_RE[k] = 29;
var LEN_LN_RE = use_typed_arrays ? new Uint8Array(0x103) : [];
for(j = 0, k = 0; j < LEN_LN.length - 1; ++j) {
for(; k < LEN_LN[j+1]; ++k) LEN_LN_RE[k] = j;
}
function write_stored(data, out) {
var boff = 0;
while(boff < data.length) {
var L = Math.min(0xFFFF, data.length - boff);
var h = boff + L == data.length;
out.write_shift(1, +h);
out.write_shift(2, L);
out.write_shift(2, (~L) & 0xFFFF);
while(L-- > 0) out[out.l++] = data[boff++];
}
return out.l;
}
/* Fixed Huffman */
function write_huff_fixed(data, out) {
var bl = 0;
var boff = 0;
var addrs = use_typed_arrays ? new Uint16Array(0x8000) : [];
while(boff < data.length) {
var L = /* data.length - boff; */ Math.min(0xFFFF, data.length - boff);
/* write a stored block for short data */
if(L < 10) {
bl = write_bits_3(out, bl, +!!(boff + L == data.length)); // jshint ignore:line
if(bl & 7) bl += 8 - (bl & 7);
out.l = (bl / 8) | 0;
out.write_shift(2, L);
out.write_shift(2, (~L) & 0xFFFF);
while(L-- > 0) out[out.l++] = data[boff++];
bl = out.l * 8;
continue;
}
bl = write_bits_3(out, bl, +!!(boff + L == data.length) + 2); // jshint ignore:line
var hash = 0;
while(L-- > 0) {
var d = data[boff];
hash = ((hash << 5) ^ d) & 0x7FFF;
var match = -1, mlen = 0;
if((match = addrs[hash])) {
match |= boff & ~0x7FFF;
if(match > boff) match -= 0x8000;
if(match < boff) while(data[match + mlen] == data[boff + mlen] && mlen < 250) ++mlen;
}
if(mlen > 2) {
/* Copy Token */
d = LEN_LN_RE[mlen];
if(d <= 22) bl = write_bits_8(out, bl, bitswap8[d+1]>>1) - 1;
else {
write_bits_8(out, bl, 3);
bl += 5;
write_bits_8(out, bl, bitswap8[d-23]>>5);
bl += 3;
}
var len_eb = (d < 8) ? 0 : ((d - 4)>>2);
if(len_eb > 0) {
write_bits_16(out, bl, mlen - LEN_LN[d]);
bl += len_eb;
}
d = DST_LN_RE[boff - match];
bl = write_bits_8(out, bl, bitswap8[d]>>3);
bl -= 3;
var dst_eb = d < 4 ? 0 : (d-2)>>1;
if(dst_eb > 0) {
write_bits_16(out, bl, boff - match - DST_LN[d]);
bl += dst_eb;
}
for(var q = 0; q < mlen; ++q) {
addrs[hash] = boff & 0x7FFF;
hash = ((hash << 5) ^ data[boff]) & 0x7FFF;
++boff;
}
L-= mlen - 1;
} else {
/* Literal Token */
if(d <= 143) d = d + 48;
else bl = write_bits_1(out, bl, 1);
bl = write_bits_8(out, bl, bitswap8[d]);
addrs[hash] = boff & 0x7FFF;
++boff;
}
}
bl = write_bits_8(out, bl, 0) - 1;
}
out.l = ((bl + 7)/8)|0;
return out.l;
}
return function _deflateRaw(data, out) {
if(data.length < 8) return write_stored(data, out);
return write_huff_fixed(data, out);
};
})();
function _deflate(data) {
var buf = new_buf(50+Math.floor(data.length*1.1));
var off = _deflateRaw(data, buf);
return buf.slice(0, off);
}
/* modified inflate function also moves original read head */
var dyn_lmap = use_typed_arrays ? new Uint16Array(32768) : zero_fill_array(32768);
var dyn_dmap = use_typed_arrays ? new Uint16Array(32768) : zero_fill_array(32768);
var dyn_cmap = use_typed_arrays ? new Uint16Array(128) : zero_fill_array(128);
@ -1304,12 +1132,14 @@ function inflate(data, usz/*:number*/) {
var sz = data[boff>>>3] | data[(boff>>>3)+1]<<8;
boff += 32;
/* push sz bytes */
if(sz > 0) {
if(!usz && OL < woff + sz) { outbuf = realloc(outbuf, woff + sz); OL = outbuf.length; }
while(sz-- > 0) { outbuf[woff++] = data[boff>>>3]; boff += 8; }
}
if(!usz && OL < woff + sz) { outbuf = realloc(outbuf, woff + sz); OL = outbuf.length; }
if(typeof data.copy === 'function') {
// $FlowIgnore
data.copy(outbuf, woff, boff>>>3, (boff>>>3)+sz);
woff += sz; boff += 8*sz;
} else while(sz-- > 0) { outbuf[woff++] = data[boff>>>3]; boff += 8; }
continue;
} else if((header >> 1) == 1) {
} else if((header >>> 1) == 1) {
/* Fixed Huffman */
max_len_1 = 9; max_len_2 = 5;
} else {
@ -1317,8 +1147,8 @@ function inflate(data, usz/*:number*/) {
boff = dyn(data, boff);
max_len_1 = dyn_len_1; max_len_2 = dyn_len_2;
}
if(!usz && (OL < woff + 32767)) { outbuf = realloc(outbuf, woff + 32767); OL = outbuf.length; }
for(;;) { // while(true) is apparently out of vogue in modern JS circles
if(!usz && (OL < woff + 32767)) { outbuf = realloc(outbuf, woff + 32767); OL = outbuf.length; }
/* ingest code and move read head */
var bits = read_bits_n(data, boff, max_len_1);
var code = (header>>>1) == 1 ? fix_lmap[bits] : dyn_lmap[bits];
@ -1349,13 +1179,12 @@ function inflate(data, usz/*:number*/) {
}
/* in the common case, manual byte copy is faster than TA set / Buffer copy */
if(!usz && OL < tgt) { outbuf = realloc(outbuf, tgt + 100); OL = outbuf.length; }
if(!usz && OL < tgt) { outbuf = realloc(outbuf, tgt); OL = outbuf.length; }
while(woff < tgt) { outbuf[woff] = outbuf[woff - dst]; ++woff; }
}
}
}
if(usz) return [outbuf, (boff+7)>>>3];
return [outbuf.slice(0, woff), (boff+7)>>>3];
return [usz ? outbuf : outbuf.slice(0, woff), (boff+7)>>>3];
}
function _inflate(payload, usz) {
@ -1410,11 +1239,6 @@ function parse_zip(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/
var L = blob.l;
blob.l = offset + 4;
/* ZIP64 lengths */
if(EF && EF[0x0001]) {
if((EF[0x0001]||{}).usz) usz = EF[0x0001].usz;
if((EF[0x0001]||{}).csz) csz = EF[0x0001].csz;
}
parse_local_file(blob, csz, usz, o, EF);
blob.l = L;
}
@ -1444,13 +1268,7 @@ function parse_local_file(blob/*:CFBlob*/, csz/*:number*/, usz/*:number*/, o/*:C
if(efsz) {
var ef = parse_extra_field(/*::(*/blob.slice(blob.l, blob.l + efsz)/*:: :any)*/);
if((ef[0x5455]||{}).mt) date = ef[0x5455].mt;
if((ef[0x0001]||{}).usz) _usz = ef[0x0001].usz;
if((ef[0x0001]||{}).csz) _csz = ef[0x0001].csz;
if(EF) {
if((EF[0x5455]||{}).mt) date = EF[0x5455].mt;
if((EF[0x0001]||{}).usz) _usz = EF[0x0001].usz;
if((EF[0x0001]||{}).csz) _csz = EF[0x0001].csz;
}
if(((EF||{})[0x5455]||{}).mt) date = EF[0x5455].mt;
}
blob.l += efsz;
@ -1460,7 +1278,7 @@ function parse_local_file(blob/*:CFBlob*/, csz/*:number*/, usz/*:number*/, o/*:C
var data = blob.slice(blob.l, blob.l + _csz);
switch(meth) {
case 8: data = _inflateRawSync(blob, _usz); break;
case 0: blob.l += _csz; break; // TODO: scan for magic number
case 0: break;
default: throw new Error("Unsupported ZIP Compression method " + meth);
}
@ -1475,8 +1293,8 @@ function parse_local_file(blob/*:CFBlob*/, csz/*:number*/, usz/*:number*/, o/*:C
if(_csz != csz) warn_or_throw(wrn, "Bad compressed size: " + csz + " != " + _csz);
if(_usz != usz) warn_or_throw(wrn, "Bad uncompressed size: " + usz + " != " + _usz);
//var _crc32 = CRC32.buf(data, 0);
//if((crc32>>0) != (_crc32>>0)) warn_or_throw(wrn, "Bad CRC32 checksum: " + crc32 + " != " + _crc32);
var _crc32 = CRC32.buf(data, 0);
if((crc32>>0) != (_crc32>>0)) warn_or_throw(wrn, "Bad CRC32 checksum: " + crc32 + " != " + _crc32);
cfb_add(o, name, data, {unsafe: true, mt: date});
}
function write_zip(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes*/ {
@ -1495,17 +1313,16 @@ function write_zip(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes*/
for(i = 1; i < cfb.FullPaths.length; ++i) {
fp = cfb.FullPaths[i].slice(root.length); fi = cfb.FileIndex[i];
if(!fi.size || !fi.content || (Array.isArray(fi.content) && fi.content.length == 0) || fp == "\u0001Sh33tJ5") continue;
if(!fi.size || !fi.content || fp == "\u0001Sh33tJ5") continue;
var start = start_cd;
/* TODO: CP437 filename */
var namebuf = new_buf(fp.length);
for(j = 0; j < fp.length; ++j) namebuf.write_shift(1, fp.charCodeAt(j) & 0x7F);
namebuf = namebuf.slice(0, namebuf.l);
crcs[fcnt] = typeof fi.content == "string" ? CRC32.bstr(fi.content, 0) : CRC32.buf(/*::((*/fi.content/*::||[]):any)*/, 0);
crcs[fcnt] = CRC32.buf(/*::((*/fi.content/*::||[]):any)*/, 0);
var outbuf = typeof fi.content == "string" ? s2a(fi.content) : fi.content/*::||[]*/;
var outbuf = fi.content/*::||[]*/;
if(method == 8) outbuf = _deflateRawSync(outbuf);
/* local file header */
@ -1528,10 +1345,7 @@ function write_zip(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes*/
start_cd += namebuf.length;
out.push(namebuf);
/* TODO: extra fields? */
/* TODO: encryption header ? */
start_cd += outbuf.length;
out.push(outbuf);
@ -1585,212 +1399,6 @@ function write_zip(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes*/
return bconcat(([bconcat((out/*:any*/)), bconcat(cdirs), o]/*:any*/));
}
var ContentTypeMap = ({
"htm": "text/html",
"xml": "text/xml",
"gif": "image/gif",
"jpg": "image/jpeg",
"png": "image/png",
"mso": "application/x-mso",
"thmx": "application/vnd.ms-officetheme",
"sh33tj5": "application/octet-stream"
}/*:any*/);
function get_content_type(fi/*:CFBEntry*/, fp/*:string*/)/*:string*/ {
if(fi.ctype) return fi.ctype;
var ext = fi.name || "", m = ext.match(/\.([^\.]+)$/);
if(m && ContentTypeMap[m[1]]) return ContentTypeMap[m[1]];
if(fp) {
m = (ext = fp).match(/[\.\\]([^\.\\])+$/);
if(m && ContentTypeMap[m[1]]) return ContentTypeMap[m[1]];
}
return "application/octet-stream";
}
/* 76 character chunks TODO: intertwine encoding */
function write_base64_76(bstr/*:string*/)/*:string*/ {
var data = Base64_encode(bstr);
var o = [];
for(var i = 0; i < data.length; i+= 76) o.push(data.slice(i, i+76));
return o.join("\r\n") + "\r\n";
}
/*
Rules for QP:
- escape =## applies for all non-display characters and literal "="
- space or tab at end of line must be encoded
- \r\n newlines can be preserved, but bare \r and \n must be escaped
- lines must not exceed 76 characters, use soft breaks =\r\n
TODO: Some files from word appear to write line extensions with bare equals:
```
<table class=3DMsoTableGrid border=3D1 cellspacing=3D0 cellpadding=3D0 width=
="70%"
```
*/
function write_quoted_printable(text/*:string*/)/*:string*/ {
var encoded = text.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7E-\xFF=]/g, function(c) {
var w = c.charCodeAt(0).toString(16).toUpperCase();
return "=" + (w.length == 1 ? "0" + w : w);
});
encoded = encoded.replace(/ $/mg, "=20").replace(/\t$/mg, "=09");
if(encoded.charAt(0) == "\n") encoded = "=0D" + encoded.slice(1);
encoded = encoded.replace(/\r(?!\n)/mg, "=0D").replace(/\n\n/mg, "\n=0A").replace(/([^\r\n])\n/mg, "$1=0A");
var o/*:Array<string>*/ = [], split = encoded.split("\r\n");
for(var si = 0; si < split.length; ++si) {
var str = split[si];
if(str.length == 0) { o.push(""); continue; }
for(var i = 0; i < str.length;) {
var end = 76;
var tmp = str.slice(i, i + end);
if(tmp.charAt(end - 1) == "=") end --;
else if(tmp.charAt(end - 2) == "=") end -= 2;
else if(tmp.charAt(end - 3) == "=") end -= 3;
tmp = str.slice(i, i + end);
i += end;
if(i < str.length) tmp += "=";
o.push(tmp);
}
}
return o.join("\r\n");
}
function parse_quoted_printable(data/*:Array<string>*/)/*:RawBytes*/ {
var o = [];
/* unify long lines */
for(var di = 0; di < data.length; ++di) {
var line = data[di];
while(di <= data.length && line.charAt(line.length - 1) == "=") line = line.slice(0, line.length - 1) + data[++di];
o.push(line);
}
/* decode */
for(var oi = 0; oi < o.length; ++oi) o[oi] = o[oi].replace(/[=][0-9A-Fa-f]{2}/g, function($$) { return String.fromCharCode(parseInt($$.slice(1), 16)); });
return s2a(o.join("\r\n"));
}
function parse_mime(cfb/*:CFBContainer*/, data/*:Array<string>*/, root/*:string*/)/*:void*/ {
var fname = "", cte = "", ctype = "", fdata;
var di = 0;
for(;di < 10; ++di) {
var line = data[di];
if(!line || line.match(/^\s*$/)) break;
var m = line.match(/^([^:]*?):\s*([^\s].*)$/);
if(m) switch(m[1].toLowerCase()) {
case "content-location": fname = m[2].trim(); break;
case "content-type": ctype = m[2].trim(); break;
case "content-transfer-encoding": cte = m[2].trim(); break;
}
}
++di;
switch(cte.toLowerCase()) {
case 'base64': fdata = s2a(Base64_decode(data.slice(di).join(""))); break;
case 'quoted-printable': fdata = parse_quoted_printable(data.slice(di)); break;
default: throw new Error("Unsupported Content-Transfer-Encoding " + cte);
}
var file = cfb_add(cfb, fname.slice(root.length), fdata, {unsafe: true});
if(ctype) file.ctype = ctype;
}
function parse_mad(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/ {
if(a2s(file.slice(0,13)).toLowerCase() != "mime-version:") throw new Error("Unsupported MAD header");
var root = (options && options.root || "");
// $FlowIgnore
var data = (has_buf && Buffer.isBuffer(file) ? file.toString("binary") : a2s(file)).split("\r\n");
var di = 0, row = "";
/* if root is not specified, scan for the common prefix */
for(di = 0; di < data.length; ++di) {
row = data[di];
if(!/^Content-Location:/i.test(row)) continue;
row = row.slice(row.indexOf("file"));
if(!root) root = row.slice(0, row.lastIndexOf("/") + 1);
if(row.slice(0, root.length) == root) continue;
while(root.length > 0) {
root = root.slice(0, root.length - 1);
root = root.slice(0, root.lastIndexOf("/") + 1);
if(row.slice(0,root.length) == root) break;
}
}
var mboundary = (data[1] || "").match(/boundary="(.*?)"/);
if(!mboundary) throw new Error("MAD cannot find boundary");
var boundary = "--" + (mboundary[1] || "");
var FileIndex/*:CFBFileIndex*/ = [], FullPaths/*:Array<string>*/ = [];
var o = {
FileIndex: FileIndex,
FullPaths: FullPaths
};
init_cfb(o);
var start_di, fcnt = 0;
for(di = 0; di < data.length; ++di) {
var line = data[di];
if(line !== boundary && line !== boundary + "--") continue;
if(fcnt++) parse_mime(o, data.slice(start_di, di), root);
start_di = di;
}
return o;
}
function write_mad(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:string*/ {
var opts = options || {};
var boundary = opts.boundary || "SheetJS";
boundary = '------=' + boundary;
var out = [
'MIME-Version: 1.0',
'Content-Type: multipart/related; boundary="' + boundary.slice(2) + '"',
'',
'',
''
];
var root = cfb.FullPaths[0], fp = root, fi = cfb.FileIndex[0];
for(var i = 1; i < cfb.FullPaths.length; ++i) {
fp = cfb.FullPaths[i].slice(root.length);
fi = cfb.FileIndex[i];
if(!fi.size || !fi.content || fp == "\u0001Sh33tJ5") continue;
/* Normalize filename */
fp = fp.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7E-\xFF]/g, function(c) {
return "_x" + c.charCodeAt(0).toString(16) + "_";
}).replace(/[\u0080-\uFFFF]/g, function(u) {
return "_u" + u.charCodeAt(0).toString(16) + "_";
});
/* Extract content as binary string */
var ca = fi.content;
// $FlowIgnore
var cstr = has_buf && Buffer.isBuffer(ca) ? ca.toString("binary") : a2s(ca);
/* 4/5 of first 1024 chars ascii -> quoted printable, else base64 */
var dispcnt = 0, L = Math.min(1024, cstr.length), cc = 0;
for(var csl = 0; csl <= L; ++csl) if((cc=cstr.charCodeAt(csl)) >= 0x20 && cc < 0x80) ++dispcnt;
var qp = dispcnt >= L * 4 / 5;
out.push(boundary);
out.push('Content-Location: ' + (opts.root || 'file:///C:/SheetJS/') + fp);
out.push('Content-Transfer-Encoding: ' + (qp ? 'quoted-printable' : 'base64'));
out.push('Content-Type: ' + get_content_type(fi, fp));
out.push('');
out.push(qp ? write_quoted_printable(cstr) : write_base64_76(cstr));
}
out.push(boundary + '--\r\n');
return out.join("\r\n");
}
function cfb_new(opts/*:?any*/)/*:CFBContainer*/ {
var o/*:CFBContainer*/ = ({}/*:any*/);
init_cfb(o, opts);
@ -1872,3 +1480,4 @@ exports.utils = {
return exports;
})();
if(typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO_NOT_EXPORT_CFB === 'undefined') { module.exports = CFB; }

@ -1,5 +1,5 @@
var _fs;
function set_fs(fs) { _fs = fs; }
if(typeof require !== 'undefined') try { _fs = require('fs'); } catch(e) {}
/* normalize data for blob ctor */
function blobify(data) {
@ -11,16 +11,6 @@ function blobify(data) {
function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
/*global IE_SaveFile, Blob, navigator, saveAs, document, File, chrome */
if(typeof _fs !== 'undefined' && _fs.writeFileSync) return enc ? _fs.writeFileSync(fname, payload, enc) : _fs.writeFileSync(fname, payload);
if(typeof Deno !== 'undefined') {
/* in this spot, it's safe to assume typed arrays and TextEncoder/TextDecoder exist */
if(enc && typeof payload == "string") switch(enc) {
case "utf8": payload = new TextEncoder(enc).encode(payload); break;
case "binary": payload = s2ab(payload); break;
/* TODO: binary equivalent */
default: throw new Error("Unsupported encoding " + enc);
}
return Deno.writeFileSync(fname, payload);
}
var data = (enc == "utf8") ? utf8write(payload) : payload;
/*:: declare var IE_SaveFile: any; */
if(typeof IE_SaveFile !== 'undefined') return IE_SaveFile(data, fname);
@ -35,7 +25,7 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
/*:: declare var chrome: any; */
if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
return chrome.downloads.download({ url: url, filename: fname, saveAs: true });
return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
}
var a = document.createElement("a");
if(a.download != null) {
@ -45,10 +35,6 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
return url;
}
} else if(typeof URL !== 'undefined' && !URL.createObjectURL && typeof chrome === 'object') {
/* manifest v3 extensions -- no URL.createObjectURL */
var b64 = "data:application/octet-stream;base64," + Base64_encode_arr(new Uint8Array(blobify(data)));
return chrome.downloads.download({ url: b64, filename: fname, saveAs: true });
}
}
// $FlowIgnore
@ -57,20 +43,19 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
var out = File(fname); out.open("w"); out.encoding = "binary";
if(Array.isArray(payload)) payload = a2s(payload);
out.write(payload); out.close(); return payload;
} catch(e) { if(!e.message || e.message.indexOf("onstruct") == -1) throw e; }
} catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; }
throw new Error("cannot save file " + fname);
}
/* read binary data from file */
function read_binary(path/*:string*/) {
if(typeof _fs !== 'undefined') return _fs.readFileSync(path);
if(typeof Deno !== 'undefined') return Deno.readFileSync(path);
// $FlowIgnore
if(typeof $ !== 'undefined' && typeof File !== 'undefined' && typeof Folder !== 'undefined') try { // extendscript
// $FlowIgnore
var infile = File(path); infile.open("r"); infile.encoding = "binary";
var data = infile.read(); infile.close();
return data;
} catch(e) { if(!e.message || e.message.indexOf("onstruct") == -1) throw e; }
} catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; }
throw new Error("Cannot access file " + path);
}

@ -31,19 +31,22 @@ function evert_arr(obj/*:any*/)/*:EvertArrType*/ {
return o;
}
var dnthresh = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
var epoch = /*#__PURE__*/v.getTime();
var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
if(date1904) { res -= 1462; return res < -1402 ? res - 1 : res; }
return res < 60 ? res - 1 : res;
var epoch = v.getTime();
if(date1904) epoch -= 1462*24*60*60*1000;
var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
}
function numdate(v/*:number*/)/*:Date|number*/ {
if(v >= 60 && v < 61) return v;
var refdate = new Date();
var dnthresh = basedate.getTime() + (refdate.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
var refoffset = refdate.getTimezoneOffset();
function numdate(v/*:number*/)/*:Date*/ {
var out = new Date();
out.setTime((v>60 ? v : (v+1)) * 24 * 60 * 60 * 1000 + dnthresh);
out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh);
if (out.getTimezoneOffset() !== refoffset) {
out.setTime(out.getTime() + (out.getTimezoneOffset() - refoffset) * 60000);
}
return out;
}
@ -74,65 +77,34 @@ function parse_isodur(s) {
return sec;
}
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]], sans "Z"
/* parses a date string as a UTC date */
function parseDate(str/*:string*/, date1904/*:boolean*/)/*:Date*/ {
if(str instanceof Date) return str;
var m = str.match(pdre1);
if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
m = str.match(pdre2);
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
/* TODO: 1900-02-29T00:00:00.000 should return a flag to treat as a date code (affects xlml) */
m = str.match(pdre3);
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt((m[7] + "0000").slice(1,4), 10))||0)));
var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
var good_pd = good_pd_date.getFullYear() == 2017;
/* parses a date as a local date */
function parseDate(str/*:string|Date*/, fixdate/*:?number*/)/*:Date*/ {
var d = new Date(str);
return d;
if(good_pd) {
/*:: if(fixdate == null) fixdate = 0; */
if(fixdate > 0) d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
else if(fixdate < 0) d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000);
return d;
}
if(str instanceof Date) return str;
if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
var s = d.getFullYear();
if(str.indexOf("" + s) > -1) return d;
d.setFullYear(d.getFullYear() + 100); return d;
}
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000);
return out;
}
function cc2str(arr/*:Array<number>*/, debomit)/*:string*/ {
if(has_buf && Buffer.isBuffer(arr)) {
if(debomit && buf_utf16le) {
// TODO: temporary patch
if(arr[0] == 0xFF && arr[1] == 0xFE) return utf8write(arr.slice(2).toString("utf16le"));
if(arr[1] == 0xFE && arr[2] == 0xFF) return utf8write(utf16beread(arr.slice(2).toString("binary")));
}
return arr.toString("binary");
}
if(typeof TextDecoder !== "undefined") try {
if(debomit) {
if(arr[0] == 0xFF && arr[1] == 0xFE) return utf8write(new TextDecoder("utf-16le").decode(arr.slice(2)));
if(arr[0] == 0xFE && arr[1] == 0xFF) return utf8write(new TextDecoder("utf-16be").decode(arr.slice(2)));
}
var rev = {
"\u20ac": "\x80", "\u201a": "\x82", "\u0192": "\x83", "\u201e": "\x84",
"\u2026": "\x85", "\u2020": "\x86", "\u2021": "\x87", "\u02c6": "\x88",
"\u2030": "\x89", "\u0160": "\x8a", "\u2039": "\x8b", "\u0152": "\x8c",
"\u017d": "\x8e", "\u2018": "\x91", "\u2019": "\x92", "\u201c": "\x93",
"\u201d": "\x94", "\u2022": "\x95", "\u2013": "\x96", "\u2014": "\x97",
"\u02dc": "\x98", "\u2122": "\x99", "\u0161": "\x9a", "\u203a": "\x9b",
"\u0153": "\x9c", "\u017e": "\x9e", "\u0178": "\x9f"
};
if(Array.isArray(arr)) arr = new Uint8Array(arr);
return new TextDecoder("latin1").decode(arr).replace(/[€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ]/g, function(c) { return rev[c] || c; });
} catch(e) {}
var o = [], i = 0;
// this cascade is for the browsers and runtimes of antiquity (and for modern runtimes that lack TextEncoder)
try {
for(i = 0; i < arr.length - 65536; i+=65536) o.push(String.fromCharCode.apply(0, arr.slice(i, i + 65536)));
o.push(String.fromCharCode.apply(0, arr.slice(i)));
} catch(e) { try {
for(; i < arr.length - 16384; i+=16384) o.push(String.fromCharCode.apply(0, arr.slice(i, i + 16384)));
o.push(String.fromCharCode.apply(0, arr.slice(i)));
} catch(e) {
for(; i != arr.length; ++i) o.push(String.fromCharCode(arr[i]));
}
}
return o.join("");
function cc2str(arr/*:Array<number>*/)/*:string*/ {
var o = "";
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
return o;
}
function dup(o/*:any*/)/*:any*/ {
@ -149,232 +121,75 @@ function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length
/* TODO: stress test */
function fuzzynum(s/*:string*/)/*:number*/ {
var v/*:number*/ = Number(s);
if(!isNaN(v)) return isFinite(v) ? v : NaN;
if(!isNaN(v)) return v;
if(!/\d/.test(s)) return v;
var wt = 1;
var ss = s.replace(/([\d]),([\d])/g,"$1$2").replace(/[$]/g,"").replace(/[%]/g, function() { wt *= 100; return "";});
if(!isNaN(v = Number(ss))) return v / wt;
ss = ss.replace(/[(]([^()]*)[)]/,function($$, $1) { wt = -wt; return $1;});
ss = ss.replace(/[(](.*)[)]/,function($$, $1) { wt = -wt; return $1;});
if(!isNaN(v = Number(ss))) return v / wt;
return v;
}
/* NOTE: Chrome rejects bare times like 1:23 PM */
var FDRE1 = /^(0?\d|1[0-2])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))\s+([ap])m?$/;
var FDRE2 = /^([01]?\d|2[0-3])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))$/;
var FDISO = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)(\.\d+)?[Z]?$/; // YYYY-mm-dd(T or space)HH:MM:SS[.UUU][Z]
// date regex reference - https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s04.html
// matches mm/dd/yy, mm/dd/yyyy, dd/mm/yy, dd/mm/yyyy
var STRICT_DATE_REGEX = [
"^(?:(1[0-2]|0[1-9])\\.(3[01]|[12][0-9]|0[1-9])|(3[01]|[12][0-9]|0[1-9])\\.(1[0-2]|0[1-9]))\\.([0-2][0-9]{3}|[0-9]{2})$",
"^(?:(1[0-2]|0[1-9])\/(3[01]|[12][0-9]|0[1-9])|(3[01]|[12][0-9]|0[1-9])\/(1[0-2]|0[1-9]))\/([0-2][0-9]{3}|[0-9]{2})$",
"^(?:(1[0-2]|0[1-9])-(3[01]|[12][0-9]|0[1-9])|(3[01]|[12][0-9]|0[1-9])-(1[0-2]|0[1-9]))-([0-2][0-9]{3}|[0-9]{2})$",
"^(?:(1[0-2]|0[1-9])\\.(3[01]|[12][0-9]|0[1-9])|(3[01]|[12][0-9]|0[1-9])\\.(1[0-2]|0[1-9]))\\.([0-2][0-9]{3}|[0-9]{2})$",
"^(?:(1[0-2]|0[1-9])\/(3[01]|[12][0-9]|0[1-9])|(3[01]|[12][0-9]|0[1-9])\/(1[0-2]|0[1-9]))\/([0-2][0-9]{3}|[0-9]{2})$",
"^(?:(1[0-2]|0[1-9])-(3[01]|[12][0-9]|0[1-9])|(3[01]|[12][0-9]|0[1-9])-(1[0-2]|0[1-9]))-([0-2][0-9]{3}|[0-9]{2})$"
];
/* TODO: 1904 adjustment */
var utc_append_works = new Date("6/9/69 00:00 UTC").valueOf() == -17798400000;
function fuzzytime1(M) /*:Date*/ {
if(!M[2]) return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0));
if(M[3]) {
if(M[4]) return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000));
else return new Date(Date.UTC(1899,11,31,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000));
function fuzzydate(s/*:string*/, strictDate/*string*/)/*:Date*/ {
var o = new Date(s), n = new Date(NaN);
if(strictDate) {
var dateFormat = strictDate.toLowerCase().replace(/[.]|[-]/g, '/')
STRICT_DATE_REGEX
.map(function (regex) {
var regexTestString =
var matchStr = regexTestString.test(s)
if(matchStr){
s.replace(/[.]|[-]/g, '/')
if (dateFormat === "dd/mm") {
var splitDate = s.split('/')
var newDate = [s[1], s[0], s[2]]
s = newDate.join('/')
o = new Date(s)
return o
}
o = new Date(s)
return o;
};
})
.filter(function (result) {
return ((result !== undefined) && (result !== null))
});
return n;
}
else if(M[5]) return new Date(Date.UTC(1899,11,31, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0));
else return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0));
}
function fuzzytime2(M) /*:Date*/ {
if(!M[2]) return new Date(Date.UTC(1899,11,31,+M[1], 0, 0, 0));
if(M[3]) {
if(M[4]) return new Date(Date.UTC(1899,11,31,+M[1], +M[2], +M[4], parseFloat(M[3])*1000));
else return new Date(Date.UTC(1899,11,31,0, +M[1], +M[2], parseFloat(M[3])*1000));
}
else if(M[5]) return new Date(Date.UTC(1899,11,31, +M[1], +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0));
else return new Date(Date.UTC(1899,11,31,+M[1], +M[2], 0, 0));
}
var lower_months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'];
function fuzzydate(s/*:string*/)/*:Date*/ {
// See issue 2863 -- this is technically not supported in Excel but is otherwise useful
if(FDISO.test(s)) return s.indexOf("Z") == -1 ? local_to_utc(new Date(s)) : new Date(s);
var lower = s.toLowerCase();
var lnos = lower.replace(/\s+/g, " ").trim();
var M = lnos.match(FDRE1);
if(M) return fuzzytime1(M);
M = lnos.match(FDRE2);
if(M) return fuzzytime2(M);
M = lnos.match(pdre3);
if(M) return new Date(Date.UTC(+M[1], +M[2]-1, +M[3], +M[4], +M[5], ((M[6] && parseInt(M[6].slice(1), 10))|| 0), ((M[7] && parseInt((M[7] + "0000").slice(1,4), 10))||0)));
var o = new Date(utc_append_works && s.indexOf("UTC") == -1 ? s + " UTC": s), n = new Date(NaN);
var y = o.getYear(), m = o.getMonth(), d = o.getDate();
if(isNaN(d)) return n;
if(lower.match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) {
lower = lower.replace(/[^a-z]/g,"").replace(/([^a-z]|^)[ap]m?([^a-z]|$)/,"");
if(lower.length > 3 && lower_months.indexOf(lower) == -1) return n;
} else if(lower.replace(/[ap]m?/, "").match(/[a-z]/)) return n;
if(y < 0 || y > 8099 || s.match(/[^-0-9:,\/\\\ ]/)) return n;
if(y < 0 || y > 8099) return n;
if((m > 0 || d > 1) && y != 101) return o;
if(s.toLowerCase().match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) return o;
if(s.match(/[^-0-9:,\/\\]/)) return n;
return o;
}
var split_regex = /*#__PURE__*/(function() {
var safe_split_regex = "abacaba".split(/(:?b)/i).length == 5;
return function split_regex(str/*:string*/, re, def/*:string*/)/*:Array<string>*/ {
if(safe_split_regex || typeof re == "string") return str.split(re);
var p = str.split(re), o = [p[0]];
for(var i = 1; i < p.length; ++i) { o.push(def); o.push(p[i]); }
return o;
};
})();
function utc_to_local(utc) {
return new Date(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate(), utc.getUTCHours(), utc.getUTCMinutes(), utc.getUTCSeconds(), utc.getUTCMilliseconds());
var safe_split_regex = "abacaba".split(/(:?b)/i).length == 5;
function split_regex(str/*:string*/, re, def/*:string*/)/*:Array<string>*/ {
if(safe_split_regex || typeof re == "string") return str.split(re);
var p = str.split(re), o = [p[0]];
for(var i = 1; i < p.length; ++i) { o.push(def); o.push(p[i]); }
return o;
}
function local_to_utc(local) {
return new Date(Date.UTC(local.getFullYear(), local.getMonth(), local.getDate(), local.getHours(), local.getMinutes(), local.getSeconds(), local.getMilliseconds()));
}
function remove_doctype(str) {
var preamble = str.slice(0, 1024);
var si = preamble.indexOf("<!DOCTYPE");
if(si == -1) return str;
var m = str.match(/<[\w]/);
if(!m) return str;
return str.slice(0, si) + str.slice(m.index);
}
/* str.match(/<!--[\s\S]*?-->/g) --> str_match_ng(str, "<!--", "-->") */
function str_match_ng(str, s, e) {
var out = [];
var si = str.indexOf(s);
while(si > -1) {
var ei = str.indexOf(e, si + s.length);
if(ei == -1) break;
out.push(str.slice(si, ei + e.length));
si = str.indexOf(s, ei + e.length);
}
return out.length > 0 ? out : null;
}
/* str.replace(/<!--[\s\S]*?-->/g, "") --> str_remove_ng(str, "<!--", "-->") */
function str_remove_ng(str, s, e) {
var out = [], last = 0;
var si = str.indexOf(s);
if(si == -1) return str;
while(si > -1) {
out.push(str.slice(last, si));
var ei = str.indexOf(e, si + s.length);
if(ei == -1) break;
if((si = str.indexOf(s, (last = ei + e.length))) == -1) out.push(str.slice(last));
}
return out.join("");
}
/* str.match(/<tag\b[^>]*?>([\s\S]*?)</tag>/) --> str_match_xml(str, "tag") */
var xml_boundary = { " ": 1, "\t": 1, "\r": 1, "\n": 1, ">": 1 };
function str_match_xml(str, tag) {
var si = str.indexOf('<' + tag), w = tag.length + 1, L = str.length;
while(si >= 0 && si <= L - w && !xml_boundary[str.charAt(si + w)]) si = str.indexOf('<' + tag, si+1);
if(si === -1) return null;
var sf = str.indexOf(">", si + tag.length);
if(sf === -1) return null;
var et = "</" + tag + ">";
var ei = str.indexOf(et, sf);
if(ei == -1) return null;
return [str.slice(si, ei + et.length), str.slice(sf + 1, ei)];
}
/* str.match(/<(?:\w+:)?tag\b[^<>]*?>([\s\S]*?)<\/(?:\w+:)?tag>/) --> str_match_xml(str, "tag") */
var str_match_xml_ns = /*#__PURE__*/(function() {
var str_match_xml_ns_cache = {};
return function str_match_xml_ns(str, tag) {
var res = str_match_xml_ns_cache[tag];
if(!res) str_match_xml_ns_cache[tag] = res = [
new RegExp('<(?:\\w+:)?'+tag+'\\b[^<>]*>', "g"),
new RegExp('</(?:\\w+:)?'+tag+'>', "g")
];
res[0].lastIndex = res[1].lastIndex = 0;
var m = res[0].exec(str);
if(!m) return null;
var si = m.index;
var sf = res[0].lastIndex;
res[1].lastIndex = res[0].lastIndex;
m = res[1].exec(str);
if(!m) return null;
var ei = m.index;
var ef = res[1].lastIndex;
return [str.slice(si, ef), str.slice(sf, ei)];
};
})();
/* str.match(/<(?:\w+:)?tag\b[^<>]*?>([\s\S]*?)<\/(?:\w+:)?tag>/g) --> str_match_xml_ns_g(str, "tag") */
var str_match_xml_ns_g = /*#__PURE__*/(function() {
var str_match_xml_ns_cache = {};
return function str_match_xml_ns(str, tag) {
var out = [];
var res = str_match_xml_ns_cache[tag];
if(!res) str_match_xml_ns_cache[tag] = res = [
new RegExp('<(?:\\w+:)?'+tag+'\\b[^<>]*>', "g"),
new RegExp('</(?:\\w+:)?'+tag+'>', "g")
];
res[0].lastIndex = res[1].lastIndex = 0;
var m;
while((m = res[0].exec(str))) {
var si = m.index;
res[1].lastIndex = res[0].lastIndex;
m = res[1].exec(str);
if(!m) return null;
var ef = res[1].lastIndex;
out.push(str.slice(si, ef));
res[0].lastIndex = res[1].lastIndex;
}
return out.length == 0 ? null : out;
};
})();
var str_remove_xml_ns_g = /*#__PURE__*/(function() {
var str_remove_xml_ns_cache = {};
return function str_remove_xml_ns_g(str, tag) {
var out = [];
var res = str_remove_xml_ns_cache[tag];
if(!res) str_remove_xml_ns_cache[tag] = res = [
new RegExp('<(?:\\w+:)?'+tag+'\\b[^<>]*>', "g"),
new RegExp('</(?:\\w+:)?'+tag+'>', "g")
];
res[0].lastIndex = res[1].lastIndex = 0;
var m;
var si = 0, ef = 0;
while((m = res[0].exec(str))) {
si = m.index;
out.push(str.slice(ef, si));
ef = si;
res[1].lastIndex = res[0].lastIndex;
m = res[1].exec(str);
if(!m) return null;
ef = res[1].lastIndex;
res[0].lastIndex = res[1].lastIndex;
}
out.push(str.slice(ef));
return out.length == 0 ? "" : out.join("");
};
})();
/* str.match(/<(?:\w+:)?tag\b[^>]*?>([\s\S]*?)<\/(?:\w+:)?tag>/gi) --> str_match_xml_ns_ig(str, "tag") */
var str_match_xml_ig = /*#__PURE__*/(function() {
var str_match_xml_ns_cache = {};
return function str_match_xml_ns(str, tag) {
var out = [];
var res = str_match_xml_ns_cache[tag];
if(!res) str_match_xml_ns_cache[tag] = res = [
new RegExp('<'+tag+'\\b[^<>]*>', "ig"),
new RegExp('</'+tag+'>', "ig")
];
res[0].lastIndex = res[1].lastIndex = 0;
var m;
while((m = res[0].exec(str))) {
var si = m.index;
res[1].lastIndex = res[0].lastIndex;
m = res[1].exec(str);
if(!m) return null;
var ef = res[1].lastIndex;
out.push(str.slice(si, ef));
res[0].lastIndex = res[1].lastIndex;
}
return out.length == 0 ? null : out;
};
})();

@ -1,10 +1,10 @@
function getdatastr(data)/*:?string*/ {
if(!data) return null;
if(data.content && data.type) return cc2str(data.content, true);
if(data.data) return debom(data.data);
if(data.asNodeBuffer && has_buf) return debom(data.asNodeBuffer().toString('binary'));
if(data.asBinary) return debom(data.asBinary());
if(data._data && data._data.getContent) return debom(cc2str(Array.prototype.slice.call(data._data.getContent(),0)));
if(data.content && data.type) return debom(cc2str(data.content));
return null;
}
@ -27,10 +27,10 @@ function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getda
/* OASIS does not comment on filename case sensitivity */
function safegetzipfile(zip, file/*:string*/) {
var k = zip.FullPaths || keys(zip.files);
var f = file.toLowerCase().replace(/[\/]/g, '\\'), g = f.replace(/\\/g,'\/');
var f = file.toLowerCase(), g = f.replace(/\//g,'\\');
for(var i=0; i<k.length; ++i) {
var n = k[i].replace(/^Root Entry[\/]/,"").toLowerCase();
if(f == n || g == n) return zip.files ? zip.files[k[i]] : zip.FileIndex[i];
var n = k[i].toLowerCase();
if(f == n || g == n) return zip.files[k[i]];
}
return null;
}
@ -53,45 +53,47 @@ function getzipstr(zip, file/*:string*/, safe/*:?boolean*/)/*:?string*/ {
try { return getzipstr(zip, file); } catch(e) { return null; }
}
function getzipbin(zip, file/*:string*/, safe/*:?boolean*/)/*:any*/ {
if(!safe) return getdatabin(getzipfile(zip, file));
if(!file) return null;
try { return getzipbin(zip, file); } catch(e) { return null; }
}
function zipentries(zip) {
var k = zip.FullPaths || keys(zip.files), o = [];
for(var i = 0; i < k.length; ++i) if(k[i].slice(-1) != '/') o.push(k[i].replace(/^Root Entry[\/]/, ""));
for(var i = 0; i < k.length; ++i) if(k[i].slice(-1) != '/') o.push(k[i]);
return o.sort();
}
function zip_add_file(zip, path, content) {
if(zip.FullPaths) {
if(Array.isArray(content) && typeof content[0] == "string") {
content = content.join("");
}
if(typeof content == "string") {
var res;
if(has_buf) res = Buffer_from(content);
/* TODO: investigate performance in Edge 13 */
//else if(typeof TextEncoder !== "undefined") res = new TextEncoder().encode(content);
else res = utf8decode(content);
return CFB.utils.cfb_add(zip, path, res);
}
CFB.utils.cfb_add(zip, path, content);
}
if(zip.FullPaths) CFB.utils.cfb_add(zip, path, content);
else zip.file(path, content);
}
function zip_new() { return CFB.utils.cfb_new(); }
var jszip;
/*:: declare var JSZipSync:any; */
/*global JSZipSync:true */
if(typeof JSZipSync !== 'undefined') jszip = JSZipSync;
if(typeof exports !== 'undefined') {
if(typeof module !== 'undefined' && module.exports) {
if(typeof jszip === 'undefined') jszip = require('./jszip.js');
}
}
function zip_new() {
if(!jszip) return CFB.utils.cfb_new();
return new jszip();
}
function zip_read(d, o) {
switch(o.type) {
case "base64": return CFB.read(d, { type: "base64" });
case "binary": return CFB.read(d, { type: "binary" });
case "buffer": case "array": return CFB.read(d, { type: "buffer" });
var zip;
if(jszip) switch(o.type) {
case "base64": zip = new jszip(d, { base64:true }); break;
case "binary": case "array": zip = new jszip(d, { base64:false }); break;
case "buffer": zip = new jszip(d); break;
default: throw new Error("Unrecognized type " + o.type);
}
throw new Error("Unrecognized type " + o.type);
else switch(o.type) {
case "base64": zip = CFB.read(d, { type: "base64" }); break;
case "binary": zip = CFB.read(d, { type: "binary" }); break;
case "buffer": case "array": zip = CFB.read(d, { type: "buffer" }); break;
default: throw new Error("Unrecognized type " + o.type);
}
return zip;
}
function resolve_path(path/*:string*/, base/*:string*/)/*:string*/ {

@ -1,7 +1,8 @@
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
var attregexg=/\s([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex1=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?<>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'"<>\s=]+))*\s*[\/\?]?>/mg, tagregex2 = /<[^<>]*>/g;
var tagregex = /*#__PURE__*/XML_HEADER.match(tagregex1) ? tagregex1 : tagregex2;
var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s*[\/\?]?>/mg;
if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*/)/*:any*/ {
var z = ({}/*:any*/);
@ -11,7 +12,7 @@ function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*
if(eq === tag.length) return z;
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1;
if(m) for(i = 0; i != m.length; ++i) {
cc = m[i].slice(1);
cc = m[i];
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
q = cc.slice(0,c).trim();
while(cc.charCodeAt(c+1) == 32) ++c;
@ -32,26 +33,6 @@ function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*
}
return z;
}
function parsexmltagraw(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*/)/*:any*/ {
var z = ({}/*:any*/);
var eq = 0, c = 0;
for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
if(!skip_root) z[0] = tag.slice(0, eq);
if(eq === tag.length) return z;
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1;
if(m) for(i = 0; i != m.length; ++i) {
cc = m[i].slice(1);
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
q = cc.slice(0,c).trim();
while(cc.charCodeAt(c+1) == 32) ++c;
quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0;
v = cc.slice(c+1+quot, cc.length-quot);
if(q.indexOf("_") > 0) q = q.slice(0, q.indexOf("_")); // from ods
z[q] = v;
if(!skip_LC) z[q.toLowerCase()] = v;
}
return z;
}
function strip_ns(x/*:string*/)/*:string*/ { return x.replace(nsregex2, "<$1"); }
var encodings = {
@ -61,26 +42,22 @@ var encodings = {
'&lt;': '<',
'&amp;': '&'
};
var rencoding = /*#__PURE__*/evert(encodings);
var rencoding = evert(encodings);
//var rencstr = "&<>'\"".split("");
// TODO: CP remap (need to read file version to determine OS)
var unescapexml/*:StringConv*/ = /*#__PURE__*/(function() {
var unescapexml/*:StringConv*/ = (function() {
/* 22.4.2.4 bstr (Basic String) */
var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/g;
function raw_unescapexml(text/*:string*/)/*:string*/ {
var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig;
return function unescapexml(text/*:string*/)/*:string*/ {
var s = text + '', i = s.indexOf("<![CDATA[");
if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
var j = s.indexOf("]]>");
return raw_unescapexml(s.slice(0, i)) + s.slice(i+9,j) + raw_unescapexml(s.slice(j+3));
}
return function unescapexml(text/*:string*/, xlsx/*:boolean*/) {
var out = raw_unescapexml(text);
return xlsx ? out.replace(/\r\n/g, "\n") : out;
return unescapexml(s.slice(0, i)) + s.slice(i+9,j) + unescapexml(s.slice(j+3));
};
})();
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f\uFFFE-\uFFFF]/g;
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
function escapexml(text/*:string*/)/*:string*/{
var s = text + '';
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";});
@ -99,24 +76,24 @@ function escapexlml(text/*:string*/)/*:string*/{
}
/* TODO: handle codepages */
var xlml_fixstr/*:StringConv*/ = /*#__PURE__*/(function() {
var xlml_fixstr/*:StringConv*/ = (function() {
var entregex = /&#(\d+);/g;
function entrepl($$/*:string*/,$1/*:string*/)/*:string*/ { return String.fromCharCode(parseInt($1,10)); }
return function xlml_fixstr(str/*:string*/)/*:string*/ { return str.replace(entregex,entrepl); };
})();
function xlml_unfixstr(str/*:string*/)/*:string*/ { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); }
var xlml_unfixstr/*:StringConv*/ = (function() {
return function xlml_unfixstr(str/*:string*/)/*:string*/ { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); };
})();
/* note: xsd:boolean valid values: true / 1 / false / 0 */
function parsexmlbool(value/*:any*/)/*:boolean*/ {
switch(value) {
case 1: case true: case '1': case 'true': return true;
case 0: case false: case '0': case 'false': return false;
//default: throw new Error("Invalid xsd:boolean " + value);
case 1: case true: case '1': case 'true': case 'TRUE': return true;
/* case '0': case 'false': case 'FALSE':*/
default: return false;
}
return false;
}
function utf8reada(orig/*:string*/)/*:string*/ {
var utf8read/*:StringConv*/ = function utf8reada(orig/*:string*/)/*:string*/ {
var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
while (i < orig.length) {
c = orig.charCodeAt(i++);
@ -131,31 +108,9 @@ function utf8reada(orig/*:string*/)/*:string*/ {
out += String.fromCharCode(0xDC00 + (w&1023));
}
return out;
}
};
function utf8readb(data) {
var out = new_raw_buf(2*data.length), w, i, j = 1, k = 0, ww=0, c;
for(i = 0; i < data.length; i+=j) {
j = 1;
if((c=data.charCodeAt(i)) < 128) w = c;
else if(c < 224) { w = (c&31)*64+(data.charCodeAt(i+1)&63); j=2; }
else if(c < 240) { w=(c&15)*4096+(data.charCodeAt(i+1)&63)*64+(data.charCodeAt(i+2)&63); j=3; }
else { j = 4;
w = (c & 7)*262144+(data.charCodeAt(i+1)&63)*4096+(data.charCodeAt(i+2)&63)*64+(data.charCodeAt(i+3)&63);
w -= 65536; ww = 0xD800 + ((w>>>10)&1023); w = 0xDC00 + (w&1023);
}
if(ww !== 0) { out[k++] = ww&255; out[k++] = ww>>>8; ww = 0; }
out[k++] = w%256; out[k++] = w>>>8;
}
return out.slice(0,k).toString('ucs2');
}
function utf8readc(data) { return Buffer_from(data, 'binary').toString('utf8'); }
var utf8corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3";
var utf8read = has_buf && (/*#__PURE__*/utf8readc(utf8corpus) == /*#__PURE__*/utf8reada(utf8corpus) && utf8readc || /*#__PURE__*/utf8readb(utf8corpus) == /*#__PURE__*/utf8reada(utf8corpus) && utf8readb) || utf8reada;
var utf8write/*:StringConv*/ = has_buf ? function(data) { return Buffer_from(data, 'utf8').toString("binary"); } : function(orig/*:string*/)/*:string*/ {
var utf8write/*:StringConv*/ = function(orig/*:string*/)/*:string*/ {
var out/*:Array<string>*/ = [], i = 0, c = 0, d = 0;
while(i < orig.length) {
c = orig.charCodeAt(i++);
@ -181,7 +136,42 @@ var utf8write/*:StringConv*/ = has_buf ? function(data) { return Buffer_from(dat
return out.join("");
};
var htmldecode/*:{(s:string):string}*/ = /*#__PURE__*/(function() {
if(has_buf) {
var utf8readb = function utf8readb(data) {
var out = Buffer.alloc(2*data.length), w, i, j = 1, k = 0, ww=0, c;
for(i = 0; i < data.length; i+=j) {
j = 1;
if((c=data.charCodeAt(i)) < 128) w = c;
else if(c < 224) { w = (c&31)*64+(data.charCodeAt(i+1)&63); j=2; }
else if(c < 240) { w=(c&15)*4096+(data.charCodeAt(i+1)&63)*64+(data.charCodeAt(i+2)&63); j=3; }
else { j = 4;
w = (c & 7)*262144+(data.charCodeAt(i+1)&63)*4096+(data.charCodeAt(i+2)&63)*64+(data.charCodeAt(i+3)&63);
w -= 65536; ww = 0xD800 + ((w>>>10)&1023); w = 0xDC00 + (w&1023);
}
if(ww !== 0) { out[k++] = ww&255; out[k++] = ww>>>8; ww = 0; }
out[k++] = w%256; out[k++] = w>>>8;
}
return out.slice(0,k).toString('ucs2');
};
var corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3";
if(utf8read(corpus) == utf8readb(corpus)) utf8read = utf8readb;
var utf8readc = function utf8readc(data) { return Buffer_from(data, 'binary').toString('utf8'); };
if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
utf8write = function(data) { return Buffer_from(data, 'utf8').toString("binary"); };
}
// matches <foo>...</foo> extracts content
var matchtag = (function() {
var mtcache/*:{[k:string]:RegExp}*/ = ({}/*:any*/);
return function matchtag(f/*:string*/,g/*:?string*/)/*:RegExp*/ {
var t = f+"|"+(g||"");
if(mtcache[t]) return mtcache[t];
return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([\\s\\S]*?)</(?:\\w+:)?'+f+'>',((g||"")/*:any*/)));
};
})();
var htmldecode/*:{(s:string):string}*/ = (function() {
var entities/*:Array<[RegExp, string]>*/ = [
['nbsp', ' '], ['middot', '·'],
['quot', '"'], ['apos', "'"], ['gt', '>'], ['lt', '<'], ['amp', '&']
@ -191,25 +181,30 @@ var htmldecode/*:{(s:string):string}*/ = /*#__PURE__*/(function() {
// Remove new lines and spaces from start of content
.replace(/^[\t\n\r ]+/, "")
// Remove new lines and spaces from end of content
.replace(/(^|[^\t\n\r ])[\t\n\r ]+$/,"$1")
.replace(/[\t\n\r ]+$/,"")
// Added line which removes any white space characters after and before html tags
.replace(/>\s+/g,">").replace(/\b\s+</g,"<")
.replace(/>\s+/g,">").replace(/\s+</g,"<")
// Replace remaining new lines and spaces with space
.replace(/[\t\n\r ]+/g, " ")
// Replace <br> tags with new lines
.replace(/<\s*[bB][rR]\s*\/?>/g,"\n")
// Strip HTML elements
.replace(/<[^<>]*>/g,"");
.replace(/<[^>]*>/g,"");
for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]);
return o;
};
})();
var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^<"'>]*)>([\s\S]*)</;
var vtregex = (function(){ var vt_cache = {};
return function vt_regex(bt) {
if(vt_cache[bt] !== undefined) return vt_cache[bt];
return (vt_cache[bt] = new RegExp("<(?:vt:)?" + bt + ">([\\s\\S]*?)</(?:vt:)?" + bt + ">", 'g') );
};})();
var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^>]*)>([\s\S]*)</;
function parseVector(data/*:string*/, opts)/*:Array<{v:string,t:string}>*/ {
var h = parsexmltag(data);
var matches/*:Array<string>*/ = str_match_xml_ns_g(data, h.baseType)||[];
var matches/*:Array<string>*/ = data.match(vtregex(h.baseType))||[];
var res/*:Array<any>*/ = [];
if(matches.length != h.size) {
if(opts.WTF) throw new Error("unexpected vector length " + matches.length + " != " + h.size);
@ -243,23 +238,7 @@ function write_vt(s, xlsx/*:?boolean*/)/*:string*/ {
throw new Error("Unable to serialize " + s);
}
function xlml_normalize(d)/*:string*/ {
if(has_buf &&/*::typeof Buffer !== "undefined" && d != null && d instanceof Buffer &&*/ Buffer.isBuffer(d)) return d.toString('utf8');
if(typeof d === 'string') return d;
/* duktape */
if(typeof Uint8Array !== 'undefined' && d instanceof Uint8Array) return utf8read(a2s(ab2a(d)));
throw new Error("Bad input format: expected Buffer or string");
}
/* UOS uses CJK in tags, ODS uses invalid XML */
var xlmlregex = /<([\/]?)([^\s?><!\/:"]*:|)([^\s?<>:\/"]+)(?:\s+[^<>=?"'\s]+="[^"]*?")*\s*[\/]?>/mg;
var XMLNS = ({
CORE_PROPS: 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties',
CUST_PROPS: "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties",
EXT_PROPS: "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties",
CT: 'http://schemas.openxmlformats.org/package/2006/content-types',
RELS: 'http://schemas.openxmlformats.org/package/2006/relationships',
TCMNT: 'http://schemas.microsoft.com/office/spreadsheetml/2018/threadedcomments',
'dc': 'http://purl.org/dc/elements/1.1/',
'dcterms': 'http://purl.org/dc/terms/',
'dcmitype': 'http://purl.org/dc/dcmitype/',
@ -271,7 +250,7 @@ var XMLNS = ({
'xsd': 'http://www.w3.org/2001/XMLSchema'
}/*:any*/);
var XMLNS_main = [
XMLNS.main = [
'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
'http://purl.oclc.org/ooxml/spreadsheetml/main',
'http://schemas.microsoft.com/office/excel/2006/main',

@ -25,59 +25,53 @@ function write_double_le(b/*:RawBytes|CFBlob*/, v/*:number*/, idx/*:number*/) {
b[idx + 7] = (e >> 4) | bs;
}
var ___toBuffer = function(bufs/*:Array<Array<RawBytes> >*/)/*:RawBytes*/ { var x=[],w=10240; for(var i=0;i<bufs[0].length;++i) if(bufs[0][i]) for(var j=0,L=bufs[0][i].length;j<L;j+=w) x.push.apply(x, bufs[0][i].slice(j,j+w)); return x; };
var __toBuffer = has_buf ? function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0].map(function(x) { return Buffer.isBuffer(x) ? x : Buffer_from(x); })) : ___toBuffer(bufs);} : ___toBuffer;
var ___utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join("").replace(chr0,''); };
var __utf16le = has_buf ? function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/ || !buf_utf16le) return ___utf16le(b,s,e); return b.toString('utf16le',s,e).replace(chr0,'')/*.replace(chr1,'!')*/; } : ___utf16le;
var ___hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); };
var __hexlify = has_buf ? function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { return Buffer.isBuffer(b)/*:: && b instanceof Buffer*/ ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); } : ___hexlify;
var ___utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
var __utf8 = has_buf ? function utf8_b(b/*:RawBytes|CFBlob*/, s/*:number*/, e/*:number*/) { return (Buffer.isBuffer(b)/*:: && (b instanceof Buffer)*/) ? b.toString('utf8',s,e) : ___utf8(b,s,e); } : ___utf8;
var ___lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var __lpstr = ___lpstr;
var ___cpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var __cpstr = ___cpstr;
var ___lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var __lpwstr = ___lpwstr;
var ___lpp4 = function lpp4_(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
var __lpp4 = ___lpp4;
var ___8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
var __8lpp4 = ___8lpp4;
var ___double = function(b/*:RawBytes|CFBlob*/, idx/*:number*/) { return read_double_le(b, idx);};
var __double = ___double;
var is_buf = function is_buf_a(a) { return Array.isArray(a) || (typeof Uint8Array !== "undefined" && a instanceof Uint8Array); };
var __toBuffer = function(bufs/*:Array<Array<RawBytes> >*/)/*:RawBytes*/ { var x=[],w=10240; for(var i=0;i<bufs[0].length;++i) if(bufs[0][i]) for(var j=0,L=bufs[0][i].length;j<L;j+=w) x.push.apply(x, bufs[0][i].slice(j,j+w)); return x; };
var ___toBuffer = __toBuffer;
var __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join("").replace(chr0,''); };
var ___utf16le = __utf16le;
var __hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); };
var ___hexlify = __hexlify;
var __utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
var ___utf8 = __utf8;
var __lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var ___lpstr = __lpstr;
var __cpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var ___cpstr = __cpstr;
var __lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var ___lpwstr = __lpwstr;
var __lpp4, ___lpp4;
__lpp4 = ___lpp4 = function lpp4_(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
var __8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
var ___8lpp4 = __8lpp4;
var __double, ___double;
__double = ___double = function(b/*:RawBytes|CFBlob*/, idx/*:number*/) { return read_double_le(b, idx);};
var is_buf = function is_buf_a(a) { return Array.isArray(a); };
if(has_buf/*:: && typeof Buffer !== 'undefined'*/) {
__utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___utf16le(b,s,e); return b.toString('utf16le',s,e).replace(chr0,'')/*.replace(chr1,'!')*/; };
__hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { return Buffer.isBuffer(b)/*:: && b instanceof Buffer*/ ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
__lpstr = function lpstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
__cpstr = function cpstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___cpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
__lpwstr = function lpwstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/ || !buf_utf16le) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
__lpp4 = function lpp4_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/ || !buf_utf16le) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);};
__lpwstr = function lpwstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
__lpp4 = function lpp4_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);};
__8lpp4 = function lpp4_8b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);};
__utf8 = function utf8_b(b/*:RawBytes|CFBlob*/, s/*:number*/, e/*:number*/) { return (Buffer.isBuffer(b)/*:: && (b instanceof Buffer)*/) ? b.toString('utf8',s,e) : ___utf8(b,s,e); };
__toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);};
bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); };
__double = function double_(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(Buffer.isBuffer(b)/*::&& b instanceof Buffer*/) return b.readDoubleLE(i); return ___double(b,i); };
is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a) || (typeof Uint8Array !== "undefined" && a instanceof Uint8Array); };
is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); };
}
/* from js-xls */
function cpdoit() {
__utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return $cptable.utils.decode(1200, b.slice(s,e)).replace(chr0, ''); };
__utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return $cptable.utils.decode(65001, b.slice(s,e)); };
__lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(current_ansi, b.slice(i+4, i+4+len-1)) : "";};
__cpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";};
__lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";};
__lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";};
__8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";};
if(typeof cptable !== 'undefined') {
__utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(1200, b.slice(s,e)).replace(chr0, ''); };
__utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(65001, b.slice(s,e)); };
__lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_ansi, b.slice(i+4, i+4+len-1)) : "";};
__cpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";};
__lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";};
__lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";};
__8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";};
}
if(typeof $cptable !== 'undefined') cpdoit();
var __readUInt8 = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx]; };
var __readUInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx+1]*(1<<8))+b[idx]; };
@ -91,7 +85,7 @@ function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
switch(t) {
case 'dbcs':
loc = this.l;
if(has_buf && Buffer.isBuffer(this) && buf_utf16le) o = this.slice(this.l, this.l+2*size).toString("utf16le");
if(has_buf && Buffer.isBuffer(this)) o = this.slice(this.l, this.l+2*size).toString("utf16le");
else for(i = 0; i < size; ++i) { o+=String.fromCharCode(__readUInt16LE(this, loc)); loc+=2; }
size *= 2;
break;
@ -100,7 +94,7 @@ function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
case 'utf16le': size *= 2; o = __utf16le(this, this.l, this.l + size); break;
case 'wstr':
if(typeof $cptable !== 'undefined') o = $cptable.utils.decode(current_codepage, this.slice(this.l, this.l+2*size));
if(typeof cptable !== 'undefined') o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l+2*size));
else return ReadShift.call(this, size, 'dbcs');
size = 2 * size; break;
@ -135,8 +129,8 @@ function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
} o = oo.join(""); size *= 2; break;
case 'cpstr':
if(typeof $cptable !== 'undefined') {
o = $cptable.utils.decode(current_codepage, this.slice(this.l, this.l + size));
if(typeof cptable !== 'undefined') {
o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l + size));
break;
}
/* falls through */
@ -181,29 +175,21 @@ function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/)/*:any*/
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i);
size = 2 * val.length;
} else if(f === 'sbcs' || f == 'cpstr') {
if(typeof $cptable !== 'undefined' && current_ansi == 874) {
} else if(f === 'sbcs') {
if(typeof cptable !== 'undefined' && current_ansi == 874) {
/* TODO: use tables directly, don't encode */
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
for(i = 0; i != val.length; ++i) {
var cpp = $cptable.utils.encode(current_ansi, val.charAt(i));
this[this.l + i] = cpp[0];
var cppayload = cptable.utils.encode(current_ansi, val.charAt(i));
this[this.l + i] = cppayload[0];
}
size = val.length;
} else if(typeof $cptable !== 'undefined' && f == 'cpstr') {
cpp = $cptable.utils.encode(current_codepage, val);
/* replace null bytes with _ when relevant */
if(cpp.length == val.length) for(i = 0; i < val.length; ++i) if(cpp[i] == 0 && val.charCodeAt(i) != 0) cpp[i] = 0x5F;
if(cpp.length == 2 * val.length) for(i = 0; i < val.length; ++i) if(cpp[2*i] == 0 && cpp[2*i+1] == 0 && val.charCodeAt(i) != 0) cpp[2*i] = 0x5F;
for(i = 0; i < cpp.length; ++i) this[this.l + i] = cpp[i];
size = cpp.length;
} else {
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
val = val.replace(/[^\x00-\x7F]/g, "_");
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
for(i = 0; i != val.length; ++i) this[this.l + i] = (val.charCodeAt(i) & 0xFF);
size = val.length;
}
size = val.length;
} else if(f === 'hex') {
for(; i < t; ++i) {
/*:: if(typeof val !== "string") throw new Error("unreachable"); */

@ -12,16 +12,15 @@ function recordhopper(data, cb/*:RecordHopperCB*/, opts/*:?any*/) {
length = tmpbyte & 0x7F;
for(cntbyte = 1; cntbyte <4 && (tmpbyte & 0x80); ++cntbyte) length += ((tmpbyte = data.read_shift(1)) & 0x7F)<<(7*cntbyte);
tgt = data.l + length;
var d = R.f && R.f(data, length, opts);
var d = (R.f||parsenoop)(data, length, opts);
data.l = tgt;
if(cb(d, R, RT)) return;
if(cb(d, R.n, RT)) return;
}
}
/* control buffer usage for fixed-length buffers */
function buf_array()/*:BufArray*/ {
var bufs/*:Array<Block>*/ = [], blksz = has_buf ? 16384 : 2048;
var has_buf_copy = has_buf && (typeof new_buf(blksz).copy == "function");
var bufs/*:Array<Block>*/ = [], blksz = has_buf ? 256 : 2048;
var newblk = function ba_newblk(sz/*:number*/)/*:Block*/ {
var o/*:Block*/ = (new_buf(sz)/*:any*/);
prep_blob(o, 0);
@ -32,11 +31,8 @@ function buf_array()/*:BufArray*/ {
var endbuf = function ba_endbuf() {
if(!curbuf) return;
// workaround for new Buffer(3).slice(0,0) bug in bun 0.1.3
if(curbuf.l) {
if(curbuf.length > curbuf.l) { curbuf = curbuf.slice(0, curbuf.l); curbuf.l = curbuf.length; }
if(curbuf.length > 0) bufs.push(curbuf);
}
if(curbuf.length > curbuf.l) { curbuf = curbuf.slice(0, curbuf.l); curbuf.l = curbuf.length; }
if(curbuf.length > 0) bufs.push(curbuf);
curbuf = null;
};
@ -48,21 +44,16 @@ function buf_array()/*:BufArray*/ {
var end = function ba_end() {
endbuf();
return bconcat(bufs);
};
var end2 = function() {
endbuf(); return bufs;
return __toBuffer([bufs]);
};
var push = function ba_push(buf) {
endbuf(); curbuf = buf; if(curbuf.l == null) curbuf.l = curbuf.length; next(blksz);
};
var push = function ba_push(buf) { endbuf(); curbuf = buf; if(curbuf.l == null) curbuf.l = curbuf.length; next(blksz); };
return ({ next:next, push:push, end:end, _bufs:bufs, end2:end2 }/*:any*/);
return ({ next:next, push:push, end:end, _bufs:bufs }/*:any*/);
}
function write_record(ba/*:BufArray*/, type/*:number*/, payload, length/*:?number*/) {
var t/*:number*/ = +type, l;
function write_record(ba/*:BufArray*/, type/*:string*/, payload, length/*:?number*/) {
var t/*:number*/ = +XLSBRE[type], l;
if(isNaN(t)) return; // TODO: throw something here?
if(!length) length = XLSBRecordEnum[t].p || (payload||[]).length || 0;
l = 1 + (t >= 0x80 ? 1 : 0) + 1/* + length*/;

@ -1,4 +0,0 @@
if(typeof cptable !== 'undefined') set_cptable(cptable);
else if(typeof module !== "undefined" && typeof require !== 'undefined') {
set_cptable(require('./dist/cpexcel.js'));
}

38
bits/26_crypto.js Normal file

@ -0,0 +1,38 @@
var OFFCRYPTO = {};
var make_offcrypto = function(O, _crypto) {
var crypto;
if(typeof _crypto !== 'undefined') crypto = _crypto;
else if(typeof require !== 'undefined') {
try { crypto = require('crypto'); }
catch(e) { crypto = null; }
}
O.rc4 = function(key, data) {
var S = new Array(256);
var c = 0, i = 0, j = 0, t = 0;
for(i = 0; i != 256; ++i) S[i] = i;
for(i = 0; i != 256; ++i) {
j = (j + S[i] + (key[i%key.length]).charCodeAt(0))&255;
t = S[i]; S[i] = S[j]; S[j] = t;
}
// $FlowIgnore
i = j = 0; var out = new_raw_buf(data.length);
for(c = 0; c != data.length; ++c) {
i = (i + 1)&255;
j = (j + S[i])%256;
t = S[i]; S[i] = S[j]; S[j] = t;
out[c] = (data[c] ^ S[(S[i]+S[j])&255]);
}
return out;
};
O.md5 = function(hex) {
if(!crypto) throw new Error("Unsupported crypto");
return crypto.createHash('md5').update(hex).digest('hex');
};
};
/*:: declare var crypto:any; */
/*global crypto:true */
make_offcrypto(OFFCRYPTO, typeof crypto !== "undefined" ? crypto : undefined);

@ -9,6 +9,7 @@ function fix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^([A-Z])/,"$
function unfix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^\$([A-Z])/,"$1"); }
function split_cell(cstr/*:string*/)/*:Array<string>*/ { return cstr.replace(/(\$?[A-Z]*)(\$?\d*)/,"$1,$2").split(","); }
//function decode_cell(cstr/*:string*/)/*:CellAddress*/ { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; }
function decode_cell(cstr/*:string*/)/*:CellAddress*/ {
var R = 0, C = 0;
for(var i = 0; i < cstr.length; ++i) {
@ -18,6 +19,7 @@ function decode_cell(cstr/*:string*/)/*:CellAddress*/ {
}
return { c: C - 1, r:R - 1 };
}
//function encode_cell(cell/*:CellAddress*/)/*:string*/ { return encode_col(cell.c) + encode_row(cell.r); }
function encode_cell(cell/*:CellAddress*/)/*:string*/ {
var col = cell.c + 1;
var s="";
@ -42,17 +44,6 @@ function encode_range(cs/*:CellAddrSpec|Range*/,ce/*:?CellAddrSpec*/)/*:string*/
/*:: if(typeof ce !== 'string') throw "unreachable"; */
return cs == ce ? cs : cs + ":" + ce;
}
function fix_range(a1/*:string*/)/*:string*/ {
var s = decode_range(a1);
return "$" + encode_col(s.s.c) + "$" + encode_row(s.s.r) + ":$" + encode_col(s.e.c) + "$" + encode_row(s.e.r);
}
// List of invalid characters needs to be tested further
function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ {
if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name");
if (/[^\w\u4E00-\u9FFF\u3040-\u30FF]/.test(sname)) return "'" + sname.replace(/'/g, "''") + "'";
return sname;
}
function safe_decode_range(range/*:string*/)/*:Range*/ {
var o = {s:{c:0,r:0},e:{c:0,r:0}};
@ -70,8 +61,7 @@ function safe_decode_range(range/*:string*/)/*:Range*/ {
}
o.s.r = --idx;
if(i === len || cc != 10) { o.e.c=o.s.c; o.e.r=o.s.r; return o; }
++i;
if(i === len || range.charCodeAt(++i) === 58) { o.e.c=o.s.c; o.e.r=o.s.r; return o; }
for(idx = 0; i != len; ++i) {
if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
@ -89,15 +79,14 @@ function safe_decode_range(range/*:string*/)/*:Range*/ {
function safe_format_cell(cell/*:Cell*/, v/*:any*/) {
var q = (cell.t == 'd' && v instanceof Date);
if(cell.z != null) try { return (cell.w = SSF_format(cell.z, q ? datenum(v) : v)); } catch(e) { }
try { return (cell.w = SSF_format((cell.XF||{}).numFmtId||(q ? 14 : 0), q ? datenum(v) : v)); } catch(e) { return ''+v; }
if(cell.z != null) try { return (cell.w = SSF.format(cell.z, q ? datenum(v) : v)); } catch(e) { }
try { return (cell.w = SSF.format((cell.XF||{}).numFmtId||(q ? 14 : 0), q ? datenum(v) : v)); } catch(e) { return ''+v; }
}
function format_cell(cell/*:Cell*/, v/*:any*/, o/*:any*/) {
if(cell == null || cell.t == null || cell.t == 'z') return "";
if(cell.w !== undefined) return cell.w;
if(cell.t == 'd' && !cell.z && o && o.dateNF) cell.z = o.dateNF;
if(cell.t == "e") return BErr[cell.v] || cell.v;
if(v == undefined) return safe_format_cell(cell, cell.v);
return safe_format_cell(cell, v);
}
@ -108,19 +97,11 @@ function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ {
return { SheetNames: [n], Sheets: sheets };
}
function sheet_new(opts) {
var out = {};
var o = opts || {};
if(o.dense) out["!data"] = [];
return out;
}
function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
var o = opts || {};
var dense = _ws ? (_ws["!data"] != null) : o.dense;
var dense = _ws ? Array.isArray(_ws) : o.dense;
if(DENSE != null && dense == null) dense = DENSE;
var ws/*:Worksheet*/ = _ws || (dense ? ({"!data": []}) : ({}/*:any*/));
if(dense && !ws["!data"]) ws["!data"] = [];
var ws/*:Worksheet*/ = _ws || (dense ? ([]/*:any*/) : ({}/*:any*/));
var _R = 0, _C = 0;
if(ws && o.origin != null) {
if(typeof o.origin == 'number') _R = o.origin;
@ -128,71 +109,54 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
_R = _origin.r; _C = _origin.c;
}
if(!ws["!ref"]) ws["!ref"] = "A1:A1";
}
var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/);
if(ws["!ref"]){
if(ws['!ref']) {
var _range = safe_decode_range(ws['!ref']);
range.s.c = _range.s.c;
range.s.r = _range.s.r;
range.e.c = Math.max(range.e.c, _range.e.c);
range.e.r = Math.max(range.e.r, _range.e.r);
if(_R == -1) range.e.r = _R = (ws["!ref"] ? _range.e.r + 1 : 0);
} else {
range.s.c = range.e.c = range.s.r = range.e.r = 0;
if(_R == -1) range.e.r = _R = _range.e.r + 1;
}
var row = [], seen = false;
for(var R = 0; R != data.length; ++R) {
if(!data[R]) continue;
if(!Array.isArray(data[R])) throw new Error("aoa_to_sheet expects an array of arrays");
var __R = _R + R;
if(dense) {
if(!ws["!data"][__R]) ws["!data"][__R] = [];
row = ws["!data"][__R];
}
var data_R = data[R];
for(var C = 0; C != data_R.length; ++C) {
if(typeof data_R[C] === 'undefined') continue;
var cell/*:Cell*/ = ({v: data_R[C], t:"" }/*:any*/);
var __C = _C + C;
for(var C = 0; C != data[R].length; ++C) {
if(typeof data[R][C] === 'undefined') continue;
var cell/*:Cell*/ = ({v: data[R][C] }/*:any*/);
var __R = _R + R, __C = _C + C;
if(range.s.r > __R) range.s.r = __R;
if(range.s.c > __C) range.s.c = __C;
if(range.e.r < __R) range.e.r = __R;
if(range.e.c < __C) range.e.c = __C;
seen = true;
if(data_R[C] && typeof data_R[C] === 'object' && !Array.isArray(data_R[C]) && !(data_R[C] instanceof Date)) cell = data_R[C];
if(data[R][C] && typeof data[R][C] === 'object' && !Array.isArray(data[R][C]) && !(data[R][C] instanceof Date)) cell = data[R][C];
else {
if(Array.isArray(cell.v)) { cell.f = data_R[C][1]; cell.v = cell.v[0]; }
if(cell.v === null) {
if(cell.f) cell.t = 'n';
else if(o.nullError) { cell.t = 'e'; cell.v = 0; }
else if(!o.sheetStubs) continue;
else cell.t = 'z';
}
else if(typeof cell.v === 'number') {
if(isFinite(cell.v)) cell.t = 'n';
else if(isNaN(cell.v)) { cell.t = 'e'; cell.v = 0x0F; /* #VALUE! */ }
else { cell.t = 'e'; cell.v = 0x07; /*# DIV/0 */ }
}
if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.sheetStubs) continue; else cell.t = 'z'; }
else if(typeof cell.v === 'number') cell.t = 'n';
else if(typeof cell.v === 'boolean') cell.t = 'b';
else if(cell.v instanceof Date) {
cell.z = o.dateNF || table_fmt[14];
if(!o.UTC) cell.v = local_to_utc(cell.v);
if(o.cellDates) { cell.t = 'd'; cell.w = SSF_format(cell.z, datenum(cell.v, o.date1904)); }
else { cell.t = 'n'; cell.v = datenum(cell.v, o.date1904); cell.w = SSF_format(cell.z, cell.v); }
cell.z = o.dateNF || SSF._table[14];
if(o.cellDates) { cell.t = 'd'; cell.w = SSF.format(cell.z, datenum(cell.v)); }
else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); }
}
else cell.t = 's';
}
if(dense) {
if(row[__C] && row[__C].z) cell.z = row[__C].z;
row[__C] = cell;
if(!ws[__R]) ws[__R] = [];
if(ws[__R][__C] && ws[__R][__C].z) cell.z = ws[__R][__C].z;
ws[__R][__C] = cell;
} else {
var cell_ref = encode_col(__C) + (__R + 1)/*:any*/;
var cell_ref = encode_cell(({c:__C,r:__R}/*:any*/));
if(ws[cell_ref] && ws[cell_ref].z) cell.z = ws[cell_ref].z;
ws[cell_ref] = cell;
}
}
}
if(seen && range.s.c < 10400000) ws['!ref'] = encode_range(range);
if(range.s.c < 10000000) ws['!ref'] = encode_range(range);
return ws;
}
function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { return sheet_add_aoa(null, data, opts); }

@ -1,6 +1,3 @@
function parse_Int32LE(data) {
return data.read_shift(4, 'i');
}
function write_UInt32LE(x/*:number*/, o) {
if (!o) o = new_buf(4);
o.write_shift(4, x);
@ -91,19 +88,6 @@ function write_XLSBCell(cell/*:any*/, o/*:?Block*/) {
return o;
}
/* Short XLSB Cell does not include column */
function parse_XLSBShortCell(data)/*:any*/ {
var iStyleRef = data.read_shift(2);
iStyleRef += data.read_shift(1) <<16;
data.l++; //var fPhShow = data.read_shift(1);
return { c:-1, iStyleRef: iStyleRef };
}
function write_XLSBShortCell(cell/*:any*/, o/*:?Block*/) {
if(o == null) o = new_buf(4);
o.write_shift(3, cell.iStyleRef || cell.s);
o.write_shift(1, 0); /* fPhShow */
return o;
}
/* [MS-XLSB] 2.5.21 */
var parse_XLSBCodeName = parse_XLWideString;
@ -135,7 +119,8 @@ function parse_RkNumber(data)/*:number*/ {
var b = data.slice(data.l, data.l + 4);
var fX100 = (b[0] & 1), fInt = (b[0] & 2);
data.l += 4;
var RK = fInt === 0 ? __double([0, 0, 0, 0, (b[0] & 0xFC), b[1], b[2], b[3]], 0) : __readInt32LE(b, 0) >> 2;
b[0] &= 0xFC; // b[0] &= ~3;
var RK = fInt === 0 ? __double([0, 0, 0, 0, b[0], b[1], b[2], b[3]], 0) : __readInt32LE(b, 0) >> 2;
return fX100 ? (RK / 100) : RK;
}
function write_RkNumber(data/*:number*/, o) {

@ -1,5 +1,4 @@
/* [MS-OLEPS] 2.2 PropertyType */
// Note: some tree shakers cannot handle VT_VECTOR | $CONST, hence extra vars
//var VT_EMPTY = 0x0000;
//var VT_NULL = 0x0001;
var VT_I2 = 0x0002;
@ -21,7 +20,7 @@ var VT_UI4 = 0x0013;
//var VT_UI8 = 0x0015;
//var VT_INT = 0x0016;
//var VT_UINT = 0x0017;
//var VT_LPSTR = 0x001E;
var VT_LPSTR = 0x001E;
//var VT_LPWSTR = 0x001F;
var VT_FILETIME = 0x0040;
var VT_BLOB = 0x0041;
@ -33,9 +32,7 @@ var VT_BLOB = 0x0041;
var VT_CF = 0x0047;
//var VT_CLSID = 0x0048;
//var VT_VERSIONED_STREAM = 0x0049;
//var VT_VECTOR = 0x1000;
var VT_VECTOR_VARIANT = 0x100C;
var VT_VECTOR_LPSTR = 0x101E;
var VT_VECTOR = 0x1000;
//var VT_ARRAY = 0x2000;
var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
@ -44,118 +41,125 @@ var VT_CUSTOM = [VT_STRING, VT_USTR];
/* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */
var DocSummaryPIDDSI = {
0x01: { n: 'CodePage', t: VT_I2 },
0x02: { n: 'Category', t: VT_STRING },
0x03: { n: 'PresentationFormat', t: VT_STRING },
0x04: { n: 'ByteCount', t: VT_I4 },
0x05: { n: 'LineCount', t: VT_I4 },
0x06: { n: 'ParagraphCount', t: VT_I4 },
0x07: { n: 'SlideCount', t: VT_I4 },
0x08: { n: 'NoteCount', t: VT_I4 },
0x09: { n: 'HiddenCount', t: VT_I4 },
0x0a: { n: 'MultimediaClipCount', t: VT_I4 },
0x0b: { n: 'ScaleCrop', t: VT_BOOL },
0x0c: { n: 'HeadingPairs', t: VT_VECTOR_VARIANT /* VT_VECTOR | VT_VARIANT */ },
0x0d: { n: 'TitlesOfParts', t: VT_VECTOR_LPSTR /* VT_VECTOR | VT_LPSTR */ },
0x0e: { n: 'Manager', t: VT_STRING },
0x0f: { n: 'Company', t: VT_STRING },
0x10: { n: 'LinksUpToDate', t: VT_BOOL },
0x11: { n: 'CharacterCount', t: VT_I4 },
0x13: { n: 'SharedDoc', t: VT_BOOL },
0x16: { n: 'HyperlinksChanged', t: VT_BOOL },
0x17: { n: 'AppVersion', t: VT_I4, p: 'version' },
0x18: { n: 'DigSig', t: VT_BLOB },
0x1A: { n: 'ContentType', t: VT_STRING },
0x1B: { n: 'ContentStatus', t: VT_STRING },
0x1C: { n: 'Language', t: VT_STRING },
0x1D: { n: 'Version', t: VT_STRING },
0xFF: {},
/* [MS-OLEPS] 2.18 */
0x80000000: { n: 'Locale', t: VT_UI4 },
0x80000003: { n: 'Behavior', t: VT_UI4 },
0x72627262: {}
/*::[*/0x01/*::]*/: { n: 'CodePage', t: VT_I2 },
/*::[*/0x02/*::]*/: { n: 'Category', t: VT_STRING },
/*::[*/0x03/*::]*/: { n: 'PresentationFormat', t: VT_STRING },
/*::[*/0x04/*::]*/: { n: 'ByteCount', t: VT_I4 },
/*::[*/0x05/*::]*/: { n: 'LineCount', t: VT_I4 },
/*::[*/0x06/*::]*/: { n: 'ParagraphCount', t: VT_I4 },
/*::[*/0x07/*::]*/: { n: 'SlideCount', t: VT_I4 },
/*::[*/0x08/*::]*/: { n: 'NoteCount', t: VT_I4 },
/*::[*/0x09/*::]*/: { n: 'HiddenCount', t: VT_I4 },
/*::[*/0x0a/*::]*/: { n: 'MultimediaClipCount', t: VT_I4 },
/*::[*/0x0b/*::]*/: { n: 'ScaleCrop', t: VT_BOOL },
/*::[*/0x0c/*::]*/: { n: 'HeadingPairs', t: VT_VECTOR | VT_VARIANT },
/*::[*/0x0d/*::]*/: { n: 'TitlesOfParts', t: VT_VECTOR | VT_LPSTR },
/*::[*/0x0e/*::]*/: { n: 'Manager', t: VT_STRING },
/*::[*/0x0f/*::]*/: { n: 'Company', t: VT_STRING },
/*::[*/0x10/*::]*/: { n: 'LinksUpToDate', t: VT_BOOL },
/*::[*/0x11/*::]*/: { n: 'CharacterCount', t: VT_I4 },
/*::[*/0x13/*::]*/: { n: 'SharedDoc', t: VT_BOOL },
/*::[*/0x16/*::]*/: { n: 'HyperlinksChanged', t: VT_BOOL },
/*::[*/0x17/*::]*/: { n: 'AppVersion', t: VT_I4, p: 'version' },
/*::[*/0x18/*::]*/: { n: 'DigSig', t: VT_BLOB },
/*::[*/0x1A/*::]*/: { n: 'ContentType', t: VT_STRING },
/*::[*/0x1B/*::]*/: { n: 'ContentStatus', t: VT_STRING },
/*::[*/0x1C/*::]*/: { n: 'Language', t: VT_STRING },
/*::[*/0x1D/*::]*/: { n: 'Version', t: VT_STRING },
/*::[*/0xFF/*::]*/: {}
};
/* [MS-OSHARED] 2.3.3.2.1.1 Summary Information Property Set PIDSI */
var SummaryPIDSI = {
0x01: { n: 'CodePage', t: VT_I2 },
0x02: { n: 'Title', t: VT_STRING },
0x03: { n: 'Subject', t: VT_STRING },
0x04: { n: 'Author', t: VT_STRING },
0x05: { n: 'Keywords', t: VT_STRING },
0x06: { n: 'Comments', t: VT_STRING },
0x07: { n: 'Template', t: VT_STRING },
0x08: { n: 'LastAuthor', t: VT_STRING },
0x09: { n: 'RevNumber', t: VT_STRING },
0x0A: { n: 'EditTime', t: VT_FILETIME },
0x0B: { n: 'LastPrinted', t: VT_FILETIME },
0x0C: { n: 'CreatedDate', t: VT_FILETIME },
0x0D: { n: 'ModifiedDate', t: VT_FILETIME },
0x0E: { n: 'PageCount', t: VT_I4 },
0x0F: { n: 'WordCount', t: VT_I4 },
0x10: { n: 'CharCount', t: VT_I4 },
0x11: { n: 'Thumbnail', t: VT_CF },
0x12: { n: 'Application', t: VT_STRING },
0x13: { n: 'DocSecurity', t: VT_I4 },
0xFF: {},
/* [MS-OLEPS] 2.18 */
0x80000000: { n: 'Locale', t: VT_UI4 },
0x80000003: { n: 'Behavior', t: VT_UI4 },
0x72627262: {}
/*::[*/0x01/*::]*/: { n: 'CodePage', t: VT_I2 },
/*::[*/0x02/*::]*/: { n: 'Title', t: VT_STRING },
/*::[*/0x03/*::]*/: { n: 'Subject', t: VT_STRING },
/*::[*/0x04/*::]*/: { n: 'Author', t: VT_STRING },
/*::[*/0x05/*::]*/: { n: 'Keywords', t: VT_STRING },
/*::[*/0x06/*::]*/: { n: 'Comments', t: VT_STRING },
/*::[*/0x07/*::]*/: { n: 'Template', t: VT_STRING },
/*::[*/0x08/*::]*/: { n: 'LastAuthor', t: VT_STRING },
/*::[*/0x09/*::]*/: { n: 'RevNumber', t: VT_STRING },
/*::[*/0x0A/*::]*/: { n: 'EditTime', t: VT_FILETIME },
/*::[*/0x0B/*::]*/: { n: 'LastPrinted', t: VT_FILETIME },
/*::[*/0x0C/*::]*/: { n: 'CreatedDate', t: VT_FILETIME },
/*::[*/0x0D/*::]*/: { n: 'ModifiedDate', t: VT_FILETIME },
/*::[*/0x0E/*::]*/: { n: 'PageCount', t: VT_I4 },
/*::[*/0x0F/*::]*/: { n: 'WordCount', t: VT_I4 },
/*::[*/0x10/*::]*/: { n: 'CharCount', t: VT_I4 },
/*::[*/0x11/*::]*/: { n: 'Thumbnail', t: VT_CF },
/*::[*/0x12/*::]*/: { n: 'Application', t: VT_STRING },
/*::[*/0x13/*::]*/: { n: 'DocSecurity', t: VT_I4 },
/*::[*/0xFF/*::]*/: {}
};
/* [MS-OLEPS] 2.18 */
var SpecialProperties = {
/*::[*/0x80000000/*::]*/: { n: 'Locale', t: VT_UI4 },
/*::[*/0x80000003/*::]*/: { n: 'Behavior', t: VT_UI4 },
/*::[*/0x72627262/*::]*/: {}
};
(function() {
for(var y in SpecialProperties) if(Object.prototype.hasOwnProperty.call(SpecialProperties, y))
DocSummaryPIDDSI[y] = SummaryPIDSI[y] = SpecialProperties[y];
})();
var DocSummaryRE/*:{[key:string]:string}*/ = evert_key(DocSummaryPIDDSI, "n");
var SummaryRE/*:{[key:string]:string}*/ = evert_key(SummaryPIDSI, "n");
/* [MS-XLS] 2.4.63 Country/Region codes */
var CountryEnum = {
0x0001: "US", // United States
0x0002: "CA", // Canada
0x0003: "", // Latin America (except Brazil)
0x0007: "RU", // Russia
0x0014: "EG", // Egypt
0x001E: "GR", // Greece
0x001F: "NL", // Netherlands
0x0020: "BE", // Belgium
0x0021: "FR", // France
0x0022: "ES", // Spain
0x0024: "HU", // Hungary
0x0027: "IT", // Italy
0x0029: "CH", // Switzerland
0x002B: "AT", // Austria
0x002C: "GB", // United Kingdom
0x002D: "DK", // Denmark
0x002E: "SE", // Sweden
0x002F: "NO", // Norway
0x0030: "PL", // Poland
0x0031: "DE", // Germany
0x0034: "MX", // Mexico
0x0037: "BR", // Brazil
0x003d: "AU", // Australia
0x0040: "NZ", // New Zealand
0x0042: "TH", // Thailand
0x0051: "JP", // Japan
0x0052: "KR", // Korea
0x0054: "VN", // Viet Nam
0x0056: "CN", // China
0x005A: "TR", // Turkey
0x0069: "JS", // Ramastan
0x00D5: "DZ", // Algeria
0x00D8: "MA", // Morocco
0x00DA: "LY", // Libya
0x015F: "PT", // Portugal
0x0162: "IS", // Iceland
0x0166: "FI", // Finland
0x01A4: "CZ", // Czech Republic
0x0376: "TW", // Taiwan
0x03C1: "LB", // Lebanon
0x03C2: "JO", // Jordan
0x03C3: "SY", // Syria
0x03C4: "IQ", // Iraq
0x03C5: "KW", // Kuwait
0x03C6: "SA", // Saudi Arabia
0x03CB: "AE", // United Arab Emirates
0x03CC: "IL", // Israel
0x03CE: "QA", // Qatar
0x03D5: "IR", // Iran
0xFFFF: "US" // United States
/*::[*/0x0001/*::]*/: "US", // United States
/*::[*/0x0002/*::]*/: "CA", // Canada
/*::[*/0x0003/*::]*/: "", // Latin America (except Brazil)
/*::[*/0x0007/*::]*/: "RU", // Russia
/*::[*/0x0014/*::]*/: "EG", // Egypt
/*::[*/0x001E/*::]*/: "GR", // Greece
/*::[*/0x001F/*::]*/: "NL", // Netherlands
/*::[*/0x0020/*::]*/: "BE", // Belgium
/*::[*/0x0021/*::]*/: "FR", // France
/*::[*/0x0022/*::]*/: "ES", // Spain
/*::[*/0x0024/*::]*/: "HU", // Hungary
/*::[*/0x0027/*::]*/: "IT", // Italy
/*::[*/0x0029/*::]*/: "CH", // Switzerland
/*::[*/0x002B/*::]*/: "AT", // Austria
/*::[*/0x002C/*::]*/: "GB", // United Kingdom
/*::[*/0x002D/*::]*/: "DK", // Denmark
/*::[*/0x002E/*::]*/: "SE", // Sweden
/*::[*/0x002F/*::]*/: "NO", // Norway
/*::[*/0x0030/*::]*/: "PL", // Poland
/*::[*/0x0031/*::]*/: "DE", // Germany
/*::[*/0x0034/*::]*/: "MX", // Mexico
/*::[*/0x0037/*::]*/: "BR", // Brazil
/*::[*/0x003d/*::]*/: "AU", // Australia
/*::[*/0x0040/*::]*/: "NZ", // New Zealand
/*::[*/0x0042/*::]*/: "TH", // Thailand
/*::[*/0x0051/*::]*/: "JP", // Japan
/*::[*/0x0052/*::]*/: "KR", // Korea
/*::[*/0x0054/*::]*/: "VN", // Viet Nam
/*::[*/0x0056/*::]*/: "CN", // China
/*::[*/0x005A/*::]*/: "TR", // Turkey
/*::[*/0x0069/*::]*/: "JS", // Ramastan
/*::[*/0x00D5/*::]*/: "DZ", // Algeria
/*::[*/0x00D8/*::]*/: "MA", // Morocco
/*::[*/0x00DA/*::]*/: "LY", // Libya
/*::[*/0x015F/*::]*/: "PT", // Portugal
/*::[*/0x0162/*::]*/: "IS", // Iceland
/*::[*/0x0166/*::]*/: "FI", // Finland
/*::[*/0x01A4/*::]*/: "CZ", // Czech Republic
/*::[*/0x0376/*::]*/: "TW", // Taiwan
/*::[*/0x03C1/*::]*/: "LB", // Lebanon
/*::[*/0x03C2/*::]*/: "JO", // Jordan
/*::[*/0x03C3/*::]*/: "SY", // Syria
/*::[*/0x03C4/*::]*/: "IQ", // Iraq
/*::[*/0x03C5/*::]*/: "KW", // Kuwait
/*::[*/0x03C6/*::]*/: "SA", // Saudi Arabia
/*::[*/0x03CB/*::]*/: "AE", // United Arab Emirates
/*::[*/0x03CC/*::]*/: "IL", // Israel
/*::[*/0x03CE/*::]*/: "QA", // Qatar
/*::[*/0x03D5/*::]*/: "IR", // Iran
/*::[*/0xFFFF/*::]*/: "US" // United States
};
/* [MS-XLS] 2.5.127 */
@ -185,7 +189,7 @@ function rgbify(arr/*:Array<number>*/)/*:Array<[number, number, number]>*/ { ret
/* [MS-XLS] 2.5.161 */
/* [MS-XLSB] 2.5.75 Icv */
var _XLSIcv = /*#__PURE__*/ rgbify([
var _XLSIcv = rgbify([
/* Color Constants */
0x000000,
0xFFFFFF,
@ -258,8 +262,8 @@ var _XLSIcv = /*#__PURE__*/ rgbify([
0x333333,
/* Other entries to appease BIFF8/12 */
0x000000, /* 0x40 icvForeground ?? */
0xFFFFFF, /* 0x41 icvBackground ?? */
0xFFFFFF, /* 0x40 icvForeground ?? */
0x000000, /* 0x41 icvBackground ?? */
0x000000, /* 0x42 icvFrame ?? */
0x000000, /* 0x43 icv3D ?? */
0x000000, /* 0x44 icv3DText ?? */
@ -277,47 +281,18 @@ var _XLSIcv = /*#__PURE__*/ rgbify([
0x000000, /* 0x50 icvInfoBk ?? */
0x000000 /* 0x51 icvInfoText ?? */
]);
var XLSIcv = /*#__PURE__*/dup(_XLSIcv);
var XLSIcv = dup(_XLSIcv);
/* [MS-XLSB] 2.5.97.2 */
var BErr = {
0x00: "#NULL!",
0x07: "#DIV/0!",
0x0F: "#VALUE!",
0x17: "#REF!",
0x1D: "#NAME?",
0x24: "#NUM!",
0x2A: "#N/A",
0x2B: "#GETTING_DATA",
0xFF: "#WTF?"
/*::[*/0x00/*::]*/: "#NULL!",
/*::[*/0x07/*::]*/: "#DIV/0!",
/*::[*/0x0F/*::]*/: "#VALUE!",
/*::[*/0x17/*::]*/: "#REF!",
/*::[*/0x1D/*::]*/: "#NAME?",
/*::[*/0x24/*::]*/: "#NUM!",
/*::[*/0x2A/*::]*/: "#N/A",
/*::[*/0x2B/*::]*/: "#GETTING_DATA",
/*::[*/0xFF/*::]*/: "#WTF?"
};
//var RBErr = evert_num(BErr);
var RBErr = {
"#NULL!": 0x00,
"#DIV/0!": 0x07,
"#VALUE!": 0x0F,
"#REF!": 0x17,
"#NAME?": 0x1D,
"#NUM!": 0x24,
"#N/A": 0x2A,
"#GETTING_DATA": 0x2B,
"#WTF?": 0xFF
};
var XLSLblBuiltIn = [
"_xlnm.Consolidate_Area",
"_xlnm.Auto_Open",
"_xlnm.Auto_Close",
"_xlnm.Extract",
"_xlnm.Database",
"_xlnm.Criteria",
"_xlnm.Print_Area",
"_xlnm.Print_Titles",
"_xlnm.Recorder",
"_xlnm.Data_Form",
"_xlnm.Auto_Activate",
"_xlnm.Auto_Deactivate",
"_xlnm.Sheet_Title",
"_xlnm._FilterDatabase"
];
var RBErr = evert_num(BErr);

@ -5,38 +5,14 @@
var ct2type/*{[string]:string}*/ = ({
/* Workbook */
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": "workbooks",
"application/vnd.ms-excel.sheet.macroEnabled.main+xml": "workbooks",
"application/vnd.ms-excel.sheet.binary.macroEnabled.main": "workbooks",
"application/vnd.ms-excel.addin.macroEnabled.main+xml": "workbooks",
"application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml": "workbooks",
/* Worksheet */
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml": "sheets",
"application/vnd.ms-excel.worksheet": "sheets",
"application/vnd.ms-excel.binIndexWs": "TODO", /* Binary Index */
/* Chartsheet */
"application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml": "charts",
"application/vnd.ms-excel.chartsheet": "charts",
/* Macrosheet */
"application/vnd.ms-excel.macrosheet+xml": "macros",
"application/vnd.ms-excel.macrosheet": "macros",
"application/vnd.ms-excel.intlmacrosheet": "TODO",
"application/vnd.ms-excel.binIndexMs": "TODO", /* Binary Index */
/* Dialogsheet */
"application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml": "dialogs",
"application/vnd.ms-excel.dialogsheet": "dialogs",
/* Shared Strings */
"application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml": "strs",
"application/vnd.ms-excel.sharedStrings": "strs",
/* Styles */
"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml": "styles",
"application/vnd.ms-excel.styles": "styles",
/* File Properties */
"application/vnd.openxmlformats-package.core-properties+xml": "coreprops",
"application/vnd.openxmlformats-officedocument.custom-properties+xml": "custprops",
@ -46,16 +22,6 @@ var ct2type/*{[string]:string}*/ = ({
"application/vnd.openxmlformats-officedocument.customXmlProperties+xml": "TODO",
"application/vnd.openxmlformats-officedocument.spreadsheetml.customProperty": "TODO",
/* Comments */
"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": "comments",
"application/vnd.ms-excel.comments": "comments",
"application/vnd.ms-excel.threadedcomments+xml": "threadedcomments",
"application/vnd.ms-excel.person+xml": "people",
/* Metadata (Stock/Geography and Dynamic Array) */
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml": "metadata",
"application/vnd.ms-excel.sheetMetadata": "metadata",
/* PivotTable */
"application/vnd.ms-excel.pivotTable": "TODO",
"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml": "TODO",
@ -94,6 +60,10 @@ var ct2type/*{[string]:string}*/ = ({
"application/vnd.ms-excel.externalLink": "links",
"application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml": "links",
/* Metadata */
"application/vnd.ms-excel.sheetMetadata": "TODO",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml": "TODO",
/* PivotCache */
"application/vnd.ms-excel.pivotCacheDefinition": "TODO",
"application/vnd.ms-excel.pivotCacheRecords": "TODO",
@ -141,7 +111,7 @@ var ct2type/*{[string]:string}*/ = ({
/* VBA */
"application/vnd.ms-office.vbaProject": "vba",
"application/vnd.ms-office.vbaProjectSignature": "TODO",
"application/vnd.ms-office.vbaProjectSignature": "vba",
/* Volatile Dependencies */
"application/vnd.ms-office.volatileDependencies": "TODO",
@ -176,54 +146,59 @@ var ct2type/*{[string]:string}*/ = ({
"sheet": "js"
}/*:any*/);
var CT_LIST = {
workbooks: {
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
xlsm: "application/vnd.ms-excel.sheet.macroEnabled.main+xml",
xlsb: "application/vnd.ms-excel.sheet.binary.macroEnabled.main",
xlam: "application/vnd.ms-excel.addin.macroEnabled.main+xml",
xltx: "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
},
strs: { /* Shared Strings */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
xlsb: "application/vnd.ms-excel.sharedStrings"
},
comments: { /* Comments */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
xlsb: "application/vnd.ms-excel.comments"
},
sheets: { /* Worksheet */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
xlsb: "application/vnd.ms-excel.worksheet"
},
charts: { /* Chartsheet */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml",
xlsb: "application/vnd.ms-excel.chartsheet"
},
dialogs: { /* Dialogsheet */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml",
xlsb: "application/vnd.ms-excel.dialogsheet"
},
macros: { /* Macrosheet (Excel 4.0 Macros) */
xlsx: "application/vnd.ms-excel.macrosheet+xml",
xlsb: "application/vnd.ms-excel.macrosheet"
},
metadata: { /* Metadata (Stock/Geography and Dynamic Array) */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml",
xlsb: "application/vnd.ms-excel.sheetMetadata"
},
styles: { /* Styles */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
xlsb: "application/vnd.ms-excel.styles"
}
};
var CT_LIST = (function(){
var o = {
workbooks: {
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
xlsm: "application/vnd.ms-excel.sheet.macroEnabled.main+xml",
xlsb: "application/vnd.ms-excel.sheet.binary.macroEnabled.main",
xlam: "application/vnd.ms-excel.addin.macroEnabled.main+xml",
xltx: "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
},
strs: { /* Shared Strings */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
xlsb: "application/vnd.ms-excel.sharedStrings"
},
comments: { /* Comments */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
xlsb: "application/vnd.ms-excel.comments"
},
sheets: { /* Worksheet */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
xlsb: "application/vnd.ms-excel.worksheet"
},
charts: { /* Chartsheet */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml",
xlsb: "application/vnd.ms-excel.chartsheet"
},
dialogs: { /* Dialogsheet */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml",
xlsb: "application/vnd.ms-excel.dialogsheet"
},
macros: { /* Macrosheet (Excel 4.0 Macros) */
xlsx: "application/vnd.ms-excel.macrosheet+xml",
xlsb: "application/vnd.ms-excel.macrosheet"
},
styles: { /* Styles */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
xlsb: "application/vnd.ms-excel.styles"
}
};
keys(o).forEach(function(k) { ["xlsm", "xlam"].forEach(function(v) { if(!o[k][v]) o[k][v] = o[k].xlsx; }); });
keys(o).forEach(function(k){ keys(o[k]).forEach(function(v) { ct2type[o[k][v]] = k; }); });
return o;
})();
var type2ct/*{[string]:Array<string>}*/ = evert_arr(ct2type);
XMLNS.CT = 'http://schemas.openxmlformats.org/package/2006/content-types';
function new_ct()/*:any*/ {
return ({
workbooks:[], sheets:[], charts:[], dialogs:[], macros:[],
rels:[], strs:[], comments:[], threadedcomments:[], links:[],
rels:[], strs:[], comments:[], links:[],
coreprops:[], extprops:[], custprops:[], themes:[], styles:[],
calcchains:[], vba: [], drawings: [], metadata: [], people:[],
calcchains:[], vba: [], drawings: [],
TODO:[], xmlns: "" }/*:any*/);
}
@ -236,7 +211,7 @@ function parse_ct(data/*:?string*/) {
switch(y[0].replace(nsregex,"<")) {
case '<?xml': break;
case '<Types': ct.xmlns = y['xmlns' + (y[0].match(/<(\w+):/)||["",""])[1] ]; break;
case '<Default': ctext[y.Extension.toLowerCase()] = y.ContentType; break;
case '<Default': ctext[y.Extension] = y.ContentType; break;
case '<Override':
if(ct[ct2type[y.ContentType]] !== undefined) ct[ct2type[y.ContentType]].push(y.PartName);
break;
@ -251,37 +226,36 @@ function parse_ct(data/*:?string*/) {
return ct;
}
function write_ct(ct, opts, raw)/*:string*/ {
var type2ct/*{[string]:Array<string>}*/ = evert_arr(ct2type);
var CTYPE_XML_ROOT = writextag('Types', null, {
'xmlns': XMLNS.CT,
'xmlns:xsd': XMLNS.xsd,
'xmlns:xsi': XMLNS.xsi
});
var CTYPE_DEFAULTS = [
['xml', 'application/xml'],
['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
['vml', 'application/vnd.openxmlformats-officedocument.vmlDrawing'],
['data', 'application/vnd.openxmlformats-officedocument.model+data'],
/* from test files */
['bmp', 'image/bmp'],
['png', 'image/png'],
['gif', 'image/gif'],
['emf', 'image/x-emf'],
['wmf', 'image/x-wmf'],
['jpg', 'image/jpeg'], ['jpeg', 'image/jpeg'],
['tif', 'image/tiff'], ['tiff', 'image/tiff'],
['pdf', 'application/pdf'],
['rels', type2ct.rels[0]]
].map(function(x) {
return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
});
function write_ct(ct, opts)/*:string*/ {
var o/*:Array<string>*/ = [], v;
if(!raw) {
o[o.length] = (XML_HEADER);
o[o.length] = writextag('Types', null, {
'xmlns': XMLNS.CT,
'xmlns:xsd': XMLNS.xsd,
'xmlns:xsi': XMLNS.xsi
});
o = o.concat([
['xml', 'application/xml'],
['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
['vml', 'application/vnd.openxmlformats-officedocument.vmlDrawing'],
['data', 'application/vnd.openxmlformats-officedocument.model+data'],
/* from test files */
['bmp', 'image/bmp'],
['png', 'image/png'],
['gif', 'image/gif'],
['emf', 'image/x-emf'],
['wmf', 'image/x-wmf'],
['jpg', 'image/jpeg'], ['jpeg', 'image/jpeg'],
['tif', 'image/tiff'], ['tiff', 'image/tiff'],
['pdf', 'application/pdf'],
['rels', 'application/vnd.openxmlformats-package.relationships+xml']
].map(function(x) {
return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
}));
}
o[o.length] = (XML_HEADER);
o[o.length] = (CTYPE_XML_ROOT);
o = o.concat(CTYPE_DEFAULTS);
/* only write first instance */
var f1 = function(w) {
@ -289,7 +263,7 @@ function write_ct(ct, opts, raw)/*:string*/ {
v = ct[w][0];
o[o.length] = (writextag('Override', null, {
'PartName': (v[0] == '/' ? "":"/") + v,
'ContentType': CT_LIST[w][opts.bookType] || CT_LIST[w]['xlsx']
'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
}));
}
};
@ -299,7 +273,7 @@ function write_ct(ct, opts, raw)/*:string*/ {
(ct[w]||[]).forEach(function(v) {
o[o.length] = (writextag('Override', null, {
'PartName': (v[0] == '/' ? "":"/") + v,
'ContentType': CT_LIST[w][opts.bookType] || CT_LIST[w]['xlsx']
'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
}));
});
};
@ -322,10 +296,7 @@ function write_ct(ct, opts, raw)/*:string*/ {
['coreprops', 'extprops', 'custprops'].forEach(f3);
f3('vba');
f3('comments');
f3('threadedcomments');
f3('drawings');
f2('metadata');
f3('people');
if(!raw && o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
if(o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}

@ -9,28 +9,6 @@ var RELS = ({
XLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLink",
CXML: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml",
CXMLP: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXmlProps",
CMNT: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",
CORE_PROPS: "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
EXT_PROPS: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties',
CUST_PROPS: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties',
SST: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings",
STY: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
THEME: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
CHART: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
CHARTEX: "http://schemas.microsoft.com/office/2014/relationships/chartEx",
CS: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet",
WS: [
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
"http://purl.oclc.org/ooxml/officeDocument/relationships/worksheet"
],
DS: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet",
MS: "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet",
IMG: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
DRAW: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing",
XLMETA: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata",
TCMNT: "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment",
PEOPLE: "http://schemas.microsoft.com/office/2017/10/relationships/person",
CONN: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/connections",
VBA: "http://schemas.microsoft.com/office/2006/relationships/vbaProject"
}/*:any*/);
@ -52,7 +30,7 @@ function parse_rels(data/*:?string*/, currentFilePath/*:string*/) {
var y = parsexmltag(x);
/* 9.3.2.2 OPC_Relationships */
if (y[0] === '<Relationship') {
var rel = {}; rel.Type = y.Type; rel.Target = unescapexml(y.Target); rel.Id = y.Id; if(y.TargetMode) rel.TargetMode = y.TargetMode;
var rel = {}; rel.Type = y.Type; rel.Target = y.Target; rel.Id = y.Id; rel.TargetMode = y.TargetMode;
var canonictarget = y.TargetMode === 'External' ? y.Target : resolve_path(y.Target, currentFilePath);
rels[canonictarget] = rel;
hash[y.Id] = rel;
@ -62,13 +40,16 @@ function parse_rels(data/*:?string*/, currentFilePath/*:string*/) {
return rels;
}
XMLNS.RELS = 'http://schemas.openxmlformats.org/package/2006/relationships';
var RELS_ROOT = writextag('Relationships', null, {
//'xmlns:ns0': XMLNS.RELS,
'xmlns': XMLNS.RELS
});
/* TODO */
function write_rels(rels)/*:string*/ {
var o = [XML_HEADER, writextag('Relationships', null, {
//'xmlns:ns0': XMLNS.RELS,
'xmlns': XMLNS.RELS
})];
var o = [XML_HEADER, RELS_ROOT];
keys(rels['!id']).forEach(function(rid) {
o[o.length] = (writextag('Relationship', null, rels['!id'][rid]));
});
@ -76,17 +57,16 @@ function write_rels(rels)/*:string*/ {
return o.join("");
}
var RELS_EXTERN = [RELS.HLINK, RELS.XPATH, RELS.XMISS];
function add_rels(rels, rId/*:number*/, f, type, relobj, targetmode/*:?string*/)/*:number*/ {
if(!relobj) relobj = {};
if(!rels['!id']) rels['!id'] = {};
if(!rels['!idx']) rels['!idx'] = 1;
if(rId < 0) for(rId = rels['!idx']; rels['!id']['rId' + rId]; ++rId){/* empty */}
rels['!idx'] = rId + 1;
if(rId < 0) for(rId = 1; rels['!id']['rId' + rId]; ++rId){/* empty */}
relobj.Id = 'rId' + rId;
relobj.Type = type;
relobj.Target = f;
if(targetmode) relobj.TargetMode = targetmode;
else if([RELS.HLINK, RELS.XPATH, RELS.XMISS].indexOf(relobj.Type) > -1) relobj.TargetMode = "External";
else if(RELS_EXTERN.indexOf(relobj.Type) > -1) relobj.TargetMode = "External";
if(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId);
rels['!id'][relobj.Id] = relobj;
rels[('/' + relobj.Target).replace("//","/")] = relobj;

@ -1,61 +1,65 @@
/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
/* Part 3 Section 4 Manifest File */
var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
function parse_manifest(d, opts) {
var str = xlml_normalize(d);
var Rn;
var FEtag;
while (Rn = xlmlregex.exec(str))
switch (Rn[3]) {
case "manifest":
break;
case "file-entry":
FEtag = parsexmltag(Rn[0], false);
if (FEtag.path == "/" && FEtag.type !== CT_ODS)
throw new Error("This OpenDocument is not a spreadsheet");
break;
case "encryption-data":
case "algorithm":
case "start-key-generation":
case "key-derivation":
throw new Error("Unsupported ODS Encryption");
default:
if (opts && opts.WTF)
throw Rn;
}
var str = xlml_normalize(d);
var Rn;
var FEtag;
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
case 'manifest': break; // 4.2 <manifest:manifest>
case 'file-entry': // 4.3 <manifest:file-entry>
FEtag = parsexmltag(Rn[0], false);
if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet");
break;
case 'encryption-data': // 4.4 <manifest:encryption-data>
case 'algorithm': // 4.5 <manifest:algorithm>
case 'start-key-generation': // 4.6 <manifest:start-key-generation>
case 'key-derivation': // 4.7 <manifest:key-derivation>
throw new Error("Unsupported ODS Encryption");
default: if(opts && opts.WTF) throw Rn;
}
}
function write_manifest(manifest) {
var o = [XML_HEADER];
o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
for (var i = 0; i < manifest.length; ++i)
o.push(' <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
o.push("</manifest:manifest>");
return o.join("");
function write_manifest(manifest/*:Array<Array<string> >*/)/*:string*/ {
var o = [XML_HEADER];
o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
for(var i = 0; i < manifest.length; ++i) o.push(' <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
o.push('</manifest:manifest>');
return o.join("");
}
function write_rdf_type(file, res, tag) {
return [
' <rdf:Description rdf:about="' + file + '">\n',
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + "#" + res + '"/>\n',
" </rdf:Description>\n"
].join("");
/* Part 3 Section 6 Metadata Manifest File */
function write_rdf_type(file/*:string*/, res/*:string*/, tag/*:?string*/) {
return [
' <rdf:Description rdf:about="' + file + '">\n',
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
' </rdf:Description>\n'
].join("");
}
function write_rdf_has(base, file) {
return [
' <rdf:Description rdf:about="' + base + '">\n',
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
" </rdf:Description>\n"
].join("");
function write_rdf_has(base/*:string*/, file/*:string*/) {
return [
' <rdf:Description rdf:about="' + base + '">\n',
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
' </rdf:Description>\n'
].join("");
}
function write_rdf(rdf) {
var o = [XML_HEADER];
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
for (var i = 0; i != rdf.length; ++i) {
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
o.push(write_rdf_has("", rdf[i][0]));
}
o.push(write_rdf_type("", "Document", "pkg"));
o.push("</rdf:RDF>");
return o.join("");
}
function write_meta_ods(wb, opts) {
return '<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>SheetJS ' + XLSX.version + "</meta:generator></office:meta></office:document-meta>";
var o = [XML_HEADER];
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
for(var i = 0; i != rdf.length; ++i) {
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
o.push(write_rdf_has("",rdf[i][0]));
}
o.push(write_rdf_type("","Document", "pkg"));
o.push('</rdf:RDF>');
return o.join("");
}
/* TODO: pull properties */
var write_meta_ods/*:{(wb:Workbook, opts:any):string}*/ = (function() {
var payload = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
return function wmo(/*:: wb: Workbook, opts: any*/)/*:string*/ {
return payload;
};
})();

@ -18,12 +18,25 @@ var CORE_PROPS/*:Array<Array<string> >*/ = [
["dcterms:modified", "ModifiedDate", 'date']
];
XMLNS.CORE_PROPS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
RELS.CORE_PROPS = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';
var CORE_PROPS_REGEX/*:Array<RegExp>*/ = (function() {
var r = new Array(CORE_PROPS.length);
for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i];
var g = "(?:"+ f[0].slice(0,f[0].indexOf(":")) +":)"+ f[0].slice(f[0].indexOf(":")+1);
r[i] = new RegExp("<" + g + "[^>]*>([\\s\\S]*?)<\/" + g + ">");
}
return r;
})();
function parse_core_props(data) {
var p = {};
data = utf8read(data);
for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i], cur = str_match_xml(data, f[0]);
var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
if(cur != null && cur.length > 0) p[f[1]] = unescapexml(cur[1]);
if(f[2] === 'date' && p[f[1]]) p[f[1]] = parseDate(p[f[1]]);
}
@ -31,6 +44,15 @@ function parse_core_props(data) {
return p;
}
var CORE_PROPS_XML_ROOT = writextag('cp:coreProperties', null, {
//'xmlns': XMLNS.CORE_PROPS,
'xmlns:cp': XMLNS.CORE_PROPS,
'xmlns:dc': XMLNS.dc,
'xmlns:dcterms': XMLNS.dcterms,
'xmlns:dcmitype': XMLNS.dcmitype,
'xmlns:xsi': XMLNS.xsi
});
function cp_doit(f, g, h, o, p) {
if(p[f] != null || g == null || g === "") return;
p[f] = g;
@ -40,14 +62,7 @@ function cp_doit(f, g, h, o, p) {
function write_core_props(cp, _opts) {
var opts = _opts || {};
var o = [XML_HEADER, writextag('cp:coreProperties', null, {
//'xmlns': XMLNS.CORE_PROPS,
'xmlns:cp': XMLNS.CORE_PROPS,
'xmlns:dc': XMLNS.dc,
'xmlns:dcterms': XMLNS.dcterms,
'xmlns:dcmitype': XMLNS.dcmitype,
'xmlns:xsi': XMLNS.xsi
})], p = {};
var o = [XML_HEADER, CORE_PROPS_XML_ROOT], p = {};
if(!cp && !opts.Props) return o.join("");
if(cp) {

@ -14,6 +14,9 @@ var EXT_PROPS/*:Array<Array<string> >*/ = [
["TitlesOfParts", "TitlesOfParts", "raw"]
];
XMLNS.EXT_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
RELS.EXT_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';
var PseudoPropsPairs = [
"Worksheets", "SheetNames",
"NamedRanges", "DefinedNames",
@ -71,12 +74,12 @@ function parse_ext_props(data, p, opts) {
data = utf8read(data);
EXT_PROPS.forEach(function(f) {
var xml = (str_match_xml_ns(data, f[0])||[])[1];
var xml = (data.match(matchtag(f[0]))||[])[1];
switch(f[2]) {
case "string": if(xml) p[f[1]] = unescapexml(xml); break;
case "bool": p[f[1]] = xml === "true"; break;
case "raw":
var cur = str_match_xml(data, f[0]);
var cur = data.match(new RegExp("<" + f[0] + "[^>]*>([\\s\\S]*?)<\/" + f[0] + ">"));
if(cur && cur.length > 0) q[f[1]] = cur[1];
break;
}
@ -87,15 +90,17 @@ function parse_ext_props(data, p, opts) {
return p;
}
var EXT_PROPS_XML_ROOT = writextag('Properties', null, {
'xmlns': XMLNS.EXT_PROPS,
'xmlns:vt': XMLNS.vt
});
function write_ext_props(cp/*::, opts*/)/*:string*/ {
var o/*:Array<string>*/ = [], W = writextag;
if(!cp) cp = {};
cp.Application = "SheetJS";
o[o.length] = (XML_HEADER);
o[o.length] = (writextag('Properties', null, {
'xmlns': XMLNS.EXT_PROPS,
'xmlns:vt': XMLNS.vt
}));
o[o.length] = (EXT_PROPS_XML_ROOT);
EXT_PROPS.forEach(function(f) {
if(cp[f[1]] === undefined) return;

@ -1,11 +1,14 @@
/* 15.2.12.2 Custom File Properties Part */
var custregex = /<[^<>]+>[^<]*/g;
XMLNS.CUST_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
RELS.CUST_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties';
var custregex = /<[^>]+>[^<]*/g;
function parse_cust_props(data/*:string*/, opts) {
var p = {}, name = "";
var m = data.match(custregex);
if(m) for(var i = 0; i != m.length; ++i) {
var x = m[i], y = parsexmltag(x);
switch(strip_ns(y[0])) {
switch(y[0]) {
case '<?xml': break;
case '<Properties': break;
case '<property': name = unescapexml(y.name); break;
@ -44,11 +47,13 @@ function parse_cust_props(data/*:string*/, opts) {
return p;
}
var CUST_PROPS_XML_ROOT = writextag('Properties', null, {
'xmlns': XMLNS.CUST_PROPS,
'xmlns:vt': XMLNS.vt
});
function write_cust_props(cp/*::, opts*/)/*:string*/ {
var o = [XML_HEADER, writextag('Properties', null, {
'xmlns': XMLNS.CUST_PROPS,
'xmlns:vt': XMLNS.vt
})];
var o = [XML_HEADER, CUST_PROPS_XML_ROOT];
if(!cp) return o.join("");
var pid = 1;
keys(cp).forEach(function custprop(k) { ++pid;

@ -31,10 +31,9 @@ var XLMLDocPropsMap = {
Identifier: 'Identifier', /* NOTE: missing from schema */
Language: 'Language' /* NOTE: missing from schema */
};
var evert_XLMLDPM;
var evert_XLMLDPM = evert(XLMLDocPropsMap);
function xlml_set_prop(Props, tag/*:string*/, val) {
if(!evert_XLMLDPM) evert_XLMLDPM = evert(XLMLDocPropsMap);
tag = evert_XLMLDPM[tag] || tag;
Props[tag] = val;
}

@ -41,18 +41,6 @@ function parse_VtStringBase(blob, stringType, pad) {
function parse_VtString(blob, t/*:number*/, pad/*:?boolean*/) { return parse_VtStringBase(blob, t, pad === false ? 0: 4); }
function parse_VtUnalignedString(blob, t/*:number*/) { if(!t) throw new Error("VtUnalignedString must have positive length"); return parse_VtStringBase(blob, t, 0); }
/* [MS-OSHARED] 2.3.3.1.7 VtVecLpwstrValue */
function parse_VtVecLpwstrValue(blob)/*:Array<string>*/ {
var length = blob.read_shift(4);
var ret/*:Array<string>*/ = [];
for(var i = 0; i != length; ++i) {
var start = blob.l;
ret[i] = blob.read_shift(0, 'lpwstr').replace(chr0,'');
if((blob.l - start) & 0x02) blob.l += 2;
}
return ret;
}
/* [MS-OSHARED] 2.3.3.1.9 VtVecUnalignedLpstrValue */
function parse_VtVecUnalignedLpstrValue(blob)/*:Array<string>*/ {
var length = blob.read_shift(4);
@ -61,12 +49,14 @@ function parse_VtVecUnalignedLpstrValue(blob)/*:Array<string>*/ {
return ret;
}
/* [MS-OSHARED] 2.3.3.1.10 VtVecUnalignedLpstr */
function parse_VtVecUnalignedLpstr(blob)/*:Array<string>*/ {
return parse_VtVecUnalignedLpstrValue(blob);
}
/* [MS-OSHARED] 2.3.3.1.13 VtHeadingPair */
function parse_VtHeadingPair(blob) {
var start = blob.l;
var headingString = parse_TypedPropertyValue(blob, VT_USTR);
if(blob[blob.l] == 0x00 && blob[blob.l+1] == 0x00 && ((blob.l - start) & 0x02)) blob.l += 2;
var headerParts = parse_TypedPropertyValue(blob, VT_I4);
return [headingString, headerParts];
}
@ -75,10 +65,16 @@ function parse_VtHeadingPair(blob) {
function parse_VtVecHeadingPairValue(blob) {
var cElements = blob.read_shift(4);
var out = [];
for(var i = 0; i < cElements / 2; ++i) out.push(parse_VtHeadingPair(blob));
for(var i = 0; i != cElements / 2; ++i) out.push(parse_VtHeadingPair(blob));
return out;
}
/* [MS-OSHARED] 2.3.3.1.15 VtVecHeadingPair */
function parse_VtVecHeadingPair(blob) {
// NOTE: When invoked, wType & padding were already consumed
return parse_VtVecHeadingPairValue(blob);
}
/* [MS-OLEPS] 2.18.1 Dictionary (uses 2.17, 2.16) */
function parse_dictionary(blob,CodePage) {
var cnt = blob.read_shift(4);
@ -117,23 +113,21 @@ function parse_TypedPropertyValue(blob, type/*:number*/, _opts)/*:any*/ {
var t = blob.read_shift(2), ret, opts = _opts||{};
blob.l += 2;
if(type !== VT_VARIANT)
if(t !== type && VT_CUSTOM.indexOf(type)===-1 && !((type & 0xFFFE) == 0x101E && (t & 0xFFFE) == 0x101E)) throw new Error('Expected type ' + type + ' saw ' + t);
if(t !== type && VT_CUSTOM.indexOf(type)===-1) throw new Error('Expected type ' + type + ' saw ' + t);
switch(type === VT_VARIANT ? t : type) {
case 0x02 /*VT_I2*/: ret = blob.read_shift(2, 'i'); if(!opts.raw) blob.l += 2; return ret;
case 0x03 /*VT_I4*/: ret = blob.read_shift(4, 'i'); return ret;
case 0x0B /*VT_BOOL*/: return blob.read_shift(4) !== 0x0;
case 0x13 /*VT_UI4*/: ret = blob.read_shift(4); return ret;
case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
case 0x1E /*VT_LPSTR*/: return parse_lpstr(blob, t, 4).replace(chr0,'');
case 0x1F /*VT_LPWSTR*/: return parse_lpwstr(blob);
case 0x40 /*VT_FILETIME*/: return parse_FILETIME(blob);
case 0x41 /*VT_BLOB*/: return parse_BLOB(blob);
case 0x47 /*VT_CF*/: return parse_ClipboardData(blob);
case 0x50 /*VT_STRING*/: return parse_VtString(blob, t, !opts.raw).replace(chr0,'');
case 0x51 /*VT_USTR*/: return parse_VtUnalignedString(blob, t/*, 4*/).replace(chr0,'');
case 0x100C /*VT_VECTOR|VT_VARIANT*/: return parse_VtVecHeadingPairValue(blob);
case 0x101E /*VT_VECTOR|VT_LPSTR*/:
case 0x101F /*VT_VECTOR|VT_LPWSTR*/:
return t == 0x101F ? parse_VtVecLpwstrValue(blob) : parse_VtVecUnalignedLpstrValue(blob);
case 0x100C /*VT_VECTOR|VT_VARIANT*/: return parse_VtVecHeadingPair(blob);
case 0x101E /*VT_LPSTR*/: return parse_VtVecUnalignedLpstr(blob);
default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + t);
}
}
@ -185,7 +179,6 @@ function parse_PropertySet(blob, PIDSI) {
if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i);
}
if(PIDSI) {
if(Props[i][0] == 0 && Props.length > i+1 && Props[i][1] == Props[i+1][1]) continue; // R9
var piddsi = PIDSI[Props[i][0]];
PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true});
if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + ("0000" + String(PropH[piddsi.n] & 0xFFFF)).slice(-4);
@ -233,8 +226,8 @@ function parse_PropertySet(blob, PIDSI) {
/* [MS-OSHARED] 2.3.3.2.3.1.2 + PROPVARIANT */
switch(blob[blob.l]) {
case 0x41 /*VT_BLOB*/: blob.l += 4; val = parse_BLOB(blob); break;
case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break;
case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break;
case 0x03 /*VT_I4*/: blob.l += 4; val = blob.read_shift(4, 'i'); break;
case 0x13 /*VT_UI4*/: blob.l += 4; val = blob.read_shift(4); break;
case 0x05 /*VT_R8*/: blob.l += 4; val = blob.read_shift(8, 'f'); break;
@ -249,7 +242,7 @@ function parse_PropertySet(blob, PIDSI) {
blob.l = start_addr + size; /* step ahead to skip padding */
return PropH;
}
var XLSPSSkip = [ "CodePage", "Thumbnail", "_PID_LINKBASE", "_PID_HLINKS", "SystemIdentifier", "FMTID" ];
var XLSPSSkip = [ "CodePage", "Thumbnail", "_PID_LINKBASE", "_PID_HLINKS", "SystemIdentifier", "FMTID" ].concat(PseudoPropsPairs);
function guess_property_type(val/*:any*/)/*:number*/ {
switch(typeof val) {
case "boolean": return 0x0B;
@ -293,7 +286,7 @@ function write_PropertySet(entries, RE, PIDSI) {
for(i = 0; i < entries.length; ++i) {
if(RE && !RE[entries[i][0]]) continue;
if(XLSPSSkip.indexOf(entries[i][0]) > -1 || PseudoPropsPairs.indexOf(entries[i][0]) > -1) continue;
if(XLSPSSkip.indexOf(entries[i][0]) > -1) continue;
if(entries[i][1] == null) continue;
var val = entries[i][1], idx = 0;
@ -410,7 +403,7 @@ function parse_Bes(blob/*::, length*/) {
}
function write_Bes(v, t/*:string*/, o) {
if(!o) o = new_buf(2);
o.write_shift(1, ((t == 'e') ? +v : +!!v));
o.write_shift(1, +v);
o.write_shift(1, ((t == 'e') ? 1 : 0));
return o;
}
@ -530,17 +523,16 @@ function parse_URLMoniker(blob/*::, length, opts*/) {
/* [MS-OSHARED] 2.3.7.8 FileMoniker TODO: all fields */
function parse_FileMoniker(blob/*::, length*/) {
var cAnti = blob.read_shift(2);
var preamble = ""; while(cAnti-- > 0) preamble += "../";
blob.l += 2; //var cAnti = blob.read_shift(2);
var ansiPath = blob.read_shift(0, 'lpstr-ansi');
blob.l += 2; //var endServer = blob.read_shift(2);
if(blob.read_shift(2) != 0xDEAD) throw new Error("Bad FileMoniker");
var sz = blob.read_shift(4);
if(sz === 0) return preamble + ansiPath.replace(/\\/g,"/");
if(sz === 0) return ansiPath.replace(/\\/g,"/");
var bytes = blob.read_shift(4);
if(blob.read_shift(2) != 3) throw new Error("Bad FileMoniker");
var unicodePath = blob.read_shift(bytes>>1, 'utf16le').replace(chr0,"");
return preamble + unicodePath;
return unicodePath;
}
/* [MS-OSHARED] 2.3.7.2 HyperlinkMoniker TODO: all the monikers */
@ -559,13 +551,6 @@ function parse_HyperlinkString(blob/*::, length*/) {
var o = len > 0 ? blob.read_shift(len, 'utf16le').replace(chr0, "") : "";
return o;
}
function write_HyperlinkString(str/*:string*/, o) {
if(!o) o = new_buf(6 + str.length * 2);
o.write_shift(4, 1 + str.length);
for(var i = 0; i < str.length; ++i) o.write_shift(2, str.charCodeAt(i));
o.write_shift(2, 0);
return o;
}
/* [MS-OSHARED] 2.3.7.1 Hyperlink Object */
function parse_Hyperlink(blob, length)/*:Hyperlink*/ {
@ -586,7 +571,6 @@ function parse_Hyperlink(blob, length)/*:Hyperlink*/ {
var target = targetFrameName||moniker||oleMoniker||"";
if(target && Loc) target+="#"+Loc;
if(!target) target = "#" + Loc;
if((flags & 0x0002) && target.charAt(0) == "/" && target.charAt(1) != "/") target = "file://" + target;
var out = ({Target:target}/*:any*/);
if(guid) out.guid = guid;
if(fileTime) out.time = fileTime;
@ -596,31 +580,29 @@ function parse_Hyperlink(blob, length)/*:Hyperlink*/ {
function write_Hyperlink(hl) {
var out = new_buf(512), i = 0;
var Target = hl.Target;
if(Target.slice(0,7) == "file://") Target = Target.slice(7);
var hashidx = Target.indexOf("#");
var F = hashidx > -1 ? 0x1f : 0x17;
var F = Target.indexOf("#") > -1 ? 0x1f : 0x17;
switch(Target.charAt(0)) { case "#": F=0x1c; break; case ".": F&=~2; break; }
out.write_shift(4,2); out.write_shift(4, F);
var data = [8,6815827,6619237,4849780,83]; for(i = 0; i < data.length; ++i) out.write_shift(4, data[i]);
if(F == 0x1C) {
Target = Target.slice(1);
write_HyperlinkString(Target, out);
out.write_shift(4, Target.length + 1);
for(i = 0; i < Target.length; ++i) out.write_shift(2, Target.charCodeAt(i));
out.write_shift(2, 0);
} else if(F & 0x02) {
data = "e0 c9 ea 79 f9 ba ce 11 8c 82 00 aa 00 4b a9 0b".split(" ");
for(i = 0; i < data.length; ++i) out.write_shift(1, parseInt(data[i], 16));
var Pretarget = hashidx > -1 ? Target.slice(0, hashidx) : Target;
out.write_shift(4, 2*(Pretarget.length + 1));
for(i = 0; i < Pretarget.length; ++i) out.write_shift(2, Pretarget.charCodeAt(i));
out.write_shift(4, 2*(Target.length + 1));
for(i = 0; i < Target.length; ++i) out.write_shift(2, Target.charCodeAt(i));
out.write_shift(2, 0);
if(F & 0x08) write_HyperlinkString(hashidx > -1 ? Target.slice(hashidx+1): "", out);
} else {
data = "03 03 00 00 00 00 00 00 c0 00 00 00 00 00 00 46".split(" ");
for(i = 0; i < data.length; ++i) out.write_shift(1, parseInt(data[i], 16));
var P = 0;
while(Target.slice(P*3,P*3+3)=="../"||Target.slice(P*3,P*3+3)=="..\\") ++P;
out.write_shift(2, P);
out.write_shift(4, Target.length - 3 * P + 1);
for(i = 0; i < Target.length - 3 * P; ++i) out.write_shift(1, Target.charCodeAt(i + 3 * P) & 0xFF);
out.write_shift(4, Target.length + 1);
for(i = 0; i < Target.length; ++i) out.write_shift(1, Target.charCodeAt(i) & 0xFF);
out.write_shift(1, 0);
out.write_shift(2, 0xFFFF);
out.write_shift(2, 0xDEAD);

@ -1,20 +1,9 @@
/* [MS-XLS] 2.5.19 */
function parse_XLSCell(blob, length, opts)/*:Cell*/ {
function parse_XLSCell(blob/*::, length*/)/*:Cell*/ {
var rw = blob.read_shift(2); // 0-indexed
var col = blob.read_shift(2);
var ret = ({r:rw, c:col, ixfe:0}/*:any*/);
if(opts && opts.biff == 2 || length == 7) {
/* TODO: pass back flags */
var flags = blob.read_shift(1);
ret.ixfe = flags & 0x3F;
blob.l += 2;
/*
var ifntifmt = blob.read_shift(1);
var ifmt = ifntifmt & 0x3f, ifnt = ifntifmt >> 6;
var flags3 = blob.read_shift(1);
*/
} else ret.ixfe = blob.read_shift(2);
return ret;
var ixfe = blob.read_shift(2);
return ({r:rw, c:col, ixfe:ixfe}/*:any*/);
}
function write_XLSCell(R/*:number*/, C/*:number*/, ixfe/*:?number*/, o) {
if(!o) o = new_buf(6);
@ -122,25 +111,25 @@ function parse_FtCf(blob) {
/* [MS-XLS] 2.5.140 - 2.5.154 and friends */
function parse_FtSkip(blob) { blob.l += 2; blob.l += blob.read_shift(2); }
var FtTab = {
0x00: parse_FtSkip, /* FtEnd */
0x04: parse_FtSkip, /* FtMacro */
0x05: parse_FtSkip, /* FtButton */
0x06: parse_FtSkip, /* FtGmo */
0x07: parse_FtCf, /* FtCf */
0x08: parse_FtSkip, /* FtPioGrbit */
0x09: parse_FtSkip, /* FtPictFmla */
0x0A: parse_FtSkip, /* FtCbls */
0x0B: parse_FtSkip, /* FtRbo */
0x0C: parse_FtSkip, /* FtSbs */
0x0D: parse_FtNts, /* FtNts */
0x0E: parse_FtSkip, /* FtSbsFmla */
0x0F: parse_FtSkip, /* FtGboData */
0x10: parse_FtSkip, /* FtEdoData */
0x11: parse_FtSkip, /* FtRboData */
0x12: parse_FtSkip, /* FtCblsData */
0x13: parse_FtSkip, /* FtLbsData */
0x14: parse_FtSkip, /* FtCblsFmla */
0x15: parse_FtCmo
/*::[*/0x00/*::]*/: parse_FtSkip, /* FtEnd */
/*::[*/0x04/*::]*/: parse_FtSkip, /* FtMacro */
/*::[*/0x05/*::]*/: parse_FtSkip, /* FtButton */
/*::[*/0x06/*::]*/: parse_FtSkip, /* FtGmo */
/*::[*/0x07/*::]*/: parse_FtCf, /* FtCf */
/*::[*/0x08/*::]*/: parse_FtSkip, /* FtPioGrbit */
/*::[*/0x09/*::]*/: parse_FtSkip, /* FtPictFmla */
/*::[*/0x0A/*::]*/: parse_FtSkip, /* FtCbls */
/*::[*/0x0B/*::]*/: parse_FtSkip, /* FtRbo */
/*::[*/0x0C/*::]*/: parse_FtSkip, /* FtSbs */
/*::[*/0x0D/*::]*/: parse_FtNts, /* FtNts */
/*::[*/0x0E/*::]*/: parse_FtSkip, /* FtSbsFmla */
/*::[*/0x0F/*::]*/: parse_FtSkip, /* FtGboData */
/*::[*/0x10/*::]*/: parse_FtSkip, /* FtEdoData */
/*::[*/0x11/*::]*/: parse_FtSkip, /* FtRboData */
/*::[*/0x12/*::]*/: parse_FtSkip, /* FtCblsData */
/*::[*/0x13/*::]*/: parse_FtSkip, /* FtLbsData */
/*::[*/0x14/*::]*/: parse_FtSkip, /* FtCblsFmla */
/*::[*/0x15/*::]*/: parse_FtCmo
};
function parse_FtArray(blob, length/*::, ot*/) {
var tgt = blob.l + length;
@ -149,7 +138,7 @@ function parse_FtArray(blob, length/*::, ot*/) {
var ft = blob.read_shift(2);
blob.l-=2;
try {
fts[ft] = FtTab[ft](blob, tgt - blob.l);
fts.push(FtTab[ft](blob, tgt - blob.l));
} catch(e) { blob.l = tgt; return fts; }
}
if(blob.l != tgt) blob.l = tgt; //throw new Error("bad Object Ft-sequence");
@ -234,17 +223,11 @@ function write_WriteAccess(s/*:string*/, opts) {
/* [MS-XLS] 2.4.351 */
function parse_WsBool(blob, length, opts) {
var flags = opts && opts.biff == 8 || length == 2 ? blob.read_shift(2) : (blob.l += length, 0);
return { fDialog: flags & 0x10, fBelow: flags & 0x40, fRight: flags & 0x80 };
return { fDialog: flags & 0x10 };
}
/* [MS-XLS] 2.4.28 */
function parse_BoundSheet8(blob, length, opts) {
var name = "";
if(opts.biff == 4) {
name = parse_ShortXLUnicodeString(blob, 0, opts);
if(name.length === 0) name = "Sheet1";
return { name:name };
}
var pos = blob.read_shift(4);
var hidden = blob.read_shift(1) & 0x03;
var dt = blob.read_shift(1);
@ -254,7 +237,7 @@ function parse_BoundSheet8(blob, length, opts) {
case 2: dt = 'Chartsheet'; break;
case 6: dt = 'VBAModule'; break;
}
name = parse_ShortXLUnicodeString(blob, 0, opts);
var name = parse_ShortXLUnicodeString(blob, 0, opts);
if(name.length === 0) name = "Sheet1";
return { pos:pos, hs:hidden, dt:dt, name:name };
}
@ -425,8 +408,8 @@ function write_Font(data, opts) {
}
/* [MS-XLS] 2.4.149 */
function parse_LabelSst(blob, length, opts) {
var cell = parse_XLSCell(blob, length, opts);
function parse_LabelSst(blob) {
var cell = parse_XLSCell(blob);
cell.isst = blob.read_shift(4);
return cell;
}
@ -439,9 +422,9 @@ function write_LabelSst(R/*:number*/, C/*:number*/, v/*:number*/, os/*:number*/
/* [MS-XLS] 2.4.148 */
function parse_Label(blob, length, opts) {
if(opts.biffguess && opts.biff == 2) opts.biff = 5;
var target = blob.l + length;
var cell = parse_XLSCell(blob, length, opts);
var cell = parse_XLSCell(blob, 6);
if(opts.biff == 2) blob.l++;
var str = parse_XLUnicodeString(blob, target - blob.l, opts);
cell.val = str;
return cell;
@ -475,19 +458,6 @@ function write_Format(i/*:number*/, f/*:string*/, opts, o) {
return out;
}
var parse_BIFF2Format = parse_XLUnicodeString2;
function write_BIFF2Format(f/*:string*/) {
var o = new_buf(1 + f.length);
o.write_shift(1, f.length);
o.write_shift(f.length, f, "sbcs");
return o;
}
function write_BIFF4Format(f/*:string*/) {
var o = new_buf(3 + f.length);
o.l += 2;
o.write_shift(1, f.length);
o.write_shift(f.length, f, "sbcs");
return o;
}
/* [MS-XLS] 2.4.90 */
function parse_Dimensions(blob, length, opts) {
@ -603,52 +573,12 @@ function write_XF(data, ixfeP, opts, o) {
o.write_shift(2, (data.numFmtId||0));
o.write_shift(2, (ixfeP<<4));
}
var f = 0;
if(data.numFmtId > 0 && b5) f |= 0x0400;
o.write_shift(4, f);
o.write_shift(4, 0);
o.write_shift(4, 0);
if(!b5) o.write_shift(4, 0);
o.write_shift(2, 0);
return o;
}
function parse_BIFF2XF(blob/*::, length, opts*/) {
var o = {};
o.ifnt = blob.read_shift(1); blob.l++; o.flags = blob.read_shift(1);
o.numFmtId = o.flags & 0x3F; o.flags>>=6;
o.fStyle = 0;
o.data = {}; // TODO
return o;
}
function write_BIFF2XF(xf) {
var o = new_buf(4);
o.l+=2;
o.write_shift(1, xf.numFmtId);
o.l++;
return o;
}
function write_BIFF3XF(xf) {
var o = new_buf(12);
o.l++;
o.write_shift(1, xf.numFmtId);
o.l += 10;
return o;
}
/* TODO: check other fields */
var write_BIFF4XF = write_BIFF3XF;
function parse_BIFF3XF(blob/*::, length, opts*/) {
var o = {};
o.ifnt = blob.read_shift(1); o.numFmtId = blob.read_shift(1); o.flags = blob.read_shift(2);
o.fStyle = (o.flags >> 2) & 0x01;
o.data = {}; // TODO
return o;
}
function parse_BIFF4XF(blob/*::, length, opts*/) {
var o = {};
o.ifnt = blob.read_shift(1); o.numFmtId = blob.read_shift(1); o.flags = blob.read_shift(2);
o.fStyle = (o.flags >> 2) & 0x01;
o.data = {}; // TODO
return o;
}
/* [MS-XLS] 2.4.134 */
function parse_Guts(blob) {
@ -669,7 +599,8 @@ function write_Guts(guts/*:Array<number>*/) {
/* [MS-XLS] 2.4.24 */
function parse_BoolErr(blob, length, opts) {
var cell = parse_XLSCell(blob, 6, opts);
var cell = parse_XLSCell(blob, 6);
if(opts.biff == 2) ++blob.l;
var val = parse_Bes(blob, 2);
cell.val = val;
cell.t = (val === true || val === false) ? 'b' : 'e';
@ -683,9 +614,8 @@ function write_BoolErr(R/*:number*/, C/*:number*/, v, os/*:number*/, opts, t/*:s
}
/* [MS-XLS] 2.4.180 Number */
function parse_Number(blob, length, opts) {
if(opts.biffguess && opts.biff == 2) opts.biff = 5;
var cell = parse_XLSCell(blob, 6, opts);
function parse_Number(blob) {
var cell = parse_XLSCell(blob, 6);
var xnum = parse_Xnum(blob, 8);
cell.val = xnum;
return cell;
@ -735,6 +665,22 @@ function parse_ExternName(blob, length, opts) {
}
/* [MS-XLS] 2.4.150 TODO */
var XLSLblBuiltIn = [
"_xlnm.Consolidate_Area",
"_xlnm.Auto_Open",
"_xlnm.Auto_Close",
"_xlnm.Extract",
"_xlnm.Database",
"_xlnm.Criteria",
"_xlnm.Print_Area",
"_xlnm.Print_Titles",
"_xlnm.Recorder",
"_xlnm.Data_Form",
"_xlnm.Auto_Activate",
"_xlnm.Auto_Deactivate",
"_xlnm.Sheet_Title",
"_xlnm._FilterDatabase"
];
function parse_Lbl(blob, length, opts) {
var target = blob.l + length;
var flags = blob.read_shift(2);
@ -751,9 +697,7 @@ function parse_Lbl(blob, length, opts) {
var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
if(flags & 0x20) name = XLSLblBuiltIn[name.charCodeAt(0)];
var npflen = target - blob.l; if(opts && opts.biff == 2) --npflen;
/*jshint -W018 */
var rgce = (target == blob.l || cce === 0 || !(npflen > 0)) ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
/*jshint +W018 */
return {
chKey: chKey,
Name: name,
@ -762,11 +706,9 @@ function parse_Lbl(blob, length, opts) {
};
}
/* [MS-XLS] 2.4.106 TODO: legacy record filename encoding */
/* [MS-XLS] 2.4.106 TODO: verify filename encoding */
function parse_ExternSheet(blob, length, opts) {
if(opts.biff < 8) return parse_BIFF5ExternSheet(blob, length, opts);
/* see issue 2907 */
if(!(opts.biff > 8) && (length == blob[blob.l] + (blob[blob.l+1] == 0x03 ? 1 : 0) + 1)) return parse_BIFF5ExternSheet(blob, length, opts);
var o = [], target = blob.l + length, len = blob.read_shift(opts.biff > 8 ? 4 : 2);
while(len-- !== 0) o.push(parse_XTI(blob, opts.biff > 8 ? 12 : 6, opts));
// [iSupBook, itabFirst, itabLast];
@ -818,34 +760,21 @@ function parse_MTRSettings(blob) {
return [fMTREnabled, fUserSetThreadCount, cUserThreadCount];
}
/* [MS-XLS] 2.5.186 */
/* [MS-XLS] 2.5.186 TODO: BIFF5 */
function parse_NoteSh(blob, length, opts) {
if(opts.biff < 8) return;
var row = blob.read_shift(2), col = blob.read_shift(2);
var flags = blob.read_shift(2), idObj = blob.read_shift(2);
var stAuthor = parse_XLUnicodeString2(blob, 0, opts);
if(opts.biff < 8) blob.read_shift(1);
return [{r:row,c:col}, stAuthor, idObj, flags];
}
/* [MS-XLS] 2.4.179 */
function parse_Note(blob, length, opts) {
if(opts && (opts.biff < 8)) {
var row = blob.read_shift(2), col = blob.read_shift(2);
if(row == 0xFFFF || row == -1) return; // TODO: test continuation
var cch = blob.read_shift(2);
var cmnt = blob.read_shift(Math.min(cch,2048), 'cpstr');
return [{r:row, c:col}, cmnt];
}
/* TODO: Support revisions */
return parse_NoteSh(blob, length, opts);
}
function write_NOTE_BIFF2(text/*:string*/, R/*:number*/, C/*:number*/, len/*?:number*/) {
var o = new_buf(6 + (len || text.length));
o.write_shift(2, R);
o.write_shift(2, C);
o.write_shift(2, len || text.length);
o.write_shift(text.length, text, "sbcs");
return o;
}
/* [MS-XLS] 2.4.168 */
function parse_MergeCells(blob, length)/*:Array<Range>*/ {
@ -869,8 +798,8 @@ function parse_Obj(blob, length, opts) {
return { cmo: cmo, ft:fts };
}
/* from older spec */
var parse_BIFF5OT = {
0x08: function(blob, length) {
var parse_BIFF5OT = [];
parse_BIFF5OT[0x08] = function(blob, length) {
var tgt = blob.l + length;
blob.l += 10; // todo
var cf = blob.read_shift(2);
@ -883,7 +812,6 @@ var parse_BIFF5OT = {
blob.l += cchName; // TODO: stName
blob.l = tgt; // TODO: fmla
return { fmt:cf };
}
};
function parse_BIFF5Obj(blob, length, opts) {
@ -916,7 +844,7 @@ try {
var ot = (opts.lastobj||{cmo:[0,0]}).cmo[1];
var controlInfo; // eslint-disable-line no-unused-vars
if([0,5,7,11,12,14].indexOf(ot) == -1) blob.l += 6;
else controlInfo = parse_ControlInfo(blob, 6, opts); // eslint-disable-line no-unused-vars
else controlInfo = parse_ControlInfo(blob, 6, opts);
var cchText = blob.read_shift(2);
/*var cbRuns = */blob.read_shift(2);
/*var ifntEmpty = */parseuint16(blob, 2);
@ -1039,20 +967,6 @@ function parse_ColInfo(blob, length, opts) {
if(opts.biff >= 5 || !opts.biff) o.level = (flags >> 8) & 0x7;
return o;
}
function write_ColInfo(col, idx) {
var o = new_buf(12);
o.write_shift(2, idx);
o.write_shift(2, idx);
o.write_shift(2, col.width * 256);
o.write_shift(2, 0);
var f = 0;
if(col.hidden) f |= 1;
o.write_shift(1, f);
f = col.level || 0;
o.write_shift(1, f);
o.write_shift(2, 0);
return o;
}
/* [MS-XLS] 2.4.257 */
function parse_Setup(blob, length) {
@ -1095,50 +1009,42 @@ function parse_ImData(blob) {
return o;
}
function write_BIFF2Cell(out, r/*:number*/, c/*:number*/, ixfe/*:number*/, ifmt/*:number*/) {
if(!out) out = new_buf(7);
out.write_shift(2, r);
out.write_shift(2, c);
out.write_shift(1, ixfe||0/* & 0x3F */);
out.write_shift(1, ifmt||0/* & 0x3F */);
out.write_shift(1, 0);
return out;
}
/* BIFF2_??? where ??? is the name from [XLS] */
function parse_BIFF2STR(blob, length, opts) {
if(opts.biffguess && opts.biff == 5) opts.biff = 2;
var cell = parse_XLSCell(blob, 7, opts);
var cell = parse_XLSCell(blob, 6);
++blob.l;
var str = parse_XLUnicodeString2(blob, length-7, opts);
cell.t = 'str';
cell.val = str;
return cell;
}
function parse_BIFF2NUM(blob, length, opts) {
var cell = parse_XLSCell(blob, 7, opts);
function parse_BIFF2NUM(blob/*::, length*/) {
var cell = parse_XLSCell(blob, 6);
++blob.l;
var num = parse_Xnum(blob, 8);
cell.t = 'n';
cell.val = num;
return cell;
}
function write_BIFF2NUM(r/*:number*/, c/*:number*/, val/*:number*/, ixfe, ifmt) {
function write_BIFF2NUM(r/*:number*/, c/*:number*/, val/*:number*/) {
var out = new_buf(15);
write_BIFF2Cell(out, r, c, ixfe||0, ifmt||0);
write_BIFF2Cell(out, r, c);
out.write_shift(8, val, 'f');
return out;
}
function parse_BIFF2INT(blob, length, opts) {
var cell = parse_XLSCell(blob, 7, opts);
function parse_BIFF2INT(blob) {
var cell = parse_XLSCell(blob, 6);
++blob.l;
var num = blob.read_shift(2);
cell.t = 'n';
cell.val = num;
return cell;
}
function write_BIFF2INT(r/*:number*/, c/*:number*/, val/*:number*/, ixfe/*:number*/, ifmt/*:number*/) {
function write_BIFF2INT(r/*:number*/, c/*:number*/, val/*:number*/) {
var out = new_buf(9);
write_BIFF2Cell(out, r, c, ixfe||0, ifmt||0);
write_BIFF2Cell(out, r, c);
out.write_shift(2, val);
return out;
}
@ -1149,16 +1055,6 @@ function parse_BIFF2STRING(blob) {
return blob.read_shift(cch, 'sbcs-cont');
}
function parse_BIFF2BOOLERR(blob, length, opts) {
var bestart = blob.l + 7;
var cell = parse_XLSCell(blob, 6, opts);
blob.l = bestart;
var val = parse_Bes(blob, 2);
cell.val = val;
cell.t = (val === true || val === false) ? 'b' : 'e';
return cell;
}
/* TODO: convert to BIFF8 font struct */
function parse_BIFF2FONTXTRA(blob, length) {
blob.l += 6; // unknown
@ -1172,7 +1068,7 @@ function parse_BIFF2FONTXTRA(blob, length) {
/* TODO: parse rich text runs */
function parse_RString(blob, length, opts) {
var end = blob.l + length;
var cell = parse_XLSCell(blob, 6, opts);
var cell = parse_XLSCell(blob, 6);
var cch = blob.read_shift(2);
var str = parse_XLUnicodeStringNoCch(blob, cch, opts);
blob.l = end;
@ -1180,10 +1076,3 @@ function parse_RString(blob, length, opts) {
cell.val = str;
return cell;
}
function parse_BIFF4SheetInfo(blob/*::, length, opts*/) {
var flags = blob.read_shift(4);
var cch = blob.read_shift(1), name = blob.read_shift(cch, "sbcs");
if(name.length === 0) name = "Sheet1";
return { flags: flags, name:name };
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -4,7 +4,7 @@ function parse_rpr(rpr) {
var pass = false;
if(m) for(;i!=m.length; ++i) {
var y = parsexmltag(m[i]);
switch(y[0].replace(/<\w*:/g,"<")) {
switch(y[0].replace(/\w*:/g,"")) {
/* 18.8.12 condense CT_BooleanProperty */
/* ** not required . */
case '<condense': break;
@ -81,19 +81,15 @@ function parse_rpr(rpr) {
case '<color':
if(y.rgb) font.color = y.rgb.slice(2,8);
break;
case '<color>': case '<color/>': case '</color>': break;
/* 18.8.18 family ST_FontFamily */
case '<family': font.family = y.val; break;
case '<family>': case '<family/>': case '</family>': break;
/* 18.4.14 vertAlign CT_VerticalAlignFontProperty TODO */
case '<vertAlign': font.valign = y.val; break;
case '<vertAlign>': case '<vertAlign/>': case '</vertAlign>': break;
/* 18.8.35 scheme CT_FontScheme TODO */
case '<scheme': break;
case '<scheme>': case '<scheme/>': case '</scheme>': break;
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': break;
@ -106,15 +102,16 @@ function parse_rpr(rpr) {
return font;
}
var parse_rs = /*#__PURE__*/(function() {
var parse_rs = (function() {
var tregex = matchtag("t"), rpregex = matchtag("rPr");
/* 18.4.4 r CT_RElt */
function parse_r(r) {
/* 18.4.12 t ST_Xstring */
var t = str_match_xml_ns(r, "t")/*, cp = 65001*/;
var t = r.match(tregex)/*, cp = 65001*/;
if(!t) return {t:"s", v:""};
var o/*:Cell*/ = ({t:'s', v:unescapexml(t[1])}/*:any*/);
var rpr = str_match_xml_ns(r, "rPr");
var rpr = r.match(rpregex);
if(rpr) o.s = parse_rpr(rpr[1]);
return o;
}
@ -126,7 +123,7 @@ var parse_rs = /*#__PURE__*/(function() {
/* Parse a list of <r> tags */
var rs_to_html = /*#__PURE__*/(function parse_rs_factory() {
var rs_to_html = (function parse_rs_factory() {
var nlregex = /(\r\n|\n)/g;
function parse_rpr2(font, intro, outro) {
var style/*:Array<string>*/ = [];
@ -167,7 +164,8 @@ var rs_to_html = /*#__PURE__*/(function parse_rs_factory() {
})();
/* 18.4.8 si CT_Rst */
var sitregex = /<(?:\w+:)?t\b[^<>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r\b[^<>]*>/;
var sitregex = /<(?:\w+:)?t[^>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r>/;
var sirphregex = /<(?:\w+:)?rPh.*?>([\s\S]*?)<\/(?:\w+:)?rPh>/g;
function parse_si(x, opts) {
var html = opts ? opts.cellHTML : true;
var z = {};
@ -176,14 +174,14 @@ function parse_si(x, opts) {
/* 18.4.12 t ST_Xstring (Plaintext String) */
// TODO: is whitespace actually valid here?
if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) {
z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||""), true);
z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||""));
z.r = utf8read(x);
if(html) z.h = escapehtml(z.t);
}
/* 18.4.4 r CT_RElt (Rich Text Run) */
else if((/*y = */x.match(sirregex))) {
z.r = utf8read(x);
z.t = unescapexml(utf8read((str_remove_xml_ns_g(x, "rPh").match(sitregex)||[]).join("").replace(tagregex,"")), true);
z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")));
if(html) z.h = rs_to_html(parse_rs(z.r));
}
/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
@ -192,30 +190,32 @@ function parse_si(x, opts) {
}
/* 18.4 Shared String Table */
var sstr0 = /<(?:\w+:)?sst([^>]*)>([\s\S]*)<\/(?:\w+:)?sst>/;
var sstr1 = /<(?:\w+:)?(?:si|sstItem)>/g;
var sstr2 = /<\/(?:\w+:)?(?:si|sstItem)>/;
function parse_sst_xml(data/*:string*/, opts)/*:SST*/ {
var s/*:SST*/ = ([]/*:any*/), ss = "";
if(!data) return s;
/* 18.4.9 sst CT_Sst */
var sst = str_match_xml_ns(data, "sst");
var sst = data.match(sstr0);
if(sst) {
ss = sst[1].replace(sstr1,"").split(sstr2);
ss = sst[2].replace(sstr1,"").split(sstr2);
for(var i = 0; i != ss.length; ++i) {
var o = parse_si(ss[i].trim(), opts);
if(o != null) s[s.length] = o;
}
sst = parsexmltag(sst[0].slice(0, sst[0].indexOf(">"))); s.Count = sst.count; s.Unique = sst.uniqueCount;
sst = parsexmltag(sst[1]); s.Count = sst.count; s.Unique = sst.uniqueCount;
}
return s;
}
RELS.SST = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
var straywsregex = /^\s|\s$|[\t\n\r]/;
function write_sst_xml(sst/*:SST*/, opts)/*:string*/ {
if(!opts.bookSST) return "";
var o = [XML_HEADER];
o[o.length] = (writextag('sst', null, {
xmlns: XMLNS_main[0],
xmlns: XMLNS.main[0],
count: sst.Count,
uniqueCount: sst.Unique
}));
@ -226,7 +226,6 @@ function write_sst_xml(sst/*:SST*/, opts)/*:string*/ {
else {
sitag += "<t";
if(!s.t) s.t = "";
if(typeof s.t !== "string") s.t = String(s.t);
if(s.t.match(straywsregex)) sitag += ' xml:space="preserve"';
sitag += ">" + escapexml(s.t) + "</t>";
}

@ -7,23 +7,24 @@ function parse_BrtBeginSst(data) {
function parse_sst_bin(data, opts)/*:SST*/ {
var s/*:SST*/ = ([]/*:any*/);
var pass = false;
recordhopper(data, function hopper_sst(val, R, RT) {
recordhopper(data, function hopper_sst(val, R_n, RT) {
switch(RT) {
case 0x009F: /* BrtBeginSst */
case 0x009F: /* 'BrtBeginSst' */
s.Count = val[0]; s.Unique = val[1]; break;
case 0x0013: /* BrtSSTItem */
case 0x0013: /* 'BrtSSTItem' */
s.push(val); break;
case 0x00A0: /* BrtEndSst */
case 0x00A0: /* 'BrtEndSst' */
return true;
case 0x0023: /* BrtFRTBegin */
case 0x0023: /* 'BrtFRTBegin' */
pass = true; break;
case 0x0024: /* BrtFRTEnd */
case 0x0024: /* 'BrtFRTEnd' */
pass = false; break;
default:
if(R.T){}
if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
if(R_n.indexOf("Begin") > 0){/* empty */}
else if(R_n.indexOf("End") > 0){/* empty */}
if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
}
});
return s;
@ -40,9 +41,9 @@ var write_BrtSSTItem = write_RichStr;
function write_sst_bin(sst/*::, opts*/) {
var ba = buf_array();
write_record(ba, 0x009F /* BrtBeginSst */, write_BrtBeginSst(sst));
for(var i = 0; i < sst.length; ++i) write_record(ba, 0x0013 /* BrtSSTItem */, write_BrtSSTItem(sst[i]));
write_record(ba, "BrtBeginSst", write_BrtBeginSst(sst));
for(var i = 0; i < sst.length; ++i) write_record(ba, "BrtSSTItem", write_BrtSSTItem(sst[i]));
/* FRTSST */
write_record(ba, 0x00A0 /* BrtEndSst */);
write_record(ba, "BrtEndSst");
return ba.end();
}

@ -1,5 +1,5 @@
function _JS2ANSI(str/*:string*/)/*:Array<number>*/ {
if(typeof $cptable !== 'undefined') return $cptable.utils.encode(current_ansi, str);
if(typeof cptable !== 'undefined') return cptable.utils.encode(current_ansi, str);
var o/*:Array<number>*/ = [], oo = str.split("");
for(var i = 0; i < oo.length; ++i) o[i] = oo[i].charCodeAt(0);
return o;
@ -208,7 +208,7 @@ function crypto_CreatePasswordVerifier_Method1(Password/*:string*/) {
}
/* [MS-OFFCRYPTO] 2.3.7.2 Binary Document XOR Array Initialization */
var crypto_CreateXorArray_Method1 = /*#__PURE__*/(function() {
var crypto_CreateXorArray_Method1 = (function() {
var PadArray = [0xBB, 0xFF, 0xFF, 0xBA, 0xFF, 0xFF, 0xB9, 0x80, 0x00, 0xBE, 0x0F, 0x00, 0xBF, 0x0F, 0x00];
var InitialCode = [0xE1F0, 0x1D0F, 0xCC9C, 0x84C0, 0x110C, 0x0E10, 0xF1CE, 0x313E, 0x1872, 0xE139, 0xD40F, 0x84F9, 0x280C, 0xA96A, 0x4EC3];
var XorMatrix = [0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09, 0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF, 0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0, 0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40, 0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5, 0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A, 0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9, 0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0, 0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC, 0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10, 0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168, 0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C, 0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD, 0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC, 0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4];

@ -1,107 +1,52 @@
function rtf_to_sheet(d, opts) {
switch (opts.type) {
case "base64":
return rtf_to_sheet_str(Base64_decode(d), opts);
case "binary":
return rtf_to_sheet_str(d, opts);
case "buffer":
return rtf_to_sheet_str(has_buf && Buffer.isBuffer(d) ? d.toString("binary") : a2s(d), opts);
case "array":
return rtf_to_sheet_str(cc2str(d), opts);
}
throw new Error("Unrecognized type " + opts.type);
}
function rtf_to_sheet_str(str, opts) {
var o = opts || {};
var ws = {};
var dense = o.dense;
if (dense)
ws["!data"] = [];
var rows = str_match_ng(str, "\\trowd", "\\row");
if (!rows)
throw new Error("RTF missing table");
var range = { s: { c: 0, r: 0 }, e: { c: 0, r: rows.length - 1 } };
var row = [];
rows.forEach(function(rowtf, R) {
if (dense)
row = ws["!data"][R] = [];
var rtfre = /\\[\w\-]+\b/g;
var last_index = 0;
var res;
var C = -1;
var payload = [];
while ((res = rtfre.exec(rowtf)) != null) {
var data = rowtf.slice(last_index, rtfre.lastIndex - res[0].length);
if (data.charCodeAt(0) == 32)
data = data.slice(1);
if (data.length)
payload.push(data);
switch (res[0]) {
case "\\cell":
++C;
if (payload.length) {
var cell = { v: payload.join(""), t: "s" };
if (cell.v == "TRUE" || cell.v == "FALSE") {
cell.v = cell.v == "TRUE";
cell.t = "b";
} else if (!isNaN(fuzzynum(cell.v))) {
cell.t = "n";
if (o.cellText !== false)
cell.w = cell.v;
cell.v = fuzzynum(cell.v);
} else if (RBErr[cell.v] != null) {
cell.t = "e";
cell.w = cell.v;
cell.v = RBErr[cell.v];
}
if (dense)
row[C] = cell;
else
ws[encode_cell({ r: R, c: C })] = cell;
}
payload = [];
break;
case "\\par":
payload.push("\n");
break;
}
last_index = rtfre.lastIndex;
}
if (C > range.e.c)
range.e.c = C;
});
ws["!ref"] = encode_range(range);
return ws;
}
function rtf_to_workbook(d, opts) {
var wb = sheet_to_workbook(rtf_to_sheet(d, opts), opts);
wb.bookType = "rtf";
return wb;
}
function sheet_to_rtf(ws, opts) {
var o = ["{\\rtf1\\ansi"];
if (!ws["!ref"])
return o[0] + "}";
var r = safe_decode_range(ws["!ref"]), cell;
var dense = ws["!data"] != null, row = [];
for (var R = r.s.r; R <= r.e.r; ++R) {
o.push("\\trowd\\trautofit1");
for (var C = r.s.c; C <= r.e.c; ++C)
o.push("\\cellx" + (C + 1));
o.push("\\pard\\intbl");
if (dense)
row = ws["!data"][R] || [];
for (C = r.s.c; C <= r.e.c; ++C) {
var coord = encode_cell({ r: R, c: C });
cell = dense ? row[C] : ws[coord];
if (!cell || cell.v == null && (!cell.f || cell.F)) {
o.push(" \\cell");
continue;
}
o.push(" " + (cell.w || (format_cell(cell), cell.w) || "").replace(/[\r\n]/g, "\\par "));
o.push("\\cell");
}
o.push("\\pard\\intbl\\row");
}
return o.join("") + "}";
}
var RTF = (function() {
function rtf_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
switch(opts.type) {
case 'base64': return rtf_to_sheet_str(Base64.decode(d), opts);
case 'binary': return rtf_to_sheet_str(d, opts);
case 'buffer': return rtf_to_sheet_str(d.toString('binary'), opts);
case 'array': return rtf_to_sheet_str(cc2str(d), opts);
}
throw new Error("Unrecognized type " + opts.type);
}
function rtf_to_sheet_str(str/*:string*/, opts)/*:Worksheet*/ {
var o = opts || {};
var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/);
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:0}}/*:any*/);
// TODO: parse
if(!str.match(/\\trowd/)) throw new Error("RTF missing table");
ws['!ref'] = encode_range(range);
return ws;
}
function rtf_to_workbook(d/*:RawData*/, opts)/*:Workbook*/ { return sheet_to_workbook(rtf_to_sheet(d, opts), opts); }
/* TODO: this is a stub */
function sheet_to_rtf(ws/*:Worksheet*//*::, opts*/)/*:string*/ {
var o = ["{\\rtf1\\ansi"];
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = Array.isArray(ws);
for(var R = r.s.r; R <= r.e.r; ++R) {
o.push("\\trowd\\trautofit1");
for(var C = r.s.c; C <= r.e.c; ++C) o.push("\\cellx" + (C+1));
o.push("\\pard\\intbl");
for(C = r.s.c; C <= r.e.c; ++C) {
var coord = encode_cell({r:R,c:C});
cell = dense ? (ws[R]||[])[C]: ws[coord];
if(!cell || cell.v == null && (!cell.f || cell.F)) continue;
o.push(" " + (cell.w || (format_cell(cell), cell.w)));
o.push("\\cell");
}
o.push("\\pard\\intbl\\row");
}
return o.join("") + "}";
}
return {
to_workbook: rtf_to_workbook,
to_sheet: rtf_to_sheet,
from_sheet: sheet_to_rtf
};
})();

@ -3,7 +3,7 @@ function parse_borders(t, styles, themes, opts) {
styles.Borders = [];
var border = {};
var pass = false;
(t.match(tagregex)||[]).forEach(function(x) {
(t[0].match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<borders': case '<borders>': case '</borders>': break;
@ -78,7 +78,7 @@ function parse_fills(t, styles, themes, opts) {
styles.Fills = [];
var fill = {};
var pass = false;
(t.match(tagregex)||[]).forEach(function(x) {
(t[0].match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<fills': case '<fills>': case '</fills>': break;
@ -144,7 +144,7 @@ function parse_fonts(t, styles, themes, opts) {
styles.Fonts = [];
var font = {};
var pass = false;
(t.match(tagregex)||[]).forEach(function(x) {
(t[0].match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<fonts': case '<fonts>': case '</fonts>': break;
@ -163,12 +163,10 @@ function parse_fonts(t, styles, themes, opts) {
/* 18.8.2 b CT_BooleanProperty */
case '<b': font.bold = y.val ? parsexmlbool(y.val) : 1; break;
case '<b/>': font.bold = 1; break;
case '</b>': case '</b': break;
/* 18.8.26 i CT_BooleanProperty */
case '<i': font.italic = y.val ? parsexmlbool(y.val) : 1; break;
case '<i/>': font.italic = 1; break;
case '</i>': case '</i': break;
/* 18.4.13 u CT_UnderlineProperty */
case '<u':
@ -180,55 +178,48 @@ function parse_fonts(t, styles, themes, opts) {
case "doubleAccounting": font.underline = 0x22; break;
} break;
case '<u/>': font.underline = 1; break;
case '</u>': case '</u': break;
/* 18.4.10 strike CT_BooleanProperty */
case '<strike': font.strike = y.val ? parsexmlbool(y.val) : 1; break;
case '<strike/>': font.strike = 1; break;
case '</strike>': case '</strike': break;
/* 18.4.2 outline CT_BooleanProperty */
case '<outline': font.outline = y.val ? parsexmlbool(y.val) : 1; break;
case '<outline/>': font.outline = 1; break;
case '</outline>': case '</outline': break;
/* 18.8.36 shadow CT_BooleanProperty */
case '<shadow': font.shadow = y.val ? parsexmlbool(y.val) : 1; break;
case '<shadow/>': font.shadow = 1; break;
case '</shadow>': case '</shadow': break;
/* 18.8.12 condense CT_BooleanProperty */
case '<condense': font.condense = y.val ? parsexmlbool(y.val) : 1; break;
case '<condense/>': font.condense = 1; break;
case '</condense>': case '</condense': break;
/* 18.8.17 extend CT_BooleanProperty */
case '<extend': font.extend = y.val ? parsexmlbool(y.val) : 1; break;
case '<extend/>': font.extend = 1; break;
case '</extend>': case '</extend': break;
/* 18.4.11 sz CT_FontSize */
case '<sz': if(y.val) font.sz = +y.val; break;
case '<sz/>': case '</sz>': case '</sz': break;
case '<sz/>': case '</sz>': break;
/* 18.4.14 vertAlign CT_VerticalAlignFontProperty */
case '<vertAlign': if(y.val) font.vertAlign = y.val; break;
case '<vertAlign/>': case '</vertAlign>': case '</vertAlign': break;
case '<vertAlign/>': case '</vertAlign>': break;
/* 18.8.18 family CT_FontFamily */
case '<family': if(y.val) font.family = parseInt(y.val,10); break;
case '<family/>': case '</family>': case '</family': break;
case '<family/>': case '</family>': break;
/* 18.8.35 scheme CT_FontScheme */
case '<scheme': if(y.val) font.scheme = y.val; break;
case '<scheme/>': case '</scheme>': case '</scheme': break;
case '<scheme/>': case '</scheme>': break;
/* 18.4.1 charset CT_IntProperty */
case '<charset':
if(y.val == '1') break;
y.codepage = CS2CP[parseInt(y.val, 10)];
break;
case '<charset/>': case '</charset>': case '</charset': break;
/* 18.?.? color CT_Color */
case '<color':
@ -240,7 +231,7 @@ function parse_fonts(t, styles, themes, opts) {
font.color.index = parseInt(y.indexed, 10);
var icv = XLSIcv[font.color.index];
if(font.color.index == 81) icv = XLSIcv[1];
if(!icv) icv = XLSIcv[1]; //throw new Error(x); // note: 206 is valid
if(!icv) throw new Error(x);
font.color.rgb = icv[0].toString(16) + icv[1].toString(16) + icv[2].toString(16);
} else if(y.theme) {
font.color.theme = parseInt(y.theme, 10);
@ -251,11 +242,11 @@ function parse_fonts(t, styles, themes, opts) {
}
break;
case '<color/>': case '</color>': case '</color': break;
case '<color/>': case '</color>': break;
/* note: sometimes mc:AlternateContent appears bare */
case '<AlternateContent': pass = true; break;
case '</AlternateContent>': case '</AlternateContent': pass = false; break;
case '</AlternateContent>': pass = false; break;
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': break;
@ -271,9 +262,9 @@ function parse_fonts(t, styles, themes, opts) {
/* 18.8.31 numFmts CT_NumFmts */
function parse_numFmts(t, styles, opts) {
styles.NumberFmt = [];
var k/*Array<number>*/ = (keys(table_fmt)/*:any*/);
for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = table_fmt[k[i]];
var m = t.match(tagregex);
var k/*Array<number>*/ = (keys(SSF._table)/*:any*/);
for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
var m = t[0].match(tagregex);
if(!m) return;
for(i=0; i < m.length; ++i) {
var y = parsexmltag(m[i]);
@ -287,7 +278,7 @@ function parse_numFmts(t, styles, opts) {
for(j = 0x188; j > 0x3c; --j) if(styles.NumberFmt[j] == null) break;
styles.NumberFmt[j] = f;
}
SSF__load(f,j);
SSF.load(f,j);
}
} break;
case '</numFmt>': break;
@ -314,27 +305,27 @@ function parse_cellXfs(t, styles, opts) {
styles.CellXf = [];
var xf;
var pass = false;
(t.match(tagregex)||[]).forEach(function(x) {
(t[0].match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x), i = 0;
switch(strip_ns(y[0])) {
case '<cellXfs': case '<cellXfs>': case '<cellXfs/>': case '</cellXfs>': break;
/* 18.8.45 xf CT_Xf */
case '<xf': case '<xf/>': case '<xf>':
case '<xf': case '<xf/>':
xf = y;
delete xf[0];
for(i = 0; i < cellXF_uint.length; ++i) if(xf[cellXF_uint[i]])
xf[cellXF_uint[i]] = parseInt(xf[cellXF_uint[i]], 10);
for(i = 0; i < cellXF_bool.length; ++i) if(xf[cellXF_bool[i]])
xf[cellXF_bool[i]] = parsexmlbool(xf[cellXF_bool[i]]);
if(styles.NumberFmt && xf.numFmtId > 0x188) {
if(xf.numFmtId > 0x188) {
for(i = 0x188; i > 0x3c; --i) if(styles.NumberFmt[xf.numFmtId] == styles.NumberFmt[i]) { xf.numFmtId = i; break; }
}
styles.CellXf.push(xf); break;
case '</xf>': break;
/* 18.8.1 alignment CT_CellAlignment */
case '<alignment': case '<alignment/>': case '<alignment>':
case '<alignment': case '<alignment/>':
var alignment = {};
if(y.vertical) alignment.vertical = y.vertical;
if(y.horizontal) alignment.horizontal = y.horizontal;
@ -346,12 +337,12 @@ function parse_cellXfs(t, styles, opts) {
case '</alignment>': break;
/* 18.8.33 protection CT_CellProtection */
case '<protection': case '<protection>':
case '<protection':
break;
case '</protection>': case '<protection/>': break;
/* note: sometimes mc:AlternateContent appears bare */
case '<AlternateContent': case '<AlternateContent>': pass = true; break;
case '<AlternateContent': pass = true; break;
case '</AlternateContent>': pass = false; break;
/* 18.2.10 extLst CT_ExtensionList ? */
@ -378,32 +369,37 @@ function write_cellXfs(cellXfs)/*:string*/ {
}
/* 18.8 Styles CT_Stylesheet*/
var parse_sty_xml= /*#__PURE__*/(function make_pstyx() {
var parse_sty_xml= (function make_pstyx() {
var numFmtRegex = /<(?:\w+:)?numFmts([^>]*)>[\S\s]*?<\/(?:\w+:)?numFmts>/;
var cellXfRegex = /<(?:\w+:)?cellXfs([^>]*)>[\S\s]*?<\/(?:\w+:)?cellXfs>/;
var fillsRegex = /<(?:\w+:)?fills([^>]*)>[\S\s]*?<\/(?:\w+:)?fills>/;
var fontsRegex = /<(?:\w+:)?fonts([^>]*)>[\S\s]*?<\/(?:\w+:)?fonts>/;
var bordersRegex = /<(?:\w+:)?borders([^>]*)>[\S\s]*?<\/(?:\w+:)?borders>/;
return function parse_sty_xml(data, themes, opts) {
var styles = {};
if(!data) return styles;
data = remove_doctype(str_remove_ng(data, "<!--", "-->"));
data = data.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
/* 18.8.39 styleSheet CT_Stylesheet */
var t;
/* 18.8.31 numFmts CT_NumFmts ? */
if((t=str_match_xml_ns(data, "numFmts"))) parse_numFmts(t[0], styles, opts);
if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts);
/* 18.8.23 fonts CT_Fonts ? */
if((t=str_match_xml_ns(data, "fonts"))) parse_fonts(t[0], styles, themes, opts);
if((t=data.match(fontsRegex))) parse_fonts(t, styles, themes, opts);
/* 18.8.21 fills CT_Fills ? */
if((t=str_match_xml_ns(data, "fills"))) parse_fills(t[0], styles, themes, opts);
if((t=data.match(fillsRegex))) parse_fills(t, styles, themes, opts);
/* 18.8.5 borders CT_Borders ? */
if((t=str_match_xml_ns(data, "borders"))) parse_borders(t[0], styles, themes, opts);
if((t=data.match(bordersRegex))) parse_borders(t, styles, themes, opts);
/* 18.8.9 cellStyleXfs CT_CellStyleXfs ? */
/* 18.8.8 cellStyles CT_CellStyles ? */
/* 18.8.10 cellXfs CT_CellXfs ? */
if((t=str_match_xml_ns(data, "cellXfs"))) parse_cellXfs(t[0], styles, opts);
if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts);
/* 18.8.15 dxfs CT_Dxfs ? */
/* 18.8.42 tableStyles CT_TableStyles ? */
@ -414,11 +410,15 @@ return function parse_sty_xml(data, themes, opts) {
};
})();
var STYLES_XML_ROOT = writextag('styleSheet', null, {
'xmlns': XMLNS.main[0],
'xmlns:vt': XMLNS.vt
});
RELS.STY = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
function write_sty_xml(wb/*:Workbook*/, opts)/*:string*/ {
var o = [XML_HEADER, writextag('styleSheet', null, {
'xmlns': XMLNS_main[0],
'xmlns:vt': XMLNS.vt
})], w;
var o = [XML_HEADER, STYLES_XML_ROOT], w;
if(wb.SSF && (w = write_numFmts(wb.SSF)) != null) o[o.length] = w;
o[o.length] = ('<fonts count="1"><font><sz val="12"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font></fonts>');
o[o.length] = ('<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');

@ -102,12 +102,11 @@ var XLSBFillPTNames = [
"gray125",
"gray0625"
];
var rev_XLSBFillPTNames/*:EvertNumType*/;
var rev_XLSBFillPTNames/*:EvertNumType*/ = (evert(XLSBFillPTNames)/*:any*/);
/* TODO: gradient fill representation */
var parse_BrtFill = parsenoop;
function write_BrtFill(fill, o) {
if(!o) o = new_buf(4*3 + 8*7 + 16*1);
if(!rev_XLSBFillPTNames) rev_XLSBFillPTNames = (evert(XLSBFillPTNames)/*:any*/);
var fls/*:number*/ = rev_XLSBFillPTNames[fill.patternType];
if(fls == null) fls = 0x28;
o.write_shift(4, fls);
@ -206,60 +205,60 @@ function write_BrtBeginTableStyles(cnt, defTableStyle, defPivotStyle) {
function parse_sty_bin(data, themes, opts) {
var styles = {};
styles.NumberFmt = ([]/*:any*/);
for(var y in table_fmt) styles.NumberFmt[y] = table_fmt[y];
for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y];
styles.CellXf = [];
styles.Fonts = [];
var state/*:Array<string>*/ = [];
var pass = false;
recordhopper(data, function hopper_sty(val, R, RT) {
recordhopper(data, function hopper_sty(val, R_n, RT) {
switch(RT) {
case 0x002C: /* BrtFmt */
styles.NumberFmt[val[0]] = val[1]; SSF__load(val[1], val[0]);
case 0x002C: /* 'BrtFmt' */
styles.NumberFmt[val[0]] = val[1]; SSF.load(val[1], val[0]);
break;
case 0x002B: /* BrtFont */
case 0x002B: /* 'BrtFont' */
styles.Fonts.push(val);
if(val.color.theme != null && themes && themes.themeElements && themes.themeElements.clrScheme) {
val.color.rgb = rgb_tint(themes.themeElements.clrScheme[val.color.theme].rgb, val.color.tint || 0);
}
break;
case 0x0401: /* BrtKnownFonts */ break;
case 0x002D: /* BrtFill */
case 0x0401: /* 'BrtKnownFonts' */ break;
case 0x002D: /* 'BrtFill' */
break;
case 0x002E: /* BrtBorder */
case 0x002E: /* 'BrtBorder' */
break;
case 0x002F: /* BrtXF */
if(state[state.length - 1] == 0x0269 /* BrtBeginCellXFs */) {
case 0x002F: /* 'BrtXF' */
if(state[state.length - 1] == "BrtBeginCellXFs") {
styles.CellXf.push(val);
}
break;
case 0x0030: /* BrtStyle */
case 0x01FB: /* BrtDXF */
case 0x023C: /* BrtMRUColor */
case 0x01DB: /* BrtIndexedColor */
case 0x0030: /* 'BrtStyle' */
case 0x01FB: /* 'BrtDXF' */
case 0x023C: /* 'BrtMRUColor' */
case 0x01DB: /* 'BrtIndexedColor': */
break;
case 0x0493: /* BrtDXF14 */
case 0x0836: /* BrtDXF15 */
case 0x046A: /* BrtSlicerStyleElement */
case 0x0200: /* BrtTableStyleElement */
case 0x082F: /* BrtTimelineStyleElement */
case 0x0C00: /* BrtUid */
case 0x0493: /* 'BrtDXF14' */
case 0x0836: /* 'BrtDXF15' */
case 0x046A: /* 'BrtSlicerStyleElement' */
case 0x0200: /* 'BrtTableStyleElement' */
case 0x082F: /* 'BrtTimelineStyleElement' */
case 0x0C00: /* 'BrtUid' */
break;
case 0x0023: /* BrtFRTBegin */
case 0x0023: /* 'BrtFRTBegin' */
pass = true; break;
case 0x0024: /* BrtFRTEnd */
case 0x0024: /* 'BrtFRTEnd' */
pass = false; break;
case 0x0025: /* BrtACBegin */
state.push(RT); pass = true; break;
case 0x0026: /* BrtACEnd */
case 0x0025: /* 'BrtACBegin' */
state.push(R_n); pass = true; break;
case 0x0026: /* 'BrtACEnd' */
state.pop(); pass = false; break;
default:
if(R.T > 0) state.push(RT);
else if(R.T < 0) state.pop();
else if(!pass || (opts.WTF && state[state.length-1] != 0x0025 /* BrtACBegin */)) throw new Error("Unexpected record 0x" + RT.toString(16));
if((R_n||"").indexOf("Begin") > 0) state.push(R_n);
else if((R_n||"").indexOf("End") > 0) state.pop();
else if(!pass || (opts.WTF && state[state.length-1] != "BrtACBegin")) throw new Error("Unexpected record " + RT + " " + R_n);
}
});
return styles;
@ -274,20 +273,20 @@ function write_FMTS_bin(ba, NF/*:?SSFTable*/) {
});
if(cnt == 0) return;
write_record(ba, 0x0267 /* BrtBeginFmts */, write_UInt32LE(cnt));
write_record(ba, "BrtBeginFmts", write_UInt32LE(cnt));
[[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
/*:: if(!NF) return; */
for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_record(ba, 0x002C /* BrtFmt */, write_BrtFmt(i, NF[i]));
for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_record(ba, "BrtFmt", write_BrtFmt(i, NF[i]));
});
write_record(ba, 0x0268 /* BrtEndFmts */);
write_record(ba, "BrtEndFmts");
}
function write_FONTS_bin(ba/*::, data*/) {
var cnt = 1;
if(cnt == 0) return;
write_record(ba, 0x0263 /* BrtBeginFonts */, write_UInt32LE(cnt));
write_record(ba, 0x002B /* BrtFont */, write_BrtFont({
write_record(ba, "BrtBeginFonts", write_UInt32LE(cnt));
write_record(ba, "BrtFont", write_BrtFont({
sz:12,
color: {theme:1},
name: "Calibri",
@ -295,77 +294,77 @@ function write_FONTS_bin(ba/*::, data*/) {
scheme: "minor"
}));
/* 1*65491BrtFont [ACFONTS] */
write_record(ba, 0x0264 /* BrtEndFonts */);
write_record(ba, "BrtEndFonts");
}
function write_FILLS_bin(ba/*::, data*/) {
var cnt = 2;
if(cnt == 0) return;
write_record(ba, 0x025B /* BrtBeginFills */, write_UInt32LE(cnt));
write_record(ba, 0x002D /* BrtFill */, write_BrtFill({patternType:"none"}));
write_record(ba, 0x002D /* BrtFill */, write_BrtFill({patternType:"gray125"}));
write_record(ba, "BrtBeginFills", write_UInt32LE(cnt));
write_record(ba, "BrtFill", write_BrtFill({patternType:"none"}));
write_record(ba, "BrtFill", write_BrtFill({patternType:"gray125"}));
/* 1*65431BrtFill */
write_record(ba, 0x025C /* BrtEndFills */);
write_record(ba, "BrtEndFills");
}
function write_BORDERS_bin(ba/*::, data*/) {
var cnt = 1;
if(cnt == 0) return;
write_record(ba, 0x0265 /* BrtBeginBorders */, write_UInt32LE(cnt));
write_record(ba, 0x002E /* BrtBorder */, write_BrtBorder({}));
write_record(ba, "BrtBeginBorders", write_UInt32LE(cnt));
write_record(ba, "BrtBorder", write_BrtBorder({}));
/* 1*65430BrtBorder */
write_record(ba, 0x0266 /* BrtEndBorders */);
write_record(ba, "BrtEndBorders");
}
function write_CELLSTYLEXFS_bin(ba/*::, data*/) {
var cnt = 1;
write_record(ba, 0x0272 /* BrtBeginCellStyleXFs */, write_UInt32LE(cnt));
write_record(ba, 0x002F /* BrtXF */, write_BrtXF({
write_record(ba, "BrtBeginCellStyleXFs", write_UInt32LE(cnt));
write_record(ba, "BrtXF", write_BrtXF({
numFmtId: 0,
fontId: 0,
fillId: 0,
borderId: 0
}, 0xFFFF));
/* 1*65430(BrtXF *FRT) */
write_record(ba, 0x0273 /* BrtEndCellStyleXFs */);
write_record(ba, "BrtEndCellStyleXFs");
}
function write_CELLXFS_bin(ba, data) {
write_record(ba, 0x0269 /* BrtBeginCellXFs */, write_UInt32LE(data.length));
data.forEach(function(c) { write_record(ba, 0x002F /* BrtXF */, write_BrtXF(c,0)); });
write_record(ba, "BrtBeginCellXFs", write_UInt32LE(data.length));
data.forEach(function(c) { write_record(ba, "BrtXF", write_BrtXF(c,0)); });
/* 1*65430(BrtXF *FRT) */
write_record(ba, 0x026A /* BrtEndCellXFs */);
write_record(ba, "BrtEndCellXFs");
}
function write_STYLES_bin(ba/*::, data*/) {
var cnt = 1;
write_record(ba, 0x026B /* BrtBeginStyles */, write_UInt32LE(cnt));
write_record(ba, 0x0030 /* BrtStyle */, write_BrtStyle({
write_record(ba, "BrtBeginStyles", write_UInt32LE(cnt));
write_record(ba, "BrtStyle", write_BrtStyle({
xfId:0,
builtinId:0,
name:"Normal"
}));
/* 1*65430(BrtStyle *FRT) */
write_record(ba, 0x026C /* BrtEndStyles */);
write_record(ba, "BrtEndStyles");
}
function write_DXFS_bin(ba/*::, data*/) {
var cnt = 0;
write_record(ba, 0x01F9 /* BrtBeginDXFs */, write_UInt32LE(cnt));
write_record(ba, "BrtBeginDXFs", write_UInt32LE(cnt));
/* *2147483647(BrtDXF *FRT) */
write_record(ba, 0x01FA /* BrtEndDXFs */);
write_record(ba, "BrtEndDXFs");
}
function write_TABLESTYLES_bin(ba/*::, data*/) {
var cnt = 0;
write_record(ba, 0x01FC /* BrtBeginTableStyles */, write_BrtBeginTableStyles(cnt, "TableStyleMedium9", "PivotStyleMedium4"));
write_record(ba, "BrtBeginTableStyles", write_BrtBeginTableStyles(cnt, "TableStyleMedium9", "PivotStyleMedium4"));
/* *TABLESTYLE */
write_record(ba, 0x01FD /* BrtEndTableStyles */);
write_record(ba, "BrtEndTableStyles");
}
function write_COLORPALETTE_bin(/*::ba, data*/) {
@ -376,7 +375,7 @@ function write_COLORPALETTE_bin(/*::ba, data*/) {
/* [MS-XLSB] 2.1.7.50 Styles */
function write_sty_bin(wb, opts) {
var ba = buf_array();
write_record(ba, 0x0116 /* BrtBeginStyleSheet */);
write_record(ba, "BrtBeginStyleSheet");
write_FMTS_bin(ba, wb.SSF);
write_FONTS_bin(ba, wb);
write_FILLS_bin(ba, wb);
@ -388,6 +387,6 @@ function write_sty_bin(wb, opts) {
write_TABLESTYLES_bin(ba, wb);
write_COLORPALETTE_bin(ba, wb);
/* FRTSTYLESHEET*/
write_record(ba, 0x0117 /* BrtEndStyleSheet */);
write_record(ba, "BrtEndStyleSheet");
return ba.end();
}

@ -1,3 +1,5 @@
RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
/* Even though theme layout is dk1 lt1 dk2 lt2, true order is lt1 dk1 lt2 dk2 */
var XLSXThemeClrScheme = [
'</a:lt1>', '</a:dk1>', '</a:lt2>', '</a:dk2>',
@ -18,12 +20,10 @@ function parse_clrScheme(t, themes, opts) {
/* 20.1.2.3.32 srgbClr CT_SRgbColor */
case '<a:srgbClr':
color.rgb = y.val; break;
case '</a:srgbClr>': break;
/* 20.1.2.3.33 sysClr CT_SystemColor */
case '<a:sysClr':
color.rgb = y.lastClr; break;
case '</a:sysClr>': break;
/* 20.1.4.1.1 accent1 (Accent 1) */
/* 20.1.4.1.2 accent2 (Accent 2) */
@ -37,10 +37,8 @@ function parse_clrScheme(t, themes, opts) {
/* 20.1.4.1.19 hlink (Hyperlink) */
/* 20.1.4.1.22 lt1 (Light 1) */
/* 20.1.4.1.23 lt2 (Light 2) */
case '</a:dk1>':
case '</a:lt1>':
case '<a:dk1>':
case '<a:lt1>':
case '<a:dk1>': case '</a:dk1>':
case '<a:lt1>': case '</a:lt1>':
case '<a:dk2>': case '</a:dk2>':
case '<a:lt2>': case '</a:lt2>':
case '<a:accent1>': case '</a:accent1>':
@ -70,35 +68,41 @@ function parse_fontScheme(/*::t, themes, opts*/) { }
/* 20.1.4.1.15 fmtScheme CT_StyleMatrix */
function parse_fmtScheme(/*::t, themes, opts*/) { }
var clrsregex = /<a:clrScheme([^>]*)>[\s\S]*<\/a:clrScheme>/;
var fntsregex = /<a:fontScheme([^>]*)>[\s\S]*<\/a:fontScheme>/;
var fmtsregex = /<a:fmtScheme([^>]*)>[\s\S]*<\/a:fmtScheme>/;
/* 20.1.6.10 themeElements CT_BaseStyles */
function parse_themeElements(data, themes, opts) {
themes.themeElements = {};
var t;
/* clrScheme CT_ColorScheme */
if(!(t=str_match_xml(data, "a:clrScheme"))) throw new Error('clrScheme not found in themeElements');
parse_clrScheme(t, themes, opts);
/* fontScheme CT_FontScheme */
if(!(t=str_match_xml(data, "a:fontScheme"))) throw new Error('fontScheme not found in themeElements');
parse_fontScheme(t, themes, opts);
/* fmtScheme CT_StyleMatrix */
if(!(t=str_match_xml(data, "a:fmtScheme"))) throw new Error('fmtScheme not found in themeElements');
parse_fmtScheme(t, themes, opts);
[
/* clrScheme CT_ColorScheme */
['clrScheme', clrsregex, parse_clrScheme],
/* fontScheme CT_FontScheme */
['fontScheme', fntsregex, parse_fontScheme],
/* fmtScheme CT_StyleMatrix */
['fmtScheme', fmtsregex, parse_fmtScheme]
].forEach(function(m) {
if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements');
m[2](t, themes, opts);
});
}
var themeltregex = /<a:themeElements([^>]*)>[\s\S]*<\/a:themeElements>/;
/* 14.2.7 Theme Part */
function parse_theme_xml(data/*:string*/, opts) {
/* 20.1.6.9 theme CT_OfficeStyleSheet */
if(!data || data.length === 0) data = write_theme();
if(!data || data.length === 0) return parse_theme_xml(write_theme());
var t;
var themes = {};
/* themeElements CT_BaseStyles */
if(!(t=str_match_xml(data, "a:themeElements"))) throw new Error('themeElements not found in theme');
if(!(t=data.match(themeltregex))) throw new Error('themeElements not found in theme');
parse_themeElements(t[0], themes, opts);
themes.raw = data;
return themes;

@ -3,10 +3,10 @@ function parse_Theme(blob, length, opts) {
var end = blob.l + length;
var dwThemeVersion = blob.read_shift(4);
if(dwThemeVersion === 124226) return;
if(!opts.cellStyles) { blob.l = end; return; }
if(!opts.cellStyles || !jszip) { blob.l = end; return; }
var data = blob.slice(blob.l);
blob.l = end;
var zip; try { zip = zip_read(data, {type: "array"}); } catch(e) { return; }
var zip; try { zip = new jszip(data); } catch(e) { return; }
var themeXML = getzipstr(zip, "theme/theme/theme1.xml", true);
if(!themeXML) return;
return parse_theme_xml(themeXML, opts);

@ -1,111 +0,0 @@
function parse_BrtMdtinfo(data, length) {
return {
flags: data.read_shift(4),
version: data.read_shift(4),
name: parse_XLWideString(data, length - 8)
};
}
function write_BrtMdtinfo(data) {
var o = new_buf(12 + 2 * data.name.length);
o.write_shift(4, data.flags);
o.write_shift(4, data.version);
write_XLWideString(data.name, o);
return o.slice(0, o.l);
}
function parse_BrtMdb(data) {
var out = [];
var cnt = data.read_shift(4);
while (cnt-- > 0)
out.push([data.read_shift(4), data.read_shift(4)]);
return out;
}
function write_BrtMdb(mdb) {
var o = new_buf(4 + 8 * mdb.length);
o.write_shift(4, mdb.length);
for (var i = 0; i < mdb.length; ++i) {
o.write_shift(4, mdb[i][0]);
o.write_shift(4, mdb[i][1]);
}
return o;
}
function write_BrtBeginEsfmd(cnt, name) {
var o = new_buf(8 + 2 * name.length);
o.write_shift(4, cnt);
write_XLWideString(name, o);
return o.slice(0, o.l);
}
function parse_BrtBeginEsmdb(data) {
data.l += 4;
return data.read_shift(4) != 0;
}
function write_BrtBeginEsmdb(cnt, cm) {
var o = new_buf(8);
o.write_shift(4, cnt);
o.write_shift(4, cm ? 1 : 0);
return o;
}
function parse_xlmeta_bin(data, name, _opts) {
var out = { Types: [], Cell: [], Value: [] };
var opts = _opts || {};
var state = [];
var pass = false;
var metatype = 2;
recordhopper(data, function(val, R, RT) {
switch (RT) {
case 335:
out.Types.push({ name: val.name });
break;
case 51:
val.forEach(function(r) {
if (metatype == 1)
out.Cell.push({ type: out.Types[r[0] - 1].name, index: r[1] });
else if (metatype == 0)
out.Value.push({ type: out.Types[r[0] - 1].name, index: r[1] });
});
break;
case 337:
metatype = val ? 1 : 0;
break;
case 338:
metatype = 2;
break;
case 35:
state.push(RT);
pass = true;
break;
case 36:
state.pop();
pass = false;
break;
default:
if (R.T) {
} else if (!pass || opts.WTF && state[state.length - 1] != 35)
throw new Error("Unexpected record 0x" + RT.toString(16));
}
});
return out;
}
function write_xlmeta_bin() {
var ba = buf_array();
write_record(ba, 332);
write_record(ba, 334, write_UInt32LE(1));
write_record(ba, 335, write_BrtMdtinfo({
name: "XLDAPR",
version: 12e4,
flags: 3496657072
}));
write_record(ba, 336);
write_record(ba, 339, write_BrtBeginEsfmd(1, "XLDAPR"));
write_record(ba, 52);
write_record(ba, 35, write_UInt32LE(514));
write_record(ba, 4096, write_UInt32LE(0));
write_record(ba, 4097, writeuint16(1));
write_record(ba, 36);
write_record(ba, 53);
write_record(ba, 340);
write_record(ba, 337, write_BrtBeginEsmdb(1, true));
write_record(ba, 51, write_BrtMdb([[1, 0]]));
write_record(ba, 338);
write_record(ba, 333);
return ba.end();
}

@ -1,85 +0,0 @@
function parse_xlmeta_xml(data, name, opts) {
var out = { Types: [], Cell: [], Value: [] };
if (!data)
return out;
var pass = false;
var metatype = 2;
var lastmeta;
data.replace(tagregex, function(x) {
var y = parsexmltag(x);
switch (strip_ns(y[0])) {
case "<?xml":
break;
case "<metadata":
case "</metadata>":
break;
case "<metadataTypes":
case "</metadataTypes>":
break;
case "<metadataType":
out.Types.push({ name: y.name });
break;
case "</metadataType>":
break;
case "<futureMetadata":
for (var j = 0; j < out.Types.length; ++j)
if (out.Types[j].name == y.name)
lastmeta = out.Types[j];
break;
case "</futureMetadata>":
break;
case "<bk>":
break;
case "</bk>":
break;
case "<rc":
if (metatype == 1)
out.Cell.push({ type: out.Types[y.t - 1].name, index: +y.v });
else if (metatype == 0)
out.Value.push({ type: out.Types[y.t - 1].name, index: +y.v });
break;
case "</rc>":
break;
case "<cellMetadata":
metatype = 1;
break;
case "</cellMetadata>":
metatype = 2;
break;
case "<valueMetadata":
metatype = 0;
break;
case "</valueMetadata>":
metatype = 2;
break;
case "<extLst":
case "<extLst>":
case "</extLst>":
case "<extLst/>":
break;
case "<ext":
pass = true;
break;
case "</ext>":
pass = false;
break;
case "<rvb":
if (!lastmeta)
break;
if (!lastmeta.offsets)
lastmeta.offsets = [];
lastmeta.offsets.push(+y.i);
break;
default:
if (!pass && (opts == null ? void 0 : opts.WTF))
throw new Error("unrecognized " + y[0] + " in metadata");
}
return x;
});
return out;
}
function write_xlmeta_xml() {
var o = [XML_HEADER];
o.push('<metadata xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:xlrd="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata" xmlns:xda="http://schemas.microsoft.com/office/spreadsheetml/2017/dynamicarray">\n <metadataTypes count="1">\n <metadataType name="XLDAPR" minSupportedVersion="120000" copy="1" pasteAll="1" pasteValues="1" merge="1" splitFirst="1" rowColShift="1" clearFormats="1" clearComments="1" assign="1" coerce="1" cellMeta="1"/>\n </metadataTypes>\n <futureMetadata name="XLDAPR" count="1">\n <bk>\n <extLst>\n <ext uri="{bdbb8cdc-fa1e-496e-a857-3c3f30c029c3}">\n <xda:dynamicArrayProperties fDynamic="1" fCollapsed="0"/>\n </ext>\n </extLst>\n </bk>\n </futureMetadata>\n <cellMetadata count="1">\n <bk>\n <rc t="1" v="0"/>\n </bk>\n </cellMetadata>\n</metadata>');
return o.join("");
}

@ -36,14 +36,15 @@ function parse_BrtCalcChainItem$(data) {
function parse_cc_bin(data, name, opts) {
var out = [];
var pass = false;
recordhopper(data, function hopper_cc(val, R, RT) {
recordhopper(data, function hopper_cc(val, R_n, RT) {
switch(RT) {
case 0x003F: /* 'BrtCalcChainItem$' */
out.push(val); break;
default:
if(R.T){/* empty */}
else if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
if((R_n||"").indexOf("Begin") > 0){/* empty */}
else if((R_n||"").indexOf("End") > 0){/* empty */}
else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
}
});
return out;

@ -11,7 +11,7 @@ function parse_xlink_bin(data, rel, name/*:string*/, _opts) {
var pass = false, end = false;
recordhopper(data, function xlink_parse(val, R, RT) {
recordhopper(data, function xlink_parse(val, R_n, RT) {
if(end) return;
switch(RT) {
case 0x0167: /* 'BrtSupTabs' */
@ -43,8 +43,9 @@ function parse_xlink_bin(data, rel, name/*:string*/, _opts) {
pass = false; break;
default:
if(R.T){/* empty */}
else if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
if((R_n||"").indexOf("Begin") > 0){/* empty */}
else if((R_n||"").indexOf("End") > 0){/* empty */}
else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT.toString(16) + " " + R_n);
}
}, opts);
}

@ -1,4 +1,7 @@
/* 20.5 DrawingML - SpreadsheetML Drawing */
RELS.IMG = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
RELS.DRAW = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing";
/* 20.5.2.35 wsDr CT_Drawing */
function parse_drawing(data, rels/*:any*/) {
if(!data) return "??";
@ -13,7 +16,7 @@ function parse_drawing(data, rels/*:any*/) {
the actual type is based on the URI of the graphicData
TODO: handle embedded charts and other types of graphics
*/
var id = (data.match(/<c:chart [^<>]*r:id="([^<>"]*)"/)||["",""])[1];
var id = (data.match(/<c:chart [^>]*r:id="([^"]*)"/)||["",""])[1];
return rels['!id'][id].Target;
}

@ -1,64 +1,20 @@
/* L.5.5.2 SpreadsheetML Comments + VML Schema */
function parse_vml(data/*:string*/, sheet, comments) {
var cidx = 0;
(str_match_xml_ns_g(data, "shape")||[]).forEach(function(m) {
var type = "";
var hidden = true;
var aidx = -1;
var R = -1, C = -1;
m.replace(tagregex, function(x/*:string*/, idx/*:number*/) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<ClientData': if(y.ObjectType) type = y.ObjectType; break;
case '<Visible': case '<Visible/>': hidden = false; break;
case '<Row': case '<Row>': aidx = idx + x.length; break;
case '</Row>': R = +m.slice(aidx, idx).trim(); break;
case '<Column': case '<Column>': aidx = idx + x.length; break;
case '</Column>': C = +m.slice(aidx, idx).trim(); break;
}
return "";
});
switch(type) {
case 'Note':
var cell = ws_get_cell_stub(sheet, ((R>=0 && C>=0) ? encode_cell({r:R,c:C}) : comments[cidx].ref));
if(cell.c) {
cell.c.hidden = hidden;
}
++cidx;
break;
}
});
}
/* comment boxes */
function write_vml(rId/*:number*/, comments, ws) {
var _shapeid = 1024;
function write_comments_vml(rId/*:number*/, comments) {
var csize = [21600, 21600];
/* L.5.2.1.2 Path Attribute */
var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(",");
var o = [
writextag("xml", null, { 'xmlns:v': XLMLNS.v, 'xmlns:o': XLMLNS.o, 'xmlns:x': XLMLNS.x, 'xmlns:mv': XLMLNS.mv }).replace(/\/>/,">"),
writextag("o:shapelayout", writextag("o:idmap", null, {'v:ext':"edit", 'data':rId}), {'v:ext':"edit"})
writextag("o:shapelayout", writextag("o:idmap", null, {'v:ext':"edit", 'data':rId}), {'v:ext':"edit"}),
writextag("v:shapetype", [
writextag("v:stroke", null, {joinstyle:"miter"}),
writextag("v:path", null, {gradientshapeok:"t", 'o:connecttype':"rect"})
].join(""), {id:"_x0000_t202", 'o:spt':202, coordsize:csize.join(","),path:bbox})
];
while(_shapeid < rId * 1000) _shapeid += 1000;
var _shapeid = 65536 * rId;
var _comments = comments || [];
if(_comments.length > 0) o.push(writextag("v:shapetype", [
writextag("v:stroke", null, {joinstyle:"miter"}),
writextag("v:path", null, {gradientshapeok:"t", 'o:connecttype':"rect"})
].join(""), {id:"_x0000_t202", coordsize:csize.join(","), 'o:spt':202, path:bbox}));
_comments.forEach(function(x) { ++_shapeid; o.push(write_vml_comment(x, _shapeid)); });
o.push('</xml>');
return o.join("");
}
function write_vml_comment(x, _shapeid, ws)/*:string*/ {
comments.forEach(function(x) {
var c = decode_cell(x[0]);
var fillopts = /*::(*/{'color2':"#BEFF82", 'type':"gradient"}/*:: :any)*/;
if(fillopts.type == "gradient") fillopts.angle = "-180";
@ -66,8 +22,9 @@ function write_vml_comment(x, _shapeid, ws)/*:string*/ {
var fillxml = writextag('v:fill', fillparm, fillopts);
var shadata = ({on:"t", 'obscured':"t"}/*:any*/);
++_shapeid;
return [
o = o.concat([
'<v:shape' + wxt_helper({
id:'_x0000_s' + _shapeid,
type:"#_x0000_t202",
@ -90,5 +47,7 @@ function write_vml_comment(x, _shapeid, ws)/*:string*/ {
x[1].hidden ? '' : '<x:Visible/>',
'</x:ClientData>',
'</v:shape>'
].join("");
]); });
o.push('</xml>');
return o.join("");
}

@ -1,16 +1,17 @@
function sheet_insert_comments(sheet/*:WorkSheet*/, comments/*:Array<RawComment>*/, threaded/*:boolean*/, people/*:?Array<any>*/) {
var dense = sheet["!data"] != null;
RELS.CMNT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
function sheet_insert_comments(sheet, comments/*:Array<RawComment>*/) {
var dense = Array.isArray(sheet);
var cell/*:Cell*/;
comments.forEach(function(comment) {
var r = decode_cell(comment.ref);
if(r.r < 0 || r.c < 0) return;
if(dense) {
if(!sheet["!data"][r.r]) sheet["!data"][r.r] = [];
cell = sheet["!data"][r.r][r.c];
if(!sheet[r.r]) sheet[r.r] = [];
cell = sheet[r.r][r.c];
} else cell = sheet[comment.ref];
if (!cell) {
cell = ({t:"z"}/*:any*/);
if(dense) sheet["!data"][r.r][r.c] = cell;
if(dense) sheet[r.r][r.c] = cell;
else sheet[comment.ref] = cell;
var range = safe_decode_range(sheet["!ref"]||"BDWGO1000001:A1");
if(range.s.r > r.r) range.s.r = r.r;
@ -18,21 +19,13 @@ function sheet_insert_comments(sheet/*:WorkSheet*/, comments/*:Array<RawComment>
if(range.s.c > r.c) range.s.c = r.c;
if(range.e.c < r.c) range.e.c = r.c;
var encoded = encode_range(range);
sheet["!ref"] = encoded;
if (encoded !== sheet["!ref"]) sheet["!ref"] = encoded;
}
if (!cell.c) cell.c = [];
var o/*:Comment*/ = ({a: comment.author, t: comment.t, r: comment.r, T: threaded});
var o/*:Comment*/ = ({a: comment.author, t: comment.t, r: comment.r});
if(comment.h) o.h = comment.h;
/* threaded comments always override */
for(var i = cell.c.length - 1; i >= 0; --i) {
if(!threaded && cell.c[i].T) return;
if(threaded && !cell.c[i].T) cell.c.splice(i, 1);
}
if(threaded && people) for(i = 0; i < people.length; ++i) {
if(o.a == people[i].id) { o.a = people[i].name || o.a; break; }
}
cell.c.push(o);
});
}

@ -4,183 +4,54 @@ function parse_comments_xml(data/*:string*/, opts)/*:Array<RawComment>*/ {
if(data.match(/<(?:\w+:)?comments *\/>/)) return [];
var authors/*:Array<string>*/ = [];
var commentList/*:Array<RawComment>*/ = [];
var authtag = str_match_xml_ns(data, "authors");
var authtag = data.match(/<(?:\w+:)?authors>([\s\S]*)<\/(?:\w+:)?authors>/);
if(authtag && authtag[1]) authtag[1].split(/<\/\w*:?author>/).forEach(function(x) {
if(x === "" || x.trim() === "") return;
var a = x.match(/<(?:\w+:)?author[^<>]*>(.*)/);
var a = x.match(/<(?:\w+:)?author[^>]*>(.*)/);
if(a) authors.push(a[1]);
});
var cmnttag = str_match_xml_ns(data, "commentList");
var cmnttag = data.match(/<(?:\w+:)?commentList>([\s\S]*)<\/(?:\w+:)?commentList>/);
if(cmnttag && cmnttag[1]) cmnttag[1].split(/<\/\w*:?comment>/).forEach(function(x) {
if(x === "" || x.trim() === "") return;
var cm = x.match(/<(?:\w+:)?comment[^<>]*>/);
var cm = x.match(/<(?:\w+:)?comment[^>]*>/);
if(!cm) return;
var y = parsexmltag(cm[0]);
var comment/*:RawComment*/ = ({ author: y.authorId && authors[y.authorId] || "sheetjsghost", ref: y.ref, guid: y.guid }/*:any*/);
var cell = decode_cell(y.ref);
if(opts.sheetRows && opts.sheetRows <= cell.r) return;
var textMatch = str_match_xml_ns(x, "text");
var textMatch = x.match(/<(?:\w+:)?text>([\s\S]*)<\/(?:\w+:)?text>/);
var rt = !!textMatch && !!textMatch[1] && parse_si(textMatch[1]) || {r:"",t:"",h:""};
comment.r = rt.r;
if(rt.r == "<t></t>") rt.t = rt.h = "";
comment.t = (rt.t||"").replace(/\r\n/g,"\n").replace(/\r/g,"\n");
comment.t = rt.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n");
if(opts.cellHTML) comment.h = rt.h;
commentList.push(comment);
});
return commentList;
}
var CMNT_XML_ROOT = writextag('comments', null, { 'xmlns': XMLNS.main[0] });
function write_comments_xml(data/*::, opts*/) {
var o = [XML_HEADER, writextag('comments', null, { 'xmlns': XMLNS_main[0] })];
var o = [XML_HEADER, CMNT_XML_ROOT];
var iauthor/*:Array<string>*/ = [];
o.push("<authors>");
data.forEach(function(x) { x[1].forEach(function(w) { var a = escapexml(w.a);
if(iauthor.indexOf(a) == -1) {
iauthor.push(a);
o.push("<author>" + a + "</author>");
}
if(w.T && w.ID && iauthor.indexOf("tc=" + w.ID) == -1) {
iauthor.push("tc=" + w.ID);
o.push("<author>" + "tc=" + w.ID + "</author>");
}
if(iauthor.indexOf(a) > -1) return;
iauthor.push(a);
o.push("<author>" + a + "</author>");
}); });
if(iauthor.length == 0) { iauthor.push("SheetJ5"); o.push("<author>SheetJ5</author>"); }
o.push("</authors>");
o.push("<commentList>");
data.forEach(function(d) {
/* 18.7.3 CT_Comment */
var lastauthor = 0, ts = [], tcnt = 0;
if(d[1][0] && d[1][0].T && d[1][0].ID) lastauthor = iauthor.indexOf("tc=" + d[1][0].ID);
d[1].forEach(function(c) {
if(c.a) lastauthor = iauthor.indexOf(escapexml(c.a));
if(c.T) ++tcnt;
ts.push(c.t == null ? "" : escapexml(c.t));
});
if(tcnt === 0) {
d[1].forEach(function(c) {
o.push('<comment ref="' + d[0] + '" authorId="' + iauthor.indexOf(escapexml(c.a)) + '"><text>');
o.push(writetag("t", c.t == null ? "" : escapexml(c.t)));
o.push('</text></comment>');
});
} else {
if(d[1][0] && d[1][0].T && d[1][0].ID) lastauthor = iauthor.indexOf("tc=" + d[1][0].ID);
/* based on Threaded Comments -> Comments projection */
o.push('<comment ref="' + d[0] + '" authorId="' + lastauthor + '"><text>');
var t = "Comment:\n " + (ts[0]) + "\n";
for(var i = 1; i < ts.length; ++i) t += "Reply:\n " + ts[i] + "\n";
o.push(writetag("t", escapexml(t)));
/* 18.7.3 CT_Comment */
o.push('<comment ref="' + d[0] + '" authorId="' + iauthor.indexOf(escapexml(c.a)) + '"><text>');
o.push(writetag("t", c.t == null ? "" : escapexml(c.t)));
o.push('</text></comment>');
}
});
});
o.push("</commentList>");
if(o.length>2) { o[o.length] = ('</comments>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}
/* [MS-XLSX] 2.1.17 */
function parse_tcmnt_xml(data/*:string*/, opts)/*:Array<RawComment>*/ {
var out = [];
var pass = false, comment = {}, tidx = 0;
data.replace(tagregex, function xml_tcmnt(x, idx) {
var y/*:any*/ = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<?xml': break;
/* 2.6.207 ThreadedComments CT_ThreadedComments */
case '<ThreadedComments': break;
case '</ThreadedComments>': break;
/* 2.6.205 threadedComment CT_ThreadedComment */
case '<threadedComment': comment = {author: y.personId, guid: y.id, ref: y.ref, T: 1}; break;
case '</threadedComment>': if(comment.t != null) out.push(comment); break;
case '<text>': case '<text': tidx = idx + x.length; break;
case '</text>': comment.t = data.slice(tidx, idx).replace(/\r\n/g, "\n").replace(/\r/g, "\n"); break;
/* 2.6.206 mentions CT_ThreadedCommentMentions TODO */
case '<mentions': case '<mentions>': pass = true; break;
case '</mentions>': pass = false; break;
/* 2.6.202 mention CT_Mention TODO */
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': case '<extLst/>': break;
/* 18.2.7 ext CT_Extension + */
case '<ext': pass=true; break;
case '</ext>': pass=false; break;
default: if(!pass && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in threaded comments');
}
return x;
});
return out;
}
function write_tcmnt_xml(comments, people, opts) {
var o = [XML_HEADER, writextag('ThreadedComments', null, { 'xmlns': XMLNS.TCMNT }).replace(/[\/]>/, ">")];
comments.forEach(function(carr) {
var rootid = "";
(carr[1] || []).forEach(function(c, idx) {
if(!c.T) { delete c.ID; return; }
if(c.a && people.indexOf(c.a) == -1) people.push(c.a);
var tcopts = {
ref: carr[0],
id: "{54EE7951-7262-4200-6969-" + ("000000000000" + opts.tcid++).slice(-12) + "}"
};
if(idx == 0) rootid = tcopts.id;
else tcopts.parentId = rootid;
c.ID = tcopts.id;
if(c.a) tcopts.personId = "{54EE7950-7262-4200-6969-" + ("000000000000" + people.indexOf(c.a)).slice(-12) + "}";
o.push(writextag('threadedComment', writetag('text', c.t||""), tcopts));
});
});
o.push('</ThreadedComments>');
return o.join("");
}
/* [MS-XLSX] 2.1.18 */
function parse_people_xml(data/*:string*/, opts) {
var out = [];
var pass = false;
data.replace(tagregex, function xml_tcmnt(x) {
var y/*:any*/ = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<?xml': break;
/* 2.4.85 personList CT_PersonList */
case '<personList': break;
case '</personList>': break;
/* 2.6.203 person CT_Person TODO: providers */
case '<person': out.push({name: y.displayname, id: y.id }); break;
case '</person>': break;
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': case '<extLst/>': break;
/* 18.2.7 ext CT_Extension + */
case '<ext': pass=true; break;
case '</ext>': pass=false; break;
default: if(!pass && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in threaded comments');
}
return x;
});
return out;
}
function write_people_xml(people/*, opts*/) {
var o = [XML_HEADER, writextag('personList', null, {
'xmlns': XMLNS.TCMNT,
'xmlns:x': XMLNS_main[0]
}).replace(/[\/]>/, ">")];
people.forEach(function(person, idx) {
o.push(writextag('person', null, {
displayName: person,
id: "{54EE7950-7262-4200-6969-" + ("000000000000" + idx).slice(-12) + "}",
userId: person,
providerId: "None"
}));
});
o.push("</personList>");
return o.join("");
}

@ -29,7 +29,7 @@ function parse_comments_bin(data, opts)/*:Array<RawComment>*/ {
var authors/*:Array<string>*/ = [];
var c = {};
var pass = false;
recordhopper(data, function hopper_cmnt(val, R, RT) {
recordhopper(data, function hopper_cmnt(val, R_n, RT) {
switch(RT) {
case 0x0278: /* 'BrtCommentAuthor' */
authors.push(val); break;
@ -56,8 +56,9 @@ function parse_comments_bin(data, opts)/*:Array<RawComment>*/ {
default:
if(R.T){/* empty */}
else if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
if((R_n||"").indexOf("Begin") > 0){/* empty */}
else if((R_n||"").indexOf("End") > 0){/* empty */}
else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
}
});
return out;
@ -66,39 +67,31 @@ function parse_comments_bin(data, opts)/*:Array<RawComment>*/ {
function write_comments_bin(data/*::, opts*/) {
var ba = buf_array();
var iauthor/*:Array<string>*/ = [];
write_record(ba, 0x0274 /* BrtBeginComments */);
write_record(ba, "BrtBeginComments");
write_record(ba, 0x0276 /* BrtBeginCommentAuthors */);
write_record(ba, "BrtBeginCommentAuthors");
data.forEach(function(comment) {
comment[1].forEach(function(c) {
if(iauthor.indexOf(c.a) > -1) return;
iauthor.push(c.a.slice(0,54));
write_record(ba, 0x0278 /* BrtCommentAuthor */, write_BrtCommentAuthor(c.a));
if(c.T && c.ID && iauthor.indexOf("tc=" + c.ID) == -1) {
iauthor.push("tc=" + c.ID);
write_record(ba, 0x0278 /* BrtCommentAuthor */, write_BrtCommentAuthor("tc=" + c.ID));
}
write_record(ba, "BrtCommentAuthor", write_BrtCommentAuthor(c.a));
});
});
write_record(ba, 0x0277 /* BrtEndCommentAuthors */);
write_record(ba, "BrtEndCommentAuthors");
write_record(ba, 0x0279 /* BrtBeginCommentList */);
write_record(ba, "BrtBeginCommentList");
data.forEach(function(comment) {
comment[1].forEach(function(c) {
var _ia = -1;
if(c.ID) _ia = iauthor.indexOf("tc=" + c.ID);
if(_ia == -1 && comment[1][0].T && comment[1][0].ID) _ia = iauthor.indexOf("tc=" + comment[1][0].ID);
if(_ia == -1) _ia = iauthor.indexOf(c.a);
c.iauthor = _ia;
c.iauthor = iauthor.indexOf(c.a);
var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])};
write_record(ba, 0x027B /* BrtBeginComment */, write_BrtBeginComment([range, c]));
if(c.t && c.t.length > 0) write_record(ba, 0x027D /* BrtCommentText */, write_BrtCommentText(c));
write_record(ba, 0x027C /* BrtEndComment */);
write_record(ba, "BrtBeginComment", write_BrtBeginComment([range, c]));
if(c.t && c.t.length > 0) write_record(ba, "BrtCommentText", write_BrtCommentText(c));
write_record(ba, "BrtEndComment");
delete c.iauthor;
});
});
write_record(ba, 0x027A /* BrtEndCommentList */);
write_record(ba, "BrtEndCommentList");
write_record(ba, 0x0275 /* BrtEndComments */);
write_record(ba, "BrtEndComments");
return ba.end();
}

@ -1,21 +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 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 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);
});
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);
});
}
var VBAFMTS = ["xlsb", "xlsm", "xlam", "biff8", "xla"];
var VBAFMTS = [ "xlsb", "xlsm", "xlam", "biff8", "xla" ];

@ -1,3 +1,6 @@
RELS.DS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet";
RELS.MS = "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet";
/* macro and dialog sheet stubs */
function parse_ds_bin(/*::data:any, opts, idx:number, rels, wb, themes, styles*/)/*:Worksheet*/ { return {'!type':'dialog'}; }
function parse_ds_xml(/*::data:any, opts, idx:number, rels, wb, themes, styles*/)/*:Worksheet*/ { return {'!type':'dialog'}; }

@ -1,5 +1,5 @@
/* TODO: it will be useful to parse the function str */
var rc_to_a1 = /*#__PURE__*/(function(){
var rc_to_a1 = (function(){
var rcregex = /(^|[^A-Za-z_])R(\[?-?\d+\]|[1-9]\d*|)C(\[?-?\d+\]|[1-9]\d*|)(?![A-Za-z0-9_])/g;
var rcbase/*:Cell*/ = ({r:0,c:0}/*:any*/);
function rcfunc($$,$1,$2,$3) {
@ -23,17 +23,14 @@ var rc_to_a1 = /*#__PURE__*/(function(){
};
})();
var crefregex = /(^|[^._A-Z0-9])(\$?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])(\$?)(\d{1,7})(?![_.\(A-Za-z0-9])/g;
try {
crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)(10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})(?![_.\(A-Za-z0-9])/g;
}catch(e){}
var a1_to_rc = /*#__PURE__*/(function(){
var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)(10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})(?![_.\(A-Za-z0-9])/g;
var a1_to_rc =(function(){
return function a1_to_rc(fstr/*:string*/, base/*:CellAddress*/) {
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
var c = decode_col($3) - ($2 ? 0 : base.c);
var r = decode_row($5) - ($4 ? 0 : base.r);
var R = $4 == "$" ? (r+1) : (r == 0 ? "" : "[" + r + "]");
var C = $2 == "$" ? (c+1) : (c == 0 ? "" : "[" + c + "]");
var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1));
var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1));
return $1 + "R" + R + "C" + C;
});
};

@ -495,113 +495,114 @@ function parse_PtgAttrNoop(blob/*::, length, opts*/) {
/* [MS-XLS] 2.5.198.25 ; [MS-XLSB] 2.5.97.16 */
var PtgTypes = {
0x01: { n:'PtgExp', f:parse_PtgExp },
0x02: { n:'PtgTbl', f:parse_PtgTbl },
0x03: { n:'PtgAdd', f:parseread1 },
0x04: { n:'PtgSub', f:parseread1 },
0x05: { n:'PtgMul', f:parseread1 },
0x06: { n:'PtgDiv', f:parseread1 },
0x07: { n:'PtgPower', f:parseread1 },
0x08: { n:'PtgConcat', f:parseread1 },
0x09: { n:'PtgLt', f:parseread1 },
0x0A: { n:'PtgLe', f:parseread1 },
0x0B: { n:'PtgEq', f:parseread1 },
0x0C: { n:'PtgGe', f:parseread1 },
0x0D: { n:'PtgGt', f:parseread1 },
0x0E: { n:'PtgNe', f:parseread1 },
0x0F: { n:'PtgIsect', f:parseread1 },
0x10: { n:'PtgUnion', f:parseread1 },
0x11: { n:'PtgRange', f:parseread1 },
0x12: { n:'PtgUplus', f:parseread1 },
0x13: { n:'PtgUminus', f:parseread1 },
0x14: { n:'PtgPercent', f:parseread1 },
0x15: { n:'PtgParen', f:parseread1 },
0x16: { n:'PtgMissArg', f:parseread1 },
0x17: { n:'PtgStr', f:parse_PtgStr },
0x1A: { n:'PtgSheet', f:parse_PtgSheet },
0x1B: { n:'PtgEndSheet', f:parse_PtgEndSheet },
0x1C: { n:'PtgErr', f:parse_PtgErr },
0x1D: { n:'PtgBool', f:parse_PtgBool },
0x1E: { n:'PtgInt', f:parse_PtgInt },
0x1F: { n:'PtgNum', f:parse_PtgNum },
0x20: { n:'PtgArray', f:parse_PtgArray },
0x21: { n:'PtgFunc', f:parse_PtgFunc },
0x22: { n:'PtgFuncVar', f:parse_PtgFuncVar },
0x23: { n:'PtgName', f:parse_PtgName },
0x24: { n:'PtgRef', f:parse_PtgRef },
0x25: { n:'PtgArea', f:parse_PtgArea },
0x26: { n:'PtgMemArea', f:parse_PtgMemArea },
0x27: { n:'PtgMemErr', f:parse_PtgMemErr },
0x28: { n:'PtgMemNoMem', f:parse_PtgMemNoMem },
0x29: { n:'PtgMemFunc', f:parse_PtgMemFunc },
0x2A: { n:'PtgRefErr', f:parse_PtgRefErr },
0x2B: { n:'PtgAreaErr', f:parse_PtgAreaErr },
0x2C: { n:'PtgRefN', f:parse_PtgRefN },
0x2D: { n:'PtgAreaN', f:parse_PtgAreaN },
0x2E: { n:'PtgMemAreaN', f:parse_PtgMemAreaN },
0x2F: { n:'PtgMemNoMemN', f:parse_PtgMemNoMemN },
0x39: { n:'PtgNameX', f:parse_PtgNameX },
0x3A: { n:'PtgRef3d', f:parse_PtgRef3d },
0x3B: { n:'PtgArea3d', f:parse_PtgArea3d },
0x3C: { n:'PtgRefErr3d', f:parse_PtgRefErr3d },
0x3D: { n:'PtgAreaErr3d', f:parse_PtgAreaErr3d },
0xFF: {}
/*::[*/0x01/*::]*/: { n:'PtgExp', f:parse_PtgExp },
/*::[*/0x02/*::]*/: { n:'PtgTbl', f:parse_PtgTbl },
/*::[*/0x03/*::]*/: { n:'PtgAdd', f:parseread1 },
/*::[*/0x04/*::]*/: { n:'PtgSub', f:parseread1 },
/*::[*/0x05/*::]*/: { n:'PtgMul', f:parseread1 },
/*::[*/0x06/*::]*/: { n:'PtgDiv', f:parseread1 },
/*::[*/0x07/*::]*/: { n:'PtgPower', f:parseread1 },
/*::[*/0x08/*::]*/: { n:'PtgConcat', f:parseread1 },
/*::[*/0x09/*::]*/: { n:'PtgLt', f:parseread1 },
/*::[*/0x0A/*::]*/: { n:'PtgLe', f:parseread1 },
/*::[*/0x0B/*::]*/: { n:'PtgEq', f:parseread1 },
/*::[*/0x0C/*::]*/: { n:'PtgGe', f:parseread1 },
/*::[*/0x0D/*::]*/: { n:'PtgGt', f:parseread1 },
/*::[*/0x0E/*::]*/: { n:'PtgNe', f:parseread1 },
/*::[*/0x0F/*::]*/: { n:'PtgIsect', f:parseread1 },
/*::[*/0x10/*::]*/: { n:'PtgUnion', f:parseread1 },
/*::[*/0x11/*::]*/: { n:'PtgRange', f:parseread1 },
/*::[*/0x12/*::]*/: { n:'PtgUplus', f:parseread1 },
/*::[*/0x13/*::]*/: { n:'PtgUminus', f:parseread1 },
/*::[*/0x14/*::]*/: { n:'PtgPercent', f:parseread1 },
/*::[*/0x15/*::]*/: { n:'PtgParen', f:parseread1 },
/*::[*/0x16/*::]*/: { n:'PtgMissArg', f:parseread1 },
/*::[*/0x17/*::]*/: { n:'PtgStr', f:parse_PtgStr },
/*::[*/0x1A/*::]*/: { n:'PtgSheet', f:parse_PtgSheet },
/*::[*/0x1B/*::]*/: { n:'PtgEndSheet', f:parse_PtgEndSheet },
/*::[*/0x1C/*::]*/: { n:'PtgErr', f:parse_PtgErr },
/*::[*/0x1D/*::]*/: { n:'PtgBool', f:parse_PtgBool },
/*::[*/0x1E/*::]*/: { n:'PtgInt', f:parse_PtgInt },
/*::[*/0x1F/*::]*/: { n:'PtgNum', f:parse_PtgNum },
/*::[*/0x20/*::]*/: { n:'PtgArray', f:parse_PtgArray },
/*::[*/0x21/*::]*/: { n:'PtgFunc', f:parse_PtgFunc },
/*::[*/0x22/*::]*/: { n:'PtgFuncVar', f:parse_PtgFuncVar },
/*::[*/0x23/*::]*/: { n:'PtgName', f:parse_PtgName },
/*::[*/0x24/*::]*/: { n:'PtgRef', f:parse_PtgRef },
/*::[*/0x25/*::]*/: { n:'PtgArea', f:parse_PtgArea },
/*::[*/0x26/*::]*/: { n:'PtgMemArea', f:parse_PtgMemArea },
/*::[*/0x27/*::]*/: { n:'PtgMemErr', f:parse_PtgMemErr },
/*::[*/0x28/*::]*/: { n:'PtgMemNoMem', f:parse_PtgMemNoMem },
/*::[*/0x29/*::]*/: { n:'PtgMemFunc', f:parse_PtgMemFunc },
/*::[*/0x2A/*::]*/: { n:'PtgRefErr', f:parse_PtgRefErr },
/*::[*/0x2B/*::]*/: { n:'PtgAreaErr', f:parse_PtgAreaErr },
/*::[*/0x2C/*::]*/: { n:'PtgRefN', f:parse_PtgRefN },
/*::[*/0x2D/*::]*/: { n:'PtgAreaN', f:parse_PtgAreaN },
/*::[*/0x2E/*::]*/: { n:'PtgMemAreaN', f:parse_PtgMemAreaN },
/*::[*/0x2F/*::]*/: { n:'PtgMemNoMemN', f:parse_PtgMemNoMemN },
/*::[*/0x39/*::]*/: { n:'PtgNameX', f:parse_PtgNameX },
/*::[*/0x3A/*::]*/: { n:'PtgRef3d', f:parse_PtgRef3d },
/*::[*/0x3B/*::]*/: { n:'PtgArea3d', f:parse_PtgArea3d },
/*::[*/0x3C/*::]*/: { n:'PtgRefErr3d', f:parse_PtgRefErr3d },
/*::[*/0x3D/*::]*/: { n:'PtgAreaErr3d', f:parse_PtgAreaErr3d },
/*::[*/0xFF/*::]*/: {}
};
/* These are duplicated in the PtgTypes table */
var PtgDupes = {
0x40: 0x20, 0x60: 0x20,
0x41: 0x21, 0x61: 0x21,
0x42: 0x22, 0x62: 0x22,
0x43: 0x23, 0x63: 0x23,
0x44: 0x24, 0x64: 0x24,
0x45: 0x25, 0x65: 0x25,
0x46: 0x26, 0x66: 0x26,
0x47: 0x27, 0x67: 0x27,
0x48: 0x28, 0x68: 0x28,
0x49: 0x29, 0x69: 0x29,
0x4A: 0x2A, 0x6A: 0x2A,
0x4B: 0x2B, 0x6B: 0x2B,
0x4C: 0x2C, 0x6C: 0x2C,
0x4D: 0x2D, 0x6D: 0x2D,
0x4E: 0x2E, 0x6E: 0x2E,
0x4F: 0x2F, 0x6F: 0x2F,
0x58: 0x22, 0x78: 0x22,
0x59: 0x39, 0x79: 0x39,
0x5A: 0x3A, 0x7A: 0x3A,
0x5B: 0x3B, 0x7B: 0x3B,
0x5C: 0x3C, 0x7C: 0x3C,
0x5D: 0x3D, 0x7D: 0x3D
/*::[*/0x40/*::]*/: 0x20, /*::[*/0x60/*::]*/: 0x20,
/*::[*/0x41/*::]*/: 0x21, /*::[*/0x61/*::]*/: 0x21,
/*::[*/0x42/*::]*/: 0x22, /*::[*/0x62/*::]*/: 0x22,
/*::[*/0x43/*::]*/: 0x23, /*::[*/0x63/*::]*/: 0x23,
/*::[*/0x44/*::]*/: 0x24, /*::[*/0x64/*::]*/: 0x24,
/*::[*/0x45/*::]*/: 0x25, /*::[*/0x65/*::]*/: 0x25,
/*::[*/0x46/*::]*/: 0x26, /*::[*/0x66/*::]*/: 0x26,
/*::[*/0x47/*::]*/: 0x27, /*::[*/0x67/*::]*/: 0x27,
/*::[*/0x48/*::]*/: 0x28, /*::[*/0x68/*::]*/: 0x28,
/*::[*/0x49/*::]*/: 0x29, /*::[*/0x69/*::]*/: 0x29,
/*::[*/0x4A/*::]*/: 0x2A, /*::[*/0x6A/*::]*/: 0x2A,
/*::[*/0x4B/*::]*/: 0x2B, /*::[*/0x6B/*::]*/: 0x2B,
/*::[*/0x4C/*::]*/: 0x2C, /*::[*/0x6C/*::]*/: 0x2C,
/*::[*/0x4D/*::]*/: 0x2D, /*::[*/0x6D/*::]*/: 0x2D,
/*::[*/0x4E/*::]*/: 0x2E, /*::[*/0x6E/*::]*/: 0x2E,
/*::[*/0x4F/*::]*/: 0x2F, /*::[*/0x6F/*::]*/: 0x2F,
/*::[*/0x58/*::]*/: 0x22, /*::[*/0x78/*::]*/: 0x22,
/*::[*/0x59/*::]*/: 0x39, /*::[*/0x79/*::]*/: 0x39,
/*::[*/0x5A/*::]*/: 0x3A, /*::[*/0x7A/*::]*/: 0x3A,
/*::[*/0x5B/*::]*/: 0x3B, /*::[*/0x7B/*::]*/: 0x3B,
/*::[*/0x5C/*::]*/: 0x3C, /*::[*/0x7C/*::]*/: 0x3C,
/*::[*/0x5D/*::]*/: 0x3D, /*::[*/0x7D/*::]*/: 0x3D
};
(function(){for(var y in PtgDupes) PtgTypes[y] = PtgTypes[PtgDupes[y]];})();
var Ptg18 = {
0x01: { n:'PtgElfLel', f:parse_PtgElfLel },
0x02: { n:'PtgElfRw', f:parse_PtgElfRw },
0x03: { n:'PtgElfCol', f:parse_PtgElfCol },
0x06: { n:'PtgElfRwV', f:parse_PtgElfRwV },
0x07: { n:'PtgElfColV', f:parse_PtgElfColV },
0x0A: { n:'PtgElfRadical', f:parse_PtgElfRadical },
0x0B: { n:'PtgElfRadicalS', f:parse_PtgElfRadicalS },
0x0D: { n:'PtgElfColS', f:parse_PtgElfColS },
0x0F: { n:'PtgElfColSV', f:parse_PtgElfColSV },
0x10: { n:'PtgElfRadicalLel', f:parse_PtgElfRadicalLel },
0x19: { n:'PtgList', f:parse_PtgList },
0x1D: { n:'PtgSxName', f:parse_PtgSxName },
0xFF: {}
/*::[*/0x01/*::]*/: { n:'PtgElfLel', f:parse_PtgElfLel },
/*::[*/0x02/*::]*/: { n:'PtgElfRw', f:parse_PtgElfRw },
/*::[*/0x03/*::]*/: { n:'PtgElfCol', f:parse_PtgElfCol },
/*::[*/0x06/*::]*/: { n:'PtgElfRwV', f:parse_PtgElfRwV },
/*::[*/0x07/*::]*/: { n:'PtgElfColV', f:parse_PtgElfColV },
/*::[*/0x0A/*::]*/: { n:'PtgElfRadical', f:parse_PtgElfRadical },
/*::[*/0x0B/*::]*/: { n:'PtgElfRadicalS', f:parse_PtgElfRadicalS },
/*::[*/0x0D/*::]*/: { n:'PtgElfColS', f:parse_PtgElfColS },
/*::[*/0x0F/*::]*/: { n:'PtgElfColSV', f:parse_PtgElfColSV },
/*::[*/0x10/*::]*/: { n:'PtgElfRadicalLel', f:parse_PtgElfRadicalLel },
/*::[*/0x19/*::]*/: { n:'PtgList', f:parse_PtgList },
/*::[*/0x1D/*::]*/: { n:'PtgSxName', f:parse_PtgSxName },
/*::[*/0xFF/*::]*/: {}
};
var Ptg19 = {
0x00: { n:'PtgAttrNoop', f:parse_PtgAttrNoop },
0x01: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
0x02: { n:'PtgAttrIf', f:parse_PtgAttrIf },
0x04: { n:'PtgAttrChoose', f:parse_PtgAttrChoose },
0x08: { n:'PtgAttrGoto', f:parse_PtgAttrGoto },
0x10: { n:'PtgAttrSum', f:parse_PtgAttrSum },
0x20: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
0x21: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
0x40: { n:'PtgAttrSpace', f:parse_PtgAttrSpace },
0x41: { n:'PtgAttrSpaceSemi', f:parse_PtgAttrSpaceSemi },
0x80: { n:'PtgAttrIfError', f:parse_PtgAttrIfError },
0xFF: {}
/*::[*/0x00/*::]*/: { n:'PtgAttrNoop', f:parse_PtgAttrNoop },
/*::[*/0x01/*::]*/: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
/*::[*/0x02/*::]*/: { n:'PtgAttrIf', f:parse_PtgAttrIf },
/*::[*/0x04/*::]*/: { n:'PtgAttrChoose', f:parse_PtgAttrChoose },
/*::[*/0x08/*::]*/: { n:'PtgAttrGoto', f:parse_PtgAttrGoto },
/*::[*/0x10/*::]*/: { n:'PtgAttrSum', f:parse_PtgAttrSum },
/*::[*/0x20/*::]*/: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
/*::[*/0x40/*::]*/: { n:'PtgAttrSpace', f:parse_PtgAttrSpace },
/*::[*/0x41/*::]*/: { n:'PtgAttrSpaceSemi', f:parse_PtgAttrSpaceSemi },
/*::[*/0x80/*::]*/: { n:'PtgAttrIfError', f:parse_PtgAttrIfError },
/*::[*/0xFF/*::]*/: {}
};
Ptg19[0x21] = Ptg19[0x20];
/* [MS-XLS] 2.5.198.103 ; [MS-XLSB] 2.5.97.87 */
function parse_RgbExtra(blob, length, rgce, opts) {
@ -645,7 +646,7 @@ function parse_Rgce(blob, length, opts) {
while(target != blob.l) {
length = target - blob.l;
id = blob[blob.l];
R = PtgTypes[id] || PtgTypes[PtgDupes[id]];
R = PtgTypes[id];
if(id === 0x18 || id === 0x19) R = (id === 0x18 ? Ptg18 : Ptg19)[blob[blob.l + 1]];
if(!R || !R.f) { /*ptgs.push*/(parsenoop(blob, length)); }
else { ptgs.push([R.n, R.f(blob, length, opts)]); }
@ -688,15 +689,13 @@ var PtgBinOp = {
PtgSub: "-"
};
// TODO: explore space
function make_3d_range(start, end) {
var s = start.lastIndexOf("!"), e = end.lastIndexOf("!");
if(s == -1 && e == -1) return start + ":" + end;
if(s > 0 && e > 0 && start.slice(0, s).toLowerCase() == end.slice(0, e).toLowerCase()) return start + ":" + end.slice(e+1);
console.error("Cannot hydrate range", start, end);
return start + ":" + end;
// List of invalid characters needs to be tested further
var quoteCharacters /*:RegExp */ = new RegExp(/[^\w\u4E00-\u9FFF\u3040-\u30FF]/);
function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ {
if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name");
if (quoteCharacters.test(sname)) return "'" + sname + "'";
return sname;
}
function get_ixti_raw(supbooks, ixti/*:number*/, opts)/*:string*/ {
if(!supbooks) return "SH33TJSERR0";
if(opts.biff > 8 && (!supbooks.XTI || !supbooks.XTI[ixti])) return supbooks.SheetNames[ixti];
@ -732,8 +731,7 @@ function get_ixti_raw(supbooks, ixti/*:number*/, opts)/*:string*/ {
}
}
function get_ixti(supbooks, ixti/*:number*/, opts)/*:string*/ {
var ixtiraw = get_ixti_raw(supbooks, ixti, opts);
return ixtiraw == "#REF" ? ixtiraw : formula_quote_sheet_name(ixtiraw, opts);
return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts), opts);
}
function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, opts)/*:string*/ {
var biff = (opts && opts.biff) || 8;
@ -793,7 +791,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
break;
case 'PtgRange': /* [MS-XLS] 2.5.198.83 */
e1 = stack.pop(); e2 = stack.pop();
stack.push(make_3d_range(e2,e1));
stack.push(e2+":"+e1);
break;
case 'PtgAttrChoose': /* [MS-XLS] 2.5.198.34 */
@ -870,8 +868,7 @@ function stringify_formula(formula/*Array<any>*/, 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);
/* [MS-XLSB] 2.5.97.10 Ftab -- last verified 20220204 */
if(name && name.slice(0,6) == "_xlfn." && !opts.xlfn) name = name.slice(6);
if(name in XLSXFutureFunctions) name = XLSXFutureFunctions[name];
stack.push(name);
break;
@ -894,7 +891,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
if(supbooks[bookidx] && supbooks[bookidx][nameidx]) o += supbooks[bookidx][nameidx].Name;
else if(supbooks[0] && supbooks[0][nameidx]) o += supbooks[0][nameidx].Name;
else {
var ixtidata = (get_ixti_raw(supbooks, bookidx, opts)||"").split(";;");
var ixtidata = get_ixti_raw(supbooks, bookidx, opts).split(";;");
if(ixtidata[nameidx - 1]) o = ixtidata[nameidx - 1]; // TODO: confirm this is correct
else o += "SH33TJSERRX";
}
@ -938,7 +935,8 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
if(supbooks.sharedf[encode_cell(c)]) {
var parsedf = (supbooks.sharedf[encode_cell(c)]);
stack.push(stringify_formula(parsedf, _range, q, supbooks, opts));
} else {
}
else {
var fnd = false;
for(e1=0;e1!=supbooks.arrayf.length; ++e1) {
/* TODO: should be something like range_has */
@ -1041,7 +1039,6 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
}
}
if(stack.length > 1 && opts.WTF) throw new Error("bad formula stack");
if(stack[0] == "TRUE") return true; if(stack[0] == "FALSE") return false;
return stack[0];
}

@ -68,7 +68,8 @@ function write_FormulaValue(value) {
/* [MS-XLS] 2.4.127 TODO */
function parse_Formula(blob, length, opts) {
var end = blob.l + length;
var cell = parse_XLSCell(blob, 6, opts);
var cell = parse_XLSCell(blob, 6);
if(opts.biff == 2) ++blob.l;
var val = parse_FormulaValue(blob,8);
var flags = blob.read_shift(1);
if(opts.biff != 2) {
@ -123,209 +124,3 @@ var parse_XLSBCellParsedFormula = parse_XLSBParsedFormula;
var parse_XLSBNameParsedFormula = parse_XLSBParsedFormula;
/* [MS-XLSB] 2.5.97.98 SharedParsedFormula */
var parse_XLSBSharedParsedFormula = parse_XLSBParsedFormula;
/* Writes a PtgNum or PtgInt */
function write_XLSBFormulaNum(val/*:number*/) {
if((val | 0) == val && val < Math.pow(2,16) && val >= 0) {
var oint = new_buf(11);
oint.write_shift(4, 3);
oint.write_shift(1, 0x1e);
oint.write_shift(2, val);
oint.write_shift(4, 0);
return oint;
}
var num = new_buf(17);
num.write_shift(4, 11);
num.write_shift(1, 0x1f);
num.write_shift(8, val);
num.write_shift(4, 0);
return num;
}
/* Writes a PtgErr */
function write_XLSBFormulaErr(val/*:number*/) {
var oint = new_buf(10);
oint.write_shift(4, 2);
oint.write_shift(1, 0x1C);
oint.write_shift(1, val);
oint.write_shift(4, 0);
return oint;
}
/* Writes a PtgBool */
function write_XLSBFormulaBool(val/*:boolean*/) {
var oint = new_buf(10);
oint.write_shift(4, 2);
oint.write_shift(1, 0x1D);
oint.write_shift(1, val?1:0);
oint.write_shift(4, 0);
return oint;
}
/* Writes a PtgStr */
function write_XLSBFormulaStr(val/*:string*/) {
var preamble = new_buf(7);
preamble.write_shift(4, 3 + 2 * val.length);
preamble.write_shift(1, 0x17);
preamble.write_shift(2, val.length);
var body = new_buf(2 * val.length);
body.write_shift(2 * val.length, val, "utf16le");
var postamble = new_buf(4);
postamble.write_shift(4, 0);
return bconcat([preamble, body, postamble]);
}
/* Writes a PtgRef */
function write_XLSBFormulaRef(str) {
var cell = decode_cell(str);
var out = new_buf(15);
out.write_shift(4, 7);
out.write_shift(1, 0x04 | ((1)<<5));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
out.write_shift(4, 0);
return out;
}
/* Writes a PtgRef3d */
function write_XLSBFormulaRef3D(str, wb) {
var lastbang = str.lastIndexOf("!");
var sname = str.slice(0, lastbang);
str = str.slice(lastbang+1);
var cell = decode_cell(str);
if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
var out = new_buf(17);
out.write_shift(4, 9);
out.write_shift(1, 0x1A | ((1)<<5));
out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase()));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
out.write_shift(4, 0);
return out;
}
/* Writes a PtgRefErr3d */
function write_XLSBFormulaRefErr3D(str, wb) {
var lastbang = str.lastIndexOf("!");
var sname = str.slice(0, lastbang);
str = str.slice(lastbang+1);
if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
var out = new_buf(17);
out.write_shift(4, 9);
out.write_shift(1, 0x1C | ((1)<<5));
out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase()));
out.write_shift(4, 0);
out.write_shift(2, 0); // <== ColRelShort
out.write_shift(4, 0);
return out;
}
/* Writes a single sheet range [PtgRef PtgRef PtgRange] */
function write_XLSBFormulaRange(_str) {
var parts = _str.split(":"), str = parts[0];
var out = new_buf(23);
out.write_shift(4, 15);
/* start cell */
str = parts[0]; var cell = decode_cell(str);
out.write_shift(1, 0x04 | ((1)<<5));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
out.write_shift(4, 0);
/* end cell */
str = parts[1]; cell = decode_cell(str);
out.write_shift(1, 0x04 | ((1)<<5));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
out.write_shift(4, 0);
/* PtgRange */
out.write_shift(1, 0x11);
out.write_shift(4, 0);
return out;
}
/* Writes a range with explicit sheet name [PtgRef3D PtgRef3D PtgRange] */
function write_XLSBFormulaRangeWS(_str, wb) {
var lastbang = _str.lastIndexOf("!");
var sname = _str.slice(0, lastbang);
_str = _str.slice(lastbang+1);
if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
var parts = _str.split(":");
var out = new_buf(27);
out.write_shift(4, 19);
/* start cell */
var str = parts[0], cell = decode_cell(str);
out.write_shift(1, 0x1A | ((1)<<5));
out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase()));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
/* end cell */
str = parts[1]; cell = decode_cell(str);
out.write_shift(1, 0x1A | ((1)<<5));
out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase()));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
/* PtgRange */
out.write_shift(1, 0x11);
out.write_shift(4, 0);
return out;
}
/* Writes a range with explicit sheet name [PtgArea3d] */
function write_XLSBFormulaArea3D(_str, wb) {
var lastbang = _str.lastIndexOf("!");
var sname = _str.slice(0, lastbang);
_str = _str.slice(lastbang+1);
if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
var range = decode_range(_str);
var out = new_buf(23);
out.write_shift(4, 15);
out.write_shift(1, 0x1B | ((1)<<5));
out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase()));
out.write_shift(4, range.s.r);
out.write_shift(4, range.e.r);
out.write_shift(2, range.s.c);
out.write_shift(2, range.e.c);
out.write_shift(4, 0);
return out;
}
/* General Formula */
function write_XLSBFormula(val/*:string|number*/, wb) {
if(typeof val == "number") return write_XLSBFormulaNum(val);
if(typeof val == "boolean") return write_XLSBFormulaBool(val);
if(/^#(DIV\/0!|GETTING_DATA|N\/A|NAME\?|NULL!|NUM!|REF!|VALUE!)$/.test(val)) return write_XLSBFormulaErr(+RBErr[val]);
if(val.match(/^\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaRef(val);
if(val.match(/^\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5}):\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaRange(val);
if(val.match(/^#REF!\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5}):\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaArea3D(val, wb);
if(val.match(/^(?:'[^\\\/?*\[\]:]*'|[^'][^\\\/?*\[\]:'`~!@#$%^()\-=+{}|;,<.>]*)!\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaRef3D(val, wb);
if(val.match(/^(?:'[^\\\/?*\[\]:]*'|[^'][^\\\/?*\[\]:'`~!@#$%^()\-=+{}|;,<.>]*)!\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5}):\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaRangeWS(val, wb);
if(/^(?:'[^\\\/?*\[\]:]*'|[^'][^\\\/?*\[\]:'`~!@#$%^()\-=+{}|;,<.>]*)!#REF!$/.test(val)) return write_XLSBFormulaRefErr3D(val, wb);
if(/^".*"$/.test(val)) return write_XLSBFormulaStr(val);
if(/^[+-]\d+$/.test(val)) return write_XLSBFormulaNum(parseInt(val, 10));
throw "Formula |" + val + "| not supported for XLSB";
}
var write_XLSBNameParsedFormula = write_XLSBFormula;

File diff suppressed because it is too large Load Diff

@ -9,8 +9,6 @@ function ods_to_csf_formula(f/*:string*/)/*:string*/ {
f = f.replace(/COM\.MICROSOFT\./g, "");
/* Part 3 Section 5.8 References */
f = f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, function($$, $1) { return $1.replace(/\./g,""); });
f = f.replace(/\$'([^']|'')+'/g, function($$) { return $$.slice(1); });
f = f.replace(/\$([^\]\. #$]+)/g, function($$, $1) { return ($1).match(/^([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])?(10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})?$/) ? $$ : $1; });
/* TODO: something other than this */
f = f.replace(/\[.(#[A-Z]*[?!])\]/g, "$1");
return f.replace(/[;~]/g,",").replace(/\|/g,";");
@ -23,14 +21,12 @@ function csf_to_ods_formula(f/*:string*/)/*:string*/ {
}
function ods_to_csf_3D(r/*:string*/)/*:[string, string]*/ {
r = r.replace(/\$'([^']|'')+'/g, function($$) { return $$.slice(1); });
r = r.replace(/\$([^\]\. #$]+)/g, function($$, $1) { return ($1).match(/^([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])?(10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})?$/) ? $$ : $1; });
var a = r.split(":");
var s = a[0].split(".")[0];
return [s, a[0].split(".")[1] + (a.length > 1 ? (":" + (a[1].split(".")[1] || a[1].split(".")[0])) : "")];
}
function csf_to_ods_3D(r/*:string*/)/*:string*/ {
return r.replace(/!/,".").replace(/:/, ":.");
return r.replace(/\./,"!");
}

@ -1,6 +1,10 @@
var strs = {}; // shared strings
var _ssfopts = {}; // spreadsheet formatting options
RELS.WS = [
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
"http://purl.oclc.org/ooxml/officeDocument/relationships/worksheet"
];
/*global Map */
var browser_has_Map = typeof Map !== 'undefined';
@ -41,7 +45,6 @@ function col_obj_w(C/*:number*/, col) {
if(wch > -1) { p.width = char2width(wch); p.customWidth = 1; }
else if(col.width != null) p.width = col.width;
if(col.hidden) p.hidden = true;
if(col.level != null) { p.outlineLevel = p.level = col.level; }
return p;
}
@ -62,7 +65,7 @@ function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) {
var i = 0x3c, len = styles.length;
if(z == null && opts.ssf) {
for(; i < 0x188; ++i) if(opts.ssf[i] == null) {
SSF__load(cell.z, i);
SSF.load(cell.z, i);
// $FlowIgnore
opts.ssf[i] = cell.z;
opts.revssf[cell.z] = z = i;
@ -81,30 +84,30 @@ function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) {
return len;
}
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles, date1904) {
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) {
try {
if(opts.cellNF) p.z = table_fmt[fmtid];
if(opts.cellNF) p.z = SSF._table[fmtid];
} catch(e) { if(opts.WTF) throw e; }
if(p.t === 'z' && !opts.cellStyles) return;
if(p.t === 'z') return;
if(p.t === 'd' && typeof p.v === 'string') p.v = parseDate(p.v);
if((!opts || opts.cellText !== false) && p.t !== 'z') try {
if(table_fmt[fmtid] == null) SSF__load(SSFImplicit[fmtid] || "General", fmtid);
if(!opts || opts.cellText !== false) try {
if(SSF._table[fmtid] == null) SSF.load(SSFImplicit[fmtid] || "General", fmtid);
if(p.t === 'e') p.w = p.w || BErr[p.v];
else if(fmtid === 0) {
if(p.t === 'n') {
if((p.v|0) === p.v) p.w = p.v.toString(10);
else p.w = SSF_general_num(p.v);
if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
else p.w = SSF._general_num(p.v);
}
else if(p.t === 'd') {
var dd = datenum(p.v, !!date1904);
if((dd|0) === dd) p.w = dd.toString(10);
else p.w = SSF_general_num(dd);
var dd = datenum(p.v);
if((dd|0) === dd) p.w = SSF._general_int(dd);
else p.w = SSF._general_num(dd);
}
else if(p.v === undefined) return "";
else p.w = SSF_general(p.v,_ssfopts);
else p.w = SSF._general(p.v,_ssfopts);
}
else if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v, !!date1904),_ssfopts);
else p.w = SSF_format(fmtid,p.v,_ssfopts);
else if(p.t === 'd') p.w = SSF.format(fmtid,datenum(p.v),_ssfopts);
else p.w = SSF.format(fmtid,p.v,_ssfopts);
} catch(e) { if(opts.WTF) throw e; }
if(!opts.cellStyles) return;
if(fillid != null) try {

@ -2,13 +2,15 @@ function parse_ws_xml_dim(ws/*:Worksheet*/, s/*:string*/) {
var d = safe_decode_range(s);
if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d);
}
var mergecregex = /<(?:\w+:)?mergeCell ref=["'][A-Z0-9:]+['"]\s*[\/]?>/g;
var hlinkregex = /<(?:\w+:)?hyperlink [^<>]*>/mg;
var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*[\/]?>/g;
var sheetdataregex = /<(?:\w+:)?sheetData[^>]*>([\s\S]*)<\/(?:\w+:)?sheetData>/;
var hlinkregex = /<(?:\w:)?hyperlink [^>]*>/mg;
var dimregex = /"(\w*:\w*)"/;
var colregex = /<(?:\w+:)?col\b[^<>]*[\/]?>/g;
var afregex = /<(?:\w+:)?autoFilter[^>]*/g;
var marginregex= /<(?:\w+:)?pageMargins[^<>]*\/>/g;
var sheetprregex = /<(?:\w+:)?sheetPr\b[^<>]*?\/>/;
var colregex = /<(?:\w:)?col\b[^>]*[\/]?>/g;
var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g;
var sheetprregex = /<(?:\w:)?sheetPr\b(?:[^>a-z][^>]*)?\/>/;
var svsregex = /<(?:\w:)?sheetViews[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetViews)>/;
/* 18.3 Worksheets */
function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ {
@ -17,11 +19,11 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
/* 18.3.1.99 worksheet CT_Worksheet */
var s = ({}/*:any*/); if(opts.dense) s["!data"] = [];
var s = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
var refguess/*:Range*/ = ({s: {r:2000000, c:2000000}, e: {r:0, c:0} }/*:any*/);
var data1 = "", data2 = "";
var mtch/*:?any*/ = str_match_xml_ns(data, "sheetData");
var mtch/*:?any*/ = data.match(sheetdataregex);
if(mtch) {
data1 = data.slice(0, mtch.index);
data2 = data.slice(mtch.index + mtch[0].length);
@ -30,17 +32,16 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
/* 18.3.1.82 sheetPr CT_SheetPr */
var sheetPr = data1.match(sheetprregex);
if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
else if((sheetPr = str_match_xml_ns(data1, "sheetPr"))) parse_ws_xml_sheetpr2(sheetPr[0], sheetPr[1]||"", s, wb, idx, styles, themes);
/* 18.3.1.35 dimension CT_SheetDimension */
var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
if(ridx > 0) {
var ref = data1.slice(ridx,ridx+50).match(dimregex);
if(ref && !(opts && opts.nodim)) parse_ws_xml_dim(s, ref[1]);
if(ref) parse_ws_xml_dim(s, ref[1]);
}
/* 18.3.1.88 sheetViews CT_SheetViews */
var svs = str_match_xml_ns(data1, "sheetViews");
var svs = data1.match(svsregex);
if(svs && svs[1]) parse_ws_xml_sheetviews(svs[1], wb);
/* 18.3.1.17 cols CT_Cols */
@ -52,7 +53,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
}
/* 18.3.1.80 sheetData CT_SheetData ? */
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles, wb);
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
/* 18.3.1.2 autoFilter CT_AutoFilter */
var afilter = data2.match(afregex);
@ -62,7 +63,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
var merges/*:Array<Range>*/ = [];
var _merge = data2.match(mergecregex);
if(_merge) for(ridx = 0; ridx != _merge.length; ++ridx)
merges[ridx] = safe_decode_range(_merge[ridx].slice(_merge[ridx].indexOf("=")+2));
merges[ridx] = safe_decode_range(_merge[ridx].slice(_merge[ridx].indexOf("\"")+1));
/* 18.3.1.48 hyperlinks CT_Hyperlinks */
var hlink = data2.match(hlinkregex);
@ -72,11 +73,6 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
var margins = data2.match(marginregex);
if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));
/* legacyDrawing */
var m;
if((m = data2.match(/legacyDrawing r:id="(.*?)"/))) s['!legrel'] = m[1];
if(opts && opts.nodim) refguess.s.c = refguess.s.r = 0;
if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
if(opts.sheetRows > 0 && s["!ref"]) {
var tmpref = safe_decode_range(s["!ref"]);
@ -92,7 +88,6 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
}
if(columns.length > 0) s["!cols"] = columns;
if(merges.length > 0) s["!merges"] = merges;
if(rels['!id'][s['!legrel']]) s['!legdrawel'] = rels['!id'][s['!legrel']];
return s;
}
@ -109,9 +104,6 @@ function parse_ws_xml_sheetpr(sheetPr/*:string*/, s, wb/*:WBWBProps*/, idx/*:num
if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
if(data.codeName) wb.Sheets[idx].CodeName = unescapexml(utf8read(data.codeName));
}
function parse_ws_xml_sheetpr2(sheetPr/*:string*/, body/*:string*/, s, wb/*:WBWBProps*/, idx/*:number*/) {
parse_ws_xml_sheetpr(sheetPr.slice(0, sheetPr.indexOf(">")), s, wb, idx);
}
function write_ws_xml_sheetpr(ws, wb, idx, opts, o) {
var needed = false;
var props = {}, payload = null;
@ -152,27 +144,27 @@ function write_ws_xml_protection(sp)/*:string*/ {
}
function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
var dense = s["!data"] != null;
var dense = Array.isArray(s);
for(var i = 0; i != data.length; ++i) {
var val = parsexmltag(utf8read(data[i]), true);
if(!val.ref) return;
var rel = ((rels || {})['!id']||[])[val.id];
if(rel) {
val.Target = rel.Target;
if(val.location) val.Target += "#"+unescapexml(val.location);
if(val.location) val.Target += "#"+val.location;
} else {
val.Target = "#" + unescapexml(val.location);
val.Target = "#" + val.location;
rel = {Target: val.Target, TargetMode: 'Internal'};
}
val.Rel = rel;
if(val.tooltip) { val.Tooltip = val.tooltip; delete val.tooltip; }
var rng = safe_decode_range(val.ref);
for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
var addr = encode_col(C) + encode_row(R);
var addr = encode_cell({c:C,r:R});
if(dense) {
if(!s["!data"][R]) s["!data"][R] = [];
if(!s["!data"][R][C]) s["!data"][R][C] = {t:"z",v:undefined};
s["!data"][R][C].l = val;
if(!s[R]) s[R] = [];
if(!s[R][C]) s[R][C] = {t:"z",v:undefined};
s[R][C].l = val;
} else {
if(!s[addr]) s[addr] = {t:"z",v:undefined};
s[addr].l = val;
@ -199,7 +191,6 @@ function parse_ws_xml_cols(columns, cols) {
var coll = parsexmltag(cols[coli], true);
if(coll.hidden) coll.hidden = parsexmlbool(coll.hidden);
var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
if(coll.outlineLevel) coll.level = (+coll.outlineLevel || 0);
delete coll.min; delete coll.max; coll.width = +coll.width;
if(!seencol && coll.width) { seencol = true; find_mdw_colw(coll.width); }
process_col(coll);
@ -231,7 +222,7 @@ function write_ws_xml_autofilter(data, ws, wb, idx)/*:string*/ {
var name = names[i];
if(name.Name != '_xlnm._FilterDatabase') continue;
if(name.Sheet != idx) continue;
name.Ref = formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref); break;
name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break;
}
if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref });
return writextag("autoFilter", null, {ref:ref});
@ -239,7 +230,7 @@ function write_ws_xml_autofilter(data, ws, wb, idx)/*:string*/ {
/* 18.3.1.88 sheetViews CT_SheetViews */
/* 18.3.1.87 sheetView CT_SheetView */
var sviewregex = /<(?:\w:)?sheetView(?:[^<>a-z][^<>]*)?\/?>/g;
var sviewregex = /<(?:\w:)?sheetView(?:[^>a-z][^>]*)?\/?>/;
function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) {
if(!wb.Views) wb.Views = [{}];
(data.match(sviewregex)||[]).forEach(function(r/*:string*/, i/*:number*/) {
@ -249,7 +240,7 @@ function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) {
// $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore
if(tag.rightToLeft && parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
});
}
function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
@ -259,33 +250,26 @@ function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
return writextag("sheetViews", writextag("sheetView", null, sview), {});
}
function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb, date1904)/*:string*/ {
if(cell.c) ws['!comments'].push([ref, cell.c]);
if((cell.v === undefined || cell.t === "z" && !(opts||{}).sheetStubs) && typeof cell.f !== "string" && typeof cell.z == "undefined") return "";
function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string*/ {
if(cell.v === undefined && typeof cell.f !== "string" || cell.t === 'z') return "";
var vv = "";
var oldt = cell.t, oldv = cell.v;
if(cell.t !== "z") switch(cell.t) {
case 'b': vv = cell.v ? "1" : "0"; break;
case 'n':
if(isNaN(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x24]; } // #NUM!
else if(!isFinite(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x07]; } // #DIV/0!
else vv = ''+cell.v; break;
case 'n': vv = ''+cell.v; break;
case 'e': vv = BErr[cell.v]; break;
case 'd':
if(opts && opts.cellDates) {
var _vv = parseDate(cell.v, date1904);
vv = _vv.toISOString();
if(_vv.getUTCFullYear() < 1900) vv = vv.slice(vv.indexOf("T") + 1).replace("Z","");
} else {
if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
else {
cell = dup(cell);
cell.t = 'n';
vv = ''+(cell.v = datenum(parseDate(cell.v, date1904), date1904));
vv = ''+(cell.v = datenum(parseDate(cell.v)));
}
if(typeof cell.z === 'undefined') cell.z = table_fmt[14];
if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
break;
default: vv = cell.v; break;
}
var v = (cell.t == "z" || cell.v == null)? "" : writetag('v', escapexml(vv)), o = ({r:ref}/*:any*/);
var v = writetag('v', escapexml(vv)), o = ({r:ref}/*:any*/);
/* TODO: cell style */
var os = get_cell_style(opts.cellXfs, cell, opts);
if(os !== 0) o.s = os;
@ -296,32 +280,29 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb, date1904)/*:st
case 'e': o.t = "e"; break;
case 'z': break;
default: if(cell.v == null) { delete cell.t; break; }
if(cell.v.length > 32767) throw new Error("Text length must not exceed 32767 characters");
if(opts && opts.bookSST) {
v = writetag('v', ''+get_sst_id(opts.Strings, cell.v, opts.revStrings));
o.t = "s"; break;
}
else o.t = "str"; break;
o.t = "str"; break;
}
if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; }
if(typeof cell.f == "string" && cell.f) {
var ff = cell.F && cell.F.slice(0, ref.length) == ref ? {t:"array", ref:cell.F} : null;
v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : "");
}
if(cell.l) {
cell.l.display = escapexml(vv);
ws['!links'].push([ref, cell.l]);
}
if(cell.D) o.cm = 1;
if(cell.l) ws['!links'].push([ref, cell.l]);
if(cell.c) ws['!comments'].push([ref, cell.c]);
return writextag('c', v, o);
}
var parse_ws_xml_data = /*#__PURE__*/(function() {
var parse_ws_xml_data = (function() {
var cellregex = /<(?:\w+:)?c[ \/>]/, rowregex = /<\/(?:\w+:)?row>/;
var rregex = /r=["']([^"']*)["']/;
var rregex = /r=["']([^"']*)["']/, isregex = /<(?:\w+:)?is>([\S\s]*?)<\/(?:\w+:)?is>/;
var refregex = /ref=["']([^"']*)["']/;
var match_v = matchtag("v"), match_f = matchtag("f");
return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles, wb) {
return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles) {
var ri = 0, x = "", cells/*:Array<string>*/ = [], cref/*:?Array<string>*/ = [], idx=0, i=0, cc=0, d="", p/*:any*/;
var tag, tagr = 0, tagc = 0;
var sstr, ftag;
@ -329,47 +310,26 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
var do_format = Array.isArray(styles.CellXf), cf;
var arrayf/*:Array<[Range, string]>*/ = [];
var sharedf = [];
var dense = s["!data"] != null;
var dense = Array.isArray(s);
var rows/*:Array<RowInfo>*/ = [], rowobj = {}, rowrite = false;
var sheetStubs = !!opts.sheetStubs;
var date1904 = !!((wb||{}).WBProps||{}).date1904;
for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
x = marr[mt].trim();
var xlen = x.length;
if(xlen === 0) continue;
/* 18.3.1.73 row CT_Row */
var rstarti = 0;
outa: for(ri = 0; ri < xlen; ++ri) switch(/*x.charCodeAt(ri)*/x[ri]) {
case ">" /*62*/:
if(/*x.charCodeAt(ri-1) != 47*/x[ri-1] != "/") { ++ri; break outa; }
if(opts && opts.cellStyles) {
// TODO: avoid duplication
tag = parsexmltag(x.slice(rstarti,ri), true);
tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
if(opts.sheetRows && opts.sheetRows < tagr) continue;
rowobj = {}; rowrite = false;
if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
if(tag.hidden && parsexmlbool(tag.hidden)) { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj;
}
break;
case "<" /*60*/: rstarti = ri; break;
}
if(rstarti >= ri) break;
tag = parsexmltag(x.slice(rstarti,ri), true);
for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
tag = parsexmltag(x.slice(0,ri), true);
tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
if(opts.sheetRows && opts.sheetRows < tagr) continue;
if(!opts.nodim) {
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
}
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
if(opts && opts.cellStyles) {
rowobj = {}; rowrite = false;
if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
if(tag.hidden && parsexmlbool(tag.hidden)) { rowrite = true; rowobj.hidden = true; }
if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj;
}
@ -398,31 +358,23 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
d = x.slice(i);
p = ({t:""}/*:any*/);
if((cref=str_match_xml_ns(d, "v"))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
if(opts.cellFormula) {
if((cref=str_match_xml_ns(d, "f"))!= null /*:: && cref != null*/) {
if(cref[1] == "") {
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
// TODO: parse formula
ftag = parsexmltag(cref[0]);
if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
}
} else {
/* TODO: match against XLSXFutureFunctions */
p.f=unescapexml(utf8read(cref[1]), true);
if(!opts.xlfn) p.f = _xlfn(p.f);
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
p.F = (d.match(refregex)||[])[1];
if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
} else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
// TODO: parse formula
ftag = parsexmltag(cref[0]);
var ___f = unescapexml(utf8read(cref[1]));
if(!opts.xlfn) ___f = _xlfn(___f);
sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
}
if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') {
/* TODO: match against XLSXFutureFunctions */
p.f=unescapexml(utf8read(cref[1])).replace(/\r\n/g, "\n");
if(!opts.xlfn) p.f = _xlfn(p.f);
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
p.F = (d.match(refregex)||[])[1];
if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
} else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
// TODO: parse formula
ftag = parsexmltag(cref[0]);
var ___f = unescapexml(utf8read(cref[1]));
if(!opts.xlfn) ___f = _xlfn(___f);
sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
}
} else if((cref=d.match(/<f[^<>]*\/>/))) {
} else if((cref=d.match(/<f[^>]*\/>/))) {
ftag = parsexmltag(cref[0]);
if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
}
@ -464,11 +416,11 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
break;
case 'str':
p.t = "s";
p.v = (p.v!=null) ? unescapexml(utf8read(p.v), true) : '';
p.v = (p.v!=null) ? utf8read(p.v) : '';
if(opts.cellHTML) p.h = escapehtml(p.v);
break;
case 'inlineStr':
cref = str_match_xml_ns(d, "is");
cref = d.match(isregex);
p.t = 's';
if(cref != null && (sstr = parse_si(cref[1]))) {
p.v = sstr.t;
@ -477,8 +429,8 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
break;
case 'b': p.v = parsexmlbool(p.v); break;
case 'd':
if(opts.cellDates) p.v = parseDate(p.v, date1904);
else { p.v = datenum(parseDate(p.v, date1904), date1904); p.t = 'n'; }
if(opts.cellDates) p.v = parseDate(p.v, 1);
else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; }
break;
/* error string in .w, number in .v */
case 'e':
@ -497,22 +449,12 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
}
}
}
safe_format(p, fmtid, fillid, opts, themes, styles, date1904);
if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.v = numdate(p.v + (date1904 ? 1462 : 0)); p.t = typeof p.v == "number" ? 'n' : 'd'; }
if(tag.cm && opts.xlmeta) {
var cm = (opts.xlmeta.Cell||[])[+tag.cm-1];
if(cm && cm.type == 'XLDAPR') p.D = true;
}
var _r;
if(opts.nodim) {
_r = decode_cell(tag.r);
if(guess.s.r > _r.r) guess.s.r = _r.r;
if(guess.e.r < _r.r) guess.e.r = _r.r;
}
safe_format(p, fmtid, fillid, opts, themes, styles);
if(opts.cellDates && do_format && p.t == 'n' && SSF.is_date(SSF._table[fmtid])) { p.t = 'd'; p.v = numdate(p.v); }
if(dense) {
_r = decode_cell(tag.r);
if(!s["!data"][_r.r]) s["!data"][_r.r] = [];
s["!data"][_r.r][_r.c] = p;
var _r = decode_cell(tag.r);
if(!s[_r.r]) s[_r.r] = [];
s[_r.r][_r.c] = p;
} else s[tag.r] = p;
}
}
@ -521,19 +463,17 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*//*::, rels*/)/*:string*/ {
var o/*:Array<string>*/ = [], r/*:Array<string>*/ = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols/*:Array<string>*/ = [], R=0, C=0, rows = ws['!rows'];
var dense = ws["!data"] != null, data = dense ? ws["!data"] : [];
var dense = Array.isArray(ws);
var params = ({r:rr}/*:any*/), row/*:RowInfo*/, height = -1;
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
for(R = range.s.r; R <= range.e.r; ++R) {
r = [];
rr = encode_row(R);
var data_R = dense ? data[R] : [];
for(C = range.s.c; C <= range.e.c; ++C) {
ref = cols[C] + rr;
var _cell = dense ? data_R[C] : ws[ref];
var _cell = dense ? (ws[R]||[])[C]: ws[ref];
if(_cell === undefined) continue;
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb, date1904)) != null) r.push(cell);
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
}
if(r.length > 0 || (rows && rows[R])) {
params = ({r:rr}/*:any*/);
@ -565,11 +505,13 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
return o.join("");
}
var WS_XML_ROOT = writextag('worksheet', null, {
'xmlns': XMLNS.main[0],
'xmlns:r': XMLNS.r
});
function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
var o = [XML_HEADER, writextag('worksheet', null, {
'xmlns': XMLNS_main[0],
'xmlns:r': XMLNS.r
})];
var o = [XML_HEADER, WS_XML_ROOT];
var s = wb.SheetNames[idx], sidx = 0, rdata = "";
var ws = wb.Sheets[s];
if(ws == null) ws = {};
@ -610,7 +552,7 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
/* sheetCalcPr */
if(ws['!protect']) o[o.length] = write_ws_xml_protection(ws['!protect']);
if(ws['!protect'] != null) o[o.length] = write_ws_xml_protection(ws['!protect']);
/* protectedRanges */
/* scenarios */
@ -634,12 +576,11 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
if(!l[1].Target) return;
rel = ({"ref":l[0]}/*:any*/);
if(l[1].Target.charAt(0) != "#") {
rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#[\s\S]*$/, ""), RELS.HLINK);
rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), RELS.HLINK);
rel["r:id"] = "rId"+rId;
}
if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1));
if(l[1].Tooltip) rel.tooltip = escapexml(l[1].Tooltip);
rel.display = l[1].display;
o[o.length] = writextag("hyperlink",null,rel);
});
o[o.length] = "</hyperlinks>";

@ -41,13 +41,12 @@ function write_BrtRowHdr(R/*:number*/, range, ws) {
o.l += 4;
var caddr = {r:R, c:0};
var dense = ws["!data"] != null;
for(var i = 0; i < 16; ++i) {
if((range.s.c > ((i+1) << 10)) || (range.e.c < (i << 10))) continue;
var first = -1, last = -1;
for(var j = (i<<10); j < ((i+1)<<10); ++j) {
caddr.c = j;
var cell = dense ? (ws["!data"][caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)];
var cell = Array.isArray(ws) ? (ws[caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)];
if(cell) { if(first < 0) first = j; last = j; }
}
if(first < 0) continue;
@ -65,7 +64,7 @@ function write_BrtRowHdr(R/*:number*/, range, ws) {
}
function write_row_header(ba, ws, range, R) {
var o = write_BrtRowHdr(R, range, ws);
if((o.length > 17) || (ws['!rows']||[])[R]) write_record(ba, 0x0000 /* BrtRowHdr */, o);
if((o.length > 17) || (ws['!rows']||[])[R]) write_record(ba, 'BrtRowHdr', o);
}
/* [MS-XLSB] 2.4.820 BrtWsDim */
@ -80,23 +79,14 @@ function parse_BrtWsFmtInfo(/*::data, length*/) {
/* [MS-XLSB] 2.4.823 BrtWsProp */
function parse_BrtWsProp(data, length) {
var z = {};
var f = data[data.l]; ++data.l;
z.above = !(f & 0x40);
z.left = !(f & 0x80);
/* TODO: pull flags */
data.l += 18;
data.l += 19;
z.name = parse_XLSBCodeName(data, length - 19);
return z;
}
function write_BrtWsProp(str, outl, o) {
function write_BrtWsProp(str, o) {
if(o == null) o = new_buf(84+4*str.length);
var f = 0xC0;
if(outl) {
if(outl.above) f &= ~0x40;
if(outl.left) f &= ~0x80;
}
o.write_shift(1, f);
for(var i = 1; i < 3; ++i) o.write_shift(1,0);
for(var i = 0; i < 3; ++i) o.write_shift(1,0);
write_BrtColor({auto:1}, o);
o.write_shift(-4,-1);
o.write_shift(-4,-1);
@ -113,14 +103,7 @@ function write_BrtCellBlank(cell, ncell, o) {
if(o == null) o = new_buf(8);
return write_XLSBCell(ncell, o);
}
function parse_BrtShortBlank(data) {
var cell = parse_XLSBShortCell(data);
return [cell];
}
function write_BrtShortBlank(cell, ncell, o) {
if(o == null) o = new_buf(4);
return write_XLSBShortCell(ncell, o);
}
/* [MS-XLSB] 2.4.307 BrtCellBool */
function parse_BrtCellBool(data) {
@ -134,17 +117,6 @@ function write_BrtCellBool(cell, ncell, o) {
o.write_shift(1, cell.v ? 1 : 0);
return o;
}
function parse_BrtShortBool(data) {
var cell = parse_XLSBShortCell(data);
var fBool = data.read_shift(1);
return [cell, fBool, 'b'];
}
function write_BrtShortBool(cell, ncell, o) {
if(o == null) o = new_buf(5);
write_XLSBShortCell(ncell, o);
o.write_shift(1, cell.v ? 1 : 0);
return o;
}
/* [MS-XLSB] 2.4.308 BrtCellError */
function parse_BrtCellError(data) {
@ -152,26 +124,6 @@ function parse_BrtCellError(data) {
var bError = data.read_shift(1);
return [cell, bError, 'e'];
}
function write_BrtCellError(cell, ncell, o) {
if(o == null) o = new_buf(9);
write_XLSBCell(ncell, o);
o.write_shift(1, cell.v);
return o;
}
function parse_BrtShortError(data) {
var cell = parse_XLSBShortCell(data);
var bError = data.read_shift(1);
return [cell, bError, 'e'];
}
function write_BrtShortError(cell, ncell, o) {
if(o == null) o = new_buf(8);
write_XLSBShortCell(ncell, o);
o.write_shift(1, cell.v);
o.write_shift(2, 0);
o.write_shift(1, 0);
return o;
}
/* [MS-XLSB] 2.4.311 BrtCellIsst */
function parse_BrtCellIsst(data) {
@ -185,17 +137,6 @@ function write_BrtCellIsst(cell, ncell, o) {
o.write_shift(4, ncell.v);
return o;
}
function parse_BrtShortIsst(data) {
var cell = parse_XLSBShortCell(data);
var isst = data.read_shift(4);
return [cell, isst, 's'];
}
function write_BrtShortIsst(cell, ncell, o) {
if(o == null) o = new_buf(8);
write_XLSBShortCell(ncell, o);
o.write_shift(4, ncell.v);
return o;
}
/* [MS-XLSB] 2.4.313 BrtCellReal */
function parse_BrtCellReal(data) {
@ -209,17 +150,6 @@ function write_BrtCellReal(cell, ncell, o) {
write_Xnum(cell.v, o);
return o;
}
function parse_BrtShortReal(data) {
var cell = parse_XLSBShortCell(data);
var value = parse_Xnum(data);
return [cell, value, 'n'];
}
function write_BrtShortReal(cell, ncell, o) {
if(o == null) o = new_buf(12);
write_XLSBShortCell(ncell, o);
write_Xnum(cell.v, o);
return o;
}
/* [MS-XLSB] 2.4.314 BrtCellRk */
function parse_BrtCellRk(data) {
@ -233,24 +163,7 @@ function write_BrtCellRk(cell, ncell, o) {
write_RkNumber(cell.v, o);
return o;
}
function parse_BrtShortRk(data) {
var cell = parse_XLSBShortCell(data);
var value = parse_RkNumber(data);
return [cell, value, 'n'];
}
function write_BrtShortRk(cell, ncell, o) {
if(o == null) o = new_buf(8);
write_XLSBShortCell(ncell, o);
write_RkNumber(cell.v, o);
return o;
}
/* [MS-XLSB] 2.4.323 BrtCellRString */
function parse_BrtCellRString(data) {
var cell = parse_XLSBCell(data);
var value = parse_RichStr(data);
return [cell, value, 'is'];
}
/* [MS-XLSB] 2.4.317 BrtCellSt */
function parse_BrtCellSt(data) {
@ -259,22 +172,9 @@ function parse_BrtCellSt(data) {
return [cell, value, 'str'];
}
function write_BrtCellSt(cell, ncell, o) {
var data = cell.v == null ? "" : String(cell.v);
if(o == null) o = new_buf(12 + 4 * cell.v.length);
write_XLSBCell(ncell, o);
write_XLWideString(data, o);
return o.length > o.l ? o.slice(0, o.l) : o;
}
function parse_BrtShortSt(data) {
var cell = parse_XLSBShortCell(data);
var value = parse_XLWideString(data);
return [cell, value, 'str'];
}
function write_BrtShortSt(cell, ncell, o) {
var data = cell.v == null ? "" : String(cell.v);
if(o == null) o = new_buf(8 + 4 * data.length);
write_XLSBShortCell(ncell, o);
write_XLWideString(data, o);
write_XLWideString(cell.v, o);
return o.length > o.l ? o.slice(0, o.l) : o;
}
@ -511,7 +411,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
var opts = _opts || {};
if(!rels) rels = {'!id':{}};
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
var s/*:Worksheet*/ = ({}); if(opts.dense) s["!data"] = [];
var s/*:Worksheet*/ = (opts.dense ? [] : {});
var ref;
var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
@ -539,12 +439,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
var colinfo/*:Array<ColInfo>*/ = [], rowinfo/*:Array<RowInfo>*/ = [];
var seencol = false;
XLSBRecordEnum[0x0010] = { n:"BrtShortReal", f:parse_BrtShortReal };
var cm, vm;
var date1904 = 1462 * +!!((wb||{}).WBProps||{}).date1904;
recordhopper(data, function ws_parse(val, RR, RT) {
recordhopper(data, function ws_parse(val, R_n, RT) {
if(end) return;
switch(RT) {
case 0x0094: /* 'BrtWsDim' */
@ -570,13 +465,6 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x0009: /* 'BrtFmlaNum' */
case 0x000A: /* 'BrtFmlaBool' */
case 0x000B: /* 'BrtFmlaError' */
case 0x000D: /* 'BrtShortRk' */
case 0x000E: /* 'BrtShortError' */
case 0x000F: /* 'BrtShortBool' */
case 0x0010: /* 'BrtShortReal' */
case 0x0011: /* 'BrtShortSt' */
case 0x0012: /* 'BrtShortIsst' */
case 0x003E: /* 'BrtCellRString' */
p = ({t:val[2]}/*:any*/);
switch(val[2]) {
case 'n': p.v = val[1]; break;
@ -584,11 +472,10 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 'b': p.v = val[1] ? true : false; break;
case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break;
case 'str': p.t = 's'; p.v = val[1]; break;
case 'is': p.t = 's'; p.v = val[1].t; break;
}
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles, date1904>0);
C = val[0].c == -1 ? C + 1 : val[0].c;
if(opts.dense) { if(!s["!data"][R]) s["!data"][R] = []; s["!data"][R][C] = p; }
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
C = val[0].c;
if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
else s[encode_col(C) + rr] = p;
if(opts.cellFormula) {
af = false;
@ -601,46 +488,30 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
}
if(!af && val.length > 3) p.f = val[3];
}
if(refguess.s.r > row.r) refguess.s.r = row.r;
if(refguess.s.c > C) refguess.s.c = C;
if(refguess.e.r < row.r) refguess.e.r = row.r;
if(refguess.e.c < C) refguess.e.c = C;
if(opts.cellDates && cf && p.t == 'n' && fmt_is_date(table_fmt[cf.numFmtId])) {
var _d = SSF_parse_date_code(p.v + date1904); if(_d) { p.t = 'd'; p.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
if(opts.cellDates && cf && p.t == 'n' && SSF.is_date(SSF._table[cf.numFmtId])) {
var _d = SSF.parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
}
if(cm) {
if(cm.type == 'XLDAPR') p.D = true;
cm = void 0;
}
if(vm) vm = void 0;
break;
case 0x0001: /* 'BrtCellBlank' */
case 0x000C: /* 'BrtShortBlank' */
if(!opts.sheetStubs || pass) break;
p = ({t:'z',v:void 0}/*:any*/);
C = val[0].c == -1 ? C + 1 : val[0].c;
if(opts.dense) { if(!s["!data"][R]) s["!data"][R] = []; s["!data"][R][C] = p; }
p = ({t:'z',v:undefined}/*:any*/);
C = val[0].c;
if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
else s[encode_col(C) + rr] = p;
if(refguess.s.r > row.r) refguess.s.r = row.r;
if(refguess.s.c > C) refguess.s.c = C;
if(refguess.e.r < row.r) refguess.e.r = row.r;
if(refguess.e.c < C) refguess.e.c = C;
if(cm) {
if(cm.type == 'XLDAPR') p.D = true;
cm = void 0;
}
if(vm) vm = void 0;
break;
case 0x00B0: /* 'BrtMergeCell' */
merges.push(val); break;
case 0x0031: { /* 'BrtCellMeta' */
cm = ((opts.xlmeta||{}).Cell||[])[val-1];
} break;
case 0x01EE: /* 'BrtHLink' */
var rel = rels['!id'][val.relId];
if(rel) {
@ -652,11 +523,11 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
}
for(R=val.rfx.s.r;R<=val.rfx.e.r;++R) for(C=val.rfx.s.c;C<=val.rfx.e.c;++C) {
if(opts.dense) {
if(!s["!data"][R]) s["!data"][R] = [];
if(!s["!data"][R][C]) s["!data"][R][C] = {t:'z',v:undefined};
s["!data"][R][C].l = val;
if(!s[R]) s[R] = [];
if(!s[R][C]) s[R][C] = {t:'z',v:undefined};
s[R][C].l = val;
} else {
addr = encode_col(C) + encode_row(R);
addr = encode_cell({c:C,r:R});
if(!s[addr]) s[addr] = {t:'z',v:undefined};
s[addr].l = val;
}
@ -666,14 +537,14 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x01AA: /* 'BrtArrFmla' */
if(!opts.cellFormula) break;
arrayf.push(val);
cell = ((opts.dense ? s["!data"][R][C] : s[encode_col(C) + rr])/*:any*/);
cell = ((opts.dense ? s[R][C] : s[encode_col(C) + rr])/*:any*/);
cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
cell.F = encode_range(val[0]);
break;
case 0x01AB: /* 'BrtShrFmla' */
if(!opts.cellFormula) break;
sharedf[encode_cell(val[0].s)] = val[1];
cell = (opts.dense ? s["!data"][R][C] : s[encode_col(C) + rr]);
cell = (opts.dense ? s[R][C] : s[encode_col(C) + rr]);
cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
break;
@ -687,10 +558,6 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
}
break;
case 0x0227: /* 'BrtLegacyDrawing' */
if(val) s["!legrel"] = val;
break;
case 0x00A1: /* 'BrtBeginAFilter' */
s['!autofilter'] = { ref:encode_range(val) };
break;
@ -702,7 +569,6 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x0093: /* 'BrtWsProp' */
if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
if(val.name) wb.Sheets[idx].CodeName = val.name;
if(val.above || val.left) s['!outline'] = { above: val.above, left: val.left };
break;
case 0x0089: /* 'BrtBeginWsView' */
@ -720,7 +586,6 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x0097: /* 'BrtPane' */
break;
case 0x0098: /* 'BrtSel' */
case 0x00AF: /* 'BrtAFilterDateGroupItem' */
case 0x0284: /* 'BrtActiveX' */
case 0x0271: /* 'BrtBigName' */
@ -732,6 +597,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x041A: /* 'BrtCFVO14' */
case 0x0289: /* 'BrtCellIgnoreEC' */
case 0x0451: /* 'BrtCellIgnoreEC14' */
case 0x0031: /* 'BrtCellMeta' */
case 0x024D: /* 'BrtCellSmartTagProperty' */
case 0x025F: /* 'BrtCellWatch' */
case 0x0234: /* 'BrtColor' */
@ -747,6 +613,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x0499: /* 'BrtFilter14' */
case 0x00A9: /* 'BrtIconFilter' */
case 0x049D: /* 'BrtIconFilter14' */
case 0x0227: /* 'BrtLegacyDrawing' */
case 0x0228: /* 'BrtLegacyDrawingHF' */
case 0x0295: /* 'BrtListPart' */
case 0x027F: /* 'BrtOleObject' */
@ -758,6 +625,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x02A8: /* 'BrtRangeProtectionIso' */
case 0x0450: /* 'BrtRangeProtectionIso14' */
case 0x0400: /* 'BrtRwDescent' */
case 0x0098: /* 'BrtSel' */
case 0x0297: /* 'BrtSheetCalcProp' */
case 0x0217: /* 'BrtSheetProtection' */
case 0x02A6: /* 'BrtSheetProtectionIso' */
@ -776,13 +644,14 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x0024: /* 'BrtFRTEnd' */
pass = false; break;
case 0x0025: /* 'BrtACBegin' */
state.push(RT); pass = true; break;
state.push(R_n); pass = true; break;
case 0x0026: /* 'BrtACEnd' */
state.pop(); pass = false; break;
default:
if(RR.T){/* empty */}
else if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
if((R_n||"").indexOf("Begin") > 0){/* empty */}
else if((R_n||"").indexOf("End") > 0){/* empty */}
else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
}
}, opts);
@ -805,131 +674,105 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
if(merges.length > 0) s["!merges"] = merges;
if(colinfo.length > 0) s["!cols"] = colinfo;
if(rowinfo.length > 0) s["!rows"] = rowinfo;
if(rels['!id'][s['!legrel']]) s['!legdrawel'] = rels['!id'][s['!legrel']];
return s;
}
/* TODO: something useful -- this is a stub */
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/, date1904/*:boolean*/)/*:boolean*/ {
var o/*:any*/ = ({r:R, c:C}/*:any*/);
if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
if(cell.v === undefined) return false;
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/) {
if(cell.v === undefined) return;
var vv = "";
switch(cell.t) {
case 'b': vv = cell.v ? "1" : "0"; break;
case 'd': // no BrtCellDate :(
cell = dup(cell);
cell.z = cell.z || table_fmt[14];
cell.v = datenum(parseDate(cell.v, date1904), date1904); cell.t = 'n';
cell.z = cell.z || SSF._table[14];
cell.v = datenum(parseDate(cell.v)); cell.t = 'n';
break;
/* falls through */
case 'n': case 'e': vv = ''+cell.v; break;
default: vv = cell.v; break;
}
var o/*:any*/ = ({r:R, c:C}/*:any*/);
/* TODO: cell style */
o.s = get_cell_style(opts.cellXfs, cell, opts);
if(cell.l) ws['!links'].push([encode_cell(o), cell.l]);
if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
switch(cell.t) {
case 's': case 'str':
if(opts.bookSST) {
vv = get_sst_id(opts.Strings, (cell.v == null ? "" : String(cell.v)/*:any*/), opts.revStrings);
vv = get_sst_id(opts.Strings, (cell.v/*:any*/), opts.revStrings);
o.t = "s"; o.v = vv;
if(last_seen) write_record(ba, 0x0012 /* BrtShortIsst */, write_BrtShortIsst(cell, o));
else write_record(ba, 0x0007 /* BrtCellIsst */, write_BrtCellIsst(cell, o));
write_record(ba, "BrtCellIsst", write_BrtCellIsst(cell, o));
} else {
o.t = "str";
if(last_seen) write_record(ba, 0x0011 /* BrtShortSt */, write_BrtShortSt(cell, o));
else write_record(ba, 0x0006 /* BrtCellSt */, write_BrtCellSt(cell, o));
write_record(ba, "BrtCellSt", write_BrtCellSt(cell, o));
}
return true;
return;
case 'n':
/* TODO: determine threshold for Real vs RK */
if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) {
if(last_seen) write_record(ba, 0x000D /* BrtShortRk */, write_BrtShortRk(cell, o));
else write_record(ba, 0x0002 /* BrtCellRk */, write_BrtCellRk(cell, o));
} else if(!isFinite(cell.v)) {
o.t = "e";
if(isNaN(cell.v)) {
if(last_seen) write_record(ba, 0x000E /* BrtShortError */, write_BrtShortError({t:"e", v: 0x24}, o)); // #NUM!
else write_record(ba, 0x0003 /* BrtCellError */, write_BrtCellError({t:"e", v: 0x24}, o)); // #NUM!
} else {
if(last_seen) write_record(ba, 0x000E /* BrtShortError */, write_BrtShortError({t:"e", v: 0x07}, o)); // #DIV/0!
else write_record(ba, 0x0003 /* BrtCellError */, write_BrtCellError({t:"e", v: 0x07}, o)); // #DIV/0!
}
} else {
if(last_seen) write_record(ba, 0x0010 /* BrtShortReal */, write_BrtShortReal(cell, o));
else write_record(ba, 0x0005 /* BrtCellReal */, write_BrtCellReal(cell, o));
} return true;
if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o));
else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o));
return;
case 'b':
o.t = "b";
if(last_seen) write_record(ba, 0x000F /* BrtShortBool */, write_BrtShortBool(cell, o));
else write_record(ba, 0x0004 /* BrtCellBool */, write_BrtCellBool(cell, o));
return true;
case 'e':
o.t = "e";
if(last_seen) write_record(ba, 0x000E /* BrtShortError */, write_BrtShortError(cell, o));
else write_record(ba, 0x0003 /* BrtCellError */, write_BrtCellError(cell, o));
return true;
write_record(ba, "BrtCellBool", write_BrtCellBool(cell, o));
return;
case 'e': /* TODO: error */ o.t = "e"; break;
}
if(last_seen) write_record(ba, 0x000C /* BrtShortBlank */, write_BrtShortBlank(cell, o));
else write_record(ba, 0x0001 /* BrtCellBlank */, write_BrtCellBlank(cell, o));
return true;
write_record(ba, "BrtCellBlank", write_BrtCellBlank(cell, o));
}
function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
var range = safe_decode_range(ws['!ref'] || "A1"), rr = "", cols/*:Array<string>*/ = [];
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
write_record(ba, 0x0091 /* BrtBeginSheetData */);
var dense = ws["!data"] != null, row = dense ? ws["!data"][range.s.r] : [];
function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols/*:Array<string>*/ = [];
write_record(ba, 'BrtBeginSheetData');
var dense = Array.isArray(ws);
var cap = range.e.r;
if(ws['!rows']) cap = Math.max(range.e.r, ws['!rows'].length - 1);
for(var R = range.s.r; R <= cap; ++R) {
rr = encode_row(R);
if(dense) row = ws["!data"][R];
/* [ACCELLTABLE] */
/* BrtRowHdr */
write_row_header(ba, ws, range, R);
if(dense && !row) continue;
var last_seen = false;
if(R <= range.e.r) for(var C = range.s.c; C <= range.e.c; ++C) {
/* *16384CELL */
if(R === range.s.r) cols[C] = encode_col(C);
var cell = dense ? row[C] : ws[cols[C] + rr];
if(!cell) { last_seen = false; continue; }
ref = cols[C] + rr;
var cell = dense ? (ws[R]||[])[C] : ws[ref];
if(!cell) continue;
/* write cell */
last_seen = write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen, date1904);
write_ws_bin_cell(ba, cell, R, C, opts, ws);
}
}
write_record(ba, 0x0092 /* BrtEndSheetData */);
write_record(ba, 'BrtEndSheetData');
}
function write_MERGECELLS(ba, ws/*:Worksheet*/) {
if(!ws || !ws['!merges']) return;
write_record(ba, 0x00B1 /* BrtBeginMergeCells */, write_BrtBeginMergeCells(ws['!merges'].length));
ws['!merges'].forEach(function(m) { write_record(ba, 0x00B0 /* BrtMergeCell */, write_BrtMergeCell(m)); });
write_record(ba, 0x00B2 /* BrtEndMergeCells */);
write_record(ba, 'BrtBeginMergeCells', write_BrtBeginMergeCells(ws['!merges'].length));
ws['!merges'].forEach(function(m) { write_record(ba, 'BrtMergeCell', write_BrtMergeCell(m)); });
write_record(ba, 'BrtEndMergeCells');
}
function write_COLINFOS(ba, ws/*:Worksheet*//*::, idx:number, opts, wb:Workbook*/) {
if(!ws || !ws['!cols']) return;
write_record(ba, 0x0186 /* BrtBeginColInfos */);
ws['!cols'].forEach(function(m, i) { if(m) write_record(ba, 0x003C /* 'BrtColInfo' */, write_BrtColInfo(i, m)); });
write_record(ba, 0x0187 /* BrtEndColInfos */);
write_record(ba, 'BrtBeginColInfos');
ws['!cols'].forEach(function(m, i) { if(m) write_record(ba, 'BrtColInfo', write_BrtColInfo(i, m)); });
write_record(ba, 'BrtEndColInfos');
}
function write_IGNOREECS(ba, ws/*:Worksheet*/) {
if(!ws || !ws['!ref']) return;
write_record(ba, 0x0288 /* BrtBeginCellIgnoreECs */);
write_record(ba, 0x0289 /* BrtCellIgnoreEC */, write_BrtCellIgnoreEC(safe_decode_range(ws['!ref'])));
write_record(ba, 0x028A /* BrtEndCellIgnoreECs */);
write_record(ba, 'BrtBeginCellIgnoreECs');
write_record(ba, 'BrtCellIgnoreEC', write_BrtCellIgnoreEC(safe_decode_range(ws['!ref'])));
write_record(ba, 'BrtEndCellIgnoreECs');
}
function write_HLINKS(ba, ws/*:Worksheet*/, rels) {
/* *BrtHLink */
ws['!links'].forEach(function(l) {
if(!l[1].Target) return;
var rId = add_rels(rels, -1, l[1].Target.replace(/#[\s\S]*$/, ""), RELS.HLINK);
write_record(ba, 0x01EE /* BrtHLink */, write_BrtHLink(l, rId));
var rId = add_rels(rels, -1, l[1].Target.replace(/#.*$/, ""), RELS.HLINK);
write_record(ba, "BrtHLink", write_BrtHLink(l, rId));
});
delete ws['!links'];
}
@ -937,7 +780,7 @@ function write_LEGACYDRAWING(ba, ws/*:Worksheet*/, idx/*:number*/, rels) {
/* [BrtLegacyDrawing] */
if(ws['!comments'].length > 0) {
var rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML);
write_record(ba, 0x0227 /* BrtLegacyDrawing */, write_RelID("rId" + rId));
write_record(ba, "BrtLegacyDrawing", write_RelID("rId" + rId));
ws['!legacy'] = rId;
}
}
@ -957,41 +800,41 @@ function write_AUTOFILTER(ba, ws, wb, idx) {
var name = names[i];
if(name.Name != '_xlnm._FilterDatabase') continue;
if(name.Sheet != idx) continue;
name.Ref = formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref); break;
name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break;
}
if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref) });
if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref });
write_record(ba, 0x00A1 /* BrtBeginAFilter */, write_UncheckedRfX(safe_decode_range(ref)));
write_record(ba, "BrtBeginAFilter", write_UncheckedRfX(safe_decode_range(ref)));
/* *FILTERCOLUMN */
/* [SORTSTATE] */
/* BrtEndAFilter */
write_record(ba, 0x00A2 /* BrtEndAFilter */);
write_record(ba, "BrtEndAFilter");
}
function write_WSVIEWS2(ba, ws, Workbook) {
write_record(ba, 0x0085 /* BrtBeginWsViews */);
write_record(ba, "BrtBeginWsViews");
{ /* 1*WSVIEW2 */
/* [ACUID] */
write_record(ba, 0x0089 /* BrtBeginWsView */, write_BrtBeginWsView(ws, Workbook));
write_record(ba, "BrtBeginWsView", write_BrtBeginWsView(ws, Workbook));
/* [BrtPane] */
/* *4BrtSel */
/* *4SXSELECT */
/* *FRT */
write_record(ba, 0x008A /* BrtEndWsView */);
write_record(ba, "BrtEndWsView");
}
/* *FRT */
write_record(ba, 0x0086 /* BrtEndWsViews */);
write_record(ba, "BrtEndWsViews");
}
function write_WSFMTINFO(/*::ba, ws*/) {
/* [ACWSFMTINFO] */
// write_record(ba, 0x01E5 /* BrtWsFmtInfo */, write_BrtWsFmtInfo(ws));
//write_record(ba, "BrtWsFmtInfo", write_BrtWsFmtInfo(ws));
}
function write_SHEETPROTECT(ba, ws) {
if(!ws['!protect']) return;
/* [BrtSheetProtectionIso] */
write_record(ba, 0x0217 /* BrtSheetProtection */, write_BrtSheetProtection(ws['!protect']));
write_record(ba, "BrtSheetProtection", write_BrtSheetProtection(ws['!protect']));
}
function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
@ -1007,9 +850,9 @@ function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
ws['!links'] = [];
/* passed back to write_zip and removed there */
ws['!comments'] = [];
write_record(ba, 0x0081 /* BrtBeginSheet */);
if(wb.vbaraw || ws['!outline']) write_record(ba, 0x0093 /* BrtWsProp */, write_BrtWsProp(c, ws['!outline']));
write_record(ba, 0x0094 /* BrtWsDim */, write_BrtWsDim(r));
write_record(ba, "BrtBeginSheet");
if(wb.vbaraw) write_record(ba, "BrtWsProp", write_BrtWsProp(c));
write_record(ba, "BrtWsDim", write_BrtWsDim(r));
write_WSVIEWS2(ba, ws, wb.Workbook);
write_WSFMTINFO(ba, ws);
write_COLINFOS(ba, ws, idx, opts, wb);
@ -1028,7 +871,7 @@ function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
/* [DVALS] */
write_HLINKS(ba, ws, rels);
/* [BrtPrintOptions] */
if(ws['!margins']) write_record(ba, 0x01DC /* BrtMargins */, write_BrtMargins(ws['!margins']));
if(ws['!margins']) write_record(ba, "BrtMargins", write_BrtMargins(ws['!margins']));
/* [BrtPageSetup] */
/* [HEADERFOOTER] */
/* [RWBRK] */
@ -1046,6 +889,6 @@ function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
/* [WEBPUBITEMS] */
/* [LISTPARTS] */
/* FRTWORKSHEET */
write_record(ba, 0x0082 /* BrtEndSheet */);
write_record(ba, "BrtEndSheet");
return ba.end();
}

@ -1,19 +1,22 @@
RELS.CHART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart";
RELS.CHARTEX = "http://schemas.microsoft.com/office/2014/relationships/chartEx";
function parse_Cache(data/*:string*/)/*:[Array<number|string>, string, ?string]*/ {
var col/*:Array<number|string>*/ = [];
var num = data.match(/^<c:numCache>/);
var f;
/* 21.2.2.150 pt CT_NumVal */
(data.match(/<c:pt idx="(\d*)"[^<>\/]*><c:v>([^<])<\/c:v><\/c:pt>/mg)||[]).forEach(function(pt) {
var q = pt.match(/<c:pt idx="(\d*)"[^<>\/]*><c:v>([^<]*)<\/c:v><\/c:pt>/);
(data.match(/<c:pt idx="(\d*)">(.*?)<\/c:pt>/mg)||[]).forEach(function(pt) {
var q = pt.match(/<c:pt idx="(\d*?)"><c:v>(.*)<\/c:v><\/c:pt>/);
if(!q) return;
col[+q[1]] = num ? +q[2] : q[2];
});
/* 21.2.2.71 formatCode CT_Xstring */
var nf = unescapexml((str_match_xml(data, "c:formatCode") || ["","General"])[1]);
var nf = unescapexml((data.match(/<c:formatCode>([\s\S]*?)<\/c:formatCode>/) || ["","General"])[1]);
(str_match_ng(data, "<c:f>", "</c:f>")||[]).forEach(function(F) { f = F.replace(/<[^<>]*>/g,""); });
(data.match(/<c:f>(.*?)<\/c:f>/mg)||[]).forEach(function(F) { f = F.replace(/<.*?>/g,""); });
return [col, nf, f];
}
@ -28,16 +31,13 @@ function parse_chart(data/*:?string*/, name/*:string*/, opts, rels, wb, csheet)
var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
/* 21.2.2.120 numCache CT_NumData */
(str_match_ng(data, "<c:numCache>", "</c:numCache>")||[]).forEach(function(nc) {
(data.match(/<c:numCache>[\s\S]*?<\/c:numCache>/gm)||[]).forEach(function(nc) {
var cache = parse_Cache(nc);
refguess.s.r = refguess.s.c = 0;
refguess.e.c = C;
col = encode_col(C);
cache[0].forEach(function(n,i) {
if(cs["!data"]) {
if(!cs["!data"][i]) cs["!data"][i] = [];
cs["!data"][i][C] = {t:'n', v:n, z:cache[1] };
} else cs[col + encode_row(i)] = {t:'n', v:n, z:cache[1] };
cs[col + encode_row(i)] = {t:'n', v:n, z:cache[1] };
R = i;
});
if(refguess.e.r < R) refguess.e.r = R;

@ -1,3 +1,10 @@
RELS.CS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet";
var CS_XML_ROOT = writextag('chartsheet', null, {
'xmlns': XMLNS.main[0],
'xmlns:r': XMLNS.r
});
/* 18.3 Worksheets also covers Chartsheets */
function parse_cs_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*::, themes, styles*/)/*:Worksheet*/ {
if(!data) return data;
@ -16,16 +23,13 @@ function parse_cs_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*::, them
if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
return s;
}
//function write_cs_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
// var o = [XML_HEADER, writextag('chartsheet', null, {
// 'xmlns': XMLNS_main[0],
// 'xmlns:r': XMLNS.r
// })];
// o[o.length] = writextag("drawing", null, {"r:id": "rId1"});
// add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
// if(o.length>2) { o[o.length] = ('</chartsheet>'); o[1]=o[1].replace("/>",">"); }
// return o.join("");
//}
function write_cs_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
var o = [XML_HEADER, CS_XML_ROOT];
o[o.length] = writextag("drawing", null, {"r:id": "rId1"});
add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
if(o.length>2) { o[o.length] = ('</chartsheet>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}
/* [MS-XLSB] 2.4.331 BrtCsProp */
function parse_BrtCsProp(data, length/*:number*/) {
@ -41,7 +45,7 @@ function parse_cs_bin(data, opts, idx/*:number*/, rels, wb/*::, themes, styles*/
var s = {'!type':"chart", '!drawel':null, '!rel':""};
var state/*:Array<string>*/ = [];
var pass = false;
recordhopper(data, function cs_parse(val, R, RT) {
recordhopper(data, function cs_parse(val, R_n, RT) {
switch(RT) {
case 0x0226: /* 'BrtDrawing' */
@ -67,36 +71,36 @@ function parse_cs_bin(data, opts, idx/*:number*/, rels, wb/*::, themes, styles*/
case 0x0024: /* 'BrtFRTEnd' */
pass = false; break;
case 0x0025: /* 'BrtACBegin' */
state.push(RT); break;
state.push(R_n); break;
case 0x0026: /* 'BrtACEnd' */
state.pop(); break;
default:
if(R.T > 0) state.push(RT);
else if(R.T < 0) state.pop();
else if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
if((R_n||"").indexOf("Begin") > 0) state.push(R_n);
else if((R_n||"").indexOf("End") > 0) state.pop();
else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
}
}, opts);
if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
return s;
}
//function write_cs_bin(/*::idx:number, opts, wb:Workbook, rels*/) {
// var ba = buf_array();
// write_record(ba, 0x0081 /* BrtBeginSheet */);
// /* [BrtCsProp] */
// /* CSVIEWS */
// /* [[BrtCsProtectionIso] BrtCsProtection] */
// /* [USERCSVIEWS] */
// /* [BrtMargins] */
// /* [BrtCsPageSetup] */
// /* [HEADERFOOTER] */
// /* BrtDrawing */
// /* [BrtLegacyDrawing] */
// /* [BrtLegacyDrawingHF] */
// /* [BrtBkHim] */
// /* [WEBPUBITEMS] */
// /* FRTCHARTSHEET */
// write_record(ba, 0x0082 /* BrtEndSheet */);
// return ba.end();
//}
function write_cs_bin(/*::idx:number, opts, wb:Workbook, rels*/) {
var ba = buf_array();
write_record(ba, "BrtBeginSheet");
/* [BrtCsProp] */
/* CSVIEWS */
/* [[BrtCsProtectionIso] BrtCsProtection] */
/* [USERCSVIEWS] */
/* [BrtMargins] */
/* [BrtCsPageSetup] */
/* [HEADERFOOTER] */
/* BrtDrawing */
/* [BrtLegacyDrawing] */
/* [BrtLegacyDrawingHF] */
/* [BrtBkHim] */
/* [WEBPUBITEMS] */
/* FRTCHARTSHEET */
write_record(ba, "BrtEndSheet");
return ba.end();
}

@ -113,19 +113,16 @@ function safe1904(wb/*:Workbook*/)/*:string*/ {
return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false";
}
var badchars = /*#__PURE__*/":][*?\/\\".split("");
var badchars = "][*?\/\\".split("");
function check_ws_name(n/*:string*/, safe/*:?boolean*/)/*:boolean*/ {
try {
if(n == "") throw new Error("Sheet name cannot be blank");
if(n.length > 31) throw new Error("Sheet name cannot exceed 31 chars");
if(n.charCodeAt(0) == 0x27 || n.charCodeAt(n.length - 1) == 0x27) throw new Error("Sheet name cannot start or end with apostrophe (')");
if(n.toLowerCase() == "history") throw new Error("Sheet name cannot be 'History'");
badchars.forEach(function(c) {
if(n.indexOf(c) == -1) return;
throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
});
} catch(e) { if(safe) return false; throw e; }
return true;
if(n.length > 31) { if(safe) return false; throw new Error("Sheet names cannot exceed 31 chars"); }
var _good = true;
badchars.forEach(function(c) {
if(n.indexOf(c) == -1) return;
if(!safe) throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
_good = false;
});
return _good;
}
function check_wb_names(N, S, codes) {
N.forEach(function(n,i) {
@ -143,16 +140,5 @@ function check_wb(wb) {
var Sheets = (wb.Workbook && wb.Workbook.Sheets) || [];
check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i);
wb.SheetNames.forEach(function(n, i) {
var ws = wb.Sheets[n];
if(!ws || !ws["!autofilter"]) return;
var DN;
if(!wb.Workbook) wb.Workbook = {};
if(!wb.Workbook.Names) wb.Workbook.Names = [];
wb.Workbook.Names.forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == i) DN = dn; });
var nn = formula_quote_sheet_name(n) + "!" + fix_range(ws["!autofilter"].ref);
if(DN) DN.Ref = nn;
else wb.Workbook.Names.push({Name: "_xlnm._FilterDatabase", Sheet: i, Ref: nn});
});
/* TODO: validate workbook */
}

@ -151,21 +151,23 @@ function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
}
return x;
});
if(XMLNS_main.indexOf(wb.xmlns) === -1) throw new Error("Unknown Namespace: " + wb.xmlns);
if(XMLNS.main.indexOf(wb.xmlns) === -1) throw new Error("Unknown Namespace: " + wb.xmlns);
parse_wb_defaults(wb);
return wb;
}
var WB_XML_ROOT = writextag('workbook', null, {
'xmlns': XMLNS.main[0],
//'xmlns:mx': XMLNS.mx,
//'xmlns:s': XMLNS.main[0],
'xmlns:r': XMLNS.r
});
function write_wb_xml(wb/*:Workbook*//*::, opts:?WriteOpts*/)/*:string*/ {
var o = [XML_HEADER];
o[o.length] = writextag('workbook', null, {
'xmlns': XMLNS_main[0],
//'xmlns:mx': XMLNS.mx,
//'xmlns:s': XMLNS_main[0],
'xmlns:r': XMLNS.r
});
o[o.length] = WB_XML_ROOT;
var write_names = (wb.Workbook && (wb.Workbook.Names||[]).length > 0);

@ -45,7 +45,6 @@ function write_BrtWbProp(data/*:?WBProps*/, o) {
var flags = 0;
if(data) {
/* TODO: mirror parse_BrtWbProp fields */
if(data.date1904) flags |= 0x01;
if(data.filterPrivacy) flags |= 0x08;
}
o.write_shift(4, flags);
@ -65,19 +64,12 @@ function parse_BrtFRTArchID$(data, length) {
/* [MS-XLSB] 2.4.687 BrtName */
function parse_BrtName(data, length, opts) {
var end = data.l + length;
var flags = data.read_shift(4);
data.l += 4; //var flags = data.read_shift(4);
data.l += 1; //var chKey = data.read_shift(1);
var itab = data.read_shift(4);
var name = parse_XLNameWideString(data);
var formula;
var comment = "";
try {
formula = parse_XLSBNameParsedFormula(data, 0, opts);
try {
comment = parse_XLNullableWideString(data);
} catch(e){}
} catch(e) { console.error("Could not parse defined name " + name); }
if(flags & 0x20) name = "_xlnm." + name;
var formula = parse_XLSBNameParsedFormula(data, 0, opts);
var comment = parse_XLNullableWideString(data);
//if(0 /* fProc */) {
// unusedstring1: XLNullableWideString
// description: XLNullableWideString
@ -85,40 +77,11 @@ function parse_BrtName(data, length, opts) {
// unusedstring2: XLNullableWideString
//}
data.l = end;
var out = ({Name:name, Ptg:formula, Flags: flags}/*:any*/);
var out = ({Name:name, Ptg:formula}/*:any*/);
if(itab < 0xFFFFFFF) out.Sheet = itab;
if(comment) out.Comment = comment;
return out;
}
function write_BrtName(name, wb) {
var o = new_buf(9);
var flags = 0;
var dname = name.Name;
if(XLSLblBuiltIn.indexOf(dname) > -1) { flags |= 0x20; dname = dname.slice(6); }
o.write_shift(4, flags); // flags
o.write_shift(1, 0); // chKey
o.write_shift(4, name.Sheet == null ? 0xFFFFFFFF : name.Sheet);
var arr = [
o,
write_XLWideString(dname),
write_XLSBNameParsedFormula(name.Ref, wb)
];
if(name.Comment) arr.push(write_XLNullableWideString(name.Comment));
else {
var x = new_buf(4);
x.write_shift(4, 0xFFFFFFFF);
arr.push(x);
}
// if macro (flags & 0x0F):
// write_shift(4, 0xFFFFFFFF);
// write_XLNullableWideString(description)
// write_XLNullableWideString(helpTopic)
// write_shift(4, 0xFFFFFFFF);
return bconcat(arr);
}
/* [MS-XLSB] 2.1.7.61 Workbook */
function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
@ -134,9 +97,7 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
supbooks.SheetNames = [];
supbooks.XTI = [];
XLSBRecordEnum[0x0010] = { n:"BrtFRTArchID$", f:parse_BrtFRTArchID$ };
recordhopper(data, function hopper_wb(val, R, RT) {
recordhopper(data, function hopper_wb(val, R_n, RT) {
switch(RT) {
case 0x009C: /* 'BrtBundleSh' */
supbooks.SheetNames.push(val.name);
@ -147,7 +108,7 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
case 0x0027: /* 'BrtName' */
if(val.Sheet != null) opts.SID = val.Sheet;
val.Ref = val.Ptg ? stringify_formula(val.Ptg, null, null, supbooks, opts) : "#REF!";
val.Ref = stringify_formula(val.Ptg, null, null, supbooks, opts);
delete opts.SID;
delete val.Ptg;
Names.push(val);
@ -170,18 +131,13 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
case 0x0169: /* 'BrtPlaceholderName' */
break;
case 0x0817: /* 'BrtAbsPath15' */
case 0x009E: /* 'BrtBookView' */
case 0x008F: /* 'BrtBeginBundleShs' */
case 0x0298: /* 'BrtBeginFnGroup' */
case 0x0161: /* 'BrtBeginExternals' */
break;
/* case 'BrtModelTimeGroupingCalcCol' */
case 0x0C00: /* 'BrtUid' */
case 0x0C01: /* 'BrtRevisionPtr' */
case 0x0817: /* 'BrtAbsPath15' */
case 0x0216: /* 'BrtBookProtection' */
case 0x02A5: /* 'BrtBookProtectionIso' */
case 0x009E: /* 'BrtBookView' */
case 0x009D: /* 'BrtCalcProp' */
case 0x0262: /* 'BrtCrashRecErr' */
case 0x0802: /* 'BrtDecoupledPivotCacheID' */
@ -206,19 +162,20 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
break;
case 0x0023: /* 'BrtFRTBegin' */
state.push(RT); pass = true; break;
state.push(R_n); pass = true; break;
case 0x0024: /* 'BrtFRTEnd' */
state.pop(); pass = false; break;
case 0x0025: /* 'BrtACBegin' */
state.push(RT); pass = true; break;
state.push(R_n); pass = true; break;
case 0x0026: /* 'BrtACEnd' */
state.pop(); pass = false; break;
case 0x0010: /* 'BrtFRTArchID$' */ break;
default:
if(R.T){/* empty */}
else if(!pass || (opts.WTF && state[state.length-1] != 0x0025 /* BrtACBegin */ && state[state.length-1] != 0x0023 /* BrtFRTBegin */)) throw new Error("Unexpected record 0x" + RT.toString(16));
if((R_n||"").indexOf("Begin") > 0){/* empty */}
else if((R_n||"").indexOf("End") > 0){/* empty */}
else if(!pass || (opts.WTF && state[state.length-1] != "BrtACBegin" && state[state.length-1] != "BrtFRTBegin")) throw new Error("Unexpected record " + RT + " " + R_n);
}
}, opts);
@ -232,13 +189,13 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
}
function write_BUNDLESHS(ba, wb/*::, opts*/) {
write_record(ba, 0x008F /* BrtBeginBundleShs */);
write_record(ba, "BrtBeginBundleShs");
for(var idx = 0; idx != wb.SheetNames.length; ++idx) {
var viz = wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx] && wb.Workbook.Sheets[idx].Hidden || 0;
var d = { Hidden: viz, iTabID: idx+1, strRelID: 'rId' + (idx+1), name: wb.SheetNames[idx] };
write_record(ba, 0x009C /* BrtBundleSh */, write_BrtBundleSh(d));
write_record(ba, "BrtBundleSh", write_BrtBundleSh(d));
}
write_record(ba, 0x0090 /* BrtEndBundleShs */);
write_record(ba, "BrtEndBundleShs");
}
/* [MS-XLSB] 2.4.649 BrtFileVersion */
@ -249,6 +206,7 @@ function write_BrtFileVersion(data, o) {
write_XLWideString(XLSX.version, o);
write_XLWideString(XLSX.version, o);
write_XLWideString("7262", o);
o.length = o.l;
return o.length > o.l ? o.slice(0, o.l) : o;
}
@ -277,38 +235,10 @@ function write_BOOKVIEWS(ba, wb/*::, opts*/) {
else if(sheets[i].Hidden == 1 && hidden == -1) hidden = i;
}
if(hidden > vistab) return;
write_record(ba, 0x0087 /* BrtBeginBookViews */);
write_record(ba, 0x009E /* BrtBookView */, write_BrtBookView(vistab));
write_record(ba, "BrtBeginBookViews");
write_record(ba, "BrtBookView", write_BrtBookView(vistab));
/* 1*(BrtBookView *FRT) */
write_record(ba, 0x0088 /* BrtEndBookViews */);
}
function write_BRTNAMES(ba, wb) {
if(!wb.Workbook || !wb.Workbook.Names) return;
wb.Workbook.Names.forEach(function(name) { try {
if(name.Flags & 0x0e) return; // TODO: macro name write
write_record(ba, 0x0027 /* BrtName */, write_BrtName(name, wb));
} catch(e) {
console.error("Could not serialize defined name " + JSON.stringify(name));
} });
}
function write_SELF_EXTERNS_xlsb(wb) {
var L = wb.SheetNames.length;
var o = new_buf(12 * L + 28);
o.write_shift(4, L + 2);
o.write_shift(4, 0); o.write_shift(4, -2); o.write_shift(4, -2); // workbook-level reference
o.write_shift(4, 0); o.write_shift(4, -1); o.write_shift(4, -1); // #REF!...
for(var i = 0; i < L; ++i) {
o.write_shift(4, 0); o.write_shift(4, i); o.write_shift(4, i);
}
return o;
}
function write_EXTERNALS_xlsb(ba, wb) {
write_record(ba, 0x0161 /* BrtBeginExternals */);
write_record(ba, 0x0165 /* BrtSupSelf */);
write_record(ba, 0x016A /* BrtExternSheet */, write_SELF_EXTERNS_xlsb(wb, 0));
write_record(ba, 0x0162 /* BrtEndExternals */);
write_record(ba, "BrtEndBookViews");
}
/* [MS-XLSB] 2.4.305 BrtCalcProp */
@ -334,29 +264,29 @@ function write_EXTERNALS_xlsb(ba, wb) {
/* [MS-XLSB] 2.1.7.61 Workbook */
function write_wb_bin(wb, opts) {
var ba = buf_array();
write_record(ba, 0x0083 /* BrtBeginBook */);
write_record(ba, 0x0080 /* BrtFileVersion */, write_BrtFileVersion());
write_record(ba, "BrtBeginBook");
write_record(ba, "BrtFileVersion", write_BrtFileVersion());
/* [[BrtFileSharingIso] BrtFileSharing] */
write_record(ba, 0x0099 /* BrtWbProp */, write_BrtWbProp(wb.Workbook && wb.Workbook.WBProps || null));
write_record(ba, "BrtWbProp", write_BrtWbProp(wb.Workbook && wb.Workbook.WBProps || null));
/* [ACABSPATH] */
/* [[BrtBookProtectionIso] BrtBookProtection] */
write_BOOKVIEWS(ba, wb, opts);
write_BUNDLESHS(ba, wb, opts);
/* [FNGROUP] */
write_EXTERNALS_xlsb(ba, wb);
if((wb.Workbook||{}).Names) write_BRTNAMES(ba, wb);
/* write_record(ba, 0x009D BrtCalcProp, write_BrtCalcProp()); */
/* [EXTERNALS] */
/* *BrtName */
/* write_record(ba, "BrtCalcProp", write_BrtCalcProp()); */
/* [BrtOleSize] */
/* *(BrtUserBookView *FRT) */
/* [PIVOTCACHEIDS] */
/* [BrtWbFactoid] */
/* [SMARTTAGTYPES] */
/* [BrtWebOpt] */
/* write_record(ba, 0x009B BrtFileRecover, write_BrtFileRecover()); */
/* write_record(ba, "BrtFileRecover", write_BrtFileRecover()); */
/* [WEBPUBITEMS] */
/* [CRERRS] */
/* FRTWORKBOOK */
write_record(ba, 0x0084 /* BrtEndBook */);
write_record(ba, "BrtEndBook");
return ba.end();
}

@ -28,6 +28,10 @@ function parse_sty(data, name/*:string*/, themes, opts) {
return parse_sty_xml((data/*:any*/), themes, opts);
}
function parse_theme(data/*:string*/, name/*:string*/, opts) {
return parse_theme_xml(data, opts);
}
function parse_sst(data, name/*:string*/, opts)/*:SST*/ {
if(name.slice(-4)===".bin") return parse_sst_bin((data/*:any*/), opts);
return parse_sst_xml((data/*:any*/), opts);
@ -48,7 +52,32 @@ function parse_xlink(data, rel, name/*:string*/, opts) {
return parse_xlink_xml((data/*:any*/), rel, name, opts);
}
function parse_xlmeta(data, name/*:string*/, opts) {
if(name.slice(-4)===".bin") return parse_xlmeta_bin((data/*:any*/), name, opts);
return parse_xlmeta_xml((data/*:any*/), name, opts);
function write_wb(wb, name/*:string*/, opts) {
return (name.slice(-4)===".bin" ? write_wb_bin : write_wb_xml)(wb, opts);
}
function write_ws(data/*:number*/, name/*:string*/, opts, wb/*:Workbook*/, rels) {
return (name.slice(-4)===".bin" ? write_ws_bin : write_ws_xml)(data, opts, wb, rels);
}
// eslint-disable-next-line no-unused-vars
function write_cs(data/*:number*/, name/*:string*/, opts, wb/*:Workbook*/, rels) {
return (name.slice(-4)===".bin" ? write_cs_bin : write_cs_xml)(data, opts, wb, rels);
}
function write_sty(data, name/*:string*/, opts) {
return (name.slice(-4)===".bin" ? write_sty_bin : write_sty_xml)(data, opts);
}
function write_sst(data/*:SST*/, name/*:string*/, opts) {
return (name.slice(-4)===".bin" ? write_sst_bin : write_sst_xml)(data, opts);
}
function write_cmnt(data/*:Array<any>*/, name/*:string*/, opts) {
return (name.slice(-4)===".bin" ? write_comments_bin : write_comments_xml)(data, opts);
}
/*
function write_cc(data, name:string, opts) {
return (name.slice(-4)===".bin" ? write_cc_bin : write_cc_xml)(data, opts);
}
*/

@ -1,5 +1,5 @@
var attregexg2=/\b((?:\w+:)?[\w]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
var attregex2=/\b((?:\w+:)?[\w]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;
var attregexg2=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
var attregex2=/([\w:]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;
function xlml_parsexmltag(tag/*:string*/, skip_root/*:?boolean*/) {
var words = tag.split(/\s+/);
var z/*:any*/ = ([]/*:any*/); if(!skip_root) z[0] = words[0];
@ -37,13 +37,10 @@ function xlml_parsexmltagobj(tag/*:string*/) {
// ----
/* map from xlml named formats to SSF TODO: localize */
var XLMLFormatMap/*: {[string]:string}*/;
function xlml_format(format, value, date1904)/*:string*/ {
function xlml_format(format, value)/*:string*/ {
var fmt = XLMLFormatMap[format] || unescapexml(format);
if(fmt === "General") return SSF_general(value);
return SSF_format(fmt, value, {date1904: !!date1904});
if(fmt === "General") return SSF._general(value);
return SSF.format(fmt, value);
}
function xlml_set_custprop(Custprops, key, cp, val/*:string*/) {
@ -59,24 +56,24 @@ function xlml_set_custprop(Custprops, key, cp, val/*:string*/) {
Custprops[unescapexml(key)] = oval;
}
function safe_format_xlml(cell/*:Cell*/, nf, o, date1904) {
function safe_format_xlml(cell/*:Cell*/, nf, o) {
if(cell.t === 'z') return;
if(!o || o.cellText !== false) try {
if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
else if(nf === "General") {
if(cell.t === 'n') {
if((cell.v|0) === cell.v) cell.w = cell.v.toString(10);
else cell.w = SSF_general_num(cell.v);
if((cell.v|0) === cell.v) cell.w = SSF._general_int(cell.v);
else cell.w = SSF._general_num(cell.v);
}
else cell.w = SSF_general(cell.v);
else cell.w = SSF._general(cell.v);
}
else cell.w = xlml_format(nf||"General", cell.v, date1904);
else cell.w = xlml_format(nf||"General", cell.v);
} catch(e) { if(o.WTF) throw e; }
try {
var z = XLMLFormatMap[nf]||nf||"General";
if(o.cellNF) cell.z = z;
if(o.cellDates && cell.t == 'n' && fmt_is_date(z)) {
var _d = SSF_parse_date_code(cell.v + (date1904 ? 1462 : 0)); if(_d) { cell.t = 'd'; cell.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
if(o.cellDates && cell.t == 'n' && SSF.is_date(z)) {
var _d = SSF.parse_date_code(cell.v); if(_d) { cell.t = 'd'; cell.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
}
} catch(e) { if(o.WTF) throw e; }
}
@ -92,18 +89,17 @@ function process_style_xlml(styles, stag, opts) {
}
/* TODO: there must exist some form of OSP-blessed spec */
function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o, date1904) {
function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o) {
var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
var interiors = [];
var i = 0;
if(sid === undefined && row) sid = row.StyleID;
if(sid === undefined && csty) sid = csty.StyleID;
while(styles[sid] !== undefined) {
var ssid = styles[sid];
if(ssid.nf) nf = ssid.nf;
if(ssid.Interior) interiors.push(ssid.Interior);
if(!ssid.Parent) break;
sid = ssid.Parent;
if(styles[sid].nf) nf = styles[sid].nf;
if(styles[sid].Interior) interiors.push(styles[sid].Interior);
if(!styles[sid].Parent) break;
sid = styles[sid].Parent;
}
switch(data.Type) {
case 'Boolean':
@ -112,12 +108,13 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
break;
case 'String':
cell.t = 's'; cell.r = xlml_fixstr(unescapexml(xml));
cell.v = (xml.indexOf("<") > -1 ? unescapexml(ss||xml).replace(/<[^<>]*>/g, "") : cell.r); // todo: BR etc
cell.v = (xml.indexOf("<") > -1 ? unescapexml(ss||xml).replace(/<.*?>/g, "") : cell.r); // todo: BR etc
break;
case 'DateTime':
if(xml.slice(-1) != "Z") xml += "Z";
cell.v = datenum(parseDate(xml, date1904), date1904);
cell.v = (parseDate(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
if(cell.v !== cell.v) cell.v = unescapexml(xml);
else if(cell.v<60) cell.v = cell.v -1;
if(!nf || nf == "General") nf = "yyyy-mm-dd";
/* falls through */
case 'Number':
@ -130,7 +127,7 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
else { cell.t = 's'; cell.v = xlml_fixstr(ss||xml); }
break;
}
safe_format_xlml(cell, nf, o, date1904);
safe_format_xlml(cell, nf, o);
if(o.cellFormula !== false) {
if(cell.Formula) {
var fstr = unescapexml(cell.Formula);
@ -159,56 +156,40 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
if(cell.StyleID !== undefined) cell.ixfe = cell.StyleID;
}
function xlml_prefix_dname(dname) {
return XLSLblBuiltIn.indexOf("_xlnm." + dname) > -1 ? "_xlnm." + dname : dname;
}
function xlml_clean_comment(comment/*:any*/) {
comment.t = comment.v || "";
comment.t = comment.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n");
comment.v = comment.w = comment.ixfe = undefined;
}
function xlml_normalize(d)/*:string*/ {
if(has_buf &&/*::typeof Buffer !== "undefined" && d != null && d instanceof Buffer &&*/ Buffer.isBuffer(d)) return d.toString('utf8');
if(typeof d === 'string') return d;
/* duktape */
if(typeof Uint8Array !== 'undefined' && d instanceof Uint8Array) return utf8read(a2s(ab2a(d)));
throw new Error("Bad input format: expected Buffer or string");
}
/* TODO: Everything */
/* UOS uses CJK in tags */
var xlmlregex = /<(\/?)([^\s?><!\/:]*:|)([^\s?<>:\/]+)(?:[\s?:\/][^>]*)?>/mg;
//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
function parse_xlml_xml(d, _opts)/*:Workbook*/ {
var opts = _opts || {};
make_ssf();
make_ssf(SSF);
var str = debom(xlml_normalize(d));
if(opts.type == 'binary' || opts.type == 'array' || opts.type == 'base64') {
if(typeof $cptable !== 'undefined') str = $cptable.utils.decode(65001, char_codes(str));
if(typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str));
else str = utf8read(str);
}
var opening = str.slice(0, 1024).toLowerCase(), ishtml = false;
opening = opening.replace(/".*?"/g, "");
if((opening.indexOf(">") & 1023) > Math.min((opening.indexOf(",") & 1023), (opening.indexOf(";")&1023))) { var _o = dup(opts); _o.type = "string"; return PRN.to_workbook(str, _o); }
if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; });
if(ishtml) return html_to_workbook(str, opts);
XLMLFormatMap = ({
"General Number": "General",
"General Date": table_fmt[22],
"Long Date": "dddd, mmmm dd, yyyy",
"Medium Date": table_fmt[15],
"Short Date": table_fmt[14],
"Long Time": table_fmt[19],
"Medium Time": table_fmt[18],
"Short Time": table_fmt[20],
"Currency": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
"Fixed": table_fmt[2],
"Standard": table_fmt[4],
"Percent": table_fmt[10],
"Scientific": table_fmt[11],
"Yes/No": '"Yes";"Yes";"No";@',
"True/False": '"True";"True";"False";@',
"On/Off": '"Yes";"Yes";"No";@'
}/*:any*/);
if(ishtml) return HTML_.to_workbook(str, opts);
var Rn;
var state = [], tmp;
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
var sheets = {}, sheetnames/*:Array<string>*/ = [], cursheet/*:Worksheet*/ = ({}), sheetname = ""; if(opts.dense) cursheet["!data"] = [];
var cell = ({}/*:any*/), row = {};// eslint-disable-line no-unused-vars
var sheets = {}, sheetnames/*:Array<string>*/ = [], cursheet/*:Worksheet*/ = (opts.dense ? [] : {}), sheetname = "";
var table = {}, cell = ({}/*:any*/), row = {};// eslint-disable-line no-unused-vars
var dtag = xlml_parsexmltag('<Data ss:Type="String">'), didx = 0;
var c = 0, r = 0;
var refguess/*:Range*/ = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
@ -222,7 +203,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
var rowinfo/*:Array<RowInfo>*/ = [], rowobj = {}, cc = 0, rr = 0;
var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false} }/*:any*/), wsprops = {};
xlmlregex.lastIndex = 0;
str = str_remove_ng(str, "<!--", "-->");
str = str.replace(/<!--([\s\S]*?)-->/mg,"");
var raw_Rn3 = "";
while((Rn = xlmlregex.exec(str))) switch((Rn[3] = (raw_Rn3 = Rn[3]).toLowerCase())) {
case 'data' /*case 'Data'*/:
@ -232,27 +213,27 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
break;
}
if(state[state.length-1][1]) break;
if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]==/*"Comment"*/"comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts, Workbook.WBProps.date1904);
if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]==/*"Comment"*/"comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts);
else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; }
break;
case 'cell' /*case 'Cell'*/:
if(Rn[1]==='/'){
if(comments.length > 0) cell.c = comments;
if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== void 0) {
if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== undefined) {
if(opts.dense) {
if(!cursheet["!data"][r]) cursheet["!data"][r] = [];
cursheet["!data"][r][c] = cell;
if(!cursheet[r]) cursheet[r] = [];
cursheet[r][c] = cell;
} else cursheet[encode_col(c) + encode_row(r)] = cell;
}
if(cell.HRef) {
cell.l = ({Target:unescapexml(cell.HRef)}/*:any*/);
cell.l = ({Target:cell.HRef}/*:any*/);
if(cell.HRefScreenTip) cell.l.Tooltip = cell.HRefScreenTip;
delete cell.HRef; delete cell.HRefScreenTip;
}
if(cell.MergeAcross || cell.MergeDown) {
cc = c + (parseInt(cell.MergeAcross,10)|0);
rr = r + (parseInt(cell.MergeDown,10)|0);
if(cc > c || rr > r) merges.push({s:{c:c,r:r},e:{c:cc,r:rr}});
merges.push({s:{c:c,r:r},e:{c:cc,r:rr}});
}
if(!opts.sheetStubs) { if(cell.MergeAcross) c = cc + 1; else ++c; }
else if(cell.MergeAcross || cell.MergeDown) {
@ -261,8 +242,8 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
for(var cmd = r; cmd <= rr; ++cmd) {
if(cma > c || cmd > r) {
if(opts.dense) {
if(!cursheet["!data"][cmd]) cursheet["!data"][cmd] = [];
cursheet["!data"][cmd][cma] = {t:'z'};
if(!cursheet[cmd]) cursheet[cmd] = [];
cursheet[cmd][cma] = {t:'z'};
} else cursheet[encode_col(cma) + encode_row(cmd)] = {t:'z'};
}
}
@ -321,7 +302,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
state.push([Rn[3], false]);
tmp = xlml_parsexmltag(Rn[0]);
sheetname = unescapexml(tmp.Name);
cursheet = ({}); if(opts.dense) cursheet["!data"] = [];
cursheet = (opts.dense ? [] : {});
merges = [];
arrayf = [];
rowinfo = [];
@ -333,6 +314,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
else if(Rn[0].slice(-2) == "/>") break;
else {
table = xlml_parsexmltag(Rn[0]);
state.push([Rn[3], false]);
cstys = []; seencol = false;
}
@ -346,13 +328,12 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
case 'numberformat' /*case 'NumberFormat'*/:
stag.nf = unescapexml(xlml_parsexmltag(Rn[0]).Format || "General");
if(XLMLFormatMap[stag.nf]) stag.nf = XLMLFormatMap[stag.nf];
for(var ssfidx = 0; ssfidx != 0x188; ++ssfidx) if(table_fmt[ssfidx] == stag.nf) break;
if(ssfidx == 0x188) for(ssfidx = 0x39; ssfidx != 0x188; ++ssfidx) if(table_fmt[ssfidx] == null) { SSF__load(stag.nf, ssfidx); break; }
for(var ssfidx = 0; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == stag.nf) break;
if(ssfidx == 0x188) for(ssfidx = 0x39; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == null) { SSF.load(stag.nf, ssfidx); break; }
break;
case 'column' /*case 'Column'*/:
if(state[state.length-1][0] !== /*'Table'*/'table') break;
if(Rn[1]==='/') break;
csty = xlml_parsexmltag(Rn[0]);
if(csty.Hidden) { csty.hidden = true; delete csty.Hidden; }
if(csty.Width) csty.wpx = parseInt(csty.Width, 10);
@ -370,7 +351,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
if(!Workbook.Names) Workbook.Names = [];
var _NamedRange = parsexmltag(Rn[0]);
var _DefinedName/*:DefinedName*/ = ({
Name: xlml_prefix_dname(_NamedRange.Name),
Name: _NamedRange.Name,
Ref: rc_to_a1(_NamedRange.RefersTo.slice(1), {r:0, c:0})
}/*:any*/);
if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1;
@ -443,7 +424,6 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
} else {
state.push([Rn[3], false]);
tmp = xlml_parsexmltag(Rn[0]);
if(!parsexmlbool(tmp["ShowAlways"]||"0")) comments.hidden = true;
comment = ({a:tmp.Author}/*:any*/);
}
break;
@ -491,8 +471,6 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
break;
case 'null' /*case 'Null'*/: break;
default:
/* FODS file root is <office:document> */
if(state.length == 0 && Rn[3] == "document") return parse_fods(str, opts);
@ -535,9 +513,6 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
/*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
Workbook.WBProps.date1904 = true;
break;
case 'hidehorizontalscrollbar' /*case 'HideHorizontalScrollBar'*/: break;
case 'hideverticalscrollbar' /*case 'HideVerticalScrollBar'*/: break;
case 'hideworkbooktabs' /*case 'HideWorkbookTabs'*/: break;
case 'windowheight' /*case 'WindowHeight'*/: break;
case 'windowwidth' /*case 'WindowWidth'*/: break;
case 'windowtopx' /*case 'WindowTopX'*/: break;
@ -606,19 +581,19 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
break;
case 'header' /*case 'Header'*/:
if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
if(!isNaN(+parsexmltag(Rn[0]).Margin)) cursheet['!margins'].header = +parsexmltag(Rn[0]).Margin;
cursheet['!margins'].header = parsexmltag(Rn[0]).Margin;
break;
case 'footer' /*case 'Footer'*/:
if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
if(!isNaN(+parsexmltag(Rn[0]).Margin)) cursheet['!margins'].footer = +parsexmltag(Rn[0]).Margin;
cursheet['!margins'].footer = parsexmltag(Rn[0]).Margin;
break;
case 'pagemargins' /*case 'PageMargins'*/:
var pagemargins = parsexmltag(Rn[0]);
if(!cursheet['!margins']) default_margins(cursheet['!margins']={},'xlml');
if(!isNaN(+pagemargins.Top)) cursheet['!margins'].top = +pagemargins.Top;
if(!isNaN(+pagemargins.Left)) cursheet['!margins'].left = +pagemargins.Left;
if(!isNaN(+pagemargins.Right)) cursheet['!margins'].right = +pagemargins.Right;
if(!isNaN(+pagemargins.Bottom)) cursheet['!margins'].bottom = +pagemargins.Bottom;
if(pagemargins.Top) cursheet['!margins'].top = pagemargins.Top;
if(pagemargins.Left) cursheet['!margins'].left = pagemargins.Left;
if(pagemargins.Right) cursheet['!margins'].right = pagemargins.Right;
if(pagemargins.Bottom) cursheet['!margins'].bottom = pagemargins.Bottom;
break;
case 'displayrighttoleft' /*case 'DisplayRightToLeft'*/:
if(!Workbook.Views) Workbook.Views = [];
@ -643,7 +618,6 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
case 'unsynced' /*case 'Unsynced'*/: break;
case 'print' /*case 'Print'*/: break;
case 'printerrors' /*case 'PrintErrors'*/: break;
case 'panes' /*case 'Panes'*/: break;
case 'scale' /*case 'Scale'*/: break;
case 'pane' /*case 'Pane'*/: break;
@ -683,17 +657,11 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
case 'allowformatcells' /*case 'AllowFormatCells'*/: break;
case 'allowsizecols' /*case 'AllowSizeCols'*/: break;
case 'allowsizerows' /*case 'AllowSizeRows'*/: break;
case 'nosummaryrowsbelowdetail' /*case 'NoSummaryRowsBelowDetail'*/:
if(!cursheet["!outline"]) cursheet["!outline"] = {};
cursheet["!outline"].above = true;
break;
case 'nosummaryrowsbelowdetail' /*case 'NoSummaryRowsBelowDetail'*/: break;
case 'tabcolorindex' /*case 'TabColorIndex'*/: break;
case 'donotdisplayheadings' /*case 'DoNotDisplayHeadings'*/: break;
case 'showpagelayoutzoom' /*case 'ShowPageLayoutZoom'*/: break;
case 'nosummarycolumnsrightdetail' /*case 'NoSummaryColumnsRightDetail'*/:
if(!cursheet["!outline"]) cursheet["!outline"] = {};
cursheet["!outline"].left = true;
break;
case 'nosummarycolumnsrightdetail' /*case 'NoSummaryColumnsRightDetail'*/: break;
case 'blackandwhite' /*case 'BlackAndWhite'*/: break;
case 'donotdisplayzeros' /*case 'DoNotDisplayZeros'*/: break;
case 'displaypagebreak' /*case 'DisplayPageBreak'*/: break;
@ -920,17 +888,16 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
if(!opts.bookSheets && !opts.bookProps) out.Sheets = sheets;
out.SheetNames = sheetnames;
out.Workbook = Workbook;
out.SSF = dup(table_fmt);
out.SSF = SSF.get_table();
out.Props = Props;
out.Custprops = Custprops;
out.bookType = "xlml";
return out;
}
function parse_xlml(data/*:RawBytes|string*/, opts)/*:Workbook*/ {
fix_read_opts(opts=opts||{});
switch(opts.type||"base64") {
case "base64": return parse_xlml_xml(Base64_decode(data), opts);
case "base64": return parse_xlml_xml(Base64.decode(data), opts);
case "binary": case "buffer": case "file": return parse_xlml_xml(data, opts);
case "array": return parse_xlml_xml(a2s(data), opts);
}
@ -947,10 +914,9 @@ function write_props_xlml(wb/*:Workbook*/, opts)/*:string*/ {
return o.join("");
}
/* TODO */
function write_wb_xlml(wb/*::, opts*/)/*:string*/ {
function write_wb_xlml(/*::wb, opts*/)/*:string*/ {
/* OfficeDocumentSettings */
/* ExcelWorkbook */
if((((wb||{}).Workbook||{}).WBProps||{}).date1904) return '<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"><Date1904/></ExcelWorkbook>';
return "";
}
/* TODO */
@ -959,14 +925,14 @@ function write_sty_xlml(wb, opts)/*:string*/ {
var styles/*:Array<string>*/ = ['<Style ss:ID="Default" ss:Name="Normal"><NumberFormat/></Style>'];
opts.cellXfs.forEach(function(xf, id) {
var payload/*:Array<string>*/ = [];
payload.push(writextag('NumberFormat', null, {"ss:Format": escapexml(table_fmt[xf.numFmtId])}));
payload.push(writextag('NumberFormat', null, {"ss:Format": escapexml(SSF._table[xf.numFmtId])}));
var o = /*::(*/{"ss:ID": "s" + (21+id)}/*:: :any)*/;
styles.push(writextag('Style', payload.join(""), o));
});
return writextag("Styles", styles.join(""));
}
function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name.slice(0,6) == "_xlnm." ? n.Name.slice(6) : n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); }
function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); }
function write_names_xlml(wb/*::, opts*/)/*:string*/ {
if(!((wb||{}).Workbook||{}).Names) return "";
/*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */
@ -1106,15 +1072,11 @@ function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workb
return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x});
}
function write_ws_xlml_comment(comments/*:Array<any>*/)/*:string*/ {
/* TODO: test multiple comments */
return comments.map(function(c) {
// TODO: formatted text
var t = xlml_unfixstr(c.t||"");
var d =writextag("ss:Data", t, {"xmlns":"http://www.w3.org/TR/REC-html40"});
var p = {};
if(c.a) p["ss:Author"] = c.a;
if(!comments.hidden) p["ss:ShowAlways"] = "1";
return writextag("Comment", d, p);
return writextag("Comment", d, {"ss:Author":c.a});
}).join("");
}
function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, addr)/*:string*/{
@ -1144,16 +1106,10 @@ function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb,
var t = "", p = "";
switch(cell.t) {
case 'z': if(!opts.sheetStubs) return ""; break;
case 'n': {
if(!isFinite(cell.v)) {
t = 'Error'; p = BErr[isNaN(cell.v) ? 0x24 : 0x07];
} else {
t = 'Number'; p = String(cell.v);
}
} break;
case 'n': t = 'Number'; p = String(cell.v); break;
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
case 'e': t = 'Error'; p = BErr[cell.v]; break;
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || table_fmt[14]; break;
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break;
case 's': t = 'String'; p = escapexlml(cell.v||""); break;
}
/* TODO: cell style */
@ -1191,13 +1147,10 @@ function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbo
if(n.hidden) k['ss:Hidden']="1";
o.push(writextag("Column",null,k));
});
var dense = ws["!data"] != null;
var addr = {r:0,c:0};
var dense = Array.isArray(ws);
for(var R = range.s.r; R <= range.e.r; ++R) {
var row = [write_ws_xlml_row(R, (ws['!rows']||[])[R])];
addr.r = R;
for(var C = range.s.c; C <= range.e.c; ++C) {
addr.c = C;
var skip = false;
for(mi = 0; mi != marr.length; ++mi) {
if(marr[mi].s.c > C) continue;
@ -1208,7 +1161,8 @@ function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbo
break;
}
if(skip) continue;
var ref = encode_col(C) + encode_row(R), cell = dense ? (ws["!data"][R]||[])[C] : ws[ref];
var addr = {r:R,c:C};
var ref = encode_cell(addr), cell = dense ? (ws[R]||[])[C] : ws[ref];
row.push(write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr));
}
row.push("</Row>");
@ -1231,15 +1185,13 @@ function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ {
/* WorksheetOptions */
o.push(write_ws_xlml_wsopts(ws, opts, idx, wb));
if(ws && ws["!autofilter"]) o.push('<AutoFilter x:Range="' + a1_to_rc(fix_range(ws["!autofilter"].ref), {r:0,c:0}) + '" xmlns="urn:schemas-microsoft-com:office:excel"></AutoFilter>');
return o.join("");
}
function write_xlml(wb, opts)/*:string*/ {
if(!opts) opts = {};
if(!wb.SSF) wb.SSF = dup(table_fmt);
if(!wb.SSF) wb.SSF = SSF.get_table();
if(wb.SSF) {
make_ssf(); SSF_load_table(wb.SSF);
make_ssf(SSF); SSF.load_table(wb.SSF);
// $FlowIgnore
opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
opts.ssf = wb.SSF;
@ -1250,10 +1202,11 @@ function write_xlml(wb, opts)/*:string*/ {
d.push(write_props_xlml(wb, opts));
d.push(write_wb_xlml(wb, opts));
d.push("");
d.push(write_names_xlml(wb, opts));
d.push("");
for(var i = 0; i < wb.SheetNames.length; ++i)
d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])}));
d[2] = write_sty_xlml(wb, opts);
d[3] = write_names_xlml(wb, opts);
return XML_HEADER + writextag("Workbook", d.join(""), {
'xmlns': XLMLNS.ss,
'xmlns:o': XLMLNS.o,

@ -28,46 +28,45 @@ function parse_compobj(obj/*:CFBEntry*/) {
/*
Continue logic for:
- 2.4.58 Continue 0x003c
- 2.4.59 ContinueBigName 0x043c
- 2.4.60 ContinueFrt 0x0812
- 2.4.61 ContinueFrt11 0x0875
- 2.4.62 ContinueFrt12 0x087f
- 2.4.58 Continue
- 2.4.59 ContinueBigName
- 2.4.60 ContinueFrt
- 2.4.61 ContinueFrt11
- 2.4.62 ContinueFrt12
*/
var CONTINUE_RT = [ 0x003c, 0x043c, 0x0812, 0x0875, 0x087f ];
function slurp(RecordType, R, blob, length/*:number*/, opts)/*:any*/ {
function slurp(R, blob, length/*:number*/, opts)/*:any*/ {
var l = length;
var bufs = [];
var d = blob.slice(blob.l,blob.l+l);
if(opts && opts.enc && opts.enc.insitu && d.length > 0) switch(RecordType) {
case 0x0009: case 0x0209: case 0x0409: case 0x0809/* BOF */: case 0x002F /* FilePass */: case 0x0195 /* FileLock */: case 0x00E1 /* InterfaceHdr */: case 0x0196 /* RRDInfo */: case 0x0138 /* RRDHead */: case 0x0194 /* UsrExcl */: case 0x000a /* EOF */:
if(opts && opts.enc && opts.enc.insitu && d.length > 0) switch(R.n) {
case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': case 'EOF':
break;
case 0x0085 /* BoundSheet8 */:
case 'BoundSheet8':
break;
default:
opts.enc.insitu(d);
}
bufs.push(d);
blob.l += l;
var nextrt = __readUInt16LE(blob,blob.l), next = XLSRecordEnum[nextrt];
var next = (XLSRecordEnum[__readUInt16LE(blob,blob.l)]);
var start = 0;
while(next != null && CONTINUE_RT.indexOf(nextrt) > -1) {
while(next != null && next.n.slice(0,8) === 'Continue') {
l = __readUInt16LE(blob,blob.l+2);
start = blob.l + 4;
if(nextrt == 0x0812 /* ContinueFrt */) start += 4;
else if(nextrt == 0x0875 || nextrt == 0x087f) {
if(next.n == 'ContinueFrt') start += 4;
else if(next.n.slice(0,11) == 'ContinueFrt') {
start += 12;
}
d = blob.slice(start,blob.l+4+l);
bufs.push(d);
blob.l += 4+l;
next = (XLSRecordEnum[nextrt = __readUInt16LE(blob, blob.l)]);
next = (XLSRecordEnum[__readUInt16LE(blob, blob.l)]);
}
var b = (bconcat(bufs)/*:any*/);
prep_blob(b, 0);
var ll = 0; b.lens = [];
for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; }
if(b.length < length) throw "XLS Record 0x" + RecordType.toString(16) + " Truncated: " + b.length + " < " + length;
if(b.length < length) throw "XLS Record " + (R && R.n || "??") + " Truncated: " + b.length + " < " + length;
return R.f(b, b.length, opts);
}
@ -77,21 +76,21 @@ function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
var fmtid = 0;
try {
fmtid = p.z || p.XF.numFmtId || 0;
if(opts.cellNF && p.z == null) p.z = table_fmt[fmtid];
if(opts.cellNF) p.z = SSF._table[fmtid];
} catch(e) { if(opts.WTF) throw e; }
if(!opts || opts.cellText !== false) try {
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
else if(fmtid === 0 || fmtid == "General") {
if(p.t === 'n') {
if((p.v|0) === p.v) p.w = p.v.toString(10);
else p.w = SSF_general_num(p.v);
if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
else p.w = SSF._general_num(p.v);
}
else p.w = SSF_general(p.v);
else p.w = SSF._general(p.v);
}
else p.w = SSF_format(fmtid,p.v, {date1904:!!date1904, dateNF: opts && opts.dateNF});
else p.w = SSF.format(fmtid,p.v, {date1904:!!date1904});
} catch(e) { if(opts.WTF) throw e; }
if(opts.cellDates && fmtid && p.t == 'n' && fmt_is_date(table_fmt[fmtid] || String(fmtid))) {
var _d = SSF_parse_date_code(p.v + (date1904 ? 1462 : 0)); if(_d) { p.t = 'd'; p.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
if(opts.cellDates && fmtid && p.t == 'n' && SSF.is_date(SSF._table[fmtid] || String(fmtid))) {
var _d = SSF.parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
}
}
@ -104,7 +103,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
var wb = ({opts:{}}/*:any*/);
var Sheets = {};
if(DENSE != null && options.dense == null) options.dense = DENSE;
var out/*:Worksheet*/ = ({}/*:any*/); if(options.dense) out["!data"] = [];
var out/*:Worksheet*/ = ((options.dense ? [] : {})/*:any*/);
var Directory = {};
var range/*:Range*/ = ({}/*:any*/);
var last_formula = null;
@ -116,16 +115,16 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
var arrayf/*:Array<[Range, string]>*/ = [];
var temp_val/*:Cell*/;
var country;
var cell_valid = true;
var XFs = []; /* XF records */
var palette/*:Array<[number, number, number]>*/ = [];
var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false}, Views:[{}] }/*:any*/), wsprops = {};
var biff4w = false;
var get_rgb = function getrgb(icv/*:number*/)/*:[number, number, number]*/ {
if(icv < 8) return XLSIcv[icv];
if(icv < 64) return palette[icv-8] || XLSIcv[icv];
return XLSIcv[icv];
};
var process_cell_style = function pcs(line/*:any*/, options) {
var process_cell_style = function pcs(cell, line/*:any*/, options) {
var xfd = line.XF.data;
if(!xfd || !xfd.patternType || !options || !options.cellStyles) return;
line.s = ({}/*:any*/);
@ -135,9 +134,10 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; }
};
var addcell = function addcell(cell/*:any*/, line/*:any*/, options/*:any*/) {
if(!biff4w && file_depth > 1) return;
if(options.sheetRows && cell.r >= options.sheetRows) return;
if(options.cellStyles && line.XF && line.XF.data) process_cell_style(line, options);
if(file_depth > 1) return;
if(options.sheetRows && cell.r >= options.sheetRows) cell_valid = false;
if(!cell_valid) return;
if(options.cellStyles && line.XF && line.XF.data) process_cell_style(cell, line, options);
delete line.ixfe; delete line.XF;
lastcell = cell;
last_cell = encode_cell(cell);
@ -158,8 +158,8 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
}
{
if(options.dense) {
if(!out["!data"][cell.r]) out["!data"][cell.r] = [];
out["!data"][cell.r][cell.c] = line;
if(!out[cell.r]) out[cell.r] = [];
out[cell.r][cell.c] = line;
} else out[last_cell] = line;
}
};
@ -182,6 +182,8 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
var merges/*:Array<Range>*/ = [];
var objects = [];
var colinfo/*:Array<ColInfo>*/ = [], rowinfo/*:Array<RowInfo>*/ = [];
// eslint-disable-next-line no-unused-vars
var defwidth = 0, defheight = 0; // twips / MDW respectively
var seencol = false;
var supbooks = ([]/*:any*/); // 1-indexed, will hold extern names
supbooks.SheetNames = opts.snames;
@ -189,7 +191,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
supbooks.arrayf = opts.arrayf;
supbooks.names = [];
supbooks.XTI = [];
var last_RT = 0;
var last_Rn = '';
var file_depth = 0; /* TODO: make a real stack */
var BIFF2Fmt = 0, BIFF2FmtTable/*:Array<string>*/ = [];
var FilterDatabases = []; /* TODO: sort out supbooks and process elsewhere */
@ -202,44 +204,45 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
while(blob.l < blob.length - 1) {
var s = blob.l;
var RecordType = blob.read_shift(2);
if(RecordType === 0 && last_RT === 0x000a /* EOF */) break;
if(RecordType === 0 && last_Rn === 'EOF') break;
var length = (blob.l === blob.length ? 0 : blob.read_shift(2));
var R = XLSRecordEnum[RecordType];
if(file_depth == 0 && [0x0009, 0x0209, 0x0409, 0x0809].indexOf(RecordType) == -1 /* BOF */) break;
//console.log(RecordType.toString(16), RecordType, R, blob.l, length, blob.length);
//if(!R) console.log(blob.slice(blob.l, blob.l + length));
if(R && R.f) {
if(options.bookSheets) {
if(last_RT === 0x0085 /* BoundSheet8 */ && RecordType !== 0x0085 /* R.n !== 'BoundSheet8' */) break;
if(last_Rn === 'BoundSheet8' && R.n !== 'BoundSheet8') break;
}
last_RT = RecordType;
last_Rn = R.n;
if(R.r === 2 || R.r == 12) {
var rt = blob.read_shift(2); length -= 2;
if(!opts.enc && rt !== RecordType && (((rt&0xFF)<<8)|(rt>>8)) !== RecordType) throw new Error("rt mismatch: " + rt + "!=" + RecordType);
if(R.r == 12){
blob.l += 10; length -= 10;
} // skip FRT
if(R.r == 12){ blob.l += 10; length -= 10; } // skip FRT
}
//console.error(R,blob.l,length,blob.length);
var val/*:any*/ = ({}/*:any*/);
if(RecordType === 0x000a /* EOF */) val = /*::(*/R.f(blob, length, opts)/*:: :any)*/;
else val = /*::(*/slurp(RecordType, R, blob, length, opts)/*:: :any)*/;
if(R.n === 'EOF') val = /*::(*/R.f(blob, length, opts)/*:: :any)*/;
else val = /*::(*/slurp(R, blob, length, opts)/*:: :any)*/;
var Rn = R.n;
/*:: val = (val:any); */
if(file_depth == 0 && [0x0009, 0x0209, 0x0409, 0x0809].indexOf(last_RT) === -1 /* BOF */) continue;
switch(RecordType) {
case 0x0022 /* Date1904 */:
if(file_depth == 0 && Rn != 'BOF') continue;
/* nested switch statements to workaround V8 128 limit */
switch(Rn) {
/* Workbook Options */
case 'Date1904':
/*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
case 0x0086 /* WriteProtect */: wb.opts.WriteProtect = true; break;
case 0x002f /* FilePass */:
case 'WriteProtect': wb.opts.WriteProtect = true; break;
case 'FilePass':
if(!opts.enc) blob.l = 0;
opts.enc = val;
if(!options.password) throw new Error("File is password-protected");
if(val.valid == null) throw new Error("Encryption scheme unsupported");
if(!val.valid) throw new Error("Password is incorrect");
break;
case 0x005c /* WriteAccess */: opts.lastuser = val; break;
case 0x0042 /* CodePage */:
case 'WriteAccess': opts.lastuser = val; break;
case 'FileSharing': break; //TODO
case 'CodePage':
var cpval = Number(val);
/* overrides based on test cases */
switch(cpval) {
@ -250,33 +253,42 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
set_cp(opts.codepage = cpval);
seen_codepage = true;
break;
case 0x013d /* RRTabId */: opts.rrtabid = val; break;
case 0x0019 /* WinProtect */: opts.winlocked = val; break;
case 0x01b7 /* RefreshAll */: wb.opts["RefreshAll"] = val; break;
case 0x000c /* CalcCount */: wb.opts["CalcCount"] = val; break;
case 0x0010 /* CalcDelta */: wb.opts["CalcDelta"] = val; break;
case 0x0011 /* CalcIter */: wb.opts["CalcIter"] = val; break;
case 0x000d /* CalcMode */: wb.opts["CalcMode"] = val; break;
case 0x000e /* CalcPrecision */: wb.opts["CalcPrecision"] = val; break;
case 0x005f /* CalcSaveRecalc */: wb.opts["CalcSaveRecalc"] = val; break;
case 0x000f /* CalcRefMode */: opts.CalcRefMode = val; break; // TODO: implement R1C1
case 0x08a3 /* ForceFullCalculation */: wb.opts.FullCalc = val; break;
case 0x0081 /* WsBool */:
case 'RRTabId': opts.rrtabid = val; break;
case 'WinProtect': opts.winlocked = val; break;
case 'Template': break; // TODO
case 'BookBool': break; // TODO
case 'UsesELFs': break;
case 'MTRSettings': break;
case 'RefreshAll':
case 'CalcCount':
case 'CalcDelta':
case 'CalcIter':
case 'CalcMode':
case 'CalcPrecision':
case 'CalcSaveRecalc':
wb.opts[Rn] = val; break;
case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
case 'Uncalced': break;
case 'ForceFullCalculation': wb.opts.FullCalc = val; break;
case 'WsBool':
if(val.fDialog) out["!type"] = "dialog";
if(!val.fBelow) (out["!outline"] || (out["!outline"] = {})).above = true;
if(!val.fRight) (out["!outline"] || (out["!outline"] = {})).left = true;
break; // TODO
case 0x0043: /* BIFF2XF */ case 0x0243: /* BIFF3XF */ case 0x0443: /* BIFF4XF */
case 0x00e0 /* XF */:
case 'XF':
XFs.push(val); break;
case 0x01ae /* SupBook */:
case 'ExtSST': break; // TODO
case 'BookExt': break; // TODO
case 'RichTextStream': break;
case 'BkHim': break;
case 'SupBook':
supbooks.push([val]);
supbooks[supbooks.length-1].XTI = [];
break;
case 0x0023: case 0x0223 /* ExternName */:
case 'ExternName':
supbooks[supbooks.length-1].push(val);
break;
case 0x0018: case 0x0218 /* Lbl */:
case 'Index': break; // TODO
case 'Lbl':
last_lbl = ({
Name: val.Name,
Ref: stringify_formula(val.rgce,range,null,supbooks,opts)
@ -289,23 +301,26 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
if(val.rgce && val.rgce[0] && val.rgce[0][0] && val.rgce[0][0][0] == 'PtgArea3d')
FilterDatabases[val.itab - 1] = { ref: encode_range(val.rgce[0][0][1][2]) };
break;
case 0x0016 /* ExternCount */: opts.ExternCount = val; break;
case 0x0017 /* ExternSheet */:
case 'ExternCount': opts.ExternCount = val; break;
case 'ExternSheet':
if(supbooks.length == 0) { supbooks[0] = []; supbooks[0].XTI = []; }
supbooks[supbooks.length - 1].XTI = supbooks[supbooks.length - 1].XTI.concat(val); supbooks.XTI = supbooks.XTI.concat(val); break;
case 0x0894 /* NameCmt */:
case 'NameCmt':
/* TODO: search for correct name */
if(opts.biff < 8) break;
if(last_lbl != null) last_lbl.Comment = val[1];
break;
case 0x0012 /* Protect */: out["!protect"] = val; break; /* for sheet or book */
case 0x0013 /* Password */: if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
case 0x0085 /* BoundSheet8 */: {
Directory[opts.biff == 4 ? opts.snames.length : val.pos] = val;
case 'Protect': out["!protect"] = val; break; /* for sheet or book */
case 'Password': if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
case 'Prot4Rev': case 'Prot4RevPass': break; /*TODO: Revision Control*/
case 'BoundSheet8': {
Directory[val.pos] = val;
opts.snames.push(val.name);
} break;
case 0x000a /* EOF */: {
if(--file_depth ? !biff4w : biff4w) break;
case 'EOF': {
if(--file_depth) break;
if(range.e) {
if(range.e.r > 0 && range.e.c > 0) {
range.e.r--; range.e.c--;
@ -326,33 +341,29 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
Workbook.Sheets.push(wsprops);
}
if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out;
out = ({}/*:any*/); if(options.dense) out["!data"] = [];
out = ((options.dense ? [] : {})/*:any*/);
} break;
case 0x0009: case 0x0209: case 0x0409: case 0x0809 /* BOF */: {
case 'BOF': {
if(opts.biff === 8) opts.biff = {
0x0009: 2,
0x0209: 3,
0x0409: 4
/*::[*/0x0009/*::]*/:2,
/*::[*/0x0209/*::]*/:3,
/*::[*/0x0409/*::]*/:4
}[RecordType] || {
0x0200: 2,
0x0300: 3,
0x0400: 4,
0x0500: 5,
0x0600: 8,
0x0002: 2,
0x0007: 2
/*::[*/0x0200/*::]*/:2,
/*::[*/0x0300/*::]*/:3,
/*::[*/0x0400/*::]*/:4,
/*::[*/0x0500/*::]*/:5,
/*::[*/0x0600/*::]*/:8,
/*::[*/0x0002/*::]*/:2,
/*::[*/0x0007/*::]*/:2
}[val.BIFFVer] || 8;
opts.biffguess = val.BIFFVer == 0;
if(val.BIFFVer == 0 && val.dt == 0x1000) { opts.biff = 5; seen_codepage = true; set_cp(opts.codepage = 28591); }
if(opts.biff == 4 && val.dt & 0x100) biff4w = true;
if(opts.biff == 8 && val.BIFFVer == 0 && val.dt == 16) opts.biff = 2;
if(file_depth++ && !biff4w) break;
out = ({}/*:any*/); if(options.dense) out["!data"] = [];
if(file_depth++) break;
cell_valid = true;
out = ((options.dense ? [] : {})/*:any*/);
if(opts.biff < 8 && !seen_codepage) { seen_codepage = true; set_cp(opts.codepage = options.codepage || 1252); }
if(opts.biff == 4 && biff4w) {
cur_sheet = (Directory[opts.snames.indexOf(cur_sheet)+1] || {name:""}).name;
} else if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) {
if(opts.biff < 5) {
if(cur_sheet === "") cur_sheet = "Sheet1";
range = {s:{r:0,c:0},e:{r:0,c:0}};
/* fake BoundSheet8 */
@ -367,38 +378,40 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
objects = [];
opts.arrayf = arrayf = [];
colinfo = []; rowinfo = [];
defwidth = defheight = 0;
seencol = false;
wsprops = {Hidden:(Directory[s]||{hs:0}).hs, name:cur_sheet };
} break;
case 0x0203 /* Number */: case 0x0003 /* BIFF2NUM */: case 0x0002 /* BIFF2INT */: {
if(out["!type"] == "chart") if(options.dense ? (out["!data"][val.r]||[])[val.c]: out[encode_col(val.c) + encode_row(val.r)]) ++val.c;
case 'Number': case 'BIFF2NUM': case 'BIFF2INT': {
if(out["!type"] == "chart") if(options.dense ? (out[val.r]||[])[val.c]: out[encode_cell({c:val.c, r:val.r})]) ++val.c;
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe]||{}, v:val.val, t:'n'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
case 0x0005: case 0x0205 /* BoolErr */: {
case 'BoolErr': {
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
case 0x027e /* RK */: {
case 'RK': {
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
case 0x00bd /* MulRk */: {
case 'MulRk': {
for(var j = val.c; j <= val.C; ++j) {
var ixfe = val.rkrec[j-val.c][0];
temp_val= ({ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:j, r:val.r}, temp_val, options);
}
} break;
case 0x0006: case 0x0206: case 0x0406 /* Formula */: {
case 'Formula': {
if(val.val == 'String') { last_formula = val; break; }
temp_val = make_cell(val.val, val.cell.ixfe, val.tt);
temp_val.XF = XFs[temp_val.ixfe];
@ -408,15 +421,15 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
var _fe = encode_cell({r:_fr, c:_fc});
if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
else temp_val.F = ((options.dense ? (out["!data"][_fr]||[])[_fc]: out[_fe]) || {}).F;
else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F;
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
}
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell(val.cell, temp_val, options);
last_formula = val;
} break;
case 0x0007: case 0x0207 /* String */: {
case 'String': {
if(last_formula) { /* technically always true */
last_formula.val = val;
temp_val = make_cell(val, last_formula.cell.ixfe, 's');
@ -424,16 +437,16 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
if(options.cellFormula) {
temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
}
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell(last_formula.cell, temp_val, options);
last_formula = null;
} else throw new Error("String record expects Formula");
} break;
case 0x0021: case 0x0221 /* Array */: {
case 'Array': {
arrayf.push(val);
var _arraystart = encode_cell(val[0].s);
cc = options.dense ? (out["!data"][val[0].s.r]||[])[val[0].s.c] : out[_arraystart];
cc = options.dense ? (out[val[0].s.r]||[])[val[0].s.c] : out[_arraystart];
if(options.cellFormula && cc) {
if(!last_formula) break; /* technically unreachable */
if(!_arraystart || !cc) break;
@ -441,95 +454,99 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
cc.F = encode_range(val[0]);
}
} break;
case 0x04bc /* ShrFmla */: {
case 'ShrFmla': {
if(!cell_valid) break;
if(!options.cellFormula) break;
if(last_cell) {
/* TODO: capture range */
if(!last_formula) break; /* technically unreachable */
sharedf[encode_cell(last_formula.cell)]= val[0];
cc = options.dense ? (out["!data"][last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
(cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
}
} break;
case 0x00fd /* LabelSst */:
case 'LabelSst':
temp_val=make_cell(sst[val.isst].t, val.ixfe, 's');
if(sst[val.isst].h) temp_val.h = sst[val.isst].h;
temp_val.XF = XFs[temp_val.ixfe];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
break;
case 0x0201 /* Blank */: if(options.sheetStubs) {
case 'Blank': if(options.sheetStubs) {
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
case 0x00be /* MulBlank */: if(options.sheetStubs) {
case 'MulBlank': if(options.sheetStubs) {
for(var _j = val.c; _j <= val.C; ++_j) {
var _ixfe = val.ixfe[_j-val.c];
temp_val= ({ixfe:_ixfe, XF:XFs[_ixfe], t:'z'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:_j, r:val.r}, temp_val, options);
}
} break;
case 0x00d6 /* RString */:
case 0x0204 /* Label */: case 0x0004 /* BIFF2STR */:
case 'RString':
case 'Label': case 'BIFF2STR':
temp_val=make_cell(val.val, val.ixfe, 's');
temp_val.XF = XFs[temp_val.ixfe];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
break;
case 0x0000: case 0x0200 /* Dimensions */: {
case 'Dimensions': {
if(file_depth === 1) range = val; /* TODO: stack */
} break;
case 0x00fc /* SST */: {
case 'SST': {
sst = val;
} break;
case 0x041e /* Format */: { /* val = [id, fmt] */
if(opts.biff >= 3 && opts.biff <= 4) {
case 'Format': { /* val = [id, fmt] */
if(opts.biff == 4) {
BIFF2FmtTable[BIFF2Fmt++] = val[1];
for(var b4idx = 0; b4idx < BIFF2Fmt + 163; ++b4idx) if(table_fmt[b4idx] == val[1]) break;
if(b4idx >= 163) SSF__load(val[1], BIFF2Fmt + 163);
for(var b4idx = 0; b4idx < BIFF2Fmt + 163; ++b4idx) if(SSF._table[b4idx] == val[1]) break;
if(b4idx >= 163) SSF.load(val[1], BIFF2Fmt + 163);
}
else SSF__load(val[1], val[0]);
else SSF.load(val[1], val[0]);
} break;
case 0x001e /* BIFF2FORMAT */: {
case 'BIFF2FORMAT': {
BIFF2FmtTable[BIFF2Fmt++] = val;
for(var b2idx = 0; b2idx < BIFF2Fmt + 163; ++b2idx) if(table_fmt[b2idx] == val) break;
if(b2idx >= 163) SSF__load(val, BIFF2Fmt + 163);
for(var b2idx = 0; b2idx < BIFF2Fmt + 163; ++b2idx) if(SSF._table[b2idx] == val) break;
if(b2idx >= 163) SSF.load(val, BIFF2Fmt + 163);
} break;
case 0x00e5 /* MergeCells */: merges = merges.concat(val); break;
case 'MergeCells': merges = merges.concat(val); break;
case 0x005d /* Obj */: objects[val.cmo[0]] = opts.lastobj = val; break;
case 0x01b6 /* TxO */: opts.lastobj.TxO = val; break;
case 0x007f /* ImData */: opts.lastobj.ImData = val; break;
case 'Obj': objects[val.cmo[0]] = opts.lastobj = val; break;
case 'TxO': opts.lastobj.TxO = val; break;
case 'ImData': opts.lastobj.ImData = val; break;
case 0x01b8 /* HLink */: {
case 'HLink': {
for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
cc = options.dense ? (out["!data"][rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
if(cc) cc.l = val[1];
}
} break;
case 0x0800 /* HLinkTooltip */: {
case 'HLinkTooltip': {
for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
cc = options.dense ? (out["!data"][rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
if(cc && cc.l) cc.l.Tooltip = val[1];
}
} break;
case 0x001c /* Note */: {
/* TODO: comment continuation (row == -1 / 0xFFFF) */
cc = options.dense ? (out["!data"][val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
/* Comments */
case 'Note': {
if(opts.biff <= 5 && opts.biff >= 2) break; /* TODO: BIFF5 */
cc = options.dense ? (out[val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
var noteobj = objects[val[2]];
if(!cc) {
if(options.dense) {
if(!out["!data"][val[0].r]) out["!data"][val[0].r] = [];
cc = out["!data"][val[0].r][val[0].c] = ({t:"z"}/*:any*/);
if(!out[val[0].r]) out[val[0].r] = [];
cc = out[val[0].r][val[0].c] = ({t:"z"}/*:any*/);
} else {
cc = out[encode_cell(val[0])] = ({t:"z"}/*:any*/);
}
@ -539,24 +556,26 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
range.s.c = Math.min(range.s.c, val[0].c);
}
if(!cc.c) cc.c = [];
if(opts.biff <= 5 && opts.biff >= 2) cmnt = {a:"SheetJ5", t:val[1]};
else {
var noteobj = objects[val[2]];
cmnt = {a:val[1],t:noteobj.TxO.t};
if(val[3] != null && !(val[3] & 0x02)) cc.c.hidden = true;
}
cmnt = {a:val[1],t:noteobj.TxO.t};
cc.c.push(cmnt);
} break;
case 0x087d /* XFExt */: update_xfext(XFs[val.ixfe], val.ext); break;
case 0x007d /* ColInfo */: {
default: switch(R.n) { /* nested */
case 'ClrtClient': break;
case 'XFExt': update_xfext(XFs[val.ixfe], val.ext); break;
case 'DefColWidth': defwidth = val; break;
case 'DefaultRowHeight': defheight = val[1]; break; // TODO: flags
case 'ColInfo': {
if(!opts.cellStyles) break;
while(val.e >= val.s) {
colinfo[val.e--] = { width: val.w/256, level: (val.level || 0), hidden: !!(val.flags & 1) };
colinfo[val.e--] = { width: val.w/256 };
if(!seencol) { seencol = true; find_mdw_colw(val.w/256); }
process_col(colinfo[val.e+1]);
}
} break;
case 0x0208 /* Row */: {
case 'Row': {
var rowobj = {};
if(val.level != null) { rowinfo[val.r] = rowobj; rowobj.level = val.level; }
if(val.hidden) { rowinfo[val.r] = rowobj; rowobj.hidden = true; }
@ -565,47 +584,274 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
rowobj.hpt = val.hpt; rowobj.hpx = pt2px(val.hpt);
}
} break;
case 0x0026 /* LeftMargin */:
case 0x0027 /* RightMargin */:
case 0x0028 /* TopMargin */:
case 0x0029 /* BottomMargin */:
case 'LeftMargin':
case 'RightMargin':
case 'TopMargin':
case 'BottomMargin':
if(!out['!margins']) default_margins(out['!margins'] = {});
out['!margins'][({0x26: "left", 0x27:"right", 0x28:"top", 0x29:"bottom"})[RecordType]] = val;
out['!margins'][Rn.slice(0,-6).toLowerCase()] = val;
break;
case 0x00a1 /* Setup */: // TODO
case 'Setup': // TODO
if(!out['!margins']) default_margins(out['!margins'] = {});
out['!margins'].header = val.header;
out['!margins'].footer = val.footer;
break;
case 0x023e /* Window2 */: // TODO
case 'Window2': // TODO
// $FlowIgnore
if(val.RTL) Workbook.Views[0].RTL = true;
break;
case 0x0092 /* Palette */: palette = val; break;
case 0x0896 /* Theme */: themes = val; break;
case 0x008c /* Country */: country = val; break;
case 0x01ba /* CodeName */: {
case 'Header': break; // TODO
case 'Footer': break; // TODO
case 'HCenter': break; // TODO
case 'VCenter': break; // TODO
case 'Pls': break; // TODO
case 'GCW': break;
case 'LHRecord': break;
case 'DBCell': break; // TODO
case 'EntExU2': break; // TODO
case 'SxView': break; // TODO
case 'Sxvd': break; // TODO
case 'SXVI': break; // TODO
case 'SXVDEx': break; // TODO
case 'SxIvd': break; // TODO
case 'SXString': break; // TODO
case 'Sync': break;
case 'Addin': break;
case 'SXDI': break; // TODO
case 'SXLI': break; // TODO
case 'SXEx': break; // TODO
case 'QsiSXTag': break; // TODO
case 'Selection': break;
case 'Feat': break;
case 'FeatHdr': case 'FeatHdr11': break;
case 'Feature11': case 'Feature12': case 'List12': break;
case 'Country': country = val; break;
case 'RecalcId': break;
case 'DxGCol': break; // TODO: htmlify
case 'Fbi': case 'Fbi2': case 'GelFrame': break;
case 'Font': break; // TODO
case 'XFCRC': break; // TODO
case 'Style': break; // TODO
case 'StyleExt': break; // TODO
case 'Palette': palette = val; break;
case 'Theme': themes = val; break;
/* Protection */
case 'ScenarioProtect': break;
case 'ObjProtect': break;
/* Conditional Formatting */
case 'CondFmt12': break;
/* Table */
case 'Table': break; // TODO
case 'TableStyles': break; // TODO
case 'TableStyle': break; // TODO
case 'TableStyleElement': break; // TODO
/* PivotTable */
case 'SXStreamID': break; // TODO
case 'SXVS': break; // TODO
case 'DConRef': break; // TODO
case 'SXAddl': break; // TODO
case 'DConBin': break; // TODO
case 'DConName': break; // TODO
case 'SXPI': break; // TODO
case 'SxFormat': break; // TODO
case 'SxSelect': break; // TODO
case 'SxRule': break; // TODO
case 'SxFilt': break; // TODO
case 'SxItm': break; // TODO
case 'SxDXF': break; // TODO
/* Scenario Manager */
case 'ScenMan': break;
/* Data Consolidation */
case 'DCon': break;
/* Watched Cell */
case 'CellWatch': break;
/* Print Settings */
case 'PrintRowCol': break;
case 'PrintGrid': break;
case 'PrintSize': break;
case 'XCT': break;
case 'CRN': break;
case 'Scl': {
//console.log("Zoom Level:", val[0]/val[1],val);
} break;
case 'SheetExt': {
/* empty */
} break;
case 'SheetExtOptional': {
/* empty */
} break;
/* VBA */
case 'ObNoMacros': {
/* empty */
} break;
case 'ObProj': {
/* empty */
} break;
case 'CodeName': {
/*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
if(!cur_sheet) Workbook.WBProps.CodeName = val || "ThisWorkbook";
else wsprops.CodeName = val || wsprops.name;
} break;
}
} else {
if(!R) console.error("Missing Info for XLS Record 0x" + RecordType.toString(16));
blob.l += length;
}
case 'GUIDTypeLib': {
/* empty */
} break;
case 'WOpt': break; // TODO: WTF?
case 'PhoneticInfo': break;
case 'OleObjectSize': break;
/* Differential Formatting */
case 'DXF': case 'DXFN': case 'DXFN12': case 'DXFN12List': case 'DXFN12NoCB': break;
/* Data Validation */
case 'Dv': case 'DVal': break;
/* Data Series */
case 'BRAI': case 'Series': case 'SeriesText': break;
/* Data Connection */
case 'DConn': break;
case 'DbOrParamQry': break;
case 'DBQueryExt': break;
case 'OleDbConn': break;
case 'ExtString': break;
/* Formatting */
case 'IFmtRecord': break;
case 'CondFmt': case 'CF': case 'CF12': case 'CFEx': break;
/* Explicitly Ignored */
case 'Excel9File': break;
case 'Units': break;
case 'InterfaceHdr': case 'Mms': case 'InterfaceEnd': case 'DSF': break;
case 'BuiltInFnGroupCount': /* 2.4.30 0x0E or 0x10 but excel 2011 generates 0x11? */ break;
/* View Stuff */
case 'Window1': case 'HideObj': case 'GridSet': case 'Guts':
case 'UserBView': case 'UserSViewBegin': case 'UserSViewEnd': break;
case 'Pane': break;
default: switch(R.n) { /* nested */
/* Chart */
case 'Dat':
case 'Begin': case 'End':
case 'StartBlock': case 'EndBlock':
case 'Frame': case 'Area':
case 'Axis': case 'AxisLine': case 'Tick': break;
case 'AxesUsed':
case 'CrtLayout12': case 'CrtLayout12A': case 'CrtLink': case 'CrtLine': case 'CrtMlFrt': case 'CrtMlFrtContinue': break;
case 'LineFormat': case 'AreaFormat':
case 'Chart': case 'Chart3d': case 'Chart3DBarShape': case 'ChartFormat': case 'ChartFrtInfo': break;
case 'PlotArea': case 'PlotGrowth': break;
case 'SeriesList': case 'SerParent': case 'SerAuxTrend': break;
case 'DataFormat': case 'SerToCrt': case 'FontX': break;
case 'CatSerRange': case 'AxcExt': case 'SerFmt': break;
case 'ShtProps': break;
case 'DefaultText': case 'Text': case 'CatLab': break;
case 'DataLabExtContents': break;
case 'Legend': case 'LegendException': break;
case 'Pie': case 'Scatter': break;
case 'PieFormat': case 'MarkerFormat': break;
case 'StartObject': case 'EndObject': break;
case 'AlRuns': case 'ObjectLink': break;
case 'SIIndex': break;
case 'AttachedLabel': case 'YMult': break;
/* Chart Group */
case 'Line': case 'Bar': break;
case 'Surf': break;
/* Axis Group */
case 'AxisParent': break;
case 'Pos': break;
case 'ValueRange': break;
/* Pivot Chart */
case 'SXViewEx9': break; // TODO
case 'SXViewLink': break;
case 'PivotChartBits': break;
case 'SBaseRef': break;
case 'TextPropsStream': break;
/* Chart Misc */
case 'LnExt': break;
case 'MkrExt': break;
case 'CrtCoopt': break;
/* Query Table */
case 'Qsi': case 'Qsif': case 'Qsir': case 'QsiSXTag': break;
case 'TxtQry': break;
/* Filter */
case 'FilterMode': break;
case 'AutoFilter': case 'AutoFilterInfo': break;
case 'AutoFilter12': break;
case 'DropDownObjIds': break;
case 'Sort': break;
case 'SortData': break;
/* Drawing */
case 'ShapePropsStream': break;
case 'MsoDrawing': case 'MsoDrawingGroup': case 'MsoDrawingSelection': break;
/* Pub Stuff */
case 'WebPub': case 'AutoWebPub': break;
/* Print Stuff */
case 'HeaderFooter': case 'HFPicture': case 'PLV':
case 'HorizontalPageBreaks': case 'VerticalPageBreaks': break;
/* Behavioral */
case 'Backup': case 'CompressPictures': case 'Compat12': break;
/* Should not Happen */
case 'Continue': case 'ContinueFrt12': break;
/* Future Records */
case 'FrtFontList': case 'FrtWrapper': break;
default: switch(R.n) { /* nested */
/* BIFF5 records */
case 'TabIdConf': case 'Radar': case 'RadarArea': case 'DropBar': case 'Intl': case 'CoordList': case 'SerAuxErrBar': break;
/* BIFF2-4 records */
case 'BIFF2FONTCLR': case 'BIFF2FMTCNT': case 'BIFF2FONTXTRA': break;
case 'BIFF2XF': case 'BIFF3XF': case 'BIFF4XF': break;
case 'BIFF4FMTCNT': case 'BIFF2ROW': case 'BIFF2WINDOW2': break;
/* Miscellaneous */
case 'SCENARIO': case 'DConBin': case 'PicF': case 'DataLabExt':
case 'Lel': case 'BopPop': case 'BopPopCustom': case 'RealTimeData':
case 'Name': break;
case 'LHNGraph': case 'FnGroupName': case 'AddMenu': case 'LPr': break;
case 'ListObj': case 'ListField': break;
case 'RRSort': break;
case 'BigName': break;
case 'ToolbarHdr': case 'ToolbarEnd': break;
case 'DDEObjName': break;
case 'FRTArchId$': break;
default: if(options.WTF) throw 'Unrecognized Record ' + R.n;
}}}}
} else blob.l += length;
}
wb.SheetNames=keys(Directory).sort(function(a,b) { return Number(a) - Number(b); }).map(function(x){return Directory[x].name;});
if(!options.bookSheets) wb.Sheets=Sheets;
if(!wb.SheetNames.length && Preamble["!ref"]) {
wb.SheetNames.push("Sheet1");
/*jshint -W069 */
if(wb.Sheets) wb.Sheets["Sheet1"] = Preamble;
/*jshint +W069 */
} else wb.Preamble=Preamble;
if(wb.Sheets) FilterDatabases.forEach(function(r,i) { wb.Sheets[wb.SheetNames[i]]['!autofilter'] = r; });
wb.Preamble=Preamble;
wb.Strings = sst;
wb.SSF = dup(table_fmt);
wb.SSF = SSF.get_table();
if(opts.enc) wb.Encryption = opts.enc;
if(themes) wb.Themes = themes;
wb.Metadata = {};
@ -623,18 +869,18 @@ var PSCLSID = {
};
function parse_xls_props(cfb/*:CFBContainer*/, props, o) {
/* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
var DSI = CFB.find(cfb, '/!DocumentSummaryInformation');
var DSI = CFB.find(cfb, '!DocumentSummaryInformation');
if(DSI && DSI.size > 0) try {
var DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI, PSCLSID.DSI);
for(var d in DocSummary) props[d] = DocSummary[d];
} catch(e) {if(o.WTF) console.error(e && e.message || e);}
} catch(e) {if(o.WTF) throw e;/* empty */}
/* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
var SI = CFB.find(cfb, '/!SummaryInformation');
var SI = CFB.find(cfb, '!SummaryInformation');
if(SI && SI.size > 0) try {
var Summary = parse_PropertySetStream(SI, SummaryPIDSI, PSCLSID.SI);
for(var s in Summary) if(props[s] == null) props[s] = Summary[s];
} catch(e) {if(o.WTF) console.error(e && e.message || e);}
} catch(e) {if(o.WTF) throw e;/* empty */}
if(props.HeadingPairs && props.TitlesOfParts) {
load_props_pairs(props.HeadingPairs, props.TitlesOfParts, props, o);
@ -644,8 +890,6 @@ function parse_xls_props(cfb/*:CFBContainer*/, props, o) {
function write_xls_props(wb/*:Workbook*/, cfb/*:CFBContainer*/) {
var DSEntries = [], SEntries = [], CEntries = [];
var i = 0, Keys;
var DocSummaryRE/*:{[key:string]:string}*/ = evert_key(DocSummaryPIDDSI, "n");
var SummaryRE/*:{[key:string]:string}*/ = evert_key(SummaryPIDSI, "n");
if(wb.Props) {
Keys = keys(wb.Props);
// $FlowIgnore
@ -658,7 +902,7 @@ function write_xls_props(wb/*:Workbook*/, cfb/*:CFBContainer*/) {
}
var CEntries2 = [];
for(i = 0; i < CEntries.length; ++i) {
if(XLSPSSkip.indexOf(CEntries[i][0]) > -1 || PseudoPropsPairs.indexOf(CEntries[i][0]) > -1) continue;
if(XLSPSSkip.indexOf(CEntries[i][0]) > -1) continue;
if(CEntries[i][1] == null) continue;
CEntries2.push(CEntries[i]);
}
@ -678,7 +922,7 @@ if(cfb.FullPaths) {
WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
} else {
switch(options.type) {
case 'base64': cfb = s2a(Base64_decode(cfb)); break;
case 'base64': cfb = s2a(Base64.decode(cfb)); break;
case 'binary': cfb = s2a(cfb); break;
case 'buffer': break;
case 'array': if(!Array.isArray(cfb)) cfb = Array.prototype.slice.call(cfb); break;
@ -698,8 +942,6 @@ else/*:: if(cfb instanceof CFBContainer) */ {
else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
/* Quattro Pro 9 */
else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
/* Works 4 for Mac */
else if((_data=CFB.find(cfb, 'MN0')) && _data.content) throw new Error("Unsupported Works 4 for Mac file");
else throw new Error("Cannot find Workbook stream");
if(options.bookVBA && cfb.FullPaths && CFB.find(cfb, '/_VBA_PROJECT_CUR/VBA/dir')) WorkbookP.vbaraw = make_vba_xls(cfb);
}

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
function write_biff_rec(ba/*:BufArray*/, type/*:number*/, payload, length/*:?number*/)/*:void*/ {
var t/*:number*/ = type;
function write_biff_rec(ba/*:BufArray*/, type/*:number|string*/, payload, length/*:?number*/)/*:void*/ {
var t/*:number*/ = +type || +XLSRE[/*::String(*/type/*::)*/];
if(isNaN(t)) return;
var len = length || (payload||[]).length || 0;
var o = ba.next(4);
@ -8,10 +8,10 @@ function write_biff_rec(ba/*:BufArray*/, type/*:number*/, payload, length/*:?num
if(/*:: len != null &&*/len > 0 && is_buf(payload)) ba.push(payload);
}
function write_biff_continue(ba/*:BufArray*/, type/*:number*/, payload, length/*:?number*/)/*:void*/ {
function write_biff_continue(ba/*:BufArray*/, type/*:number|string*/, payload, length/*:?number*/)/*:void*/ {
var len = length || (payload||[]).length || 0;
if(len <= 8224) return write_biff_rec(ba, type, payload, len);
var t = type;
var t/*:number*/ = +type || +XLSRE[/*::String(*/type/*::)*/];
if(isNaN(t)) return;
var parts = payload.parts || [], sidx = 0;
var i = 0, w = 0;
@ -31,10 +31,20 @@ function write_biff_continue(ba/*:BufArray*/, type/*:number*/, payload, length/*
}
}
function write_BIFF2Cell(out, r/*:number*/, c/*:number*/) {
if(!out) out = new_buf(7);
out.write_shift(2, r);
out.write_shift(2, c);
out.write_shift(2, 0);
out.write_shift(1, 0);
return out;
}
function write_BIFF2BERR(r/*:number*/, c/*:number*/, val, t/*:?string*/) {
var out = new_buf(9);
write_BIFF2Cell(out, r, c);
write_Bes(val, t || 'b', out);
if(t == 'e') { out.write_shift(1, val); out.write_shift(1, 1); }
else { out.write_shift(1, val?1:0); out.write_shift(1, 0); }
return out;
}
@ -47,373 +57,64 @@ function write_BIFF2LABEL(r/*:number*/, c/*:number*/, val) {
return out.l < out.length ? out.slice(0, out.l) : out;
}
function write_comments_biff2(ba/*:BufArray*/, comments/*:Array<[Comment[], number, number]>*/) {
comments.forEach(function(data) {
var text = data[0].map(function(cc) { return cc.t; }).join("");
// TODO: should '\n' be translated to '\r' to correct for Excel 5.0 bug when exporting to BIFF2/3 ?
if(text.length <= 2048) return write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text, data[1], data[2]));
write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text.slice(0, 2048), data[1], data[2], text.length));
for(var i = 2048; i < text.length; i += 2048)
write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text.slice(i, Math.min(i+2048, text.length)), -1, -1, Math.min(2048, text.length - i)));
});
}
/* TODO: BIFF3/4 use different records -- see comments*/
function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/) {
var ifmt = 0;
if(cell.z != null) {
ifmt = opts._BIFF2FmtTable.indexOf(cell.z);
if(ifmt == -1) { opts._BIFF2FmtTable.push(cell.z); ifmt = opts._BIFF2FmtTable.length - 1; }
}
var ixfe = 0;
if(cell.z != null) {
for(; ixfe < opts.cellXfs.length; ++ixfe) if(opts.cellXfs[ixfe].numFmtId == ifmt) break;
if(ixfe == opts.cellXfs.length) opts.cellXfs.push({numFmtId: ifmt});
}
function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*//*::, opts*/) {
if(cell.v != null) switch(cell.t) {
case 'd': case 'n':
var v = cell.t == 'd' ? datenum(parseDate(cell.v, date1904), date1904) : cell.v;
if(opts.biff == 2 && (v == (v|0)) && (v >= 0) && (v < 65536))
// 0x027E (RK) in BIFF3/4
write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v, ixfe, ifmt));
else if(isNaN(v))
// 0x0205 in BIFF3/4
write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x24, "e")); // #NUM!
else if(!isFinite(v))
// 0x0205 in BIFF3/4
write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x07, "e")); // #DIV/0!
var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
if((v == (v|0)) && (v >= 0) && (v < 65536))
write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v));
else
// 0x0203 in BIFF3/4
write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v, ixfe, ifmt));
write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v));
return;
case 'b': case 'e':
// 0x0205 in BIFF3/4
write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
/* TODO: codepage, sst */
case 's': case 'str':
// 0x0204 in BIFF3/4
write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v == null ? "" : String(cell.v).slice(0,255)));
write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v));
return;
}
// 0x0201 in BIFF3/4
write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
}
function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
var dense = ws["!data"] != null;
var range = safe_decode_range(ws['!ref'] || "A1"), rr = "", cols/*:Array<string>*/ = [];
function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
var dense = Array.isArray(ws);
var range = safe_decode_range(ws['!ref'] || "A1"), ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
range.e.r = Math.min(range.e.r, 0x3FFF);
range.e.r = Math.min(range.e.c, 0x3FFF);
ref = encode_range(range);
}
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
var row = [], comments = [];
/* TODO: 0x0000 / 0x0200 dimensions? */
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
for(var R = range.s.r; R <= range.e.r; ++R) {
if(dense) row = ws["!data"][R] || [];
rr = encode_row(R);
for(C = range.s.c; C <= range.e.c; ++C) {
var cell = dense ? row[C] : ws[cols[C] + rr];
for(var C = range.s.c; C <= range.e.c; ++C) {
if(R === range.s.r) cols[C] = encode_col(C);
ref = cols[C] + rr;
var cell = dense ? (ws[R]||[])[C] : ws[ref];
if(!cell) continue;
/* write cell */
write_ws_biff2_cell(ba, cell, R, C, opts, date1904);
if(cell.c) comments.push([cell.c, R, C]);
write_ws_biff2_cell(ba, cell, R, C, opts);
}
}
/* ... 0x12 0x19 0x13 (Password) */
write_comments_biff2(ba, comments);
/* 0x3d (Window1) ... */
}
/* Based on test files */
function write_biff2_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
var o = opts || {};
if(DENSE != null && o.dense == null) o.dense = DENSE;
var ba = buf_array();
var idx = 0;
for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i;
if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
write_biff_rec(ba, (o.biff == 4 ? 0x0409 : (o.biff == 3 ? 0x0209 : 0x0009)), write_BOF(wb, 0x10, o));
if(((wb.Workbook||{}).WBProps||{}).date1904) write_biff_rec(ba, 0x0022, writebool(true));
o.cellXfs = [{numFmtId: 0}];
o._BIFF2FmtTable/*:Array<string>*/ = ["General"]; o._Fonts = [];
var body = buf_array();
write_ws_biff2(body, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
o._BIFF2FmtTable.forEach(function(f) {
if(o.biff <= 3) write_biff_rec(ba, 0x001E, write_BIFF2Format(f));
else write_biff_rec(ba, 0x041E, write_BIFF4Format(f));
});
o.cellXfs.forEach(function(xf) {
switch(o.biff) {
case 2: write_biff_rec(ba, 0x0043, write_BIFF2XF(xf)); break;
case 3: write_biff_rec(ba, 0x0243, write_BIFF3XF(xf)); break;
case 4: write_biff_rec(ba, 0x0443, write_BIFF4XF(xf)); break;
}
});
delete o._BIFF2FmtTable; delete o.cellXfs; delete o._Fonts;
ba.push(body.end());
write_biff_rec(ba, 0x0009, write_BOF(wb, 0x10, o));
/* ... */
write_ws_biff2(ba, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
/* ... */
write_biff_rec(ba, 0x000A);
return ba.end();
}
var b8oid = 1, b8ocnts/*:Array<[number, number, number]>*/ = [];
function write_MsoDrawingGroup() {
var buf = new_buf(82 + 8 * b8ocnts.length);
/* [MS-ODRAW] 2.2.12 OfficeArtDggContainer */
buf.write_shift(2, 0x0F);
buf.write_shift(2, 0xF000);
buf.write_shift(4, 74 + 8 * b8ocnts.length);
/* 2.2.48 OfficeArtFDGGBlock */
{
buf.write_shift(2, 0);
buf.write_shift(2, 0xF006);
buf.write_shift(4, 16 + 8 * b8ocnts.length);
/* 2.2.47 OfficeArtFDGG */
{
buf.write_shift(4, b8oid);
buf.write_shift(4, b8ocnts.length+1);
var acc = 0; for(var i = 0; i < b8ocnts.length; ++i) acc += (b8ocnts[i] && b8ocnts[i][1] || 0); buf.write_shift(4, acc);
buf.write_shift(4, b8ocnts.length);
}
/* 2.2.46 OfficeArtIDCL + */
b8ocnts.forEach(function(b8) {
buf.write_shift(4, b8[0]);
buf.write_shift(4, b8[2]);
});
}
/* 2.2.9 OfficeArtFOPT */
{
buf.write_shift(2, 0x33); // 0x03 | (3 << 4)
buf.write_shift(2, 0xF00B);
buf.write_shift(4, 0x12); // 3 * 6
/* 2.3.21.15 Text Boolean Properties */
buf.write_shift(2, 0xBF); buf.write_shift(4, 0x00080008);
/* 2.3.7.2 fillColor */
buf.write_shift(2, 0x0181); buf.write_shift(4, 0x08000041);
/* 2.3.8.1 lineColor */
buf.write_shift(2, 0x01C0); buf.write_shift(4, 0x08000040);
}
/* 2.2.45 OfficeArtSplitMenuColorContainer */
{
buf.write_shift(2, 0x40);
buf.write_shift(2, 0xF11E);
buf.write_shift(4, 16);
buf.write_shift(4, 0x0800000D);
buf.write_shift(4, 0x0800000C);
buf.write_shift(4, 0x08000017);
buf.write_shift(4, 0x100000F7);
}
return buf;
}
function write_comments_biff8(ba/*:BufArray*/, comments/*:Array<[Comment[], number, number]>*/) {
var notes/*:Array<RawData>*/ = [], sz = 0, pl = buf_array(), baseid = b8oid;
var _oasc;
comments.forEach(function(c, ci) {
var author = "";
var text = c[0].map(function(t) { if(t.a && !author) author = t.a; return t.t; }).join("");
++b8oid;
/* 2.2.14 OfficeArtSpContainer */
{
var oasc = new_buf(0x96);
oasc.write_shift(2, 0x0F);
oasc.write_shift(2, 0xF004);
oasc.write_shift(4, 0x96);
/* 2.2.40 OfficeArtFSP */
{
oasc.write_shift(2, 0xca2); // 0x02 | (0xca << 4)
oasc.write_shift(2, 0xF00A);
oasc.write_shift(4, 8);
oasc.write_shift(4, b8oid);
oasc.write_shift(4, 0xA00);
}
/* 2.2.9 OfficeArtFOPT */
{
oasc.write_shift(2, 0xE3); // 0x03 | (14 << 4)
oasc.write_shift(2, 0xF00B);
oasc.write_shift(4, 0x54); // 14 * 6
/* 2.3.21.1 ITxid */
oasc.write_shift(2, 0x80); oasc.write_shift(4, 0);
/* 2.3.21.12 txdir */
oasc.write_shift(2, 0x8B); oasc.write_shift(4, 0x02);
/* 2.3.21.15 Text Boolean Properties */
oasc.write_shift(2, 0xBF); oasc.write_shift(4, 0x00080008);
/* 2.3.6.30 cxk */
oasc.write_shift(2, 0x0158); oasc.l += 4;
/* 2.3.7.2 fillColor */
oasc.write_shift(2, 0x0181); oasc.write_shift(4, 0x08000050);
/* 2.3.7.4 fillBackColor */
oasc.write_shift(2, 0x0183); oasc.write_shift(4, 0x08000050);
/* 2.3.7.6 fillCrMod */
oasc.write_shift(2, 0x0185); oasc.write_shift(4, 0x100000F4);
/* 2.3.7.43 Fill Style Boolean Properties */
oasc.write_shift(2, 0x01BF); oasc.write_shift(4, 0x00100010);
/* 2.3.8.1 lineColor */
oasc.write_shift(2, 0x01C0); oasc.write_shift(4, 0x08000051);
/* 2.3.8.4 lineCrMod */
oasc.write_shift(2, 0x01C3); oasc.write_shift(4, 0x100000F4);
/* 2.3.13.2 shadowColor */
oasc.write_shift(2, 0x0201); oasc.write_shift(4, 0x08000051);
/* 2.3.13.4 shadowCrMod */
oasc.write_shift(2, 0x0203); oasc.write_shift(4, 0x100000F4);
/* 2.3.13.23 Shadow Style Boolean Properties */
oasc.write_shift(2, 0x023F); oasc.write_shift(4, 0x00030001);
/* 2.3.4.44 Group Shape Boolean Properties */
oasc.write_shift(2, 0x03BF); oasc.write_shift(4, 0x00020000 | (c[0].hidden ? 2 : 0));
}
/* [MS-XLS] 2.5.193 OfficeArtClientAnchorSheet */
{
oasc.l += 2;
oasc.write_shift(2, 0xF010);
oasc.write_shift(4, 0x12);
oasc.write_shift(2, 0x3); // do not move or size with cells
oasc.write_shift(2, c[2] + 2); oasc.l += 2;
oasc.write_shift(2, c[1] + 1); oasc.l += 2;
oasc.write_shift(2, c[2] + 4); oasc.l += 2;
oasc.write_shift(2, c[1] + 5); oasc.l += 2;
}
/* [MS-XLS] 2.5.194 OfficeArtClientData */
{
oasc.l += 2;
oasc.write_shift(2, 0xF011);
oasc.l += 4;
}
oasc.l = 0x96;
if(ci == 0) /* write_biff_rec(pl, 0x003C, oasc); */ _oasc = oasc;
else write_biff_rec(pl, 0x00EC, oasc);
}
sz += 0x96;
/* [MS-XLS] 2.4.181 Obj */
{
var obj = new_buf(52); // 22 + 26 + 4
/* [MS-XLS] 2.5.143 FtCmo */
obj.write_shift(2, 0x15);
obj.write_shift(2, 0x12);
obj.write_shift(2, 0x19);
obj.write_shift(2, b8oid);
obj.write_shift(2, 0);
obj.l = 22;
/* [MS-XLS] 2.5.149 FtNts */
obj.write_shift(2, 0x0D);
obj.write_shift(2, 0x16);
obj.write_shift(4, 0x62726272);
obj.write_shift(4, 0x95374305);
obj.write_shift(4, 0x80301328);
obj.write_shift(4, 0x69696904 + b8oid*256);
obj.write_shift(2,0);
obj.write_shift(4,0);
// reserved
obj.l += 4;
write_biff_rec(pl, 0x005D, obj);
}
/* [MS-XLS] 2.5.195 OfficeArtClientTextbox */
{
var oact = new_buf(8);
oact.l += 2;
oact.write_shift(2, 0xF00D);
oact.l += 4;
write_biff_rec(pl, 0x00EC, oact);
}
sz += 8;
/* [MS-XLS] 2.4.329 TxO */
{
var txo = new_buf(18);
txo.write_shift(2, 0x12);
txo.l += 8;
txo.write_shift(2, text.length);
txo.write_shift(2, 0x10);
txo.l += 4;
write_biff_rec(pl, 0x01b6, txo);
/* text continue record TODO: switch to wide strings */
{
var cont = new_buf(1 + text.length);
cont.write_shift(1, 0);
cont.write_shift(text.length, text, "sbcs");
write_biff_rec(pl, 0x003C, cont);
}
/* formatting continue records */
{
var conf = new_buf(0x10);
conf.l += 8;
conf.write_shift(2, text.length);
conf.l += 6;
write_biff_rec(pl, 0x003C, conf);
}
}
/* 2.4.179 Note */
{
var notesh = new_buf(12 + author.length);
notesh.write_shift(2, c[1]);
notesh.write_shift(2, c[2]);
notesh.write_shift(2, 0 | (c[0].hidden ? 0 : 2));
notesh.write_shift(2, b8oid);
notesh.write_shift(2, author.length);
notesh.write_shift(1, 0);
notesh.write_shift(author.length, author, "sbcs");
notesh.l ++;
notes.push(notesh);
}
});
/* [MS-ODRAW] 2.2.13 OfficeArtDgContainer */
{
var hdr = new_buf(80);
hdr.write_shift(2, 0x0F);
hdr.write_shift(2, 0xF002);
hdr.write_shift(4, sz + hdr.length - 8);
/* [MS-ODRAW] 2.2.49 OfficeArtFDG */
{
hdr.write_shift(2, 0x10);
hdr.write_shift(2, 0xF008);
hdr.write_shift(4, 0x08);
hdr.write_shift(4, comments.length + 1);
hdr.write_shift(4, b8oid);
}
/* [MS-ODRAW] 2.2.16 OfficeArtSpgrContainer */
{
hdr.write_shift(2, 0x0f);
hdr.write_shift(2, 0xF003);
hdr.write_shift(4, sz + 0x30);
/* [MS-ODRAW] 2.2.14 OfficeArtSpContainer */
{
hdr.write_shift(2, 0x0f);
hdr.write_shift(2, 0xF004);
hdr.write_shift(4, 0x28);
/* [MS-ODRAW] 2.2.38 OfficeArtFSPGR */
{
hdr.write_shift(2, 0x01);
hdr.write_shift(2, 0xF009);
hdr.write_shift(4, 0x10);
hdr.l += 16;
}
/* [MS-ODRAW] 2.2.40 OfficeArtFSP */
{
hdr.write_shift(2, 0x02);
hdr.write_shift(2, 0xF00A);
hdr.write_shift(4, 0x08);
hdr.write_shift(4, baseid);
hdr.write_shift(4, 0x05);
}
}
}
write_biff_rec(ba, 0x00EC, /* hdr */ _oasc ? bconcat([hdr, _oasc]) : hdr);
}
ba.push(pl.end());
notes.forEach(function(n) { write_biff_rec(ba, 0x001C, n); });
b8ocnts.push([baseid, comments.length + 1, b8oid]);
++b8oid;
}
function write_FONTS_biff8(ba, data, opts) {
write_biff_rec(ba, 0x0031 /* Font */, write_Font({
write_biff_rec(ba, "Font", write_Font({
sz:12,
color: {theme:1},
name: "Arial",
@ -427,7 +128,7 @@ function write_FMTS_biff8(ba, NF/*:?SSFTable*/, opts) {
if(!NF) return;
[[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
/*:: if(!NF) return; */
for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_biff_rec(ba, 0x041E /* Format */, write_Format(i, NF[i], opts));
for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_biff_rec(ba, "Format", write_Format(i, NF[i], opts));
});
}
@ -436,7 +137,7 @@ function write_FEAT(ba, ws) {
var o = new_buf(19);
o.write_shift(4, 0x867); o.write_shift(4, 0); o.write_shift(4, 0);
o.write_shift(2, 3); o.write_shift(1, 1); o.write_shift(4, 0);
write_biff_rec(ba, 0x0867 /* FeatHdr */, o);
write_biff_rec(ba, "FeatHdr", o);
/* [MS-XLS] 2.4.111 */
o = new_buf(39);
o.write_shift(4, 0x868); o.write_shift(4, 0); o.write_shift(4, 0);
@ -444,62 +145,50 @@ function write_FEAT(ba, ws) {
o.write_shift(2, 1); o.write_shift(4, 4); o.write_shift(2, 0);
write_Ref8U(safe_decode_range(ws['!ref']||"A1"), o);
o.write_shift(4, 4);
write_biff_rec(ba, 0x0868 /* Feat */, o);
write_biff_rec(ba, "Feat", o);
}
function write_CELLXFS_biff8(ba, opts) {
for(var i = 0; i < 16; ++i) write_biff_rec(ba, 0x00e0 /* XF */, write_XF({numFmtId:0, style:true}, 0, opts));
for(var i = 0; i < 16; ++i) write_biff_rec(ba, "XF", write_XF({numFmtId:0, style:true}, 0, opts));
opts.cellXfs.forEach(function(c) {
write_biff_rec(ba, 0x00e0 /* XF */, write_XF(c, 0, opts));
write_biff_rec(ba, "XF", write_XF(c, 0, opts));
});
}
function write_ws_biff8_hlinks(ba/*:BufArray*/, ws) {
for(var R=0; R<ws['!links'].length; ++R) {
var HL = ws['!links'][R];
write_biff_rec(ba, 0x01b8 /* HLink */, write_HLink(HL));
if(HL[1].Tooltip) write_biff_rec(ba, 0x0800 /* HLinkTooltip */, write_HLinkTooltip(HL));
write_biff_rec(ba, "HLink", write_HLink(HL));
if(HL[1].Tooltip) write_biff_rec(ba, "HLinkTooltip", write_HLinkTooltip(HL));
}
delete ws['!links'];
}
function write_ws_cols_biff8(ba, cols) {
if(!cols) return;
var cnt = 0;
cols.forEach(function(col, idx) {
if(++cnt <= 256 && col) {
write_biff_rec(ba, 0x007d /* ColInfo */, write_ColInfo(col_obj_w(idx, col), idx));
}
});
}
function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/) {
function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) {
var os = 16 + get_cell_style(opts.cellXfs, cell, opts);
if(cell.v == null && !cell.bf) {
write_biff_rec(ba, 0x0201 /* Blank */, write_XLSCell(R, C, os));
write_biff_rec(ba, "Blank", write_XLSCell(R, C, os));
return;
}
if(cell.bf) write_biff_rec(ba, 0x0006 /* Formula */, write_Formula(cell, R, C, opts, os));
if(cell.bf) write_biff_rec(ba, "Formula", write_Formula(cell, R, C, opts, os));
else switch(cell.t) {
case 'd': case 'n':
var v = cell.t == 'd' ? datenum(parseDate(cell.v, date1904), date1904) : cell.v;
if(isNaN(v)) write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, 0x24, os, opts, "e")); // #NUM!
else if(!isFinite(v)) write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, 0x07, os, opts, "e")); // #DIV/0!
var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
/* TODO: emit RK as appropriate */
else write_biff_rec(ba, 0x0203 /* Number */, write_Number(R, C, v, os, opts));
write_biff_rec(ba, "Number", write_Number(R, C, v, os, opts));
break;
case 'b': case 'e':
write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, cell.v, os, opts, cell.t));
write_biff_rec(ba, 0x0205, write_BoolErr(R, C, cell.v, os, opts, cell.t));
break;
/* TODO: codepage, sst */
case 's': case 'str':
if(opts.bookSST) {
var isst = get_sst_id(opts.Strings, cell.v == null ? "" : String(cell.v), opts.revStrings);
write_biff_rec(ba, 0x00fd /* LabelSst */, write_LabelSst(R, C, isst, os, opts));
} else write_biff_rec(ba, 0x0204 /* Label */, write_Label(R, C, (cell.v == null ? "" : String(cell.v)).slice(0,255), os, opts));
var isst = get_sst_id(opts.Strings, cell.v, opts.revStrings);
write_biff_rec(ba, "LabelSst", write_LabelSst(R, C, isst, os, opts));
} else write_biff_rec(ba, "Label", write_Label(R, C, cell.v, os, opts));
break;
default:
write_biff_rec(ba, 0x0201 /* Blank */, write_XLSCell(R, C, os));
write_biff_rec(ba, "Blank", write_XLSCell(R, C, os));
}
}
@ -509,72 +198,64 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
var _WB/*:WBWBProps*/ = ((wb||{}).Workbook||{}/*:any*/);
var _sheet/*:WBWSProp*/ = ((_WB.Sheets||[])[idx]||{}/*:any*/);
var dense = ws["!data"] != null;
var dense = Array.isArray(ws);
var b8 = opts.biff == 8;
var ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
var range = safe_decode_range(ws['!ref'] || "A1");
var MAX_ROWS = b8 ? 65536 : 16384;
if(range.e.c > 0xFF || range.e.r >= MAX_ROWS) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV" + MAX_ROWS);
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
range.e.r = Math.min(range.e.r, MAX_ROWS-1);
range.e.r = Math.min(range.e.c, MAX_ROWS-1);
}
write_biff_rec(ba, 0x0809, write_BOF(wb, 0x10, opts));
/* [Uncalced] Index */
write_biff_rec(ba, 0x000d /* CalcMode */, writeuint16(1));
write_biff_rec(ba, 0x000c /* CalcCount */, writeuint16(100));
write_biff_rec(ba, 0x000f /* CalcRefMode */, writebool(true));
write_biff_rec(ba, 0x0011 /* CalcIter */, writebool(false));
write_biff_rec(ba, 0x0010 /* CalcDelta */, write_Xnum(0.001));
write_biff_rec(ba, 0x005f /* CalcSaveRecalc */, writebool(true));
write_biff_rec(ba, 0x002a /* PrintRowCol */, writebool(false));
write_biff_rec(ba, 0x002b /* PrintGrid */, writebool(false));
write_biff_rec(ba, 0x0082 /* GridSet */, writeuint16(1));
write_biff_rec(ba, 0x0080 /* Guts */, write_Guts([0,0]));
write_biff_rec(ba, "CalcMode", writeuint16(1));
write_biff_rec(ba, "CalcCount", writeuint16(100));
write_biff_rec(ba, "CalcRefMode", writebool(true));
write_biff_rec(ba, "CalcIter", writebool(false));
write_biff_rec(ba, "CalcDelta", write_Xnum(0.001));
write_biff_rec(ba, "CalcSaveRecalc", writebool(true));
write_biff_rec(ba, "PrintRowCol", writebool(false));
write_biff_rec(ba, "PrintGrid", writebool(false));
write_biff_rec(ba, "GridSet", writeuint16(1));
write_biff_rec(ba, "Guts", write_Guts([0,0]));
/* DefaultRowHeight WsBool [Sync] [LPr] [HorizontalPageBreaks] [VerticalPageBreaks] */
/* Header (string) */
/* Footer (string) */
write_biff_rec(ba, 0x0083 /* HCenter */, writebool(false));
write_biff_rec(ba, 0x0084 /* VCenter */, writebool(false));
write_biff_rec(ba, "HCenter", writebool(false));
write_biff_rec(ba, "VCenter", writebool(false));
/* ... */
if(b8) write_ws_cols_biff8(ba, ws["!cols"]);
/* ... */
write_biff_rec(ba, 0x0200 /* Dimensions */, write_Dimensions(range, opts));
write_biff_rec(ba, 0x200, write_Dimensions(range, opts));
/* ... */
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
if(b8) ws['!links'] = [];
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
var comments = [];
var row = [];
for(var R = range.s.r; R <= range.e.r; ++R) {
if(dense) row = ws["!data"][R] || [];
rr = encode_row(R);
for(C = range.s.c; C <= range.e.c; ++C) {
var cell = dense ? row[C] : ws[cols[C] + rr];
for(var C = range.s.c; C <= range.e.c; ++C) {
if(R === range.s.r) cols[C] = encode_col(C);
ref = cols[C] + rr;
var cell = dense ? (ws[R]||[])[C] : ws[ref];
if(!cell) continue;
/* write cell */
write_ws_biff8_cell(ba, cell, R, C, opts, date1904);
if(b8 && cell.l) ws['!links'].push([cols[C] + rr, cell.l]);
if(cell.c) comments.push([cell.c, R, C]);
write_ws_biff8_cell(ba, cell, R, C, opts);
if(b8 && cell.l) ws['!links'].push([ref, cell.l]);
}
}
var cname/*:string*/ = _sheet.CodeName || _sheet.name || s;
/* ... */
if(b8) write_comments_biff8(ba, comments); else write_comments_biff2(ba, comments);
if(b8) write_biff_rec(ba, "Window2", write_Window2((_WB.Views||[])[0]));
/* ... */
if(b8) write_biff_rec(ba, 0x023e /* Window2 */, write_Window2((_WB.Views||[])[0]));
/* ... */
if(b8 && (ws['!merges']||[]).length) write_biff_rec(ba, 0x00e5 /* MergeCells */, write_MergeCells(ws['!merges']));
if(b8 && (ws['!merges']||[]).length) write_biff_rec(ba, "MergeCells", write_MergeCells(ws['!merges']));
/* [LRng] *QUERYTABLE [PHONETICINFO] CONDFMTS */
if(b8) write_ws_biff8_hlinks(ba, ws);
/* [DVAL] */
write_biff_rec(ba, 0x01ba /* CodeName */, write_XLUnicodeString(cname, opts));
write_biff_rec(ba, "CodeName", write_XLUnicodeString(cname, opts));
/* *WebPub *CellWatch [SheetExt] */
if(b8) write_FEAT(ba, ws);
/* *FEAT11 *RECORD12 */
write_biff_rec(ba, 0x000a /* EOF */);
write_biff_rec(ba, "EOF");
return ba.end();
}
@ -586,61 +267,59 @@ function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) {
var _wb/*:WBProps*/ = /*::((*/_WB.WBProps||{/*::CodeName:"ThisWorkbook"*/}/*:: ):any)*/;
var b8 = opts.biff == 8, b5 = opts.biff == 5;
write_biff_rec(A, 0x0809, write_BOF(wb, 0x05, opts));
if(opts.bookType == "xla") write_biff_rec(A, 0x0087 /* Addin */);
write_biff_rec(A, 0x00e1 /* InterfaceHdr */, b8 ? writeuint16(0x04b0) : null);
write_biff_rec(A, 0x00c1 /* Mms */, writezeroes(2));
if(b5) write_biff_rec(A, 0x00bf /* ToolbarHdr */);
if(b5) write_biff_rec(A, 0x00c0 /* ToolbarEnd */);
write_biff_rec(A, 0x00e2 /* InterfaceEnd */);
write_biff_rec(A, 0x005c /* WriteAccess */, write_WriteAccess("SheetJS", opts));
if(opts.bookType == "xla") write_biff_rec(A, "Addin");
write_biff_rec(A, "InterfaceHdr", b8 ? writeuint16(0x04b0) : null);
write_biff_rec(A, "Mms", writezeroes(2));
if(b5) write_biff_rec(A, "ToolbarHdr");
if(b5) write_biff_rec(A, "ToolbarEnd");
write_biff_rec(A, "InterfaceEnd");
write_biff_rec(A, "WriteAccess", write_WriteAccess("SheetJS", opts));
/* [FileSharing] */
write_biff_rec(A, 0x0042 /* CodePage */, writeuint16(b8 ? 0x04b0 : 0x04E4));
write_biff_rec(A, "CodePage", writeuint16(b8 ? 0x04b0 : 0x04E4));
/* *2047 Lel */
if(b8) write_biff_rec(A, 0x0161 /* DSF */, writeuint16(0));
if(b8) write_biff_rec(A, 0x01c0 /* Excel9File */);
write_biff_rec(A, 0x013d /* RRTabId */, write_RRTabId(wb.SheetNames.length));
if(b8 && wb.vbaraw) write_biff_rec(A, 0x00d3 /* ObProj */);
if(b8) write_biff_rec(A, "DSF", writeuint16(0));
if(b8) write_biff_rec(A, "Excel9File");
write_biff_rec(A, "RRTabId", write_RRTabId(wb.SheetNames.length));
if(b8 && wb.vbaraw) write_biff_rec(A, "ObProj");
/* [ObNoMacros] */
if(b8 && wb.vbaraw) {
var cname/*:string*/ = _wb.CodeName || "ThisWorkbook";
write_biff_rec(A, 0x01ba /* CodeName */, write_XLUnicodeString(cname, opts));
write_biff_rec(A, "CodeName", write_XLUnicodeString(cname, opts));
}
write_biff_rec(A, 0x009c /* BuiltInFnGroupCount */, writeuint16(0x11));
write_biff_rec(A, "BuiltInFnGroupCount", writeuint16(0x11));
/* *FnGroupName *FnGrp12 */
/* *Lbl */
/* [OleObjectSize] */
write_biff_rec(A, 0x0019 /* WinProtect */, writebool(false));
write_biff_rec(A, 0x0012 /* Protect */, writebool(false));
write_biff_rec(A, 0x0013 /* Password */, writeuint16(0));
if(b8) write_biff_rec(A, 0x01af /* Prot4Rev */, writebool(false));
if(b8) write_biff_rec(A, 0x01bc /* Prot4RevPass */, writeuint16(0));
write_biff_rec(A, 0x003d /* Window1 */, write_Window1(opts));
write_biff_rec(A, 0x0040 /* Backup */, writebool(false));
write_biff_rec(A, 0x008d /* HideObj */, writeuint16(0));
write_biff_rec(A, 0x0022 /* Date1904 */, writebool(safe1904(wb)=="true"));
write_biff_rec(A, 0x000e /* CalcPrecision */, writebool(true));
if(b8) write_biff_rec(A, 0x01b7 /* RefreshAll */, writebool(false));
write_biff_rec(A, 0x00DA /* BookBool */, writeuint16(0));
write_biff_rec(A, "WinProtect", writebool(false));
write_biff_rec(A, "Protect", writebool(false));
write_biff_rec(A, "Password", writeuint16(0));
if(b8) write_biff_rec(A, "Prot4Rev", writebool(false));
if(b8) write_biff_rec(A, "Prot4RevPass", writeuint16(0));
write_biff_rec(A, "Window1", write_Window1(opts));
write_biff_rec(A, "Backup", writebool(false));
write_biff_rec(A, "HideObj", writeuint16(0));
write_biff_rec(A, "Date1904", writebool(safe1904(wb)=="true"));
write_biff_rec(A, "CalcPrecision", writebool(true));
if(b8) write_biff_rec(A, "RefreshAll", writebool(false));
write_biff_rec(A, "BookBool", writeuint16(0));
/* ... */
write_FONTS_biff8(A, wb, opts);
write_FMTS_biff8(A, wb.SSF, opts);
write_CELLXFS_biff8(A, opts);
/* ... */
if(b8) write_biff_rec(A, 0x0160 /* UsesELFs */, writebool(false));
if(b8) write_biff_rec(A, "UsesELFs", writebool(false));
var a = A.end();
var C = buf_array();
/* METADATA [MTRSettings] [ForceFullCalculation] */
if(b8) write_biff_rec(C, 0x008C /* Country */, write_Country());
/* *SUPBOOK *LBL *RTD [RecalcId] *HFPicture */
if(b8) write_biff_rec(C, "Country", write_Country());
/* *SUPBOOK *LBL *RTD [RecalcId] *HFPicture *MSODRAWINGGROUP */
/* BIFF8: MsoDrawingGroup [*Continue] */
if(b8 && b8ocnts.length) write_biff_rec(C, 0x00EB /* MsoDrawingGroup */, write_MsoDrawingGroup());
/* BIFF8: [SST *Continue] ExtSST */
if(b8 && opts.Strings) write_biff_continue(C, 0x00FC /* SST */, write_SST(opts.Strings, opts));
if(b8 && opts.Strings) write_biff_continue(C, "SST", write_SST(opts.Strings, opts));
/* *WebPub [WOpt] [CrErr] [BookExt] *FeatHdr *DConn [THEME] [CompressPictures] [Compat12] [GUIDTypeLib] */
write_biff_rec(C, 0x000A /* EOF */);
write_biff_rec(C, "EOF");
var c = C.end();
var B = buf_array();
@ -649,7 +328,7 @@ function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) {
var start = a.length + blen + c.length;
for(j = 0; j < wb.SheetNames.length; ++j) {
var _sheet/*:WBWSProp*/ = _sheets[j] || ({}/*:any*/);
write_biff_rec(B, 0x0085 /* BoundSheet8 */, write_BoundSheet8({pos:start, hs:_sheet.Hidden||0, dt:0, name:wb.SheetNames[j]}, opts));
write_biff_rec(B, "BoundSheet8", write_BoundSheet8({pos:start, hs:_sheet.Hidden||0, dt:0, name:wb.SheetNames[j]}, opts));
start += bufs[j].length;
}
/* 1*BoundSheet8 */
@ -660,7 +339,7 @@ function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) {
if(a.length) out.push(a);
if(b.length) out.push(b);
if(c.length) out.push(c);
return bconcat(out);
return __toBuffer([out]);
}
/* [MS-XLS] 2.1.7.20 Workbook Stream */
@ -669,16 +348,15 @@ function write_biff8_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
var bufs = [];
if(wb && !wb.SSF) {
wb.SSF = dup(table_fmt);
wb.SSF = SSF.get_table();
}
if(wb && wb.SSF) {
make_ssf(); SSF_load_table(wb.SSF);
make_ssf(SSF); SSF.load_table(wb.SSF);
// $FlowIgnore
o.revssf = evert_num(wb.SSF); o.revssf[wb.SSF[65535]] = 0;
o.ssf = wb.SSF;
}
b8oid = 1; b8ocnts = [];
o.Strings = /*::((*/[]/*:: :any):SST)*/; o.Strings.Count = 0; o.Strings.Unique = 0;
fix_write_opts(o);
@ -689,22 +367,10 @@ function write_biff8_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
for(var i = 0; i < wb.SheetNames.length; ++i) bufs[bufs.length] = write_ws_biff8(i, o, wb);
bufs.unshift(write_biff8_global(wb, bufs, o));
return bconcat(bufs);
return __toBuffer([bufs]);
}
function write_biff_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
for(var i = 0; i <= wb.SheetNames.length; ++i) {
var ws = wb.Sheets[wb.SheetNames[i]];
if(!ws || !ws["!ref"]) continue;
var range = decode_range(ws["!ref"]);
if(range.e.c > 255) { // note: 255 is IV
if(typeof console != "undefined" && console.error) console.error("Worksheet '" + wb.SheetNames[i] + "' extends beyond column IV (255). Data may be lost.");
}
if(range.e.r > 65535) {
if(typeof console != "undefined" && console.error) console.error("Worksheet '" + wb.SheetNames[i] + "' extends beyond row 65536. Data may be lost.");
}
}
var o = opts || {};
switch(o.biff || 2) {
case 8: case 5: return write_biff8_buf(wb, opts);

@ -1,150 +1,127 @@
/* note: browser DOM element cannot see mso- style attrs, must parse */
function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ {
var opts = _opts || {};
var dense = (opts.dense != null) ? opts.dense : DENSE;
var ws/*:Worksheet*/ = ({}/*:any*/); if(dense) ws["!data"] = [];
str = str_remove_ng(str, "<!--", "-->");
var mtch/*:any*/ = str.match(/<table/i);
if(!mtch) throw new Error("Invalid HTML: could not find <table>");
var mtch2/*:any*/ = str.match(/<\/table/i);
var i/*:number*/ = mtch.index, j/*:number*/ = mtch2 && mtch2.index || str.length;
var rows = split_regex(str.slice(i, j), /(:?<tr[^<>]*>)/i, "<tr>");
var R = -1, C = 0, RS = 0, CS = 0;
var range/*:Range*/ = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
var merges/*:Array<Range>*/ = [];
for(i = 0; i < rows.length; ++i) {
var row = rows[i].trim();
var hd = row.slice(0,3).toLowerCase();
if(hd == "<tr") { ++R; if(opts.sheetRows && opts.sheetRows <= R) { --R; break; } C = 0; continue; }
if(hd != "<td" && hd != "<th") continue;
var cells = row.split(/<\/t[dh]>/i);
for(j = 0; j < cells.length; ++j) {
var cell = cells[j].trim();
if(!cell.match(/<t[dh]/i)) continue;
var m = cell, cc = 0;
/* TODO: parse styles etc */
while(m.charAt(0) == "<" && (cc = m.indexOf(">")) > -1) m = m.slice(cc+1);
for(var midx = 0; midx < merges.length; ++midx) {
var _merge/*:Range*/ = merges[midx];
if(_merge.s.c == C && _merge.s.r < R && R <= _merge.e.r) { C = _merge.e.c + 1; midx = -1; }
var HTML_ = (function() {
function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ {
var opts = _opts || {};
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
str = str.replace(/<!--.*?-->/g, "");
var mtch/*:any*/ = str.match(/<table/i);
if(!mtch) throw new Error("Invalid HTML: could not find <table>");
var mtch2/*:any*/ = str.match(/<\/table/i);
var i/*:number*/ = mtch.index, j/*:number*/ = mtch2 && mtch2.index || str.length;
var rows = split_regex(str.slice(i, j), /(:?<tr[^>]*>)/i, "<tr>");
var R = -1, C = 0, RS = 0, CS = 0;
var range/*:Range*/ = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
var merges/*:Array<Range>*/ = [];
for(i = 0; i < rows.length; ++i) {
var row = rows[i].trim();
var hd = row.slice(0,3).toLowerCase();
if(hd == "<tr") { ++R; if(opts.sheetRows && opts.sheetRows <= R) { --R; break; } C = 0; continue; }
if(hd != "<td" && hd != "<th") continue;
var cells = row.split(/<\/t[dh]>/i);
for(j = 0; j < cells.length; ++j) {
var cell = cells[j].trim();
if(!cell.match(/<t[dh]/i)) continue;
var m = cell, cc = 0;
/* TODO: parse styles etc */
while(m.charAt(0) == "<" && (cc = m.indexOf(">")) > -1) m = m.slice(cc+1);
for(var midx = 0; midx < merges.length; ++midx) {
var _merge/*:Range*/ = merges[midx];
if(_merge.s.c == C && _merge.s.r < R && R <= _merge.e.r) { C = _merge.e.c + 1; midx = -1; }
}
var tag = parsexmltag(cell.slice(0, cell.indexOf(">")));
CS = tag.colspan ? +tag.colspan : 1;
if((RS = +tag.rowspan)>1 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
var _t/*:string*/ = tag.t || "";
/* TODO: generate stub cells */
if(!m.length) { C += CS; continue; }
m = htmldecode(m);
if(range.s.r > R) range.s.r = R; if(range.e.r < R) range.e.r = R;
if(range.s.c > C) range.s.c = C; if(range.e.c < C) range.e.c = C;
if(!m.length) continue;
var o/*:Cell*/ = {t:'s', v:m};
if(opts.raw || !m.trim().length || _t == 's'){}
else if(m === 'TRUE') o = {t:'b', v:true};
else if(m === 'FALSE') o = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)};
else if(!isNaN(fuzzydate(m).getDate())) {
o = ({t:'d', v:parseDate(m)}/*:any*/);
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
o.z = opts.dateNF || SSF._table[14];
}
if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; }
else ws[encode_cell({r:R, c:C})] = o;
C += CS;
}
var tag = parsexmltag(cell.slice(0, cell.indexOf(">")));
CS = tag.colspan ? +tag.colspan : 1;
if((RS = +tag.rowspan)>1 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
var _t/*:string*/ = tag.t || tag["data-t"] || "";
/* TODO: generate stub cells */
if(!m.length) { C += CS; continue; }
m = htmldecode(m);
if(range.s.r > R) range.s.r = R; if(range.e.r < R) range.e.r = R;
if(range.s.c > C) range.s.c = C; if(range.e.c < C) range.e.c = C;
if(!m.length) { C += CS; continue; }
var o/*:Cell*/ = {t:'s', v:m};
if(opts.raw || !m.trim().length || _t == 's'){}
else if(m === 'TRUE') o = {t:'b', v:true};
else if(m === 'FALSE') o = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)};
else if(!isNaN(fuzzydate(m).getDate())) {
o = ({t:'d', v:parseDate(m)}/*:any*/);
if(opts.UTC === false) o.v = utc_to_local(o.v);
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
o.z = opts.dateNF || table_fmt[14];
} else if(m.charCodeAt(0) == 35 /* # */ && RBErr[m] != null) {
o.t = 'e'; o.w = m; o.v = RBErr[m];
}
ws['!ref'] = encode_range(range);
if(merges.length) ws["!merges"] = merges;
return ws;
}
function html_to_book(str/*:string*/, opts)/*:Workbook*/ {
return sheet_to_workbook(html_to_sheet(str, opts), opts);
}
function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
var M/*:Array<Range>*/ = (ws['!merges'] ||[]);
var oo/*:Array<string>*/ = [];
for(var C = r.s.c; C <= r.e.c; ++C) {
var RS = 0, CS = 0;
for(var j = 0; j < M.length; ++j) {
if(M[j].s.r > R || M[j].s.c > C) continue;
if(M[j].e.r < R || M[j].e.c < C) continue;
if(M[j].s.r < R || M[j].s.c < C) { RS = -1; break; }
RS = M[j].e.r - M[j].s.r + 1; CS = M[j].e.c - M[j].s.c + 1; break;
}
if(o.cellText !== false) o.w = m;
if(dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = o; }
else ws[encode_cell({r:R, c:C})] = o;
C += CS;
if(RS < 0) continue;
var coord = encode_cell({r:R,c:C});
var cell = o.dense ? (ws[R]||[])[C] : ws[coord];
/* TODO: html entities */
var w = (cell && cell.v != null) && (cell.h || escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || "";
var sp = ({}/*:any*/);
if(RS > 1) sp.rowspan = RS;
if(CS > 1) sp.colspan = CS;
sp.t = cell && cell.t || 'z';
if(o.editable) w = '<span contenteditable="true">' + w + '</span>';
sp.id = (o.id || "sjs") + "-" + coord;
if(sp.t != "z") { sp.v = cell.v; if(cell.z != null) sp.z = cell.z; }
oo.push(writextag('td', w, sp));
}
var preamble = "<tr>";
return preamble + oo.join("") + "</tr>";
}
ws['!ref'] = encode_range(range);
if(merges.length) ws["!merges"] = merges;
return ws;
}
function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
var M/*:Array<Range>*/ = (ws['!merges'] ||[]);
var oo/*:Array<string>*/ = [];
var sp = ({}/*:any*/);
var dense = ws["!data"] != null;
for(var C = r.s.c; C <= r.e.c; ++C) {
var RS = 0, CS = 0;
for(var j = 0; j < M.length; ++j) {
if(M[j].s.r > R || M[j].s.c > C) continue;
if(M[j].e.r < R || M[j].e.c < C) continue;
if(M[j].s.r < R || M[j].s.c < C) { RS = -1; break; }
RS = M[j].e.r - M[j].s.r + 1; CS = M[j].e.c - M[j].s.c + 1; break;
}
if(RS < 0) continue;
var coord = encode_col(C) + encode_row(R);
var cell = dense ? (ws["!data"][R]||[])[C] : ws[coord];
if(cell && cell.t == 'n' && cell.v != null && !isFinite(cell.v)) {
if(isNaN(cell.v)) cell = ({t:'e', v:0x24, w:BErr[0x24]});
else cell = ({t:'e', v:0x07, w:BErr[0x07]});
}
/* TODO: html entities */
var w = (cell && cell.v != null) && (cell.h || escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || "";
sp = ({}/*:any*/);
if(RS > 1) sp.rowspan = RS;
if(CS > 1) sp.colspan = CS;
if(o.editable) w = '<span contenteditable="true">' + w + '</span>';
else if(cell) {
sp["data-t"] = cell && cell.t || 'z';
// note: data-v is unaffected by the timezone interpretation
if(cell.v != null) sp["data-v"] = escapehtml(cell.v instanceof Date ? cell.v.toISOString() : cell.v);
if(cell.z != null) sp["data-z"] = cell.z;
if(cell.f != null) sp["data-f"] = escapehtml(cell.f);
if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + escapehtml(cell.l.Target) +'">' + w + '</a>';
}
sp.id = (o.id || "sjs") + "-" + coord;
oo.push(writextag('td', w, sp));
function make_html_preamble(ws/*:Worksheet*/, R/*:Range*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
var out/*:Array<string>*/ = [];
return out.join("") + '<table' + (o && o.id ? ' id="' + o.id + '"' : "") + '>';
}
var preamble = "<tr>";
return preamble + oo.join("") + "</tr>";
}
var _BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
var _END = '</body></html>';
function sheet_to_html(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*//*, wb:?Workbook*/)/*:string*/ {
var o = opts || {};
var header = o.header != null ? o.header : _BEGIN;
var footer = o.footer != null ? o.footer : _END;
var out/*:Array<string>*/ = [header];
var r = decode_range(ws['!ref']);
o.dense = Array.isArray(ws);
out.push(make_html_preamble(ws, r, o));
for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
out.push("</table>" + footer);
return out.join("");
var HTML_BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
var HTML_END = '</body></html>';
function html_to_workbook(str/*:string*/, opts)/*:Workbook*/ {
var mtch = str_match_xml_ig(str, "table");
if(!mtch || mtch.length == 0) throw new Error("Invalid HTML: could not find <table>");
if(mtch.length == 1) {
var w = sheet_to_workbook(html_to_sheet(mtch[0], opts), opts);
w.bookType = "html";
return w;
}
var wb = book_new();
mtch.forEach(function(s, idx) { book_append_sheet(wb, html_to_sheet(s, opts), "Sheet" + (idx+1)); });
wb.bookType = "html";
return wb;
}
function make_html_preamble(ws/*:Worksheet*/, R/*:Range*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
var out/*:Array<string>*/ = [];
return out.join("") + '<table' + (o && o.id ? ' id="' + o.id + '"' : "") + '>';
}
function sheet_to_html(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*//*, wb:?Workbook*/)/*:string*/ {
var o = opts || {};
var header = o.header != null ? o.header : HTML_BEGIN;
var footer = o.footer != null ? o.footer : HTML_END;
var out/*:Array<string>*/ = [header];
var r = decode_range(ws['!ref'] || "A1");
out.push(make_html_preamble(ws, r, o));
if(ws["!ref"]) for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
out.push("</table>" + footer);
return out.join("");
}
return {
to_workbook: html_to_book,
to_sheet: html_to_sheet,
_row: make_html_row,
BEGIN: _BEGIN,
END: _END,
_preamble: make_html_preamble,
from_sheet: sheet_to_html
};
})();
function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
var rows/*:HTMLCollection<HTMLTableRowElement>*/ = table.rows;
if(!rows) {
/* not an HTML TABLE */
throw "Unsupported origin when " + table.tagName + " is not a TABLE";
}
var opts = _opts || {};
var dense = ws["!data"] != null;
if(DENSE != null) opts.dense = DENSE;
var or_R = 0, or_C = 0;
if(opts.origin != null) {
if(typeof opts.origin == 'number') or_R = opts.origin;
@ -153,7 +130,7 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
or_R = _origin.r; or_C = _origin.c;
}
}
var rows/*:HTMLCollection<HTMLTableRowElement>*/ = table.getElementsByTagName('tr');
var sheetRows = Math.min(opts.sheetRows||10000000, rows.length);
var range/*:Range*/ = {s:{r:0,c:0},e:{r:or_R,c:or_C}};
if(ws["!ref"]) {
@ -174,13 +151,12 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
if (opts.display) continue;
rowinfo[R] = {hidden: true};
}
var elts/*:HTMLCollection<HTMLTableCellElement>*/ = (row.cells);
var elts/*:HTMLCollection<HTMLTableCellElement>*/ = (row.children/*:any*/);
for(_C = C = 0; _C < elts.length; ++_C) {
var elt/*:HTMLTableCellElement*/ = elts[_C];
if (opts.display && is_dom_element_hidden(elt)) continue;
var v/*:?string*/ = elt.hasAttribute('data-v') ? elt.getAttribute('data-v') : elt.hasAttribute('v') ? elt.getAttribute('v') : htmldecode(elt.innerHTML);
var z/*:?string*/ = elt.getAttribute('data-z') || elt.getAttribute('z');
var f/*:?string*/ = elt.hasAttribute('data-f') ? elt.getAttribute('data-f') : elt.hasAttribute('f') ? elt.getAttribute('f') : null;
var v/*:?string*/ = elt.hasAttribute('v') ? elt.getAttribute('v') : htmldecode(elt.innerHTML);
var z/*:?string*/ = elt.getAttribute('z');
for(midx = 0; midx < merges.length; ++midx) {
var m/*:Range*/ = merges[midx];
if(m.s.c == C + or_C && m.s.r < R + or_R && R + or_R <= m.e.r) { C = m.e.c+1 - or_C; midx = -1; }
@ -189,31 +165,21 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
CS = +elt.getAttribute("colspan") || 1;
if( ((RS = (+elt.getAttribute("rowspan") || 1)))>1 || CS>1) merges.push({s:{r:R + or_R,c:C + or_C},e:{r:R + or_R + (RS||1) - 1, c:C + or_C + (CS||1) - 1}});
var o/*:Cell*/ = {t:'s', v:v};
var _t/*:string*/ = elt.getAttribute("data-t") || elt.getAttribute("t") || "";
var _t/*:string*/ = elt.getAttribute("t") || "";
if(v != null) {
if(v.length == 0) o.t = _t || 'z';
else if(opts.raw || v.trim().length == 0 || _t == "s"){}
else if(_t == "e" && BErr[+v]) o = {t:'e', v:+v, w: BErr[+v]};
else if(v === 'TRUE') o = {t:'b', v:true};
else if(v === 'FALSE') o = {t:'b', v:false};
else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
else if(!isNaN(fuzzydate(v).getDate())) {
o = ({t:'d', v:parseDate(v)}/*:any*/);
if(opts.UTC) o.v = local_to_utc(o.v);
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
o.z = opts.dateNF || table_fmt[14];
} else if(v.charCodeAt(0) == 35 /* # */ && RBErr[v] != null) o = ({t:'e', v: RBErr[v], w: v});
o.z = opts.dateNF || SSF._table[14];
}
}
if(o.z === undefined && z != null) o.z = z;
/* The first link is used. Links are assumed to be fully specified.
* TODO: The right way to process relative links is to make a new <a> */
var l = "", Aelts = elt.getElementsByTagName("A");
if(Aelts && Aelts.length) for(var Aelti = 0; Aelti < Aelts.length; ++Aelti) if(Aelts[Aelti].hasAttribute("href")) {
l = Aelts[Aelti].getAttribute("href"); if(l.charAt(0) != "#") break;
}
if(l && l.charAt(0) != "#" && l.slice(0, 11).toLowerCase() != 'javascript:') o.l = ({ Target: l });
if(f != null) o.f = f;
if(dense) { if(!ws["!data"][R + or_R]) ws["!data"][R + or_R] = []; ws["!data"][R + or_R][C + or_C] = o; }
if(opts.dense) { if(!ws[R + or_R]) ws[R + or_R] = []; ws[R + or_R][C + or_C] = o; }
else ws[encode_cell({c:C + or_C, r:R + or_R})] = o;
if(range.e.c < C + or_C) range.e.c = C + or_C;
C += CS;
@ -229,21 +195,19 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
var opts = _opts || {};
var ws/*:Worksheet*/ = ({}/*:any*/); if(opts.dense) ws["!data"] = [];
var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
return sheet_add_dom(ws, table, _opts);
}
function table_to_book(table/*:HTMLElement*/, opts/*:?any*/)/*:Workbook*/ {
var o = sheet_to_workbook(parse_dom_table(table, opts), opts);
//o.bookType = "dom"; // TODO: define a type for this
return o;
return sheet_to_workbook(parse_dom_table(table, opts), opts);
}
function is_dom_element_hidden(element/*:HTMLElement*/)/*:boolean*/ {
var display/*:string*/ = '';
var get_computed_style/*:?function*/ = get_get_computed_style_function(element);
if(get_computed_style) display = get_computed_style(element).getPropertyValue('display');
if(!display) display = element.style && element.style.display;
if(!display) display = element.style.display; // Fallback for cases when getComputedStyle is not available (e.g. an old browser or some Node.js environments) or doesn't work (e.g. if the element is not inserted to a document)
return display === 'none';
}

@ -1,262 +1,56 @@
/* OpenDocument */
function parse_text_p(text/*:string*//*::, tag*/)/*:Array<any>*/ {
/* 6.1.2 White Space Characters */
var fixed = text
.replace(/[\t\r\n]/g, " ").trim().replace(/ +/g, " ")
.replace(/<text:s\/>/g," ")
.replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); })
.replace(/<text:tab[^<>]*\/>/g,"\t")
.replace(/<text:line-break\/>/g,"\n");
var v = unescapexml(fixed.replace(/<[^<>]*>/g,""));
var parse_content_xml = (function() {
return [v];
}
var parse_text_p = function(text/*:string*//*::, tag*/)/*:Array<any>*/ {
/* 6.1.2 White Space Characters */
var fixed = text
.replace(/[\t\r\n]/g, " ").trim().replace(/ +/g, " ")
.replace(/<text:s\/>/g," ")
.replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); })
.replace(/<text:tab[^>]*\/>/g,"\t")
.replace(/<text:line-break\/>/g,"\n");
var v = unescapexml(fixed.replace(/<[^>]*>/g,""));
/* Note: ODS can stick styles in content.xml or styles.xml, FODS blurs lines */
function parse_ods_styles(d/*:string*/, _opts, _nfm) {
var number_format_map = _nfm || {};
var str = xlml_normalize(d);
xlmlregex.lastIndex = 0;
str = remove_doctype(str_remove_ng(str, "<!--", "-->"));
var Rn, NFtag, NF = "", tNF = "", y, etpos = 0, tidx = -1, infmt = false, payload = "";
while((Rn = xlmlregex.exec(str))) {
switch((Rn[3]=Rn[3].replace(/_[\s\S]*$/,""))) {
/* Number Format Definitions */
case 'number-style': // <number:number-style> 16.29.2
case 'currency-style': // <number:currency-style> 16.29.8
case 'percentage-style': // <number:percentage-style> 16.29.10
case 'date-style': // <number:date-style> 16.29.11
case 'time-style': // <number:time-style> 16.29.19
case 'text-style': // <number:text-style> 16.29.26
if(Rn[1]==='/') {
infmt = false;
if(NFtag['truncate-on-overflow'] == "false") {
if(NF.match(/h/)) NF = NF.replace(/h+/, "[$&]");
else if(NF.match(/m/)) NF = NF.replace(/m+/, "[$&]");
else if(NF.match(/s/)) NF = NF.replace(/s+/, "[$&]");
}
number_format_map[NFtag.name] = NF;
NF = "";
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
infmt = true;
NF = "";
NFtag = parsexmltag(Rn[0], false);
} break;
return [v];
};
// LibreOffice bug https://bugs.documentfoundation.org/show_bug.cgi?id=149484
case 'boolean-style': // <number:boolean-style> 16.29.24
if(Rn[1]==='/') {
infmt = false;
number_format_map[NFtag.name] = "General";
NF = "";
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
infmt = true;
NF = "";
NFtag = parsexmltag(Rn[0], false);
} break;
var number_formats = {
/* ods name: [short ssf fmt, long ssf fmt] */
day: ["d", "dd"],
month: ["m", "mm"],
year: ["y", "yy"],
hours: ["h", "hh"],
minutes: ["m", "mm"],
seconds: ["s", "ss"],
"am-pm": ["A/P", "AM/PM"],
"day-of-week": ["ddd", "dddd"],
era: ["e", "ee"],
/* there is no native representation of LO "Q" format */
quarter: ["\\Qm", "m\\\"th quarter\""]
};
/* Number Format Elements */
case 'boolean': // <number:boolean> 16.29.25
NF += "General"; // ODF spec is unfortunately underspecified here
break;
case 'text': // <number:text> 16.29.27
if(Rn[1]==='/') {
payload = str.slice(tidx, xlmlregex.lastIndex - Rn[0].length);
// NOTE: Excel has a different interpretation of "%%" and friends
if(payload == "%" && NFtag[0] == '<number:percentage-style') NF += "%";
else NF += '"' + payload.replace(/"/g, '""') + '"';
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
tidx = xlmlregex.lastIndex;
} break;
case 'day': { // <number:day> 16.29.12
y = parsexmltag(Rn[0], false);
switch(y["style"]) {
case "short": NF += "d"; break;
case "long": NF += "dd"; break;
default: NF += "dd"; break; // TODO: error condition
}
} break;
case 'day-of-week': { // <number:day-of-week> 16.29.16
y = parsexmltag(Rn[0], false);
switch(y["style"]) {
case "short": NF += "ddd"; break;
case "long": NF += "dddd"; break;
default: NF += "ddd"; break;
}
} break;
case 'era': { // <number:era> 16.29.15 TODO: proper mapping
y = parsexmltag(Rn[0], false);
switch(y["style"]) {
case "short": NF += "ee"; break;
case "long": NF += "eeee"; break;
default: NF += "eeee"; break; // TODO: error condition
}
} break;
case 'hours': { // <number:hours> 16.29.20
y = parsexmltag(Rn[0], false);
switch(y["style"]) {
case "short": NF += "h"; break;
case "long": NF += "hh"; break;
default: NF += "hh"; break; // TODO: error condition
}
} break;
case 'minutes': { // <number:minutes> 16.29.21
y = parsexmltag(Rn[0], false);
switch(y["style"]) {
case "short": NF += "m"; break;
case "long": NF += "mm"; break;
default: NF += "mm"; break; // TODO: error condition
}
} break;
case 'month': { // <number:month> 16.29.13
y = parsexmltag(Rn[0], false);
if(y["textual"]) NF += "mm";
switch(y["style"]) {
case "short": NF += "m"; break;
case "long": NF += "mm"; break;
default: NF += "m"; break;
}
} break;
case 'seconds': { // <number:seconds> 16.29.22
y = parsexmltag(Rn[0], false);
switch(y["style"]) {
case "short": NF += "s"; break;
case "long": NF += "ss"; break;
default: NF += "ss"; break; // TODO: error condition
}
if(y["decimal-places"]) NF += "." + fill("0", +y["decimal-places"]);
} break;
case 'year': { // <number:year> 16.29.14
y = parsexmltag(Rn[0], false);
switch(y["style"]) {
case "short": NF += "yy"; break;
case "long": NF += "yyyy"; break;
default: NF += "yy"; break; // TODO: error condition
}
} break;
case 'am-pm': // <number:am-pm> 16.29.23
NF += "AM/PM"; // LO autocorrects A/P -> AM/PM
break;
case 'week-of-year': // <number:week-of-year> 16.29.17
case 'quarter': // <number:quarter> 16.29.18
console.error("Excel does not support ODS format token " + Rn[3]);
break;
case 'fill-character': // <number:fill-character> 16.29.5
if(Rn[1]==='/') {
payload = str.slice(tidx, xlmlregex.lastIndex - Rn[0].length);
// NOTE: Excel has a different interpretation of "%%" and friends
NF += '"' + payload.replace(/"/g, '""') + '"*';
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
tidx = xlmlregex.lastIndex;
} break;
case 'scientific-number': // <number:scientific-number> 16.29.6
// TODO: find a mapping for all parameters
y = parsexmltag(Rn[0], false);
NF += "0." + fill("0", +y["min-decimal-places"] || +y["decimal-places"] || 2) + fill("?", +y["decimal-places"] - +y["min-decimal-places"] || 0) + "E" + (parsexmlbool(y["forced-exponent-sign"]) ? "+" : "") + fill("0", +y["min-exponent-digits"] || 2);
break;
case 'fraction': // <number:fraction> 16.29.7
// TODO: find a mapping for all parameters
y = parsexmltag(Rn[0], false);
if(!+y["min-integer-digits"]) NF += "#";
else NF += fill("0", +y["min-integer-digits"]);
NF += " ";
NF += fill("?", +y["min-numerator-digits"] || 1);
NF += "/";
if(+y["denominator-value"]) NF += y["denominator-value"];
else NF += fill("?", +y["min-denominator-digits"] || 1);
break;
case 'currency-symbol': // <number:currency-symbol> 16.29.9
// TODO: localization with [$-...]
if(Rn[1]==='/') {
NF += '"' + str.slice(tidx, xlmlregex.lastIndex - Rn[0].length).replace(/"/g, '""') + '"';
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
tidx = xlmlregex.lastIndex;
} else NF += "$";
break;
case 'text-properties': // <style:text-properties> 16.29.29
y = parsexmltag(Rn[0], false);
switch((y["color"]||"").toLowerCase().replace("#", "")) {
case "ff0000": case "red": NF = "[Red]" + NF; break;
}
break;
case 'text-content': // <number:text-content> 16.29.28
NF += "@";
break;
case 'map': // <style:map> 16.3
// TODO: handle more complex maps
y = parsexmltag(Rn[0], false);
if(unescapexml(y["condition"]) == "value()>=0") NF = number_format_map[y["apply-style-name"]] + ";" + NF;
else console.error("ODS number format may be incorrect: " + y["condition"]);
break;
case 'number': // <number:number> 16.29.3
// TODO: handle all the attributes
if(Rn[1]==='/') break;
y = parsexmltag(Rn[0], false);
tNF = "";
tNF += fill("0", +y["min-integer-digits"] || 1);
if(parsexmlbool(y["grouping"])) tNF = commaify(fill("#", Math.max(0, 4 - tNF.length)) + tNF);
if(+y["min-decimal-places"] || +y["decimal-places"]) tNF += ".";
if(+y["min-decimal-places"]) tNF += fill("0", +y["min-decimal-places"] || 1);
if(+y["decimal-places"] - (+y["min-decimal-places"]||0)) tNF += fill("0", +y["decimal-places"] - (+y["min-decimal-places"]||0)); // TODO: should this be "#" ?
NF += tNF;
break;
case 'embedded-text': // <number:embedded-text> 16.29.4
// TODO: verify interplay with grouping et al
if(Rn[1]==='/') {
if(etpos == 0) NF += '"' + str.slice(tidx, xlmlregex.lastIndex - Rn[0].length).replace(/"/g, '""') + '"';
else NF = NF.slice(0, etpos) + '"' + str.slice(tidx, xlmlregex.lastIndex - Rn[0].length).replace(/"/g, '""') + '"' + NF.slice(etpos);
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
tidx = xlmlregex.lastIndex;
etpos = -+parsexmltag(Rn[0], false)["position"] || 0;
} break;
}}
return number_format_map;
}
function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
return function pcx(d/*:string*/, _opts)/*:Workbook*/ {
var opts = _opts || {};
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
var str = xlml_normalize(d);
var state/*:Array<any>*/ = [], tmp;
var tag/*:: = {}*/;
var nfidx, NF = "", pidx = 0;
var NFtag = {name:""}, NF = "", pidx = 0;
var sheetag/*:: = {name:"", '名称':""}*/;
var rowtag/*:: = {'行号':""}*/;
var Sheets = {}, SheetNames/*:Array<string>*/ = [];
var ws = ({}/*:any*/); if(opts.dense) ws["!data"] = [];
var ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
var Rn, q/*:: :any = ({t:"", v:null, z:null, w:"",c:[],}:any)*/;
var ctag = ({value:""}/*:any*/), ctag2 = ({}/*:any*/);
var textp = "", textpidx = 0, textptag/*:: = {}*/, oldtextp = "", oldtextpidx = 0;
var textR = [], oldtextR = [];
var ctag = ({value:""}/*:any*/);
var textp = "", textpidx = 0, textptag/*:: = {}*/;
var textR = [];
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
var row_ol = 0;
var number_format_map = _nfm || {}, styles = {}, tstyles = {};
var number_format_map = {};
var merges/*:Array<Range>*/ = [], mrange = {}, mR = 0, mC = 0;
var rowinfo/*:Array<RowInfo>*/ = [], rowpeat = 1, colpeat = 1;
var arrayf/*:Array<[Range, string]>*/ = [];
var WB = {Names:[], WBProps:{}, Sheets:[]};
var WB = {Names:[]};
var atag = ({}/*:any*/);
var _Ref/*:[string, string]*/ = ["", ""];
var comments/*:Array<Comment>*/ = [], comment/*:Comment*/ = ({}/*:any*/);
@ -264,8 +58,8 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
var isstub = false, intable = false;
var i = 0;
xlmlregex.lastIndex = 0;
str = remove_doctype(str_remove_ng(str, "<!--", "-->"));
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_[\s\S]*$/,""))) {
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
case 'table': case '工作表': // 9.1.2 <table:table>
if(Rn[1]==='/') {
@ -282,17 +76,13 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
if(typeof JSON !== 'undefined') JSON.stringify(sheetag);
SheetNames.push(sheetag.name);
Sheets[sheetag.name] = ws;
WB.Sheets.push({
/* TODO: CodeName */
Hidden: (tstyles[sheetag["style-name"]] && tstyles[sheetag["style-name"]]["display"] ? (parsexmlbool(tstyles[sheetag["style-name"]]["display"]) ? 0 : 1) : 0)
});
intable = false;
}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
sheetag = parsexmltag(Rn[0], false);
R = C = -1;
range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0;
ws = ({}/*:any*/); if(opts.dense) ws["!data"] = []; merges = [];
ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/); merges = [];
rowinfo = [];
intable = true;
}
@ -310,18 +100,10 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
if(rowpeat < 10) for(i = 0; i < rowpeat; ++i) if(row_ol > 0) rowinfo[R + i] = {level: row_ol};
C = -1; break;
case 'covered-table-cell': // 9.1.5 <table:covered-table-cell>
if(Rn[1] !== '/') {
++C;
ctag = parsexmltag(Rn[0], false);
colpeat = parseInt(ctag['number-columns-repeated']||"1",10) || 1;
if(opts.sheetStubs) {
while(colpeat-- > 0) {
if(opts.dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = {t:'z'}; }
else ws[encode_cell({r:R,c:C})] = {t:'z'};
++C;
} --C;
}
else C += colpeat - 1;
if(Rn[1] !== '/') ++C;
if(opts.sheetStubs) {
if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = {t:'z'}; }
else ws[encode_cell({r:R,c:C})] = {t:'z'};
}
textp = ""; textR = [];
break; /* stub */
@ -329,23 +111,21 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
if(Rn[0].charAt(Rn[0].length-2) === '/') {
++C;
ctag = parsexmltag(Rn[0], false);
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10)||1;
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
q = ({t:'z', v:null/*:: , z:null, w:"",c:[]*/}/*:any*/);
if(ctag.formula && opts.cellFormula != false) q.f = ods_to_csf_formula(unescapexml(ctag.formula));
if(ctag["style-name"] && styles[ctag["style-name"]]) q.z = styles[ctag["style-name"]];
if((ctag['数据类型'] || ctag['value-type']) == "string") {
q.t = "s"; q.v = unescapexml(ctag['string-value'] || "");
if(opts.dense) {
if(!ws["!data"][R]) ws["!data"][R] = [];
ws["!data"][R][C] = q;
if(!ws[R]) ws[R] = [];
ws[R][C] = q;
} else {
ws[encode_col(C) + encode_row(R)] = q;
ws[encode_cell({r:R,c:C})] = q;
}
}
C+= colpeat-1;
} else if(Rn[1]!=='/') {
++C;
textp = oldtextp = ""; textpidx = oldtextpidx = 0; textR = []; oldtextR = [];
colpeat = 1;
var rptR = rowpeat ? R + rowpeat - 1 : R;
if(C > range.e.c) range.e.c = C;
@ -353,10 +133,8 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
if(R < range.s.r) range.s.r = R;
if(rptR > range.e.r) range.e.r = rptR;
ctag = parsexmltag(Rn[0], false);
ctag2 = parsexmltagraw(Rn[0], true);
comments = []; comment = ({}/*:any*/);
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:"",c:[]*/}/*:any*/);
if(ctag["style-name"] && styles[ctag["style-name"]]) q.z = styles[ctag["style-name"]];
if(opts.cellFormula) {
if(ctag.formula) ctag.formula = unescapexml(ctag.formula);
if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
@ -373,34 +151,26 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
q.F = arrayf[i][1];
}
if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) {
mR = parseInt(ctag['number-rows-spanned']||"1",10) || 1;
mC = parseInt(ctag['number-columns-spanned']||"1",10) || 1;
if(mR * mC > 1) {
mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
merges.push(mrange);
}
mR = parseInt(ctag['number-rows-spanned'],10) || 0;
mC = parseInt(ctag['number-columns-spanned'],10) || 0;
mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
merges.push(mrange);
}
/* 19.675.2 table:number-columns-repeated */
if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10);
/* 19.385 office:value-type TODO: verify ODS and UOS */
/* 19.385 office:value-type */
switch(q.t) {
case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']) || (+ctag['boolean-value'] >= 1); break;
case 'float': q.t = 'n'; q.v = parseFloat(ctag.value);
if(opts.cellDates && q.z && fmt_is_date(q.z)) { q.v = numdate(q.v + (WB.WBProps.date1904 ? 1462 : 0)); q.t = typeof q.v == "number" ? 'n' : 'd'; }
break;
case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break;
case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value'], WB.WBProps.date1904);
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904); }
if(!q.z) q.z = 'm/d/yy'; break;
/* NOTE: for `time`, Excel ODS export incorrectly uses durations relative to 1900 epoch even if 1904 is specified */
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400;
if(opts.cellDates) { q.v = numdate(q.v); q.t = typeof q.v == "number" ? 'n' : 'd'; }
if(!q.z) q.z = 'HH:MM:SS'; break;
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']);
break;
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']);
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v); }
q.z = 'm/d/yy'; break;
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400; break;
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
default:
if(q.t === 'string' || q.t === 'text' || !q.t) {
q.t = 's';
@ -409,9 +179,6 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
}
} else {
isstub = false;
if(ctag2['calcext:value-type'] == "error" && RBErr[textp] != null) {
q.t = 'e'; q.w = textp; q.v = RBErr[textp];
}
if(q.t === 's') {
q.v = textp || '';
if(textR.length) q.R = textR;
@ -426,9 +193,9 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
for(var rpt = 0; rpt < rowpeat; ++rpt) {
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
if(opts.dense) {
if(!ws["!data"][R + rpt]) ws["!data"][R + rpt] = [];
ws["!data"][R + rpt][C] = rpt == 0 ? q : dup(q);
while(--colpeat > 0) ws["!data"][R + rpt][C + colpeat] = dup(q);
if(!ws[R + rpt]) ws[R + rpt] = [];
ws[R + rpt][C] = rpt == 0 ? q : dup(q);
while(--colpeat > 0) ws[R + rpt][C + colpeat] = dup(q);
} else {
ws[encode_cell({r:R + rpt,c:C})] = q;
while(--colpeat > 0) ws[encode_cell({r:R + rpt,c:C + colpeat})] = dup(q);
@ -452,7 +219,7 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
case 'scripts': // 3.12 <office:scripts>
case 'styles': // TODO <office:styles>
case 'font-face-decls': // 3.14 <office:font-face-decls>
case 'master-styles': // 3.15.4 <office:master-styles> -- relevant for FODS
case 'master-styles': //3.15.4 <office:master-styles> -- relevant for FODS
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
break;
@ -464,17 +231,10 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
if(textR.length) /*::(*/comment/*:: :any)*/.R = textR;
comment.a = creator;
comments.push(comment);
textp = oldtextp; textpidx = oldtextpidx; textR = oldtextR;
}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
state.push([Rn[3], false]);
var annotag = parsexmltag(Rn[0], true);
/* office:display TODO: check if there is a global override */
if(!(annotag["display"] && parsexmlbool(annotag["display"]))) comments.hidden = true;
oldtextp = textp; oldtextpidx = textpidx; oldtextR = textR;
textp = ""; textpidx = 0; textR = [];
}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);}
creator = ""; creatoridx = 0;
textp = ""; textpidx = 0; textR = [];
break;
case 'creator': // 4.3.2.7 <dc:creator>
@ -504,24 +264,23 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
textp = ""; textpidx = 0; textR = [];
break;
case 'scientific-number': // <number:scientific-number>
case 'currency-symbol': // <number:currency-symbol>
case 'fill-character': // 16.29.5 <number:fill-character>
case 'scientific-number': // TODO: <number:scientific-number>
break;
case 'currency-symbol': // TODO: <number:currency-symbol>
break;
case 'currency-style': // TODO: <number:currency-style>
break;
case 'text-style': // 16.27.25 <number:text-style>
case 'boolean-style': // 16.27.23 <number:boolean-style>
case 'number-style': // 16.27.2 <number:number-style>
case 'currency-style': // 16.29.8 <number:currency-style>
case 'percentage-style': // 16.27.9 <number:percentage-style>
case 'date-style': // 16.27.10 <number:date-style>
case 'time-style': // 16.27.18 <number:time-style>
if(Rn[1]==='/'){
var xlmlidx = xlmlregex.lastIndex;
parse_ods_styles(str.slice(nfidx, xlmlregex.lastIndex), _opts, number_format_map);
xlmlregex.lastIndex = xlmlidx;
number_format_map[NFtag.name] = NF;
if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
nfidx = xlmlregex.lastIndex - Rn[0].length;
NF = "";
NFtag = parsexmltag(Rn[0], false);
state.push([Rn[3], true]);
} break;
case 'script': break; // 3.13 <office:script>
@ -530,25 +289,24 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
case 'default-style': // TODO: <style:default-style>
case 'page-layout': break; // TODO: <style:page-layout>
case 'style': { // 16.2 <style:style>
var styletag = parsexmltag(Rn[0], false);
if(styletag["family"] == "table-cell" && number_format_map[styletag["data-style-name"]]) styles[styletag["name"]] = number_format_map[styletag["data-style-name"]];
else if(styletag["family"] == "table") tstyles[styletag["name"]] = styletag;
} break;
case 'style': // 16.2 <style:style>
break;
case 'map': break; // 16.3 <style:map>
case 'font-face': break; // 16.21 <style:font-face>
case 'paragraph-properties': break; // 17.6 <style:paragraph-properties>
case 'table-properties': { // 17.15 <style:table-properties>
var proptag = parsexmltag(Rn[0], false);
if(styletag && styletag.family == "table") styletag.display = proptag.display;
} break;
case 'table-properties': break; // 17.15 <style:table-properties>
case 'table-column-properties': break; // 17.16 <style:table-column-properties>
case 'table-row-properties': break; // 17.17 <style:table-row-properties>
case 'table-cell-properties': break; // 17.18 <style:table-cell-properties>
case 'number': // 16.27.3 <number:number>
break;
switch(state[state.length-1][0]) {
case 'time-style':
case 'date-style':
tag = parsexmltag(Rn[0], false);
NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
} break;
case 'fraction': break; // TODO 16.27.6 <number:fraction>
@ -563,9 +321,16 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
case 'minutes': // 16.27.20 <number:minutes>
case 'seconds': // 16.27.21 <number:seconds>
case 'am-pm': // 16.27.22 <number:am-pm>
break;
switch(state[state.length-1][0]) {
case 'time-style':
case 'date-style':
tag = parsexmltag(Rn[0], false);
NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
} break;
case 'boolean-style': break; // 16.27.23 <number:boolean-style>
case 'boolean': break; // 16.27.24 <number:boolean>
case 'text-style': break; // 16.27.25 <number:text-style>
case 'text': // 16.27.26 <number:text>
if(Rn[0].slice(-2) === "/>") break;
else if(Rn[1]==="/") switch(state[state.length-1][0]) {
@ -601,12 +366,7 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
case 'table-header-columns': break; // 9.1.11 <table:table-header-columns>
case 'table-columns': break; // 9.1.12 <table:table-columns>
case 'null-date': // 9.4.2 <table:null-date>
tag = parsexmltag(Rn[0], false);
switch(tag["date-value"]) {
case "1904-01-01": WB.WBProps.date1904 = true; break;
}
break;
case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
case 'graphic-properties': break; // 17.21 <style:graphic-properties>
case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
@ -626,9 +386,6 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) {
var ptp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0];
} else if(Rn[0].slice(-2) == "/>") {
/* TODO: is self-closing 文本串 valid? */
textp += "\n";
} else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
break; // <text:p>
case 's': break; // <text:s>
@ -658,13 +415,10 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
case 'help-message': break; // 9.4.6 <table:
case 'error-message': break; // 9.4.7 <table:
case 'database-ranges': break; // 9.4.14 <table:database-ranges>
/* 9.5 Filters */
case 'filter': break; // 9.5.2 <table:filter>
case 'filter-and': break; // 9.5.3 <table:filter-and>
case 'filter-or': break; // 9.5.4 <table:filter-or>
case 'filter-condition': break; // 9.5.5 <table:filter-condition>
case 'filter-set-item': break; // 9.5.6 <table:filter-condition>
case 'list-level-style-bullet': break; // 16.31 <text:
case 'list-level-style-number': break; // 16.32 <text:
@ -759,11 +513,11 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
if(Rn[1]!== '/') {
atag = parsexmltag(Rn[0], false);
if(!atag.href) break;
atag.Target = unescapexml(atag.href); delete atag.href;
atag.Target = atag.href; delete atag.href;
if(atag.Target.charAt(0) == "#" && atag.Target.indexOf(".") > -1) {
_Ref = ods_to_csf_3D(atag.Target.slice(1));
atag.Target = "#" + _Ref[0] + "!" + _Ref[1];
} else if(atag.Target.match(/^\.\.[\\\/]/)) atag.Target = atag.Target.slice(3);
}
}
break;
@ -795,22 +549,20 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
}/*:any*/);
if(opts.bookSheets) delete /*::(*/out/*:: :any)*/.Sheets;
return out;
}
};
})();
function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
opts = opts || ({}/*:any*/);
if(safegetzipfile(zip, 'META-INF/manifest.xml')) parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
var styles = getzipstr(zip, 'styles.xml');
var Styles = styles && parse_ods_styles(utf8read(styles), opts);
var ods = !!safegetzipfile(zip, 'objectdata');
if(ods) parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
var content = getzipstr(zip, 'content.xml');
if(!content) throw new Error("Missing content.xml in ODS / UOF file");
var wb = parse_content_xml(utf8read(content), opts, Styles);
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
var wb = parse_content_xml(ods ? content : utf8read(content), opts);
if(safegetzipfile(zip, 'meta.xml')) wb.Props = parse_core_props(getzipdata(zip, 'meta.xml'));
wb.bookType = "ods";
return wb;
}
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
var wb = parse_content_xml(data, opts);
wb.bookType = "fods";
return wb;
return parse_content_xml(data, opts);
}

@ -1,16 +1,5 @@
/* OpenDocument */
var write_styles_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function() {
var master_styles = [
'<office:master-styles>',
'<style:master-page style:name="mp1" style:page-layout-name="mp1">',
'<style:header/>',
'<style:header-left style:display="false"/>',
'<style:footer/>',
'<style:footer-left style:display="false"/>',
'</style:master-page>',
'</office:master-styles>'
].join("");
var write_styles_ods/*:{(wb:any, opts:any):string}*/ = (function() {
var payload = '<office:document-styles ' + wxt_helper({
'xmlns:office': "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
'xmlns:table': "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
@ -24,213 +13,33 @@ var write_styles_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function(
'xmlns:svg': "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
'xmlns:of': "urn:oasis:names:tc:opendocument:xmlns:of:1.2",
'office:version': "1.2"
}) + '>' + master_styles + '</office:document-styles>';
}) + '></office:document-styles>';
return function wso(/*::wb, opts*/) {
return XML_HEADER + payload;
};
})();
// TODO: find out if anyone actually read the spec. LO has some wild errors
function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
var type = "number", payload = "", nopts = { "style:name": nfidx }, c = "", i = 0;
nf = nf.replace(/"[$]"/g, "$");
/* TODO: replace with an actual parser based on a real grammar */
j: {
// TODO: support style maps
if(nf.indexOf(";") > -1) {
console.error("Unsupported ODS Style Map exported. Using first branch of " + nf);
nf = nf.slice(0, nf.indexOf(";"));
}
if(nf == "@") { type = "text"; payload = "<number:text-content/>"; break j; }
/* currency flag */
if(nf.indexOf(/\$/) > -1) { type = "currency"; }
/* opening string literal */
if(nf[i] == '"') {
c = "";
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
if(nf[i+1] == "*") {
i++;
payload += '<number:fill-character>' + escapexml(c.replace(/""/g, '"')) + '</number:fill-character>';
} else {
payload += '<number:text>' + escapexml(c.replace(/""/g, '"')) + '</number:text>';
}
nf = nf.slice(i+1); i = 0;
}
/* fractions */
var t = nf.match(/# (\?+)\/(\?+)/);
if(t) { payload += writextag("number:fraction", null, {"number:min-integer-digits":0, "number:min-numerator-digits": t[1].length, "number:max-denominator-value": Math.max(+(t[1].replace(/./g, "9")), +(t[2].replace(/./g, "9"))) }); break j; }
if((t=nf.match(/# (\?+)\/(\d+)/))) { payload += writextag("number:fraction", null, {"number:min-integer-digits":0, "number:min-numerator-digits": t[1].length, "number:denominator-value": +t[2]}); break j; }
/* percentages */
if((t=nf.match(/\b(\d+)(|\.\d+)%/))) { type = "percentage"; payload += writextag("number:number", null, {"number:decimal-places": t[2] && t.length - 1 || 0, "number:min-decimal-places": t[2] && t.length - 1 || 0, "number:min-integer-digits": t[1].length }) + "<number:text>%</number:text>"; break j; }
/* datetime */
var has_time = false;
if(["y","m","d"].indexOf(nf[0]) > -1) {
type = "date";
k: for(; i < nf.length; ++i) switch((c = nf[i].toLowerCase())) {
case "h": case "s": has_time = true; --i; break k;
case "m":
l: for(var h = i+1; h < nf.length; ++h) switch(nf[h]) {
case "y": case "d": break l;
case "h": case "s": has_time = true; --i; break k;
}
/* falls through */
case "y": case "d":
while((nf[++i]||"").toLowerCase() == c[0]) c += c[0]; --i;
switch(c) {
case "y": case "yy": payload += "<number:year/>"; break;
case "yyy": case "yyyy": payload += '<number:year number:style="long"/>'; break;
case "mmmmm": console.error("ODS has no equivalent of format |mmmmm|");
/* falls through */
case "m": case "mm": case "mmm": case "mmmm":
payload += '<number:month number:style="' + (c.length % 2 ? "short" : "long") + '" number:textual="' + (c.length >= 3 ? "true" : "false") + '"/>';
break;
case "d": case "dd": payload += '<number:day number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break;
case "ddd": case "dddd": payload += '<number:day-of-week number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break;
}
break;
case '"':
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
break;
case '\\': c = nf[++i];
payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
default: console.error("unrecognized character " + c + " in ODF format " + nf);
}
if(!has_time) break j;
nf = nf.slice(i+1); i = 0;
}
if(nf.match(/^\[?[hms]/)) {
if(type == "number") type = "time";
if(nf.match(/\[/)) {
nf = nf.replace(/[\[\]]/g, "");
nopts['number:truncate-on-overflow'] = "false";
}
for(; i < nf.length; ++i) switch((c = nf[i].toLowerCase())) {
case "h": case "m": case "s":
while((nf[++i]||"").toLowerCase() == c[0]) c += c[0]; --i;
switch(c) {
case "h": case "hh": payload += '<number:hours number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break;
case "m": case "mm": payload += '<number:minutes number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break;
case "s": case "ss":
if(nf[i+1] == ".") do { c += nf[i+1]; ++i; } while(nf[i+1] == "0");
payload += '<number:seconds number:style="' + (c.match("ss") ? "long" : "short") + '"' + (c.match(/\./) ? ' number:decimal-places="' + (c.match(/0+/)||[""])[0].length + '"' : "")+ '/>'; break;
}
break;
case '"':
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
break;
case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
case "a":
if(nf.slice(i, i+3).toLowerCase() == "a/p") { payload += '<number:am-pm/>'; i += 2; break; } // Note: ODF does not support A/P
if(nf.slice(i, i+5).toLowerCase() == "am/pm") { payload += '<number:am-pm/>'; i += 4; break; }
/* falls through */
default: console.error("unrecognized character " + c + " in ODF format " + nf);
}
break j;
}
/* currency flag */
if(nf.indexOf(/\$/) > -1) { type = "currency"; }
/* should be in a char loop */
if(nf[0] == "$") { payload += '<number:currency-symbol number:language="en" number:country="US">$</number:currency-symbol>'; nf = nf.slice(1); i = 0; }
i = 0; if(nf[i] == '"') {
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
if(nf[i+1] == "*") {
i++;
payload += '<number:fill-character>' + escapexml(c.replace(/""/g, '"')) + '</number:fill-character>';
} else {
payload += '<number:text>' + escapexml(c.replace(/""/g, '"')) + '</number:text>';
}
nf = nf.slice(i+1); i = 0;
}
/* number TODO: interstitial text e.g. 000)000-0000 */
var np = nf.match(/([#0][0#,]*)(\.[0#]*|)(E[+]?0*|)/i);
if(!np || !np[0]) console.error("Could not find numeric part of " + nf);
else {
var base = np[1].replace(/,/g, "");
payload += '<number:' + (np[3] ? "scientific-" : "")+ 'number' +
' number:min-integer-digits="' + (base.indexOf("0") == -1 ? "0" : base.length - base.indexOf("0")) + '"' +
(np[0].indexOf(",") > -1 ? ' number:grouping="true"' : "") +
(np[2] && ' number:decimal-places="' + (np[2].length - 1) + '"' || ' number:decimal-places="0"') +
(np[3] && np[3].indexOf("+") > -1 ? ' number:forced-exponent-sign="true"' : "" ) +
(np[3] ? ' number:min-exponent-digits="' + np[3].match(/0+/)[0].length + '"' : "" ) +
'>' +
/* TODO: interstitial text placeholders */
'</number:' + (np[3] ? "scientific-" : "") + 'number>';
i = np.index + np[0].length;
}
/* residual text */
if(nf[i] == '"') {
c = "";
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
payload += '<number:text>' + escapexml(c.replace(/""/g, '"')) + '</number:text>';
}
}
if(!payload) { console.error("Could not generate ODS number format for |" + nf + "|"); return ""; }
return writextag("number:" + type + "-style", payload, nopts);
}
function write_names_ods(Names, SheetNames, idx) {
//var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
var scoped = []; for(var namei = 0; namei < Names.length; ++namei) {
var name = Names[namei];
if(!name) continue;
if(name.Sheet == (idx == -1 ? null : idx)) scoped.push(name);
}
if(!scoped.length) return "";
return " <table:named-expressions>\n" + scoped.map(function(name) {
var odsref = (idx == -1 ? "$" : "") + csf_to_ods_3D(name.Ref);
return " " + writextag("table:named-range", null, {
"table:name": name.Name,
"table:cell-range-address": odsref,
"table:base-cell-address": odsref.replace(/[\.][^\.]*$/, ".$A$1")
});
}).join("\n") + "\n </table:named-expressions>\n";
}
var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function() {
var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
/* 6.1.2 White Space Characters */
var write_text_p = function(text/*:string*/, span)/*:string*/ {
var write_text_p = function(text/*:string*/)/*:string*/ {
return escapexml(text)
.replace(/ +/g, function($$){return '<text:s text:c="'+$$.length+'"/>';})
.replace(/\t/g, "<text:tab/>")
.replace(/\n/g, span ? "<text:line-break/>": "</text:p><text:p>")
.replace(/\n/g, "<text:line-break/>")
.replace(/^ /, "<text:s/>").replace(/ $/, "<text:s/>");
};
var null_cell_xml = ' <table:table-cell />\n';
var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts, nfs, date1904)/*:string*/ {
var covered_cell_xml = ' <table:covered-table-cell/>\n';
var write_ws = function(ws, wb/*:Workbook*/, i/*:number*//*::, opts*/)/*:string*/ {
/* Section 9 Tables */
var o/*:Array<string>*/ = [];
var tstyle = "ta1";
if(((((wb||{}).Workbook||{}).Sheets||[])[i]||{}).Hidden) tstyle = "ta2";
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="' + tstyle + '">\n');
var R=0,C=0, range = decode_range(ws['!ref']||"A1");
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="ta1">\n');
var R=0,C=0, range = decode_range(ws['!ref']);
var marr/*:Array<Range>*/ = ws['!merges'] || [], mi = 0;
var dense = ws["!data"] != null;
if(ws["!cols"]) {
for(C = 0; C <= range.e.c; ++C) o.push(' <table:table-column' + (ws["!cols"][C] ? ' table:style-name="co' + ws["!cols"][C].ods + '"' : '') + '></table:table-column>\n');
}
var H = "", ROWS = ws["!rows"]||[];
for(R = 0; R < range.s.r; ++R) {
H = ROWS[R] ? ' table:style-name="ro' + ROWS[R].ods + '"' : "";
o.push(' <table:table-row' + H + '></table:table-row>\n');
}
var dense = Array.isArray(ws);
for(R = 0; R < range.s.r; ++R) o.push(' <table:table-row></table:table-row>\n');
for(; R <= range.e.r; ++R) {
H = ROWS[R] ? ' table:style-name="ro' + ROWS[R].ods + '"' : "";
o.push(' <table:table-row' + H + '>\n');
o.push(' <table:table-row>\n');
for(C=0; C < range.s.c; ++C) o.push(null_cell_xml);
for(; C <= range.e.c; ++C) {
var skip = false, ct = {}, textp = "";
@ -244,8 +53,8 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
ct['table:number-rows-spanned'] = (marr[mi].e.r - marr[mi].s.r + 1);
break;
}
if(skip) { o.push(' <table:covered-table-cell/>\n'); continue; }
var ref = encode_cell({r:R, c:C}), cell = dense ? (ws["!data"][R]||[])[C]: ws[ref];
if(skip) { o.push(covered_cell_xml); continue; }
var ref = encode_cell({r:R, c:C}), cell = dense ? (ws[R]||[])[C]: ws[ref];
if(cell && cell.f) {
ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f));
if(cell.F) {
@ -264,110 +73,39 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
ct['office:boolean-value'] = (cell.v ? 'true' : 'false');
break;
case 'n':
if(!isFinite(cell.v)) {
if(isNaN(cell.v)) {
textp = "#NUM!";
ct['table:formula'] = "of:=#NUM!";
} else {
textp = "#DIV/0!";
ct['table:formula'] = "of:=" + (cell.v < 0 ? "-" : "") + "1/0";
}
ct['office:string-value'] = "";
ct['office:value-type'] = "string";
ct['calcext:value-type'] = "error";
} else {
textp = (cell.w||String(cell.v||0));
ct['office:value-type'] = "float";
ct['office:value'] = (cell.v||0);
}
textp = (cell.w||String(cell.v||0));
ct['office:value-type'] = "float";
ct['office:value'] = (cell.v||0);
break;
case 's': case 'str':
textp = cell.v == null ? "" : cell.v;
ct['office:value-type'] = "string";
break;
case 'd':
textp = (cell.w||(parseDate(cell.v, date1904).toISOString()));
textp = (cell.w||(parseDate(cell.v).toISOString()));
ct['office:value-type'] = "date";
ct['office:date-value'] = (parseDate(cell.v, date1904).toISOString());
ct['office:date-value'] = (parseDate(cell.v).toISOString());
ct['table:style-name'] = "ce1";
break;
//case 'e': // TODO: translate to ODS errors
default: o.push(null_cell_xml); continue; // TODO: empty cell with comments
//case 'e':
default: o.push(null_cell_xml); continue;
}
var text_p = write_text_p(textp);
if(cell.l && cell.l.Target) {
var _tgt = cell.l.Target;
_tgt = _tgt.charAt(0) == "#" ? "#" + csf_to_ods_3D(_tgt.slice(1)) : _tgt;
// TODO: choose correct parent path format based on link delimiters
if(_tgt.charAt(0) != "#" && !_tgt.match(/^\w+:/)) _tgt = '../' + _tgt;
text_p = writextag('text:a', text_p, {'xlink:href': _tgt.replace(/&/g, "&amp;")});
var _tgt = cell.l.Target; _tgt = _tgt.charAt(0) == "#" ? "#" + csf_to_ods_3D(_tgt.slice(1)) : _tgt;
text_p = writextag('text:a', text_p, {'xlink:href': _tgt});
}
if(nfs[cell.z]) ct["table:style-name"] = "ce" + nfs[cell.z].slice(1);
var payload = writextag('text:p', text_p, {});
if(cell.c) {
var acreator = "", apayload = "", aprops = {};
for(var ci = 0; ci < cell.c.length; ++ci) {
if(!acreator && cell.c[ci].a) acreator = cell.c[ci].a;
apayload += "<text:p>" + write_text_p(cell.c[ci].t) + "</text:p>";
}
if(!cell.c.hidden) aprops["office:display"] = true;
payload = writextag('office:annotation', apayload, aprops) + payload;
}
o.push(' ' + writextag('table:table-cell', payload, ct) + '\n');
o.push(' ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n');
}
o.push(' </table:table-row>\n');
}
if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, i));
o.push(' </table:table>\n');
return o.join("");
};
var write_automatic_styles_ods = function(o/*:Array<string>*/, wb) {
var write_automatic_styles_ods = function(o/*:Array<string>*/) {
o.push(' <office:automatic-styles>\n');
/* column styles */
var cidx = 0;
wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
if(!ws) return;
if(ws["!cols"]) {
for(var C = 0; C < ws["!cols"].length; ++C) if(ws["!cols"][C]) {
var colobj = ws["!cols"][C];
if(colobj.width == null && colobj.wpx == null && colobj.wch == null) continue;
process_col(colobj);
colobj.ods = cidx;
var w = ws["!cols"][C].wpx + "px";
o.push(' <style:style style:name="co' + cidx + '" style:family="table-column">\n');
o.push(' <style:table-column-properties fo:break-before="auto" style:column-width="' + w + '"/>\n');
o.push(' </style:style>\n');
++cidx;
}
}
});
/* row styles */
var ridx = 0;
wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
if(!ws) return;
if(ws["!rows"]) {
for(var R = 0; R < ws["!rows"].length; ++R) if(ws["!rows"][R]) {
ws["!rows"][R].ods = ridx;
var h = ws["!rows"][R].hpx + "px";
o.push(' <style:style style:name="ro' + ridx + '" style:family="table-row">\n');
o.push(' <style:table-row-properties fo:break-before="auto" style:row-height="' + h + '"/>\n');
o.push(' </style:style>\n');
++ridx;
}
}
});
/* table */
o.push(' <style:style style:name="ta1" style:family="table" style:master-page-name="mp1">\n');
o.push(' <style:table-properties table:display="true" style:writing-mode="lr-tb"/>\n');
o.push(' </style:style>\n');
o.push(' <style:style style:name="ta2" style:family="table" style:master-page-name="mp1">\n');
o.push(' <style:table-properties table:display="false" style:writing-mode="lr-tb"/>\n');
o.push(' </style:style>\n');
o.push(' <number:date-style style:name="N37" number:automatic-order="true">\n');
o.push(' <number:month number:style="long"/>\n');
o.push(' <number:text>/</number:text>\n');
@ -376,32 +114,17 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
o.push(' <number:year/>\n');
o.push(' </number:date-style>\n');
/* number formats, table cells, text */
var nfs = {};
var nfi = 69;
wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
if(!ws) return;
var dense = (ws["!data"] != null);
if(!ws["!ref"]) return;
var range = decode_range(ws["!ref"]);
for(var R = 0; R <= range.e.r; ++R) for(var C = 0; C <= range.e.c; ++C) {
var c = dense ? (ws["!data"][R]||[])[C] : ws[encode_cell({r:R,c:C})];
if(!c || !c.z || c.z.toLowerCase() == "general") continue;
if(!nfs[c.z]) {
var out = write_number_format_ods(c.z, "N" + nfi);
if(out) { nfs[c.z] = "N" + nfi; ++nfi; o.push(out + "\n"); }
}
}
});
/* table */
o.push(' <style:style style:name="ta1" style:family="table">\n'); // style:master-page-name="mp1">\n');
o.push(' <style:table-properties table:display="true" style:writing-mode="lr-tb"/>\n');
o.push(' </style:style>\n');
/* table cells, text */
o.push(' <style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N37"/>\n');
keys(nfs).forEach(function(nf) {
o.push('<style:style style:name="ce' + nfs[nf].slice(1) + '" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="' + nfs[nf] + '"/>\n');
});
/* page-layout */
o.push(' </office:automatic-styles>\n');
return nfs;
};
return function wcx(wb, opts) {
@ -452,18 +175,12 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
'office:mimetype': "application/vnd.oasis.opendocument.spreadsheet"
});
if(opts.bookType == "fods") {
o.push('<office:document' + attr + fods + '>\n');
o.push(write_meta_ods().replace(/<office:document-meta[^<>]*?>/, "").replace(/<\/office:document-meta>/, "") + "\n");
// TODO: settings (equiv of settings.xml for ODS)
} else o.push('<office:document-content' + attr + '>\n');
// o.push(' <office:scripts/>\n');
var nfs = write_automatic_styles_ods(o, wb);
if(opts.bookType == "fods") o.push('<office:document' + attr + fods + '>\n');
else o.push('<office:document-content' + attr + '>\n');
write_automatic_styles_ods(o);
o.push(' <office:body>\n');
o.push(' <office:spreadsheet>\n');
if(((wb.Workbook||{}).WBProps||{}).date1904) o.push(' <table:calculation-settings table:case-sensitive="false" table:search-criteria-must-apply-to-whole-cell="true" table:use-wildcards="true" table:use-regular-expressions="false" table:automatic-find-labels="false">\n <table:null-date table:date-value="1904-01-01"/>\n </table:calculation-settings>\n');
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs, ((wb.Workbook||{}).WBProps||{}).date1904));
if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1));
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts));
o.push(' </office:spreadsheet>\n');
o.push(' </office:body>\n');
if(opts.bookType == "fods") o.push('</office:document>');
@ -475,6 +192,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
function write_ods(wb/*:any*/, opts/*:any*/) {
if(opts.bookType == "fods") return write_content_ods(wb, opts);
/*:: if(!jszip) throw new Error("JSZip is not available"); */
var zip = zip_new();
var f = "";
@ -499,7 +217,7 @@ function write_ods(wb/*:any*/, opts/*:any*/) {
/* TODO: this is hard-coded to satiate excel */
f = "meta.xml";
zip_add_file(zip, f, XML_HEADER + write_meta_ods(/*::wb, opts*/));
zip_add_file(zip, f, write_meta_ods(/*::wb, opts*/));
manifest.push([f, "text/xml"]);
rdf.push([f, "MetadataFile"]);

24
bits/82_sheeter.js Normal file

@ -0,0 +1,24 @@
function write_sheet_index(wb/*:Workbook*/, sheet/*:?string*/)/*:number*/ {
if(!sheet) return 0;
var idx = wb.SheetNames.indexOf(sheet);
if(idx == -1) throw new Error("Sheet not found: " + sheet);
return idx;
}
function write_obj_str(factory/*:WriteObjStrFactory*/) {
return function write_str(wb/*:Workbook*/, o/*:WriteOpts*/)/*:string*/ {
var idx = write_sheet_index(wb, o.sheet);
return factory.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb);
};
}
var write_htm_str = write_obj_str(HTML_);
var write_csv_str = write_obj_str({from_sheet:sheet_to_csv});
var write_slk_str = write_obj_str(typeof SYLK !== "undefined" ? SYLK : {});
var write_dif_str = write_obj_str(typeof DIF !== "undefined" ? DIF : {});
var write_prn_str = write_obj_str(typeof PRN !== "undefined" ? PRN : {});
var write_rtf_str = write_obj_str(typeof RTF !== "undefined" ? RTF : {});
var write_txt_str = write_obj_str({from_sheet:sheet_to_txt});
var write_dbf_buf = write_obj_str(typeof DBF !== "undefined" ? DBF : {});
var write_eth_str = write_obj_str(typeof ETH !== "undefined" ? ETH : {});

File diff suppressed because it is too large Load Diff

@ -8,7 +8,7 @@ function fix_opts_func(defaults/*:Array<Array<any> >*/)/*:{(o:any):void}*/ {
};
}
function fix_read_opts(opts) {
var fix_read_opts = function(opts) {
fix_opts_func([
['cellNF', false], /* emit cell number format string as .z */
['cellHTML', true], /* emit html string as .h */
@ -29,10 +29,9 @@ fix_opts_func([
['password',''], /* password */
['WTF', false] /* WTF mode (throws errors) */
])(opts);
}
};
function fix_write_opts(opts) {
fix_opts_func([
var fix_write_opts = fix_opts_func([
['cellDates', false], /* write date cells with type `d` */
['bookSST', false], /* Generate Shared String Table */
@ -42,5 +41,4 @@ fix_opts_func([
['compression', false], /* Use file compression */
['WTF', false] /* WTF mode (throws errors) */
])(opts);
}
]);

@ -13,13 +13,6 @@ function safe_parse_wbrels(wbrels, sheets) {
return !wbrels || wbrels.length === 0 ? null : wbrels;
}
function parse_sheet_legacy_drawing(sheet, type, zip, path, idx, opts, wb, comments) {
if(!sheet || !sheet['!legdrawel']) return;
var dfile = resolve_path(sheet['!legdrawel'].Target, path);
var draw = getzipstr(zip, dfile, true);
if(draw) parse_vml(utf8read(draw), sheet, comments||[]);
}
function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/*:number*/, sheetRels, sheets, stype/*:string*/, opts, wb, themes, styles) {
try {
sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
@ -42,30 +35,23 @@ function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/
}
sheets[sheet] = _ws;
/* scan rels for comments and threaded comments */
var comments = [], tcomments = [];
/* scan rels for comments */
var comments = [];
if(sheetRels && sheetRels[sheet]) keys(sheetRels[sheet]).forEach(function(n) {
var dfile = "";
if(sheetRels[sheet][n].Type == RELS.CMNT) {
dfile = resolve_path(sheetRels[sheet][n].Target, path);
var dfile = resolve_path(sheetRels[sheet][n].Target, path);
comments = parse_cmnt(getzipdata(zip, dfile, true), dfile, opts);
if(!comments || !comments.length) return;
sheet_insert_comments(_ws, comments, false);
}
if(sheetRels[sheet][n].Type == RELS.TCMNT) {
dfile = resolve_path(sheetRels[sheet][n].Target, path);
tcomments = tcomments.concat(parse_tcmnt_xml(getzipdata(zip, dfile, true), opts));
sheet_insert_comments(_ws, comments);
}
});
if(tcomments && tcomments.length) sheet_insert_comments(_ws, tcomments, true, opts.people || []);
parse_sheet_legacy_drawing(_ws, stype, zip, path, idx, opts, wb, comments);
} catch(e) { if(opts.WTF) throw e; }
}
function strip_front_slash(x/*:string*/)/*:string*/ { return x.charAt(0) == '/' ? x.slice(1) : x; }
function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
make_ssf();
make_ssf(SSF);
opts = opts || {};
fix_read_opts(opts);
@ -74,30 +60,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
/* UOC */
if(safegetzipfile(zip, 'objectdata.xml')) return parse_ods(zip, opts);
/* Numbers */
if(safegetzipfile(zip, 'Index/Document.iwa')) {
if(typeof Uint8Array == "undefined") throw new Error('NUMBERS file parsing requires Uint8Array support');
if(typeof parse_numbers_iwa != "undefined") {
if(zip.FileIndex) return parse_numbers_iwa(zip, opts);
var _zip = CFB.utils.cfb_new();
zipentries(zip).forEach(function(e) { zip_add_file(_zip, e, getzipbin(zip, e)); });
return parse_numbers_iwa(_zip, opts);
}
throw new Error('Unsupported NUMBERS file');
}
if(!safegetzipfile(zip, '[Content_Types].xml')) {
if(safegetzipfile(zip, 'index.xml.gz')) throw new Error('Unsupported NUMBERS 08 file');
if(safegetzipfile(zip, 'index.xml')) throw new Error('Unsupported NUMBERS 09 file');
var index_zip = CFB.find(zip, 'Index.zip');
if(index_zip) {
opts = dup(opts);
delete opts.type;
if(typeof index_zip.content == "string") opts.type = "binary";
// TODO: Bun buffer bug
if(typeof Bun !== "undefined" && Buffer.isBuffer(index_zip.content)) return readSync(new Uint8Array(index_zip.content), opts);
return readSync(index_zip.content, opts);
}
throw new Error('Unsupported ZIP file');
}
if(safegetzipfile(zip, 'Index/Document.iwa')) throw new Error('Unsupported NUMBERS file');
var entries = zipentries(zip);
var dir = parse_ct((getzipstr(zip, '[Content_Types].xml')/*:?any*/));
@ -121,7 +84,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
strs = [];
if(dir.sst) try { strs=parse_sst(getzipdata(zip, strip_front_slash(dir.sst)), dir.sst, opts); } catch(e) { if(opts.WTF) throw e; }
if(opts.cellStyles && dir.themes.length) themes = parse_theme_xml(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"", opts);
if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts);
if(dir.style) styles = parse_sty(getzipdata(zip, strip_front_slash(dir.style)), dir.style, themes, opts);
}
@ -184,17 +147,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
var wbrelsi = dir.workbooks[0].lastIndexOf("/");
var wbrelsfile = (dir.workbooks[0].slice(0, wbrelsi+1) + "_rels/" + dir.workbooks[0].slice(wbrelsi+1) + ".rels").replace(/^\//,"");
if(!safegetzipfile(zip, wbrelsfile)) wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
var wbrels = parse_rels(getzipstr(zip, wbrelsfile, true), wbrelsfile.replace(/_rels.*/, "s5s"));
if((dir.metadata || []).length >= 1) {
/* TODO: MDX and other types of metadata */
opts.xlmeta = parse_xlmeta(getzipdata(zip, strip_front_slash(dir.metadata[0])),dir.metadata[0],opts);
}
if((dir.people || []).length >= 1) {
opts.people = parse_people_xml(getzipdata(zip, strip_front_slash(dir.people[0])),opts);
}
var wbrels = parse_rels(getzipstr(zip, wbrelsfile, true), wbrelsfile);
if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
/* Numbers iOS hack */
@ -204,7 +157,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
if(wbrels && wbrels[i]) {
path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
if(!safegetzipfile(zip, path)) path = wbrels[i][1];
if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/[\S\s]*$/,"") + wbrels[i][1];
if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/.*$/,"") + wbrels[i][1];
stype = wbrels[i][2];
} else {
path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
@ -237,28 +190,16 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
Strings: strs,
Styles: styles,
Themes: themes,
SSF: dup(table_fmt)
SSF: SSF.get_table()
}/*:any*/);
if(opts && opts.bookFiles) {
if(zip.files) {
out.keys = entries;
out.files = zip.files;
} else {
out.keys = [];
out.files = {};
zip.FullPaths.forEach(function(p, idx) {
p = p.replace(/^Root Entry[\/]/, "");
out.keys.push(p);
out.files[p] = zip.FileIndex[idx];
});
}
out.keys = entries;
out.files = zip.files;
}
if(opts && opts.bookVBA) {
if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,strip_front_slash(dir.vba[0]),true);
else if(dir.defaults && dir.defaults.bin === CT_VBA) out.vbaraw = getzipdata(zip, 'xl/vbaProject.bin',true);
}
// TODO: pass back content types metadata for xlsm/xlsx resolution
out.bookType = xlsb ? "xlsb" : "xlsx";
return out;
}

@ -1,9 +1,11 @@
function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
_shapeid = 1024;
if(opts.bookType == "ods") return write_ods(wb, opts);
if(wb && !wb.SSF) {
wb.SSF = dup(table_fmt);
wb.SSF = SSF.get_table();
}
if(wb && wb.SSF) {
make_ssf(); SSF_load_table(wb.SSF);
make_ssf(SSF); SSF.load_table(wb.SSF);
// $FlowIgnore
opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
opts.ssf = wb.SSF;
@ -12,166 +14,11 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
opts.Strings = /*::((*/[]/*:: :any):SST)*/; opts.Strings.Count = 0; opts.Strings.Unique = 0;
if(browser_has_Map) opts.revStrings = new Map();
else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; }
var wbext = "bin";
var vbafmt = true;
var ct = new_ct();
fix_write_opts(opts = opts || {});
var zip = zip_new();
var f = "", rId = 0;
opts.cellXfs = [];
get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}});
if(!wb.Props) wb.Props = {};
f = "docProps/core.xml";
zip_add_file(zip, f, write_core_props(wb.Props, opts));
ct.coreprops.push(f);
add_rels(opts.rels, 2, f, RELS.CORE_PROPS);
/*::if(!wb.Props) throw "unreachable"; */
f = "docProps/app.xml";
if(wb.Props && wb.Props.SheetNames){/* empty */}
else if(!wb.Workbook || !wb.Workbook.Sheets) wb.Props.SheetNames = wb.SheetNames;
else {
var _sn = [];
for(var _i = 0; _i < wb.SheetNames.length; ++_i)
if((wb.Workbook.Sheets[_i]||{}).Hidden != 2) _sn.push(wb.SheetNames[_i]);
wb.Props.SheetNames = _sn;
}
wb.Props.Worksheets = wb.Props.SheetNames.length;
zip_add_file(zip, f, write_ext_props(wb.Props, opts));
ct.extprops.push(f);
add_rels(opts.rels, 3, f, RELS.EXT_PROPS);
if(wb.Custprops !== wb.Props && keys(wb.Custprops||{}).length > 0) {
f = "docProps/custom.xml";
zip_add_file(zip, f, write_cust_props(wb.Custprops, opts));
ct.custprops.push(f);
add_rels(opts.rels, 4, f, RELS.CUST_PROPS);
}
var people = ["SheetJ5"];
opts.tcid = 0;
for(rId=1;rId <= wb.SheetNames.length; ++rId) {
var wsrels = {'!id':{}};
var ws = wb.Sheets[wb.SheetNames[rId-1]];
var _type = (ws || {})["!type"] || "sheet";
switch(_type) {
case "chart":
/* falls through */
default:
f = "xl/worksheets/sheet" + rId + "." + wbext;
zip_add_file(zip, f, write_ws_bin(rId-1, opts, wb, wsrels));
ct.sheets.push(f);
add_rels(opts.wbrels, -1, "worksheets/sheet" + rId + "." + wbext, RELS.WS[0]);
}
if(ws) {
var comments = ws['!comments'];
var need_vml = false;
var cf = "";
if(comments && comments.length > 0) {
var needtc = false;
comments.forEach(function(carr) {
carr[1].forEach(function(c) { if(c.T == true) needtc = true; });
});
if(needtc) {
cf = "xl/threadedComments/threadedComment" + rId + ".xml";
zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts));
ct.threadedcomments.push(cf);
add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + ".xml", RELS.TCMNT);
}
cf = "xl/comments" + rId + "." + wbext;
zip_add_file(zip, cf, write_comments_bin(comments, opts));
ct.comments.push(cf);
add_rels(wsrels, -1, "../comments" + rId + "." + wbext, RELS.CMNT);
need_vml = true;
}
if(ws['!legacy']) {
if(need_vml) zip_add_file(zip, "xl/drawings/vmlDrawing" + (rId) + ".vml", write_vml(rId, ws['!comments']));
}
delete ws['!comments'];
delete ws['!legacy'];
}
if(wsrels['!id'].rId1) zip_add_file(zip, get_rels_path(f), write_rels(wsrels));
}
if(opts.Strings != null && opts.Strings.length > 0) {
f = "xl/sharedStrings." + wbext;
zip_add_file(zip, f, write_sst_bin(opts.Strings, opts));
ct.strs.push(f);
add_rels(opts.wbrels, -1, "sharedStrings." + wbext, RELS.SST);
}
f = "xl/workbook." + wbext;
zip_add_file(zip, f, write_wb_bin(wb, opts));
ct.workbooks.push(f);
add_rels(opts.rels, 1, f, RELS.WB);
/* TODO: something more intelligent with themes */
f = "xl/theme/theme1.xml";
var ww = write_theme(wb.Themes, opts);
zip_add_file(zip, f, ww);
ct.themes.push(f);
add_rels(opts.wbrels, -1, "theme/theme1.xml", RELS.THEME);
/* TODO: something more intelligent with styles */
f = "xl/styles." + wbext;
zip_add_file(zip, f, write_sty_bin(wb, opts));
ct.styles.push(f);
add_rels(opts.wbrels, -1, "styles." + wbext, RELS.STY);
if(wb.vbaraw && vbafmt) {
f = "xl/vbaProject.bin";
zip_add_file(zip, f, wb.vbaraw);
ct.vba.push(f);
add_rels(opts.wbrels, -1, "vbaProject.bin", RELS.VBA);
}
f = "xl/metadata." + wbext;
zip_add_file(zip, f, write_xlmeta_bin());
ct.metadata.push(f);
add_rels(opts.wbrels, -1, "metadata." + wbext, RELS.XLMETA);
if(people.length > 1) {
f = "xl/persons/person.xml";
zip_add_file(zip, f, write_people_xml(people, opts));
ct.people.push(f);
add_rels(opts.wbrels, -1, "persons/person.xml", RELS.PEOPLE);
}
zip_add_file(zip, "[Content_Types].xml", write_ct(ct, opts));
zip_add_file(zip, '_rels/.rels', write_rels(opts.rels));
zip_add_file(zip, 'xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));
delete opts.revssf; delete opts.ssf;
return zip;
}
function write_zip_xlsx(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
if(wb && !wb.SSF) {
wb.SSF = dup(table_fmt);
}
if(wb && wb.SSF) {
make_ssf(); SSF_load_table(wb.SSF);
// $FlowIgnore
opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
opts.ssf = wb.SSF;
}
opts.rels = {}; opts.wbrels = {};
opts.Strings = /*::((*/[]/*:: :any):SST)*/; opts.Strings.Count = 0; opts.Strings.Unique = 0;
if(browser_has_Map) opts.revStrings = new Map();
else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; }
var wbext = "xml";
var wbext = opts.bookType == "xlsb" ? "bin" : "xml";
var vbafmt = VBAFMTS.indexOf(opts.bookType) > -1;
var ct = new_ct();
fix_write_opts(opts = opts || {});
/*:: if(!jszip) throw new Error("JSZip is not available"); */
var zip = zip_new();
var f = "", rId = 0;
@ -207,9 +54,6 @@ function write_zip_xlsx(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
add_rels(opts.rels, 4, f, RELS.CUST_PROPS);
}
var people = ["SheetJ5"];
opts.tcid = 0;
for(rId=1;rId <= wb.SheetNames.length; ++rId) {
var wsrels = {'!id':{}};
var ws = wb.Sheets[wb.SheetNames[rId-1]];
@ -219,7 +63,7 @@ function write_zip_xlsx(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
/* falls through */
default:
f = "xl/worksheets/sheet" + rId + "." + wbext;
zip_add_file(zip, f, write_ws_xml(rId-1, opts, wb, wsrels));
zip_add_file(zip, f, write_ws(rId-1, f, opts, wb, wsrels));
ct.sheets.push(f);
add_rels(opts.wbrels, -1, "worksheets/sheet" + rId + "." + wbext, RELS.WS[0]);
}
@ -227,27 +71,15 @@ function write_zip_xlsx(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
if(ws) {
var comments = ws['!comments'];
var need_vml = false;
var cf = "";
if(comments && comments.length > 0) {
var needtc = false;
comments.forEach(function(carr) {
carr[1].forEach(function(c) { if(c.T == true) needtc = true; });
});
if(needtc) {
cf = "xl/threadedComments/threadedComment" + rId + ".xml";
zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts));
ct.threadedcomments.push(cf);
add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + ".xml", RELS.TCMNT);
}
cf = "xl/comments" + rId + "." + wbext;
zip_add_file(zip, cf, write_comments_xml(comments, opts));
var cf = "xl/comments" + rId + "." + wbext;
zip_add_file(zip, cf, write_cmnt(comments, cf, opts));
ct.comments.push(cf);
add_rels(wsrels, -1, "../comments" + rId + "." + wbext, RELS.CMNT);
need_vml = true;
}
if(ws['!legacy']) {
if(need_vml) zip_add_file(zip, "xl/drawings/vmlDrawing" + (rId) + ".vml", write_vml(rId, ws['!comments']));
if(need_vml) zip_add_file(zip, "xl/drawings/vmlDrawing" + (rId) + ".vml", write_comments_vml(rId, ws['!comments']));
}
delete ws['!comments'];
delete ws['!legacy'];
@ -258,13 +90,13 @@ function write_zip_xlsx(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
if(opts.Strings != null && opts.Strings.length > 0) {
f = "xl/sharedStrings." + wbext;
zip_add_file(zip, f, write_sst_xml(opts.Strings, opts));
zip_add_file(zip, f, write_sst(opts.Strings, f, opts));
ct.strs.push(f);
add_rels(opts.wbrels, -1, "sharedStrings." + wbext, RELS.SST);
}
f = "xl/workbook." + wbext;
zip_add_file(zip, f, write_wb_xml(wb, opts));
zip_add_file(zip, f, write_wb(wb, f, opts));
ct.workbooks.push(f);
add_rels(opts.rels, 1, f, RELS.WB);
@ -278,7 +110,7 @@ function write_zip_xlsx(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
/* TODO: something more intelligent with styles */
f = "xl/styles." + wbext;
zip_add_file(zip, f, write_sty_xml(wb, opts));
zip_add_file(zip, f, write_sty(wb, f, opts));
ct.styles.push(f);
add_rels(opts.wbrels, -1, "styles." + wbext, RELS.STY);
@ -289,18 +121,6 @@ function write_zip_xlsx(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
add_rels(opts.wbrels, -1, "vbaProject.bin", RELS.VBA);
}
f = "xl/metadata." + wbext;
zip_add_file(zip, f, write_xlmeta_xml());
ct.metadata.push(f);
add_rels(opts.wbrels, -1, "metadata." + wbext, RELS.XLMETA);
if(people.length > 1) {
f = "xl/persons/person.xml";
zip_add_file(zip, f, write_people_xml(people, opts));
ct.people.push(f);
add_rels(opts.wbrels, -1, "persons/person.xml", RELS.PEOPLE);
}
zip_add_file(zip, "[Content_Types].xml", write_ct(ct, opts));
zip_add_file(zip, '_rels/.rels', write_rels(opts.rels));
zip_add_file(zip, 'xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));
@ -308,4 +128,3 @@ function write_zip_xlsx(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
delete opts.revssf; delete opts.ssf;
return zip;
}

@ -2,7 +2,7 @@ function firstbyte(f/*:RawData*/,o/*:?TypeOpts*/)/*:Array<number>*/ {
var x = "";
switch((o||{}).type || "base64") {
case 'buffer': return [f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]];
case 'base64': x = Base64_decode(f.slice(0,12)); break;
case 'base64': x = Base64.decode(f.slice(0,12)); break;
case 'binary': x = f; break;
case 'array': return [f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]];
default: throw new Error("Unrecognized type " + (o && o.type || "undefined"));
@ -16,6 +16,7 @@ function read_cfb(cfb/*:CFBContainer*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
}
function read_zip(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
/*:: if(!jszip) throw new Error("JSZip is not available"); */
var zip, d = data;
var o = opts||{};
if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
@ -36,27 +37,20 @@ function read_plaintext(data/*:string*/, o/*:ParseOpts*/)/*:Workbook*/ {
function read_plaintext_raw(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
var str = "", bytes = firstbyte(data, o);
switch(o.type) {
case 'base64': str = Base64_decode(data); break;
case 'base64': str = Base64.decode(data); break;
case 'binary': str = data; break;
case 'buffer': str = data.toString('binary'); break;
case 'array': str = cc2str(data); break;
default: throw new Error("Unrecognized type " + o.type);
}
if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str);
o.type = "binary";
return read_plaintext(str, o);
}
function read_utf16(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
var d = data;
if(o.type == 'base64') d = Base64_decode(d);
if(typeof ArrayBuffer !== "undefined" && data instanceof ArrayBuffer) d = new Uint8Array(data);
d = typeof $cptable !== "undefined" ? $cptable.utils.decode(1200, d.slice(2), 'str') : (
(has_buf && Buffer.isBuffer(data)) ? data.slice(2).toString("utf16le") :
(typeof Uint8Array !== "undefined" && d instanceof Uint8Array) ? (
typeof TextDecoder !== "undefined" ? new TextDecoder("utf-16le").decode(d.slice(2)) : utf16lereadu(d.slice(2))
) : utf16leread(d.slice(2))
);
if(o.type == 'base64') d = Base64.decode(d);
d = cptable.utils.decode(1200, d.slice(2), 'str');
o.type = "binary";
return read_plaintext(d, o);
}
@ -72,18 +66,14 @@ function read_prn(data, d, o, str) {
function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
reset_cp();
var o = opts||{};
if(o.codepage && typeof $cptable === "undefined") console.error("Codepage tables are not loaded. Non-ASCII characters may not give expected results");
if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), (o = dup(o), o.type = "array", o));
/* Javet projects `byte[]` to `Int8Array` */
if(typeof Int8Array !== 'undefined' && data instanceof Int8Array) return readSync(new Uint8Array(data.buffer, data.byteOffset, data.length), o);
if(typeof Uint8Array !== 'undefined' && data instanceof Uint8Array && !o.type) o.type = typeof Deno !== "undefined" ? "buffer" : "array";
if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), opts);
var d = data, n = [0,0,0,0], str = false;
var o = opts||{};
if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; }
_ssfopts = {};
if(o.dateNF) _ssfopts.dateNF = o.dateNF;
if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
if(o.type == "file") { o.type = has_buf ? "buffer" : "binary"; d = read_binary(data); if(typeof Uint8Array !== 'undefined' && !has_buf) o.type = "array"; }
if(o.type == "file") { o.type = has_buf ? "buffer" : "binary"; d = read_binary(data); }
if(o.type == "string") { str = true; o.type = "binary"; o.codepage = 65001; d = bstrify(data); }
if(o.type == 'array' && typeof Uint8Array !== 'undefined' && data instanceof Uint8Array && typeof ArrayBuffer !== 'undefined') {
// $FlowIgnore
@ -93,7 +83,7 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
}
switch((n = firstbyte(d, o))[0]) {
case 0xD0: if(n[1] === 0xCF && n[2] === 0x11 && n[3] === 0xE0 && n[4] === 0xA1 && n[5] === 0xB1 && n[6] === 0x1A && n[7] === 0xE1) return read_cfb(CFB.read(d, o), o); break;
case 0x09: if(n[1] <= 0x08) return parse_xlscfb(d, o); break;
case 0x09: if(n[1] <= 0x04) return parse_xlscfb(d, o); break;
case 0x3C: return parse_xlml(d, o);
case 0x49:
if(n[1] === 0x49 && n[2] === 0x2a && n[3] === 0x00) throw new Error("TIFF Image File is not a spreadsheet");
@ -102,27 +92,13 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
case 0x54: if(n[1] === 0x41 && n[2] === 0x42 && n[3] === 0x4C) return DIF.to_workbook(d, o); break;
case 0x50: return (n[1] === 0x4B && n[2] < 0x09 && n[3] < 0x09) ? read_zip(d, o) : read_prn(data, d, o, str);
case 0xEF: return n[3] === 0x3C ? parse_xlml(d, o) : read_prn(data, d, o, str);
case 0xFF:
if(n[1] === 0xFE) { return read_utf16(d, o); }
else if(n[1] === 0x00 && n[2] === 0x02 && n[3] === 0x00) return WK_.to_workbook(d, o);
break;
case 0x00:
if(n[1] === 0x00) {
if(n[2] >= 0x02 && n[3] === 0x00) return WK_.to_workbook(d, o);
if(n[2] === 0x00 && (n[3] === 0x08 || n[3] === 0x09)) return WK_.to_workbook(d, o);
}
break;
case 0xFF: if(n[1] === 0xFE) { return read_utf16(d, o); } break;
case 0x00: if(n[1] === 0x00 && n[2] >= 0x02 && n[3] === 0x00) return WK_.to_workbook(d, o); break;
case 0x03: case 0x83: case 0x8B: case 0x8C: return DBF.to_workbook(d, o);
case 0x7B: if(n[1] === 0x5C && n[2] === 0x72 && n[3] === 0x74) return rtf_to_workbook(d, o); break;
case 0x7B: if(n[1] === 0x5C && n[2] === 0x72 && n[3] === 0x74) return RTF.to_workbook(d, o); break;
case 0x0A: case 0x0D: case 0x20: return read_plaintext_raw(d, o);
case 0x89: if(n[1] === 0x50 && n[2] === 0x4E && n[3] === 0x47) throw new Error("PNG Image File is not a spreadsheet"); break;
case 0x08: if(n[1] === 0xE7) throw new Error("Unsupported Multiplan 1.x file!"); break;
case 0x0C:
if(n[1] === 0xEC) throw new Error("Unsupported Multiplan 2.x file!");
if(n[1] === 0xED) throw new Error("Unsupported Multiplan 3.x file!");
break;
}
if(DBF_SUPPORTED_VERSIONS.indexOf(n[0]) > -1 && n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
if(DBF.versions.indexOf(n[0]) > -1 && n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
return read_prn(data, d, o, str);
}

@ -9,46 +9,22 @@ function write_cfb_ctr(cfb/*:CFBContainer*/, o/*:WriteOpts*/)/*:any*/ {
return CFB.write(cfb, o);
}
function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
switch(opts.bookType) {
case "ods": return write_ods(wb, opts);
case "numbers": return write_numbers_iwa(wb, opts);
case "xlsb": return write_zip_xlsb(wb, opts);
default: return write_zip_xlsx(wb, opts);
}
}
/*:: declare var encrypt_agile:any; */
function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:any*/ {
var o = dup(opts||{});
var o = opts||{};
var z = write_zip(wb, o);
return write_zip_denouement(z, o);
}
function write_zip_typeXLSX(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:any*/ {
var o = dup(opts||{});
var z = write_zip_xlsx(wb, o);
return write_zip_denouement(z, o);
}
function write_zip_denouement(z/*:any*/, o/*:?WriteOpts*/)/*:any*/ {
var oopts = {};
var ftype = has_buf ? "nodebuffer" : (typeof Uint8Array !== "undefined" ? "array" : "string");
if(o.compression) oopts.compression = 'DEFLATE';
if(o.password) oopts.type = ftype;
if(o.password) oopts.type = has_buf ? "nodebuffer" : "string";
else switch(o.type) {
case "base64": oopts.type = "base64"; break;
case "binary": oopts.type = "string"; break;
case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files");
case "buffer":
case "file": oopts.type = ftype; break;
case "file": oopts.type = has_buf ? "nodebuffer" : "string"; break;
default: throw new Error("Unrecognized type " + o.type);
}
var out = z.FullPaths ? CFB.write(z, {fileType:"zip", type: /*::(*/{"nodebuffer": "buffer", "string": "binary"}/*:: :any)*/[oopts.type] || oopts.type, compression: !!o.compression}) : z.generate(oopts);
if(typeof Deno !== "undefined") {
if(typeof out == "string") {
if(o.type == "binary" || o.type == "base64") return out;
out = new Uint8Array(s2ab(out));
}
}
var out = z.FullPaths ? CFB.write(z, {fileType:"zip", type: /*::(*/{"nodebuffer": "buffer", "string": "binary"}/*:: :any)*/[oopts.type] || oopts.type}) : z.generate(oopts);
/*jshint -W083 */
if(o.password && typeof encrypt_agile !== 'undefined') return write_cfb_ctr(encrypt_agile(out, o.password), o); // eslint-disable-line no-undef
/*jshint +W083 */
@ -66,13 +42,12 @@ function write_string_type(out/*:string*/, opts/*:WriteOpts*/, bom/*:?string*/)/
if(!bom) bom = "";
var o = bom + out;
switch(opts.type) {
case "base64": return Base64_encode(utf8write(o));
case "base64": return Base64.encode(utf8write(o));
case "binary": return utf8write(o);
case "string": return out;
case "file": return write_dl(opts.file, o, 'utf8');
case "buffer": {
if(has_buf) return Buffer_from(o, 'utf8');
else if(typeof TextEncoder !== "undefined") return new TextEncoder().encode(o);
else return write_string_type(o, {type:'binary'}).split("").map(function(c) { return c.charCodeAt(0); });
}
}
@ -81,7 +56,7 @@ function write_string_type(out/*:string*/, opts/*:WriteOpts*/, bom/*:?string*/)/
function write_stxt_type(out/*:string*/, opts/*:WriteOpts*/)/*:any*/ {
switch(opts.type) {
case "base64": return Base64_encode_pass(out);
case "base64": return Base64.encode(out);
case "binary": return out;
case "string": return out; /* override in sheet_to_txt */
case "file": return write_dl(opts.file, out, 'binary');
@ -102,51 +77,34 @@ function write_binary_type(out, opts/*:WriteOpts*/)/*:any*/ {
var bstr = "";
// $FlowIgnore
for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]);
return opts.type == 'base64' ? Base64_encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr;
return opts.type == 'base64' ? Base64.encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr;
case "file": return write_dl(opts.file, out);
case "buffer": return out;
default: throw new Error("Unrecognized type " + opts.type);
}
}
function writeSyncXLSX(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
reset_cp();
check_wb(wb);
var o = dup(opts||{});
if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; }
if(o.type == "array") { o.type = "binary"; var out/*:string*/ = (writeSyncXLSX(wb, o)/*:any*/); o.type = "array"; return s2ab(out); }
return write_zip_typeXLSX(wb, o);
}
function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
reset_cp();
check_wb(wb);
var o = dup(opts||{});
var o = opts||{};
if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; }
if(o.type == "array") { o.type = "binary"; var out/*:string*/ = (writeSync(wb, o)/*:any*/); o.type = "array"; return s2ab(out); }
var idx = 0;
if(o.sheet) {
if(typeof o.sheet == "number") idx = o.sheet;
else idx = wb.SheetNames.indexOf(o.sheet);
if(!wb.SheetNames[idx]) throw new Error("Sheet not found: " + o.sheet + " : " + (typeof o.sheet));
}
switch(o.bookType || 'xlsb') {
case 'xml':
case 'xlml': return write_string_type(write_xlml(wb, o), o);
case 'slk':
case 'sylk': return write_string_type(SYLK.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb), o);
case 'sylk': return write_string_type(write_slk_str(wb, o), o);
case 'htm':
case 'html': return write_string_type(sheet_to_html(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'txt': return write_stxt_type(sheet_to_txt(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'csv': return write_string_type(sheet_to_csv(wb.Sheets[wb.SheetNames[idx]], o), o, "\ufeff");
case 'dif': return write_string_type(DIF.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'dbf': return write_binary_type(DBF.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'prn': return write_string_type(PRN.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'rtf': return write_string_type(sheet_to_rtf(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'eth': return write_string_type(ETH.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'html': return write_string_type(write_htm_str(wb, o), o);
case 'txt': return write_stxt_type(write_txt_str(wb, o), o);
case 'csv': return write_string_type(write_csv_str(wb, o), o, "\ufeff");
case 'dif': return write_string_type(write_dif_str(wb, o), o);
case 'dbf': return write_binary_type(write_dbf_buf(wb, o), o);
case 'prn': return write_string_type(write_prn_str(wb, o), o);
case 'rtf': return write_string_type(write_rtf_str(wb, o), o);
case 'eth': return write_string_type(write_eth_str(wb, o), o);
case 'fods': return write_string_type(write_ods(wb, o), o);
case 'wk1': return write_binary_type(WK_.sheet_to_wk1(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'wk3': return write_binary_type(WK_.book_to_wk3(wb, o), o);
case 'biff2': if(!o.biff) o.biff = 2; /* falls through */
case 'biff3': if(!o.biff) o.biff = 3; /* falls through */
case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o);
@ -158,7 +116,6 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
case 'xlsm':
case 'xlam':
case 'xlsb':
case 'numbers':
case 'ods': return write_zip_type(wb, o);
default: throw new Error ("Unrecognized bookType |" + o.bookType + "|");
}
@ -185,14 +142,6 @@ function writeFileSync(wb/*:Workbook*/, filename/*:string*/, opts/*:?WriteFileOp
return writeSync(wb, o);
}
function writeFileSyncXLSX(wb/*:Workbook*/, filename/*:string*/, opts/*:?WriteFileOpts*/) {
var o = opts||{}; o.type = 'file';
o.file = filename;
resolve_book_type(o);
return writeSyncXLSX(wb, o);
}
function writeFileAsync(filename/*:string*/, wb/*:Workbook*/, opts/*:?WriteFileOpts*/, cb/*:?(e?:ErrnoError)=>void*/) {
var o = opts||{}; o.type = 'file';
o.file = filename;

@ -4,18 +4,18 @@ type MJRObject = {
isempty: boolean;
};
*/
function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, header/*:number*/, hdr/*:Array<any>*/, o/*:Sheet2JSONOpts*/)/*:MJRObject*/ {
function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, header/*:number*/, hdr/*:Array<any>*/, dense/*:boolean*/, o/*:Sheet2JSONOpts*/)/*:MJRObject*/ {
var rr = encode_row(R);
var defval = o.defval, raw = o.raw || !Object.prototype.hasOwnProperty.call(o, "raw");
var isempty = true, dense = (sheet["!data"] != null);
var isempty = true;
var row/*:any*/ = (header === 1) ? [] : {};
if(header !== 1) {
if(Object.defineProperty) try { Object.defineProperty(row, '__rowNum__', {value:R, enumerable:false}); } catch(e) { row.__rowNum__ = R; }
else row.__rowNum__ = R;
}
if(!dense || sheet["!data"][R]) for (var C = r.s.c; C <= r.e.c; ++C) {
var val = dense ? (sheet["!data"][R]||[])[C] : sheet[cols[C] + rr];
if(val == null || val.t === undefined) {
if(!dense || sheet[R]) for (var C = r.s.c; C <= r.e.c; ++C) {
var val = dense ? sheet[R][C] : sheet[cols[C] + rr];
if(val === undefined || val.t === undefined) {
if(defval === undefined) continue;
if(hdr[C] != null) { row[hdr[C]] = defval; }
continue;
@ -23,23 +23,17 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
var v = val.v;
switch(val.t){
case 'z': if(v == null) break; continue;
case 'e': v = (v == 0 ? null : void 0); break;
case 's': case 'b':
case 'n': if(!val.z || !fmt_is_date(val.z)) break;
v = numdate(v); // TODO: date1904 setting should also be stored in worksheet object
if(typeof v == "number") break;
/* falls through */
case 'd': if(!(o && (o.UTC||(o.raw === false)))) v = utc_to_local(new Date(v)); break;
case 'e': v = void 0; break;
case 's': case 'd': case 'b': case 'n': break;
default: throw new Error('unrecognized type ' + val.t);
}
if(hdr[C] != null) {
if(v == null) {
if(val.t == "e" && v === null) row[hdr[C]] = null;
else if(defval !== undefined) row[hdr[C]] = defval;
if(defval !== undefined) row[hdr[C]] = defval;
else if(raw && v === null) row[hdr[C]] = null;
else continue;
} else {
row[hdr[C]] = (val.t === 'n' && typeof o.rawNumbers === 'boolean' ? o.rawNumbers : raw) ? v : format_cell(val, v, o);
row[hdr[C]] = raw || (o.rawNumbers && val.t == "n") ? v : format_cell(val,v,o);
}
if(v != null) isempty = false;
}
@ -68,16 +62,12 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) {
var cols/*:Array<string>*/ = [];
var out/*:Array<any>*/ = [];
var outi = 0, counter = 0;
var dense = sheet["!data"] != null;
var R = r.s.r, C = 0;
var header_cnt = {};
if(dense && !sheet["!data"][R]) sheet["!data"][R] = [];
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
var rowinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!rows"] || [];
var dense = Array.isArray(sheet);
var R = r.s.r, C = 0, CC = 0;
if(dense && !sheet[R]) sheet[R] = [];
for(C = r.s.c; C <= r.e.c; ++C) {
if(((colinfo[C]||{}).hidden)) continue;
cols[C] = encode_col(C);
val = dense ? sheet["!data"][R][C] : sheet[cols[C] + rr];
val = dense ? sheet[R][C] : sheet[cols[C] + rr];
switch(header) {
case 1: hdr[C] = C - r.s.c; break;
case 2: hdr[C] = cols[C]; break;
@ -85,18 +75,13 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) {
default:
if(val == null) val = {w: "__EMPTY", t: "s"};
vv = v = format_cell(val, null, o);
counter = header_cnt[v] || 0;
if(!counter) header_cnt[v] = 1;
else {
do { vv = v + "_" + (counter++); } while(header_cnt[vv]); header_cnt[v] = counter;
header_cnt[vv] = 1;
}
counter = 0;
for(CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter);
hdr[C] = vv;
}
}
for (R = r.s.r + offset; R <= r.e.r; ++R) {
if ((rowinfo[R]||{}).hidden) continue;
var row = make_json_row(sheet, r, R, cols, header, hdr, o);
var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o);
if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) out[outi++] = row.row;
}
out.length = outi;
@ -104,20 +89,18 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) {
}
var qreg = /"/g;
function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, fs/*:number*/, rs/*:number*/, FS/*:string*/, w/*:number*/, o/*:Sheet2CSVOpts*/)/*:?string*/ {
function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, fs/*:number*/, rs/*:number*/, FS/*:string*/, o/*:Sheet2CSVOpts*/)/*:?string*/ {
var isempty = true;
var row/*:Array<string>*/ = [], txt = "", rr = encode_row(R);
var dense = sheet["!data"] != null;
var datarow = dense && sheet["!data"][R] || [];
for(var C = r.s.c; C <= r.e.c; ++C) {
if (!cols[C]) continue;
var val = dense ? datarow[C]: sheet[cols[C] + rr];
var val = o.dense ? (sheet[R]||[])[C]: sheet[cols[C] + rr];
if(val == null) txt = "";
else if(val.v != null) {
isempty = false;
txt = ''+(o.rawNumbers && val.t == "n" ? val.v : format_cell(val, null, o));
for(var i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34 || o.forceQuotes) {txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
if(txt == "ID" && w == 0 && row.length == 0) txt = '"ID"';
if(txt == "ID") txt = '"ID"';
} else if(val.f != null && !val.F) {
isempty = false;
txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"';
@ -125,7 +108,6 @@ function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Arr
/* NOTE: Excel CSV does not support array formulae */
row.push(txt);
}
if(o.strip) while(row[row.length - 1] === "") --row.length;
if(o.blankrows === false && isempty) return null;
return row.join(FS);
}
@ -137,40 +119,43 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ {
var r = safe_decode_range(sheet["!ref"]);
var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
var row = "", cols/*:Array<string>*/ = [];
o.dense = Array.isArray(sheet);
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
var rowinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!rows"] || [];
for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
var w = 0;
for(var R = r.s.r; R <= r.e.r; ++R) {
if ((rowinfo[R]||{}).hidden) continue;
row = make_csv_row(sheet, r, R, cols, fs, rs, FS, w, o);
row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o);
if(row == null) { continue; }
if(row || (o.blankrows !== false)) out.push((w++ ? RS : "") + row);
if(o.strip) row = row.replace(endregex,"");
out.push(row + RS);
}
delete o.dense;
return out.join("");
}
function sheet_to_txt(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n";
var s = sheet_to_csv(sheet, opts);
if(typeof $cptable == 'undefined' || opts.type == 'string') return s;
var o = $cptable.utils.encode(1200, s, 'str');
if(typeof cptable == 'undefined' || opts.type == 'string') return s;
var o = cptable.utils.encode(1200, s, 'str');
return String.fromCharCode(255) + String.fromCharCode(254) + o;
}
function sheet_to_formulae(sheet/*:Worksheet*/, opts/*:?Sheet2FormulaOpts*/)/*:Array<string>*/ {
function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
var y = "", x, val="";
if(sheet == null || sheet["!ref"] == null) return [];
var r = safe_decode_range(sheet['!ref']), rr = "", cols/*:Array<string>*/ = [], C;
var cmds/*:Array<string>*/ = [];
var dense = sheet["!data"] != null;
var dense = Array.isArray(sheet);
for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C);
for(var R = r.s.r; R <= r.e.r; ++R) {
rr = encode_row(R);
for(C = r.s.c; C <= r.e.c; ++C) {
y = cols[C] + rr;
x = dense ? (sheet["!data"][R]||[])[C] : sheet[y];
x = dense ? (sheet[R]||[])[C] : sheet[y];
val = "";
if(x === undefined) continue;
else if(x.F != null) {
@ -180,7 +165,6 @@ function sheet_to_formulae(sheet/*:Worksheet*/, opts/*:?Sheet2FormulaOpts*/)/*:A
if(y.indexOf(":") == -1) y = y + ":" + y;
}
if(x.f != null) val = x.f;
else if(opts && opts.values === false) continue;
else if(x.t == 'z') continue;
else if(x.t == 'n' && x.v != null) val = "" + x.v;
else if(x.t == 'b') val = x.v ? "TRUE" : "FALSE";
@ -196,11 +180,8 @@ function sheet_to_formulae(sheet/*:Worksheet*/, opts/*:?Sheet2FormulaOpts*/)/*:A
function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet*/ {
var o = opts || {};
var dense = _ws ? (_ws["!data"] != null) : o.dense;
if(DENSE != null && dense == null) dense = DENSE;
var offset = +!o.skipHeader;
var ws/*:Worksheet*/ = _ws || ({});
if(!_ws && dense) ws["!data"] = [];
var ws/*:Worksheet*/ = _ws || ({}/*:any*/);
var _R = 0, _C = 0;
if(ws && o.origin != null) {
if(typeof o.origin == 'number') _R = o.origin;
@ -209,6 +190,7 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
_R = _origin.r; _C = _origin.c;
}
}
var cell/*:Cell*/;
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}}/*:any*/);
if(ws['!ref']) {
var _range = safe_decode_range(ws['!ref']);
@ -219,35 +201,28 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
if(_R == -1) { _R = 0; range.e.r = js.length - 1 + offset; }
}
var hdr/*:Array<string>*/ = o.header || [], C = 0;
var ROW = [];
js.forEach(function (JS, R/*:number*/) {
if(dense && !ws["!data"][_R + R + offset]) ws["!data"][_R + R + offset] = [];
if(dense) ROW = ws["!data"][_R + R + offset];
keys(JS).forEach(function(k) {
if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k;
var v = JS[k];
var t = 'z';
var z = "";
var ref = dense ? "" : (encode_col(_C + C) + encode_row(_R + R + offset));
var cell/*:Cell*/ = dense ? ROW[_C + C] : ws[ref];
var ref = encode_cell({c:_C + C,r:_R + R + offset});
cell = utils.sheet_get_cell(ws, ref);
if(v && typeof v === 'object' && !(v instanceof Date)){
if(dense) ROW[_C + C] = v;
else ws[ref] = v;
ws[ref] = v;
} else {
if(typeof v == 'number') t = 'n';
else if(typeof v == 'boolean') t = 'b';
else if(typeof v == 'string') t = 's';
else if(v instanceof Date) {
t = 'd';
if(!o.UTC) v = local_to_utc(v);
if(!o.cellDates) { t = 'n'; v = datenum(v); }
z = (cell != null && cell.z && fmt_is_date(cell.z)) ? cell.z : (o.dateNF || table_fmt[14]);
z = (o.dateNF || SSF._table[14]);
}
else if(v === null && o.nullError) { t = 'e'; v = 0; }
if(!cell) {
if(!dense) ws[ref] = cell = ({t:t, v:v}/*:any*/);
else ROW[_C + C] = cell = ({t:t, v:v}/*:any*/);
} else {
if(!cell) ws[ref] = cell = ({t:t, v:v}/*:any*/);
else {
cell.t = t; cell.v = v;
delete cell.w; delete cell.R;
if(z) cell.z = z;
@ -258,132 +233,39 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
});
range.e.c = Math.max(range.e.c, _C + hdr.length - 1);
var __R = encode_row(_R);
if(dense && !ws["!data"][_R]) ws["!data"][_R] = [];
if(offset) for(C = 0; C < hdr.length; ++C) {
if(dense) ws["!data"][_R][C + _C] = {t:'s', v:hdr[C]};
else ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]};
}
if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]};
ws['!ref'] = encode_range(range);
return ws;
}
function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ { return sheet_add_json(null, js, opts); }
/* get cell, creating a stub if necessary */
function ws_get_cell_stub(ws/*:Worksheet*/, R, C/*:?number*/)/*:Cell*/ {
/* A1 cell address */
if(typeof R == "string") {
if(ws["!data"] != null) {
var RC = decode_cell(R);
if(!ws["!data"][RC.r]) ws["!data"][RC.r] = [];
return ws["!data"][RC.r][RC.c] || (ws["!data"][RC.r][RC.c] = {t:'z'});
}
return ws[R] || (ws[R] = {t:'z'});
}
/* cell address object */
if(typeof R != "number") return ws_get_cell_stub(ws, encode_cell(R));
/* R and C are 0-based indices */
return ws_get_cell_stub(ws, encode_col(C||0) + encode_row(R));
}
/* find sheet index for given name / validate index */
function wb_sheet_idx(wb/*:Workbook*/, sh/*:number|string*/) {
if(typeof sh == "number") {
if(sh >= 0 && wb.SheetNames.length > sh) return sh;
throw new Error("Cannot find sheet # " + sh);
} else if(typeof sh == "string") {
var idx = wb.SheetNames.indexOf(sh);
if(idx > -1) return idx;
throw new Error("Cannot find sheet name |" + sh + "|");
} else throw new Error("Cannot find sheet |" + sh + "|");
}
/* simple blank or single-sheet workbook object */
function book_new(ws/*:?Worksheet*/, wsname/*:?string*/)/*:Workbook*/ {
var wb = { SheetNames: [], Sheets: {} };
if(ws) book_append_sheet(wb, ws, wsname || "Sheet1");
return wb;
}
/* add a worksheet to the end of a given workbook */
function book_append_sheet(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/, roll/*:?boolean*/)/*:string*/ {
var i = 1;
if(!name) for(; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break;
if(!name || wb.SheetNames.length >= 0xFFFF) throw new Error("Too many worksheets");
if(roll && wb.SheetNames.indexOf(name) >= 0 && name.length < 32) {
var m = name.match(/\d+$/); // at this point, name length is capped at 32
i = m && +m[0] || 0;
var root = m && name.slice(0, m.index) || name;
for(++i; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf(name = root + i) == -1) break;
}
check_ws_name(name);
if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!");
wb.SheetNames.push(name);
wb.Sheets[name] = ws;
return name;
}
/* set sheet visibility (visible/hidden/very hidden) */
function book_set_sheet_visibility(wb/*:Workbook*/, sh/*:number|string*/, vis/*:number*/) {
if(!wb.Workbook) wb.Workbook = {};
if(!wb.Workbook.Sheets) wb.Workbook.Sheets = [];
var idx = wb_sheet_idx(wb, sh);
// $FlowIgnore
if(!wb.Workbook.Sheets[idx]) wb.Workbook.Sheets[idx] = {};
switch(vis) {
case 0: case 1: case 2: break;
default: throw new Error("Bad sheet visibility setting " + vis);
}
// $FlowIgnore
wb.Workbook.Sheets[idx].Hidden = vis;
}
/* set number format */
function cell_set_number_format(cell/*:Cell*/, fmt/*:string|number*/) {
cell.z = fmt;
return cell;
}
/* set cell hyperlink */
function cell_set_hyperlink(cell/*:Cell*/, target/*:string*/, tooltip/*:?string*/) {
if(!target) {
delete cell.l;
} else {
cell.l = ({ Target: target }/*:Hyperlink*/);
if(tooltip) cell.l.Tooltip = tooltip;
}
return cell;
}
function cell_set_internal_link(cell/*:Cell*/, range/*:string*/, tooltip/*:?string*/) { return cell_set_hyperlink(cell, "#" + range, tooltip); }
/* add to cell comments */
function cell_add_comment(cell/*:Cell*/, text/*:string*/, author/*:?string*/) {
if(!cell.c) cell.c = [];
cell.c.push({t:text, a:author||"SheetJS"});
}
/* set array formula and flush related cells */
function sheet_set_array_formula(ws/*:Worksheet*/, range, formula/*:string*/, dynamic/*:boolean*/) {
var rng = typeof range != "string" ? range : safe_decode_range(range);
var rngstr = typeof range == "string" ? range : encode_range(range);
for(var R = rng.s.r; R <= rng.e.r; ++R) for(var C = rng.s.c; C <= rng.e.c; ++C) {
var cell = ws_get_cell_stub(ws, R, C);
cell.t = 'n';
cell.F = rngstr;
delete cell.v;
if(R == rng.s.r && C == rng.s.c) {
cell.f = formula;
if(dynamic) cell.D = true;
}
}
var wsr = decode_range(ws["!ref"]);
if(wsr.s.r > rng.s.r) wsr.s.r = rng.s.r;
if(wsr.s.c > rng.s.c) wsr.s.c = rng.s.c;
if(wsr.e.r < rng.e.r) wsr.e.r = rng.e.r;
if(wsr.e.c < rng.e.c) wsr.e.c = rng.e.c;
ws["!ref"] = encode_range(wsr);
return ws;
}
var utils/*:any*/ = {
encode_col: encode_col,
encode_row: encode_row,
encode_cell: encode_cell,
encode_range: encode_range,
decode_col: decode_col,
decode_row: decode_row,
split_cell: split_cell,
decode_cell: decode_cell,
decode_range: decode_range,
format_cell: format_cell,
get_formulae: sheet_to_formulae,
make_csv: sheet_to_csv,
make_json: sheet_to_json,
make_formulae: sheet_to_formulae,
sheet_add_aoa: sheet_add_aoa,
sheet_add_json: sheet_add_json,
sheet_add_dom: sheet_add_dom,
aoa_to_sheet: aoa_to_sheet,
json_to_sheet: json_to_sheet,
table_to_sheet: parse_dom_table,
table_to_book: table_to_book,
sheet_to_csv: sheet_to_csv,
sheet_to_txt: sheet_to_txt,
sheet_to_json: sheet_to_json,
sheet_to_html: HTML_.from_sheet,
sheet_to_formulae: sheet_to_formulae,
sheet_to_row_object_array: sheet_to_json
};

@ -1,41 +1,116 @@
var utils/*:any*/ = {
encode_col: encode_col,
encode_row: encode_row,
encode_cell: encode_cell,
encode_range: encode_range,
decode_col: decode_col,
decode_row: decode_row,
split_cell: split_cell,
decode_cell: decode_cell,
decode_range: decode_range,
format_cell: format_cell,
sheet_new: sheet_new,
sheet_add_aoa: sheet_add_aoa,
sheet_add_json: sheet_add_json,
sheet_add_dom: sheet_add_dom,
aoa_to_sheet: aoa_to_sheet,
json_to_sheet: json_to_sheet,
table_to_sheet: parse_dom_table,
table_to_book: table_to_book,
sheet_to_csv: sheet_to_csv,
sheet_to_txt: sheet_to_txt,
sheet_to_json: sheet_to_json,
sheet_to_html: sheet_to_html,
sheet_to_formulae: sheet_to_formulae,
sheet_to_row_object_array: sheet_to_json,
sheet_get_cell: ws_get_cell_stub,
book_new: book_new,
book_append_sheet: book_append_sheet,
book_set_sheet_visibility: book_set_sheet_visibility,
cell_set_number_format: cell_set_number_format,
cell_set_hyperlink: cell_set_hyperlink,
cell_set_internal_link: cell_set_internal_link,
cell_add_comment: cell_add_comment,
sheet_set_array_formula: sheet_set_array_formula,
consts: {
SHEET_VISIBLE: 0,
SHEET_HIDDEN: 1,
SHEET_VERY_HIDDEN: 2
(function(utils) {
utils.consts = utils.consts || {};
function add_consts(R/*Array<any>*/) { R.forEach(function(a){ utils.consts[a[0]] = a[1]; }); }
function get_default(x/*:any*/, y/*:any*/, z/*:any*/)/*:any*/ { return x[y] != null ? x[y] : (x[y] = z); }
/* get cell, creating a stub if necessary */
function ws_get_cell_stub(ws/*:Worksheet*/, R, C/*:?number*/)/*:Cell*/ {
/* A1 cell address */
if(typeof R == "string") {
/* dense */
if(Array.isArray(ws)) {
var RC = decode_cell(R);
if(!ws[RC.r]) ws[RC.r] = [];
return ws[RC.r][RC.c] || (ws[RC.r][RC.c] = {t:'z'});
}
return ws[R] || (ws[R] = {t:'z'});
}
/* cell address object */
if(typeof R != "number") return ws_get_cell_stub(ws, encode_cell(R));
/* R and C are 0-based indices */
return ws_get_cell_stub(ws, encode_cell({r:R,c:C||0}));
}
utils.sheet_get_cell = ws_get_cell_stub;
/* find sheet index for given name / validate index */
function wb_sheet_idx(wb/*:Workbook*/, sh/*:number|string*/) {
if(typeof sh == "number") {
if(sh >= 0 && wb.SheetNames.length > sh) return sh;
throw new Error("Cannot find sheet # " + sh);
} else if(typeof sh == "string") {
var idx = wb.SheetNames.indexOf(sh);
if(idx > -1) return idx;
throw new Error("Cannot find sheet name |" + sh + "|");
} else throw new Error("Cannot find sheet |" + sh + "|");
}
/* simple blank workbook object */
utils.book_new = function()/*:Workbook*/ {
return { SheetNames: [], Sheets: {} };
};
/* add a worksheet to the end of a given workbook */
utils.book_append_sheet = function(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/) {
if(!name) for(var i = 1; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break;
if(!name || wb.SheetNames.length >= 0xFFFF) throw new Error("Too many worksheets");
check_ws_name(name);
if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!");
wb.SheetNames.push(name);
wb.Sheets[name] = ws;
};
/* set sheet visibility (visible/hidden/very hidden) */
utils.book_set_sheet_visibility = function(wb/*:Workbook*/, sh/*:number|string*/, vis/*:number*/) {
get_default(wb,"Workbook",{});
get_default(wb.Workbook,"Sheets",[]);
var idx = wb_sheet_idx(wb, sh);
// $FlowIgnore
get_default(wb.Workbook.Sheets,idx, {});
switch(vis) {
case 0: case 1: case 2: break;
default: throw new Error("Bad sheet visibility setting " + vis);
}
// $FlowIgnore
wb.Workbook.Sheets[idx].Hidden = vis;
};
add_consts([
["SHEET_VISIBLE", 0],
["SHEET_HIDDEN", 1],
["SHEET_VERY_HIDDEN", 2]
]);
/* set number format */
utils.cell_set_number_format = function(cell/*:Cell*/, fmt/*:string|number*/) {
cell.z = fmt;
return cell;
};
/* set cell hyperlink */
utils.cell_set_hyperlink = function(cell/*:Cell*/, target/*:string*/, tooltip/*:?string*/) {
if(!target) {
delete cell.l;
} else {
cell.l = ({ Target: target }/*:Hyperlink*/);
if(tooltip) cell.l.Tooltip = tooltip;
}
return cell;
};
utils.cell_set_internal_link = function(cell/*:Cell*/, range/*:string*/, tooltip/*:?string*/) { return utils.cell_set_hyperlink(cell, "#" + range, tooltip); };
/* add to cell comments */
utils.cell_add_comment = function(cell/*:Cell*/, text/*:string*/, author/*:?string*/) {
if(!cell.c) cell.c = [];
cell.c.push({t:text, a:author||"SheetJS"});
};
/* set array formula and flush related cells */
utils.sheet_set_array_formula = function(ws/*:Worksheet*/, range, formula/*:string*/) {
var rng = typeof range != "string" ? range : safe_decode_range(range);
var rngstr = typeof range == "string" ? range : encode_range(range);
for(var R = rng.s.r; R <= rng.e.r; ++R) for(var C = rng.s.c; C <= rng.e.c; ++C) {
var cell = ws_get_cell_stub(ws, R, C);
cell.t = 'n';
cell.F = rngstr;
delete cell.v;
if(R == rng.s.r && C == rng.s.c) cell.f = formula;
}
return ws;
};
return utils;
})(utils);

Some files were not shown because too many files have changed in this diff Show More