Compare commits

..

No commits in common. "master" and "v0.11.9" have entirely different histories.

682 changed files with 74637 additions and 2577734 deletions

View File

@ -1 +0,0 @@
xlsx.js

View File

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

View File

@ -2,25 +2,20 @@
"env": { "shared-node-browser":true },
"globals": {},
"parserOptions": {
"ecmaVersion": 3
"ecmaVersion": 3,
},
"plugins": [ "html", "json" ],
"extends": "eslint:recommended",
"!extends": "eslint:recommended",
"rules": {
"comma-style": [ 2, "last" ],
"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, {
"functions":false, "classes":true, "variables":false
}],
"no-useless-escape": 0,
"semi": [ 2, "always" ]
"no-console": 0,
"no-bitwise": 0,
"curly": 0,
"comma-style": [ 2, "last" ],
"no-trailing-spaces": 2,
"semi": [ 2, "always" ],
"comma-dangle": [ 2, "never" ]
}
}

View File

@ -8,15 +8,13 @@
.*/misc/.*
.*/perf/.*
.*/_book/.*
.*/packages/.*
.*/demo/browser.js
.*/shim.js
.*/xlsx.js
.*/xlsx.mini.js
.*/xlsx.mini.flow.js
.*/xlsxworker.js
.*/jszip.js
.*/tests/.*
.*/demos/.*

16
.fossaignore Normal file
View File

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

12
.gitattributes vendored
View File

@ -1,17 +1,5 @@
*.html linguist-documentation
*.md text eol=lf
bits/*.js text eol=lf
test.js text eol=lf
xlsx*.js text eol=lf
*.flow.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

3
.github/FUNDING.yml vendored
View File

@ -1,3 +0,0 @@
github: SheetJSDev
custom: https://sheetjs.com
open_collective: s5s

View File

@ -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'

View File

@ -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

View File

@ -1,92 +0,0 @@
name: 'Tests: node.js'
on: [pull_request, push]
jobs:
matrix:
runs-on: ubuntu-latest
outputs:
latest: ${{ steps.set-matrix.outputs.requireds }}
steps:
- uses: ljharb/actions/node/matrix@main
id: set-matrix
with:
versionsAsRoot: true
type: 'majors'
preset: '>=4'
latest:
needs: [matrix]
name: 'latest majors'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
include:
- node-version: '14.'
env:
TZ: America/New_York
- node-version: '13.'
env:
TZ: Europe/London
- node-version: '12.'
env:
TZ: Asia/Seoul
- node-version: '11.'
env:
TZ: America/Los_Angeles
FMTS: misc
- node-version: '10.'
env:
TZ: Europe/Berlin
FMTS: misc
- node-version: '9.'
env:
TZ: Asia/Kolkata
FMTS: misc
- node-version: '8.'
env:
TZ: Asia/Shanghai
FMTS: misc
- node-version: '7.'
env:
TZ: America/Cancun
FMTS: misc
- node-version: '6.'
env:
TZ: Asia/Seoul
FMTS: misc
- node-version: '5.'
env:
TZ: America/Anchorage
FMTS: misc
- node-version: '4.'
env:
TZ: America/Barbados
FMTS: misc
- node-version: '4.4.7' # see GH issue #1150
env:
TZ: Asia/Tokyo
FMTS: misc
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 }}
- 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+'
needs: [latest]
runs-on: ubuntu-latest
steps:
- run: 'echo tests completed'

View File

@ -1,45 +0,0 @@
name: 'Tests: node.js (io.js)'
on: [pull_request, push]
jobs:
matrix:
runs-on: ubuntu-latest
outputs:
latest: ${{ steps.set-matrix.outputs.requireds }}
steps:
- uses: ljharb/actions/node/matrix@main
id: set-matrix
with:
type: 'majors'
preset: 'iojs'
latest:
needs: [matrix]
name: 'latest majors'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.matrix.outputs.latest) }}
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 }}
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'
needs: [latest]
runs-on: ubuntu-latest
steps:
- run: 'echo tests completed'

View File

@ -1,32 +0,0 @@
name: 'Tests: pretest/posttest'
on: [pull_request, push]
jobs:
pretest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ljharb/actions/node/install@main
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
# posttest:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v2
# - uses: ljharb/actions/node/install@main
# name: 'nvm install lts/* && npm install'
# with:
# node-version: 'lts/*'
# - run: make init
# - run: 'cd test_files; make all; cd -'
# - run: npm run posttest

View File

@ -1,88 +0,0 @@
name: 'Tests: node.js (0.x)'
on: [pull_request, push]
jobs:
matrix:
runs-on: ubuntu-latest
outputs:
stable: ${{ steps.set-matrix.outputs.requireds }}
# unstable: ${{ steps.set-matrix.outputs.optionals }}
steps:
- uses: ljharb/actions/node/matrix@main
id: set-matrix
with:
versionsAsRoot: true
preset: '0.x'
stable:
needs: [matrix]
name: 'stable minors'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: ${{ fromJson(needs.matrix.outputs.stable) }}
include:
- node-version: '0.12.'
env:
TZ: America/Cayman
FMTS: misc
- node-version: '0.10.'
env:
TZ: Pacific/Honolulu
FMTS: misc
- node-version: '0.8.'
env:
TZ: America/Mexico_City
FMTS: misc
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
#- 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
# 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
node:
name: 'node 0.x'
# needs: [stable, unstable]
needs: [stable]
runs-on: ubuntu-latest
steps:
- run: 'echo tests completed'

View File

@ -1,15 +0,0 @@
name: Automatic Rebase
on: [pull_request_target]
jobs:
_:
name: "Automatic Rebase"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ljharb/rebase@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -1,12 +0,0 @@
name: Require “Allow Edits”
on: [pull_request_target]
jobs:
_:
name: "Require “Allow Edits”"
runs-on: ubuntu-latest
steps:
- uses: ljharb/require-allow-edits@main

17
.gitignore vendored
View File

@ -4,35 +4,24 @@ package-lock.json
_book/
misc/coverage.html
misc/prof.js
misc/*.[sS][vV][gG]
v8.log
tmp
*.[tT][xX][tT]
*.[cC][sS][vV]
*.[dD][iIbB][fF]
*.[pP][rR][nN]
*.[pP][mM][dD]*
*.[pP][dD][fF]
*.[sS][lL][kK]
*.[sS][yY][lL][kK]
*.socialcalc
*.[xX][lL][sSwWcCaAtTmMrR]
*.[xX][lL][sSaAtT][xXmMbB]
*.[xX][lL][sSwWcC]
*.[xX][lL][sS][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

1
.gitmodules vendored
View File

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

View File

@ -1,43 +1,29 @@
test_files/
modules/
packages/
.github/
tests/files/
demos/
index.html
misc/
node_modules
*.tgz
*.jsx
_book
book.json
v8.log
tmp
*.[tT][xX][tT]
*.[cC][sS][vV]
*.[dD][iIbB][fF]
*.[pP][rR][nN]
*.[pP][mM][dD]*
*.[pP][dD][fF]
*.[sS][lL][kK]
*.[sS][yY][lL][kK]
*.socialcalc
*.[xX][lL][sSwWcCaAtTmMrR]
*.[xX][lL][sSaAtT][xXmMbB]
*.[xX][lL][sSwWcC]
*.[xX][lL][sS][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
@ -48,11 +34,8 @@ tmp
.gitattributes
.fossaignore
.spelling
.eslintignore
.eslintrc
.eslintmjs
.jshintrc
xlsx.mini.js
CONTRIBUTING.md
Makefile
make.cmd
@ -61,11 +44,6 @@ make.cmd
xlsworker.js
shim.js
test.js
test.mjs
test.ts
test.mts
testnocp.ts
testbun.mjs
.jscs.json
.gitmodules
.travis.yml

View File

@ -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,135 +34,67 @@ tooltips
Browserify
CDNjs
CommonJS
Deno
Ethercalc
ExtendScript
InDesign
IndexedDB
FileSaver
JavaScriptCore
LocalStorage
NestJS
NPM
Nuxt
PhantomJS
Photoshop
Redis
Nuxt.js
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
Base64
Booleans
FileReader
JS
NoSQL
README
UTF-8
UTF-16
VBScript
XHR
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
commonjs
async
uncheck
vendoring
- demos/altjs/README.md
ChakraCore
Duktape
Goja
Nashorn
QuickJS
- demos/angular/README.md
AngularJS
angular-ui-grid
ui-grid
- demos/angular2/README.md
NativeScript
angular-cli
- demos/array/README.md
WebGL
WebAssembly
dataset
TensorFlow
- demos/database/README.md
Knex
LowDB
MariaDB
MongoDB
MySQL
PostgreSQL
schemaless
schemas
storages
- demos/extendscript/README.md
Photoshop
InDesign
minifier
- demos/function/README.md
microservice
- demos/headless/README.md
PhantomJS
SlimerJS
@ -180,9 +110,6 @@ Preact
- demos/server/README.md
hapi
- demos/showcase/README.md
vscode-data-preview
- demos/xhr/README.md
axios
superagent

View File

@ -1,40 +1,32 @@
language: node_js
dist: xenial
node_js:
- "14"
- "13"
- "12"
- "11"
- "10"
- "9"
- "8"
- "7"
- "6"
matrix:
include:
- node_js: "14"
env: TZ="America/New_York"
- node_js: "13"
env: TZ="Europe/London"
- node_js: "12"
env: TZ="Asia/Seoul"
- node_js: "11"
env: TZ="America/Los_Angeles" FMTS=misc
- node_js: "10"
env: TZ="Europe/Berlin" FMTS=misc
- node_js: "9"
env: TZ="Asia/Kolkata" FMTS=misc
- node_js: "6"
env: TZ="America/New_York" FMTS=misc
- node_js: "8"
env: TZ="Asia/Shanghai" FMTS=misc
env: TZ="America/Los_Angeles"
- node_js: "8"
env: TZ="Europe/London" FMTS=misc
- node_js: "6"
env: TZ="Europe/Berlin"
- node_js: "6"
env: TZ="Asia/Kolkata" FMTS=misc
- node_js: "9"
env: TZ="Asia/Shanghai"
- node_js: "8"
env: TZ="Asia/Seoul" FMTS=misc
- node_js: "7"
env: TZ="America/Cancun" FMTS=misc
- node_js: "6"
env: TZ="Asia/Seoul" FMTS=misc
- node_js: "5"
env: TZ="America/Anchorage" FMTS=misc
- node_js: "4"
env: TZ="America/Barbados" FMTS=misc
# see GH issue #1150
- node_js: "4.4.7"
env: TZ="Asia/Tokyo" FMTS=misc
- node_js: "0.12"
env: TZ="America/Cayman" FMTS=misc
- node_js: "0.10"
@ -43,11 +35,10 @@ matrix:
env: TZ="America/Mexico_City" FMTS=misc
before_install:
- "npm config set strict-ssl false"
- "./misc/node_version.sh"
- "npm install -g npm@4.3.0"
- "npm install -g mocha@2.x voc"
- "npm install blanket"
- "npm install word"
- "npm install xlsjs"
- "npm install coveralls mocha-lcov-reporter"
# note: jsdom 11.x expects node >= 6 but is missing engines.node
- "npm install jsdom@11.x"

View File

@ -4,275 +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.
## 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)
## v0.16.1
* skip empty custom property tags if data is absent (fixes DocSecurity issue)
* HTML output add raw value, type, number format
* DOM parse look for `v` / `t` / `z` attributes when determining value
* double quotes in properties escaped using `_x0022_`
* changed AMD structure for NetSuite and other RequireJS implementations
- `encode_cell` and `decode_cell` do not rely on `encode_col` / `decode_col`
## v0.16.0
* Date handling changed
* XLML certain tag tests are now case insensitive
* Fixed potentially vulnerable regular expressions
## v0.15.6
* CFB prevent infinite loop
* ODS empty cells marked as stub (type "z")
* `cellStyles` option implies `sheetStubs`
## v0.15.5
* `sheets` parse option to specify which sheets to parse
## v0.15.4
* AOA utilities properly preserve number formats
* Number formats captured in stub cells
## v0.15.3
* Properties and Custom Properties properly XML-encoded
## v0.15.2
- `sheet_get_cell` utility function
- `sheet_to_json` explicitly support `null` as alias for default behavior
- `encode_col` throw on negative column index
- HTML properly handle whitespace around tags in a run
- HTML use `id` option on write
- Files starting with `0x09` followed by a display character are now TSV files
- XLS parse references col/row indices mod by the correct number for BIFF ver
- XLSX comments moved to avoid overlapping cell
- XLSB outline level
- AutoFilter update `_FilterDatabase` defined name on write
- XLML skip CDATA blocks
## v0.15.1 (2019-08-14)
* XLSX ignore XML artifacts
* HTML capture and persist merges
## v0.15.0
* `dist/xlsx.mini.min.js` mini build with XLSX read/write and some utilities
* Removed legacy conversion utility functions
## v0.14.5
* XLS PtgNameX lookup
* XLS always create stub cells for blank cells with comments
## v0.14.4
* Better treatment of `skipHidden` in CSV output
* Ignore CLSID in XLS
* SYLK 7-bit character encoding
* SYLK and DBF codepage support
## v0.14.3
* Proper shifting of addresses in Shared Formulae
## v0.14.2
* Proper XML encoding of comments
## v0.14.1
* raw cell objects can be passed to `sheet_add_aoa`
* `_FilterDatabase` fix for AutoFilter-related crashes
* `stream.to_json` doesn't end up accidentally scanning to max row
## 0.14.0 (2018-09-06)
* `sheet_to_json` default flipped to `raw: true`
## 0.13.5 (2018-08-25)
* HTML output generates `<br/>` instead of encoded newline character
## 0.13.2 (2018-07-08)
* Buffer.from shim replaced, will not be defined in node `<=0.12`
## 0.13.0 (2018-06-01)
* Library reshaped to support AMD out of the box
## 0.12.11 (2018-04-27)
* XLS/XLSX/XLSB range truncation (errors in `WTF` mode)
## 0.12.4 (2018-03-04)
* `JSZip` renamed to `JSZipSync`
## 0.12.0 (2018-02-08)
* Extendscript target script in NPM package
## 0.11.19 (2018-02-03)
* Error on empty workbook
## 0.11.16 (2017-12-30)
* XLS ANSI/CP separation
* 'array' write type and ArrayBuffer processing
## 0.11.6 (2017-10-16)
* Semicolon-delimited files are detected

View File

@ -12,9 +12,9 @@ no commercial product should depend on them.
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
@ -28,13 +28,6 @@ shared or included in a test suite (although I will ask :)
If sending email to a gmail account is problematic, the <dev@sheetjs.com> email
inbox is self-hosted.
# Opening Pull Requests
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
Before thinking about contributing, make sure that:
@ -67,4 +60,4 @@ Keep these in mind as you work:
Before contributions are merged, you will receive an email (at the address
associated with the git commit) and will be asked to confirm the aforementioned
items. Ensure that the email addresses associated with the commits are valid.
items. Ensure that the email addresses associated with the commits is valid.

View File

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright (C) 2012-present SheetJS LLC
Copyright (C) 2012-present SheetJS LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

231
Makefile
View File

@ -1,36 +1,26 @@
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
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)
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)
FLOWTGTS=$(TARGET) $(AUXTARGETS) $(AUXSCPTS)
UGLIFYOPTS=--support-ie8 -m
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) ## 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,""))' > $@
@ -38,28 +28,15 @@ $(FLOWTGTS): %.js : %.flow.js
$(FLOWTARGET): $(DEPS)
cat $^ | tr -d '\15\32' > $@
$(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,132 +44,66 @@ 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)"
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)
.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}.min.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
xlsx.exe: bin/xlsx.njs xlsx.js
tail -n+2 $< | sed 's#\.\./#./xlsx#g' > nexe.js
nexe -i nexe.js -o $@
rm nexe.js
.PHONY: pkg
pkg: bin/xlsx.njs xlsx.js ## Build pkg standalone executable
pkg $<
nexe -i $< -o $@ --flags
## Testing
.PHONY: test mocha
test mocha: test.js ## Run test suite
mocha -R spec -t 30000
mocha -R spec -t 20000
#* 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: testbun.mjs ## Run Bun test suite
bun $<
.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,40 +114,77 @@ 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
.PHONY: fullint
fullint: lint mdlint ## Run all checks (removed: old-lint, tslint, flow)
fullint: lint old-lint tslint flow mdlint ## Run all checks
.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
@eslint --ext .js,.njs,.json,.html,.htm $(TARGET) $(AUXTARGETS) $(CMDS) $(HTMLLINT) package.json bower.json
if [ -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
@jshint --show-non-errors $(TARGET) $(AUXTARGETS)
@jshint --show-non-errors $(CMDS)
@jshint --show-non-errors package.json bower.json test.js
@jshint --show-non-errors --extract=always $(HTMLLINT)
@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
#@npm install dtslint typescript
#@npm run-script dtslint
./node_modules/.bin/dtslint types
dtslint types
.PHONY: flow
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 $<
@flow check --all --show-all-errors
.PHONY: cov
cov: misc/coverage.html ## Run coverage test
@ -248,17 +196,32 @@ $(COVFMT): cov_%:
FMTS=$* make cov
misc/coverage.html: $(TARGET) test.js
mocha --require blanket -R html-cov -t 30000 > $@
mocha --require blanket -R html-cov -t 20000 > $@
.PHONY: coveralls
coveralls: ## Coverage Test + Send to coveralls.io
mocha --require blanket --reporter mocha-lcov-reporter -t 30000 | node ./node_modules/coveralls/bin/coveralls.js
mocha --require blanket --reporter mocha-lcov-reporter -t 20000 | 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 $^
./node_modules/.bin/mdspell -a -n -x -r --en-us $^
alex $^
mdspell -a -n -x -r --en-us $^
.PHONY: help
help:

2488
README.md

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,11 @@
#!/usr/bin/env node
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* eslint-env node */
/* vim: set ts=2 ft=javascript: */
var n = "xlsx";
/* vim: set ts=2 ft=javascript: */
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]')
@ -33,18 +19,14 @@ program
.option('-B, --xlsb', 'emit XLSB to <sheetname> or <file>.xlsb')
.option('-M, --xlsm', 'emit XLSM to <sheetname> or <file>.xlsm')
.option('-X, --xlsx', 'emit XLSX to <sheetname> or <file>.xlsx')
.option('-I, --xlam', 'emit XLAM to <sheetname> or <file>.xlam')
.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)')
@ -55,18 +37,12 @@ program
.option('-U, --dbf', 'emit DBF to <sheetname> or <file>.dbf (MSVFP DBF)')
.option('-K, --sylk', 'emit SYLK to <sheetname> or <file>.slk (Excel SYLK)')
.option('-P, --prn', 'emit PRN to <sheetname> or <file>.prn (Lotus PRN)')
.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')
.option('-F, --field-sep <sep>', 'CSV field separator', ",")
.option('-R, --row-sep <sep>', 'CSV row separator', "\n")
.option('-n, --sheet-rows <num>', 'Number of rows to process (0=all rows)')
.option('--codepage <cp>', 'default to specified codepage when ambiguous')
.option('--req <module>', 'require module before processing')
.option('--sst', 'generate shared string table for XLS* formats')
.option('--compress', 'use compression when writing XLSX/M/B and ODS')
.option('--read', 'read but do not generate output')
@ -86,15 +62,11 @@ program.on('--help', function() {
var workbook_formats = [
['xlsx', 'xlsx', 'xlsx'],
['xlsm', 'xlsm', 'xlsm'],
['xlam', 'xlam', 'xlam'],
['xlsb', 'xlsb', 'xlsb'],
['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']
@ -118,10 +90,6 @@ if(!fs.existsSync(filename)) {
process.exit(2);
}
if(program.req) program.req.split(",").forEach(function(r) {
require((fs.existsSync(r) || fs.existsSync(r + '.js')) ? require('path').resolve(r) : r);
});
var opts = {}, wb/*:?Workbook*/;
if(program.listSheets) opts.bookSheets = true;
if(program.sheetRows) opts.sheetRows = program.sheetRows;
@ -131,7 +99,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,13 +123,9 @@ if(program.all) {
opts.cellStyles = true;
opts.sheetStubs = true;
opts.cellDates = true;
wopts.cellFormula = true;
wopts.cellStyles = true;
wopts.sheetStubs = true;
wopts.bookVBA = true;
}
if(program.sparse) opts.dense = false; else opts.dense = true;
if(program.codepage) opts.codepage = +program.codepage;
if(program.dev) {
opts.WTF = true;
@ -182,35 +145,23 @@ if(program.listSheets) {
console.log((wb.SheetNames||[]).join("\n"));
process.exit(0);
}
if(program.dump) {
console.log(JSON.stringify(wb));
process.exit(0);
}
if(program.props) {
if(wb) dump_props(wb);
process.exit(0);
}
/* 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);
X.writeFile(wb, program.output || sheetname || ((filename || "") + "." + m[2]), wopts);
process.exit(0);
} });
wb_formats_2.forEach(function(m) { if(program[m[0]] || isfmt(m[0])) {
wopts.bookType = m[1];
if(wb) X.writeFile(wb, program.output || sheetname || ((filename || "") + "." + m[2]), wopts);
X.writeFile(wb, program.output || sheetname || ((filename || "") + "." + m[2]), wopts);
process.exit(0);
} });
var target_sheet = sheetname || '';
if(target_sheet === '') {
if(+program.sheetIndex < (wb.SheetNames||[]).length) target_sheet = wb.SheetNames[+program.sheetIndex];
if(program.sheetIndex < (wb.SheetNames||[]).length) target_sheet = wb.SheetNames[program.sheetIndex];
else target_sheet = (wb.SheetNames||[""])[0];
}
@ -236,16 +187,13 @@ if(!program.quiet && !program.book) console.error(target_sheet);
['sylk', '.slk'],
['html', '.html'],
['prn', '.prn'],
['eth', '.eth'],
['rtf', '.rtf'],
['txt', '.txt'],
['dbf', '.dbf'],
['wk1', '.wk1'],
['dif', '.dif']
].forEach(function(m) { if(program[m[0]] || isfmt(m[1])) {
wopts.bookType = m[0];
if(program.book) {
/*:: if(wb == null) throw new Error("Unreachable"); */
wb.SheetNames.forEach(function(n, i) {
wopts.sheet = n;
X.writeFile(wb, (program.output || sheetname || filename || "") + m[1] + "." + i, wopts);
@ -257,9 +205,7 @@ if(!program.quiet && !program.book) console.error(target_sheet);
function outit(o, fn) { if(fn) fs.writeFileSync(fn, o); else console.log(o); }
function doit(cb) {
/*:: if(!wb) throw new Error("unreachable"); */
if(program.book) wb.SheetNames.forEach(function(n, i) {
/*:: if(!wb) throw new Error("unreachable"); */
outit(cb(wb.Sheets[n]), (program.output || sheetname || filename) + "." + i);
});
else outit(cb(ws), program.output);
@ -281,30 +227,9 @@ 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}); });
break;
}
function dump_props(wb/*:Workbook*/) {
var propaoa = [];
if(Object.assign && Object.entries) propaoa = Object.entries(Object.assign({}, wb.Props, wb.Custprops));
else {
var Keys/*:: :Array<string> = []*/, pi;
if(wb.Props) {
Keys = Object.keys(wb.Props);
for(pi = 0; pi < Keys.length; ++pi) {
if(Object.prototype.hasOwnProperty.call(Keys, Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
}
}
if(wb.Custprops) {
Keys = Object.keys(wb.Custprops);
for(pi = 0; pi < Keys.length; ++pi) {
if(Object.prototype.hasOwnProperty.call(Keys, Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
}
}
}
console.log(X.utils.sheet_to_csv(X.utils.aoa_to_sheet(propaoa)));
}

View File

@ -1,6 +1,6 @@
/*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* 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 */
var XLSX = {};
function make_xlsx_lib(XLSX){
(function make_xlsx(XLSX){

View File

@ -1 +1 @@
XLSX.version = '0.20.2';
XLSX.version = '0.11.9';

View File

@ -1,81 +1,42 @@
var current_codepage = 1200, current_ansi = 1252;
var current_codepage = 1200;
/*:: declare var cptable:any; */
/*global cptable:true, window */
var $cptable;
/*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
if(typeof cptable === 'undefined') global.cptable = require('./dist/cpexcel.js');
}
function reset_cp() { set_cp(1200); }
var set_cp = function(cp) { current_codepage = cp; };
var VALID_ANSI = [ 874, 932, 936, 949, 950, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 10000 ];
/* 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 */
}/*:any*/);
var set_ansi = function(cp/*:number*/) { if(VALID_ANSI.indexOf(cp) == -1) return; current_ansi = CS2CP[0] = cp; };
function reset_ansi() { set_ansi(1252); }
var set_cp = function(cp/*:number*/) { current_codepage = cp; set_ansi(cp); };
function reset_cp() { set_cp(1200); reset_ansi(); }
function char_codes(data/*:string*/)/*:Array<number>*/ { var o/*:Array<number>*/ = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; }
function char_codes(data) { var o = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; }
function utf16leread(data/*:string*/)/*:string*/ {
var o/*:Array<string>*/ = [];
var o = [];
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>*/ = [];
var o = [];
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i+1) + (data.charCodeAt(2*i)<<8));
return o.join("");
}
var debom = function(data/*:string*/)/*:string*/ {
var c1 = data.charCodeAt(0), c2 = data.charCodeAt(1);
if(c1 == 0xFF && c2 == 0xFE) return utf16leread(data.slice(2));
if(c1 == 0xFE && c2 == 0xFF) return utf16beread(data.slice(2));
if(c1 == 0xFEFF) return data.slice(1);
if(c1 == 0xFF && c2 == 0xFE) return utf16leread(data.substr(2));
if(c1 == 0xFE && c2 == 0xFF) return utf16beread(data.substr(2));
if(c1 == 0xFEFF) return data.substr(1);
return data;
};
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;
set_cp = function(cp/*:number*/) { current_codepage = cp; set_ansi(cp); };
if(typeof cptable !== 'undefined') {
set_cp = function(cp/*:number*/) { current_codepage = 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.substr(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];
};
cpdoit();
}

View File

@ -1,94 +1,41 @@
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, c2, c3, e1, e2, e3, e4;
for(var i = 0; i < input.length; ) {
c1 = input.charCodeAt(i++);
c2 = input.charCodeAt(i++);
c3 = input.charCodeAt(i++);
e1 = c1 >> 2;
e2 = (c1 & 3) << 4 | c2 >> 4;
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, c2, c3;
var e1, e2, e3, e4;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
for(var i = 0; i < input.length;) {
e1 = map.indexOf(input.charAt(i++));
e2 = map.indexOf(input.charAt(i++));
e3 = map.indexOf(input.charAt(i++));
e4 = map.indexOf(input.charAt(i++));
c1 = e1 << 2 | e2 >> 4;
c2 = (e2 & 15) << 4 | e3 >> 2;
c3 = (e3 & 3) << 6 | e4;
o += String.fromCharCode(c1);
if (e3 != 64) { o += String.fromCharCode(c2); }
if (e4 != 64) { o += String.fromCharCode(c3); }
}
return o;
}
};
})();

View File

@ -1,114 +1,17 @@
var has_buf = /*#__PURE__*/(function() { return 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 has_buf = (typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && process.versions.node);
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);
// $FlowIgnore
return new (has_buf ? Buffer : 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);
/* jshint +W056 */
function s2a(s/*:string*/) {
if(has_buf) return new Buffer(s, "binary");
return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; });
}
var s2a = function s2a(s/*:string*/)/*:any*/ {
if(has_buf) return Buffer_from(s, "binary");
return s.split("").map(function(x/*:string*/)/*:number*/{ return x.charCodeAt(0) & 0xff; });
};
var bconcat = function(bufs) { return [].concat.apply([], bufs); };
function s2ab(s/*:string*/)/*:any*/ {
if(typeof ArrayBuffer === 'undefined') return s2a(s);
var buf = new ArrayBuffer(s.length), view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
function a2s(data/*:any*/)/*:string*/ {
if(Array.isArray(data)) return data.map(function(c) { return String.fromCharCode(c); }).join("");
var o/*:Array<string>*/ = []; for(var i = 0; i < data.length; ++i) o[i] = String.fromCharCode(data[i]); return o.join("");
}
function a2u(data/*:Array<number>*/)/*:Uint8Array*/ {
if(typeof Uint8Array === 'undefined') throw new Error("Unsupported");
return new Uint8Array(data);
}
function ab2a(data/*:ArrayBuffer|Uint8Array*/)/*:Array<number>*/ {
if(typeof ArrayBuffer == 'undefined') throw new Error("Unsupported");
if(data instanceof ArrayBuffer) return ab2a(new Uint8Array(data));
/*:: if(data instanceof ArrayBuffer) throw new Error("unreachable"); */
var o = new Array(data.length);
for(var i = 0; i < data.length; ++i) o[i] = data[i];
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 chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/g;
var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/;

View File

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

View File

@ -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.10.0';
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,12 @@ function SSF_init_table(t/*:any*/) {
t[48]= '##0.0E+0';
t[49]= '@';
t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "';
return t;
t[65535]= 'General';
}
/* 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"秒 "'
};
/* 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
23: 0, 24: 0, 25: 0, 26: 0, // 23 -> 0 ... 26 -> 0
27: 14, 28: 14, 29: 14, 30: 14, 31: 14, // 27 -> 14 ... 31 -> 14
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
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)
};
/* 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\\)',
// 6 -- Currency, 0 decimal, red negative
6: '"$"#,##0_);[Red]\\("$"#,##0\\)',
64: '"$"#,##0_);[Red]\\("$"#,##0\\)',
// 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>*/ {
var table_fmt = {};
init_table(table_fmt);
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 +94,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 +115,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,77 +124,63 @@ function SSF_parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
out.q = dow;
return out;
}
/* 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");
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);
}
/* 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");
}
/* exponent >= -9 and <= 9 */
function SSF_small_exp(v/*:number*/)/*:string*/ {
function general_fmt_int(v/*:number*/)/*:string*/ { return v.toString(10); }
SSF._general_int = general_fmt_int;
var general_fmt_num = (function make_general_fmt_num() {
var gnr1 = /\.(\d*[1-9])0+$/, gnr2 = /\.0*$/, gnr4 = /\.(\d*[1-9])0+/, gnr5 = /\.0*[Ee]/, gnr6 = /(E[+-])(\d)$/;
function gfn2(v) {
var w = (v<0?12:11);
var o = SSF_strip_decimal(v.toFixed(12)); if(o.length <= w) return o;
var o = gfn5(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;
function gfn3(v) {
var o = v.toFixed(11).replace(gnr1,".$1");
if(o.length > (v<0?12:11)) o = v.toPrecision(6);
return o;
}
function SSF_general_num(v/*:number*/)/*:string*/ {
function gfn4(o) {
for(var i = 0; i != o.length; ++i) if((o.charCodeAt(i) | 0x20) === 101) return o.replace(gnr4,".$1").replace(gnr5,"E").replace("e","E").replace(gnr6,"$10$2");
return o;
}
function gfn5(o) {
return o.indexOf(".") > -1 ? o.replace(gnr2,"").replace(gnr1,".$1") : o;
}
return function general_fmt_num(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(Math.abs(V) <= 9) o = gfn2(v);
else if(V === 10) o = v.toFixed(10).substr(0,12);
else o = SSF_large_exp(v);
return SSF_strip_decimal(SSF_normalize_exp(o.toUpperCase()));
}
/*
"General" rules:
- text is passed through ("@")
- booleans are rendered as TRUE/FALSE
- "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*/) {
else o = gfn3(v);
return gfn5(gfn4(o));
};})();
SSF._general_num = general_fmt_num;
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 ? general_fmt_int(v) : 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]*/) {
/* TODO: properly adjust y/m/d and */
o[0] -= 581;
var dow = date.getDay();
if(date < 60) dow = (dow + 6) % 7;
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*/ {
SSF._general = general_fmt;
function fix_hijri(/*::date, o*/) { return 0; }
/*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 */
@ -340,18 +235,14 @@ 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 */
out = y; outl = 1; break;
out = y; outl = 1;
}
var outstr = outl > 0 ? pad0(out, outl) : "";
return outstr;
if(outl > 0) return pad0(out, outl); else return "";
}
/*jshint -W086 */
/*jshint +W086 */
function commaify(s/*:string*/)/*:string*/ {
var w = 3;
@ -360,18 +251,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;
@ -408,7 +298,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;
@ -422,9 +312,10 @@ function hashq(str/*:string*/)/*:string*/ {
}
function rnd(val/*:number*/, d/*:number*/)/*:string*/ { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
function dec(val/*:number*/, d/*:number*/)/*:number*/ {
var _frac = val - Math.floor(val), dd = Math.pow(10,d);
if (d < ('' + Math.round(_frac * dd)).length) return 0;
return Math.round(_frac * dd);
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
return 0;
}
return Math.round((val-Math.floor(val))*Math.pow(10,d));
}
function carry(val/*:number*/, d/*:number*/)/*:number*/ {
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
@ -432,10 +323,7 @@ function carry(val/*:number*/, d/*:number*/)/*:number*/ {
}
return 0;
}
function flr(val/*:number*/)/*:string*/ {
if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0));
return ""+Math.floor(val);
}
function flr(val/*:number*/)/*:string*/ { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); }
function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
@ -480,7 +368,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";
@ -492,7 +380,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?]+$/))) {
@ -600,7 +488,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";
@ -612,7 +500,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?]+$/))) {
@ -638,10 +526,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))) {
@ -657,14 +545,14 @@ 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]*\]/;
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 '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;){/*empty*/} ++i; break;
case 'G': if(isgeneral(fmt, i)) i+= 6; i++; break;
case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) ++i; ++i; break;
case '\\': i+=2; break;
case '_': i+=2; break;
case '@': ++i; break;
@ -674,15 +562,14 @@ function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
/* falls through */
case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g': return true;
case 'A': case 'a': case '上':
case 'A': case 'a':
if(fmt.substr(i, 3).toUpperCase() === "A/P") return true;
if(fmt.substr(i, 5).toUpperCase() === "AM/PM") return true;
if(fmt.substr(i, 5).toUpperCase() === "上午/下午") return true;
++i; break;
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 */
@ -700,7 +587,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';
@ -708,7 +595,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);
@ -720,7 +607,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 */
@ -729,17 +616,16 @@ 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 '上':
case 'A': case 'a':
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; }
if(dt==null && q.t === 'T') return "";
out[out.length] = q; lst = c; break;
@ -747,8 +633,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) {
@ -764,7 +650,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
}
/* falls through */
case '0': case '#':
o = c; while(++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1) o += c;
o = c; while((++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1) || (c=='\\' && fmt.charAt(i+1) == "-" && i < fmt.length - 2 && "0#".indexOf(fmt.charAt(i+2))>-1)) o += c;
out[out.length] = {t:'n', v:o}; break;
case '?':
o = c; while(fmt.charAt(++i) === c) o+=c;
@ -775,24 +661,20 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
o = c; while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1) o+=fmt.charAt(i);
out[out.length] = {t:'D', v:o}; break;
case ' ': out[out.length] = {t:c, v:c}; ++i; break;
case '$': out[out.length] = {t:'t', v:'$'}; ++i; break;
default:
if(",$-+/():!^&'~{}<>=€acfijklopqrtuvwxzP".indexOf(c) === -1) throw new Error('unrecognized character ' + c + ' in ' + fmt);
out[out.length] = {t:'t', v:c}; ++i; break;
}
}
/* Scan for date/time parts */
var bt = 0, ss0 = 0, ssm;
for(i=out.length-1, lst='t'; i >= 0; --i) {
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;
@ -802,32 +684,20 @@ 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;
}
/* replace fields */
var nstr = "", jj;
for(i=0; i < out.length; ++i) {
@ -836,9 +706,9 @@ 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 '?':
case 'n': case '(': case '?':
jj = i+1;
while(out[jj] != null && (
(c=out[jj].t) === "?" || c === "D" ||
@ -851,14 +721,14 @@ 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;
if(nstr.length > 0) {
if(nstr.charCodeAt(0) == 40) /* '(' */ {
myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v);
ostr = write_num('n', nstr, myv);
ostr = write_num('(', nstr, myv);
} else {
myv = (v<0 && flen > 1 ? -v : v);
ostr = write_num('n', nstr, myv);
@ -873,7 +743,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
var lasti=out.length;
if(decpt === out.length && ostr.indexOf("E") === -1) {
for(i=out.length-1; i>= 0;--i) {
if(out[i] == null || 'n?'.indexOf(out[i].t) === -1) continue;
if(out[i] == null || 'n?('.indexOf(out[i].t) === -1) continue;
if(jj>=out[i].v.length-1) { jj -= out[i].v.length; out[i].v = ostr.substr(jj+1, out[i].v.length); }
else if(jj < 0) out[i].v = "";
else { out[i].v = ostr.substr(0, jj+1); jj = -1; }
@ -885,7 +755,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
else if(decpt !== out.length && ostr.indexOf("E") === -1) {
jj = ostr.indexOf(".")-1;
for(i=decpt; i>= 0; --i) {
if(out[i] == null || 'n?'.indexOf(out[i].t) === -1) continue;
if(out[i] == null || 'n?('.indexOf(out[i].t) === -1) continue;
j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1;
vv = out[i].v.substr(j+1);
for(; j>=0; --j) {
@ -910,7 +780,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
}
}
}
for(i=0; i<out.length; ++i) if(out[i] != null && 'n?'.indexOf(out[i].t)>-1) {
for(i=0; i<out.length; ++i) if(out[i] != null && 'n(?'.indexOf(out[i].t)>-1) {
myv = (flen >1 && v < 0 && i>0 && out[i-1].v === "-" ? -v:v);
out[i].v = write_num(out[i].t, out[i].v, myv);
out[i].t = 't';
@ -919,8 +789,9 @@ 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;
}
var cfregex2 = /\[(=|>[=]?|<[>=]?)(-?\d+(?:\.\d*)?)\]/;
SSF._eval = eval_fmt;
var cfregex = /\[[=<>]/;
var cfregex2 = /\[([=<>]*)(-?\d+\.?\d*)\]/;
function chkcond(v, rr) {
if(rr == null) return false;
var thresh = parseFloat(rr[2]);
@ -935,7 +806,7 @@ 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("|") + "|");
@ -948,14 +819,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) {
@ -966,19 +837,17 @@ 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";
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 "";
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; */
@ -994,22 +863,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);

View File

@ -1,49 +1,28 @@
var SSFImplicit/*{[number]:string}*/ = ({
"5": '"$"#,##0_);\\("$"#,##0\\)',
"6": '"$"#,##0_);[Red]\\("$"#,##0\\)',
"7": '"$"#,##0.00_);\\("$"#,##0.00\\)',
"8": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
"23": 'General', "24": 'General', "25": 'General', "26": 'General',
"27": 'm/d/yy', "28": 'm/d/yy', "29": 'm/d/yy', "30": 'm/d/yy', "31": 'm/d/yy',
"32": 'h:mm:ss', "33": 'h:mm:ss', "34": 'h:mm:ss', "35": 'h:mm:ss',
"36": 'm/d/yy',
"41": '_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)',
"42": '_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)',
"43": '_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)',
"44": '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)',
"50": 'm/d/yy', "51": 'm/d/yy', "52": 'm/d/yy', "53": 'm/d/yy', "54": 'm/d/yy',
"55": 'm/d/yy', "56": 'm/d/yy', "57": 'm/d/yy', "58": 'm/d/yy',
"59": '0',
"60": '0.00',
"61": '#,##0',
"62": '#,##0.00',
"63": '"$"#,##0_);\\("$"#,##0\\)',
"64": '"$"#,##0_);[Red]\\("$"#,##0\\)',
"65": '"$"#,##0.00_);\\("$"#,##0.00\\)',
"66": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
"67": '0%',
"68": '0.00%',
"69": '# ?/?',
"70": '# ??/??',
"71": 'm/d/yy',
"72": 'm/d/yy',
"73": 'd-mmm-yy',
"74": 'd-mmm',
"75": 'mmm-yy',
"76": 'h:mm',
"77": 'h:mm:ss',
"78": 'm/d/yy h:mm',
"79": 'mm:ss',
"80": '[h]:mm:ss',
"81": 'mmss.0'
/* 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*/);
/* 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 +35,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 +45,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);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,76 +0,0 @@
var _fs;
function set_fs(fs) { _fs = fs; }
/* normalize data for blob ctor */
function blobify(data) {
if(typeof data === "string") return s2ab(data);
if(Array.isArray(data)) return a2u(data);
return data;
}
/* write or download file */
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);
if(typeof Blob !== 'undefined') {
var blob = new Blob([blobify(data)], {type:"application/octet-stream"});
/*:: declare var navigator: any; */
if(typeof navigator !== 'undefined' && navigator.msSaveBlob) return navigator.msSaveBlob(blob, fname);
/*:: declare var saveAs: any; */
if(typeof saveAs !== 'undefined') return saveAs(blob, fname);
if(typeof URL !== 'undefined' && typeof document !== 'undefined' && document.createElement && URL.createObjectURL) {
var url = URL.createObjectURL(blob);
/*:: 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 });
}
var a = document.createElement("a");
if(a.download != null) {
/*:: if(document.body == null) throw new Error("unreachable"); */
a.download = fname; a.href = url; document.body.appendChild(a); a.click();
/*:: if(document.body == null) throw new Error("unreachable"); */ document.body.removeChild(a);
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
if(typeof $ !== 'undefined' && typeof File !== 'undefined' && typeof Folder !== 'undefined') try { // extendscript
// $FlowIgnore
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; }
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; }
throw new Error("Cannot access file " + path);
}

View File

@ -1,12 +1,10 @@
function keys(o/*:any*/)/*:Array<any>*/ {
var ks = Object.keys(o), o2 = [];
for(var i = 0; i < ks.length; ++i) if(Object.prototype.hasOwnProperty.call(o, ks[i])) o2.push(ks[i]);
return o2;
}
function isval(x/*:?any*/)/*:boolean*/ { return x !== undefined && x !== null; }
function keys(o/*:any*/)/*:Array<any>*/ { return Object.keys(o); }
function evert_key(obj/*:any*/, key/*:string*/)/*:EvertType*/ {
var o = ([]/*:any*/), K = keys(obj);
for(var i = 0; i !== K.length; ++i) if(o[obj[K[i]][key]] == null) o[obj[K[i]][key]] = K[i];
for(var i = 0; i !== K.length; ++i) o[obj[K[i]][key]] = K[i];
return o;
}
@ -31,19 +29,16 @@ 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
var dnthresh = basedate.getTime() + (new Date().getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
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;
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
}
function numdate(v/*:number*/)/*:Date|number*/ {
if(v >= 60 && v < 61) return v;
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);
return out;
}
@ -56,9 +51,9 @@ function parse_isodur(s) {
if(!m[i]) continue;
mt = 1;
if(i > 3) time = true;
switch(m[i].slice(m[i].length-1)) {
switch(m[i].substr(m[i].length-1)) {
case 'Y':
throw new Error("Unsupported ISO Duration Field: " + m[i].slice(m[i].length-1));
throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1));
case 'D': mt *= 24;
/* falls through */
case 'H': mt *= 60;
@ -74,73 +69,47 @@ 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");
}
function cc2str(arr/*:Array<number>*/)/*:string*/ {
var o = "";
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
return o;
}
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 str2cc(str) {
var o = [];
for(var i = 0; i != str.length; ++i) o.push(str.charCodeAt(i));
return o;
}
function dup(o/*:any*/)/*:any*/ {
if(typeof JSON != 'undefined' && !Array.isArray(o)) return JSON.parse(JSON.stringify(o));
if(typeof o != 'object' || o == null) return o;
if(o instanceof Date) return new Date(o.getTime());
var out = {};
for(var k in o) if(Object.prototype.hasOwnProperty.call(o, k)) out[k] = dup(o[k]);
for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]);
return out;
}
@ -149,232 +118,29 @@ 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(!/\d/.test(s)) return v;
if(!isNaN(v)) 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]
/* 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));
}
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 o = new Date(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;
};
})();

View File

@ -1,6 +1,5 @@
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());
@ -14,10 +13,9 @@ function getdatabin(data) {
if(data.asNodeBuffer && has_buf) return data.asNodeBuffer();
if(data._data && data._data.getContent) {
var o = data._data.getContent();
if(typeof o == "string") return char_codes(o);
if(typeof o == "string") return str2cc(o);
return Array.prototype.slice.call(o);
}
if(data.content && data.type) return data.content;
return null;
}
@ -26,11 +24,11 @@ function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getda
/* Part 2 Section 10.1.2 "Mapping Content Types" Names are case-insensitive */
/* 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 k = keys(zip.files);
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,46 +51,18 @@ 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[\/]/, ""));
return o.sort();
}
function zip_add_file(zip, path, content) {
if(zip.FullPaths) {
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);
var _fs, jszip;
/*:: declare var JSZip:any; */
/*global JSZip:true */
if(typeof JSZip !== 'undefined') jszip = JSZip;
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
if(typeof jszip === 'undefined') jszip = require('./jszip.js');
try { _fs = require('fs'); } catch(e) { }
}
else zip.file(path, content);
}
function zip_new() { return CFB.utils.cfb_new(); }
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" });
}
throw new Error("Unrecognized type " + o.type);
}
function resolve_path(path/*:string*/, base/*:string*/)/*:string*/ {
if(path.charAt(0) == "/") return path.slice(1);
var result = base.split('/');
if(base.slice(-1) != "/") result.pop(); // folder path
var target = path.split('/');

View File

@ -1,33 +1,30 @@
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]+))/g;
var tagregex=/<[\/\?]?[a-zA-Z0-9:]+(?:\s+[^"\s?>\/]+=(?:"[^"]*"|'[^']*'|[^'">\s]+))*\s?[\/\?]?>/g;
if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*/)/*:any*/ {
function parsexmltag(tag/*:string*/, skip_root/*:?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(!skip_root) z[0] = tag.substr(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);
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;
q = cc.substr(0,c);
quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0;
v = cc.slice(c+1+quot, cc.length-quot);
v = cc.substring(c+1+quot, cc.length-quot);
for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
if(j===q.length) {
if(q.indexOf("_") > 0) q = q.slice(0, q.indexOf("_")); // from ods
if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_")); // from ods
z[q] = v;
if(!skip_LC) z[q.toLowerCase()] = v;
}
else {
var k = (j===5 && q.slice(0,5)==="xmlns"?"xmlns":"")+q.slice(j+1);
if(z[k] && q.slice(j-3,j) == "ext") continue; // from ods
var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1);
if(z[k] && q.substr(j-3,3) == "ext") continue; // from ods
z[k] = v;
if(!skip_LC) z[k.toLowerCase()] = v;
}
}
return z;
@ -41,62 +38,53 @@ 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})_/ig;
function raw_unescapexml(text/*:string*/)/*:string*/ {
var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/g, coderegex = /_x([\da-fA-F]{4})_/g;
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;
function escapexml(text/*:string*/)/*:string*/{
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
function escapexml(text/*:string*/, xml/*:?boolean*/)/*: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) + "_";});
}
function escapexmltag(text/*:string*/)/*:string*/{ return escapexml(text).replace(/ /g,"_x0020_"); }
var htmlcharegex = /[\u0000-\u001f]/g;
function escapehtml(text/*:string*/)/*:string*/{
function escapehtml(text){
var s = text + '';
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(/\n/g, "<br/>").replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; });
}
function escapexlml(text/*:string*/)/*:string*/{
var s = text + '';
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; });
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; });
}
/* 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*/ {
function parsexmlbool(value/*:any*/, tag/*:?string*/)/*: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) {
var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
while (i < orig.length) {
c = orig.charCodeAt(i++);
@ -111,31 +99,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) {
var out/*:Array<string>*/ = [], i = 0, c = 0, d = 0;
while(i < orig.length) {
c = orig.charCodeAt(i++);
@ -161,85 +127,87 @@ var utf8write/*:StringConv*/ = has_buf ? function(data) { return Buffer_from(dat
return out.join("");
};
var htmldecode/*:{(s:string):string}*/ = /*#__PURE__*/(function() {
var entities/*:Array<[RegExp, string]>*/ = [
['nbsp', ' '], ['middot', '·'],
['quot', '"'], ['apos', "'"], ['gt', '>'], ['lt', '<'], ['amp', '&']
].map(function(x/*:[string, string]*/) { return [new RegExp('&' + x[0] + ';', "ig"), x[1]]; });
return function htmldecode(str/*:string*/)/*:string*/ {
var o = str
// 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")
// Added line which removes any white space characters after and before html tags
.replace(/>\s+/g,">").replace(/\b\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,"");
for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]);
return o;
if(has_buf) {
var utf8readb = function utf8readb(data) {
var out = new Buffer(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;
// $FlowIgnore
var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
utf8write = function(data) { return new Buffer(data, 'utf8').toString("binary"); };
}
// matches <foo>...</foo> extracts content
var matchtag = (function() {
var mtcache/*:{[k:string]:RegExp}*/ = ({}/*:any*/);
return function matchtag(f,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 vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^<"'>]*)>([\s\S]*)</;
function parseVector(data/*:string*/, opts)/*:Array<{v:string,t:string}>*/ {
function htmldecode(str/*:string*/)/*:string*/ {
return str.trim().replace(/\s+/g, " ").replace(/<\s*[bB][rR]\s*\/?>/g,"\n").replace(/<[^>]*>/g,"").replace(/&nbsp;/g, " ");
}
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, opts) {
var h = parsexmltag(data);
var matches/*:Array<string>*/ = str_match_xml_ns_g(data, h.baseType)||[];
var res/*:Array<any>*/ = [];
var matches = data.match(vtregex(h.baseType))||[];
var res = [];
if(matches.length != h.size) {
if(opts.WTF) throw new Error("unexpected vector length " + matches.length + " != " + h.size);
return res;
}
matches.forEach(function(x/*:string*/) {
matches.forEach(function(x) {
var v = x.replace(vtvregex,"").match(vtmregex);
if(v) res.push({v:utf8read(v[2]), t:v[1]});
res.push({v:utf8read(v[2]), t:v[1]});
});
return res;
}
var wtregex = /(^\s|\s$|\n)/;
function writetag(f/*:string*/,g/*:string*/)/*:string*/ { return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>'; }
function writetag(f,g) {return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>';}
function wxt_helper(h)/*:string*/ { return keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join(""); }
function writextag(f/*:string*/,g/*:?string*/,h) { return '<' + f + ((h != null) ? wxt_helper(h) : "") + ((g != null) ? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';}
function writextag(f,g,h) { return '<' + f + (isval(h) /*:: && h */? wxt_helper(h) : "") + (isval(g) /*:: && g */? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';}
function write_w3cdtf(d/*:Date*/, t/*:?boolean*/)/*:string*/ { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } return ""; }
function write_vt(s, xlsx/*:?boolean*/)/*:string*/ {
function write_vt(s)/*:string*/ {
switch(typeof s) {
case 'string':
var o = writextag('vt:lpwstr', escapexml(s));
if(xlsx) o = o.replace(/&quot;/g, "_x0022_");
return o;
case 'number': return writextag((s|0)==s?'vt:i4':'vt:r8', escapexml(String(s)));
case 'string': return writextag('vt:lpwstr', s);
case 'number': return writextag((s|0)==s?'vt:i4':'vt:r8', String(s));
case 'boolean': return writextag('vt:bool',s?'true':'false');
}
if(s instanceof Date) return writextag('vt:filetime', write_w3cdtf(s));
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/',
@ -251,7 +219,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',

View File

@ -3,96 +3,89 @@ function read_double_le(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ {
var e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 0x0f);
var m = (b[idx+6]&0x0f);
for(var i = 5; i >= 0; --i) m = m * 256 + b[idx + i];
if(e == 0x7ff) return m == 0 ? (s * Infinity) : NaN;
if(e == 0x7ff) return m == 0 ? s * Infinity : NaN;
if(e == 0) e = -1022;
else { e -= 1023; m += Math.pow(2,52); }
return s * Math.pow(2, e - 52) * m;
}
function write_double_le(b/*:RawBytes|CFBlob*/, v/*:number*/, idx/*:number*/) {
var bs = ((((v < 0) || (1/v == -Infinity)) ? 1 : 0) << 7), e = 0, m = 0;
var av = bs ? (-v) : v;
var bs = ((v < 0 || 1/v == -Infinity) ? 1 : 0) << 7, e = 0, m = 0;
var av = bs ? -v : v;
if(!isFinite(av)) { e = 0x7ff; m = isNaN(v) ? 0x6969 : 0; }
else if(av == 0) e = m = 0;
else {
e = Math.floor(Math.log(av) / Math.LN2);
m = av * Math.pow(2, 52 - e);
if((e <= -1023) && (!isFinite(m) || (m < Math.pow(2,52)))) { e = -1022; }
if(e <= -1023 && (!isFinite(m) || m < Math.pow(2,52))) { e = -1022; }
else { m -= Math.pow(2,52); e+=1023; }
}
for(var i = 0; i <= 5; ++i, m/=256) b[idx + i] = m & 0xff;
b[idx + 6] = ((e & 0x0f) << 4) | (m & 0xf);
b[idx + 6] = ((e & 0x0f) << 4) | m & 0xf;
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) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } 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 __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_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]; };
var __readInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { var u = (b[idx+1]*(1<<8))+b[idx]; return (u < 0x8000) ? u : ((0xffff - u + 1) * -1); };
var __readUInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+1]*(1<<8)+b[idx]; };
var __readInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; };
var __readUInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
var __readInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
var __readInt32BE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx]<<24)|(b[idx+1]<<16)|(b[idx+2]<<8)|b[idx+3]; };
var ___unhexlify = function(s/*:string*/)/*:Array<number>*/ { return (s.match(/../g)||[]).map(function(x) { return parseInt(x,16);}); };
var __unhexlify = typeof Buffer !== "undefined" ? function(s/*:string*/)/*:Array<number>|Buffer*/ { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;
function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
var o="", oI/*:: :number = 0*/, oR, oo=[], w, vv, i, loc;
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");
else for(i = 0; i < size; ++i) { o+=String.fromCharCode(__readUInt16LE(this, loc)); loc+=2; }
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,15 +93,14 @@ 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;
/* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */
case 'lpstr-ansi': o = __lpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break;
case 'lpstr-cp': o = __cpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break;
case 'lpstr': o = __lpstr(this, this.l); size = 5 + o.length; break;
/* [MS-OLEDS] 2.1.5 LengthPrefixedUnicodeString */
case 'lpwstr': o = __lpwstr(this, this.l); size = 4 + 2 * __readUInt32LE(this, this.l); break;
case 'lpwstr': o = __lpwstr(this, this.l); size = 5 + o.length; if(o[o.length-1] == '\u0000') size += 2; break;
/* [MS-OFFCRYPTO] 2.1.2 Length-Prefixed Padded Unicode String (UNICODE-LP-P4) */
case 'lpp4': size = 4 + __readUInt32LE(this, this.l); o = __lpp4(this, this.l); if(size & 0x02) size += 2; break;
/* [MS-OFFCRYPTO] 2.1.3 Length-Prefixed UTF-8 String (UTF-8-LP-P4) */
@ -123,7 +115,7 @@ function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
/* sbcs and dbcs support continue records in the SST way TODO codepages */
case 'dbcs-cont': o = ""; loc = this.l;
for(i = 0; i < size; ++i) {
for(i = 0; i != size; ++i) {
if(this.lens && this.lens.indexOf(loc) !== -1) {
w = __readUInt8(this, loc);
this.l = loc + 1;
@ -134,12 +126,6 @@ function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
loc+=2;
} 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));
break;
}
/* falls through */
case 'sbcs-cont': o = ""; loc = this.l;
for(i = 0; i != size; ++i) {
if(this.lens && this.lens.indexOf(loc) !== -1) {
@ -157,7 +143,7 @@ function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
case 1: oI = __readUInt8(this, this.l); this.l++; return oI;
case 2: oI = (t === 'i' ? __readInt16LE : __readUInt16LE)(this, this.l); this.l += 2; return oI;
case 4: case -4:
if(t === 'i' || ((this[this.l+3] & 0x80)===0)) { oI = ((size > 0) ? __readInt32LE : __readInt32BE)(this, this.l); this.l += 4; return oI; }
if(t === 'i' || (this[this.l+3] & 0x80)===0) { oI = (size > 0 ? __readInt32LE : __readInt32BE)(this, this.l); this.l += 4; return oI; }
else { oR = __readUInt32LE(this, this.l); this.l += 4; } return oR;
case 8: case -8:
if(t === 'f') {
@ -181,41 +167,25 @@ 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) {
/* 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];
}
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;
}
} else if(f === 'sbcs') {
/* TODO: codepage */
/*:: 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;
} else if(f === 'hex') {
for(; i < t; ++i) {
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
this[this.l++] = (parseInt(val.slice(2*i, 2*i+2), 16)||0);
this[this.l++] = parseInt(val.slice(2*i, 2*i+2), 16)||0;
} return this;
} else if(f === 'utf16le') {
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
var end/*:number*/ = Math.min(this.l + t, this.length);
var end/*:number*/ = this.l + t;
for(i = 0; i < Math.min(val.length, t); ++i) {
var cc = val.charCodeAt(i);
this[this.l++] = (cc & 0xff);
this[this.l++] = (cc >> 8);
this[this.l++] = cc & 0xff;
this[this.l++] = cc >> 8;
}
while(this.l < end) this[this.l++] = 0;
return this;
@ -246,6 +216,9 @@ function prep_blob(blob, pos/*:number*/)/*:void*/ {
}
function parsenoop(blob, length/*:: :number, opts?:any */) { blob.l += length; }
function parsenooplog(blob, length/*:number*/) { if(typeof console != 'undefined') console.log(blob.slice(blob.l, blob.l + length)); blob.l += length; }
function writenoop(blob, length/*:number*/) { blob.l += length; }
function new_buf(sz/*:number*/)/*:Block*/ {
var o = new_raw_buf(sz);

View File

@ -12,54 +12,51 @@ 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 ? 256 : 2048;
var newblk = function ba_newblk(sz/*:number*/)/*:Block*/ {
var bufs = [], blksz = has_buf ? 256 : 2048;
var newblk = function ba_newblk(sz) {
var o/*:Block*/ = (new_buf(sz)/*:any*/);
prep_blob(o, 0);
return o;
};
var curbuf/*:Block*/ = newblk(blksz);
var curbuf = newblk(blksz);
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);
if(curbuf.length > 0) bufs.push(curbuf);
curbuf = null;
};
var next = function ba_next(sz/*:number*/)/*:Block*/ {
if(curbuf && (sz < (curbuf.length - curbuf.l))) return curbuf;
var next = function ba_next(sz) {
if(curbuf && sz < curbuf.length - curbuf.l) return curbuf;
endbuf();
return (curbuf = newblk(Math.max(sz+1, blksz)));
};
var end = function ba_end() {
endbuf();
return bconcat(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; next(blksz); };
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*/;
l = 1 + (t >= 0x80 ? 1 : 0) + 1 + length;
if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l;
var o = ba.next(l);
if(t <= 0x7F) o.write_shift(1, t);

View File

@ -5,8 +5,8 @@ function shift_cell_xls(cell/*:CellAddress*/, tgt/*:any*/, opts/*:?any*/)/*:Cell
if(out.cRel) out.c += tgt.s.c;
if(out.rRel) out.r += tgt.s.r;
} else {
if(out.cRel) out.c += tgt.c;
if(out.rRel) out.r += tgt.r;
out.c += tgt.c;
out.r += tgt.r;
}
if(!opts || opts.biff < 12) {
while(out.c >= 0x100) out.c -= 0x100;
@ -22,25 +22,23 @@ function shift_range_xls(cell, range, opts) {
return out;
}
function encode_cell_xls(c/*:CellAddress*/, biff/*:number*/)/*:string*/ {
if(c.cRel && c.c < 0) { c = dup(c); while(c.c < 0) c.c += (biff > 8) ? 0x4000 : 0x100; }
if(c.rRel && c.r < 0) { c = dup(c); while(c.r < 0) c.r += (biff > 8) ? 0x100000 : ((biff > 5) ? 0x10000 : 0x4000); }
function encode_cell_xls(c/*:CellAddress*/)/*:string*/ {
var s = encode_cell(c);
if(!c.cRel && c.cRel != null) s = fix_col(s);
if(!c.rRel && c.rRel != null) s = fix_row(s);
if(c.cRel === 0) s = fix_col(s);
if(c.rRel === 0) s = fix_row(s);
return s;
}
function encode_range_xls(r, opts)/*:string*/ {
if(r.s.r == 0 && !r.s.rRel) {
if(r.e.r == (opts.biff >= 12 ? 0xFFFFF : (opts.biff >= 8 ? 0x10000 : 0x4000)) && !r.e.rRel) {
if(r.e.r == (opts.biff >= 12 ? 0xFFFFF : 0xFFFF) && !r.e.rRel) {
return (r.s.cRel ? "" : "$") + encode_col(r.s.c) + ":" + (r.e.cRel ? "" : "$") + encode_col(r.e.c);
}
}
if(r.s.c == 0 && !r.s.cRel) {
if(r.e.c == (opts.biff >= 12 ? 0x3FFF : 0xFF) && !r.e.cRel) {
if(r.e.c == (opts.biff >= 12 ? 0xFFFF : 0xFF) && !r.e.cRel) {
return (r.s.rRel ? "" : "$") + encode_row(r.s.r) + ":" + (r.e.rRel ? "" : "$") + encode_row(r.e.r);
}
}
return encode_cell_xls(r.s, opts.biff) + ":" + encode_cell_xls(r.e, opts.biff);
return encode_cell_xls(r.s) + ":" + encode_cell_xls(r.e);
}

View File

@ -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
View 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 = Buffer(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);

View File

@ -4,31 +4,16 @@ function fix_row(cstr/*:string*/)/*:string*/ { return cstr.replace(/([A-Z]|^)(\d
function unfix_row(cstr/*:string*/)/*:string*/ { return cstr.replace(/\$(\d+)$/,"$1"); }
function decode_col(colstr/*:string*/)/*:number*/ { var c = unfix_col(colstr), d = 0, i = 0; for(; i !== c.length; ++i) d = 26*d + c.charCodeAt(i) - 64; return d - 1; }
function encode_col(col/*:number*/)/*:string*/ { if(col < 0) throw new Error("invalid column " + col); var s=""; for(++col; col; col=Math.floor((col-1)/26)) s = String.fromCharCode(((col-1)%26) + 65) + s; return s; }
function encode_col(col/*:number*/)/*:string*/ { var s=""; for(++col; col; col=Math.floor((col-1)/26)) s = String.fromCharCode(((col-1)%26) + 65) + s; return s; }
function fix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^([A-Z])/,"$$$1"); }
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 R = 0, C = 0;
for(var i = 0; i < cstr.length; ++i) {
var cc = cstr.charCodeAt(i);
if(cc >= 48 && cc <= 57) R = 10 * R + (cc - 48);
else if(cc >= 65 && cc <= 90) C = 26 * C + (cc - 64);
}
return { c: C - 1, r:R - 1 };
}
function encode_cell(cell/*:CellAddress*/)/*:string*/ {
var col = cell.c + 1;
var s="";
for(; col; col=((col-1)/26)|0) s = String.fromCharCode(((col-1)%26) + 65) + s;
return s + (cell.r + 1);
}
function decode_range(range/*:string*/)/*:Range*/ {
var idx = range.indexOf(":");
if(idx == -1) return { s: decode_cell(range), e: decode_cell(range) };
return { s: decode_cell(range.slice(0, idx)), e: decode_cell(range.slice(idx + 1)) };
}
function decode_cell(cstr/*:string*/)/*:CellAddress*/ { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; }
function encode_cell(cell/*:CellAddress*/)/*:string*/ { return encode_col(cell.c) + encode_row(cell.r); }
function fix_cell(cstr/*:string*/)/*:string*/ { return fix_col(fix_row(cstr)); }
function unfix_cell(cstr/*:string*/)/*:string*/ { return unfix_col(unfix_row(cstr)); }
function decode_range(range/*:string*/)/*:Range*/ { var x =range.split(":").map(decode_cell); return {s:x[0],e:x[x.length-1]}; }
/*# if only one arg, it is assumed to be a Range. If 2 args, both are cell addresses */
function encode_range(cs/*:CellAddrSpec|Range*/,ce/*:?CellAddrSpec*/)/*:string*/ {
if(typeof ce === 'undefined' || typeof ce === 'number') {
@ -42,17 +27,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 +44,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 +62,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,88 +80,39 @@ function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ {
return { SheetNames: [n], Sheets: sheets };
}
function sheet_new(opts) {
var out = {};
function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
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;
if(DENSE != null && dense == null) dense = DENSE;
var ws/*:Worksheet*/ = _ws || ({}/*:any*/);
if(dense && !ws["!data"]) ws["!data"] = [];
var _R = 0, _C = 0;
if(ws && o.origin != null) {
if(typeof o.origin == 'number') _R = o.origin;
else {
var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
_R = _origin.r; _C = _origin.c;
}
}
if(DENSE != null && o.dense == null) o.dense = DENSE;
var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/);
var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/);
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;
}
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, __Rstr = "" + (__R + 1);
//console.log("!!", R, _R, __R);
if(dense) {
if(!ws["!data"][__R]) ws["!data"][__R] = [];
row = ws["!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] }/*:any*/);
var __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];
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') 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); }
}
else cell.t = 's';
if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
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;
if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.cellStubs) 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 || 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); }
}
if(dense) {
if(row[__C] && row[__C].z) cell.z = row[__C].z;
row[__C] = cell;
else cell.t = 's';
if(o.dense) {
if(!ws[R]) ws[R] = [];
ws[R][C] = cell;
} else {
var cell_ref = encode_col(__C) + __Rstr/*:any*/;
if(ws[cell_ref] && ws[cell_ref].z) cell.z = ws[cell_ref].z;
var cell_ref = encode_cell(({c:C,r:R}/*:any*/));
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); }

View File

@ -1,8 +1,5 @@
function parse_Int32LE(data) {
return data.read_shift(4, 'i');
}
function write_UInt32LE(x/*:number*/, o) {
if (!o) o = new_buf(4);
if(!o) o = new_buf(4);
o.write_shift(4, x);
return o;
}
@ -13,43 +10,37 @@ function parse_XLWideString(data/*::, length*/)/*:string*/ {
return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, 'dbcs');
}
function write_XLWideString(data/*:string*/, o) {
var _null = false; if (o == null) { _null = true; o = new_buf(4 + 2 * data.length); }
var _null = false; if(o == null) { _null = true; o = new_buf(4+2*data.length); }
o.write_shift(4, data.length);
if (data.length > 0) o.write_shift(0, data, 'dbcs');
if(data.length > 0) o.write_shift(0, data, 'dbcs');
return _null ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.5.91 */
//function parse_LPWideString(data/*::, length*/)/*:string*/ {
// var cchCharacters = data.read_shift(2);
// return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, "utf16le");
//}
/* [MS-XLSB] 2.5.143 */
function parse_StrRun(data) {
function parse_StrRun(data, length/*:?number*/) {
return { ich: data.read_shift(2), ifnt: data.read_shift(2) };
}
function write_StrRun(run, o) {
if (!o) o = new_buf(4);
if(!o) o = new_buf(4);
o.write_shift(2, run.ich || 0);
o.write_shift(2, run.ifnt || 0);
return o;
}
/* [MS-XLSB] 2.5.121 */
/* [MS-XLSB] 2.1.7.121 */
function parse_RichStr(data, length/*:number*/)/*:XLString*/ {
var start = data.l;
var flags = data.read_shift(1);
var str = parse_XLWideString(data);
var rgsStrRun = [];
var z = ({ t: str, h: str }/*:any*/);
if ((flags & 1) !== 0) { /* fRichStr */
if((flags & 1) !== 0) { /* fRichStr */
/* TODO: formatted string */
var dwSizeStrRun = data.read_shift(4);
for (var i = 0; i != dwSizeStrRun; ++i) rgsStrRun.push(parse_StrRun(data));
for(var i = 0; i != dwSizeStrRun; ++i) rgsStrRun.push(parse_StrRun(data));
z.r = rgsStrRun;
}
else z.r = [{ ich: 0, ifnt: 0 }];
else z.r = [{ich:0, ifnt:0}];
//if((flags & 2) !== 0) { /* fExtStr */
// /* TODO: phonetic string */
//}
@ -58,20 +49,20 @@ function parse_RichStr(data, length/*:number*/)/*:XLString*/ {
}
function write_RichStr(str/*:XLString*/, o/*:?Block*/)/*:Block*/ {
/* TODO: formatted string */
var _null = false; if (o == null) { _null = true; o = new_buf(15 + 4 * str.t.length); }
o.write_shift(1, 0);
var _null = false; if(o == null) { _null = true; o = new_buf(15+4*str.t.length); }
o.write_shift(1,0);
write_XLWideString(str.t, o);
return _null ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.328 BrtCommentText (RichStr w/1 run) */
/* [MS-XLSB] 2.4.325 BrtCommentText (RichStr w/1 run) */
var parse_BrtCommentText = parse_RichStr;
function write_BrtCommentText(str/*:XLString*/, o/*:?Block*/)/*:Block*/ {
/* TODO: formatted string */
var _null = false; if (o == null) { _null = true; o = new_buf(23 + 4 * str.t.length); }
o.write_shift(1, 1);
var _null = false; if(o == null) { _null = true; o = new_buf(23+4*str.t.length); }
o.write_shift(1,1);
write_XLWideString(str.t, o);
o.write_shift(4, 1);
write_StrRun({ ich: 0, ifnt: 0 }, o);
o.write_shift(4,1);
write_StrRun({ich:0,ifnt:0}, o);
return _null ? o.slice(0, o.l) : o;
}
@ -79,31 +70,18 @@ function write_BrtCommentText(str/*:XLString*/, o/*:?Block*/)/*:Block*/ {
function parse_XLSBCell(data)/*:any*/ {
var col = data.read_shift(4);
var iStyleRef = data.read_shift(2);
iStyleRef += data.read_shift(1) << 16;
data.l++; //var fPhShow = data.read_shift(1);
return { c: col, iStyleRef: iStyleRef };
iStyleRef += data.read_shift(1) <<16;
var fPhShow = data.read_shift(1);
return { c:col, iStyleRef: iStyleRef };
}
function write_XLSBCell(cell/*:any*/, o/*:?Block*/) {
if (o == null) o = new_buf(8);
if(o == null) o = new_buf(8);
o.write_shift(-4, cell.c);
o.write_shift(3, cell.iStyleRef || cell.s);
o.write_shift(1, 0); /* fPhShow */
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;
@ -115,50 +93,53 @@ function parse_XLNullableWideString(data/*::, length*/)/*:string*/ {
return cchCharacters === 0 || cchCharacters === 0xFFFFFFFF ? "" : data.read_shift(cchCharacters, 'dbcs');
}
function write_XLNullableWideString(data/*:string*/, o) {
var _null = false; if (o == null) { _null = true; o = new_buf(127); }
var _null = false; if(o == null) { _null = true; o = new_buf(127); }
o.write_shift(4, data.length > 0 ? data.length : 0xFFFFFFFF);
if (data.length > 0) o.write_shift(0, data, 'dbcs');
if(data.length > 0) o.write_shift(0, data, 'dbcs');
return _null ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.5.165 */
var parse_XLNameWideString = parse_XLWideString;
//var write_XLNameWideString = write_XLWideString;
var write_XLNameWideString = write_XLWideString;
/* [MS-XLSB] 2.5.114 */
var parse_RelID = parse_XLNullableWideString;
var write_RelID = write_XLNullableWideString;
/* [MS-XLS] 2.5.217 ; [MS-XLSB] 2.5.122 */
/* [MS-XLSB] 2.5.122 */
/* [MS-XLS] 2.5.217 */
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;
return fX100 ? (RK / 100) : RK;
var b = data.slice(data.l, data.l+4);
var fX100 = b[0] & 1, fInt = b[0] & 2;
data.l+=4;
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) {
if (o == null) o = new_buf(4);
if(o == null) o = new_buf(4);
var fX100 = 0, fInt = 0, d100 = data * 100;
if ((data == (data | 0)) && (data >= -(1 << 29)) && (data < (1 << 29))) { fInt = 1; }
else if ((d100 == (d100 | 0)) && (d100 >= -(1 << 29)) && (d100 < (1 << 29))) { fInt = 1; fX100 = 1; }
if (fInt) o.write_shift(-4, ((fX100 ? d100 : data) << 2) + (fX100 + 2));
if(data == (data | 0) && data >= -(1<<29) && data < (1 << 29)) { fInt = 1; }
else if(d100 == (d100 | 0) && d100 >= -(1<<29) && d100 < (1 << 29)) { fInt = 1; fX100 = 1; }
if(fInt) o.write_shift(-4, ((fX100 ? d100 : data) << 2) + (fX100 + 2));
else throw new Error("unsupported RkNumber " + data); // TODO
}
/* [MS-XLSB] 2.5.117 RfX */
function parse_RfX(data /*::, length*/)/*:Range*/ {
var cell/*:Range*/ = ({ s: {}, e: {} }/*:any*/);
var cell/*:Range*/ = ({s: {}, e: {}}/*:any*/);
cell.s.r = data.read_shift(4);
cell.e.r = data.read_shift(4);
cell.s.c = data.read_shift(4);
cell.e.c = data.read_shift(4);
return cell;
}
function write_RfX(r/*:Range*/, o) {
if (!o) o = new_buf(16);
if(!o) o = new_buf(16);
o.write_shift(4, r.s.r);
o.write_shift(4, r.e.r);
o.write_shift(4, r.s.c);
@ -170,40 +151,32 @@ function write_RfX(r/*:Range*/, o) {
var parse_UncheckedRfX = parse_RfX;
var write_UncheckedRfX = write_RfX;
/* [MS-XLSB] 2.5.155 UncheckedSqRfX */
//function parse_UncheckedSqRfX(data) {
// var cnt = data.read_shift(4);
// var out = [];
// for(var i = 0; i < cnt; ++i) {
// var rng = parse_UncheckedRfX(data);
// out.push(encode_range(rng));
// }
// return out.join(",");
//}
//function write_UncheckedSqRfX(sqrfx/*:string*/) {
// var parts = sqrfx.split(/\s*,\s*/);
// var o = new_buf(4); o.write_shift(4, parts.length);
// var out = [o];
// parts.forEach(function(rng) {
// out.push(write_UncheckedRfX(safe_decode_range(rng)));
// });
// return bconcat(out);
//}
/* [MS-XLS] 2.5.342 ; [MS-XLSB] 2.5.171 */
/* [MS-XLSB] 2.5.171 */
/* [MS-XLS] 2.5.342 */
/* TODO: error checking, NaN and Infinity values are not valid Xnum */
function parse_Xnum(data/*::, length*/) {
if(data.length - data.l < 8) throw "XLS Xnum Buffer underflow";
return data.read_shift(8, 'f');
}
function parse_Xnum(data, length/*:?number*/) { return data.read_shift(8, 'f'); }
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); }
/* [MS-XLSB] 2.4.324 BrtColor */
function parse_BrtColor(data/*::, length*/) {
/* [MS-XLSB] 2.5.198.2 */
var BErr = {
/*::[*/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);
/* [MS-XLSB] 2.4.321 BrtColor */
function parse_BrtColor(data, length/*:number*/) {
var out = {};
var d = data.read_shift(1);
//var fValidRGB = d & 1;
var fValidRGB = d & 1;
var xColorType = d >>> 1;
var index = data.read_shift(1);
@ -211,15 +184,15 @@ function parse_BrtColor(data/*::, length*/) {
var bR = data.read_shift(1);
var bG = data.read_shift(1);
var bB = data.read_shift(1);
data.l++; //var bAlpha = data.read_shift(1);
var bAlpha = data.read_shift(1);
switch (xColorType) {
switch(xColorType) {
case 0: out.auto = 1; break;
case 1:
out.index = index;
var icv = XLSIcv[index];
/* automatic pseudo index 81 */
if (icv) out.rgb = rgb2Hex(icv);
if(icv) out.rgb = rgb2Hex(icv);
break;
case 2:
/* if(!fValidRGB) throw new Error("invalid"); */
@ -227,17 +200,17 @@ function parse_BrtColor(data/*::, length*/) {
break;
case 3: out.theme = index; break;
}
if (nTS != 0) out.tint = nTS > 0 ? nTS / 32767 : nTS / 32768;
if(nTS != 0) out.tint = nTS > 0 ? nTS / 32767 : nTS / 32768;
return out;
}
function write_BrtColor(color, o) {
if (!o) o = new_buf(8);
if (!color || color.auto) { o.write_shift(4, 0); o.write_shift(4, 0); return o; }
if (color.index != null) {
if(!o) o = new_buf(8);
if(!color||color.auto) { o.write_shift(4, 0); o.write_shift(4, 0); return o; }
if(color.index) {
o.write_shift(1, 0x02);
o.write_shift(1, color.index);
} else if (color.theme != null) {
} else if(color.theme) {
o.write_shift(1, 0x06);
o.write_shift(1, color.theme);
} else {
@ -245,32 +218,31 @@ function write_BrtColor(color, o) {
o.write_shift(1, 0);
}
var nTS = color.tint || 0;
if (nTS > 0) nTS *= 32767;
else if (nTS < 0) nTS *= 32768;
if(nTS > 0) nTS *= 32767;
else if(nTS < 0) nTS *= 32768;
o.write_shift(2, nTS);
if (!color.rgb || color.theme != null) {
if(!color.rgb) {
o.write_shift(2, 0);
o.write_shift(1, 0);
o.write_shift(1, 0);
} else {
var rgb = (color.rgb || 'FFFFFF');
if (typeof rgb == 'number') rgb = ("000000" + rgb.toString(16)).slice(-6);
o.write_shift(1, parseInt(rgb.slice(0, 2), 16));
o.write_shift(1, parseInt(rgb.slice(2, 4), 16));
o.write_shift(1, parseInt(rgb.slice(4, 6), 16));
o.write_shift(1, parseInt(rgb.substr(0,2),16));
o.write_shift(1, parseInt(rgb.substr(2,2),16));
o.write_shift(1, parseInt(rgb.substr(4,2),16));
o.write_shift(1, 0xFF);
}
return o;
}
/* [MS-XLSB] 2.5.52 */
function parse_FontFlags(data/*::, length, opts*/) {
function parse_FontFlags(data, length/*:number*/, opts) {
var d = data.read_shift(1);
data.l++;
var out = {
fBold: d & 0x01,
/* fBold: d & 0x01 */
fItalic: d & 0x02,
fUnderline: d & 0x04,
/* fUnderline: d & 0x04 */
fStrikeout: d & 0x08,
fOutline: d & 0x10,
fShadow: d & 0x20,
@ -280,32 +252,16 @@ function parse_FontFlags(data/*::, length, opts*/) {
return out;
}
function write_FontFlags(font, o) {
if (!o) o = new_buf(2);
if(!o) o = new_buf(2);
var grbit =
(font.italic ? 0x02 : 0) |
(font.strike ? 0x08 : 0) |
(font.outline ? 0x10 : 0) |
(font.shadow ? 0x20 : 0) |
(font.italic ? 0x02 : 0) |
(font.strike ? 0x08 : 0) |
(font.outline ? 0x10 : 0) |
(font.shadow ? 0x20 : 0) |
(font.condense ? 0x40 : 0) |
(font.extend ? 0x80 : 0);
(font.extend ? 0x80 : 0);
o.write_shift(1, grbit);
o.write_shift(1, 0);
return o;
}
/* [MS-OLEDS] 2.3.1 and 2.3.2 */
function parse_ClipboardFormatOrString(o, w/*:number*/)/*:string*/ {
// $FlowIgnore
var ClipFmt = { 2: "BITMAP", 3: "METAFILEPICT", 8: "DIB", 14: "ENHMETAFILE" };
var m/*:number*/ = o.read_shift(4);
switch (m) {
case 0x00000000: return "";
case 0xffffffff: case 0xfffffffe: return ClipFmt[o.read_shift(4)] || "";
}
if (m > 0x190) throw new Error("Unsupported Clipboard: " + m.toString(16));
o.l -= 4;
return o.read_shift(0, w == 1 ? "lpstr" : "lpwstr");
}
function parse_ClipboardFormatOrAnsiString(o) { return parse_ClipboardFormatOrString(o, 1); }
function parse_ClipboardFormatOrUnicodeString(o) { return parse_ClipboardFormatOrString(o, 2); }

View File

@ -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;
@ -18,13 +17,13 @@ var VT_VARIANT = 0x000C;
//var VT_UI2 = 0x0012;
var VT_UI4 = 0x0013;
//var VT_I8 = 0x0014;
//var VT_UI8 = 0x0015;
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;
//var VT_BLOB = 0x0041;
//var VT_STREAM = 0x0042;
//var VT_STORAGE = 0x0043;
//var VT_STREAMED_Object = 0x0044;
@ -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,121 @@ 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: 'Scale', t: VT_BOOL },
/*::[*/0x0c/*::]*/: { n: 'HeadingPair', t: VT_VECTOR | VT_VARIANT },
/*::[*/0x0d/*::]*/: { n: 'DocParts', t: VT_VECTOR | VT_LPSTR },
/*::[*/0x0e/*::]*/: { n: 'Manager', t: VT_STRING },
/*::[*/0x0f/*::]*/: { n: 'Company', t: VT_STRING },
/*::[*/0x10/*::]*/: { n: 'LinksDirty', t: VT_BOOL },
/*::[*/0x11/*::]*/: { n: 'CharacterCount', t: VT_I4 },
/*::[*/0x13/*::]*/: { n: 'SharedDoc', t: VT_BOOL },
/*::[*/0x16/*::]*/: { n: 'HLinksChanged', t: VT_BOOL },
/*::[*/0x17/*::]*/: { n: 'AppVersion', t: VT_I4, p: 'version' },
/*::[*/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: 'ApplicationName', t: VT_LPSTR },
/*::[*/0x13/*::]*/: { n: 'DocumentSecurity', 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(SpecialProperties.hasOwnProperty(y))
DocSummaryPIDDSI[y] = SummaryPIDSI[y] = SpecialProperties[y];
})();
/* [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 */
@ -181,11 +181,11 @@ var XLSFillPattern = [
'gray0625'
];
function rgbify(arr/*:Array<number>*/)/*:Array<[number, number, number]>*/ { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); }
function rgbify(arr) { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); }
/* [MS-XLS] 2.5.161 */
/* [MS-XLSB] 2.5.75 Icv */
var _XLSIcv = /*#__PURE__*/ rgbify([
/* [MS-XLSB] 2.5.75 */
var XLSIcv = rgbify([
/* Color Constants */
0x000000,
0xFFFFFF,
@ -258,8 +258,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 +277,4 @@ var _XLSIcv = /*#__PURE__*/ rgbify([
0x000000, /* 0x50 icvInfoBk ?? */
0x000000 /* 0x51 icvInfoText ?? */
]);
var XLSIcv = /*#__PURE__*/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?"
};
//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"
];

View File

@ -1,42 +1,19 @@
/* Parts enumerated in OPC spec, MS-XLSB and MS-XLSX */
/* 12.3 Part Summary <SpreadsheetML> */
/* 14.2 Part Summary <DrawingML> */
/* [MS-XLSX] 2.1 Part Enumerations ; [MS-XLSB] 2.1.7 Part Enumeration */
/* [MS-XLSX] 2.1 Part Enumerations */
/* [MS-XLSB] 2.1.7 Part Enumeration */
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,32 +23,16 @@ 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",
/* Chart Objects */
"application/vnd.openxmlformats-officedocument.drawingml.chart+xml": "TODO",
/* Chart Colors */
"application/vnd.ms-office.chartcolorstyle+xml": "TODO",
/* Chart Style */
"application/vnd.ms-office.chartstyle+xml": "TODO",
/* Chart Advanced */
"application/vnd.ms-office.chartex+xml": "TODO",
/* Calculation Chain */
"application/vnd.ms-excel.calcChain": "calcchains",
"application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains",
@ -94,6 +55,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 +106,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",
@ -158,6 +123,7 @@ var ct2type/*{[string]:string}*/ = ({
/* Drawing */
"application/vnd.openxmlformats-officedocument.drawing+xml": "drawings",
"application/vnd.openxmlformats-officedocument.drawingml.chart+xml": "TODO",
"application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml": "TODO",
"application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml": "TODO",
"application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml": "TODO",
@ -176,58 +142,62 @@ 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",
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) { if(!o[k].xlsm) o[k].xlsm = 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*/);
}
function parse_ct(data/*:?string*/) {
function parse_ct(data/*:?string*/, opts) {
var ct = new_ct();
if(!data || !data.match) return ct;
var ctext = {};
@ -236,7 +206,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,60 +221,52 @@ 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'],
/* 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]});
}));
}
/* only write first instance */
o[o.length] = (XML_HEADER);
o[o.length] = (CTYPE_XML_ROOT);
o = o.concat(CTYPE_DEFAULTS);
var f1 = function(w) {
if(ct[w] && ct[w].length > 0) {
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']
}));
}
};
/* book type-specific */
var f2 = function(w) {
(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']
}));
});
};
/* standard type */
var f3 = function(t) {
(ct[t]||[]).forEach(function(v) {
o[o.length] = (writextag('Override', null, {
@ -313,7 +275,6 @@ function write_ct(ct, opts, raw)/*:string*/ {
}));
});
};
f1('workbooks');
f2('sheets');
f2('charts');
@ -322,10 +283,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("");
}

View File

@ -4,55 +4,28 @@ var RELS = ({
SHEET: "http://sheetjs.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
HLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
VML: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing",
XPATH: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath",
XMISS: "http://schemas.microsoft.com/office/2006/relationships/xlExternalLinkPath/xlPathMissing",
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*/);
/* 9.3.3 Representing Relationships */
function get_rels_path(file/*:string*/)/*:string*/ {
var n = file.lastIndexOf("/");
return file.slice(0,n+1) + '_rels/' + file.slice(n+1) + ".rels";
return file.substr(0,n+1) + '_rels/' + file.substr(n+1) + ".rels";
}
function parse_rels(data/*:?string*/, currentFilePath/*:string*/) {
var rels = {"!id":{}};
if (!data) return rels;
if (!data) return data;
if (currentFilePath.charAt(0) !== '/') {
currentFilePath = '/'+currentFilePath;
}
var rels = {};
var hash = {};
(data.match(tagregex)||[]).forEach(function(x) {
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 +35,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 +52,14 @@ function write_rels(rels)/*:string*/ {
return o.join("");
}
function add_rels(rels, rId/*:number*/, f, type, relobj, targetmode/*:?string*/)/*:number*/ {
function add_rels(rels, rId, f, type, relobj)/*: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";
if(relobj.Type == RELS.HLINK) 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;

View File

@ -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> >*/, opts)/*: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>";
function write_rdf(rdf, opts) {
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) {
return payload;
};
})();

View File

@ -18,36 +18,50 @@ 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].substr(0,f[0].indexOf(":")) +":)"+ f[0].substr(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]);
if(cur != null && cur.length > 0) p[f[1]] = unescapexml(cur[1]);
var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
if(cur != null && cur.length > 0) p[f[1]] = cur[1];
if(f[2] === 'date' && p[f[1]]) p[f[1]] = parseDate(p[f[1]]);
}
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;
g = escapexml(g);
o[o.length] = (h ? writextag(f,g,h) : writetag(f,g));
}
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) {

View File

@ -14,94 +14,87 @@ var EXT_PROPS/*:Array<Array<string> >*/ = [
["TitlesOfParts", "TitlesOfParts", "raw"]
];
var PseudoPropsPairs = [
"Worksheets", "SheetNames",
"NamedRanges", "DefinedNames",
"Chartsheets", "ChartNames"
];
function load_props_pairs(HP/*:string|Array<Array<any>>*/, TOP, props, opts) {
var v = [];
if(typeof HP == "string") v = parseVector(HP, opts);
else for(var j = 0; j < HP.length; ++j) v = v.concat(HP[j].map(function(hp) { return {v:hp}; }));
var parts = (typeof TOP == "string") ? parseVector(TOP, opts).map(function (x) { return x.v; }) : TOP;
var idx = 0, len = 0;
if(parts.length > 0) for(var i = 0; i !== v.length; i += 2) {
len = +(v[i+1].v);
switch(v[i].v) {
case "Worksheets":
case "工作表":
case "Листы":
case "أوراق العمل":
case "ワークシート":
case "גליונות עבודה":
case "Arbeitsblätter":
case "Çalışma Sayfaları":
case "Feuilles de calcul":
case "Fogli di lavoro":
case "Folhas de cálculo":
case "Planilhas":
case "Regneark":
case "Hojas de cálculo":
case "Werkbladen":
props.Worksheets = len;
props.SheetNames = parts.slice(idx, idx + len);
break;
case "Named Ranges":
case "Rangos con nombre":
case "名前付き一覧":
case "Benannte Bereiche":
case "Navngivne områder":
props.NamedRanges = len;
props.DefinedNames = parts.slice(idx, idx + len);
break;
case "Charts":
case "Diagramme":
props.Chartsheets = len;
props.ChartNames = parts.slice(idx, idx + len);
break;
}
idx += len;
}
}
XMLNS.EXT_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
RELS.EXT_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';
function parse_ext_props(data, p, opts) {
var q = {}; if(!p) p = {};
data = utf8read(data);
EXT_PROPS.forEach(function(f) {
var xml = (str_match_xml_ns(data, 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 "string": p[f[1]] = (data.match(matchtag(f[0]))||[])[1]; break;
case "bool": p[f[1]] = (data.match(matchtag(f[0]))||[])[1] === "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;
}
});
if(q.HeadingPairs && q.TitlesOfParts) load_props_pairs(q.HeadingPairs, q.TitlesOfParts, p, opts);
if(q.HeadingPairs && q.TitlesOfParts) {
var v = parseVector(q.HeadingPairs, opts);
var parts = parseVector(q.TitlesOfParts, opts).map(function (x) { return x.v; });
var idx = 0, len = 0;
if(parts.length > 0) for(var i = 0; i !== v.length; i += 2) {
len = +(v[i+1].v);
switch(v[i].v) {
case "Worksheets":
case "工作表":
case "Листы":
case "أوراق العمل":
case "ワークシート":
case "גליונות עבודה":
case "Arbeitsblätter":
case "Çalışma Sayfaları":
case "Feuilles de calcul":
case "Fogli di lavoro":
case "Folhas de cálculo":
case "Planilhas":
case "Regneark":
case "Werkbladen":
p.Worksheets = len;
p.SheetNames = parts.slice(idx, idx + len);
break;
case "Named Ranges":
case "名前付き一覧":
case "Benannte Bereiche":
case "Navngivne områder":
p.NamedRanges = len;
p.DefinedNames = parts.slice(idx, idx + len);
break;
case "Charts":
case "Diagramme":
p.Chartsheets = len;
p.ChartNames = parts.slice(idx, idx + len);
break;
}
idx += len;
}
}
return p;
}
function write_ext_props(cp/*::, opts*/)/*:string*/ {
var o/*:Array<string>*/ = [], W = writextag;
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 = [], p = {}, 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;
var v;
switch(f[2]) {
case 'string': v = escapexml(String(cp[f[1]])); break;
case 'string': v = String(cp[f[1]]); break;
case 'bool': v = cp[f[1]] ? 'true' : 'false'; break;
}
if(v !== undefined) o[o.length] = (W(f[0], v));

View File

@ -1,25 +1,28 @@
/* 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;
case '<property': name = y.name; break;
case '</property>': name = null; break;
default: if (x.indexOf('<vt:') === 0) {
var toks = x.split('>');
var type = toks[0].slice(4), text = toks[1];
var type = toks[0].substring(4), text = toks[1];
/* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */
switch(type) {
case 'lpstr': case 'bstr': case 'lpwstr':
p[name] = unescapexml(text);
break;
case 'bool':
p[name] = parsexmlbool(text);
p[name] = parsexmlbool(text, '<vt:bool>');
break;
case 'i1': case 'i2': case 'i4': case 'i8': case 'int': case 'uint':
p[name] = parseInt(text, 10);
@ -37,25 +40,28 @@ function parse_cust_props(data/*:string*/, opts) {
if(type.slice(-1) == '/') break;
if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks);
}
} else if(x.slice(0,2) === "</") {/* empty */
} else if(x.substr(0,2) === "</") {/* empty */
} else if(opts.WTF) throw new Error(x);
}
}
return p;
}
function write_cust_props(cp/*::, opts*/)/*:string*/ {
var o = [XML_HEADER, writextag('Properties', null, {
'xmlns': XMLNS.CUST_PROPS,
'xmlns:vt': XMLNS.vt
})];
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, CUST_PROPS_XML_ROOT];
if(!cp) return o.join("");
var pid = 1;
keys(cp).forEach(function custprop(k) { ++pid;
o[o.length] = (writextag('property', write_vt(cp[k], true), {
// $FlowIgnore
o[o.length] = (writextag('property', write_vt(cp[k]), {
'fmtid': '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}',
'pid': pid,
'name': escapexml(k)
'name': k
}));
});
if(o.length>2){ o[o.length] = '</Properties>'; o[1]=o[1].replace("/>",">"); }

View File

@ -31,16 +31,15 @@ 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;
}
function xlml_write_docprops(Props, opts) {
var o/*:Array<string>*/ = [];
var o = [];
keys(XLMLDocPropsMap).map(function(m) {
for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i];
for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i];
@ -58,13 +57,13 @@ function xlml_write_docprops(Props, opts) {
});
return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o });
}
function xlml_write_custprops(Props, Custprops/*::, opts*/) {
function xlml_write_custprops(Props, Custprops, opts) {
var BLACKLIST = ["Worksheets","SheetNames"];
var T = 'CustomDocumentProperties';
var o/*:Array<string>*/ = [];
var o = [];
if(Props) keys(Props).forEach(function(k) {
/*:: if(!Props) return; */
if(!Object.prototype.hasOwnProperty.call(Props, k)) return;
if(!Props.hasOwnProperty(k)) return;
for(var i = 0; i < CORE_PROPS.length; ++i) if(k == CORE_PROPS[i][1]) return;
for(i = 0; i < EXT_PROPS.length; ++i) if(k == EXT_PROPS[i][1]) return;
for(i = 0; i < BLACKLIST.length; ++i) if(k == BLACKLIST[i]) return;
@ -78,8 +77,7 @@ function xlml_write_custprops(Props, Custprops/*::, opts*/) {
});
if(Custprops) keys(Custprops).forEach(function(k) {
/*:: if(!Custprops) return; */
if(!Object.prototype.hasOwnProperty.call(Custprops, k)) return;
if(Props && Object.prototype.hasOwnProperty.call(Props, k)) return;
if(!Custprops.hasOwnProperty(k)) return;
var m = Custprops[k];
var t = "string";
if(typeof m == 'number') { t = "float"; m = String(m); }

View File

@ -5,21 +5,11 @@ function parse_FILETIME(blob) {
var dwLowDateTime = blob.read_shift(4), dwHighDateTime = blob.read_shift(4);
return new Date(((dwHighDateTime/1e7*Math.pow(2,32) + dwLowDateTime/1e7) - 11644473600)*1000).toISOString().replace(/\.000/,"");
}
function write_FILETIME(time/*:string|Date*/) {
var date = (typeof time == "string") ? new Date(Date.parse(time)) : time;
var t = date.getTime() / 1000 + 11644473600;
var l = t % Math.pow(2,32), h = (t - l) / Math.pow(2,32);
l *= 1e7; h *= 1e7;
var w = (l / Math.pow(2,32)) | 0;
if(w > 0) { l = l % Math.pow(2,32); h += w; }
var o = new_buf(8); o.write_shift(4, l); o.write_shift(4, h); return o;
}
/* [MS-OSHARED] 2.3.3.1.4 Lpstr */
function parse_lpstr(blob, type, pad/*:?number*/) {
var start = blob.l;
var str = blob.read_shift(0, 'lpstr-cp');
if(pad) while((blob.l - start) & 3) ++blob.l;
var str = blob.read_shift(0, 'lpstr');
if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3;
return str;
}
@ -41,32 +31,22 @@ 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>*/ {
function parse_VtVecUnalignedLpstrValue(blob) {
var length = blob.read_shift(4);
var ret/*:Array<string>*/ = [];
for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr-cp').replace(chr0,'');
var ret = [];
for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr');
return ret;
}
/* [MS-OSHARED] 2.3.3.1.10 VtVecUnalignedLpstr */
function parse_VtVecUnalignedLpstr(blob) {
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 +55,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);
@ -87,7 +73,6 @@ function parse_dictionary(blob,CodePage) {
var pid = blob.read_shift(4);
var len = blob.read_shift(4);
dict[pid] = blob.read_shift(len, (CodePage === 0x4B0 ?'utf16le':'utf8')).replace(chr0,'').replace(chr1,'!');
if(CodePage === 0x4B0 && (len % 2)) blob.l += 2;
}
if(blob.l & 3) blob.l = (blob.l>>2+1)<<2;
return dict;
@ -97,7 +82,6 @@ function parse_dictionary(blob,CodePage) {
function parse_BLOB(blob) {
var size = blob.read_shift(4);
var bytes = blob.slice(blob.l,blob.l+size);
blob.l += size;
if((size & 3) > 0) blob.l += (4 - (size & 3)) & 3;
return bytes;
}
@ -108,16 +92,27 @@ function parse_ClipboardData(blob) {
var o = {};
o.Size = blob.read_shift(4);
//o.Format = blob.read_shift(4);
blob.l += o.Size + 3 - (o.Size - 1) % 4;
blob.l += o.Size;
return o;
}
/* [MS-OLEPS] 2.14 Vector and Array Property Types */
function parse_VtVector(blob, cb) {
/* [MS-OLEPS] 2.14.2 VectorHeader */
/* var Length = blob.read_shift(4);
var o = [];
for(var i = 0; i != Length; ++i) {
o.push(cb(blob));
}
return o;*/
}
/* [MS-OLEPS] 2.15 TypedPropertyValue */
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;
@ -130,33 +125,22 @@ function parse_TypedPropertyValue(blob, type/*:number*/, _opts)/*:any*/ {
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);
}
}
function write_TypedPropertyValue(type/*:number*/, value) {
var o = new_buf(4), p = new_buf(4);
o.write_shift(4, type == 0x50 ? 0x1F : type);
switch(type) {
case 0x03 /*VT_I4*/: p.write_shift(-4, value); break;
case 0x05 /*VT_I4*/: p = new_buf(8); p.write_shift(8, value, 'f'); break;
case 0x0B /*VT_BOOL*/: p.write_shift(4, value ? 0x01 : 0x00); break;
case 0x40 /*VT_FILETIME*/: /*:: if(typeof value !== "string" && !(value instanceof Date)) throw "unreachable"; */ p = write_FILETIME(value); break;
case 0x1F /*VT_LPWSTR*/:
case 0x50 /*VT_STRING*/:
/*:: if(typeof value !== "string") throw "unreachable"; */
p = new_buf(4 + 2 * (value.length + 1) + (value.length % 2 ? 0 : 2));
p.write_shift(4, value.length + 1);
p.write_shift(0, value, "dbcs");
while(p.l != p.length) p.write_shift(1, 0);
break;
default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + value);
/* [MS-OLEPS] 2.14.2 VectorHeader */
/*function parse_VTVectorVariant(blob) {
var Length = blob.read_shift(4);
if(Length & 1 !== 0) throw new Error("VectorHeader Length=" + Length + " must be even");
var o = [];
for(var i = 0; i != Length; ++i) {
o.push(parse_TypedPropertyValue(blob, VT_VARIANT));
}
return bconcat([o, p]);
}
return o;
}*/
/* [MS-OLEPS] 2.20 PropertySet */
function parse_PropertySet(blob, PIDSI) {
@ -171,24 +155,22 @@ function parse_PropertySet(blob, PIDSI) {
var Offset = blob.read_shift(4);
Props[i] = [PropID, Offset + start_addr];
}
Props.sort(function(x,y) { return x[1] - y[1]; });
var PropH = {};
for(i = 0; i != NumProps; ++i) {
if(blob.l !== Props[i][1]) {
var fail = true;
if(i>0 && PIDSI) switch(PIDSI[Props[i-1][0]].t) {
case 0x02 /*VT_I2*/: if(blob.l+2 === Props[i][1]) { blob.l+=2; fail = false; } break;
case 0x02 /*VT_I2*/: if(blob.l +2 === Props[i][1]) { blob.l+=2; fail = false; } break;
case 0x50 /*VT_STRING*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
case 0x100C /*VT_VECTOR|VT_VARIANT*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
}
if((!PIDSI||i==0) && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; }
if(!PIDSI && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; }
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);
if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + String(PropH[piddsi.n] & 0xFFFF);
if(piddsi.n == "CodePage") switch(PropH[piddsi.n]) {
case 0: PropH[piddsi.n] = 1252;
/* falls through */
@ -233,8 +215,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]); break;
case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]); 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,86 +231,9 @@ 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" ];
function guess_property_type(val/*:any*/)/*:number*/ {
switch(typeof val) {
case "boolean": return 0x0B;
case "number": return ((val|0)==val) ? 0x03 : 0x05;
case "string": return 0x1F;
case "object": if(val instanceof Date) return 0x40; break;
}
return -1;
}
function write_PropertySet(entries, RE, PIDSI) {
var hdr = new_buf(8), piao = [], prop = [];
var sz = 8, i = 0;
var pr = new_buf(8), pio = new_buf(8);
pr.write_shift(4, 0x0002);
pr.write_shift(4, 0x04B0);
pio.write_shift(4, 0x0001);
prop.push(pr); piao.push(pio);
sz += 8 + pr.length;
if(!RE) {
pio = new_buf(8);
pio.write_shift(4, 0);
piao.unshift(pio);
var bufs = [new_buf(4)];
bufs[0].write_shift(4, entries.length);
for(i = 0; i < entries.length; ++i) {
var value = entries[i][0];
pr = new_buf(4 + 4 + 2 * (value.length + 1) + (value.length % 2 ? 0 : 2));
pr.write_shift(4, i+2);
pr.write_shift(4, value.length + 1);
pr.write_shift(0, value, "dbcs");
while(pr.l != pr.length) pr.write_shift(1, 0);
bufs.push(pr);
}
pr = bconcat(bufs);
prop.unshift(pr);
sz += 8 + pr.length;
}
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(entries[i][1] == null) continue;
var val = entries[i][1], idx = 0;
if(RE) {
idx = +RE[entries[i][0]];
var pinfo = (PIDSI/*:: || {}*/)[idx]/*:: || {} */;
if(pinfo.p == "version" && typeof val == "string") {
/*:: if(typeof val !== "string") throw "unreachable"; */
var arr = val.split(".");
val = ((+arr[0])<<16) + ((+arr[1])||0);
}
pr = write_TypedPropertyValue(pinfo.t, val);
} else {
var T = guess_property_type(val);
if(T == -1) { T = 0x1F; val = String(val); }
pr = write_TypedPropertyValue(T, val);
}
prop.push(pr);
pio = new_buf(8);
pio.write_shift(4, !RE ? 2+i : idx);
piao.push(pio);
sz += 8 + pr.length;
}
var w = 8 * (prop.length + 1);
for(i = 0; i < prop.length; ++i) { piao[i].write_shift(4, w); w += prop[i].length; }
hdr.write_shift(4, sz);
hdr.write_shift(4, prop.length);
return bconcat([hdr].concat(piao).concat(prop));
}
/* [MS-OLEPS] 2.21 PropertySetStream */
function parse_PropertySetStream(file, PIDSI, clsid) {
function parse_PropertySetStream(file, PIDSI) {
var blob = file.content;
if(!blob) return ({}/*:any*/);
prep_blob(blob, 0);
@ -336,10 +241,9 @@ function parse_PropertySetStream(file, PIDSI, clsid) {
var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;
blob.chk('feff', 'Byte Order: ');
/*var vers = */blob.read_shift(2); // TODO: check version
var vers = blob.read_shift(2); // TODO: check version
var SystemIdentifier = blob.read_shift(4);
var CLSID = blob.read_shift(16);
if(CLSID !== CFB.utils.consts.HEADER_CLSID && CLSID !== clsid) throw new Error("Bad PropertySet CLSID " + CLSID);
blob.chk(CFB.utils.consts.HEADER_CLSID, 'CLSID: ');
NumSets = blob.read_shift(4);
if(NumSets !== 1 && NumSets !== 2) throw new Error("Unrecognized #Sets: " + NumSets);
FMTID0 = blob.read_shift(16); Offset0 = blob.read_shift(4);
@ -354,7 +258,6 @@ function parse_PropertySetStream(file, PIDSI, clsid) {
rval.FMTID = FMTID0;
//rval.PSet0 = PSet0;
if(NumSets === 1) return rval;
if(Offset1 - blob.l == 2) blob.l += 2;
if(blob.l !== Offset1) throw new Error("Length mismatch 2: " + blob.l + " !== " + Offset1);
var PSet1;
try { PSet1 = parse_PropertySet(blob, null); } catch(e) {/* empty */}
@ -362,27 +265,7 @@ function parse_PropertySetStream(file, PIDSI, clsid) {
rval.FMTID = [FMTID0, FMTID1]; // TODO: verify FMTID0/1
return rval;
}
function write_PropertySetStream(entries, clsid, RE, PIDSI/*:{[key:string|number]:any}*/, entries2/*:?any*/, clsid2/*:?any*/) {
var hdr = new_buf(entries2 ? 68 : 48);
var bufs = [hdr];
hdr.write_shift(2, 0xFFFE);
hdr.write_shift(2, 0x0000); /* TODO: type 1 props */
hdr.write_shift(4, 0x32363237);
hdr.write_shift(16, CFB.utils.consts.HEADER_CLSID, "hex");
hdr.write_shift(4, (entries2 ? 2 : 1));
hdr.write_shift(16, clsid, "hex");
hdr.write_shift(4, (entries2 ? 68 : 48));
var ps0 = write_PropertySet(entries, RE, PIDSI);
bufs.push(ps0);
if(entries2) {
var ps1 = write_PropertySet(entries2, null, null);
hdr.write_shift(16, clsid2, "hex");
hdr.write_shift(4, 68 + ps0.length);
bufs.push(ps1);
}
return bconcat(bufs);
}
function parsenoop2(blob, length) { blob.read_shift(length); return null; }
function writezeroes(n, o) { if(!o) o=new_buf(n); for(var j=0; j<n; ++j) o.write_shift(1, 0); return o; }
@ -410,24 +293,23 @@ 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, ((t == 'e') ? 1 : 0));
o.write_shift(1, +v);
o.write_shift(1, t == 'e' ? 1 : 0);
return o;
}
/* [MS-XLS] 2.5.240 ShortXLUnicodeString */
function parse_ShortXLUnicodeString(blob, length, opts) {
var cch = blob.read_shift(opts && opts.biff >= 12 ? 2 : 1);
var encoding = 'sbcs-cont';
var width = 1, encoding = 'sbcs-cont';
var cp = current_codepage;
if(opts && opts.biff >= 8) current_codepage = 1200;
if(!opts || opts.biff == 8 ) {
var fHighByte = blob.read_shift(1);
if(fHighByte) { encoding = 'dbcs-cont'; }
if(fHighByte) { width = 2; encoding = 'dbcs-cont'; }
} else if(opts.biff == 12) {
encoding = 'wstr';
width = 2; encoding = 'wstr';
}
if(opts.biff >= 2 && opts.biff <= 5) encoding = 'cpstr';
var o = cch ? blob.read_shift(cch, encoding) : "";
current_codepage = cp;
return o;
@ -438,13 +320,13 @@ function parse_XLUnicodeRichExtendedString(blob) {
var cp = current_codepage;
current_codepage = 1200;
var cch = blob.read_shift(2), flags = blob.read_shift(1);
var /*fHighByte = flags & 0x1,*/ fExtSt = flags & 0x4, fRichSt = flags & 0x8;
var fHighByte = flags & 0x1, fExtSt = flags & 0x4, fRichSt = flags & 0x8;
var width = 1 + (flags & 0x1); // 0x0 -> utf8, 0x1 -> dbcs
var cRun = 0, cbExtRst;
var z = {};
if(fRichSt) cRun = blob.read_shift(2);
if(fExtSt) cbExtRst = blob.read_shift(4);
var encoding = width == 2 ? 'dbcs-cont' : 'sbcs-cont';
var encoding = (flags & 0x1) ? 'dbcs-cont' : 'sbcs-cont';
var msg = cch === 0 ? "" : blob.read_shift(cch, encoding);
if(fRichSt) blob.l += 4 * cRun; //TODO: parse this
if(fExtSt) blob.l += cbExtRst; //TODO: parse this
@ -453,27 +335,12 @@ function parse_XLUnicodeRichExtendedString(blob) {
current_codepage = cp;
return z;
}
function write_XLUnicodeRichExtendedString(xlstr/*:: :XLString, opts*/) {
var str = (xlstr.t||""), nfmts = 1;
var hdr = new_buf(3 + (nfmts > 1 ? 2 : 0));
hdr.write_shift(2, str.length);
hdr.write_shift(1, (nfmts > 1 ? 0x08 : 0x00) | 0x01);
if(nfmts > 1) hdr.write_shift(2, nfmts);
var otext = new_buf(2 * str.length);
otext.write_shift(2 * str.length, str, 'utf16le');
var out = [hdr, otext];
return bconcat(out);
}
/* 2.5.296 XLUnicodeStringNoCch */
function parse_XLUnicodeStringNoCch(blob, cch, opts) {
var retval;
if(opts) {
if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'cpstr');
if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'sbcs-cont');
if(opts.biff >= 12) return blob.read_shift(cch, 'dbcs-cont');
}
var fHighByte = blob.read_shift(1);
@ -493,7 +360,7 @@ function parse_XLUnicodeString2(blob, length, opts) {
if(opts.biff > 5) return parse_XLUnicodeString(blob, length, opts);
var cch = blob.read_shift(1);
if(cch === 0) { blob.l++; return ""; }
return blob.read_shift(cch, (opts.biff <= 4 || !blob.lens ) ? 'cpstr' : 'sbcs-cont');
return blob.read_shift(cch, 'sbcs-cont');
}
/* TODO: BIFF5 and lower, codepage awareness */
function write_XLUnicodeString(str, opts, o) {
@ -505,7 +372,7 @@ function write_XLUnicodeString(str, opts, o) {
}
/* [MS-XLS] 2.5.61 ControlInfo */
function parse_ControlInfo(blob/*::, length, opts*/) {
function parse_ControlInfo(blob, length, opts) {
var flags = blob.read_shift(1);
blob.l++;
var accel = blob.read_shift(2);
@ -529,18 +396,18 @@ function parse_URLMoniker(blob/*::, length, opts*/) {
}
/* [MS-OSHARED] 2.3.7.8 FileMoniker TODO: all fields */
function parse_FileMoniker(blob/*::, length*/) {
function parse_FileMoniker(blob, length) {
var cAnti = blob.read_shift(2);
var preamble = ""; while(cAnti-- > 0) preamble += "../";
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,"/");
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;
var ansiLength = blob.read_shift(4);
var ansiPath = blob.read_shift(ansiLength, 'cstr');
var endServer = blob.read_shift(2);
var versionNumber = blob.read_shift(2);
var cbUnicodePathSize = blob.read_shift(4);
if(cbUnicodePathSize === 0) return ansiPath.replace(/\\/g,"/");
var cbUnicodePathBytes = blob.read_shift(4);
var usKeyValue = blob.read_shift(2);
var unicodePath = blob.read_shift(cbUnicodePathBytes>>1, 'utf16le').replace(chr0,"");
return unicodePath;
}
/* [MS-OSHARED] 2.3.7.2 HyperlinkMoniker TODO: all the monikers */
@ -554,83 +421,35 @@ function parse_HyperlinkMoniker(blob, length) {
}
/* [MS-OSHARED] 2.3.7.9 HyperlinkString */
function parse_HyperlinkString(blob/*::, length*/) {
function parse_HyperlinkString(blob, length) {
var len = blob.read_shift(4);
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);
var o = blob.read_shift(len, 'utf16le').replace(chr0, "");
return o;
}
/* [MS-OSHARED] 2.3.7.1 Hyperlink Object */
function parse_Hyperlink(blob, length)/*:Hyperlink*/ {
/* [MS-OSHARED] 2.3.7.1 Hyperlink Object TODO: unify params with XLSX */
function parse_Hyperlink(blob, length) {
var end = blob.l + length;
var sVer = blob.read_shift(4);
if(sVer !== 2) throw new Error("Unrecognized streamVersion: " + sVer);
var flags = blob.read_shift(2);
blob.l += 2;
var displayName, targetFrameName, moniker, oleMoniker, Loc="", guid, fileTime;
var displayName, targetFrameName, moniker, oleMoniker, location, guid, fileTime;
if(flags & 0x0010) displayName = parse_HyperlinkString(blob, end - blob.l);
if(flags & 0x0080) targetFrameName = parse_HyperlinkString(blob, end - blob.l);
if((flags & 0x0101) === 0x0101) moniker = parse_HyperlinkString(blob, end - blob.l);
if((flags & 0x0101) === 0x0001) oleMoniker = parse_HyperlinkMoniker(blob, end - blob.l);
if(flags & 0x0008) Loc = parse_HyperlinkString(blob, end - blob.l);
if(flags & 0x0008) location = parse_HyperlinkString(blob, end - blob.l);
if(flags & 0x0020) guid = blob.read_shift(16);
if(flags & 0x0040) fileTime = parse_FILETIME(blob/*, 8*/);
blob.l = end;
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;
if(displayName) out.Tooltip = displayName;
return out;
}
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;
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);
} 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(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(1, 0);
out.write_shift(2, 0xFFFF);
out.write_shift(2, 0xDEAD);
for(i = 0; i < 6; ++i) out.write_shift(4, 0);
}
return out.slice(0, out.l);
var target = (targetFrameName||moniker||oleMoniker);
if(location) target+="#"+location;
return {Target: target};
}
/* 2.5.178 LongRGBA */
function parse_LongRGBA(blob/*::, length*/) { var r = blob.read_shift(1), g = blob.read_shift(1), b = blob.read_shift(1), a = blob.read_shift(1); return [r,g,b,a]; }
function parse_LongRGBA(blob, length) { var r = blob.read_shift(1), g = blob.read_shift(1), b = blob.read_shift(1), a = blob.read_shift(1); return [r,g,b,a]; }
/* 2.5.177 LongRGB */
function parse_LongRGB(blob, length) { var x = parse_LongRGBA(blob, length); x[3] = 0; return x; }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,139 +1,132 @@
/* 18.4.7 rPr CT_RPrElt */
function parse_rpr(rpr) {
var font = {}, m = rpr.match(tagregex), i = 0;
var pass = false;
if(m) for(;i!=m.length; ++i) {
var y = parsexmltag(m[i]);
switch(y[0].replace(/<\w*:/g,"<")) {
/* 18.8.12 condense CT_BooleanProperty */
/* ** not required . */
case '<condense': break;
/* 18.8.17 extend CT_BooleanProperty */
/* ** not required . */
case '<extend': break;
/* 18.8.36 shadow CT_BooleanProperty */
/* ** not required . */
case '<shadow':
if(!y.val) break;
/* falls through */
case '<shadow>':
case '<shadow/>': font.shadow = 1; break;
case '</shadow>': break;
/* 18.4.1 charset CT_IntProperty TODO */
case '<charset':
if(y.val == '1') break;
font.cp = CS2CP[parseInt(y.val, 10)];
break;
/* 18.4.2 outline CT_BooleanProperty TODO */
case '<outline':
if(!y.val) break;
/* falls through */
case '<outline>':
case '<outline/>': font.outline = 1; break;
case '</outline>': break;
/* 18.4.5 rFont CT_FontName */
case '<rFont': font.name = y.val; break;
/* 18.4.11 sz CT_FontSize */
case '<sz': font.sz = y.val; break;
/* 18.4.10 strike CT_BooleanProperty */
case '<strike':
if(!y.val) break;
/* falls through */
case '<strike>':
case '<strike/>': font.strike = 1; break;
case '</strike>': break;
/* 18.4.13 u CT_UnderlineProperty */
case '<u':
if(!y.val) break;
switch(y.val) {
case 'double': font.uval = "double"; break;
case 'singleAccounting': font.uval = "single-accounting"; break;
case 'doubleAccounting': font.uval = "double-accounting"; break;
}
/* falls through */
case '<u>':
case '<u/>': font.u = 1; break;
case '</u>': break;
/* 18.8.2 b */
case '<b':
if(y.val == '0') break;
/* falls through */
case '<b>':
case '<b/>': font.b = 1; break;
case '</b>': break;
/* 18.8.26 i */
case '<i':
if(y.val == '0') break;
/* falls through */
case '<i>':
case '<i/>': font.i = 1; break;
case '</i>': break;
/* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */
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;
case '<ext': pass = true; break;
case '</ext>': pass = false; break;
default:
if(y[0].charCodeAt(1) !== 47 && !pass) throw new Error('Unrecognized rich format ' + y[0]);
}
}
return font;
}
var parse_rs = /*#__PURE__*/(function() {
/* 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*/;
if(!t) return {t:"s", v:""};
var o/*:Cell*/ = ({t:'s', v:unescapexml(t[1])}/*:any*/);
var rpr = str_match_xml_ns(r, "rPr");
if(rpr) o.s = parse_rpr(rpr[1]);
return o;
}
var rregex = /<(?:\w+:)?r>/g, rend = /<\/(?:\w+:)?r>/;
return function parse_rs(rs) {
return rs.replace(rregex,"").split(rend).map(parse_r).filter(function(r) { return r.v; });
};
})();
/* 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 */
}/*:any*/);
/* Parse a list of <r> tags */
var rs_to_html = /*#__PURE__*/(function parse_rs_factory() {
var nlregex = /(\r\n|\n)/g;
function parse_rpr2(font, intro, outro) {
var style/*:Array<string>*/ = [];
var parse_rs = (function parse_rs_factory() {
var tregex = matchtag("t"), rpregex = matchtag("rPr"), rregex = /<(?:\w+:)?r>/g, rend = /<\/(?:\w+:)?r>/, nlregex = /\r\n/g;
/* 18.4.7 rPr CT_RPrElt */
var parse_rpr = function parse_rpr(rpr, intro, outro) {
var font = {}, cp = 65001, align = "";
var m = rpr.match(tagregex), i = 0;
if(m) for(;i!=m.length; ++i) {
var y = parsexmltag(m[i]);
switch(y[0].replace(/\w*:/g,"")) {
/* 18.8.12 condense CT_BooleanProperty */
/* ** not required . */
case '<condense': break;
/* 18.8.17 extend CT_BooleanProperty */
/* ** not required . */
case '<extend': break;
/* 18.8.36 shadow CT_BooleanProperty */
/* ** not required . */
case '<shadow':
if(!y.val) break;
/* falls through */
case '<shadow>':
case '<shadow/>': font.shadow = 1; break;
case '</shadow>': break;
/* 18.4.1 charset CT_IntProperty TODO */
case '<charset':
if(y.val == '1') break;
cp = CS2CP[parseInt(y.val, 10)];
break;
/* 18.4.2 outline CT_BooleanProperty TODO */
case '<outline':
if(!y.val) break;
/* falls through */
case '<outline>':
case '<outline/>': font.outline = 1; break;
case '</outline>': break;
/* 18.4.5 rFont CT_FontName */
case '<rFont': font.name = y.val; break;
/* 18.4.11 sz CT_FontSize */
case '<sz': font.sz = y.val; break;
/* 18.4.10 strike CT_BooleanProperty */
case '<strike':
if(!y.val) break;
/* falls through */
case '<strike>':
case '<strike/>': font.strike = 1; break;
case '</strike>': break;
/* 18.4.13 u CT_UnderlineProperty */
case '<u':
if(!y.val) break;
switch(y.val) {
case 'double': font.uval = "double"; break;
case 'singleAccounting': font.uval = "single-accounting"; break;
case 'doubleAccounting': font.uval = "double-accounting"; break;
}
/* falls through */
case '<u>':
case '<u/>': font.u = 1; break;
case '</u>': break;
/* 18.8.2 b */
case '<b':
if(y.val == '0') break;
/* falls through */
case '<b>':
case '<b/>': font.b = 1; break;
case '</b>': break;
/* 18.8.26 i */
case '<i':
if(y.val == '0') break;
/* falls through */
case '<i>':
case '<i/>': font.i = 1; break;
case '</i>': break;
/* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */
case '<color':
if(y.rgb) font.color = y.rgb.substr(2,6);
break;
/* 18.8.18 family ST_FontFamily */
case '<family': font.family = y.val; break;
/* 18.4.14 vertAlign CT_VerticalAlignFontProperty TODO */
case '<vertAlign': align = y.val; break;
/* 18.8.35 scheme CT_FontScheme TODO */
case '<scheme': break;
default:
if(y[0].charCodeAt(1) !== 47) throw 'Unrecognized rich format ' + y[0];
}
}
var style = [];
if(font.u) style.push("text-decoration: underline;");
if(font.uval) style.push("text-underline-style:" + font.uval + ";");
if(font.sz) style.push("font-size:" + font.sz + "pt;");
if(font.sz) style.push("font-size:" + font.sz + ";");
if(font.outline) style.push("text-effect: outline;");
if(font.shadow) style.push("text-shadow: auto;");
intro.push('<span style="' + style.join("") + '">');
@ -142,49 +135,52 @@ var rs_to_html = /*#__PURE__*/(function parse_rs_factory() {
if(font.i) { intro.push("<i>"); outro.push("</i>"); }
if(font.strike) { intro.push("<s>"); outro.push("</s>"); }
var align = font.valign || "";
if(align == "superscript" || align == "super") align = "sup";
if(align == "superscript") align = "sup";
else if(align == "subscript") align = "sub";
if(align != "") { intro.push("<" + align + ">"); outro.push("</" + align + ">"); }
outro.push("</span>");
return font;
}
return cp;
};
/* 18.4.4 r CT_RElt */
function r_to_html(r) {
var terms/*:[Array<string>, string, Array<string>]*/ = [[],r.v,[]];
if(!r.v) return "";
function parse_r(r) {
var terms = [[],"",[]];
/* 18.4.12 t ST_Xstring */
var t = r.match(tregex), cp = 65001;
if(!isval(t)/*:: || !t*/) return "";
terms[1] = t[1];
if(r.s) parse_rpr2(r.s, terms[0], terms[2]);
var rpr = r.match(rpregex);
if(isval(rpr)/*:: && rpr*/) cp = parse_rpr(rpr[1], terms[0], terms[2]);
return terms[0].join("") + terms[1].replace(nlregex,'<br/>') + terms[2].join("");
}
return function parse_rs(rs) {
return rs.map(r_to_html).join("");
return rs.replace(rregex,"").split(rend).map(parse_r).join("");
};
})();
/* 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 = {};
if(!x) return { t: "" };
//var y;
if(!x) return null;
var y;
/* 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))) {
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);
if(html) z.h = rs_to_html(parse_rs(z.r));
z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")));
if(html) z.h = parse_rs(z.r);
}
/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
/* 18.4.6 rPh CT_PhoneticRun (TODO: needed for Asian support) */
@ -192,30 +188,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");
if(sst) {
ss = sst[1].replace(sstr1,"").split(sstr2);
var sst = data.match(sstr0);
if(isval(sst)/*:: && sst*/) {
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 +224,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>";
}

View File

@ -1,5 +1,5 @@
/* [MS-XLSB] 2.4.221 BrtBeginSst */
function parse_BrtBeginSst(data) {
/* [MS-XLSB] 2.4.219 BrtBeginSst */
function parse_BrtBeginSst(data, length) {
return [data.read_shift(4), data.read_shift(4)];
}
@ -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;
@ -38,11 +39,11 @@ function write_BrtBeginSst(sst, o) {
var write_BrtSSTItem = write_RichStr;
function write_sst_bin(sst/*::, opts*/) {
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();
}

View File

@ -1,6 +1,6 @@
function _JS2ANSI(str/*:string*/)/*:Array<number>*/ {
if(typeof $cptable !== 'undefined') return $cptable.utils.encode(current_ansi, str);
var o/*:Array<number>*/ = [], oo = str.split("");
if(typeof cptable !== 'undefined') return cptable.utils.encode(1252, str);
var o = [], oo = str.split("");
for(var i = 0; i < oo.length; ++i) o[i] = oo[i].charCodeAt(0);
return o;
}
@ -16,7 +16,7 @@ function parse_CRYPTOVersion(blob, length/*:?number*/) {
}
/* [MS-OFFCRYPTO] 2.1.5 DataSpaceVersionInfo */
function parse_DataSpaceVersionInfo(blob) {
function parse_DataSpaceVersionInfo(blob, length) {
var o = {};
o.id = blob.read_shift(0, 'lpp4');
o.R = parse_CRYPTOVersion(blob, 4);
@ -31,17 +31,21 @@ function parse_DataSpaceMapEntry(blob) {
var end = blob.l + len - 4;
var o = {};
var cnt = blob.read_shift(4);
var comps/*:Array<{t:number, v:string}>*/ = [];
/* [MS-OFFCRYPTO] 2.1.6.2 DataSpaceReferenceComponent Structure */
while(cnt-- > 0) comps.push({ t: blob.read_shift(4), v: blob.read_shift(0, 'lpp4') });
var comps = [];
while(cnt-- > 0) {
/* [MS-OFFCRYPTO] 2.1.6.2 DataSpaceReferenceComponent Structure */
var rc = {};
rc.t = blob.read_shift(4);
rc.v = blob.read_shift(0, 'lpp4');
comps.push(rc);
}
o.name = blob.read_shift(0, 'lpp4');
o.comps = comps;
if(blob.l != end) throw new Error("Bad DataSpaceMapEntry: " + blob.l + " != " + end);
return o;
}
/* [MS-OFFCRYPTO] 2.1.6 DataSpaceMap */
function parse_DataSpaceMap(blob) {
function parse_DataSpaceMap(blob, length) {
var o = [];
blob.l += 4; // must be 0x8
var cnt = blob.read_shift(4);
@ -50,8 +54,8 @@ function parse_DataSpaceMap(blob) {
}
/* [MS-OFFCRYPTO] 2.1.7 DataSpaceDefinition */
function parse_DataSpaceDefinition(blob)/*:Array<string>*/ {
var o/*:Array<string>*/ = [];
function parse_DataSpaceDefinition(blob, length) {
var o = [];
blob.l += 4; // must be 0x8
var cnt = blob.read_shift(4);
while(cnt-- > 0) o.push(blob.read_shift(0, 'lpp4'));
@ -59,11 +63,13 @@ function parse_DataSpaceDefinition(blob)/*:Array<string>*/ {
}
/* [MS-OFFCRYPTO] 2.1.8 DataSpaceDefinition */
function parse_TransformInfoHeader(blob) {
function parse_TransformInfoHeader(blob, length) {
var o = {};
/*var len = */blob.read_shift(4);
var len = blob.read_shift(4);
var tgt = blob.l + len - 4;
blob.l += 4; // must be 0x1
o.id = blob.read_shift(0, 'lpp4');
// tgt == len
o.name = blob.read_shift(0, 'lpp4');
o.R = parse_CRYPTOVersion(blob, 4);
o.U = parse_CRYPTOVersion(blob, 4);
@ -71,7 +77,7 @@ function parse_TransformInfoHeader(blob) {
return o;
}
function parse_Primary(blob) {
function parse_Primary(blob, length) {
/* [MS-OFFCRYPTO] 2.2.6 IRMDSTransformInfo */
var hdr = parse_TransformInfoHeader(blob);
/* [MS-OFFCRYPTO] 2.1.9 EncryptionTransformInfo */
@ -101,24 +107,24 @@ function parse_EncryptionHeader(blob, length/*:number*/) {
o.KeySize = blob.read_shift(4);
o.ProviderType = blob.read_shift(4);
blob.l += 8;
o.CSPName = blob.read_shift((tgt-blob.l)>>1, 'utf16le');
o.CSPName = blob.read_shift((tgt-blob.l)>>1, 'utf16le').slice(0,-1);
blob.l = tgt;
return o;
}
/* [MS-OFFCRYPTO] 2.3.3 Encryption Verifier */
function parse_EncryptionVerifier(blob, length/*:number*/) {
var o = {}, tgt = blob.l + length;
var o = {};
blob.l += 4; // SaltSize must be 0x10
o.Salt = blob.slice(blob.l, blob.l+16); blob.l += 16;
o.Verifier = blob.slice(blob.l, blob.l+16); blob.l += 16;
/*var sz = */blob.read_shift(4);
o.VerifierHash = blob.slice(blob.l, tgt); blob.l = tgt;
var sz = blob.read_shift(4);
o.VerifierHash = blob.slice(blob.l, blob.l + sz); blob.l += sz;
return o;
}
/* [MS-OFFCRYPTO] 2.3.4.* EncryptionInfo Stream */
function parse_EncryptionInfo(blob) {
function parse_EncryptionInfo(blob, length/*:?number*/) {
var vers = parse_CRYPTOVersion(blob);
switch(vers.Minor) {
case 0x02: return [vers.Minor, parse_EncInfoStd(blob, vers)];
@ -129,42 +135,26 @@ function parse_EncryptionInfo(blob) {
}
/* [MS-OFFCRYPTO] 2.3.4.5 EncryptionInfo Stream (Standard Encryption) */
function parse_EncInfoStd(blob/*::, vers*/) {
function parse_EncInfoStd(blob, vers) {
var flags = blob.read_shift(4);
if((flags & 0x3F) != 0x24) throw new Error("EncryptionInfo mismatch");
var sz = blob.read_shift(4);
//var tgt = blob.l + sz;
var tgt = blob.l + sz;
var hdr = parse_EncryptionHeader(blob, sz);
var verifier = parse_EncryptionVerifier(blob, blob.length - blob.l);
return { t:"Std", h:hdr, v:verifier };
}
/* [MS-OFFCRYPTO] 2.3.4.6 EncryptionInfo Stream (Extensible Encryption) */
function parse_EncInfoExt(/*::blob, vers*/) { throw new Error("File is password-protected: ECMA-376 Extensible"); }
function parse_EncInfoExt(blob, vers) { throw new Error("File is password-protected: ECMA-376 Extensible"); }
/* [MS-OFFCRYPTO] 2.3.4.10 EncryptionInfo Stream (Agile Encryption) */
function parse_EncInfoAgl(blob/*::, vers*/) {
var KeyData = ["saltSize","blockSize","keyBits","hashSize","cipherAlgorithm","cipherChaining","hashAlgorithm","saltValue"];
function parse_EncInfoAgl(blob, vers) {
blob.l+=4;
var xml = blob.read_shift(blob.length - blob.l, 'utf8');
var o = {};
xml.replace(tagregex, function xml_agile(x) {
var y/*:any*/ = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<?xml': break;
case '<encryption': case '</encryption>': break;
case '<keyData': KeyData.forEach(function(k) { o[k] = y[k]; }); break;
case '<dataIntegrity': o.encryptedHmacKey = y.encryptedHmacKey; o.encryptedHmacValue = y.encryptedHmacValue; break;
case '<keyEncryptors>': case '<keyEncryptors': o.encs = []; break;
case '</keyEncryptors>': break;
case '<keyEncryptor': o.uri = y.uri; break;
case '</keyEncryptor>': break;
case '<encryptedKey': o.encs.push(y); break;
default: throw y[0];
}
});
return o;
return blob.read_shift(blob.length - blob.l, 'utf8');
}
/* [MS-OFFCRYPTO] 2.3.5.1 RC4 CryptoAPI Encryption Header */
function parse_RC4CryptoHeader(blob, length/*:number*/) {
var o = {};
@ -178,9 +168,9 @@ function parse_RC4CryptoHeader(blob, length/*:number*/) {
return o;
}
/* [MS-OFFCRYPTO] 2.3.6.1 RC4 Encryption Header */
function parse_RC4Header(blob/*::, length*/) {
function parse_RC4Header(blob, length/*:number*/) {
var o = {};
var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4);
var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4); length -= 4;
if(vers.Major != 1 || vers.Minor != 1) throw 'unrecognized version code ' + vers.Major + ' : ' + vers.Minor;
o.Salt = blob.read_shift(16);
o.EncryptedVerifier = blob.read_shift(16);
@ -208,7 +198,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];
@ -309,7 +299,7 @@ function parse_FilePassHeader(blob, length/*:number*/, oo) {
function parse_FilePass(blob, length/*:number*/, opts) {
var o = ({ Type: opts.biff >= 8 ? blob.read_shift(2) : 0 }/*:any*/); /* wEncryptionType */
if(o.Type) parse_FilePassHeader(blob, length-2, o);
else parse_XORObfuscation(blob, opts.biff >= 8 ? length : length - 2, opts, o);
else parse_XORObfuscation(blob, length-2, opts, o);
return o;
}

View File

@ -1,103 +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);
}
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*/ = ({}/*: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
};
})();

View File

@ -1,10 +1,10 @@
function hex2RGB(h) {
var o = h.slice(h[0]==="#"?1:0).slice(0,6);
return [parseInt(o.slice(0,2),16),parseInt(o.slice(2,4),16),parseInt(o.slice(4,6),16)];
var o = h.substr(h[0]==="#"?1:0,6);
return [parseInt(o.substr(0,2),16),parseInt(o.substr(2,2),16),parseInt(o.substr(4,2),16)];
}
function rgb2Hex(rgb) {
for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);
return o.toString(16).toUpperCase().slice(1);
return o.toString(16).toUpperCase().substr(1);
}
function rgb2HSL(rgb) {
@ -55,8 +55,8 @@ var DEF_MDW = 6, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); }
function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; }
function char2width(chr) { return (Math.round((chr * MDW + 5)/MDW*256))/256; }
//function px2char_(px) { return (((px - 5)/MDW * 100 + 0.5))/100; }
//function char2width_(chr) { return (((chr * MDW + 5)/MDW*256))/256; }
function px2char_(px) { return (((px - 5)/MDW * 100 + 0.5))/100; }
function char2width_(chr) { return (((chr * MDW + 5)/MDW*256))/256; }
function cycle_width(collw) { return char2width(px2char(width2px(collw))); }
/* XLSX/XLSB/XLS specify width in units of MDW */
function find_mdw_colw(collw) {
@ -65,7 +65,7 @@ function find_mdw_colw(collw) {
MDW = _MDW;
}
/* XLML specifies width in terms of pixels */
/*function find_mdw_wpx(wpx) {
function find_mdw_wpx(wpx) {
var delta = Infinity, guess = 0, _MDW = MIN_MDW;
for(MDW=MIN_MDW; MDW<MAX_MDW; ++MDW) {
guess = char2width_(px2char_(wpx))*256;
@ -74,7 +74,7 @@ function find_mdw_colw(collw) {
if(Math.abs(guess) < delta) { delta = Math.abs(guess); _MDW = MDW; }
}
MDW = _MDW;
}*/
}
function process_col(coll/*:ColInfo*/) {
if(coll.width) {

View File

@ -1,18 +1,17 @@
/* 18.8.5 borders CT_Borders */
function parse_borders(t, styles, themes, opts) {
styles.Borders = [];
var border = {};
var pass = false;
(t.match(tagregex)||[]).forEach(function(x) {
var border = {}, sub_border = {};
t[0].match(tagregex).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
switch (y[0]) {
case '<borders': case '<borders>': case '</borders>': break;
/* 18.8.4 border CT_Border */
case '<border': case '<border>': case '<border/>':
border = /*::(*/{}/*:: :any)*/;
if(y.diagonalUp) border.diagonalUp = parsexmlbool(y.diagonalUp);
if(y.diagonalDown) border.diagonalDown = parsexmlbool(y.diagonalDown);
border = {};
if (y.diagonalUp) { border.diagonalUp = y.diagonalUp; }
if (y.diagonalDown) { border.diagonalDown = y.diagonalDown; }
styles.Borders.push(border);
break;
case '</border>': break;
@ -58,17 +57,10 @@ function parse_borders(t, styles, themes, opts) {
case '</end>': break;
/* 18.8.? color CT_Color */
case '<color': case '<color>':
break;
case '<color': case '<color>': break;
case '<color/>': case '</color>': break;
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': break;
case '<ext': pass = true; break;
case '</ext>': pass = false; break;
default: if(opts && opts.WTF) {
if(!pass) throw new Error('unrecognized ' + y[0] + ' in borders');
}
default: if(opts && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in borders');
}
});
}
@ -77,10 +69,9 @@ function parse_borders(t, styles, themes, opts) {
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])) {
switch(y[0]) {
case '<fills': case '<fills>': case '</fills>': break;
/* 18.8.20 fill CT_Fill */
@ -116,7 +107,7 @@ function parse_fills(t, styles, themes, opts) {
if(y.theme) fill.fgColor.theme = parseInt(y.theme, 10);
if(y.tint) fill.fgColor.tint = parseFloat(y.tint);
/* Excel uses ARGB strings */
if(y.rgb != null) fill.fgColor.rgb = y.rgb.slice(-6);
if(y.rgb) fill.fgColor.rgb = y.rgb.slice(-6);
break;
case '<fgColor/>': case '</fgColor>': break;
@ -128,13 +119,7 @@ function parse_fills(t, styles, themes, opts) {
case '<color': case '<color/>': break;
case '</color>': break;
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': break;
case '<ext': pass = true; break;
case '</ext>': pass = false; break;
default: if(opts && opts.WTF) {
if(!pass) throw new Error('unrecognized ' + y[0] + ' in fills');
}
default: if(opts && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fills');
}
});
}
@ -143,10 +128,9 @@ function parse_fills(t, styles, themes, opts) {
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])) {
switch (y[0]) {
case '<fonts': case '<fonts>': case '</fonts>': break;
/* 18.8.22 font CT_Font */
@ -157,7 +141,7 @@ function parse_fonts(t, styles, themes, opts) {
break;
/* 18.8.29 name CT_FontName */
case '<name': if(y.val) font.name = utf8read(y.val); break;
case '<name': if(y.val) font.name = y.val; break;
case '<name/>': case '</name>': break;
/* 18.8.2 b CT_BooleanProperty */
@ -231,7 +215,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);
@ -244,17 +228,7 @@ function parse_fonts(t, styles, themes, opts) {
break;
case '<color/>': case '</color>': break;
/* note: sometimes mc:AlternateContent appears bare */
case '<AlternateContent': pass = true; break;
case '</AlternateContent>': pass = false; break;
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': break;
case '<ext': pass = true; break;
case '</ext>': pass = false; break;
default: if(opts && opts.WTF) {
if(!pass) throw new Error('unrecognized ' + y[0] + ' in fonts');
}
default: if(opts && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fonts');
}
});
}
@ -262,13 +236,13 @@ 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]);
switch(strip_ns(y[0])) {
switch(y[0]) {
case '<numFmts': case '</numFmts>': case '<numFmts/>': case '<numFmts>': break;
case '<numFmt': {
var f=unescapexml(utf8read(y.formatCode)), j=parseInt(y.numFmtId,10);
@ -278,7 +252,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;
@ -287,7 +261,7 @@ function parse_numFmts(t, styles, opts) {
}
}
function write_numFmts(NF/*:{[n:number|string]:string}*//*::, opts*/) {
function write_numFmts(NF/*:{[n:number|string]:string}*/, opts) {
var o = ["<numFmts>"];
[[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) o[o.length] = (writextag('numFmt',null,{numFmtId:i,formatCode:escapexml(NF[i])}));
@ -304,64 +278,52 @@ var cellXF_bool = [ "applyAlignment", "applyBorder", "applyFill", "applyFont", "
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])) {
switch(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) {
xf[cellXF_bool[i]] = parsexmlbool(xf[cellXF_bool[i]], "");
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;
if(y.textRotation != null) alignment.textRotation = y.textRotation;
if(y.indent) alignment.indent = y.indent;
if(y.wrapText) alignment.wrapText = parsexmlbool(y.wrapText);
if(y.wrapText) alignment.wrapText = y.wrapText;
xf.alignment = alignment;
break;
case '</alignment>': break;
/* 18.8.33 protection CT_CellProtection */
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 = false; break;
case '<protection': case '</protection>': case '<protection/>': break;
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': break;
case '<ext': pass = true; break;
case '</ext>': pass = false; break;
default: if(opts && opts.WTF) {
if(!pass) throw new Error('unrecognized ' + y[0] + ' in cellXfs');
}
case '<extLst': case '</extLst>': break;
case '<ext': break;
default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in cellXfs');
}
});
}
function write_cellXfs(cellXfs)/*:string*/ {
var o/*:Array<string>*/ = [];
var o = [];
o[o.length] = (writextag('cellXfs',null));
cellXfs.forEach(function(c) {
o[o.length] = (writextag('xf', null, c));
});
cellXfs.forEach(function(c) { o[o.length] = (writextag('xf', null, c)); });
o[o.length] = ("</cellXfs>");
if(o.length === 2) return "";
o[0] = writextag('cellXfs',null, {count:o.length-2}).replace("/>",">");
@ -369,33 +331,38 @@ 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 = /<numFmts([^>]*)>[\S\s]*?<\/numFmts>/;
var cellXfRegex = /<cellXfs([^>]*)>[\S\s]*?<\/cellXfs>/;
var fillsRegex = /<fills([^>]*)>[\S\s]*?<\/fills>/;
var fontsRegex = /<fonts([^>]*)>[\S\s]*?<\/fonts>/;
var bordersRegex = /<borders([^>]*)>[\S\s]*?<\/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.8 cellStyles CT_CellStyles ? */
/* 18.8.15 dxfs CT_Dxfs ? */
/* 18.8.42 tableStyles CT_TableStyles ? */
/* 18.8.11 colors CT_Colors ? */
@ -405,11 +372,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>');

View File

@ -1,4 +1,4 @@
/* [MS-XLSB] 2.4.657 BrtFmt */
/* [MS-XLSB] 2.4.651 BrtFmt */
function parse_BrtFmt(data, length/*:number*/) {
var numFmtId = data.read_shift(2);
var stFmtCode = parse_XLWideString(data,length-2);
@ -8,24 +8,22 @@ function write_BrtFmt(i/*:number*/, f/*:string*/, o) {
if(!o) o = new_buf(6 + 4 * f.length);
o.write_shift(2, i);
write_XLWideString(f, o);
var out = (o.length > o.l) ? o.slice(0, o.l) : o;
if(o.l == null) o.l = o.length;
return out;
return o.length > o.l ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.659 BrtFont TODO */
/* [MS-XLSB] 2.4.653 BrtFont TODO */
function parse_BrtFont(data, length/*:number*/, opts) {
var out = ({}/*:any*/);
out.sz = data.read_shift(2) / 20;
var grbit = parse_FontFlags(data, 2, opts);
if(grbit.fItalic) out.italic = 1;
if(grbit.fCondense) out.condense = 1;
if(grbit.fExtend) out.extend = 1;
if(grbit.fShadow) out.shadow = 1;
if(grbit.fOutline) out.outline = 1;
if(grbit.fStrikeout) out.strike = 1;
if(grbit.fItalic) out.italic = 1;
var bls = data.read_shift(2);
if(bls === 0x02BC) out.bold = 1;
@ -58,7 +56,7 @@ function parse_BrtFont(data, length/*:number*/, opts) {
return out;
}
function write_BrtFont(font/*:any*/, o) {
function write_BrtFont(font, o) {
if(!o) o = new_buf(25+4*32);
o.write_shift(2, font.sz * 20);
write_FontFlags(font, o);
@ -80,7 +78,7 @@ function write_BrtFont(font/*:any*/, o) {
return o.length > o.l ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.650 BrtFill */
/* [MS-XLSB] 2.4.644 BrtFill */
var XLSBFillPTNames = [
"none",
"solid",
@ -102,12 +100,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);
@ -135,12 +132,11 @@ function write_BrtFill(fill, o) {
return o.length > o.l ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.824 BrtXF */
/* [MS-XLSB] 2.4.816 BrtXF */
function parse_BrtXF(data, length/*:number*/) {
var tgt = data.l + length;
var ixfeParent = data.read_shift(2);
var ifmt = data.read_shift(2);
data.l = tgt;
parsenoop(data, length-4);
return {ixfe:ixfeParent, numFmtId:ifmt };
}
function write_BrtXF(data, ixfeP, o) {
@ -152,8 +148,7 @@ function write_BrtXF(data, ixfeP, o) {
o.write_shift(2, 0); /* ixBorder */
o.write_shift(1, 0); /* trot */
o.write_shift(1, 0); /* indent */
var flow = 0;
o.write_shift(1, flow); /* flags */
o.write_shift(1, 0); /* flags */
o.write_shift(1, 0); /* flags */
o.write_shift(1, 0); /* xfGrbitAtr */
o.write_shift(1, 0);
@ -169,7 +164,7 @@ function write_Blxf(data, o) {
o.write_shift(4, 0); /* color */
return o;
}
/* [MS-XLSB] 2.4.302 BrtBorder TODO */
/* [MS-XLSB] 2.4.299 BrtBorder TODO */
var parse_BrtBorder = parsenoop;
function write_BrtBorder(border, o) {
if(!o) o = new_buf(51);
@ -182,7 +177,7 @@ function write_BrtBorder(border, o) {
return o.length > o.l ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.763 BrtStyle TODO */
/* [MS-XLSB] 2.4.755 BrtStyle TODO */
function write_BrtStyle(style, o) {
if(!o) o = new_buf(12+4*10);
o.write_shift(4, style.xfId);
@ -193,7 +188,7 @@ function write_BrtStyle(style, o) {
return o.length > o.l ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.272 BrtBeginTableStyles */
/* [MS-XLSB] 2.4.269 BrtBeginTableStyles */
function write_BrtBeginTableStyles(cnt, defTableStyle, defPivotStyle) {
var o = new_buf(4+256*2*4);
o.write_shift(4, cnt);
@ -206,60 +201,58 @@ 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 state = [];
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 */
break;
case 0x002E: /* BrtBorder */
break;
case 0x002F: /* BrtXF */
if(state[state.length - 1] == 0x0269 /* BrtBeginCellXFs */) {
case 0x0401: /* 'BrtKnownFonts' */ break;
case 0x002D: /* 'BrtFill' */ break;
case 0x002E: /* 'BrtBorder' */ break;
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 '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 */
state.pop(); pass = false; break;
case 0x0025: /* 'BrtACBegin' */
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 && 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) throw new Error("Unexpected record " + RT + " " + R_n);
}
});
return styles;
@ -274,20 +267,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*/) {
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,80 +288,80 @@ 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*/) {
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*/) {
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*/) {
function write_CELLSTYLEXFS_bin(ba, data) {
var cnt = 1;
write_record(ba, 0x0272 /* BrtBeginCellStyleXFs */, write_UInt32LE(cnt));
write_record(ba, 0x002F /* BrtXF */, write_BrtXF({
numFmtId: 0,
fontId: 0,
fillId: 0,
borderId: 0
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*/) {
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(1));
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*/) {
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*/) {
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*/) {
function write_COLORPALETTE_bin(ba, data) {
return;
/* BrtBeginColorPalette [INDEXEDCOLORS] [MRUCOLORS] BrtEndColorPalette */
}
@ -376,7 +369,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 +381,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();
}

View File

@ -1,10 +1,5 @@
/* 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>',
'</a:accent1>', '</a:accent2>', '</a:accent3>',
'</a:accent4>', '</a:accent5>', '</a:accent6>',
'</a:hlink>', '</a:folHlink>'
];
RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
/* 20.1.6.2 clrScheme CT_ColorScheme */
function parse_clrScheme(t, themes, opts) {
themes.themeElements.clrScheme = [];
@ -18,12 +13,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 +30,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>':
@ -52,10 +43,10 @@ function parse_clrScheme(t, themes, opts) {
case '<a:hlink>': case '</a:hlink>':
case '<a:folHlink>': case '</a:folHlink>':
if (y[0].charAt(1) === '/') {
themes.themeElements.clrScheme[XLSXThemeClrScheme.indexOf(y[0])] = color;
themes.themeElements.clrScheme.push(color);
color = {};
} else {
color.name = y[0].slice(3, y[0].length - 1);
color.name = y[0].substring(3, y[0].length - 1);
}
break;
@ -65,10 +56,14 @@ function parse_clrScheme(t, themes, opts) {
}
/* 20.1.4.1.18 fontScheme CT_FontScheme */
function parse_fontScheme(/*::t, themes, opts*/) { }
function parse_fontScheme(t, themes, opts) { }
/* 20.1.4.1.15 fmtScheme CT_StyleMatrix */
function parse_fmtScheme(/*::t, themes, opts*/) { }
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) {
@ -76,37 +71,38 @@ function parse_themeElements(data, themes, opts) {
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;
}
function write_theme(Themes, opts)/*:string*/ {
if(opts && opts.themeXLSX) return opts.themeXLSX;
if(Themes && typeof Themes.raw == "string") return Themes.raw;
var o = [XML_HEADER];
o[o.length] = '<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">';
o[o.length] = '<a:themeElements>';

View File

@ -1,22 +1,15 @@
/* [MS-XLS] 2.4.326 TODO: payload is a zip file */
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; }
var data = blob.slice(blob.l);
blob.l = end;
var zip; try { zip = zip_read(data, {type: "array"}); } catch(e) { return; }
var themeXML = getzipstr(zip, "theme/theme/theme1.xml", true);
if(!themeXML) return;
return parse_theme_xml(themeXML, opts);
blob.l += length-4;
}
/* 2.5.49 */
function parse_ColorTheme(blob/*::, length*/) { return blob.read_shift(4); }
function parse_ColorTheme(blob, length) { return blob.read_shift(4); }
/* 2.5.155 */
function parse_FullColorExt(blob/*::, length*/) {
function parse_FullColorExt(blob, length) {
var o = {};
o.xclrType = blob.read_shift(2);
o.nTintShade = blob.read_shift(2);
@ -41,17 +34,17 @@ function parse_XFExtGradient(blob, length) {
return parsenoop(blob, length);
}
/* [MS-XLS] 2.5.108 */
function parse_ExtProp(blob/*::, length*/)/*:Array<any>*/ {
/* 2.5.108 */
function parse_ExtProp(blob, length) {
var extType = blob.read_shift(2);
var cb = blob.read_shift(2) - 4;
var cb = blob.read_shift(2);
var o = [extType];
switch(extType) {
case 0x04: case 0x05: case 0x07: case 0x08:
case 0x09: case 0x0A: case 0x0B: case 0x0D:
o[1] = parse_FullColorExt(blob, cb); break;
case 0x06: o[1] = parse_XFExtGradient(blob, cb); break;
case 0x0E: case 0x0F: o[1] = blob.read_shift(cb === 1 ? 1 : 2); break;
case 0x0E: case 0x0F: o[1] = blob.read_shift(cb === 5 ? 1 : 2); break;
default: throw new Error("Unrecognized ExtProp type: " + extType + " " + cb);
}
return o;
@ -64,7 +57,7 @@ function parse_XFExt(blob, length) {
var ixfe = blob.read_shift(2);
blob.l += 2;
var cexts = blob.read_shift(2);
var ext/*:AOA*/ = [];
var ext = [];
while(cexts-- > 0) ext.push(parse_ExtProp(blob, end-blob.l));
return {ixfe:ixfe, ext:ext};
}
@ -81,8 +74,7 @@ function update_xfext(xf, xfext) {
case 0x09: break; /* left cell border color */
case 0x0a: break; /* right cell border color */
case 0x0b: break; /* diagonal cell border color */
case 0x0d: /* text color */
break;
case 0x0d: break; /* text color */
case 0x0e: break; /* font scheme */
case 0x0f: break; /* indentation level */
}

View File

@ -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();
}

View File

@ -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("");
}

View File

@ -1,8 +1,8 @@
/* 18.6 Calculation Chain */
function parse_cc_xml(data/*::, name, opts*/)/*:Array<any>*/ {
function parse_cc_xml(data, name, opts) {
var d = [];
if(!data) return d;
var i = 1;
var l = 0, i = 1;
(data.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(y[0]) {
@ -16,10 +16,10 @@ function parse_cc_xml(data/*::, name, opts*/)/*:Array<any>*/ {
return d;
}
//function write_cc_xml(data, opts) { }
function write_cc_xml(data, opts) { }
/* [MS-XLSB] 2.6.4.1 */
function parse_BrtCalcChainItem$(data) {
function parse_BrtCalcChainItem$(data, length) {
var out = {};
out.i = data.read_shift(4);
var cell = {};
@ -36,17 +36,18 @@ 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;
}
//function write_cc_bin(data, opts) { }
function write_cc_bin(data, opts) { }

View File

@ -1,17 +1,17 @@
/* 18.14 Supplementary Workbook Data */
function parse_xlink_xml(/*::data, rel, name:string, _opts*/) {
//var opts = _opts || {};
function parse_xlink_xml(data, name/*:string*/, _opts) {
var opts = _opts || {};
//if(opts.WTF) throw "XLSX External Link";
}
/* [MS-XLSB] 2.1.7.25 External Link */
function parse_xlink_bin(data, rel, name/*:string*/, _opts) {
function parse_xlink_bin(data, name/*:string*/, _opts) {
if(!data) return data;
var opts = _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);
}

View File

@ -1,5 +1,6 @@
RELS.IMG = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
RELS.DRAW = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing";
/* 20.5 DrawingML - SpreadsheetML Drawing */
/* 20.5.2.35 wsDr CT_Drawing */
function parse_drawing(data, rels/*:any*/) {
if(!data) return "??";
/*
@ -13,7 +14,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;
}

View File

@ -1,94 +1,44 @@
/* 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, 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*/ {
var c = decode_cell(x[0]);
var fillopts = /*::(*/{'color2':"#BEFF82", 'type':"gradient"}/*:: :any)*/;
if(fillopts.type == "gradient") fillopts.angle = "-180";
var fillparm = fillopts.type == "gradient" ? writextag("o:fill", null, {type:"gradientUnscaled", 'v:ext':"view"}) : null;
var fillxml = writextag('v:fill', fillparm, fillopts);
var shadata = ({on:"t", 'obscured':"t"}/*:any*/);
return [
comments.map(function(x) { return decode_cell(x[0]); }).forEach(function(c,i) { o = o.concat([
'<v:shape' + wxt_helper({
id:'_x0000_s' + _shapeid,
id:'_x0000_s' + (++_shapeid),
type:"#_x0000_t202",
style:"position:absolute; margin-left:80pt;margin-top:5pt;width:104pt;height:64pt;z-index:10" + (x[1].hidden ? ";visibility:hidden" : "") ,
style:"position:absolute; margin-left:80pt;margin-top:5pt;width:104pt;height:64pt;z-index:10;visibility:hidden",
fillcolor:"#ECFAD4",
strokecolor:"#edeaa1"
}) + '>',
fillxml,
writextag("v:shadow", null, shadata),
writextag('v:fill', writextag("o:fill", null, {type:"gradientUnscaled", 'v:ext':"view"}), {'color2':"#BEFF82", 'angle':"-180", 'type':"gradient"}),
writextag("v:shadow", null, {on:"t", 'obscured':"t"}),
writextag("v:path", null, {'o:connecttype':"none"}),
'<v:textbox><div style="text-align:left"></div></v:textbox>',
'<x:ClientData ObjectType="Note">',
'<x:MoveWithCells/>',
'<x:SizeWithCells/>',
/* Part 4 19.4.2.3 Anchor (Anchor) */
writetag('x:Anchor', [c.c+1, 0, c.r+1, 0, c.c+3, 20, c.r+5, 20].join(",")),
writetag('x:Anchor', [c.c, 0, c.r, 0, c.c+3, 100, c.r+5, 100].join(",")),
writetag('x:AutoFill', "False"),
writetag('x:Row', String(c.r)),
writetag('x:Column', String(c.c)),
x[1].hidden ? '' : '<x:Visible/>',
'<x:Visible/>',
'</x:ClientData>',
'</v:shape>'
].join("");
]); });
o.push('</xml>');
return o.join("");
}

View File

@ -1,38 +1,50 @@
function sheet_insert_comments(sheet/*:WorkSheet*/, comments/*:Array<RawComment>*/, threaded/*:boolean*/, people/*:?Array<any>*/) {
var dense = sheet["!data"] != null;
var cell/*:Cell*/;
RELS.CMNT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
function parse_comments(zip, dirComments, sheets, sheetRels, opts) {
for(var i = 0; i != dirComments.length; ++i) {
var canonicalpath=dirComments[i];
var comments=parse_cmnt(getzipdata(zip, canonicalpath.replace(/^\//,''), true), canonicalpath, opts);
if(!comments || !comments.length) continue;
// find the sheets targeted by these comments
var sheetNames = keys(sheets);
for(var j = 0; j != sheetNames.length; ++j) {
var sheetName = sheetNames[j];
var rels = sheetRels[sheetName];
if(rels) {
var rel = rels[canonicalpath];
if(rel) insertCommentsIntoSheet(sheetName, sheets[sheetName], comments);
}
}
}
}
function insertCommentsIntoSheet(sheetName, sheet, comments) {
var dense = Array.isArray(sheet);
var cell, r;
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];
r = decode_cell(comment.ref);
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;
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;
if(range.e.r < r.r) range.e.r = r.r;
if(range.s.c > r.c) range.s.c = r.c;
if(range.e.c < r.c) range.e.c = r.c;
var thisCell = decode_cell(comment.ref);
if(range.s.r > thisCell.r) range.s.r = thisCell.r;
if(range.e.r < thisCell.r) range.e.r = thisCell.r;
if(range.s.c > thisCell.c) range.s.c = thisCell.c;
if(range.e.c < thisCell.c) range.e.c = thisCell.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 = ({a: comment.author, t: comment.t, r: comment.r}/*:any*/);
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);
});
}

View File

@ -1,186 +1,59 @@
/* 18.7 Comments */
function parse_comments_xml(data/*:string*/, opts)/*:Array<RawComment>*/ {
function parse_comments_xml(data/*:string*/, opts)/*:Array<Comment>*/ {
/* 18.7.6 CT_Comments */
if(data.match(/<(?:\w+:)?comments *\/>/)) return [];
var authors/*:Array<string>*/ = [];
var commentList/*:Array<RawComment>*/ = [];
var authtag = str_match_xml_ns(data, "authors");
var authors = [];
var commentList = [];
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");
if(cmnttag && cmnttag[1]) cmnttag[1].split(/<\/\w*:?comment>/).forEach(function(x) {
var cmnttag = data.match(/<(?:\w+:)?commentList>([\s\S]*)<\/(?:\w+:)?commentList>/);
if(cmnttag && cmnttag[1]) cmnttag[1].split(/<\/\w*:?comment>/).forEach(function(x, index) {
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 comment/*:Comment*/ = ({ 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;
}
function write_comments_xml(data/*::, opts*/) {
var o = [XML_HEADER, writextag('comments', null, { 'xmlns': XMLNS_main[0] })];
var CMNT_XML_ROOT = writextag('comments', null, { 'xmlns': XMLNS.main[0] });
function write_comments_xml(data, opts) {
var o = [XML_HEADER, CMNT_XML_ROOT];
var iauthor/*:Array<string>*/ = [];
var iauthor = [];
o.push("<authors>");
data.forEach(function(x) { x[1].forEach(function(w) { var a = escapexml(w.a);
if(iauthor.indexOf(a) == -1) {
data.map(function(x) { return x[1]; }).forEach(function(comment) {
comment.map(function(x) { return escapexml(x.a); }).forEach(function(a) {
if(iauthor.indexOf(a) > -1) return;
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.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 ? "" : 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("");
}

View File

@ -1,5 +1,5 @@
/* [MS-XLSB] 2.4.28 BrtBeginComment */
function parse_BrtBeginComment(data) {
function parse_BrtBeginComment(data, length/*:number*/) {
var out = {};
out.iauthor = data.read_shift(4);
var rfx = parse_UncheckedRfX(data, 16);
@ -19,17 +19,17 @@ function write_BrtBeginComment(data, o) {
return o;
}
/* [MS-XLSB] 2.4.327 BrtCommentAuthor */
/* [MS-XLSB] 2.4.324 BrtCommentAuthor */
var parse_BrtCommentAuthor = parse_XLWideString;
function write_BrtCommentAuthor(data) { return write_XLWideString(data.slice(0, 54)); }
/* [MS-XLSB] 2.1.7.8 Comments */
function parse_comments_bin(data, opts)/*:Array<RawComment>*/ {
var out/*:Array<RawComment>*/ = [];
var authors/*:Array<string>*/ = [];
function parse_comments_bin(data, opts) {
var out = [];
var authors = [];
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;
@ -39,13 +39,12 @@ function parse_comments_bin(data, opts)/*:Array<RawComment>*/ {
c.t = val.t; c.h = val.h; c.r = val.r; break;
case 0x027C: /* 'BrtEndComment' */
c.author = authors[c.iauthor];
delete (c/*:any*/).iauthor;
if(opts.sheetRows && c.rfx && opts.sheetRows <= c.rfx.r) break;
delete c.iauthor;
if(opts.sheetRows && opts.sheetRows <= c.rfx.r) break;
if(!c.t) c.t = "";
delete c.rfx; out.push(c); break;
case 0x0C00: /* 'BrtUid' */
break;
/* case 'BrtUid': */
case 0x0023: /* 'BrtFRTBegin' */
pass = true; break;
@ -56,49 +55,43 @@ 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;
}
function write_comments_bin(data/*::, opts*/) {
function write_comments_bin(data, opts) {
var ba = buf_array();
var iauthor/*:Array<string>*/ = [];
write_record(ba, 0x0274 /* BrtBeginComments */);
write_record(ba, 0x0276 /* 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));
}
var iauthor = [];
write_record(ba, "BrtBeginComments");
{ /* COMMENTAUTHORS */
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, "BrtCommentAuthor", write_BrtCommentAuthor(c.a));
});
});
});
write_record(ba, 0x0277 /* BrtEndCommentAuthors */);
write_record(ba, 0x0279 /* 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;
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 */);
delete c.iauthor;
write_record(ba, "BrtEndCommentAuthors");
}
{ /* COMMENTLIST */
write_record(ba, "BrtBeginCommentList");
data.forEach(function(comment) {
comment[1].forEach(function(c) {
c.iauthor = iauthor.indexOf(c.a);
var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])};
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, 0x0275 /* BrtEndComments */);
write_record(ba, "BrtEndCommentList");
}
write_record(ba, "BrtEndComments");
return ba.end();
}

View File

@ -1,21 +1,18 @@
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"];

View File

@ -1,5 +1,8 @@
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'}; }
function parse_ms_bin(/*::data:any, opts, idx:number, rels, wb, themes, styles*/)/*:Worksheet*/ { return {'!type':'macro'}; }
function parse_ms_xml(/*::data:any, opts, idx:number, rels, wb, themes, styles*/)/*:Worksheet*/ { return {'!type':'macro'}; }
function parse_ds_bin(data/*:any*/, opts, rels, wb, themes, styles)/*:Worksheet*/ { return {'!type':'dialog'}; }
function parse_ds_xml(data/*:any*/, opts, rels, wb, themes, styles)/*:Worksheet*/ { return {'!type':'dialog'}; }
function parse_ms_bin(data/*:any*/, opts, rels, wb, themes, styles)/*:Worksheet*/ { return {'!type':'macro'}; }
function parse_ms_xml(data/*:any*/, opts, rels, wb, themes, styles)/*:Worksheet*/ { return {'!type':'macro'}; }

View File

@ -1,20 +1,13 @@
/* TODO: it will be useful to parse the function str */
var rc_to_a1 = /*#__PURE__*/(function(){
var rcregex = /(^|[^A-Za-z_])R(\[?-?\d+\]|[1-9]\d*|)C(\[?-?\d+\]|[1-9]\d*|)(?![A-Za-z0-9_])/g;
var rc_to_a1 = (function(){
var rcregex = /(^|[^A-Za-z])R(\[?)(-?\d+|)\]?C(\[?)(-?\d+|)\]?/g;
var rcbase/*:Cell*/ = ({r:0,c:0}/*:any*/);
function rcfunc($$,$1,$2,$3) {
function rcfunc($$,$1,$2,$3,$4,$5) {
var R = $3.length>0?parseInt($3,10)|0:0, C = $5.length>0?parseInt($5,10)|0:0;
if(C<0 && $4.length === 0) C=0;
var cRel = false, rRel = false;
if($2.length == 0) rRel = true;
else if($2.charAt(0) == "[") { rRel = true; $2 = $2.slice(1, -1); }
if($3.length == 0) cRel = true;
else if($3.charAt(0) == "[") { cRel = true; $3 = $3.slice(1, -1); }
var R = $2.length>0?parseInt($2,10)|0:0, C = $3.length>0?parseInt($3,10)|0:0;
if(cRel) C += rcbase.c; else --C;
if(rRel) R += rcbase.r; else --R;
if($4.length > 0 || $5.length == 0) cRel = true; if(cRel) C += rcbase.c; else --C;
if($2.length > 0 || $3.length == 0) rRel = true; if(rRel) R += rcbase.r; else --R;
return $1 + (cRel ? "" : "$") + encode_col(C) + (rRel ? "" : "$") + encode_row(R);
}
return function rc_to_a1(fstr/*:string*/, base/*:Cell*/)/*:string*/ {
@ -23,25 +16,21 @@ 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(){
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 + "]");
return $1 + "R" + R + "C" + C;
var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)([1-9]\d{0,5}|10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6])(?![_.\(A-Za-z0-9])/g;
var a1_to_rc =(function(){
return function a1_to_rc(fstr, base) {
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
/* TODO: handle fixcol / fixrow */
var c = decode_col($3) - base.c;
var r = decode_row($5) - base.r;
return $1 + "R" + (r == 0 ? "" : "[" + r + "]") + "C" + (c == 0 ? "" : "[" + c + "]");
});
};
})();
/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
function shift_formula_str(f/*:string*/, delta/*:Cell*/)/*:string*/ {
return f.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
return f.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
});
}
@ -57,7 +46,3 @@ function fuzzyfmla(f/*:string*/)/*:boolean*/ {
if(f.length == 1) return false;
return true;
}
function _xlfn(f/*:string*/)/*:string*/ {
return f.replace(/_xlfn\./g,"");
}

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,10 @@
/* [MS-XLS] 2.5.198.1 TODO */
function parse_ArrayParsedFormula(blob, length, opts/*::, ref*/) {
function parse_ArrayParsedFormula(blob, length, opts, ref) {
var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
var rgcb, cce = blob.read_shift(len); // length of rgce
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
var rgce = parse_Rgce(blob, cce, opts);
if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
blob.l = target;
return [rgce, rgcb];
}
@ -16,7 +15,6 @@ function parse_XLSCellParsedFormula(blob, length, opts) {
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
var rgce = parse_Rgce(blob, cce, opts);
if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
blob.l = target;
return [rgce, rgcb];
}
@ -51,59 +49,27 @@ function parse_FormulaValue(blob/*::, length*/) {
}
return [];
}
function write_FormulaValue(value) {
if(value == null) {
// Blank String Value
var o = new_buf(8);
o.write_shift(1, 0x03);
o.write_shift(1, 0);
o.write_shift(2, 0);
o.write_shift(2, 0);
o.write_shift(2, 0xFFFF);
return o;
} else if(typeof value == "number") return write_Xnum(value);
return write_Xnum(0);
}
/* [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) {
blob.read_shift(1);
if(opts.biff >= 5) {
/*var chn = */blob.read_shift(4);
var chn = blob.read_shift(4);
}
}
var cbf = parse_XLSCellParsedFormula(blob, end - blob.l, opts);
return {cell:cell, val:val[0], formula:cbf, shared: (flags >> 3) & 1, tt:val[1]};
}
function write_Formula(cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, os/*:number*/) {
// Cell
var o1 = write_XLSCell(R, C, os);
// FormulaValue
var o2 = write_FormulaValue(cell.v);
// flags + cache
var o3 = new_buf(6);
var flags = 0x01 | 0x20;
o3.write_shift(2, flags);
o3.write_shift(4, 0);
// CellParsedFormula
var bf = new_buf(cell.bf.length);
for(var i = 0; i < cell.bf.length; ++i) bf[i] = cell.bf[i];
var out = bconcat([o1, o2, o3, bf]);
return out;
}
/* XLSB Parsed Formula records have the same shape */
function parse_XLSBParsedFormula(data, length, opts) {
var end = data.l + length;
var cce = data.read_shift(4);
var rgce = parse_Rgce(data, cce, opts);
var cb = data.read_shift(4);
@ -115,217 +81,7 @@ function parse_XLSBParsedFormula(data, length, opts) {
var parse_XLSBArrayParsedFormula = parse_XLSBParsedFormula;
/* [MS-XLSB] 2.5.97.4 CellParsedFormula */
var parse_XLSBCellParsedFormula = parse_XLSBParsedFormula;
/* [MS-XLSB] 2.5.97.8 DVParsedFormula */
//var parse_XLSBDVParsedFormula = parse_XLSBParsedFormula;
/* [MS-XLSB] 2.5.97.9 FRTParsedFormula */
//var parse_XLSBFRTParsedFormula = parse_XLSBParsedFormula2;
/* [MS-XLSB] 2.5.97.12 NameParsedFormula */
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

View File

@ -1,16 +1,14 @@
/* Part 3 TODO: actually parse formulae */
function ods_to_csf_formula(f/*:string*/)/*:string*/ {
if(f.slice(0,3) == "of:") f = f.slice(3);
if(f.substr(0,3) == "of:") f = f.substr(3);
/* 5.2 Basic Expressions */
if(f.charCodeAt(0) == 61) {
f = f.slice(1);
if(f.charCodeAt(0) == 61) f = f.slice(1);
f = f.substr(1);
if(f.charCodeAt(0) == 61) f = f.substr(1);
}
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,";");
@ -22,15 +20,8 @@ function csf_to_ods_formula(f/*:string*/)/*:string*/ {
return o.replace(/;/g, "|").replace(/,/g,";");
}
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; });
function ods_to_csf_range_3D(r/*:string*/)/*:[string, string]*/ {
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])) : "")];
return [s, a[0].split(".")[1] + ":" + a[1].split(".")[1]];
}
function csf_to_ods_3D(r/*:string*/)/*:string*/ {
return r.replace(/!/,".").replace(/:/, ":.");
}

View File

@ -1,33 +1,14 @@
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';
function get_sst_id(sst/*:SST*/, str/*:string*/, rev)/*:number*/ {
var i = 0, len = sst.length;
if(rev) {
if(browser_has_Map ? rev.has(str) : Object.prototype.hasOwnProperty.call(rev, str)) {
var revarr = browser_has_Map ? rev.get(str) : rev[str];
for(; i < revarr.length; ++i) {
if(sst[revarr[i]].t === str) { sst.Count ++; return revarr[i]; }
}
}
} else for(; i < len; ++i) {
if(sst[i].t === str) { sst.Count ++; return i; }
}
sst[len] = ({t:str}/*:any*/); sst.Count ++; sst.Unique ++;
if(rev) {
if(browser_has_Map) {
if(!rev.has(str)) rev.set(str, []);
rev.get(str).push(len);
} else {
if(!Object.prototype.hasOwnProperty.call(rev, str)) rev[str] = [];
rev[str].push(len);
}
}
return len;
function get_sst_id(sst/*:SST*/, str/*:string*/)/*:number*/ {
for(var i = 0, len = sst.length; i < len; ++i) if(sst[i].t === str) { sst.Count ++; return i; }
sst[len] = {t:str}; sst.Count ++; sst.Unique ++; return len;
}
function col_obj_w(C/*:number*/, col) {
@ -41,7 +22,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;
}
@ -57,13 +37,12 @@ function default_margins(margins/*:Margins*/, mode/*:?string*/) {
if(margins.footer == null) margins.footer = defs[5];
}
function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) {
function get_cell_style(styles, cell, opts) {
var z = opts.revssf[cell.z != null ? cell.z : "General"];
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);
// $FlowIgnore
SSF.load(cell.z, i);
opts.ssf[i] = cell.z;
opts.revssf[cell.z] = z = i;
break;
@ -81,30 +60,29 @@ 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) {
try {
if(opts.cellNF) p.z = table_fmt[fmtid];
} catch(e) { if(opts.WTF) throw e; }
if(p.t === 'z' && !opts.cellStyles) return;
function safe_format(p, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) {
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);
try {
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) {
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 {
@ -119,10 +97,3 @@ function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, the
}
} catch(e) { if(opts.WTF && styles.Fills) throw e; }
}
function check_ws(ws/*:Worksheet*/, sname/*:string*/, i/*:number*/) {
if(ws && ws['!ref']) {
var range = safe_decode_range(ws['!ref']);
if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
}
}

View File

@ -1,50 +1,40 @@
function parse_ws_xml_dim(ws/*:Worksheet*/, s/*:string*/) {
function parse_ws_xml_dim(ws, s) {
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[^>]*[\/]?>/g;
var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g;
/* 18.3 Worksheets */
function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ {
function parse_ws_xml(data/*:?string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(!data) return data;
if(!rels) rels = {'!id':{}};
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);
data1 = data.substr(0, mtch.index);
data2 = data.substr(mtch.index + mtch[0].length);
} else data1 = data2 = data;
/* 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 */
/* 18.3.1.35 dimension CT_SheetDimension ? */
// $FlowIgnore
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]);
var ref = data1.substr(ridx,50).match(dimregex);
if(ref) parse_ws_xml_dim(s, ref[1]);
}
/* 18.3.1.88 sheetViews CT_SheetViews */
var svs = str_match_xml_ns(data1, "sheetViews");
if(svs && svs[1]) parse_ws_xml_sheetviews(svs[1], wb);
/* 18.3.1.17 cols CT_Cols */
var columns/*:Array<ColInfo>*/ = [];
var columns = [];
if(opts.cellStyles) {
/* 18.3.1.13 col CT_Col */
var cols = data1.match(colregex);
@ -52,17 +42,17 @@ 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);
if(afilter) s['!autofilter'] = parse_ws_xml_autofilter(afilter[0]);
/* 18.3.1.55 mergeCells CT_MergeCells */
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("\"")+1));
var mergecells = [];
var merges = data2.match(mergecregex);
if(merges) for(ridx = 0; ridx != merges.length; ++ridx)
mergecells[ridx] = safe_decode_range(merges[ridx].substr(merges[ridx].indexOf("\"")+1));
/* 18.3.1.48 hyperlinks CT_Hyperlinks */
var hlink = data2.match(hlinkregex);
@ -72,15 +62,10 @@ 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"]);
if(opts.sheetRows <= +tmpref.e.r) {
if(opts.sheetRows < +tmpref.e.r) {
tmpref.e.r = opts.sheetRows - 1;
if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
@ -91,88 +76,58 @@ 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']];
if(mergecells.length > 0) s["!merges"] = mergecells;
return s;
}
function write_ws_xml_merges(merges/*:Array<Range>*/)/*:string*/ {
function write_ws_xml_merges(merges) {
if(merges.length === 0) return "";
var o = '<mergeCells count="' + merges.length + '">';
for(var i = 0; i != merges.length; ++i) o += '<mergeCell ref="' + encode_range(merges[i]) + '"/>';
return o + '</mergeCells>';
}
/* 18.3.1.82-3 sheetPr CT_ChartsheetPr / CT_SheetPr */
function parse_ws_xml_sheetpr(sheetPr/*:string*/, s, wb/*:WBWBProps*/, idx/*:number*/) {
var data = parsexmltag(sheetPr);
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;
if(opts.bookType !== 'xlsx' && wb.vbaraw) {
var cname = wb.SheetNames[idx];
try { if(wb.Workbook) cname = wb.Workbook.Sheets[idx].CodeName || cname; } catch(e) {}
needed = true;
props.codeName = utf8write(escapexml(cname));
}
if(ws && ws["!outline"]) {
var outlineprops = {summaryBelow:1, summaryRight:1};
if(ws["!outline"].above) outlineprops.summaryBelow = 0;
if(ws["!outline"].left) outlineprops.summaryRight = 0;
payload = (payload||"") + writextag('outlinePr', null, outlineprops);
}
if(!needed && !payload) return;
o[o.length] = (writextag('sheetPr', payload, props));
}
/* 18.3.1.85 sheetProtection CT_SheetProtection */
var sheetprot_deffalse = ["objects", "scenarios", "selectLockedCells", "selectUnlockedCells"];
var sheetprot_deftrue = [
"formatColumns", "formatRows", "formatCells",
"insertColumns", "insertRows", "insertHyperlinks",
"deleteColumns", "deleteRows",
"sort", "autoFilter", "pivotTables"
];
/* 18.3.1.85 sheetPr CT_SheetProtection */
function write_ws_xml_protection(sp)/*:string*/ {
// algorithmName, hashValue, saltValue, spinCount
// algorithmName, hashValue, saltValue, spinCountpassword
var o = ({sheet:1}/*:any*/);
sheetprot_deffalse.forEach(function(n) { if(sp[n] != null && sp[n]) o[n] = "1"; });
sheetprot_deftrue.forEach(function(n) { if(sp[n] != null && !sp[n]) o[n] = "0"; });
var deffalse = ["objects", "scenarios", "selectLockedCells", "selectUnlockedCells"];
var deftrue = [
"formatColumns", "formatRows", "formatCells",
"insertColumns", "insertRows", "insertHyperlinks",
"deleteColumns", "deleteRows",
"sort", "autoFilter", "pivotTables"
];
deffalse.forEach(function(n) { if(sp[n] != null && sp[n]) o[n] = "1"; });
deftrue.forEach(function(n) { if(sp[n] != null && !sp[n]) o[n] = "0"; });
/* TODO: algorithm */
if(sp.password) o.password = crypto_CreatePasswordVerifier_Method1(sp.password).toString(16).toUpperCase();
return writextag('sheetProtection', null, o);
}
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];
var rel = rels ? rels['!id'][val.id] : null;
if(rel) {
val.Target = rel.Target;
if(val.location) val.Target += "#"+unescapexml(val.location);
if(val.location) val.Target += "#"+val.location;
val.Rel = rel;
} else {
val.Target = "#" + unescapexml(val.location);
rel = {Target: val.Target, TargetMode: 'Internal'};
val.Target = val.location;
rel = {Target: val.location, TargetMode: 'Internal'};
val.Rel = rel;
}
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;
@ -188,7 +143,7 @@ function parse_ws_xml_margins(margin) {
});
return o;
}
function write_ws_xml_margins(margin)/*:string*/ {
function write_ws_xml_margins(margin) {
default_margins(margin);
return writextag('pageMargins', null, margin);
}
@ -199,15 +154,15 @@ 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);
while(colm <= colM) columns[colm++] = dup(coll);
}
}
function write_ws_xml_cols(ws, cols)/*:string*/ {
var o = ["<cols>"], col;
var o = ["<cols>"], col, width;
for(var i = 0; i != cols.length; ++i) {
if(!(col = cols[i])) continue;
o[o.length] = (writextag('col', null, col_obj_w(i, col)));
@ -216,76 +171,40 @@ function write_ws_xml_cols(ws, cols)/*:string*/ {
return o.join("");
}
function parse_ws_xml_autofilter(data/*:string*/) {
function parse_ws_xml_autofilter(data) {
var o = { ref: (data.match(/ref="([^"]*)"/)||[])[1]};
return o;
}
function write_ws_xml_autofilter(data, ws, wb, idx)/*:string*/ {
var ref = typeof data.ref == "string" ? data.ref : encode_range(data.ref);
if(!wb.Workbook) wb.Workbook = ({Sheets:[]}/*:any*/);
if(!wb.Workbook.Names) wb.Workbook.Names = [];
var names/*: Array<any> */ = wb.Workbook.Names;
var range = decode_range(ref);
if(range.s.r == range.e.r) { range.e.r = decode_range(ws["!ref"]).e.r; ref = encode_range(range); }
for(var i = 0; i < names.length; ++i) {
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;
}
if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref });
return writextag("autoFilter", null, {ref:ref});
function write_ws_xml_autofilter(data)/*:string*/ {
return writextag("autoFilter", null, {ref:data.ref});
}
/* 18.3.1.88 sheetViews CT_SheetViews */
/* 18.3.1.87 sheetView CT_SheetView */
var sviewregex = /<(?:\w:)?sheetView(?:[^<>a-z][^<>]*)?\/?>/g;
function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) {
if(!wb.Views) wb.Views = [{}];
(data.match(sviewregex)||[]).forEach(function(r/*:string*/, i/*:number*/) {
var tag = parsexmltag(r);
// $FlowIgnore
if(!wb.Views[i]) wb.Views[i] = {};
// $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore
if(tag.rightToLeft && parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
});
}
function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
var sview = ({workbookViewId:"0"}/*:any*/);
// $FlowIgnore
if((((wb||{}).Workbook||{}).Views||[])[0]) sview.rightToLeft = wb.Workbook.Views[0].RTL ? "1" : "0";
return writextag("sheetViews", writextag("sheetView", null, sview), {});
return writextag("sheetViews", writextag("sheetView", null, {workbookViewId:"0"}), {});
}
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, ref, ws, opts, idx, wb) {
if(cell.v === undefined && cell.f === undefined || cell.t === 'z') return "";
var vv = "";
var oldt = cell.t, oldv = cell.v;
if(cell.t !== "z") switch(cell.t) {
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.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;
@ -294,95 +213,67 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb, date1904)/*:st
case 'd': o.t = "d"; break;
case 'b': o.t = "b"; break;
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));
if(opts.bookSST) {
v = writetag('v', ''+get_sst_id(opts.Strings, cell.v));
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;
if(cell.f) {
var ff = cell.F && cell.F.substr(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 cellregex = /<(?:\w+:)?c[ \/>]/, rowregex = /<\/(?:\w+:)?row>/;
var rregex = /r=["']([^"']*)["']/;
var parse_ws_xml_data = (function parse_ws_xml_data_factory() {
var cellregex = /<(?:\w+:)?c[ >]/, rowregex = /<\/(?:\w+:)?row>/;
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) {
var ri = 0, x = "", cells/*:Array<string>*/ = [], cref/*:?Array<string>*/ = [], idx=0, i=0, cc=0, d="", p/*:any*/;
return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
var ri = 0, x = "", cells = [], cref = [], idx=0, i=0, cc=0, d="", p/*:any*/;
var tag, tagr = 0, tagc = 0;
var sstr, ftag;
var fmtid = 0, fillid = 0;
var do_format = Array.isArray(styles.CellXf), cf;
var arrayf/*:Array<[Range, string]>*/ = [];
var arrayf = [];
var sharedf = [];
var dense = s["!data"] != null;
var rows/*:Array<RowInfo>*/ = [], rowobj = {}, rowrite = false;
var sheetStubs = !!opts.sheetStubs;
var date1904 = !!((wb||{}).WBProps||{}).date1904;
var dense = Array.isArray(s);
var rows = [], rowobj = {}, rowrite = false;
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.substr(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;
}
/* 18.3.1.4 c CT_Cell */
cells = x.slice(ri).split(cellregex);
for(var rslice = 0; rslice != cells.length; ++rslice) if(cells[rslice].trim().charAt(0) != "<") break;
cells = cells.slice(rslice);
cells = x.substr(ri).split(cellregex);
for(ri = 0; ri != cells.length; ++ri) {
x = cells[ri].trim();
if(x.length === 0) continue;
cref = x.match(rregex); idx = ri; i=0; cc=0;
x = "<c " + (x.slice(0,1)=="<"?">":"") + x;
x = "<c " + (x.substr(0,1)=="<"?">":"") + x;
if(cref != null && cref.length === 2) {
idx = 0; d=cref[1];
for(i=0; i != d.length; ++i) {
@ -393,38 +284,27 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
tagc = idx;
} else ++tagc;
for(i = 0; i != x.length; ++i) if(x.charCodeAt(i) === 62) break; ++i;
tag = parsexmltag(x.slice(0,i), true);
tag = parsexmltag(x.substr(0,i), true);
if(!tag.r) tag.r = encode_cell({r:tagr-1, c:tagc});
d = x.slice(i);
d = x.substr(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(/_xlfn\./,"");
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]);
sharedf[parseInt(ftag.si, 10)] = [ftag, unescapexml(utf8read(cref[1]))];
}
} 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);
if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][0].ref, tag.r);
}
/* TODO: factor out contains logic */
var _tag = decode_cell(tag.r);
@ -437,23 +317,20 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
if(tag.t == null && p.v === undefined) {
if(p.f || p.F) {
p.v = 0; p.t = "n";
} else if(!sheetStubs) continue;
} else if(!opts.sheetStubs) continue;
else p.t = "z";
}
else p.t = tag.t || "n";
if(guess.s.c > tagc) guess.s.c = tagc;
if(guess.e.c < tagc) guess.e.c = tagc;
if(guess.s.c > idx) guess.s.c = idx;
if(guess.e.c < idx) guess.e.c = idx;
/* 18.18.11 t ST_CellType */
switch(p.t) {
case 'n':
if(p.v == "" || p.v == null) {
if(!sheetStubs) continue;
p.t = 'z';
} else p.v = parseFloat(p.v);
p.v = parseFloat(p.v);
break;
case 's':
if(typeof p.v == 'undefined') {
if(!sheetStubs) continue;
if(!opts.sheetStubs) continue;
p.t = 'z';
} else {
sstr = strs[parseInt(p.v, 10)];
@ -464,21 +341,18 @@ 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;
if(opts.cellHTML) p.h = sstr.h;
} else p.v = "";
if(cref != null && (sstr = parse_si(cref[1]))) p.v = sstr.t; else p.v = "";
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':
@ -487,7 +361,6 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
}
/* formatting */
fmtid = fillid = 0;
cf = null;
if(do_format && tag.s !== undefined) {
cf = styles.CellXf[tag.s];
if(cf != null) {
@ -497,53 +370,42 @@ 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;
}
}
if(rows.length > 0) s['!rows'] = rows;
}; })();
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;
function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/, rels)/*:string*/ {
var o = [], r = [], range = safe_decode_range(ws['!ref']), cell, ref, rr = "", cols = [], R=0, C=0, rows = ws['!rows'];
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);
for(C = range.s.c; C <= range.e.c; ++C) {
ref = cols[C] + rr;
var _cell = dense ? (ws["!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])) {
if(r.length > 0 || rows && rows[R]) {
params = ({r:rr}/*:any*/);
if(rows && rows[R]) {
row = rows[R];
if(row.hidden) params.hidden = 1;
height = -1;
if(row.hpx) height = px2pt(row.hpx);
else if(row.hpt) height = row.hpt;
if(height > -1) { params.ht = height; params.customHeight = 1; }
if(row.level) { params.outlineLevel = row.level; }
if (row.hpx) height = px2pt(row.hpx);
else if (row.hpt) height = row.hpt;
if (height > -1) { params.ht = height; params.customHeight = 1; }
if (row.level) { params.outlineLevel = row.level; }
}
o[o.length] = (writextag('row', r.join(""), params));
}
@ -564,27 +426,22 @@ 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 = {};
var ref = ws['!ref'] || 'A1';
var range = safe_decode_range(ref);
if(range.e.c > 0x3FFF || range.e.r > 0xFFFFF) {
if(opts.WTF) throw new Error("Range " + ref + " exceeds format limit A1:XFD1048576");
range.e.c = Math.min(range.e.c, 0x3FFF);
range.e.r = Math.min(range.e.c, 0xFFFFF);
ref = encode_range(range);
}
var ref = ws['!ref']; if(ref == null) ref = 'A1';
if(!rels) rels = {};
ws['!comments'] = [];
var _drawing = [];
ws['!drawing'] = [];
write_ws_xml_sheetpr(ws, wb, idx, opts, o);
o[o.length] = (writextag('sheetPr', null, {'codeName': escapexml(wb.SheetNames[idx])}));
o[o.length] = (writextag('dimension', null, {'ref': ref}));
@ -609,12 +466,12 @@ 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 */
if(ws['!autofilter'] != null) o[o.length] = write_ws_xml_autofilter(ws['!autofilter'], ws, wb, idx);
if(ws['!autofilter'] != null) o[o.length] = write_ws_xml_autofilter(ws['!autofilter']);
/* sortState */
/* dataConsolidate */
@ -627,18 +484,14 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
/* dataValidations */
var relc = -1, rel, rId = -1;
if(/*::(*/ws['!links']/*::||[])*/.length > 0) {
if(ws['!links'].length > 0) {
o[o.length] = "<hyperlinks>";
/*::(*/ws['!links']/*::||[])*/.forEach(function(l) {
ws['!links'].forEach(function(l) {
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);
rel["r:id"] = "rId"+rId;
}
if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1));
rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), RELS.HLINK);
rel = ({"ref":l[0], "r:id":"rId"+rId}/*:any*/);
if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.substr(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>";
@ -646,25 +499,24 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
delete ws['!links'];
/* printOptions */
if(ws['!margins'] != null) o[o.length] = write_ws_xml_margins(ws['!margins']);
if (ws['!margins'] != null) o[o.length] = write_ws_xml_margins(ws['!margins']);
/* pageSetup */
/* headerFooter */
var hfidx = o.length;
o[o.length] = "";
/* rowBreaks */
/* colBreaks */
/* customProperties */
/* cellWatches */
if(!opts || opts.ignoreEC || (opts.ignoreEC == (void 0))) o[o.length] = writetag("ignoredErrors", writextag("ignoredError", null, {numberStoredAsText:1, sqref:ref}));
/* ignoredErrors */
/* smartTags */
if(_drawing.length > 0) {
if(ws['!drawing'].length > 0) {
rId = add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
o[o.length] = writextag("drawing", null, {"r:id":"rId" + rId});
ws['!drawing'] = _drawing;
}
else delete ws['!drawing'];
if(ws['!comments'].length > 0) {
rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML);
@ -672,14 +524,14 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
ws['!legacy'] = rId;
}
/* legacyDrawingHF */
/* drawingHF */
/* picture */
/* oleObjects */
/* controls */
/* webPublishItems */
/* tableParts */
/* extLst */
/* extList */
if(o.length>1) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
if(o.length>2) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}

View File

@ -1,5 +1,5 @@
/* [MS-XLSB] 2.4.726 BrtRowHdr */
/* [MS-XLSB] 2.4.718 BrtRowHdr */
function parse_BrtRowHdr(data, length) {
var z = ({}/*:any*/);
var tgt = data.l + length;
@ -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;
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,38 +64,29 @@ 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 */
/* [MS-XLSB] 2.4.812 BrtWsDim */
var parse_BrtWsDim = parse_UncheckedRfX;
var write_BrtWsDim = write_UncheckedRfX;
/* [MS-XLSB] 2.4.821 BrtWsFmtInfo */
function parse_BrtWsFmtInfo(/*::data, length*/) {
/* [MS-XLSB] 2.4.813 BrtWsFmtInfo */
function parse_BrtWsFmtInfo(data, length) {
}
//function write_BrtWsFmtInfo(ws, o) { }
/* [MS-XLSB] 2.4.823 BrtWsProp */
/* [MS-XLSB] 2.4.815 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);
@ -104,8 +94,8 @@ function write_BrtWsProp(str, outl, o) {
return o.slice(0, o.l);
}
/* [MS-XLSB] 2.4.306 BrtCellBlank */
function parse_BrtCellBlank(data) {
/* [MS-XLSB] 2.4.303 BrtCellBlank */
function parse_BrtCellBlank(data, length) {
var cell = parse_XLSBCell(data);
return [cell];
}
@ -113,17 +103,10 @@ 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) {
/* [MS-XLSB] 2.4.304 BrtCellBool */
function parse_BrtCellBool(data, length) {
var cell = parse_XLSBCell(data);
var fBool = data.read_shift(1);
return [cell, fBool, 'b'];
@ -134,47 +117,16 @@ 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) {
/* [MS-XLSB] 2.4.305 BrtCellError */
function parse_BrtCellError(data, length) {
var cell = parse_XLSBCell(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) {
/* [MS-XLSB] 2.4.308 BrtCellIsst */
function parse_BrtCellIsst(data, length) {
var cell = parse_XLSBCell(data);
var isst = data.read_shift(4);
return [cell, isst, 's'];
@ -185,20 +137,9 @@ 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) {
/* [MS-XLSB] 2.4.310 BrtCellReal */
function parse_BrtCellReal(data, length) {
var cell = parse_XLSBCell(data);
var value = parse_Xnum(data);
return [cell, value, 'n'];
@ -209,20 +150,9 @@ 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) {
/* [MS-XLSB] 2.4.311 BrtCellRk */
function parse_BrtCellRk(data, length) {
var cell = parse_XLSBCell(data);
var value = parse_RkNumber(data);
return [cell, value, 'n'];
@ -233,52 +163,22 @@ 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) {
/* [MS-XLSB] 2.4.314 BrtCellSt */
function parse_BrtCellSt(data, length) {
var cell = parse_XLSBCell(data);
var value = parse_XLWideString(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;
}
/* [MS-XLSB] 2.4.653 BrtFmlaBool */
/* [MS-XLSB] 2.4.647 BrtFmlaBool */
function parse_BrtFmlaBool(data, length, opts) {
var end = data.l + length;
var cell = parse_XLSBCell(data);
@ -294,7 +194,7 @@ function parse_BrtFmlaBool(data, length, opts) {
return o;
}
/* [MS-XLSB] 2.4.654 BrtFmlaError */
/* [MS-XLSB] 2.4.648 BrtFmlaError */
function parse_BrtFmlaError(data, length, opts) {
var end = data.l + length;
var cell = parse_XLSBCell(data);
@ -310,7 +210,7 @@ function parse_BrtFmlaError(data, length, opts) {
return o;
}
/* [MS-XLSB] 2.4.655 BrtFmlaNum */
/* [MS-XLSB] 2.4.649 BrtFmlaNum */
function parse_BrtFmlaNum(data, length, opts) {
var end = data.l + length;
var cell = parse_XLSBCell(data);
@ -326,7 +226,7 @@ function parse_BrtFmlaNum(data, length, opts) {
return o;
}
/* [MS-XLSB] 2.4.656 BrtFmlaString */
/* [MS-XLSB] 2.4.650 BrtFmlaString */
function parse_BrtFmlaString(data, length, opts) {
var end = data.l + length;
var cell = parse_XLSBCell(data);
@ -342,18 +242,18 @@ function parse_BrtFmlaString(data, length, opts) {
return o;
}
/* [MS-XLSB] 2.4.682 BrtMergeCell */
/* [MS-XLSB] 2.4.676 BrtMergeCell */
var parse_BrtMergeCell = parse_UncheckedRfX;
var write_BrtMergeCell = write_UncheckedRfX;
/* [MS-XLSB] 2.4.107 BrtBeginMergeCells */
/* [MS-XLSB] 2.4.108 BrtBeginMergeCells */
function write_BrtBeginMergeCells(cnt, o) {
if(o == null) o = new_buf(4);
o.write_shift(4, cnt);
return o;
}
/* [MS-XLSB] 2.4.662 BrtHLink */
function parse_BrtHLink(data, length/*::, opts*/) {
/* [MS-XLSB] 2.4.656 BrtHLink */
function parse_BrtHLink(data, length, opts) {
var end = data.l + length;
var rfx = parse_UncheckedRfX(data, 16);
var relId = parse_XLNullableWideString(data);
@ -365,22 +265,18 @@ function parse_BrtHLink(data, length/*::, opts*/) {
if(tooltip) o.Tooltip = tooltip;
return o;
}
function write_BrtHLink(l, rId) {
var o = new_buf(50+4*(l[1].Target.length + (l[1].Tooltip || "").length));
function write_BrtHLink(l, rId, o) {
if(o == null) o = new_buf(50+4*l[1].Target.length);
write_UncheckedRfX({s:decode_cell(l[0]), e:decode_cell(l[0])}, o);
write_RelID("rId" + rId, o);
var locidx = l[1].Target.indexOf("#");
var loc = locidx == -1 ? "" : l[1].Target.slice(locidx+1);
var loc = locidx == -1 ? "" : l[1].Target.substr(locidx+1);
write_XLWideString(loc || "", o);
write_XLWideString(l[1].Tooltip || "", o);
write_XLWideString("", o);
return o.slice(0, o.l);
}
/* [MS-XLSB] 2.4.692 BrtPane */
function parse_BrtPane(/*data, length, opts*/) {
}
/* [MS-XLSB] 2.4.6 BrtArrFmla */
function parse_BrtArrFmla(data, length, opts) {
var end = data.l + length;
@ -394,7 +290,7 @@ function parse_BrtArrFmla(data, length, opts) {
return o;
}
/* [MS-XLSB] 2.4.750 BrtShrFmla */
/* [MS-XLSB] 2.4.742 BrtShrFmla */
function parse_BrtShrFmla(data, length, opts) {
var end = data.l + length;
var rfx = parse_UncheckedRfX(data, 16);
@ -419,14 +315,14 @@ function write_BrtColInfo(C/*:number*/, col, o) {
var flags = 0;
if(col.hidden) flags |= 0x01;
if(typeof p.width == 'number') flags |= 0x02;
if(col.level) flags |= (col.level << 8);
o.write_shift(2, flags); // bit flag
o.write_shift(1, flags); // bit flag
o.write_shift(1, 0); // bit flag
return o;
}
/* [MS-XLSB] 2.4.678 BrtMargins */
/* [MS-XLSB] 2.4.672 BrtMargins */
var BrtMarginKeys = ["left","right","top","bottom","header","footer"];
function parse_BrtMargins(data/*::, length, opts*/)/*:Margins*/ {
function parse_BrtMargins(data, length, opts)/*:Margins*/ {
var margins = ({}/*:any*/);
BrtMarginKeys.forEach(function(k) { margins[k] = parse_Xnum(data, 8); });
return margins;
@ -438,17 +334,10 @@ function write_BrtMargins(margins/*:Margins*/, o) {
return o;
}
/* [MS-XLSB] 2.4.299 BrtBeginWsView */
function parse_BrtBeginWsView(data/*::, length, opts*/) {
var f = data.read_shift(2);
data.l += 28;
return { RTL: f & 0x20 };
}
function write_BrtBeginWsView(ws, Workbook, o) {
/* [MS-XLSB] 2.4.292 BrtBeginWsView */
function write_BrtBeginWsView(ws, o) {
if(o == null) o = new_buf(30);
var f = 0x39c;
if((((Workbook||{}).Views||[])[0]||{}).RTL) f |= 0x20;
o.write_shift(2, f); // bit flag
o.write_shift(2, 924); // bit flag
o.write_shift(4, 0);
o.write_shift(4, 0); // view first row
o.write_shift(4, 0); // view first col
@ -463,16 +352,7 @@ function write_BrtBeginWsView(ws, Workbook, o) {
return o;
}
/* [MS-XLSB] 2.4.309 BrtCellIgnoreEC */
function write_BrtCellIgnoreEC(ref) {
var o = new_buf(24);
o.write_shift(4, 4);
o.write_shift(4, 1);
write_UncheckedRfX(ref, o);
return o;
}
/* [MS-XLSB] 2.4.748 BrtSheetProtection */
/* [MS-XLSB] 2.4.740 BrtSheetProtection */
function write_BrtSheetProtection(sp, o) {
if(o == null) o = new_buf(16*4+2);
o.write_shift(2, sp.password ? crypto_CreatePasswordVerifier_Method1(sp.password) : 0);
@ -501,50 +381,41 @@ function write_BrtSheetProtection(sp, o) {
return o;
}
function parse_BrtDVal(/*data, length, opts*/) {
}
function parse_BrtDVal14(/*data, length, opts*/) {
}
/* [MS-XLSB] 2.1.7.61 Worksheet */
function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ {
function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(!data) return data;
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} };
var state/*:Array<string>*/ = [];
var pass = false, end = false;
var row, p, cf, R, C, addr, sstr, rr, cell/*:Cell*/;
var merges/*:Array<Range>*/ = [];
var mergecells = [];
opts.biff = 12;
opts['!row'] = 0;
var ai = 0, af = false;
var arrayf/*:Array<[Range, string]>*/ = [];
var sharedf = {};
var supbooks = opts.supbooks || /*::(*/wb/*:: :any)*/.supbooks || ([[]]/*:any*/);
supbooks.sharedf = sharedf;
supbooks.arrayf = arrayf;
var array_formulae = [];
var shared_formulae = {};
var supbooks = opts.supbooks || ([[]]/*:any*/);
supbooks.sharedf = shared_formulae;
supbooks.arrayf = array_formulae;
supbooks.SheetNames = wb.SheetNames || wb.Sheets.map(function(x) { return x.name; });
if(!opts.supbooks) {
opts.supbooks = supbooks;
if(wb.Names) for(var i = 0; i < wb.Names.length; ++i) supbooks[0][i+1] = wb.Names[i];
for(var i = 0; i < wb.Names.length; ++i) supbooks[0][i+1] = wb.Names[i];
}
var colinfo/*:Array<ColInfo>*/ = [], rowinfo/*:Array<RowInfo>*/ = [];
var colinfo = [], rowinfo = [];
var defwidth = 0, defheight = 0; // twips / MDW respectively
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 +441,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,16 +448,15 @@ 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;
for(ai = 0; ai < arrayf.length; ++ai) {
var aii = arrayf[ai];
for(ai = 0; ai < array_formulae.length; ++ai) {
var aii = array_formulae[ai];
if(row.r >= aii[0].s.r && row.r <= aii[0].e.r)
if(C >= aii[0].s.c && C <= aii[0].e.c) {
p.F = encode_range(aii[0]); af = true;
@ -601,45 +464,29 @@ 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;
mergecells.push(val); break;
case 0x01EE: /* 'BrtHLink' */
var rel = rels['!id'][val.relId];
@ -647,16 +494,14 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
val.Target = rel.Target;
if(val.loc) val.Target += "#"+val.loc;
val.Rel = rel;
} else if(val.relId == '') {
val.Target = "#" + val.loc;
}
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;
}
@ -665,15 +510,15 @@ 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*/);
array_formulae.push(val);
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]);
shared_formulae[encode_cell(val[0].s)] = val[1];
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;
@ -681,16 +526,12 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x003C: /* 'BrtColInfo' */
if(!opts.cellStyles) break;
while(val.e >= val.s) {
colinfo[val.e--] = { width: val.w/256, hidden: !!(val.flags & 0x01), level: val.level };
colinfo[val.e--] = { width: val.w/256, hidden: !!(val.flags & 0x01) };
if(!seencol) { seencol = true; find_mdw_colw(val.w/256); }
process_col(colinfo[val.e+1]);
}
break;
case 0x0227: /* 'BrtLegacyDrawing' */
if(val) s["!legrel"] = val;
break;
case 0x00A1: /* 'BrtBeginAFilter' */
s['!autofilter'] = { ref:encode_range(val) };
break;
@ -699,28 +540,8 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
s['!margins'] = val;
break;
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' */
if(!wb.Views) wb.Views = [{}];
if(!wb.Views[0]) wb.Views[0] = {};
if(val.RTL) wb.Views[0].RTL = true;
break;
case 0x01E5: /* 'BrtWsFmtInfo' */
break;
case 0x0040: /* 'BrtDVal' */
case 0x041D: /* 'BrtDVal14' */
break;
case 0x0097: /* 'BrtPane' */
break;
case 0x0098: /* 'BrtSel' */
/* case 'BrtUid' */
case 0x00AF: /* 'BrtAFilterDateGroupItem' */
case 0x0284: /* 'BrtActiveX' */
case 0x0271: /* 'BrtBigName' */
@ -732,6 +553,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' */
@ -740,17 +562,20 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x00AE: /* 'BrtCustomFilter' */
case 0x049C: /* 'BrtCustomFilter14' */
case 0x01F3: /* 'BrtDRef' */
case 0x01FB: /* 'BrtDXF' */
case 0x0040: /* 'BrtDVal' */
case 0x041D: /* 'BrtDVal14' */
case 0x0226: /* 'BrtDrawing' */
case 0x00AB: /* 'BrtDynamicFilter' */
case 0x00A7: /* 'BrtFilter' */
case 0x0499: /* 'BrtFilter14' */
case 0x00A9: /* 'BrtIconFilter' */
case 0x049D: /* 'BrtIconFilter14' */
case 0x0227: /* 'BrtLegacyDrawing' */
case 0x0228: /* 'BrtLegacyDrawingHF' */
case 0x0295: /* 'BrtListPart' */
case 0x027F: /* 'BrtOleObject' */
case 0x01DE: /* 'BrtPageSetup' */
case 0x0097: /* 'BrtPane' */
case 0x0219: /* 'BrtPhoneticInfo' */
case 0x01DD: /* 'BrtPrintOptions' */
case 0x0218: /* 'BrtRangeProtection' */
@ -758,6 +583,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' */
@ -765,24 +591,23 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x0413: /* 'BrtSparkline' */
case 0x01AC: /* 'BrtTable' */
case 0x00AA: /* 'BrtTop10Filter' */
case 0x0C00: /* 'BrtUid' */
case 0x0032: /* 'BrtValueMeta' */
case 0x0816: /* 'BrtWebExtension' */
case 0x0415: /* 'BrtWsFmtInfoEx14' */
case 0x0093: /* 'BrtWsProp' */
break;
case 0x0023: /* 'BrtFRTBegin' */
pass = true; break;
case 0x0024: /* 'BrtFRTEnd' */
pass = false; break;
case 0x0025: /* 'BrtACBegin' */
state.push(RT); pass = true; break;
case 0x0026: /* 'BrtACEnd' */
state.pop(); pass = false; break;
case 0x0025: /* 'BrtACBegin' */ break;
case 0x0026: /* 'BrtACEnd' */ 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);
@ -792,7 +617,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
if(!s["!ref"] && (refguess.s.r < 2000000 || ref && (ref.e.r > 0 || ref.e.c > 0 || ref.s.r > 0 || ref.s.c > 0))) s["!ref"] = encode_range(ref || refguess);
if(opts.sheetRows && s["!ref"]) {
var tmpref = safe_decode_range(s["!ref"]);
if(opts.sheetRows <= +tmpref.e.r) {
if(opts.sheetRows < +tmpref.e.r) {
tmpref.e.r = opts.sheetRows - 1;
if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
@ -802,82 +627,61 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
s["!ref"] = encode_range(tmpref);
}
}
if(merges.length > 0) s["!merges"] = merges;
if(mergecells.length > 0) s["!merges"] = mergecells;
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*/));
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(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(!isFinite(cell.v)) {
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"), ref, rr = "", cols/*:Array<string>*/ = [];
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
write_record(ba, 0x0091 /* BrtBeginSheetData */);
var dense = ws["!data"] != null;
var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = [];
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) {
@ -885,47 +689,39 @@ function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbo
/* [ACCELLTABLE] */
/* BrtRowHdr */
write_row_header(ba, ws, range, R);
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);
ref = cols[C] + rr;
var cell = dense ? (ws["!data"][R]||[])[C] : ws[ref];
if(!cell) { last_seen = false; continue; }
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*/) {
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 */);
}
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, 'BrtBeginColInfos');
ws['!cols'].forEach(function(m, i) { if(m) write_record(ba, 'BrtColInfo', write_BrtColInfo(i, m)); });
write_record(ba, 'BrtEndColInfos');
}
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'];
}
@ -933,80 +729,57 @@ 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;
}
}
function write_AUTOFILTER(ba, ws, wb, idx) {
function write_AUTOFILTER(ba, ws) {
if(!ws['!autofilter']) return;
var data = ws['!autofilter'];
var ref = typeof data.ref === "string" ? data.ref : encode_range(data.ref);
/* Update FilterDatabase defined name for the worksheet */
if(!wb.Workbook) wb.Workbook = ({Sheets:[]}/*:any*/);
if(!wb.Workbook.Names) wb.Workbook.Names = [];
var names/*: Array<any> */ = wb.Workbook.Names;
var range = decode_range(ref);
if(range.s.r == range.e.r) { range.e.r = decode_range(ws["!ref"]).e.r; ref = encode_range(range); }
for(var i = 0; i < names.length; ++i) {
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;
}
if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref) });
write_record(ba, 0x00A1 /* BrtBeginAFilter */, write_UncheckedRfX(safe_decode_range(ref)));
write_record(ba, "BrtBeginAFilter", write_UncheckedRfX(decode_range(ws['!autofilter'].ref)));
/* *FILTERCOLUMN */
/* [SORTSTATE] */
/* BrtEndAFilter */
write_record(ba, 0x00A2 /* BrtEndAFilter */);
write_record(ba, "BrtEndAFilter");
}
function write_WSVIEWS2(ba, ws, Workbook) {
write_record(ba, 0x0085 /* BrtBeginWsViews */);
function write_WSVIEWS2(ba, ws) {
write_record(ba, "BrtBeginWsViews");
{ /* 1*WSVIEW2 */
/* [ACUID] */
write_record(ba, 0x0089 /* BrtBeginWsView */, write_BrtBeginWsView(ws, Workbook));
write_record(ba, "BrtBeginWsView", write_BrtBeginWsView(ws));
/* [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*/) {
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) {
var ba = buf_array();
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
var c/*:string*/ = s; try { if(wb && wb.Workbook) c = wb.Workbook.Sheets[idx].CodeName || c; } catch(e) {}
var r = safe_decode_range(ws['!ref'] || "A1");
if(r.e.c > 0x3FFF || r.e.r > 0xFFFFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:XFD1048576");
r.e.c = Math.min(r.e.c, 0x3FFF);
r.e.r = Math.min(r.e.c, 0xFFFFF);
}
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_WSVIEWS2(ba, ws, wb.Workbook);
write_record(ba, "BrtBeginSheet");
write_record(ba, "BrtWsProp", write_BrtWsProp(s));
write_record(ba, "BrtWsDim", write_BrtWsDim(r));
write_WSVIEWS2(ba, ws);
write_WSFMTINFO(ba, ws);
write_COLINFOS(ba, ws, idx, opts, wb);
write_CELLTABLE(ba, ws, idx, opts, wb);
@ -1014,7 +787,7 @@ function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
write_SHEETPROTECT(ba, ws);
/* *([BrtRangeProtectionIso] BrtRangeProtection) */
/* [SCENMAN] */
write_AUTOFILTER(ba, ws, wb, idx);
write_AUTOFILTER(ba, ws);
/* [SORTSTATE] */
/* [DCON] */
/* [USERSHVIEWS] */
@ -1024,14 +797,14 @@ 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] */
/* [COLBRK] */
/* *BrtBigName */
/* [CELLWATCHES] */
if(!opts || opts.ignoreEC || (opts.ignoreEC == (void 0))) write_IGNOREECS(ba, ws);
/* [IGNOREECS] */
/* [SMARTTAGS] */
/* [BrtDrawing] */
write_LEGACYDRAWING(ba, ws, idx, rels);
@ -1042,6 +815,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();
}

View File

@ -1,26 +1,22 @@
function parse_Cache(data/*:string*/)/*:[Array<number|string>, string, ?string]*/ {
var col/*:Array<number|string>*/ = [];
var num = data.match(/^<c:numCache>/);
var f;
function parse_numCache(data) {
var col = [];
/* 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="(.*?)"><c:v>(.*)<\/c:v><\/c:pt>/);
if(!q) return;
col[+q[1]] = num ? +q[2] : q[2];
col[+q[1]] = +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,""); });
return [col, nf, f];
return [col, nf];
}
/* 21.2 DrawingML - Charts */
function parse_chart(data/*:?string*/, name/*:string*/, opts, rels, wb, csheet) {
var cs/*:Worksheet*/ = ((csheet || {"!type":"chart"})/*:any*/);
function parse_chart(data, name/*:string*/, opts, rels, wb, csheet) {
var cs = ((csheet || {"!type":"chart"})/*:any*/);
if(!data) return csheet;
/* 21.2.2.27 chart CT_Chart */
@ -28,16 +24,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) {
var cache = parse_Cache(nc);
(data.match(/<c:numCache>[\s\S]*?<\/c:numCache>/gm)||[]).forEach(function(nc) {
var cache = parse_numCache(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;

View File

@ -1,65 +1,54 @@
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*/ {
function parse_cs_xml(data/*:?string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(!data) return data;
/* 18.3.1.12 chartsheet CT_ChartSheet */
if(!rels) rels = {'!id':{}};
var s = ({'!type':"chart", '!drawel':null, '!rel':""}/*:any*/);
var s = {'!type':"chart", '!chart':null, '!rel':""};
var m;
/* 18.3.1.83 sheetPr CT_ChartsheetPr */
var sheetPr = data.match(sheetprregex);
if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
/* 18.3.1.36 drawing CT_Drawing */
if((m = data.match(/drawing r:id="(.*?)"/))) s['!rel'] = m[1];
if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
if(rels['!id'][s['!rel']]) s['!chart'] = 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("");
//}
/* [MS-XLSB] 2.4.331 BrtCsProp */
function parse_BrtCsProp(data, length/*:number*/) {
data.l += 10;
var name = parse_XLWideString(data, length - 10);
return { name: name };
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.1.7.7 Chart Sheet */
function parse_cs_bin(data, opts, idx/*:number*/, rels, wb/*::, themes, styles*/)/*:Worksheet*/ {
function parse_cs_bin(data, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(!data) return data;
if(!rels) rels = {'!id':{}};
var s = {'!type':"chart", '!drawel':null, '!rel':""};
var state/*:Array<string>*/ = [];
var s = {'!type':"chart", '!chart':null, '!rel':""};
var state = [];
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' */
s['!rel'] = val; break;
case 0x028B: /* 'BrtCsProp' */
if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
if(val.name) wb.Sheets[idx].CodeName = val.name;
break;
/* case 'BrtUid': */
case 0x0232: /* 'BrtBkHim' */
case 0x028C: /* 'BrtCsPageSetup' */
case 0x028B: /* 'BrtCsProp' */
case 0x029D: /* 'BrtCsProtection' */
case 0x02A7: /* 'BrtCsProtectionIso' */
case 0x0227: /* 'BrtLegacyDrawing' */
case 0x0228: /* 'BrtLegacyDrawingHF' */
case 0x01DC: /* 'BrtMargins' */
case 0x0C00: /* 'BrtUid' */
break;
case 0x0023: /* 'BrtFRTBegin' */
@ -67,36 +56,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']];
if(rels['!id'][s['!rel']]) s['!chart'] = 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();
}

View File

@ -4,7 +4,7 @@ var WBPropsDef = [
['autoCompressPictures', true, "bool"],
['backupFile', false, "bool"],
['checkCompatibility', false, "bool"],
['CodeName', ''],
['codeName', ''],
['date1904', false, "bool"],
['defaultThemeVersion', 0, "int"],
['filterPrivacy', false, "bool"],
@ -54,7 +54,7 @@ var CalcPrDef = [
];
/* 18.2.3 (CT_CustomWorkbookView) Defaults */
/*var CustomWBViewDef = [
var CustomWBViewDef = [
['autoUpdate', 'false'],
['changesSavedWin', 'false'],
['includeHiddenRowCol', 'true'],
@ -73,14 +73,14 @@ var CalcPrDef = [
['tabRatio', '600'],
['xWindow', '0'],
['yWindow', '0']
];*/
];
function push_defaults_array(target, defaults) {
for(var j = 0; j != target.length; ++j) { var w = target[j];
for(var i=0; i != defaults.length; ++i) { var z = defaults[i];
if(w[z[0]] == null) w[z[0]] = z[1];
else switch(z[2]) {
case "bool": if(typeof w[z[0]] == "string") w[z[0]] = parsexmlbool(w[z[0]]); break;
case "bool": if(typeof w[z[0]] == "string") w[z[0]] = parsexmlbool(w[z[0]], z[0]); break;
case "int": if(typeof w[z[0]] == "string") w[z[0]] = parseInt(w[z[0]], 10); break;
}
}
@ -90,7 +90,7 @@ function push_defaults(target, defaults) {
for(var i = 0; i != defaults.length; ++i) { var z = defaults[i];
if(target[z[0]] == null) target[z[0]] = z[1];
else switch(z[2]) {
case "bool": if(typeof target[z[0]] == "string") target[z[0]] = parsexmlbool(target[z[0]]); break;
case "bool": if(typeof target[z[0]] == "string") target[z[0]] = parsexmlbool(target[z[0]], z[0]); break;
case "int": if(typeof target[z[0]] == "string") target[z[0]] = parseInt(target[z[0]], 10); break;
}
}
@ -103,7 +103,7 @@ function parse_wb_defaults(wb) {
push_defaults_array(wb.WBView, WBViewDef);
push_defaults_array(wb.Sheets, SheetDef);
_ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904);
_ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904, 'date1904');
}
function safe1904(wb/*:Workbook*/)/*:string*/ {
@ -113,46 +113,25 @@ 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) {
function check_wb_names(N) {
N.forEach(function(n,i) {
check_ws_name(n);
for(var j = 0; j < i; ++j) if(n == N[j]) throw new Error("Duplicate Sheet Name: " + n);
if(codes) {
var cn = (S && S[i] && S[i].CodeName) || n;
if(cn.charCodeAt(0) == 95 && cn.length > 22) throw new Error("Bad Code Name: Worksheet" + cn);
}
});
}
function check_wb(wb) {
if(!wb || !wb.SheetNames || !wb.Sheets) throw new Error("Invalid Workbook");
if(!wb.SheetNames.length) throw new Error("Workbook is empty");
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});
});
check_wb_names(wb.SheetNames);
/* TODO: validate workbook */
}

View File

@ -2,9 +2,10 @@
var wbnsregex = /<\w+:workbook/;
function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
if(!data) throw new Error("Could not find file");
var wb = /*::(*/{ AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, Names:[], xmlns: "" }/*::)*/;
var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, Names:[], xmlns: "" };
var pass = false, xmlns = "xmlns";
var dname = {}, dnstart = 0;
/*(data.match(tagregex)||[]).forEach */
data.replace(tagregex, function xml_wb(x, idx) {
var y/*:any*/ = parsexmltag(x);
switch(strip_ns(y[0])) {
@ -22,9 +23,7 @@ function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
case '<fileVersion/>': case '</fileVersion>': break;
/* 18.2.12 fileSharing CT_FileSharing ? */
case '<fileSharing':
break;
case '<fileSharing/>': break;
case '<fileSharing': case '<fileSharing/>': break;
/* 18.2.28 workbookPr CT_WorkbookPr ? */
case '<workbookPr':
@ -32,24 +31,22 @@ function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
WBPropsDef.forEach(function(w) {
if(y[w[0]] == null) return;
switch(w[2]) {
case "bool": wb.WBProps[w[0]] = parsexmlbool(y[w[0]]); break;
case "bool": wb.WBProps[w[0]] = parsexmlbool(y[w[0]], w[0]); break;
case "int": wb.WBProps[w[0]] = parseInt(y[w[0]], 10); break;
default: wb.WBProps[w[0]] = y[w[0]];
}
});
if(y.codeName) wb.WBProps.CodeName = utf8read(y.codeName);
break;
case '</workbookPr>': break;
/* 18.2.29 workbookProtection CT_WorkbookProtection ? */
case '<workbookProtection':
break;
case '<workbookProtection': break;
case '<workbookProtection/>': break;
/* 18.2.1 bookViews CT_BookViews ? */
case '<bookViews': case '<bookViews>': case '</bookViews>': break;
/* 18.2.30 workbookView CT_BookView + */
case '<workbookView': case '<workbookView/>': delete y[0]; wb.WBView.push(y); break;
case '<workbookView': delete y[0]; wb.WBView.push(y); break;
case '</workbookView>': break;
/* 18.2.20 sheets CT_Sheets 1 */
@ -83,14 +80,13 @@ function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
/* 18.2.5 definedName CT_DefinedName + */
case '<definedName': {
dname = {};
dname.Name = utf8read(y.name);
dname.Name = y.name;
if(y.comment) dname.Comment = y.comment;
if(y.localSheetId) dname.Sheet = +y.localSheetId;
if(parsexmlbool(y.hidden||"0")) dname.Hidden = true;
dnstart = idx + x.length;
} break;
case '</definedName>': {
dname.Ref = unescapexml(utf8read(data.slice(dnstart, idx)));
dname.Ref = data.slice(dnstart, idx);
wb.Names.push(dname);
} break;
case '<definedName/>': break;
@ -105,7 +101,7 @@ function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
/* 18.2.4 customWorkbookViews CT_CustomWorkbookViews ? */
case '<customWorkbookViews>': case '</customWorkbookViews>': case '<customWorkbookViews': break;
/* 18.2.3 customWorkbookView CT_CustomWorkbookView + */
/* 18.2.3 customWorkbookView CT_CustomWorkbookView + */
case '<customWorkbookView': case '</customWorkbookView>': break;
/* 18.2.18 pivotCaches CT_PivotCaches ? */
@ -118,7 +114,7 @@ function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
/* 18.2.23 smartTagTypes CT_SmartTagTypes ? */
case '<smartTagTypes': case '<smartTagTypes>': case '</smartTagTypes>': break;
/* 18.2.22 smartTagType CT_SmartTagType ? */
/* 18.2.22 smartTagType CT_SmartTagType ? */
case '<smartTagType': break;
/* 18.2.24 webPublishing CT_WebPublishing ? */
@ -134,7 +130,7 @@ function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': case '<extLst/>': break;
/* 18.2.7 ext CT_Extension + */
/* 18.2.7 ext CT_Extension + */
case '<ext': pass=true; break; //TODO: check with versions of excel
case '</ext>': pass=false; break;
@ -151,60 +147,48 @@ 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;
}
function write_wb_xml(wb/*:Workbook*//*::, opts:?WriteOpts*/)/*:string*/ {
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);
/* fileVersion */
/* fileSharing */
var workbookPr/*:any*/ = ({codeName:"ThisWorkbook"}/*:any*/);
var workbookPr/*:WBProps*/ = ({codeName:"ThisWorkbook"}/*:any*/);
if(wb.Workbook && wb.Workbook.WBProps) {
if(wb.Workbook.WBProps.codeName) workbookPr.codeName = wb.Workbook.WBProps.codeName;
WBPropsDef.forEach(function(x) {
/*:: if(!wb.Workbook || !wb.Workbook.WBProps) throw "unreachable"; */
if((wb.Workbook.WBProps[x[0]]/*:any*/) == null) return;
if((wb.Workbook.WBProps[x[0]]/*:any*/) == x[1]) return;
workbookPr[x[0]] = (wb.Workbook.WBProps[x[0]]/*:any*/);
});
/*:: if(!wb.Workbook || !wb.Workbook.WBProps) throw "unreachable"; */
if(wb.Workbook.WBProps.CodeName) { workbookPr.codeName = wb.Workbook.WBProps.CodeName; delete workbookPr.CodeName; }
}
o[o.length] = (writextag('workbookPr', null, workbookPr));
/* workbookProtection */
var sheets = wb.Workbook && wb.Workbook.Sheets || [];
var i = 0;
/* bookViews only written if first worksheet is hidden */
if(sheets && sheets[0] && !!sheets[0].Hidden) {
o[o.length] = "<bookViews>";
for(i = 0; i != wb.SheetNames.length; ++i) {
if(!sheets[i]) break;
if(!sheets[i].Hidden) break;
}
if(i == wb.SheetNames.length) i = 0;
o[o.length] = '<workbookView firstSheet="' + i + '" activeTab="' + i + '"/>';
o[o.length] = "</bookViews>";
}
/* bookViews */
o[o.length] = "<sheets>";
for(i = 0; i != wb.SheetNames.length; ++i) {
var sht = ({name:escapexml(wb.SheetNames[i].slice(0,31))}/*:any*/);
var sheets = wb.Workbook && wb.Workbook.Sheets || [];
for(var i = 0; i != wb.SheetNames.length; ++i) {
var sht = ({name:escapexml(wb.SheetNames[i].substr(0,31))}/*:any*/);
sht.sheetId = ""+(i+1);
sht["r:id"] = "rId"+(i+1);
if(sheets[i]) switch(sheets[i].Hidden) {
@ -224,9 +208,8 @@ function write_wb_xml(wb/*:Workbook*//*::, opts:?WriteOpts*/)/*:string*/ {
var d/*:any*/ = {name:n.Name};
if(n.Comment) d.comment = n.Comment;
if(n.Sheet != null) d.localSheetId = ""+n.Sheet;
if(n.Hidden) d.hidden = "1";
if(!n.Ref) return;
o[o.length] = writextag('definedName', escapexml(n.Ref), d);
o[o.length] = writextag('definedName', String(n.Ref), d);
});
o[o.length] = "</definedNames>";
}

View File

@ -1,4 +1,4 @@
/* [MS-XLSB] 2.4.304 BrtBundleSh */
/* [MS-XLSB] 2.4.301 BrtBundleSh */
function parse_BrtBundleSh(data, length/*:number*/) {
var z = {};
z.Hidden = data.read_shift(4); //hsState ST_SheetState
@ -12,17 +12,17 @@ function write_BrtBundleSh(data, o) {
o.write_shift(4, data.Hidden);
o.write_shift(4, data.iTabID);
write_RelID(data.strRelID, o);
write_XLWideString(data.name.slice(0,31), o);
write_XLWideString(data.name.substr(0,31), o);
return o.length > o.l ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.815 BrtWbProp */
/* [MS-XLSB] 2.4.807 BrtWbProp */
function parse_BrtWbProp(data, length)/*:WBProps*/ {
var o/*:WBProps*/ = ({}/*:any*/);
var flags = data.read_shift(4);
o.defaultThemeVersion = data.read_shift(4);
var strName = (length > 8) ? parse_XLWideString(data) : "";
if(strName.length > 0) o.CodeName = strName;
if(strName.length > 0) o.codeName = strName;
o.autoCompressPictures = !!(flags & 0x10000);
o.backupFile = !!(flags & 0x40);
o.checkCompatibility = !!(flags & 0x1000);
@ -45,12 +45,11 @@ 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);
o.write_shift(4, 0);
write_XLSBCodeName(data && data.CodeName || "ThisWorkbook", o);
write_XLSBCodeName("ThisWorkbook", o);
return o.slice(0, o.l);
}
@ -62,22 +61,15 @@ function parse_BrtFRTArchID$(data, length) {
return o;
}
/* [MS-XLSB] 2.4.687 BrtName */
/* [MS-XLSB] 2.4.680 BrtName */
function parse_BrtName(data, length, opts) {
var end = data.l + length;
var flags = data.read_shift(4);
data.l += 1; //var chKey = data.read_shift(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,46 +77,15 @@ 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, Comment:comment}/*: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 */
/* [MS-XLSB] 2.1.7.60 Workbook */
function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
var state/*:Array<string>*/ = [];
var pass = false;
var pass = false, z;
if(!opts) opts = {};
opts.biff = 12;
@ -134,9 +95,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 +106,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 +129,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 'BrtRevisionPtr' */
/* case 'BrtUid' */
case 0x0817: /* 'BrtAbsPath15' */
case 0x0216: /* 'BrtBookProtection' */
case 0x02A5: /* 'BrtBookProtectionIso' */
case 0x009E: /* 'BrtBookView' */
case 0x009D: /* 'BrtCalcProp' */
case 0x0262: /* 'BrtCrashRecErr' */
case 0x0802: /* 'BrtDecoupledPivotCacheID' */
@ -206,19 +160,18 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
break;
case 0x0023: /* 'BrtFRTBegin' */
state.push(RT); pass = true; break;
pass = true; break;
case 0x0024: /* 'BrtFRTEnd' */
state.pop(); pass = false; break;
case 0x0025: /* 'BrtACBegin' */
state.push(RT); pass = true; break;
case 0x0026: /* 'BrtACEnd' */
state.pop(); pass = false; break;
pass = false; break;
case 0x0025: /* 'BrtACBegin' */ break;
case 0x0026: /* 'BrtACEnd' */ 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) throw new Error("Unexpected record " + RT + " " + R_n);
}
}, opts);
@ -231,17 +184,18 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
return wb;
}
function write_BUNDLESHS(ba, wb/*::, opts*/) {
write_record(ba, 0x008F /* BrtBeginBundleShs */);
/* [MS-XLSB] 2.1.7.60 Workbook */
function write_BUNDLESHS(ba, wb, opts) {
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 */
/* [MS-XLSB] 2.4.643 BrtFileVersion */
function write_BrtFileVersion(data, o) {
if(!o) o = new_buf(127);
for(var i = 0; i != 4; ++i) o.write_shift(4, 0);
@ -249,10 +203,11 @@ 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;
}
/* [MS-XLSB] 2.4.301 BrtBookView */
/* [MS-XLSB] 2.4.298 BrtBookView */
function write_BrtBookView(idx, o) {
if(!o) o = new_buf(29);
o.write_shift(-4, 0);
@ -267,7 +222,8 @@ function write_BrtBookView(idx, o) {
return o.length > o.l ? o.slice(0, o.l) : o;
}
function write_BOOKVIEWS(ba, wb/*::, opts*/) {
/* [MS-XLSB] 2.1.7.60 Workbook */
function write_BOOKVIEWS(ba, wb, opts) {
/* required if hidden tab appears before visible tab */
if(!wb.Workbook || !wb.Workbook.Sheets) return;
var sheets = wb.Workbook.Sheets;
@ -277,44 +233,16 @@ 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 */);
write_record(ba, "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 */);
}
/* [MS-XLSB] 2.4.305 BrtCalcProp */
/*function write_BrtCalcProp(data, o) {
/* [MS-XLSB] 2.4.302 BrtCalcProp */
function write_BrtCalcProp(data, o) {
if(!o) o = new_buf(26);
o.write_shift(4,0); // force recalc
o.write_shift(4,0); /* force recalc */
o.write_shift(4,1);
o.write_shift(4,0);
write_Xnum(0, o);
@ -322,41 +250,41 @@ function write_EXTERNALS_xlsb(ba, wb) {
o.write_shift(1, 0x33);
o.write_shift(1, 0x00);
return o;
}*/
}
/* [MS-XLSB] 2.4.646 BrtFileRecover */
/*function write_BrtFileRecover(data, o) {
/* [MS-XLSB] 2.4.640 BrtFileRecover */
function write_BrtFileRecover(data, o) {
if(!o) o = new_buf(1);
o.write_shift(1,0);
return o;
}*/
}
/* [MS-XLSB] 2.1.7.61 Workbook */
/* [MS-XLSB] 2.1.7.60 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();
}

View File

@ -3,24 +3,24 @@ function parse_wb(data, name/*:string*/, opts)/*:WorkbookFile*/ {
return parse_wb_xml((data/*:any*/), opts);
}
function parse_ws(data, name/*:string*/, idx/*:number*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_ws_bin((data/*:any*/), opts, idx, rels, wb, themes, styles);
return parse_ws_xml((data/*:any*/), opts, idx, rels, wb, themes, styles);
function parse_ws(data, name/*:string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_ws_bin((data/*:any*/), opts, rels, wb, themes, styles);
return parse_ws_xml((data/*:any*/), opts, rels, wb, themes, styles);
}
function parse_cs(data, name/*:string*/, idx/*:number*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_cs_bin((data/*:any*/), opts, idx, rels, wb, themes, styles);
return parse_cs_xml((data/*:any*/), opts, idx, rels, wb, themes, styles);
function parse_cs(data, name/*:string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_cs_bin((data/*:any*/), opts, rels, wb, themes, styles);
return parse_cs_xml((data/*:any*/), opts, rels, wb, themes, styles);
}
function parse_ms(data, name/*:string*/, idx/*:number*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_ms_bin((data/*:any*/), opts, idx, rels, wb, themes, styles);
return parse_ms_xml((data/*:any*/), opts, idx, rels, wb, themes, styles);
function parse_ms(data, name/*:string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_ms_bin((data/*:any*/), opts, rels, wb, themes, styles);
return parse_ms_xml((data/*:any*/), opts, rels, wb, themes, styles);
}
function parse_ds(data, name/*:string*/, idx/*:number*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_ds_bin((data/*:any*/), opts, idx, rels, wb, themes, styles);
return parse_ds_xml((data/*:any*/), opts, idx, rels, wb, themes, styles);
function parse_ds(data, name/*:string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_ds_bin((data/*:any*/), opts, rels, wb, themes, styles);
return parse_ds_xml((data/*:any*/), opts, rels, wb, themes, styles);
}
function parse_sty(data, name/*:string*/, themes, opts) {
@ -28,12 +28,16 @@ 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);
}
function parse_cmnt(data, name/*:string*/, opts)/*:Array<RawComment>*/ {
function parse_cmnt(data, name/*:string*/, opts) {
if(name.slice(-4)===".bin") return parse_comments_bin((data/*:any*/), opts);
return parse_comments_xml((data/*:any*/), opts);
}
@ -43,12 +47,36 @@ function parse_cc(data, name/*:string*/, opts) {
return parse_cc_xml((data/*:any*/), name, opts);
}
function parse_xlink(data, rel, name/*:string*/, opts) {
if(name.slice(-4)===".bin") return parse_xlink_bin((data/*:any*/), rel, name, opts);
return parse_xlink_xml((data/*:any*/), rel, name, opts);
function parse_xlink(data, name/*:string*/, opts) {
if(name.slice(-4)===".bin") return parse_xlink_bin((data/*:any*/), name, opts);
return parse_xlink_xml((data/*:any*/), 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);
}
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);
}
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +1,28 @@
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*/) {
var t/*:number*/ = +type || +XLSRE[/*::String(*/type/*::)*/];
if(isNaN(t)) return;
var len = length || (payload||[]).length || 0;
var o = ba.next(4);
var o = ba.next(4 + len);
o.write_shift(2, t);
o.write_shift(2, len);
if(/*:: len != null &&*/len > 0 && is_buf(payload)) ba.push(payload);
}
function write_biff_continue(ba/*:BufArray*/, type/*:number*/, payload, length/*:?number*/)/*:void*/ {
var len = length || (payload||[]).length || 0;
if(len <= 8224) return write_biff_rec(ba, type, payload, len);
var t = type;
if(isNaN(t)) return;
var parts = payload.parts || [], sidx = 0;
var i = 0, w = 0;
while(w + (parts[sidx] || 8224) <= 8224) { w+= (parts[sidx] || 8224); sidx++; }
var o = ba.next(4);
o.write_shift(2, t);
o.write_shift(2, w);
ba.push(payload.slice(i, i + w));
i += w;
while(i < len) {
o = ba.next(4);
o.write_shift(2, 0x3c); // TODO: figure out correct continue type
w = 0;
while(w + (parts[sidx] || 8224) <= 8224) { w+= (parts[sidx] || 8224); sidx++; }
o.write_shift(2, w);
ba.push(payload.slice(i, i+w)); i+= w;
}
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(1, 0);
out.write_shift(1, 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,601 +35,156 @@ 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>*/ = [];
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.c, 0x3FFF);
}
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);
var dense = Array.isArray(ws);
var range = safe_decode_range(ws['!ref'] || "A1"), ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
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({
sz:12,
color: {theme:1},
name: "Arial",
family: 2,
scheme: "minor"
}, opts));
}
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));
});
}
function write_FEAT(ba, ws) {
/* [MS-XLS] 2.4.112 */
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);
/* [MS-XLS] 2.4.111 */
o = new_buf(39);
o.write_shift(4, 0x868); o.write_shift(4, 0); o.write_shift(4, 0);
o.write_shift(2, 3); o.write_shift(1, 0); o.write_shift(4, 0);
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);
}
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));
opts.cellXfs.forEach(function(c) {
write_biff_rec(ba, 0x00e0 /* 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));
}
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*/) {
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));
return;
}
if(cell.bf) write_biff_rec(ba, 0x0006 /* Formula */, write_Formula(cell, R, C, opts, os));
else switch(cell.t) {
function write_ws_biff8_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(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));
break;
case 'b': case 'e':
write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, cell.v, os, opts, cell.t));
break;
write_biff_rec(ba, "Number", write_Number(R, C, v, opts));
return;
case 'b': case 'e': write_biff_rec(ba, "BoolErr", write_BoolErr(R, C, cell.v, opts, cell.t)); return;
/* 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));
break;
default:
write_biff_rec(ba, 0x0201 /* Blank */, write_XLSCell(R, C, os));
write_biff_rec(ba, "Label", write_Label(R, C, cell.v, opts));
return;
}
write_biff_rec(ba, "Blank", write_XLSCell(R, C));
}
/* [MS-XLS] 2.1.7.20.5 */
function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
var ba = buf_array();
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 b8 = opts.biff == 8;
var dense = Array.isArray(ws);
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:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
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]));
/* 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));
/* ... */
if(b8) write_ws_cols_biff8(ba, ws["!cols"]);
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]));
/* ... */
write_biff_rec(ba, 0x0200 /* Dimensions */, write_Dimensions(range, opts));
write_biff_rec(ba, "HCenter", writebool(false));
write_biff_rec(ba, "VCenter", writebool(false));
/* ... */
write_biff_rec(ba, "Dimensions", 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) {
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 ? row[C] : ws[ref];
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([ref, cell.l]);
if(cell.c) comments.push([cell.c, R, C]);
write_ws_biff8_cell(ba, cell, R, C, opts);
}
}
var cname/*:string*/ = _sheet.CodeName || _sheet.name || s;
var cname = ((((wb||{}).Workbook||{}).Sheets||[])[idx]||{}).name||s;
write_biff_rec(ba, "CodeName", write_XLUnicodeString(cname, opts));
/* ... */
if(b8) write_comments_biff8(ba, comments); else write_comments_biff2(ba, comments);
/* ... */
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']));
/* [LRng] *QUERYTABLE [PHONETICINFO] CONDFMTS */
if(b8) write_ws_biff8_hlinks(ba, ws);
/* [DVAL] */
write_biff_rec(ba, 0x01ba /* 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();
}
/* [MS-XLS] 2.1.7.20.3 */
function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) {
var A = buf_array();
var _WB/*:WBWBProps*/ = ((wb||{}).Workbook||{}/*:any*/);
var _sheets/*:Array<WBWSProp>*/ = (_WB.Sheets||[]);
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));
/* [FileSharing] */
write_biff_rec(A, 0x0042 /* 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 */);
/* [ObNoMacros] */
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));
write_biff_rec(A, "CodePage", writeuint16(b8 ? 0x04b0 : 0x04E4));
if(b8) write_biff_rec(A, "DSF", writeuint16(0));
write_biff_rec(A, "RRTabId", write_RRTabId(wb.SheetNames.length));
if(b8 && wb.vbaraw) {
var cname/*:string*/ = _wb.CodeName || "ThisWorkbook";
write_biff_rec(A, 0x01ba /* CodeName */, write_XLUnicodeString(cname, opts));
write_biff_rec(A, "ObProj");
var cname = ((wb.Workbook||{}).WBProps||{}).codeName || "ThisWorkbook";
write_biff_rec(A, "CodeName", write_XLUnicodeString(cname, opts));
}
write_biff_rec(A, 0x009c /* 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, "BuiltInFnGroupCount", writeuint16(0x11));
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 */
/* BIFF8: MsoDrawingGroup [*Continue] */
if(b8 && b8ocnts.length) write_biff_rec(C, 0x00EB /* MsoDrawingGroup */, write_MsoDrawingGroup());
if(b8) write_biff_rec(C, "Country", write_Country());
/* BIFF8: [SST *Continue] ExtSST */
if(b8 && opts.Strings) write_biff_continue(C, 0x00FC /* 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,8 +192,7 @@ function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) {
for(j = 0; j < wb.SheetNames.length; ++j) blen += (b8 ? 12 : 11) + (b8 ? 2 : 1) * wb.SheetNames[j].length;
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:0, dt:0, name:wb.SheetNames[j]}, opts));
start += bufs[j].length;
}
/* 1*BoundSheet8 */
@ -661,48 +203,19 @@ 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 */
function write_biff8_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
var o = opts || {};
var bufs = [];
if(wb && !wb.SSF) {
wb.SSF = dup(table_fmt);
}
if(wb && wb.SSF) {
make_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);
o.cellXfs = [];
get_cell_style(o.cellXfs, {}, {revssf:{"General":0}});
if(!wb.Props) wb.Props = {};
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.");
}
}
var o = opts || {};
switch(o.biff || 2) {
case 8: case 5: return write_biff8_buf(wb, opts);

View File

@ -1,247 +1,171 @@
/* 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*/);
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 = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
var merges = [], midx = 0;
for(i = 0; i < rows.length; ++i) {
var row = rows[i].trim();
var hd = row.substr(0,3).toLowerCase();
if(hd == "<tr") { ++R; C = 0; continue; }
if(hd != "<td") continue;
var cells = row.split(/<\/td>/i);
for(j = 0; j < cells.length; ++j) {
var cell = cells[j].trim();
if(cell.substr(0,3).toLowerCase() != "<td") continue;
var m = cell, cc = 0;
/* TODO: parse styles etc */
while(m.charAt(0) == "<" && (cc = m.indexOf(">")) > -1) m = m.slice(cc+1);
while(m.indexOf(">") > -1) m = m.slice(0, m.lastIndexOf("<"));
var tag = parsexmltag(cell.slice(0, cell.indexOf(">")));
CS = tag.colspan ? +tag.colspan : 1;
if((RS = +tag.rowspan)>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
/* TODO: generate stub cells */
if(!m.length) { C += CS; continue; }
m = htmldecode(unescapexml(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(opts.dense) {
if(!ws[R]) ws[R] = [];
if(!m.length){}
else if(opts.raw || !m.trim().length) ws[R][C] = {t:'s', v:m};
else if(m === 'TRUE') ws[R][C] = {t:'b', v:true};
else if(m === 'FALSE') ws[R][C] = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)};
else ws[R][C] = {t:'s', v:m};
} else {
var coord/*:string*/ = encode_cell({r:R, c:C});
/* TODO: value parsing */
if(!m.length){}
else if(opts.raw) ws[coord] = {t:'s', v:m};
else if(opts.raw || !m.trim().length) ws[coord] = {t:'s', v:m};
else if(m === 'TRUE') ws[coord] = {t:'b', v:true};
else if(m === 'FALSE') ws[coord] = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) ws[coord] = {t:'n', v:fuzzynum(m)};
else ws[coord] = {t:'s', v:m};
}
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];
}
ws['!ref'] = encode_range(range);
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 = (ws['!merges'] ||[]);
var oo = [];
var nullcell = "<td>" + (o.editable ? '<span contenteditable="true"></span>' : "" ) + "</td>";
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];
if(!cell || cell.v == null) { oo.push(nullcell); continue; }
/* TODO: html entities */
var w = cell.h || escapexml(cell.w || (format_cell(cell), cell.w) || "");
var sp = {};
if(RS > 1) sp.rowspan = RS;
if(CS > 1) sp.colspan = CS;
if(o.editable) w = '<span contenteditable="true">' + w + '</span>'
sp.id = "sjs-" + coord;
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];
/* 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.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 = [];
return out.join("") + '<table>';
}
var preamble = "<tr>";
return preamble + oo.join("") + "</tr>";
}
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("");
}
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 _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("");
}
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 parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
var opts = _opts || {};
var dense = ws["!data"] != null;
var or_R = 0, or_C = 0;
if(opts.origin != null) {
if(typeof opts.origin == 'number') or_R = opts.origin;
else {
var _origin/*:CellAddress*/ = typeof opts.origin == "string" ? decode_cell(opts.origin) : opts.origin;
or_R = _origin.r; or_C = _origin.c;
}
}
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"]) {
var _range/*:Range*/ = decode_range(ws["!ref"]);
range.s.r = Math.min(range.s.r, _range.s.r);
range.s.c = Math.min(range.s.c, _range.s.c);
range.e.r = Math.max(range.e.r, _range.e.r);
range.e.c = Math.max(range.e.c, _range.e.c);
if(or_R == -1) range.e.r = or_R = _range.e.r + 1;
}
var merges/*:Array<Range>*/ = [], midx = 0;
var rowinfo/*:Array<RowInfo>*/ = ws["!rows"] || (ws["!rows"] = []);
var _R = 0, R = 0, _C = 0, C = 0, RS = 0, CS = 0;
if(!ws["!cols"]) ws['!cols'] = [];
for(; _R < rows.length && R < sheetRows; ++_R) {
var row/*:HTMLTableRowElement*/ = rows[_R];
if (is_dom_element_hidden(row)) {
if (opts.display) continue;
rowinfo[R] = {hidden: true};
}
var elts/*:HTMLCollection<HTMLTableCellElement>*/ = (row.cells);
if(DENSE != null) opts.dense = DENSE;
var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
var rows = table.getElementsByTagName('tr');
var range = {s:{r:0,c:0},e:{r:rows.length - 1,c:0}};
var merges = [], midx = 0;
var R = 0, _C = 0, C = 0, RS = 0, CS = 0;
for(; R < rows.length; ++R) {
var row = rows[R];
var elts = row.children;
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 elt = elts[_C], v = htmldecode(elts[_C].innerHTML);
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; }
var m = merges[midx];
if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; }
}
/* TODO: figure out how to extract nonstandard mso- style */
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}});
if((RS = +elt.getAttribute("rowspan"))>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
var o/*:Cell*/ = {t:'s', v:v};
var _t/*:string*/ = elt.getAttribute("data-t") || elt.getAttribute("t") || "";
if(v != null) {
if(v.length == 0) o.t = _t || 'z';
else if(opts.raw || v.trim().length == 0 || _t == "s"){}
if(v.length == 0) o.t = 'z';
else if(opts.raw){}
else if(v.trim().length == 0) o.t = 's';
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];
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(dense) { if(!ws["!data"][R + or_R]) ws["!data"][R + or_R] = []; ws["!data"][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;
if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; }
else ws[encode_cell({c:C, r:R})] = o;
if(range.e.c < C) range.e.c = C;
C += CS;
}
++R;
}
if(merges.length) ws['!merges'] = (ws["!merges"] || []).concat(merges);
range.e.r = Math.max(range.e.r, R - 1 + or_R);
ws['!merges'] = merges;
ws['!ref'] = encode_range(range);
if(R >= sheetRows) ws['!fullref'] = encode_range((range.e.r = rows.length-_R+R-1 + or_R,range)); // We can count the real number of rows to parse but we don't to improve the performance
return ws;
}
function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
var opts = _opts || {};
var ws/*:Worksheet*/ = ({}/*:any*/); if(opts.dense) ws["!data"] = [];
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;
}
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;
return display === 'none';
}
/* global getComputedStyle */
function get_get_computed_style_function(element/*:HTMLElement*/)/*:?function*/ {
// The proper getComputedStyle implementation is the one defined in the element window
if(element.ownerDocument.defaultView && typeof element.ownerDocument.defaultView.getComputedStyle === 'function') return element.ownerDocument.defaultView.getComputedStyle;
// If it is not available, try to get one from the global namespace
if(typeof getComputedStyle === 'function') return getComputedStyle;
return null;
return sheet_to_workbook(parse_dom_table(table, opts), opts);
}

View File

@ -1,296 +1,76 @@
/* OpenDocument */
function parse_text_p(text/*:string*//*::, tag*/)/*:Array<any>*/ {
var parse_content_xml = (function() {
/* 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_text_p = function(text/*:string*/, tag)/*:string*/ {
return unescapexml(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")
.replace(/<[^>]*>/g,"")
);
};
return [v];
}
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\""]
};
/* 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;
// 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;
/* 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 Rn, q/*:: :any = ({t:"", v:null, z:null, w:"",c:[],}:any)*/;
var ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
var Rn, q/*:: = ({t:"", v:null, z:null, w:"",c:[]}:any)*/;
var ctag = ({value:""}/*:any*/);
var textp = "", textpidx = 0, textptag/*:: = {}*/, oldtextp = "", oldtextpidx = 0;
var textR = [], oldtextR = [];
var textp = "", textpidx = 0, textptag/*:: = {}*/;
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 = {};
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:{}};
var atag = ({}/*:any*/);
var _Ref/*:[string, string]*/ = ["", ""];
var comments/*:Array<Comment>*/ = [], comment/*:Comment*/ = ({}/*:any*/);
var number_format_map = {};
var merges = [], mrange = {}, mR = 0, mC = 0;
var rowinfo = [], rowpeat = 1, colpeat = 1;
var arrayf = [];
var comments = [], comment = {};
var creator = "", creatoridx = 0;
var isstub = false, intable = false;
var isstub = 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]==='/') {
if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = encode_range(range);
else ws['!ref'] = "A1:A1";
if(opts.sheetRows > 0 && opts.sheetRows <= range.e.r) {
ws['!fullref'] = ws['!ref'];
range.e.r = opts.sheetRows - 1;
ws['!ref'] = encode_range(range);
}
if(merges.length) ws['!merges'] = merges;
if(rowinfo.length) ws["!rows"] = rowinfo;
sheetag.name = sheetag['名称'] || sheetag.name;
if(typeof JSON !== 'undefined') JSON.stringify(sheetag);
sheetag.name = utf8read(sheetag['名称'] || sheetag.name);
SheetNames.push(sheetag.name);
Sheets[sheetag.name] = ws;
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;
}
break;
@ -306,12 +86,11 @@ 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;
++C;
if(opts.sheetStubs) {
if(opts.dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = {t:'z'}; }
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 */
case 'table-cell': case '数据':
if(Rn[0].charAt(Rn[0].length-2) === '/') {
@ -320,30 +99,26 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
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;
if(R > range.e.r) range.e.r = R;
if(C < range.s.c) range.s.c = C;
if(R < range.s.r) range.s.r = R;
if(rptR > range.e.r) range.e.r = rptR;
ctag = parsexmltag(Rn[0], false);
comments = []; comment = ({}/*:any*/);
comments = []; comment = {};
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']) {
@ -369,48 +144,39 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
/* 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';
if(ctag['string-value'] != null) { textp = unescapexml(ctag['string-value']); textR = []; }
if(ctag['string-value'] != null) textp = unescapexml(ctag['string-value']);
} else throw new Error('Unsupported value type ' + q.t);
}
} else {
isstub = false;
if(q.t === 's') {
q.v = textp || '';
if(textR.length) q.R = textR;
isstub = textpidx == 0;
}
if(atag.Target) q.l = atag;
if(comments.length > 0) { q.c = comments; comments = []; }
if(textp && opts.cellText !== false) q.w = textp;
if(isstub) { q.t = "z"; delete q.v; }
if(!isstub || opts.sheetStubs) {
if(!(opts.sheetRows && opts.sheetRows <= R)) {
if(!(opts.sheetRows && opts.sheetRows < R)) {
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);
@ -422,9 +188,8 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
C += colpeat-1; colpeat = 0;
q = {/*:: t:"", v:null, z:null, w:"",c:[]*/};
textp = ""; textR = [];
textp = "";
}
atag = ({}/*:any*/);
break; // 9.1.4 <table:table-cell>
/* pure state */
@ -434,7 +199,6 @@ 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
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;
@ -443,20 +207,12 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
if(Rn[1]==='/'){
if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
comment.t = textp;
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;
break;
case 'creator': // 4.3.2.7 <dc:creator>
@ -483,39 +239,36 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
case 'chart': // TODO
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], false]);
textp = ""; textpidx = 0; textR = [];
textp = ""; textpidx = 0;
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>
case 'libraries': break; // TODO: <ooo:libraries>
case 'automatic-styles': break; // 3.15.3 <office:automatic-styles>
case 'master-styles': break; // TODO: <office:master-styles>
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"]];
} break;
case 'style': break; // 16.2 <style:style>
case 'map': break; // 16.3 <style:map>
case 'font-face': break; // 16.21 <style:font-face>
@ -526,7 +279,12 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
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>
@ -541,9 +299,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]) {
@ -555,15 +320,6 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
}
else pidx = Rn.index + Rn[0].length;
break;
case 'named-range': // 9.4.12 <table:named-range>
tag = parsexmltag(Rn[0], false);
_Ref = ods_to_csf_3D(tag['cell-range-address']);
var nrange = ({Name:tag.name, Ref:_Ref[0] + '!' + _Ref[1]}/*:any*/);
if(intable) nrange.Sheet = SheetNames.length;
WB.Names.push(nrange);
break;
case 'text-content': break; // 16.27.27 <number:text-content>
case 'text-properties': break; // 16.27.27 <style:text-properties>
case 'embedded-text': break; // 16.27.4 <number:embedded-text>
@ -579,16 +335,12 @@ 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>
case 'named-expressions': break; // 9.4.11 <table:named-expressions>
case 'named-range': break; // 9.4.12 <table:named-range>
case 'label-range': break; // 9.4.9 <table:label-range>
case 'label-ranges': break; // 9.4.10 <table:label-ranges>
case 'named-expression': break; // 9.4.13 <table:named-expression>
@ -600,22 +352,16 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
case 'line-break': break; // 6.1.5 <text:line-break>
case 'span': break; // 6.1.7 <text:span>
case 'p': case '文本串': // 5.1.3 <text:p>
if(['master-styles'].indexOf(state[state.length-1][0]) > -1) break;
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; }
if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) textp = (textp.length > 0 ? textp + "\n" : "") + parse_text_p(str.slice(textpidx,Rn.index), textptag);
else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
break; // <text:p>
case 's': break; // <text:s>
case 'database-range': // 9.4.15 <table:database-range>
if(Rn[1]==='/') break;
try {
_Ref = ods_to_csf_3D(parsexmltag(Rn[0])['target-range-address']);
Sheets[_Ref[0]]['!autofilter'] = { ref:_Ref[1] };
var AutoFilter = ods_to_csf_range_3D(parsexmltag(Rn[0])['target-range-address']);
Sheets[AutoFilter[0]]['!autofilter'] = { ref: AutoFilter[1] };
} catch(e) {/* empty */}
break;
@ -636,13 +382,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:
@ -733,17 +476,7 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
case 'properties': break; // 13.7 <form:properties>
case 'property': break; // 13.8 <form:property>
case 'a': // 6.1.8 hyperlink
if(Rn[1]!== '/') {
atag = parsexmltag(Rn[0], false);
if(!atag.href) break;
atag.Target = unescapexml(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;
case 'a': break; // 6.1.8 hyperlink
/* non-standard */
case 'table-protection': break;
@ -766,30 +499,26 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
default: if(opts.WTF) throw new Error(Rn);
}
}
var out/*:Workbook*/ = ({
var out = {
Sheets: Sheets,
SheetNames: SheetNames,
Workbook: WB
}/*:any*/);
if(opts.bookSheets) delete /*::(*/out/*:: :any)*/.Sheets;
SheetNames: SheetNames
};
if(opts.bookSheets) delete out.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) var manifest = 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);
}

View File

@ -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,211 +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>';
return function wso(/*::wb, opts*/) {
}) + '></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>*/ = [];
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']||"A1");
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 o = [];
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n');
var R=0,C=0, range = decode_range(ws['!ref']);
var marr = ws['!merges'] || [], mi = 0;
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 = "";
@ -242,12 +53,12 @@ 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) {
if(cell.F.slice(0, ref.length) == ref) {
if(cell.F.substr(0, ref.length) == ref) {
var _Fref = decode_range(cell.F);
ct['table:number-matrix-columns-spanned'] = (_Fref.e.c - _Fref.s.c + 1);
ct['table:number-matrix-rows-spanned'] = (_Fref.e.r - _Fref.s.r + 1);
@ -267,89 +78,28 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
ct['office:value'] = (cell.v||0);
break;
case 's': case 'str':
textp = cell.v == null ? "" : cell.v;
textp = 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;")});
}
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', write_text_p(textp), {}), 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(' <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');
@ -357,33 +107,8 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
o.push(' <number:text>/</number:text>\n');
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"); }
}
}
});
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) {
@ -434,18 +159,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>');
@ -457,42 +176,43 @@ 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);
var zip = zip_new();
/*:: if(!jszip) throw new Error("JSZip is not available"); */
var zip = new jszip();
var f = "";
var manifest/*:Array<Array<string> >*/ = [];
var rdf/*:Array<[string, string]>*/ = [];
var rdf = [];
/* Part 3 Section 3.3 MIME Media Type */
f = "mimetype";
zip_add_file(zip, f, "application/vnd.oasis.opendocument.spreadsheet");
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
/* Part 1 Section 2.2 Documents */
f = "content.xml";
zip_add_file(zip, f, write_content_ods(wb, opts));
zip.file(f, write_content_ods(wb, opts));
manifest.push([f, "text/xml"]);
rdf.push([f, "ContentFile"]);
/* TODO: these are hard-coded styles to satiate excel */
f = "styles.xml";
zip_add_file(zip, f, write_styles_ods(wb, opts));
zip.file(f, write_styles_ods(wb, opts));
manifest.push([f, "text/xml"]);
rdf.push([f, "StylesFile"]);
/* TODO: this is hard-coded to satiate excel */
f = "meta.xml";
zip_add_file(zip, f, XML_HEADER + write_meta_ods(/*::wb, opts*/));
zip.file(f, write_meta_ods(wb, opts));
manifest.push([f, "text/xml"]);
rdf.push([f, "MetadataFile"]);
/* Part 3 Section 6 Metadata Manifest File */
f = "manifest.rdf";
zip_add_file(zip, f, write_rdf(rdf/*, opts*/));
zip.file(f, write_rdf(rdf, opts));
manifest.push([f, "application/rdf+xml"]);
/* Part 3 Section 4 Manifest File */
f = "META-INF/manifest.xml";
zip_add_file(zip, f, write_manifest(manifest/*, opts*/));
zip.file(f, write_manifest(manifest, opts));
return zip;
}

24
bits/82_sheeter.js Normal file
View 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(SYLK);
var write_dif_str = write_obj_str(DIF);
var write_prn_str = write_obj_str(PRN);
var write_rtf_str = write_obj_str(RTF);
var write_txt_str = write_obj_str({from_sheet:sheet_to_txt});
// $FlowIgnore
var write_dbf_buf = write_obj_str(DBF);

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