forked from sheetjs/sheetjs
Compare commits
104 Commits
master
...
protobi/ma
Author | SHA1 | Date | |
---|---|---|---|
|
8f7a29464d | ||
|
6d0f51fc98 | ||
|
6226e1afe8 | ||
|
92333227c4 | ||
|
c86472d281 | ||
|
f2520b7223 | ||
|
68ba4e8f58 | ||
|
c224819b16 | ||
|
a03dc219ab | ||
|
f959b02ae9 | ||
|
9edf279467 | ||
|
1903cff791 | ||
|
6e6678960c | ||
|
d5092b42cb | ||
|
d3f63434a0 | ||
|
796fbb515a | ||
|
3c7f807bfa | ||
|
34d618c8fe | ||
|
245ffb895a | ||
|
8198744d58 | ||
|
2424890518 | ||
|
0b8e5386bb | ||
|
eef7da3099 | ||
|
876c4a0552 | ||
|
bed6327d22 | ||
|
2ec18e96ba | ||
|
050b74edbf | ||
|
0e62411e83 | ||
|
aceebf4690 | ||
|
9407fe8aeb | ||
|
166d0e33bf | ||
|
fe748adc01 | ||
|
f984bd6479 | ||
|
7de41c2657 | ||
|
0bf1153da5 | ||
|
376096b151 | ||
|
bbeec3edfd | ||
|
43f569884a | ||
|
d4e0b8b172 | ||
|
634699fb16 | ||
|
2886195440 | ||
|
8b1add6659 | ||
|
fd83f20b40 | ||
|
03b755b3ae | ||
|
d00f36f94f | ||
|
599f285dfd | ||
|
905c51206b | ||
|
7461389d49 | ||
|
57b6fd4662 | ||
|
348c533f6c | ||
|
3e3633ad52 | ||
|
d76234ae80 | ||
|
0d1281cc94 | ||
|
dcf6f17455 | ||
|
f52c80eef6 | ||
|
e7b06d7a62 | ||
|
1ca3c3e6b5 | ||
|
c034eda675 | ||
|
3010d93f40 | ||
|
d60a0a5b89 | ||
|
a6023550ee | ||
|
9145958b40 | ||
|
0096c09dd3 | ||
|
8801e76e3f | ||
|
0255a05f14 | ||
|
4099a24cfa | ||
|
ed0cd9b2c1 | ||
|
858abf1103 | ||
|
21e1976f82 | ||
|
40cfb0cf8f | ||
|
acf60c22bc | ||
|
c2873831ca | ||
|
5dbf215c9c | ||
|
89066b45b6 | ||
|
51b7cabd2c | ||
|
08e648bbb5 | ||
|
0b1a0408cb | ||
|
5f9576a6d2 | ||
|
114f257ce4 | ||
|
9102c8214d | ||
|
8da3738378 | ||
|
995f5e89bf | ||
|
37a031caee | ||
|
27a300b862 | ||
|
33c32f0647 | ||
|
4f4f7fc6bc | ||
|
ad2a1203f1 | ||
|
0e2b8a499d | ||
|
1a51c40423 | ||
|
9b76f6b1f5 | ||
|
aa8f3a759f | ||
|
33dc7b883d | ||
|
97d4001343 | ||
|
c3af249415 | ||
|
5e443310f8 | ||
|
91ec052ae6 | ||
|
1f02e5bea2 | ||
|
05b58d839a | ||
|
576b59f96a | ||
|
cd2b20f7e5 | ||
|
5f7a0f2ad2 | ||
|
a562150b96 | ||
|
845d2a8880 | ||
|
0227496616 |
BIN
.DS_Store
vendored
Normal file
BIN
.DS_Store
vendored
Normal file
Binary file not shown.
@ -1 +0,0 @@
|
||||
xlsx.js
|
12
.eslintmjs
12
.eslintmjs
@ -1,12 +0,0 @@
|
||||
{
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 2020
|
||||
},
|
||||
"plugins": [
|
||||
"tree-shaking"
|
||||
],
|
||||
"rules": {
|
||||
"tree-shaking/no-side-effects-in-initialization": 2
|
||||
}
|
||||
}
|
26
.eslintrc
26
.eslintrc
@ -1,26 +0,0 @@
|
||||
{
|
||||
"env": { "shared-node-browser":true },
|
||||
"globals": {},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 3
|
||||
},
|
||||
"plugins": [ "html", "json" ],
|
||||
"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" ]
|
||||
}
|
||||
}
|
40
.flowconfig
40
.flowconfig
@ -1,40 +0,0 @@
|
||||
[ignore]
|
||||
.*/node_modules/.*
|
||||
.*/dist/.*
|
||||
.*/tmp/.*
|
||||
|
||||
.*/bits/.*
|
||||
.*/ctest/.*
|
||||
.*/misc/.*
|
||||
.*/perf/.*
|
||||
.*/_book/.*
|
||||
.*/packages/.*
|
||||
|
||||
.*/demo/browser.js
|
||||
.*/shim.js
|
||||
|
||||
.*/xlsx.js
|
||||
.*/xlsx.mini.js
|
||||
.*/xlsx.mini.flow.js
|
||||
.*/xlsxworker.js
|
||||
.*/tests/.*
|
||||
.*/demos/.*
|
||||
|
||||
#.*/xlsx.flow.js
|
||||
[include]
|
||||
xlsxworker.flow.js
|
||||
xlsx.flow.js
|
||||
.*/bin/.*.njs
|
||||
.*/demo/browser.flow.js
|
||||
test.js
|
||||
|
||||
[libs]
|
||||
bits/09_types.js
|
||||
misc/flow.js
|
||||
misc/flowdeps.js
|
||||
|
||||
[options]
|
||||
module.file_ext=.js
|
||||
module.file_ext=.njs
|
||||
module.ignore_non_literal_requires=true
|
||||
suppress_comment= \\(.\\|\n\\)*\\$FlowIgnore
|
17
.gitattributes
vendored
17
.gitattributes
vendored
@ -1,17 +0,0 @@
|
||||
*.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
3
.github/FUNDING.yml
vendored
@ -1,3 +0,0 @@
|
||||
github: SheetJSDev
|
||||
custom: https://sheetjs.com
|
||||
open_collective: s5s
|
20
.github/workflows/bun.yml
vendored
20
.github/workflows/bun.yml
vendored
@ -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'
|
39
.github/workflows/deno.yml
vendored
39
.github/workflows/deno.yml
vendored
@ -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
|
92
.github/workflows/node-4+.yml
vendored
92
.github/workflows/node-4+.yml
vendored
@ -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'
|
45
.github/workflows/node-iojs.yml
vendored
45
.github/workflows/node-iojs.yml
vendored
@ -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'
|
32
.github/workflows/node-pretest.yml
vendored
32
.github/workflows/node-pretest.yml
vendored
@ -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
|
88
.github/workflows/node-zero.yml
vendored
88
.github/workflows/node-zero.yml
vendored
@ -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'
|
15
.github/workflows/rebase.yml
vendored
15
.github/workflows/rebase.yml
vendored
@ -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 }}
|
12
.github/workflows/require-allow-edits.yml
vendored
12
.github/workflows/require-allow-edits.yml
vendored
@ -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
|
52
.gitignore
vendored
52
.gitignore
vendored
@ -1,43 +1,27 @@
|
||||
node_modules
|
||||
package-lock.json
|
||||
*.tgz
|
||||
_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]
|
||||
*.txt
|
||||
*.csv
|
||||
*.dif
|
||||
*.prn
|
||||
*.slk
|
||||
*.socialcalc
|
||||
*.[xX][lL][sSwWcCaAtTmMrR]
|
||||
*.[xX][lL][sSaAtT][xXmMbB]
|
||||
*.[oO][dD][sS]
|
||||
*.[fF][oO][dD][sS]
|
||||
*.[xX][mM][lL]
|
||||
*.[xX][lL][mM][lL]
|
||||
*.[uU][oO][sS]
|
||||
*.[wW][kKqQbB][sS1234567890]
|
||||
*.[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
|
||||
*.xls
|
||||
*.xlsb
|
||||
*.xlsm
|
||||
*.xlsx
|
||||
*.xlsm
|
||||
*.xlsb
|
||||
*.xml
|
||||
*.htm
|
||||
*.html
|
||||
*.sheetjs
|
||||
*.exe
|
||||
*.img
|
||||
test_files.zip
|
||||
test_files/
|
||||
|
||||
lab/
|
||||
test_files
|
||||
example.js
|
||||
example2.js
|
||||
.idea
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -0,0 +1,3 @@
|
||||
[submodule "test_files"]
|
||||
path = test_files
|
||||
url = https://github.com/SheetJS/test_files
|
63
.npmignore
63
.npmignore
@ -1,76 +1,35 @@
|
||||
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]
|
||||
*.txt
|
||||
*.csv
|
||||
*.dif
|
||||
*.prn
|
||||
*.slk
|
||||
*.socialcalc
|
||||
*.[xX][lL][sSwWcCaAtTmMrR]
|
||||
*.[xX][lL][sSaAtT][xXmMbB]
|
||||
*.[oO][dD][sS]
|
||||
*.[fF][oO][dD][sS]
|
||||
*.[xX][mM][lL]
|
||||
*.[xX][lL][mM][lL]
|
||||
*.[uU][oO][sS]
|
||||
*.[wW][kKqQbB][S1234567890]
|
||||
*.[qQ][pP][wW]
|
||||
*.[fF][mM][3tT]
|
||||
*.[bB][iI][fF][fF][23458]
|
||||
*.[rR][tT][fF]
|
||||
*.[eE][tT]
|
||||
*.[eE][tT][hH]
|
||||
*.[nN][uU][mM][bB][eE][rR][sS]
|
||||
*.[mM][oO][dD]
|
||||
*.123
|
||||
*.xls
|
||||
*.xlsb
|
||||
*.xlsm
|
||||
*.xlsx
|
||||
*.xml
|
||||
*.htm
|
||||
*.html
|
||||
*.sheetjs
|
||||
*.exe
|
||||
*.img
|
||||
.gitignore
|
||||
.gitattributes
|
||||
.fossaignore
|
||||
.spelling
|
||||
.eslintignore
|
||||
.eslintrc
|
||||
.eslintmjs
|
||||
.jshintrc
|
||||
xlsx.mini.js
|
||||
CONTRIBUTING.md
|
||||
Makefile
|
||||
make.cmd
|
||||
*.lst
|
||||
.npmignore
|
||||
xlsworker.js
|
||||
shim.js
|
||||
test.js
|
||||
test.mjs
|
||||
test.ts
|
||||
test.mts
|
||||
testnocp.ts
|
||||
testbun.mjs
|
||||
.jscs.json
|
||||
.gitmodules
|
||||
.travis.yml
|
||||
.flowconfig
|
||||
*.flow.js
|
||||
bits/
|
||||
docbits/
|
||||
odsbits/
|
||||
tests/
|
||||
|
189
.spelling
189
.spelling
@ -1,189 +0,0 @@
|
||||
# xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com
|
||||
SheetJS
|
||||
sheetjs
|
||||
js-xlsx
|
||||
xls
|
||||
xlsb
|
||||
xlsx
|
||||
|
||||
# Excel-related terms
|
||||
A1-style
|
||||
AutoFilter
|
||||
ECMA-376
|
||||
FoxPro
|
||||
Multiplan
|
||||
OData
|
||||
OpenDocument
|
||||
OpenFormula
|
||||
PivotTable
|
||||
PivotTables
|
||||
Quattro
|
||||
SpreadsheetML
|
||||
Unhide
|
||||
VBA
|
||||
Visicalc
|
||||
chartsheet
|
||||
chartsheets
|
||||
dialogsheet
|
||||
dialogsheets
|
||||
dBASE
|
||||
macrosheet
|
||||
macrosheets
|
||||
tooltip
|
||||
tooltips
|
||||
|
||||
# Third-party
|
||||
Browserify
|
||||
CDNjs
|
||||
CommonJS
|
||||
Deno
|
||||
Ethercalc
|
||||
ExtendScript
|
||||
InDesign
|
||||
IndexedDB
|
||||
JavaScriptCore
|
||||
LocalStorage
|
||||
NestJS
|
||||
NPM
|
||||
Nuxt
|
||||
PhantomJS
|
||||
Photoshop
|
||||
Redis
|
||||
RequireJS
|
||||
Rollup
|
||||
SessionStorage
|
||||
SQLite
|
||||
SystemJS
|
||||
Vite
|
||||
VueJS
|
||||
WebKit
|
||||
WebSQL
|
||||
WK_
|
||||
iOS
|
||||
iWork
|
||||
nodejs
|
||||
node.js
|
||||
npm
|
||||
unpkg
|
||||
webpack
|
||||
weex
|
||||
|
||||
# Other terms
|
||||
1.x
|
||||
2.x
|
||||
3.x
|
||||
4.x
|
||||
5.x
|
||||
6.x
|
||||
7.x
|
||||
8.x
|
||||
9.x
|
||||
ActiveX
|
||||
APIs
|
||||
ArrayBuffer
|
||||
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
|
||||
|
||||
- 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
|
||||
wkhtmltopdf
|
||||
|
||||
- demos/nwjs/README.md
|
||||
NW.js
|
||||
|
||||
- demos/react/README.md
|
||||
Next.js
|
||||
Preact
|
||||
|
||||
- demos/server/README.md
|
||||
hapi
|
||||
|
||||
- demos/showcase/README.md
|
||||
vscode-data-preview
|
||||
|
||||
- demos/xhr/README.md
|
||||
axios
|
||||
superagent
|
||||
|
58
.travis.yml
58
.travis.yml
@ -1,58 +1,16 @@
|
||||
language: node_js
|
||||
dist: xenial
|
||||
node_js:
|
||||
- "14"
|
||||
- "13"
|
||||
- "12"
|
||||
- "11"
|
||||
- "10"
|
||||
- "9"
|
||||
- "8"
|
||||
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: "8"
|
||||
env: TZ="Asia/Shanghai" 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"
|
||||
env: TZ="Pacific/Honolulu" FMTS=misc
|
||||
- node_js: "0.8"
|
||||
env: TZ="America/Mexico_City" FMTS=misc
|
||||
|
||||
- "iojs"
|
||||
- "0.11.14"
|
||||
- "0.10"
|
||||
# - "0.8" # commented because of npm issue with camelcase
|
||||
before_install:
|
||||
- "npm config set strict-ssl false"
|
||||
- "./misc/node_version.sh"
|
||||
- "npm install -g mocha@2.x voc"
|
||||
- "npm install -g mocha"
|
||||
- "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"
|
||||
before_script:
|
||||
- "make init"
|
||||
- "cd test_files; make all; cd -"
|
||||
- "cd test_files; make all; cd -"
|
||||
after_success:
|
||||
# - "make coveralls-spin"
|
||||
- "make coveralls-spin"
|
||||
|
365
CHANGELOG.md
365
CHANGELOG.md
@ -1,365 +0,0 @@
|
||||
# CHANGELOG
|
||||
|
||||
This log is intended to keep track of backwards-incompatible changes, including
|
||||
but not limited to API changes and file location changes. Minor behavioral
|
||||
changes may not be included if they are not expected to break existing code.
|
||||
|
||||
* Sheet Visibility for ODS / FODS (h/t @edemaine)
|
||||
* HTML DOM ingress support formulae (`data-f`)
|
||||
* Proper handling of XLSX encoded entities (h/t @inreoh)
|
||||
|
||||
## v0.20.3
|
||||
|
||||
* Correct parsing of NUMBERS and ODS merge cells (h/t @s-ashwin)
|
||||
* More precise treatment of infinite and NaN values
|
||||
* XLML Streaming Write
|
||||
* Parse `Int8Array` objects (for compatibility with JS engines in Java)
|
||||
* CSV Export only quote leading ID (h/t @lako12)
|
||||
|
||||
## v0.20.2
|
||||
|
||||
* Reworked parsing methods to avoid slow regexes (CVE-2024-22363)
|
||||
* HTML properly encode data-v attribute
|
||||
* SYLK read and write error cells
|
||||
|
||||
## v0.20.1
|
||||
|
||||
* `init` use packaged test files to work around GitHub breaking changes
|
||||
* SSF date code rounding to 15 decimal digits (h/t @davidtamaki)
|
||||
* `sheet_to_json` force UTC interpretation for formatted strings (h/t @Blanay)
|
||||
* QPW extract result of string formula
|
||||
* XLSX parse non-compliant merge cell expressions
|
||||
* NUMBERS correctly handle rows omitted from official exports
|
||||
* DBF parse empty logical field (h/t @Roman91)
|
||||
* `dense` option added to types
|
||||
* package.json add mini and core scripts to export map (h/t @stof)
|
||||
|
||||
## v0.20.0
|
||||
|
||||
* Use UTC interpretation of Date objects for date cells (potentially breaking)
|
||||
* API functions support UTC and local time value interpretations
|
||||
* Export `NaN` values to `#NUM!` and infinite values to `#DIV/0!`
|
||||
|
||||
## v0.19.3
|
||||
|
||||
* XLSX Ensure comment address is valid (h/t @slonser)
|
||||
* Enforce Excel worksheet name restrictions
|
||||
* Fixed "Prototype Pollution" vulnerability (CVE-2023-30533)
|
||||
|
||||
## v0.19.2
|
||||
|
||||
* XLSX proper decoding of hyperlinks (h/t @tw-yaxu)
|
||||
* XLSX ignore unexpected attributes in rich text (h/t @colin4)
|
||||
* `sheet_to_json` type fix (h/t @chsdwn)
|
||||
|
||||
## v0.19.1
|
||||
|
||||
* Fixed types issue in strict mode (h/t @younes-io)
|
||||
* Numbers 12.2 parsing skip ActivityStream.iwa
|
||||
|
||||
## v0.19.0
|
||||
|
||||
* XLSX export hyperlinks compatible with google sheets (h/t Evan Bovie)
|
||||
* NUMBERS export multiple sheets, full worksheet range
|
||||
* formalized `dense` mode
|
||||
|
||||
## v0.18.12
|
||||
|
||||
* `package.json` added types in `exports` structure
|
||||
* uncapped NUMBERS single-sheet single-table export
|
||||
* DBF export records using supported codepages
|
||||
|
||||
## v0.18.11
|
||||
|
||||
* Base64 input ignore data URI wrapper
|
||||
* Parse ZIP files that use ZIP64 extended information field
|
||||
* More precise handling of time-only values
|
||||
* Threaded Comment fallback text for older Excel
|
||||
|
||||
## v0.18.10
|
||||
|
||||
* `exports` field in package.json to satiate ViteJS and newer tooling
|
||||
* JSC (Safari / Bun) perf, see <https://bugs.webkit.org/show_bug.cgi?id=243148>
|
||||
* workbook `bookType` property to denote the origin format when parsed from file
|
||||
* XLSX force export of stub cells with number formats when `sheetStubs` is set
|
||||
|
||||
## v0.18.9
|
||||
|
||||
* XLSX / ODS write defined names
|
||||
* sync defined names to AutoFilter setting on export
|
||||
* 1904 date system setting properly roundtripped
|
||||
* ODS read/write number formats
|
||||
|
||||
## v0.18.8
|
||||
|
||||
* Plaintext parsing of dateless meridien time values (`1:23:45 PM`)
|
||||
* Legacy format (SYLK / WK# / Multiplan) minutiae
|
||||
|
||||
## v0.18.7
|
||||
|
||||
* Normalized handling of `\r` and `\n` newline characters
|
||||
|
||||
## v0.18.6
|
||||
|
||||
* Removed all npm dependencies
|
||||
* Auto-correct bad Google Sheets format `d.m`
|
||||
* NUMBERS write merge cells, cells up to column "ALL"
|
||||
|
||||
## v0.18.5
|
||||
|
||||
* Enabled `sideEffects: false` in package.json
|
||||
* Basic NUMBERS write support
|
||||
|
||||
## v0.18.4
|
||||
|
||||
* CSV output omits trailing record separator
|
||||
* Properly terminate NodeJS Streams
|
||||
* DBF preserve column types on import and use when applicable on export
|
||||
|
||||
## v0.18.3
|
||||
|
||||
* Removed references to `require` and `process` in browser builds
|
||||
|
||||
## v0.18.2
|
||||
|
||||
* Hotfix for unicode processing of XLSX exports
|
||||
|
||||
## v0.18.1
|
||||
|
||||
* Removed Node ESM build script and folded into standard ESM build
|
||||
* Removed undocumented aliases including `make_formulae` and `get_formulae`
|
||||
|
||||
## v0.18.0
|
||||
|
||||
* Browser scripts only expose `XLSX` variable
|
||||
* Module no longer ships with `dist/jszip.js` browser script
|
||||
|
||||
## v0.17.4
|
||||
|
||||
* CLI script moved to `xlsx-cli` package
|
||||
|
||||
## v0.17.3
|
||||
|
||||
* `window.XLSX` explicit assignment to satiate LWC
|
||||
* CSV Proper formatting of errors
|
||||
* HTML emit data-\* attributes
|
||||
|
||||
## v0.17.2
|
||||
|
||||
* Browser and Node optional ESM support
|
||||
* DSV correct handling of bare quotes (h/t @bgamrat)
|
||||
|
||||
## v0.17.1
|
||||
|
||||
* `XLSB` writer uses short cell form when viable
|
||||
|
||||
## 0.17.0:
|
||||
|
||||
* mini build includes ODS parse/write support
|
||||
* DBF explicitly cap worksheet to 1<<20 rows
|
||||
* XLS throw errors on truncated records
|
||||
|
||||
## v0.16.2
|
||||
|
||||
* Disabled `PRN` parsing by default (better support for CSV without delimeters)
|
||||
|
||||
## 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
|
||||
|
||||
## 0.11.5 (2017-09-30)
|
||||
|
||||
* Bower main script shifted to full version
|
||||
* 'binary' / 'string' encoding
|
||||
|
||||
## 0.11.3 (2017-08-19)
|
||||
|
||||
* XLS cell ixfe/XF removed
|
||||
|
||||
## 0.11.0 (2017-07-31)
|
||||
|
||||
* Strip `require` statements from minified version
|
||||
* minifier mangler enabled
|
||||
|
||||
## 0.10.9 (2017-07-28)
|
||||
|
||||
* XLML/HTML resolution logic looks further into the data stream to decide type
|
||||
* Errors thrown on suspected RTF files
|
||||
|
||||
## 0.10.5 (2017-06-09)
|
||||
|
||||
* HTML Table output header/footer should not include `<table>` tag
|
||||
|
||||
## 0.10.2 (2017-05-16)
|
||||
|
||||
* Dates are converted to numbers by default (set `cellDates:true` to emit Dates)
|
||||
* Module does not export CFB
|
||||
|
||||
## 0.9.10 (2017-04-08)
|
||||
|
||||
* `--perf` renamed to `--read-only`
|
||||
|
||||
## 0.9.9 (2017-04-03)
|
||||
|
||||
* default output format changed to XLSB
|
||||
* comment text line endings are now normalized
|
||||
* errors thrown on write when worksheets have invalid names
|
||||
|
||||
## 0.9.7 (2017-03-28)
|
||||
|
||||
* XLS legacy `!range` field removed
|
||||
* Hyperlink tooltip is stored in the `Tooltip` field
|
||||
|
||||
## 0.9.6 (2017-03-25)
|
||||
|
||||
* `sheet_to_json` now passes `null` values when `raw` is set to `true`
|
||||
* `sheet_to_json` treats `null` stub cells as values in conjunction with `raw`
|
||||
|
||||
## 0.9.5 (2017-03-22)
|
||||
|
||||
* `cellDates` affects parsing in non-XLSX formats
|
||||
|
||||
## 0.9.3 (2017-03-15)
|
||||
|
||||
* XLML property names are more closely mapped to the XLSX equivalent
|
||||
* Stub cells are now cell type `z`
|
||||
|
||||
## 0.9.2 (2017-03-13)
|
||||
|
||||
* Removed stale TypeScript definition files. Flowtype comments are used in the
|
||||
`xlsx.flow.js` source and stripped to produce `xlsx.js`.
|
||||
* sed usage reworked to support GNU sed in-place form. BSD sed seems to work,
|
||||
but the build script has not been tested on other sed variants:
|
||||
|
||||
```bash
|
||||
$ sed -i.ext [...] # GNU
|
||||
$ sed -i .ext [...] # bsd
|
||||
```
|
||||
|
||||
## 0.9.0 (2017-03-09)
|
||||
|
||||
* Removed ods.js source. The xlsx.js source absorbed the ODS logic and exposes
|
||||
the ODS variable, so projects should remove references to ods.js
|
||||
|
@ -4,17 +4,17 @@ The SheetJS Libraries should be free and clear to use in your projects. In
|
||||
order to maintain that, every contributor must be vigilant.
|
||||
|
||||
There have been many projects in the past that have been very lax regarding
|
||||
licensing. We are of the opinion that those are ticking timebombs and that no
|
||||
commercial product should depend on them.
|
||||
licensing, and we are of the opinion that those are ticking timebombs and that
|
||||
no commercial product should depend on them.
|
||||
|
||||
|
||||
# Required Reading
|
||||
|
||||
These are pretty short reads and emphasize the importance of proper licensing:
|
||||
|
||||
- https://github.com/jazzband/tablib/issues/114 (discussion of other tools)
|
||||
- https://github.com/kennethreitz/tablib/issues/114 (discussion of other tools)
|
||||
|
||||
- https://web.archive.org/web/20120615223756/http://www.codinghorror.com/blog/2007/04/pick-a-license-any-license.html
|
||||
- http://www.codinghorror.com/blog/2007/04/pick-a-license-any-license.html
|
||||
|
||||
|
||||
# Raising Issues
|
||||
@ -28,12 +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
|
||||
|
||||
[Squash commits](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History)
|
||||
before opening a pull request, If the pull request addresses documentation or
|
||||
demos, add `[ci skip]` in the body or title of the commit message to skip tests.
|
||||
|
||||
# Pre-Contribution Checklist
|
||||
|
||||
Before thinking about contributing, make sure that:
|
||||
@ -56,8 +50,8 @@ issue. If it is a particularly high-priority issue, please drop an email to
|
||||
Keep these in mind as you work:
|
||||
|
||||
- Your contributions are your original work. Take note of any resources you
|
||||
consult in the process. Be extra careful not to use unlicensed code on the
|
||||
Internet or code generated by a large language model or other AI tool.
|
||||
consult in the process (and be extra careful not to use unlicensed code on
|
||||
the internet.
|
||||
|
||||
- You are working on your own time. Unless they explicitly grant permission,
|
||||
your employer may be the ultimate owner of your IP
|
||||
@ -66,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.
|
||||
|
194
LICENSE
194
LICENSE
@ -1,192 +1,4 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright (C) 2012-present SheetJS LLC
|
||||
Copyright (C) 2012-2015 SheetJS
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -199,3 +11,7 @@
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Except where noted, this license applies to any and all software programs and associated documentation files created by the Original Author and distributed with the Software:
|
||||
|
||||
'jszip.js' is a modified version of JSZip, Copyright (c) Stuart Knightley, David Duponchel, Franz Buchinger, Ant'onio Afonso. JSZip is dual licensed and is used according to the terms of the MIT License.
|
||||
|
287
Makefile
287
Makefile
@ -1,269 +1,116 @@
|
||||
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)
|
||||
|
||||
AUXTARGETS=ods.js
|
||||
|
||||
ULIB=$(shell echo $(LIB) | tr a-z A-Z)
|
||||
DEPS=$(sort $(wildcard bits/*.js))
|
||||
TSBITS=$(patsubst modules/%,bits/%,$(wildcard modules/[0-9][0-9]_*.js))
|
||||
MTSBITS=$(patsubst modules/%,misc/%,$(wildcard modules/[0-9][0-9]_*.js))
|
||||
TARGET=$(LIB).js
|
||||
FLOWTARGET=$(LIB).flow.js
|
||||
FLOWAUX=$(patsubst %.js,%.flow.js,$(AUXTARGETS))
|
||||
AUXSCPTS=xlsxworker.js
|
||||
FLOWTGTS=$(TARGET) $(AUXTARGETS) $(AUXSCPTS) $(MINITGT)
|
||||
UGLIFYOPTS=--support-ie8 -m
|
||||
CLOSURE=/usr/local/lib/node_modules/google-closure-compiler/compiler.jar
|
||||
|
||||
## Main Targets
|
||||
|
||||
.PHONY: all
|
||||
all: $(TARGET) $(AUXTARGETS) $(AUXSCPTS) $(MINITGT) $(ESMJSTGT) ## Build library and auxiliary scripts
|
||||
all: $(TARGET) $(AUXTARGETS)
|
||||
|
||||
$(FLOWTGTS): %.js : %.flow.js
|
||||
node -e 'process.stdout.write(require("fs").readFileSync("$<","utf8").replace(/^[ \t]*\/\*[:#][^*]*\*\/\s*(\n)?/gm,"").replace(/\/\*[:#][^*]*\*\//gm,""))' > $@
|
||||
|
||||
$(FLOWTARGET): $(DEPS)
|
||||
cat $^ | tr -d '\15\32' > $@
|
||||
|
||||
$(MINIFLOW): $(MINIDEPS)
|
||||
cat $^ | tr -d '\15\32' > $@
|
||||
|
||||
$(ESMJSTGT): $(ESMJSDEPS)
|
||||
$(TARGET): $(DEPS)
|
||||
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/dist/xlscfb.js
|
||||
cp $^ $@
|
||||
|
||||
$(MTSBITS): misc/%: modules/%
|
||||
cp $^ $@
|
||||
|
||||
|
||||
.PHONY: clean
|
||||
clean: ## Remove targets and build artifacts
|
||||
rm -f $(TARGET) $(FLOWTARGET) $(ESMJSTGT) $(MINITGT) $(MINIFLOW)
|
||||
clean:
|
||||
rm -f $(TARGET)
|
||||
|
||||
.PHONY: clean-data
|
||||
clean-data:
|
||||
rm -f *.xlsx *.xlsm *.xlsb *.xls *.xml
|
||||
|
||||
.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
|
||||
mkdir -p tmp
|
||||
init:
|
||||
git submodule init
|
||||
git submodule update
|
||||
git submodule foreach git pull origin master
|
||||
git submodule foreach make
|
||||
|
||||
DISTHDR=misc/suppress_export.js
|
||||
.PHONY: dist
|
||||
dist: dist-deps $(TARGET) bower.json ## Prepare JS files for distribution
|
||||
mkdir -p dist
|
||||
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)"
|
||||
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
|
||||
|
||||
.PHONY: aux
|
||||
aux: $(AUXTARGETS)
|
||||
|
||||
BYTEFILEC=dist/xlsx.{full,core,mini}.min.js xlsx.mjs
|
||||
BYTEFILER=dist/xlsx.extendscript.js
|
||||
.PHONY: bytes
|
||||
bytes: ## Display minified and gzipped file sizes
|
||||
@for i in $(BYTEFILEC); do npx printj "%-30s %7d %10d" $$i $$(wc -c < $$i) $$(gzip --best --stdout $$i | wc -c); done
|
||||
@for i in $(BYTEFILER); do npx printj "%-30s %7d" $$i $$(wc -c < $$i); done
|
||||
@npx printj "%-30s %10d" "treeshake" "$$(npx -y esbuild@0.14.14 --bundle misc/import.js | wc -c)"
|
||||
|
||||
|
||||
.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 $<
|
||||
|
||||
## Testing
|
||||
|
||||
.PHONY: test mocha
|
||||
test mocha: test.js ## Run test suite
|
||||
mocha -R spec -t 30000
|
||||
test mocha: test.js
|
||||
mkdir -p tmp
|
||||
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: test.test.mjs ## Run Bun test suite
|
||||
bun test $<
|
||||
|
||||
.PHONY: test-deno
|
||||
test-deno: test.ts ## Run Deno test suite
|
||||
deno test --check --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $<
|
||||
|
||||
.PHONY: test-denocp
|
||||
test-denocp: testnocp.ts ## Run Deno test suite (without codepage)
|
||||
deno test --check --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $<
|
||||
.PHONY: prof
|
||||
prof:
|
||||
cat misc/prof.js test.js > prof.js
|
||||
node --prof prof.js
|
||||
|
||||
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
|
||||
|
||||
.PHONY: ctest
|
||||
ctest: ## Build browser test fixtures
|
||||
node tests/make_fixtures.js
|
||||
|
||||
.PHONY: ctestserv
|
||||
ctestserv: ## Start a test server on port 8000
|
||||
@cd tests && python -mSimpleHTTPServer || python3 -mhttp.server || npx -y http-server -p 8000 .
|
||||
|
||||
## Code Checking
|
||||
|
||||
.PHONY: fullint
|
||||
fullint: lint mdlint ## Run all checks (removed: old-lint, tslint, flow)
|
||||
|
||||
.PHONY: lint
|
||||
lint: $(TARGET) $(AUXTARGETS) ## Run eslint checks
|
||||
@./node_modules/.bin/eslint --ext .js,.njs,.json,.html,.htm $(FLOWTARGET) $(AUXTARGETS) $(CMDS) $(HTMLLINT) package.json bower.json
|
||||
@if [ -x "$(CLOSURE)" ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi
|
||||
lint: $(TARGET)
|
||||
jshint --show-non-errors $(TARGET) $(AUXTARGETS)
|
||||
jshint --show-non-errors package.json bower.json
|
||||
jscs $(TARGET) $(AUXTARGETS)
|
||||
|
||||
.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
|
||||
.PHONY: test-osx
|
||||
test-osx:
|
||||
node tests/write.js
|
||||
open -a Numbers sheetjs.xlsx
|
||||
open -a "Microsoft Excel" sheetjs.xlsx
|
||||
|
||||
.PHONY: tslint
|
||||
tslint: $(TARGET) ## Run typescript checks
|
||||
#@npm install dtslint typescript
|
||||
#@npm run-script dtslint
|
||||
./node_modules/.bin/dtslint types
|
||||
.PHONY: cov cov-spin
|
||||
cov: misc/coverage.html
|
||||
cov-spin:
|
||||
make cov & bash misc/spin.sh $$!
|
||||
|
||||
.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 $<
|
||||
|
||||
.PHONY: cov
|
||||
cov: misc/coverage.html ## Run coverage test
|
||||
|
||||
#* To run coverage tests for one format, make cov_<fmt>
|
||||
COVFMT=$(patsubst %,cov_%,$(FMT))
|
||||
.PHONY: $(COVFMT)
|
||||
$(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 > $@
|
||||
|
||||
.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
|
||||
.PHONY: coveralls coveralls-spin
|
||||
coveralls:
|
||||
mocha --require blanket --reporter mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js
|
||||
|
||||
MDLINT=README.md
|
||||
.PHONY: mdlint
|
||||
mdlint: $(MDLINT) ## Check markdown documents
|
||||
./node_modules/.bin/alex $^
|
||||
./node_modules/.bin/mdspell -a -n -x -r --en-us $^
|
||||
coveralls-spin:
|
||||
make coveralls & bash misc/spin.sh $$!
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@grep -hE '(^[a-zA-Z_-][ a-zA-Z_-]*:.*?|^#[#*])' $(MAKEFILE_LIST) | bash misc/help.sh
|
||||
bower.json: misc/_bower.json package.json
|
||||
cat $< | sed 's/_VERSION_/'`grep version package.json | awk '{gsub(/[^0-9a-z\.-]/,"",$$2); print $$2}'`'/' > $@
|
||||
|
||||
#* To show a spinner, append "-spin" to any target e.g. cov-spin
|
||||
%-spin:
|
||||
@make $* & bash misc/spin.sh $$!
|
||||
.PHONY: dist
|
||||
dist: dist-deps $(TARGET) bower.json
|
||||
cp $(TARGET) dist/
|
||||
cp LICENSE dist/
|
||||
uglifyjs $(TARGET) -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 $(REQS) $(TARGET) -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
|
||||
uglifyjs $(REQS) $(ADDONS) $(TARGET) -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
|
||||
|
||||
.PHONY: aux
|
||||
aux: $(AUXTARGETS)
|
||||
|
||||
.PHONY: ods
|
||||
ods: ods.js
|
||||
|
||||
ODSDEPS=$(sort $(wildcard odsbits/*.js))
|
||||
ods.js: $(ODSDEPS)
|
||||
cat $(ODSDEPS) | tr -d '\15\32' > $@
|
||||
cp ods.js dist/ods.js
|
||||
|
||||
.PHONY: dist-deps
|
||||
dist-deps: ods.js
|
||||
cp node_modules/codepage/dist/cpexcel.full.js dist/cpexcel.js
|
||||
cp jszip.js dist/jszip.js
|
||||
cp ods.js dist/ods.js
|
||||
|
709
README.md
709
README.md
@ -1,38 +1,705 @@
|
||||
# [SheetJS](https://sheetjs.com)
|
||||
# xlsx-style
|
||||
|
||||
The SheetJS Community Edition offers battle-tested open-source solutions for
|
||||
extracting useful data from almost any complex spreadsheet and generating new
|
||||
spreadsheets that will work with legacy and modern software alike.
|
||||
Parser and writer for various spreadsheet formats. Pure-JS cleanroom implementation from official specifications and related documents.
|
||||
|
||||
[SheetJS Pro](https://sheetjs.com/pro) offers solutions beyond data processing:
|
||||
Edit complex templates with ease; let out your inner Picasso with styling; make
|
||||
custom sheets with images/graphs/PivotTables; evaluate formula expressions and
|
||||
port calculations to web apps; automate common spreadsheet tasks, and much more!
|
||||
# About this fork
|
||||
**NOTE:** [This project](https://github.com/SheetJS/js-xlsx/tree/beta) is a fork of the original (and awesome) [SheetJS/xlsx](https://github.com/SheetJS/js-xlsx) project.
|
||||
It is extended to enable cell formats to be read from and written to .xlsx workbooks.
|
||||
The intent is to provide a temporary means of using these features in practice, and ultimately to merge this into the primary project.
|
||||
Report any issues to https://github.com/protobi/js-xlsx/issues.
|
||||
|
||||
## Documentation
|
||||
For those contributing to this fork:
|
||||
* `master` is the main branch, which follows the original repo to enable a future pull request.
|
||||
* `beta` branch is published to npm and bower to make this fork available for use.
|
||||
|
||||
- [API and Usage Documentation](https://docs.sheetjs.com)
|
||||
# Supported formats
|
||||
|
||||
- [Downloadable Scripts and Modules](https://cdn.sheetjs.com)
|
||||
Supported read formats:
|
||||
|
||||
## Constellation
|
||||
- Excel 2007+ XML Formats (XLSX/XLSM)
|
||||
- Excel 2007+ Binary Format (XLSB)
|
||||
- Excel 2003-2004 XML Format (XML "SpreadsheetML")
|
||||
- Excel 97-2004 (XLS BIFF8)
|
||||
- Excel 5.0/95 (XLS BIFF5)
|
||||
- OpenDocument Spreadsheet (ODS)
|
||||
|
||||
- <https://oss.sheetjs.com/notes/>: File Format Notes
|
||||
Supported write formats:
|
||||
|
||||
- [`ssf`](packages/ssf): Format data using ECMA-376 spreadsheet format codes
|
||||
- XLSX
|
||||
- CSV (and general DSV)
|
||||
- JSON and JS objects (various styles)
|
||||
|
||||
- [`xlsx-cli`](packages/xlsx-cli): NodeJS command-line tool for processing files
|
||||
Demo: <http://oss.sheetjs.com/js-xlsx>
|
||||
|
||||
- [`cfb`](https://git.sheetjs.com/SheetJS/js-cfb): Container (OLE/ZIP) file
|
||||
processing library
|
||||
Source: <http://git.io/xlsx>
|
||||
|
||||
- [`codepage`](https://git.sheetjs.com/SheetJS/js-codepage): Legacy text
|
||||
encodings for XLS and other legacy spreadsheet formats
|
||||
## Installation
|
||||
|
||||
- [`dta`](packages/dta): Stata DTA file processor
|
||||
With [npm](https://www.npmjs.org/package/xlsx-style):
|
||||
|
||||
```sh
|
||||
npm install xlsx-style --save
|
||||
```
|
||||
|
||||
In the browser:
|
||||
|
||||
```html
|
||||
<script lang="javascript" src="dist/xlsx.core.min.js"></script>
|
||||
```
|
||||
|
||||
With [bower](http://bower.io/search/?q=js-xlsx):
|
||||
|
||||
```sh
|
||||
bower install js-xlsx-style#beta
|
||||
```
|
||||
|
||||
CDNjs automatically pulls the latest version and makes all versions available at
|
||||
<http://cdnjs.com/libraries/xlsx>
|
||||
|
||||
## Optional Modules
|
||||
|
||||
The node version automatically requires modules for additional features. Some
|
||||
of these modules are rather large in size and are only needed in special
|
||||
circumstances, so they do not ship with the core. For browser use, they must
|
||||
be included directly:
|
||||
|
||||
```html
|
||||
<!-- international support from https://github.com/sheetjs/js-codepage -->
|
||||
<script src="dist/cpexcel.js"></script>
|
||||
<!-- ODS support -->
|
||||
<script src="dist/ods.js"></script>
|
||||
```
|
||||
|
||||
An appropriate version for each dependency is included in the dist/ directory.
|
||||
|
||||
The complete single-file version is generated at `dist/xlsx.full.min.js`
|
||||
|
||||
## ECMAScript 5 Compatibility
|
||||
|
||||
Since xlsx.js uses ES5 functions like `Array#forEach`, older browsers require
|
||||
[Polyfills](http://git.io/QVh77g). This repo and the gh-pages branch include
|
||||
[a shim](https://github.com/SheetJS/js-xlsx/blob/master/shim.js)
|
||||
|
||||
To use the shim, add the shim before the script tag that loads xlsx.js:
|
||||
|
||||
```html
|
||||
<script type="text/javascript" src="/path/to/shim.js"></script>
|
||||
```
|
||||
|
||||
## Parsing Workbooks
|
||||
|
||||
For parsing, the first step is to read the file. This involves acquiring the
|
||||
data and feeding it into the library. Here are a few common scenarios:
|
||||
|
||||
- node readFile:
|
||||
|
||||
```js
|
||||
if(typeof require !== 'undefined') XLSX = require('xlsx');
|
||||
var workbook = XLSX.readFile('test.xlsx');
|
||||
/* DO SOMETHING WITH workbook HERE */
|
||||
```
|
||||
|
||||
- ajax (for a more complete example that works in older browsers, check the demo
|
||||
at <http://oss.sheetjs.com/js-xlsx/ajax.html>):
|
||||
|
||||
```js
|
||||
/* set up XMLHttpRequest */
|
||||
var url = "test_files/formula_stress_test_ajax.xlsx";
|
||||
var oReq = new XMLHttpRequest();
|
||||
|
||||
oReq.open("GET", url, true);
|
||||
oReq.responseType = "arraybuffer";
|
||||
|
||||
oReq.onload = function(e) {
|
||||
var arraybuffer = oReq.response;
|
||||
|
||||
/* convert data to binary string */
|
||||
var data = new Uint8Array(arraybuffer);
|
||||
var arr = new Array();
|
||||
for(var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
|
||||
var bstr = arr.join("");
|
||||
|
||||
/* Call XLSX */
|
||||
var workbook = XLSX.read(bstr, {type:"binary"});
|
||||
|
||||
/* DO SOMETHING WITH workbook HERE */
|
||||
}
|
||||
|
||||
oReq.send();
|
||||
```
|
||||
|
||||
- HTML5 drag-and-drop using readAsBinaryString:
|
||||
|
||||
```js
|
||||
/* set up drag-and-drop event */
|
||||
function handleDrop(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
var files = e.dataTransfer.files;
|
||||
var i, f;
|
||||
|
||||
for (i = 0, f = files[i]; i != files.length; ++i) {
|
||||
var reader = new FileReader();
|
||||
var name = f.name;
|
||||
reader.onload = function(e) {
|
||||
var data = e.target.result;
|
||||
|
||||
/* if binary string, read with type 'binary' */
|
||||
var workbook = XLSX.read(data, {type: 'binary'});
|
||||
|
||||
/* DO SOMETHING WITH workbook HERE */
|
||||
};
|
||||
reader.readAsBinaryString(f);
|
||||
}
|
||||
}
|
||||
drop_dom_element.addEventListener('drop', handleDrop, false);
|
||||
```
|
||||
|
||||
- HTML5 input file element using readAsBinaryString:
|
||||
|
||||
```js
|
||||
function handleFile(e) {
|
||||
var files = e.target.files;
|
||||
var i, f;
|
||||
|
||||
for (i = 0, f = files[i]; i != files.length; ++i) {
|
||||
var reader = new FileReader();
|
||||
var name = f.name;
|
||||
reader.onload = function(e) {
|
||||
var data = e.target.result;
|
||||
|
||||
var workbook = XLSX.read(data, {type: 'binary'});
|
||||
|
||||
/* DO SOMETHING WITH workbook HERE */
|
||||
};
|
||||
reader.readAsBinaryString(f);
|
||||
}
|
||||
}
|
||||
input_dom_element.addEventListener('change', handleFile, false);
|
||||
```
|
||||
|
||||
## Working with the Workbook
|
||||
|
||||
The full object format is described later in this README.
|
||||
|
||||
This example extracts the value stored in cell A1 from the first worksheet:
|
||||
|
||||
```js
|
||||
var first_sheet_name = workbook.SheetNames[0];
|
||||
var address_of_cell = 'A1';
|
||||
|
||||
/* Get worksheet */
|
||||
var worksheet = workbook.Sheets[first_sheet_name];
|
||||
|
||||
/* Find desired cell */
|
||||
var desired_cell = worksheet[address_of_cell];
|
||||
|
||||
/* Get the value */
|
||||
var desired_value = desired_cell.v;
|
||||
```
|
||||
|
||||
This example iterates through every nonempty of every sheet and dumps values:
|
||||
|
||||
```js
|
||||
var sheet_name_list = workbook.SheetNames;
|
||||
|
||||
sheet_name_list.forEach(function(y) { /* iterate through sheets */
|
||||
var worksheet = workbook.Sheets[y];
|
||||
for (z in worksheet) {
|
||||
/* all keys that do not begin with "!" correspond to cell addresses */
|
||||
if(z[0] === '!') continue;
|
||||
console.log(y + "!" + z + "=" + JSON.stringify(worksheet[z].v));
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Complete examples:
|
||||
|
||||
- <http://oss.sheetjs.com/js-xlsx/> HTML5 File API / Base64 Text / Web Workers
|
||||
|
||||
Note that older versions of IE does not support HTML5 File API, so the base64
|
||||
mode is provided for testing. On OSX you can get the base64 encoding with:
|
||||
|
||||
```sh
|
||||
$ <target_file.xlsx base64 | pbcopy
|
||||
```
|
||||
|
||||
- <http://oss.sheetjs.com/js-xlsx/ajax.html> XMLHttpRequest
|
||||
|
||||
- <https://github.com/SheetJS/js-xlsx/blob/master/bin/xlsx.njs> node
|
||||
|
||||
The node version installs a command line tool `xlsx` which can read spreadsheet
|
||||
files and output the contents in various formats. The source is available at
|
||||
`xlsx.njs` in the bin directory.
|
||||
|
||||
Some helper functions in `XLSX.utils` generate different views of the sheets:
|
||||
|
||||
- `XLSX.utils.sheet_to_csv` generates CSV
|
||||
- `XLSX.utils.sheet_to_json` generates an array of objects
|
||||
- `XLSX.utils.sheet_to_formulae` generates a list of formulae
|
||||
|
||||
## Writing Workbooks
|
||||
|
||||
For writing, the first step is to generate output data. The helper functions
|
||||
`write` and `writeFile` will produce the data in various formats suitable for
|
||||
dissemination. The second step is to actual share the data with the end point.
|
||||
Assuming `workbook` is a workbook object:
|
||||
|
||||
- nodejs write to file:
|
||||
|
||||
```js
|
||||
/* output format determined by filename */
|
||||
XLSX.writeFile(workbook, 'out.xlsx');
|
||||
/* at this point, out.xlsx is a file that you can distribute */
|
||||
```
|
||||
|
||||
- write to binary string (using FileSaver.js):
|
||||
|
||||
```js
|
||||
/* bookType can be 'xlsx' or 'xlsm' or 'xlsb' */
|
||||
var wopts = { bookType:'xlsx', bookSST:false, type:'binary' };
|
||||
|
||||
var wbout = XLSX.write(workbook,wopts);
|
||||
|
||||
function s2ab(s) {
|
||||
var buf = new ArrayBuffer(s.length);
|
||||
var view = new Uint8Array(buf);
|
||||
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* the saveAs call downloads a file on the local machine */
|
||||
saveAs(new Blob([s2ab(wbout)],{type:""}), "test.xlsx")
|
||||
```
|
||||
|
||||
Complete examples:
|
||||
|
||||
- <http://sheetjs.com/demos/writexlsx.html> generates a simple file
|
||||
- <http://git.io/WEK88Q> writing an array of arrays in nodejs
|
||||
- <http://sheetjs.com/demos/table.html> exporting an HTML table
|
||||
|
||||
## Interface
|
||||
|
||||
`XLSX` is the exposed variable in the browser and the exported node variable
|
||||
|
||||
`XLSX.version` is the version of the library (added by the build script).
|
||||
|
||||
`XLSX.SSF` is an embedded version of the [format library](http://git.io/ssf).
|
||||
|
||||
### Parsing functions
|
||||
|
||||
`XLSX.read(data, read_opts)` attempts to parse `data`.
|
||||
|
||||
`XLSX.readFile(filename, read_opts)` attempts to read `filename` and parse.
|
||||
|
||||
### Writing functions
|
||||
|
||||
`XLSX.write(wb, write_opts)` attempts to write the workbook `wb`
|
||||
|
||||
`XLSX.writeFile(wb, filename, write_opts)` attempts to write `wb` to `filename`
|
||||
|
||||
### Utilities
|
||||
|
||||
Utilities are available in the `XLSX.utils` object:
|
||||
|
||||
Exporting:
|
||||
|
||||
- `sheet_to_json` converts a workbook object to an array of JSON objects.
|
||||
- `sheet_to_csv` generates delimiter-separated-values output
|
||||
- `sheet_to_formulae` generates a list of the formulae (with value fallbacks)
|
||||
|
||||
Cell and cell address manipulation:
|
||||
|
||||
- `format_cell` generates the text value for a cell (using number formats)
|
||||
- `{en,de}code_{row,col}` convert between 0-indexed rows/cols and A1 forms.
|
||||
- `{en,de}code_cell` converts cell addresses
|
||||
- `{en,de}code_range` converts cell ranges
|
||||
|
||||
## Workbook / Worksheet / Cell Object Description
|
||||
|
||||
js-xlsx conforms to the Common Spreadsheet Format (CSF):
|
||||
|
||||
### General Structures
|
||||
|
||||
Cell address objects are stored as `{c:C, r:R}` where `C` and `R` are 0-indexed
|
||||
column and row numbers, respectively. For example, the cell address `B5` is
|
||||
represented by the object `{c:1, r:4}`.
|
||||
|
||||
Cell range objects are stored as `{s:S, e:E}` where `S` is the first cell and
|
||||
`E` is the last cell in the range. The ranges are inclusive. For example, the
|
||||
range `A3:B7` is represented by the object `{s:{c:0, r:2}, e:{c:1, r:6}}`. Utils
|
||||
use the following pattern to walk each of the cells in a range:
|
||||
|
||||
```js
|
||||
for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) {
|
||||
var cell_address = {c:C, r:R};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Cell Object
|
||||
|
||||
| Key | Description |
|
||||
| --- | ----------- |
|
||||
| `v` | raw value (see Data Types section for more info) |
|
||||
| `w` | formatted text (if applicable) |
|
||||
| `t` | cell type: `b` Boolean, `n` Number, `e` error, `s` String, `d` Date |
|
||||
| `f` | cell formula (if applicable) |
|
||||
| `r` | rich text encoding (if applicable) |
|
||||
| `h` | HTML rendering of the rich text (if applicable) |
|
||||
| `c` | comments associated with the cell ** |
|
||||
| `z` | number format string associated with the cell (if requested) |
|
||||
| `l` | cell hyperlink object (.Target holds link, .tooltip is tooltip) |
|
||||
| `s` | the style/theme of the cell (if applicable) |
|
||||
|
||||
Built-in export utilities (such as the CSV exporter) will use the `w` text if it
|
||||
is available. To change a value, be sure to delete `cell.w` (or set it to
|
||||
`undefined`) before attempting to export. The utilities will regenerate the `w`
|
||||
text from the number format (`cell.z`) and the raw value if possible.
|
||||
|
||||
**Note**: The .z attribute is now deprecated. Use the `.s` attribute to specify cell styles including number formats.
|
||||
To specify a number format, use `s.numFmt`, e.g. `{v: 42145.822, s: { numFmt: "m/dd/yy"}}` described below.
|
||||
|
||||
### Data Types
|
||||
|
||||
The raw value is stored in the `v` field, interpreted based on the `t` field.
|
||||
|
||||
Type `b` is the Boolean type. `v` is interpreted according to JS truth tables
|
||||
|
||||
Type `e` is the Error type. `v` holds the number and `w` holds the common name:
|
||||
|
||||
| Value | Error Meaning |
|
||||
| ----: | :------------ |
|
||||
| 0x00 | #NULL! |
|
||||
| 0x07 | #DIV/0! |
|
||||
| 0x0F | #VALUE! |
|
||||
| 0x17 | #REF! |
|
||||
| 0x1D | #NAME? |
|
||||
| 0x24 | #NUM! |
|
||||
| 0x2A | #N/A |
|
||||
| 0x2B | #GETTING_DATA |
|
||||
|
||||
Type `n` is the Number type. This includes all forms of data that Excel stores
|
||||
as numbers, such as dates/times and Boolean fields. Excel exclusively uses data
|
||||
that can be fit in an IEEE754 floating point number, just like JS Number, so the
|
||||
`v` field holds the raw number. The `w` field holds formatted text.
|
||||
|
||||
Type `d` is the Date type, generated only when the option `cellDates` is passed.
|
||||
Since JSON does not have a natural Date type, parsers are generally expected to
|
||||
store ISO 8601 Date strings like you would get from `date.toISOString()`. On
|
||||
the other hand, writers and exporters should be able to handle date strings and
|
||||
JS Date objects. Note that Excel disregards the timezone modifier and treats all
|
||||
dates in the local timezone. js-xlsx does not correct for this error.
|
||||
|
||||
Type `s` is the String type. `v` should be explicitly stored as a string to
|
||||
avoid possible confusion.
|
||||
|
||||
|
||||
### Worksheet Object
|
||||
|
||||
Each key that does not start with `!` maps to a cell (using `A-1` notation)
|
||||
|
||||
`worksheet[address]` returns the cell object for the specified address.
|
||||
|
||||
Special worksheet keys (accessible as `worksheet[key]`, each starting with `!`):
|
||||
|
||||
- `ws['!ref']`: A-1 based range representing the worksheet range. Functions that
|
||||
work with sheets should use this parameter to determine the range. Cells that
|
||||
are assigned outside of the range are not processed. In particular, when
|
||||
writing a worksheet by hand, be sure to update the range. For a longer
|
||||
discussion, see <http://git.io/KIaNKQ>
|
||||
|
||||
Functions that handle worksheets should test for the presence of `!ref` field.
|
||||
If the `!ref` is omitted or is not a valid range, functions are free to treat
|
||||
the sheet as empty or attempt to guess the range. The standard utilities that
|
||||
ship with this library treat sheets as empty (for example, the CSV output is an
|
||||
empty string).
|
||||
|
||||
When reading a worksheet with the `sheetRows` property set, the ref parameter
|
||||
will use the restricted range. The original range is set at `ws['!fullref']`
|
||||
|
||||
- `ws['!cols']`: array of column properties objects. Column widths are actually
|
||||
stored in files in a normalized manner, measured in terms of the "Maximum
|
||||
Digit Width" (the largest width of the rendered digits 0-9, in pixels). When
|
||||
parsed, the column objects store the pixel width in the `wpx` field, character
|
||||
width in the `wch` field, and the maximum digit width in the `MDW` field.
|
||||
|
||||
- `ws['!merges']`: array of range objects corresponding to the merged cells in
|
||||
the worksheet. Plaintext utilities are unaware of merge cells. CSV export
|
||||
will write all cells in the merge range if they exist, so be sure that only
|
||||
the first cell (upper-left) in the range is set.
|
||||
|
||||
- `ws['!printHeader']`: array of row indices for repeating row headers on print, e.g. `[1:1]` to repeat just the first row.
|
||||
|
||||
The following properties are currently used when generating an XLSX file, but not yet parsed:
|
||||
|
||||
- `ws['!rowBreaks']`: array of row break points, e.g. `[16,32]`
|
||||
- `ws['!colBreaks']`: array of col break points, e.g. `[8,16]`
|
||||
- `ws['!pageSetup']`: `{scale: '100', orientation: 'portrait'||'landscape'}
|
||||
- `ws['!printHeader']`: array of first and last row indexes for repeat header on printing, e.g. `[1,1]` to repeat just first row
|
||||
- `ws['!freeze']`: string cell reference for breakpoint, e.g. the following will freeze the first row and first column:
|
||||
{
|
||||
xSplit: "1",
|
||||
ySplit: "1",
|
||||
topLeftCell: "B2",
|
||||
activePane: "bottomRight",
|
||||
state: "frozen"
|
||||
}
|
||||
|
||||
|
||||
### Workbook Object
|
||||
|
||||
`workbook.SheetNames` is an ordered list of the sheets in the workbook
|
||||
|
||||
`wb.Sheets[sheetname]` returns an object representing the worksheet.
|
||||
|
||||
`wb.Props` is an object storing the standard properties. The following properties are currently used when
|
||||
generating an XLSX file, but not yet parsed:
|
||||
- `title`
|
||||
- `subject`
|
||||
- `description`
|
||||
- `keywords`
|
||||
- `creator`
|
||||
|
||||
`wb.Custprops` stores custom properties. Since the XLS standard properties deviate from the XLSX
|
||||
standard, XLS parsing stores core properties in both places. .
|
||||
|
||||
|
||||
## Parsing Options
|
||||
|
||||
The exported `read` and `readFile` functions accept an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | ------: | :---------- |
|
||||
| cellFormula | true | Save formulae to the .f field ** |
|
||||
| cellHTML | true | Parse rich text and save HTML to the .h field |
|
||||
| cellNF | false | Save number format string to the .z field |
|
||||
| cellStyles | false | Save style/theme info to the .s field |
|
||||
| cellDates | false | Store dates as type `d` (default is `n`) ** |
|
||||
| sheetStubs | false | Create cell objects for stub cells |
|
||||
| sheetRows | 0 | If >0, read the first `sheetRows` rows ** |
|
||||
| bookDeps | false | If true, parse calculation chains |
|
||||
| bookFiles | false | If true, add raw files to book object ** |
|
||||
| bookProps | false | If true, only parse enough to get book metadata ** |
|
||||
| bookSheets | false | If true, only parse enough to get the sheet names |
|
||||
| bookVBA | false | If true, expose vbaProject.bin to `vbaraw` field ** |
|
||||
| password | "" | If defined and file is encrypted, use password ** |
|
||||
|
||||
- `cellFormula` option only applies to formats that require extra processing to
|
||||
parse formulae (XLS/XLSB).
|
||||
- Even if `cellNF` is false, formatted text will be generated and saved to `.w`
|
||||
- In some cases, sheets may be parsed even if `bookSheets` is false.
|
||||
- `bookSheets` and `bookProps` combine to give both sets of information
|
||||
- `Deps` will be an empty object if `bookDeps` is falsy
|
||||
- `bookFiles` behavior depends on file type:
|
||||
* `keys` array (paths in the ZIP) for ZIP-based formats
|
||||
* `files` hash (mapping paths to objects representing the files) for ZIP
|
||||
* `cfb` object for formats using CFB containers
|
||||
- `sheetRows-1` rows will be generated when looking at the JSON object output
|
||||
(since the header row is counted as a row when parsing the data)
|
||||
- `bookVBA` merely exposes the raw vba object. It does not parse the data.
|
||||
- `cellDates` currently does not convert numerical dates to JS dates.
|
||||
- Currently only XOR encryption is supported. Unsupported error will be thrown
|
||||
for files employing other encryption methods.
|
||||
|
||||
The defaults are enumerated in bits/84_defaults.js
|
||||
|
||||
## Writing Options
|
||||
|
||||
The exported `write` and `writeFile` functions accept an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | ------: | :---------- |
|
||||
| cellDates | false | Store dates as type `d` (default is `n`) |
|
||||
| bookSST | false | Generate Shared String Table ** |
|
||||
| bookType | 'xlsx' | Type of Workbook ("xlsx" or "xlsm" or "xlsb") |
|
||||
| showGridLines | true | Show gridlines on all pages |
|
||||
| tabSelected | '1' | Initial tab selected |
|
||||
| Props | null | Workbook properties |
|
||||
|
||||
|
||||
|
||||
|
||||
- `bookSST` is slower and more memory intensive, but has better compatibility
|
||||
with older versions of iOS Numbers
|
||||
- `bookType = 'xlsb'` is stubbed and far from complete
|
||||
- The raw data is the only thing guaranteed to be saved. Formulae, formatting,
|
||||
and other niceties may not be serialized (pending CSF standardization)
|
||||
- `cellDates` only applies to XLSX output and is not guaranteed to work with
|
||||
third-party readers. Excel itself does not usually write cells with type `d`
|
||||
so non-Excel tools may ignore the data or blow up in the presence of dates.
|
||||
- showGridLines and tabSelected are currently used when generating an XLSX file but not yet parse.
|
||||
- Props specifies workbook properties
|
||||
|
||||
|
||||
|
||||
|
||||
## Cell Styles
|
||||
|
||||
Cell styles are specified by a style object that roughly parallels the OpenXML structure. The style object has five
|
||||
top-level attributes: `fill`, `font`, `numFmt`, `alignment`, and `border`.
|
||||
|
||||
|
||||
| Style Attribute | Sub Attributes | Values |
|
||||
| :-------------- | :------------- | :------------- |
|
||||
| fill | patternType | `"solid"` or `"none"`
|
||||
| | fgColor | `COLOR_SPEC`
|
||||
| | bgColor | `COLOR_SPEC`
|
||||
| font | name | `"Calibri"` // default
|
||||
| | sz | `"11"` // font size in points
|
||||
| | color | `COLOR_SPEC`
|
||||
| | bold | `true` or `false`
|
||||
| | underline | `true` or `false`
|
||||
| | italic | `true` or `false`
|
||||
| | strike | `true` or `false`
|
||||
| | outline | `true` or `false`
|
||||
| | shadow | `true` or `false`
|
||||
| | vertAlign | `true` or `false`
|
||||
| numFmt | | `"0"` // integer index to built in formats, see StyleBuilder.SSF property
|
||||
| | | `"0.00%"` // string matching a built-in format, see StyleBuilder.SSF
|
||||
| | | `"0.0%"` // string specifying a custom format
|
||||
| | | `"0.00%;\\(0.00%\\);\\-;@"` // string specifying a custom format, escaping special characters
|
||||
| | | `"m/dd/yy"` // string a date format using Excel's format notation
|
||||
| alignment | vertical | `"bottom"` or `"center"` or `"top"`
|
||||
| | horizontal | `"left"` or `"center"` or `"right"`
|
||||
| | wrapText | `true ` or ` false`
|
||||
| | readingOrder | `2` // for right-to-left
|
||||
| | textRotation | Number from `0` to `180` or `255` (default is `0`)
|
||||
| | | `90` is rotated up 90 degrees
|
||||
| | | `45` is rotated up 45 degrees
|
||||
| | | `135` is rotated down 45 degrees
|
||||
| | | `180` is rotated down 180 degrees
|
||||
| | | `255` is special, aligned vertically
|
||||
| border | top | `{ style: BORDER_STYLE, color: COLOR_SPEC }`
|
||||
| | bottom | `{ style: BORDER_STYLE, color: COLOR_SPEC }`
|
||||
| | left | `{ style: BORDER_STYLE, color: COLOR_SPEC }`
|
||||
| | right | `{ style: BORDER_STYLE, color: COLOR_SPEC }`
|
||||
| | diagonal | `{ style: BORDER_STYLE, color: COLOR_SPEC }`
|
||||
| | diagonalUp | `true` or `false`
|
||||
| | diagonalDown | `true` or `false`
|
||||
|
||||
**COLOR_SPEC**: Colors for `fill`, `font`, and `border` are specified as objects, either:
|
||||
* `{ auto: 1}` specifying automatic values
|
||||
* `{ rgb: "FFFFAA00" }` specifying a hex ARGB value
|
||||
* `{ theme: "1", tint: "-0.25"}` specifying an integer index to a theme color and a tint value (default 0)
|
||||
* `{ indexed: 64}` default value for `fill.bgColor`
|
||||
|
||||
**BORDER_STYLE**: Border style is a string value which may take on one of the following values:
|
||||
* `thin`
|
||||
* `medium`
|
||||
* `thick`
|
||||
* `dotted`
|
||||
* `hair`
|
||||
* `dashed`
|
||||
* `mediumDashed`
|
||||
* `dashDot`
|
||||
* `mediumDashDot`
|
||||
* `dashDotDot`
|
||||
* `mediumDashDotDot`
|
||||
* `slantDashDot`
|
||||
|
||||
|
||||
Borders for merged areas are specified for each cell within the merged area. So to apply a box border to a merged area of 3x3 cells, border styles would need to be specified for eight different cells:
|
||||
* left borders for the three cells on the left,
|
||||
* right borders for the cells on the right
|
||||
* top borders for the cells on the top
|
||||
* bottom borders for the cells on the left
|
||||
|
||||
|
||||
|
||||
## Tested Environments
|
||||
|
||||
- NodeJS 0.8, 0.10 (latest release), 0.11.14 (unstable), io.js
|
||||
- IE 6/7/8/9/10/11 using Base64 mode (IE10/11 using HTML5 mode)
|
||||
- FF 18 using Base64 or HTML5 mode
|
||||
- Chrome 24 using Base64 or HTML5 mode
|
||||
|
||||
Tests utilize the mocha testing framework. Travis-CI and Sauce Labs links:
|
||||
|
||||
- <https://travis-ci.org/SheetJS/js-xlsx> for XLSX module in nodejs
|
||||
- <https://travis-ci.org/SheetJS/SheetJS.github.io> for XLS* modules
|
||||
- <https://saucelabs.com/u/sheetjs> for XLS* modules using Sauce Labs
|
||||
|
||||
## Test Files
|
||||
|
||||
Test files are housed in [another repo](https://github.com/SheetJS/test_files).
|
||||
|
||||
Running `make init` will refresh the `test_files` submodule and get the files.
|
||||
|
||||
## Testing
|
||||
|
||||
`make test` will run the node-based tests. To run the in-browser tests, clone
|
||||
[the oss.sheetjs.com repo](https://github.com/SheetJS/SheetJS.github.io) and
|
||||
replace the xlsx.js file (then fire up the browser and go to `stress.html`):
|
||||
|
||||
```sh
|
||||
$ cp xlsx.js ../SheetJS.github.io
|
||||
$ cd ../SheetJS.github.io
|
||||
$ simplehttpserver # or "python -mSimpleHTTPServer" or "serve"
|
||||
$ open -a Chromium.app http://localhost:8000/stress.html
|
||||
```
|
||||
|
||||
For a much smaller test, run `make test_misc`.
|
||||
|
||||
## Contributing
|
||||
|
||||
Due to the precarious nature of the Open Specifications Promise, it is very
|
||||
important to ensure code is cleanroom. Consult CONTRIBUTING.md
|
||||
|
||||
The xlsx.js file is constructed from the files in the `bits` subdirectory. The
|
||||
build script (run `make`) will concatenate the individual bits to produce the
|
||||
script. Before submitting a contribution, ensure that running make will produce
|
||||
the xlsx.js file exactly. The simplest way to test is to move the script:
|
||||
|
||||
```sh
|
||||
$ mv xlsx.js xlsx.new.js
|
||||
$ make
|
||||
$ diff xlsx.js xlsx.new.js
|
||||
```
|
||||
|
||||
To produce the dist files, run `make dist`. The dist files are updated in each
|
||||
version release and should not be committed between versions.
|
||||
|
||||
## License
|
||||
|
||||
Please consult the attached LICENSE file for details. All rights not explicitly
|
||||
granted by the Apache 2.0 License are reserved by the Original Author.
|
||||
granted by the Apache 2.0 license are reserved by the Original Author.
|
||||
|
||||
It is the opinion of the Original Author that this code conforms to the terms of
|
||||
the Microsoft Open Specifications Promise, falling under the same terms as
|
||||
OpenOffice (which is governed by the Apache License v2). Given the vagaries of
|
||||
the promise, the Original Author makes no legal claim that in fact end users are
|
||||
protected from future actions. It is highly recommended that, for commercial
|
||||
uses, you consult a lawyer before proceeding.
|
||||
|
||||
## References
|
||||
|
||||
ISO/IEC 29500:2012(E) "Information technology — Document description and processing languages — Office Open XML File Formats"
|
||||
|
||||
OSP-covered specifications:
|
||||
|
||||
- [MS-XLSB]: Excel (.xlsb) Binary File Format
|
||||
- [MS-XLSX]: Excel (.xlsx) Extensions to the Office Open XML SpreadsheetML File Format
|
||||
- [MS-OE376]: Office Implementation Information for ECMA-376 Standards Support
|
||||
- [MS-CFB]: Compound File Binary File Format
|
||||
- [MS-XLS]: Excel Binary File Format (.xls) Structure Specification
|
||||
- [MS-ODATA]: Open Data Protocol (OData)
|
||||
- [MS-OFFCRYPTO]: Office Document Cryptography Structure
|
||||
- [MS-OLEDS]: Object Linking and Embedding (OLE) Data Structures
|
||||
- [MS-OLEPS]: Object Linking and Embedding (OLE) Property Set Data Structures
|
||||
- [MS-OSHARED]: Office Common Data Types and Objects Structures
|
||||
- [MS-OVBA]: Office VBA File Format Structure
|
||||
- [MS-CTXLS]: Excel Custom Toolbar Binary File Format
|
||||
- [MS-XLDM]: Spreadsheet Data Model File Format
|
||||
- [MS-EXSPXML3]: Excel Calculation Version 2 Web Service XML Schema
|
||||
- [XLS]: Microsoft Office Excel 97-2007 Binary File Format Specification
|
||||
|
||||
Open Document Format for Office Applications Version 1.2 (29 September 2011)
|
||||
|
||||
|
||||
## Badges
|
||||
|
||||
[![Build Status](https://travis-ci.org/SheetJS/js-xlsx.svg?branch=master)](https://travis-ci.org/SheetJS/js-xlsx)
|
||||
|
||||
[![Coverage Status](http://img.shields.io/coveralls/SheetJS/js-xlsx/master.svg)](https://coveralls.io/r/SheetJS/js-xlsx?branch=master)
|
||||
|
269
bin/xlsx.njs
269
bin/xlsx.njs
@ -1,79 +1,31 @@
|
||||
#!/usr/bin/env node
|
||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
/* eslint-env node */
|
||||
/* vim: set ts=2 ft=javascript: */
|
||||
/* xlsx.js (C) 2013-2015 SheetJS -- http://sheetjs.com */
|
||||
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);
|
||||
}
|
||||
var fs = require('fs'), program = require('commander');
|
||||
program
|
||||
.version(X.version)
|
||||
.usage('[options] <file> [sheetname]')
|
||||
.option('-f, --file <file>', 'use specified workbook')
|
||||
.option('-s, --sheet <sheet>', 'print specified sheet (default first sheet)')
|
||||
.option('-N, --sheet-index <idx>', 'use specified sheet index (0-based)')
|
||||
.option('-p, --password <pw>', 'if file is encrypted, try with specified pw')
|
||||
.option('-l, --list-sheets', 'list sheet names and exit')
|
||||
.option('-o, --output <file>', 'output to specified file')
|
||||
|
||||
.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('-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)')
|
||||
.option('-J, --raw-js', 'emit raw JS object (raw numbers)')
|
||||
.option('-A, --arrays', 'emit rows as JS objects (raw numbers)')
|
||||
.option('-H, --html', 'emit HTML to <sheetname> or <file>.html')
|
||||
.option('-D, --dif', 'emit DIF to <sheetname> or <file>.dif (Lotus DIF)')
|
||||
.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('-S, --formulae', 'print formulae')
|
||||
.option('-j, --json', 'emit formatted JSON (all fields text)')
|
||||
.option('-J, --raw-js', 'emit raw JS object (raw numbers)')
|
||||
.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')
|
||||
.option('--book', 'for single-sheet formats, emit a file per worksheet')
|
||||
.option('--all', 'parse everything; write as much as possible')
|
||||
.option('--sst', 'generate sst')
|
||||
.option('--perf', 'do not generate output')
|
||||
.option('--all', 'parse everything; XLS[XMB] write as much as possible')
|
||||
.option('--dev', 'development mode')
|
||||
.option('--sparse', 'sparse mode')
|
||||
.option('--read', 'read but do not print out contents')
|
||||
.option('-q, --quiet', 'quiet mode');
|
||||
|
||||
program.on('--help', function() {
|
||||
@ -82,26 +34,20 @@ program.on('--help', function() {
|
||||
console.log(' Web Demo: http://oss.sheetjs.com/js-'+n+'/');
|
||||
});
|
||||
|
||||
/* flag, bookType, default ext */
|
||||
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']
|
||||
];
|
||||
var wb_formats_2 = [
|
||||
['xlml', 'xlml', 'xls']
|
||||
];
|
||||
program.parse(process.argv);
|
||||
|
||||
var filename = '', sheetname = '';
|
||||
/* see https://github.com/SheetJS/j/issues/4 */
|
||||
if(process.version === 'v0.10.31') {
|
||||
var msgs = [
|
||||
"node v0.10.31 is known to crash on OSX and Linux, refusing to proceed.",
|
||||
"see https://github.com/SheetJS/j/issues/4 for the relevant discussion.",
|
||||
"see https://github.com/joyent/node/issues/8208 for the relevant node issue"
|
||||
];
|
||||
msgs.forEach(function(m) { console.error(m); });
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var filename, sheetname = '';
|
||||
if(program.args[0]) {
|
||||
filename = program.args[0];
|
||||
if(program.args[1]) sheetname = program.args[1];
|
||||
@ -113,61 +59,35 @@ if(!filename) {
|
||||
console.error(n + ": must specify a filename");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if(!fs.existsSync(filename)) {
|
||||
console.error(n + ": " + filename + ": No such file or directory");
|
||||
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*/;
|
||||
var opts = {}, wb;
|
||||
if(program.listSheets) opts.bookSheets = true;
|
||||
if(program.sheetRows) opts.sheetRows = program.sheetRows;
|
||||
if(program.password) opts.password = program.password;
|
||||
var seen = false;
|
||||
function wb_fmt() {
|
||||
seen = true;
|
||||
opts.cellFormula = true;
|
||||
if(program.xlsx || program.xlsm || program.xlsb) {
|
||||
opts.cellNF = true;
|
||||
opts.xlfn = true;
|
||||
if(program.output) sheetname = program.output;
|
||||
}
|
||||
function isfmt(m/*:string*/)/*:boolean*/ {
|
||||
if(!program.output) return false;
|
||||
var t = m.charAt(0) === "." ? m : "." + m;
|
||||
return program.output.slice(-t.length) === t;
|
||||
}
|
||||
workbook_formats.forEach(function(m) { if(program[m[0]] || isfmt(m[0])) { wb_fmt(); } });
|
||||
wb_formats_2.forEach(function(m) { if(program[m[0]] || isfmt(m[0])) { wb_fmt(); } });
|
||||
if(seen) {
|
||||
} else if(program.formulae) opts.cellFormula = true;
|
||||
else if(program.formulae);
|
||||
else opts.cellFormula = false;
|
||||
|
||||
var wopts = ({WTF:opts.WTF, bookSST:program.sst}/*:any*/);
|
||||
if(program.compress) wopts.compression = true;
|
||||
|
||||
if(program.all) {
|
||||
opts.cellFormula = true;
|
||||
opts.bookVBA = true;
|
||||
opts.cellNF = true;
|
||||
opts.cellHTML = true;
|
||||
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) {
|
||||
X.verbose = 2;
|
||||
opts.WTF = true;
|
||||
wb = X.readFile(filename, opts);
|
||||
} else try {
|
||||
}
|
||||
else try {
|
||||
wb = X.readFile(filename, opts);
|
||||
} catch(e) {
|
||||
var msg = (program.quiet) ? "" : n + ": error parsing ";
|
||||
@ -176,135 +96,38 @@ if(program.dev) {
|
||||
process.exit(3);
|
||||
}
|
||||
if(program.read) process.exit(0);
|
||||
if(!wb) { console.error(n + ": error parsing " + filename + ": empty workbook"); process.exit(0); }
|
||||
/*:: if(!wb) throw new Error("unreachable"); */
|
||||
|
||||
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);
|
||||
console.log(wb.SheetNames.join("\n"));
|
||||
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);
|
||||
process.exit(0);
|
||||
} });
|
||||
var wopts = {WTF:opts.WTF, bookSST:program.sst};
|
||||
|
||||
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);
|
||||
process.exit(0);
|
||||
} });
|
||||
if(program.xlsx) return X.writeFile(wb, sheetname || (filename + ".xlsx"), wopts);
|
||||
if(program.xlsm) return X.writeFile(wb, sheetname || (filename + ".xlsm"), wopts);
|
||||
if(program.xlsb) return X.writeFile(wb, sheetname || (filename + ".xlsb"), wopts);
|
||||
|
||||
var target_sheet = sheetname || '';
|
||||
if(target_sheet === '') {
|
||||
if(+program.sheetIndex < (wb.SheetNames||[]).length) target_sheet = wb.SheetNames[+program.sheetIndex];
|
||||
else target_sheet = (wb.SheetNames||[""])[0];
|
||||
}
|
||||
if(target_sheet === '') target_sheet = wb.SheetNames[0];
|
||||
|
||||
var ws;
|
||||
try {
|
||||
ws = wb.Sheets[target_sheet];
|
||||
if(!ws) {
|
||||
console.error("Sheet " + target_sheet + " cannot be found");
|
||||
process.exit(3);
|
||||
}
|
||||
if(!ws) throw "Sheet " + target_sheet + " cannot be found";
|
||||
} catch(e) {
|
||||
console.error(n + ": error parsing "+filename+" "+target_sheet+": " + e);
|
||||
process.exit(4);
|
||||
}
|
||||
|
||||
if(!program.quiet && !program.book) console.error(target_sheet);
|
||||
if(program.perf) return;
|
||||
|
||||
/* single worksheet file formats */
|
||||
[
|
||||
['biff2', '.xls'],
|
||||
['biff3', '.xls'],
|
||||
['biff4', '.xls'],
|
||||
['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);
|
||||
});
|
||||
} else X.writeFile(wb, program.output || sheetname || ((filename || "") + m[1]), wopts);
|
||||
process.exit(0);
|
||||
} });
|
||||
var oo = "";
|
||||
if(!program.quiet) console.error(target_sheet);
|
||||
if(program.formulae) oo = X.utils.get_formulae(ws).join("\n");
|
||||
else if(program.json) oo = JSON.stringify(X.utils.sheet_to_row_object_array(ws));
|
||||
else if(program.rawJs) oo = JSON.stringify(X.utils.sheet_to_row_object_array(ws,{raw:true}));
|
||||
else oo = X.utils.make_csv(ws, {FS:program.fieldSep, RS:program.rowSep});
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
var jso = {};
|
||||
switch(true) {
|
||||
case program.formulae:
|
||||
doit(function(ws) { return X.utils.sheet_to_formulae(ws).join("\n"); });
|
||||
break;
|
||||
|
||||
case program.arrays: jso.header = 1;
|
||||
/* falls through */
|
||||
case program.rawJs: jso.raw = true;
|
||||
/* falls through */
|
||||
case program.json:
|
||||
doit(function(ws) { return JSON.stringify(X.utils.sheet_to_json(ws,jso)); });
|
||||
break;
|
||||
|
||||
default:
|
||||
if(!program.book) {
|
||||
var stream = X.stream.to_csv(ws, {FS:program.fieldSep||",", RS:program.rowSep||"\n"});
|
||||
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)));
|
||||
}
|
||||
if(program.output) fs.writeFileSync(program.output, oo);
|
||||
else console.log(oo);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
/* xlsx.js (C) 2013-2015 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 */
|
||||
/*jshint -W041 */
|
||||
/*jshint funcscope:true, eqnull:true */
|
||||
var XLSX = {};
|
||||
function make_xlsx_lib(XLSX){
|
||||
(function make_xlsx(XLSX){
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.20.3';
|
||||
XLSX.version = '0.8.20';
|
||||
|
@ -1,81 +1,23 @@
|
||||
var current_codepage = 1200, current_ansi = 1252;
|
||||
/*:: declare var cptable:any; */
|
||||
/*global cptable:true, window */
|
||||
var $cptable;
|
||||
|
||||
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 utf16leread(data/*:string*/)/*:string*/ {
|
||||
var o/*:Array<string>*/ = [];
|
||||
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i) + (data.charCodeAt(2*i+1)<<8));
|
||||
return o.join("");
|
||||
}
|
||||
function utf16lereadu(data/*:Uint8Array*/)/*:string*/ {
|
||||
var o/*:Array<string>*/ = [];
|
||||
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data[2*i] + (data[2*i+1]<<8));
|
||||
return o.join("");
|
||||
}
|
||||
function utf16beread(data/*:string*/)/*:string*/ {
|
||||
var o/*:Array<string>*/ = [];
|
||||
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i+1) + (data.charCodeAt(2*i)<<8));
|
||||
return o.join("");
|
||||
var current_codepage = 1200, current_cptable;
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
|
||||
if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel');
|
||||
current_cptable = cptable[current_codepage];
|
||||
}
|
||||
function reset_cp() { set_cp(1200); }
|
||||
var set_cp = function(cp) { current_codepage = cp; };
|
||||
|
||||
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);
|
||||
return data;
|
||||
};
|
||||
function char_codes(data) { var o = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; }
|
||||
var debom_xml = function(data) { 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); };
|
||||
debom = function(data/*:string*/) {
|
||||
if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return $cptable.utils.decode(1200, char_codes(data.slice(2))); }
|
||||
var _getchar = function _gc1(x) { return String.fromCharCode(x); };
|
||||
if(typeof cptable !== 'undefined') {
|
||||
set_cp = function(cp) { current_codepage = cp; current_cptable = cptable[cp]; };
|
||||
debom_xml = function(data) {
|
||||
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*/ {
|
||||
_getchar = function _gc2(x) {
|
||||
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();
|
||||
}
|
||||
|
@ -1,2 +0,0 @@
|
||||
var DENSE = null;
|
||||
var DIF_XL = true;
|
@ -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, utf8) {
|
||||
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, utf8) {
|
||||
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;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
114
bits/05_buf.js
114
bits/05_buf.js
@ -1,114 +1,16 @@
|
||||
var has_buf = /*#__PURE__*/(function() { return typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.node; })();
|
||||
var has_buf = (typeof Buffer !== 'undefined');
|
||||
|
||||
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;
|
||||
})();
|
||||
|
||||
|
||||
function new_raw_buf(len/*:number*/) {
|
||||
function new_raw_buf(len) {
|
||||
/* jshint -W056 */
|
||||
if(has_buf) return Buffer.alloc ? Buffer.alloc(len) : new Buffer(len);
|
||||
return typeof Uint8Array != "undefined" ? new Uint8Array(len) : new Array(len);
|
||||
return 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) {
|
||||
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]/;
|
||||
|
@ -1,18 +0,0 @@
|
||||
/*::
|
||||
declare type Block = any;
|
||||
declare type BufArray = {
|
||||
newblk(sz:number):Block;
|
||||
next(sz:number):Block;
|
||||
end():any;
|
||||
push(buf:Block):void;
|
||||
};
|
||||
|
||||
type RecordHopperCB = {(d:any, Rn:string, RT:number):?boolean;};
|
||||
|
||||
type EvertType = {[string]:string};
|
||||
type EvertNumType = {[string]:number};
|
||||
type EvertArrType = {[string]:Array<string>};
|
||||
|
||||
type StringConv = {(string):string};
|
||||
|
||||
*/
|
821
bits/10_ssf.js
821
bits/10_ssf.js
File diff suppressed because it is too large
Load Diff
@ -1,78 +1,20 @@
|
||||
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'
|
||||
}/*: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;
|
||||
fmt = fmt.replace(dateNFregex, "(\\d+)");
|
||||
dateNFregex.lastIndex = 0;
|
||||
return new RegExp("^" + fmt + "$");
|
||||
}
|
||||
function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/*:string*/ {
|
||||
var Y = -1, m = -1, d = -1, H = -1, M = -1, S = -1;
|
||||
(dateNF.match(dateNFregex)||[]).forEach(function(n, i) {
|
||||
var v = parseInt(match[i+1], 10);
|
||||
switch(n.toLowerCase().charAt(0)) {
|
||||
case 'y': Y = v; break; case 'd': d = v; break;
|
||||
case 'h': H = v; break; case 's': S = v; break;
|
||||
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;
|
||||
if(datestr.length == 8) datestr = "20" + datestr;
|
||||
var timestr = (("00" + (H>=0?H:0)).slice(-2) + ":" + ("00" + (M>=0?M:0)).slice(-2) + ":" + ("00" + (S>=0?S:0)).slice(-2));
|
||||
if(H == -1 && M == -1 && S == -1) return datestr;
|
||||
if(Y == -1 && m == -1 && d == -1) return timestr;
|
||||
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'
|
||||
/* map from xlml named formats to SSF TODO: localize */
|
||||
var XLMLFormatMap = {
|
||||
"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";@'
|
||||
};
|
||||
|
||||
function SSF__load(fmt, idx) {
|
||||
return SSF_load(bad_formats[fmt] || fmt, idx);
|
||||
}
|
||||
|
||||
|
1757
bits/18_cfb.js
1757
bits/18_cfb.js
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
@ -1,29 +1,27 @@
|
||||
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) { return x !== undefined && x !== null; }
|
||||
|
||||
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];
|
||||
function keys(o) { return Object.keys(o); }
|
||||
|
||||
function evert_key(obj, key) {
|
||||
var o = [], K = keys(obj);
|
||||
for(var i = 0; i !== K.length; ++i) o[obj[K[i]][key]] = K[i];
|
||||
return o;
|
||||
}
|
||||
|
||||
function evert(obj/*:any*/)/*:EvertType*/ {
|
||||
var o = ([]/*:any*/), K = keys(obj);
|
||||
function evert(obj) {
|
||||
var o = [], K = keys(obj);
|
||||
for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = K[i];
|
||||
return o;
|
||||
}
|
||||
|
||||
function evert_num(obj/*:any*/)/*:EvertNumType*/ {
|
||||
var o = ([]/*:any*/), K = keys(obj);
|
||||
function evert_num(obj) {
|
||||
var o = [], K = keys(obj);
|
||||
for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = parseInt(K[i],10);
|
||||
return o;
|
||||
}
|
||||
|
||||
function evert_arr(obj/*:any*/)/*:EvertArrType*/ {
|
||||
var o/*:EvertArrType*/ = ([]/*:any*/), K = keys(obj);
|
||||
function evert_arr(obj) {
|
||||
var o = [], K = keys(obj);
|
||||
for(var i = 0; i !== K.length; ++i) {
|
||||
if(o[obj[K[i]]] == null) o[obj[K[i]]] = [];
|
||||
o[obj[K[i]]].push(K[i]);
|
||||
@ -31,350 +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
|
||||
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;
|
||||
}
|
||||
function numdate(v/*:number*/)/*:Date|number*/ {
|
||||
if(v >= 60 && v < 61) return v;
|
||||
var out = new Date();
|
||||
out.setTime((v>60 ? v : (v+1)) * 24 * 60 * 60 * 1000 + dnthresh);
|
||||
return out;
|
||||
/* TODO: date1904 logic */
|
||||
function datenum(v, date1904) {
|
||||
if(date1904) v+=1462;
|
||||
var epoch = Date.parse(v);
|
||||
return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
/* ISO 8601 Duration */
|
||||
function parse_isodur(s) {
|
||||
var sec = 0, mt = 0, time = false;
|
||||
var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
|
||||
if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
|
||||
for(var i = 1; i != m.length; ++i) {
|
||||
if(!m[i]) continue;
|
||||
mt = 1;
|
||||
if(i > 3) time = true;
|
||||
switch(m[i].slice(m[i].length-1)) {
|
||||
case 'Y':
|
||||
throw new Error("Unsupported ISO Duration Field: " + m[i].slice(m[i].length-1));
|
||||
case 'D': mt *= 24;
|
||||
/* falls through */
|
||||
case 'H': mt *= 60;
|
||||
/* falls through */
|
||||
case 'M':
|
||||
if(!time) throw new Error("Unsupported ISO Duration Field: M");
|
||||
else mt *= 60;
|
||||
/* falls through */
|
||||
case 'S': break;
|
||||
}
|
||||
sec += mt * parseInt(m[i], 10);
|
||||
}
|
||||
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 d = new Date(str);
|
||||
return d;
|
||||
}
|
||||
|
||||
function cc2str(arr/*:Array<number>*/, debomit)/*:string*/ {
|
||||
if(has_buf && Buffer.isBuffer(arr)) {
|
||||
if(debomit && buf_utf16le) {
|
||||
// TODO: temporary patch
|
||||
if(arr[0] == 0xFF && arr[1] == 0xFE) return utf8write(arr.slice(2).toString("utf16le"));
|
||||
if(arr[1] == 0xFE && arr[2] == 0xFF) return utf8write(utf16beread(arr.slice(2).toString("binary")));
|
||||
}
|
||||
return arr.toString("binary");
|
||||
}
|
||||
|
||||
if(typeof TextDecoder !== "undefined") try {
|
||||
if(debomit) {
|
||||
if(arr[0] == 0xFF && arr[1] == 0xFE) return utf8write(new TextDecoder("utf-16le").decode(arr.slice(2)));
|
||||
if(arr[0] == 0xFE && arr[1] == 0xFF) return utf8write(new TextDecoder("utf-16be").decode(arr.slice(2)));
|
||||
}
|
||||
var rev = {
|
||||
"\u20ac": "\x80", "\u201a": "\x82", "\u0192": "\x83", "\u201e": "\x84",
|
||||
"\u2026": "\x85", "\u2020": "\x86", "\u2021": "\x87", "\u02c6": "\x88",
|
||||
"\u2030": "\x89", "\u0160": "\x8a", "\u2039": "\x8b", "\u0152": "\x8c",
|
||||
"\u017d": "\x8e", "\u2018": "\x91", "\u2019": "\x92", "\u201c": "\x93",
|
||||
"\u201d": "\x94", "\u2022": "\x95", "\u2013": "\x96", "\u2014": "\x97",
|
||||
"\u02dc": "\x98", "\u2122": "\x99", "\u0161": "\x9a", "\u203a": "\x9b",
|
||||
"\u0153": "\x9c", "\u017e": "\x9e", "\u0178": "\x9f"
|
||||
};
|
||||
if(Array.isArray(arr)) arr = new Uint8Array(arr);
|
||||
return new TextDecoder("latin1").decode(arr).replace(/[€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ]/g, function(c) { return rev[c] || c; });
|
||||
} catch(e) {}
|
||||
|
||||
var o = [], i = 0;
|
||||
// this cascade is for the browsers and runtimes of antiquity (and for modern runtimes that lack TextEncoder)
|
||||
try {
|
||||
for(i = 0; i < arr.length - 65536; i+=65536) o.push(String.fromCharCode.apply(0, arr.slice(i, i + 65536)));
|
||||
o.push(String.fromCharCode.apply(0, arr.slice(i)));
|
||||
} catch(e) { try {
|
||||
for(; i < arr.length - 16384; i+=16384) o.push(String.fromCharCode.apply(0, arr.slice(i, i + 16384)));
|
||||
o.push(String.fromCharCode.apply(0, arr.slice(i)));
|
||||
} catch(e) {
|
||||
for(; i != arr.length; ++i) o.push(String.fromCharCode(arr[i]));
|
||||
}
|
||||
}
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
function 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]);
|
||||
return out;
|
||||
}
|
||||
|
||||
function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; }
|
||||
|
||||
/* 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;
|
||||
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;});
|
||||
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 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;
|
||||
function cc2str(arr) {
|
||||
var o = "";
|
||||
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
|
||||
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());
|
||||
}
|
||||
function local_to_utc(local) {
|
||||
return new Date(Date.UTC(local.getFullYear(), local.getMonth(), local.getDate(), local.getHours(), local.getMinutes(), local.getSeconds(), local.getMilliseconds()));
|
||||
}
|
||||
|
||||
function remove_doctype(str) {
|
||||
var preamble = str.slice(0, 1024);
|
||||
var si = preamble.indexOf("<!DOCTYPE");
|
||||
if(si == -1) return str;
|
||||
var m = str.match(/<[\w]/);
|
||||
if(!m) return str;
|
||||
return str.slice(0, si) + str.slice(m.index);
|
||||
}
|
||||
|
||||
/* str.match(/<!--[\s\S]*?-->/g) --> str_match_ng(str, "<!--", "-->") */
|
||||
function str_match_ng(str, s, e) {
|
||||
var out = [];
|
||||
|
||||
var si = str.indexOf(s);
|
||||
while(si > -1) {
|
||||
var ei = str.indexOf(e, si + s.length);
|
||||
if(ei == -1) break;
|
||||
|
||||
out.push(str.slice(si, ei + e.length));
|
||||
si = str.indexOf(s, ei + e.length);
|
||||
}
|
||||
|
||||
return out.length > 0 ? out : null;
|
||||
}
|
||||
|
||||
/* str.replace(/<!--[\s\S]*?-->/g, "") --> str_remove_ng(str, "<!--", "-->") */
|
||||
function str_remove_ng(str, s, e) {
|
||||
var out = [], last = 0;
|
||||
|
||||
var si = str.indexOf(s);
|
||||
if(si == -1) return str;
|
||||
while(si > -1) {
|
||||
out.push(str.slice(last, si));
|
||||
var ei = str.indexOf(e, si + s.length);
|
||||
if(ei == -1) break;
|
||||
|
||||
if((si = str.indexOf(s, (last = ei + e.length))) == -1) out.push(str.slice(last));
|
||||
}
|
||||
|
||||
return out.join("");
|
||||
}
|
||||
|
||||
/* str.match(/<tag\b[^>]*?>([\s\S]*?)</tag>/) --> str_match_xml(str, "tag") */
|
||||
var xml_boundary = { " ": 1, "\t": 1, "\r": 1, "\n": 1, ">": 1 };
|
||||
function str_match_xml(str, tag) {
|
||||
var si = str.indexOf('<' + tag), w = tag.length + 1, L = str.length;
|
||||
while(si >= 0 && si <= L - w && !xml_boundary[str.charAt(si + w)]) si = str.indexOf('<' + tag, si+1);
|
||||
if(si === -1) return null;
|
||||
var sf = str.indexOf(">", si + tag.length);
|
||||
if(sf === -1) return null;
|
||||
var et = "</" + tag + ">";
|
||||
var ei = str.indexOf(et, sf);
|
||||
if(ei == -1) return null;
|
||||
return [str.slice(si, ei + et.length), str.slice(sf + 1, ei)];
|
||||
}
|
||||
|
||||
/* str.match(/<(?:\w+:)?tag\b[^<>]*?>([\s\S]*?)<\/(?:\w+:)?tag>/) --> str_match_xml(str, "tag") */
|
||||
var str_match_xml_ns = /*#__PURE__*/(function() {
|
||||
var str_match_xml_ns_cache = {};
|
||||
return function str_match_xml_ns(str, tag) {
|
||||
var res = str_match_xml_ns_cache[tag];
|
||||
if(!res) str_match_xml_ns_cache[tag] = res = [
|
||||
new RegExp('<(?:\\w+:)?'+tag+'\\b[^<>]*>', "g"),
|
||||
new RegExp('</(?:\\w+:)?'+tag+'>', "g")
|
||||
];
|
||||
res[0].lastIndex = res[1].lastIndex = 0;
|
||||
var m = res[0].exec(str);
|
||||
if(!m) return null;
|
||||
var si = m.index;
|
||||
var sf = res[0].lastIndex;
|
||||
res[1].lastIndex = res[0].lastIndex;
|
||||
m = res[1].exec(str);
|
||||
if(!m) return null;
|
||||
var ei = m.index;
|
||||
var ef = res[1].lastIndex;
|
||||
return [str.slice(si, ef), str.slice(sf, ei)];
|
||||
};
|
||||
})();
|
||||
|
||||
/* str.match(/<(?:\w+:)?tag\b[^<>]*?>([\s\S]*?)<\/(?:\w+:)?tag>/g) --> str_match_xml_ns_g(str, "tag") */
|
||||
var str_match_xml_ns_g = /*#__PURE__*/(function() {
|
||||
var str_match_xml_ns_cache = {};
|
||||
return function str_match_xml_ns(str, tag) {
|
||||
var out = [];
|
||||
var res = str_match_xml_ns_cache[tag];
|
||||
if(!res) str_match_xml_ns_cache[tag] = res = [
|
||||
new RegExp('<(?:\\w+:)?'+tag+'\\b[^<>]*>', "g"),
|
||||
new RegExp('</(?:\\w+:)?'+tag+'>', "g")
|
||||
];
|
||||
res[0].lastIndex = res[1].lastIndex = 0;
|
||||
var m;
|
||||
while((m = res[0].exec(str))) {
|
||||
var si = m.index;
|
||||
res[1].lastIndex = res[0].lastIndex;
|
||||
m = res[1].exec(str);
|
||||
if(!m) return null;
|
||||
var ef = res[1].lastIndex;
|
||||
out.push(str.slice(si, ef));
|
||||
res[0].lastIndex = res[1].lastIndex;
|
||||
}
|
||||
return out.length == 0 ? null : out;
|
||||
};
|
||||
})();
|
||||
var str_remove_xml_ns_g = /*#__PURE__*/(function() {
|
||||
var str_remove_xml_ns_cache = {};
|
||||
return function str_remove_xml_ns_g(str, tag) {
|
||||
var out = [];
|
||||
var res = str_remove_xml_ns_cache[tag];
|
||||
if(!res) str_remove_xml_ns_cache[tag] = res = [
|
||||
new RegExp('<(?:\\w+:)?'+tag+'\\b[^<>]*>', "g"),
|
||||
new RegExp('</(?:\\w+:)?'+tag+'>', "g")
|
||||
];
|
||||
res[0].lastIndex = res[1].lastIndex = 0;
|
||||
var m;
|
||||
var si = 0, ef = 0;
|
||||
while((m = res[0].exec(str))) {
|
||||
si = m.index;
|
||||
out.push(str.slice(ef, si));
|
||||
ef = si;
|
||||
res[1].lastIndex = res[0].lastIndex;
|
||||
m = res[1].exec(str);
|
||||
if(!m) return null;
|
||||
ef = res[1].lastIndex;
|
||||
res[0].lastIndex = res[1].lastIndex;
|
||||
}
|
||||
out.push(str.slice(ef));
|
||||
return out.length == 0 ? "" : out.join("");
|
||||
};
|
||||
})();
|
||||
|
||||
/* str.match(/<(?:\w+:)?tag\b[^>]*?>([\s\S]*?)<\/(?:\w+:)?tag>/gi) --> str_match_xml_ns_ig(str, "tag") */
|
||||
var str_match_xml_ig = /*#__PURE__*/(function() {
|
||||
var str_match_xml_ns_cache = {};
|
||||
return function str_match_xml_ns(str, tag) {
|
||||
var out = [];
|
||||
var res = str_match_xml_ns_cache[tag];
|
||||
if(!res) str_match_xml_ns_cache[tag] = res = [
|
||||
new RegExp('<'+tag+'\\b[^<>]*>', "ig"),
|
||||
new RegExp('</'+tag+'>', "ig")
|
||||
];
|
||||
res[0].lastIndex = res[1].lastIndex = 0;
|
||||
var m;
|
||||
while((m = res[0].exec(str))) {
|
||||
var si = m.index;
|
||||
res[1].lastIndex = res[0].lastIndex;
|
||||
m = res[1].exec(str);
|
||||
if(!m) return null;
|
||||
var ef = res[1].lastIndex;
|
||||
out.push(str.slice(si, ef));
|
||||
res[0].lastIndex = res[1].lastIndex;
|
||||
}
|
||||
return out.length == 0 ? null : out;
|
||||
};
|
||||
})();
|
||||
|
@ -1,108 +1,49 @@
|
||||
function getdatastr(data)/*:?string*/ {
|
||||
function getdata(data) {
|
||||
if(!data) return null;
|
||||
if(data.content && data.type) return cc2str(data.content, true);
|
||||
if(data.data) return debom(data.data);
|
||||
if(data.asNodeBuffer && has_buf) return debom(data.asNodeBuffer().toString('binary'));
|
||||
if(data.asBinary) return debom(data.asBinary());
|
||||
if(data._data && data._data.getContent) return debom(cc2str(Array.prototype.slice.call(data._data.getContent(),0)));
|
||||
return null;
|
||||
}
|
||||
|
||||
function getdatabin(data) {
|
||||
if(!data) return null;
|
||||
if(data.data) return char_codes(data.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);
|
||||
return Array.prototype.slice.call(o);
|
||||
}
|
||||
if(data.content && data.type) return data.content;
|
||||
return null;
|
||||
}
|
||||
|
||||
function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getdatabin(data) : getdatastr(data); }
|
||||
|
||||
/* 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,'\/');
|
||||
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];
|
||||
if(data.name.substr(-4) === ".bin") {
|
||||
if(data.data) return char_codes(data.data);
|
||||
if(data.asNodeBuffer && has_buf) return data.asNodeBuffer();
|
||||
if(data._data && data._data.getContent) return Array.prototype.slice.call(data._data.getContent());
|
||||
} else {
|
||||
if(data.data) return data.name.substr(-4) !== ".bin" ? debom_xml(data.data) : char_codes(data.data);
|
||||
if(data.asNodeBuffer && has_buf) return debom_xml(data.asNodeBuffer().toString('binary'));
|
||||
if(data.asBinary) return debom_xml(data.asBinary());
|
||||
if(data._data && data._data.getContent) return debom_xml(cc2str(Array.prototype.slice.call(data._data.getContent(),0)));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getzipfile(zip, file/*:string*/) {
|
||||
function safegetzipfile(zip, file) {
|
||||
var f = file; if(zip.files[f]) return zip.files[f];
|
||||
|
||||
var lowerCaseFiles = {};
|
||||
for (var key in zip.files) {
|
||||
lowerCaseFiles[key.toLowerCase()] = zip.files[key];
|
||||
}
|
||||
|
||||
f = file.toLowerCase(); if(lowerCaseFiles[f]) return lowerCaseFiles[f];
|
||||
f = f.replace(/\//g,'\\'); if(lowerCaseFiles[f]) return lowerCaseFiles[f];
|
||||
return null;
|
||||
}
|
||||
|
||||
function getzipfile(zip, file) {
|
||||
var o = safegetzipfile(zip, file);
|
||||
if(o == null) throw new Error("Cannot find file " + file + " in zip");
|
||||
return o;
|
||||
}
|
||||
|
||||
function getzipdata(zip, file/*:string*/, safe/*:?boolean*/)/*:any*/ {
|
||||
function getzipdata(zip, file, safe) {
|
||||
if(!safe) return getdata(getzipfile(zip, file));
|
||||
if(!file) return null;
|
||||
try { return getzipdata(zip, file); } catch(e) { return null; }
|
||||
}
|
||||
|
||||
function getzipstr(zip, file/*:string*/, safe/*:?boolean*/)/*:?string*/ {
|
||||
if(!safe) return getdatastr(getzipfile(zip, file));
|
||||
if(!file) return null;
|
||||
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(Array.isArray(content) && typeof content[0] == "string") {
|
||||
content = content.join("");
|
||||
}
|
||||
if(typeof content == "string") {
|
||||
var res;
|
||||
if(has_buf) res = Buffer_from(content);
|
||||
/* TODO: investigate performance in Edge 13 */
|
||||
//else if(typeof TextEncoder !== "undefined") res = new TextEncoder().encode(content);
|
||||
else res = utf8decode(content);
|
||||
return CFB.utils.cfb_add(zip, path, res);
|
||||
}
|
||||
CFB.utils.cfb_add(zip, path, content);
|
||||
var _fs, jszip;
|
||||
if(typeof JSZip !== 'undefined') jszip = JSZip;
|
||||
if (typeof exports !== 'undefined') {
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
if(has_buf && typeof jszip === 'undefined') jszip = require('js'+'zip');
|
||||
if(typeof jszip === 'undefined') jszip = require('./js'+'zip').JSZip;
|
||||
_fs = require('f'+'s');
|
||||
}
|
||||
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('/');
|
||||
while (target.length !== 0) {
|
||||
var step = target.shift();
|
||||
if (step === '..') result.pop();
|
||||
else if (step !== '.') result.push(step);
|
||||
}
|
||||
return result.join('/');
|
||||
}
|
||||
|
@ -1,58 +1,24 @@
|
||||
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=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
|
||||
var tagregex=/<[^>]*>/g;
|
||||
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
|
||||
function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*/)/*:any*/ {
|
||||
var z = ({}/*:any*/);
|
||||
function parsexmltag(tag, skip_root) {
|
||||
var z = [];
|
||||
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;
|
||||
var m = tag.match(attregexg), j=0, w="", v="", i=0, q="", cc="";
|
||||
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;
|
||||
quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0;
|
||||
v = cc.slice(c+1+quot, cc.length-quot);
|
||||
q = cc.substr(0,c); v = cc.substring(c+2, cc.length-1);
|
||||
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
|
||||
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
|
||||
z[k] = v;
|
||||
if(!skip_LC) z[k.toLowerCase()] = v;
|
||||
}
|
||||
if(j===q.length) z[q] = v;
|
||||
else z[(j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1)] = v;
|
||||
}
|
||||
return z;
|
||||
}
|
||||
function parsexmltagraw(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*/)/*:any*/ {
|
||||
var z = ({}/*:any*/);
|
||||
var eq = 0, c = 0;
|
||||
for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
|
||||
if(!skip_root) z[0] = tag.slice(0, eq);
|
||||
if(eq === tag.length) return z;
|
||||
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1;
|
||||
if(m) for(i = 0; i != m.length; ++i) {
|
||||
cc = m[i].slice(1);
|
||||
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
|
||||
q = cc.slice(0,c).trim();
|
||||
while(cc.charCodeAt(c+1) == 32) ++c;
|
||||
quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0;
|
||||
v = cc.slice(c+1+quot, cc.length-quot);
|
||||
if(q.indexOf("_") > 0) q = q.slice(0, q.indexOf("_")); // from ods
|
||||
z[q] = v;
|
||||
if(!skip_LC) z[q.toLowerCase()] = v;
|
||||
}
|
||||
return z;
|
||||
}
|
||||
function strip_ns(x/*:string*/)/*:string*/ { return x.replace(nsregex2, "<$1"); }
|
||||
function strip_ns(x) { return x.replace(nsregex2, "<$1"); }
|
||||
|
||||
var encodings = {
|
||||
'"': '"',
|
||||
@ -61,68 +27,46 @@ var encodings = {
|
||||
'<': '<',
|
||||
'&': '&'
|
||||
};
|
||||
var rencoding = /*#__PURE__*/evert(encodings);
|
||||
//var rencstr = "&<>'\"".split("");
|
||||
var rencoding = evert(encodings);
|
||||
var rencstr = "&<>'\"".split("");
|
||||
|
||||
// TODO: CP remap (need to read file version to determine OS)
|
||||
var unescapexml/*:StringConv*/ = /*#__PURE__*/(function() {
|
||||
/* 22.4.2.4 bstr (Basic String) */
|
||||
var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/g;
|
||||
function raw_unescapexml(text/*:string*/)/*:string*/ {
|
||||
var 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;
|
||||
var unescapexml = (function() {
|
||||
var encregex = /&[a-z]*;/g, coderegex = /_x([\da-fA-F]+)_/g;
|
||||
return function unescapexml(text){
|
||||
var s = text + '';
|
||||
return s.replace(encregex, function($$) { return encodings[$$]; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
|
||||
};
|
||||
})();
|
||||
|
||||
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){
|
||||
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*/{
|
||||
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(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).substr(-4) + "_";});
|
||||
}
|
||||
|
||||
/* TODO: handle codepages */
|
||||
var xlml_fixstr/*:StringConv*/ = /*#__PURE__*/(function() {
|
||||
var xlml_fixstr = (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 entrepl($$,$1) { return String.fromCharCode(parseInt($1,10)); }
|
||||
return function xlml_fixstr(str) { return str.replace(entregex,entrepl); };
|
||||
})();
|
||||
function xlml_unfixstr(str/*:string*/)/*:string*/ { return str.replace(/(\r\n|[\r\n])/g,"\ "); }
|
||||
|
||||
/* note: xsd:boolean valid values: true / 1 / false / 0 */
|
||||
function parsexmlbool(value/*:any*/)/*:boolean*/ {
|
||||
function parsexmlbool(value, tag) {
|
||||
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 'TRUE': return true;
|
||||
/* case '0': case 'false': case 'FALSE':*/
|
||||
default: return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function utf8reada(orig/*:string*/)/*:string*/ {
|
||||
var utf8read = 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++);
|
||||
if (c < 128) { out += String.fromCharCode(c); continue; }
|
||||
d = orig.charCodeAt(i++);
|
||||
if (c>191 && c<224) { f = ((c & 31) << 6); f |= (d & 63); out += String.fromCharCode(f); continue; }
|
||||
if (c>191 && c<224) { out += String.fromCharCode(((c & 31) << 6) | (d & 63)); continue; }
|
||||
e = orig.charCodeAt(i++);
|
||||
if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; }
|
||||
f = orig.charCodeAt(i++);
|
||||
@ -131,135 +75,82 @@ 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 out/*:Array<string>*/ = [], i = 0, c = 0, d = 0;
|
||||
while(i < orig.length) {
|
||||
c = orig.charCodeAt(i++);
|
||||
switch(true) {
|
||||
case c < 128: out.push(String.fromCharCode(c)); break;
|
||||
case c < 2048:
|
||||
out.push(String.fromCharCode(192 + (c >> 6)));
|
||||
out.push(String.fromCharCode(128 + (c & 63)));
|
||||
break;
|
||||
case c >= 55296 && c < 57344:
|
||||
c -= 55296; d = orig.charCodeAt(i++) - 56320 + (c<<10);
|
||||
out.push(String.fromCharCode(240 + ((d >>18) & 7)));
|
||||
out.push(String.fromCharCode(144 + ((d >>12) & 63)));
|
||||
out.push(String.fromCharCode(128 + ((d >> 6) & 63)));
|
||||
out.push(String.fromCharCode(128 + (d & 63)));
|
||||
break;
|
||||
default:
|
||||
out.push(String.fromCharCode(224 + (c >> 12)));
|
||||
out.push(String.fromCharCode(128 + ((c >> 6) & 63)));
|
||||
out.push(String.fromCharCode(128 + (c & 63)));
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
out.length = k;
|
||||
return out.toString('ucs2');
|
||||
};
|
||||
var corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3";
|
||||
if(utf8read(corpus) == utf8readb(corpus)) utf8read = utf8readb;
|
||||
var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
|
||||
if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
|
||||
}
|
||||
|
||||
// matches <foo>...</foo> extracts content
|
||||
var matchtag = (function() {
|
||||
var mtcache = {};
|
||||
return function matchtag(f,g) {
|
||||
var t = f+"|"+g;
|
||||
if(mtcache[t] !== undefined) return mtcache[t];
|
||||
return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([^\u2603]*)</(?:\\w+:)?'+f+'>',(g||"")));
|
||||
};
|
||||
})();
|
||||
|
||||
var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^<"'>]*)>([\s\S]*)</;
|
||||
function parseVector(data/*:string*/, opts)/*:Array<{v:string,t:string}>*/ {
|
||||
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 + ">(.*?)</vt:" + bt + ">", 'g') );
|
||||
};})();
|
||||
var vtvregex = /<\/?vt:variant>/g, vtmregex = /<vt:([^>]*)>(.*)</;
|
||||
function parseVector(data) {
|
||||
var h = parsexmltag(data);
|
||||
|
||||
var matches/*:Array<string>*/ = str_match_xml_ns_g(data, h.baseType)||[];
|
||||
var res/*:Array<any>*/ = [];
|
||||
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*/) {
|
||||
var matches = data.match(vtregex(h.baseType))||[];
|
||||
if(matches.length != h.size) throw "unexpected vector length " + matches.length + " != " + h.size;
|
||||
var res = [];
|
||||
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: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 wxt_helper(h) { return keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join(""); }
|
||||
function writextag(f,g,h) { return '<' + f + (isval(h) ? wxt_helper(h) : "") + (isval(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_w3cdtf(d, t) { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } }
|
||||
|
||||
function write_vt(s, xlsx/*:?boolean*/)/*:string*/ {
|
||||
function write_vt(s) {
|
||||
switch(typeof s) {
|
||||
case 'string':
|
||||
var o = writextag('vt:lpwstr', escapexml(s));
|
||||
if(xlsx) o = o.replace(/"/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',
|
||||
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
|
||||
var XMLNS = {
|
||||
'dc': 'http://purl.org/dc/elements/1.1/',
|
||||
'dcterms': 'http://purl.org/dc/terms/',
|
||||
'dcmitype': 'http://purl.org/dc/dcmitype/',
|
||||
@ -269,21 +160,12 @@ var XMLNS = ({
|
||||
'vt': 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes',
|
||||
'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
||||
'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',
|
||||
'http://schemas.microsoft.com/office/excel/2006/2'
|
||||
];
|
||||
|
||||
var XLMLNS = ({
|
||||
'o': 'urn:schemas-microsoft-com:office:office',
|
||||
'x': 'urn:schemas-microsoft-com:office:excel',
|
||||
'ss': 'urn:schemas-microsoft-com:office:spreadsheet',
|
||||
'dt': 'uuid:C2F41010-65B3-11d1-A29F-00AA00C14882',
|
||||
'mv': 'http://macVmlSchemaUri',
|
||||
'v': 'urn:schemas-microsoft-com:vml',
|
||||
'html': 'http://www.w3.org/TR/REC-html40'
|
||||
}/*:any*/);
|
||||
|
@ -1,129 +1,94 @@
|
||||
function read_double_le(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ {
|
||||
var s = 1 - 2 * (b[idx + 7] >>> 7);
|
||||
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 == 0) e = -1022;
|
||||
else { e -= 1023; m += Math.pow(2,52); }
|
||||
return s * Math.pow(2, e - 52) * m;
|
||||
function readIEEE754(buf, idx, isLE, nl, ml) {
|
||||
if(isLE === undefined) isLE = true;
|
||||
if(!nl) nl = 8;
|
||||
if(!ml && nl === 8) ml = 52;
|
||||
var e, m, el = nl * 8 - ml - 1, eMax = (1 << el) - 1, eBias = eMax >> 1;
|
||||
var bits = -7, d = isLE ? -1 : 1, i = isLE ? (nl - 1) : 0, s = buf[idx + i];
|
||||
|
||||
i += d;
|
||||
e = s & ((1 << (-bits)) - 1); s >>>= (-bits); bits += el;
|
||||
for (; bits > 0; e = e * 256 + buf[idx + i], i += d, bits -= 8);
|
||||
m = e & ((1 << (-bits)) - 1); e >>>= (-bits); bits += ml;
|
||||
for (; bits > 0; m = m * 256 + buf[idx + i], i += d, bits -= 8);
|
||||
if (e === eMax) return m ? NaN : ((s ? -1 : 1) * Infinity);
|
||||
else if (e === 0) e = 1 - eBias;
|
||||
else { m = m + Math.pow(2, ml); e = e - eBias; }
|
||||
return (s ? -1 : 1) * m * Math.pow(2, e - ml);
|
||||
}
|
||||
|
||||
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;
|
||||
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; }
|
||||
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 + 7] = (e >> 4) | bs;
|
||||
}
|
||||
var __toBuffer, ___toBuffer;
|
||||
__toBuffer = ___toBuffer = function toBuffer_(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; };
|
||||
var __utf16le, ___utf16le;
|
||||
__utf16le = ___utf16le = function utf16le_(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join(""); };
|
||||
var __hexlify, ___hexlify;
|
||||
__hexlify = ___hexlify = function hexlify_(b,s,l) { return b.slice(s,(s+l)).map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); };
|
||||
var __utf8, ___utf8;
|
||||
__utf8 = ___utf8 = function(b,s,e) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
|
||||
var __lpstr, ___lpstr;
|
||||
__lpstr = ___lpstr = function lpstr_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
|
||||
var __lpwstr, ___lpwstr;
|
||||
__lpwstr = ___lpwstr = function lpwstr_(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
|
||||
var __double, ___double;
|
||||
__double = ___double = function(b, idx) { return readIEEE754(b, idx);};
|
||||
|
||||
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); };
|
||||
|
||||
if(has_buf/*:: && typeof Buffer !== 'undefined'*/) {
|
||||
__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);};
|
||||
__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);};
|
||||
__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); };
|
||||
var is_buf = function is_buf_a(a) { return Array.isArray(a); };
|
||||
if(has_buf) {
|
||||
__utf16le = function utf16le_b(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e); };
|
||||
__hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
|
||||
__lpstr = function lpstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
|
||||
__lpwstr = function lpwstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
|
||||
__utf8 = function utf8_b(s,e) { return this.toString('utf8',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,i) { if(Buffer.isBuffer(b)) return b.readDoubleLE(i); return ___double(b,i); };
|
||||
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,s,e) { return cptable.utils.decode(1200, b.slice(s,e)); };
|
||||
__utf8 = function(b,s,e) { return cptable.utils.decode(65001, b.slice(s,e)); };
|
||||
__lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";};
|
||||
__lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";};
|
||||
}
|
||||
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 __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 __readUInt8 = function(b, idx) { return b[idx]; };
|
||||
var __readUInt16LE = function(b, idx) { return b[idx+1]*(1<<8)+b[idx]; };
|
||||
var __readInt16LE = function(b, idx) { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; };
|
||||
var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
|
||||
var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
|
||||
|
||||
function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
|
||||
var o="", oI/*:: :number = 0*/, oR, oo=[], w, vv, i, loc;
|
||||
var ___unhexlify = function(s) { return s.match(/../g).map(function(x) { return parseInt(x,16);}); };
|
||||
var __unhexlify = typeof Buffer !== "undefined" ? function(s) { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;
|
||||
|
||||
function ReadShift(size, t) {
|
||||
var o="", oI, 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;
|
||||
|
||||
case 'utf8': o = __utf8(this, this.l, this.l + size); break;
|
||||
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));
|
||||
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;
|
||||
/* [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) */
|
||||
case '8lpp4': size = 4 + __readUInt32LE(this, this.l); o = __8lpp4(this, this.l); if(size & 0x03) size += 4 - (size & 0x03); break;
|
||||
case 'lpwstr': o = __lpwstr(this, this.l); size = 5 + o.length; if(o[o.length-1] == '\u0000') size += 2; break;
|
||||
|
||||
case 'cstr': size = 0; o = "";
|
||||
while((w=__readUInt8(this, this.l + size++))!==0) oo.push(_getchar(w));
|
||||
o = oo.join(""); break;
|
||||
case '_wstr': size = 0; o = "";
|
||||
case 'wstr': size = 0; o = "";
|
||||
while((w=__readUInt16LE(this,this.l +size))!==0){oo.push(_getchar(w));size+=2;}
|
||||
size+=2; o = oo.join(""); break;
|
||||
|
||||
/* 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 +99,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) {
|
||||
@ -156,98 +115,51 @@ function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
|
||||
switch(size) {
|
||||
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; }
|
||||
else { oR = __readUInt32LE(this, this.l); this.l += 4; } return oR;
|
||||
case 8: case -8:
|
||||
if(t === 'f') {
|
||||
if(size == 8) oR = __double(this, this.l);
|
||||
else oR = __double([this[this.l+7],this[this.l+6],this[this.l+5],this[this.l+4],this[this.l+3],this[this.l+2],this[this.l+1],this[this.l+0]], 0);
|
||||
this.l += 8; return oR;
|
||||
} else size = 8;
|
||||
case 4:
|
||||
if(t === 'i' || (this[this.l+3] & 0x80)===0) { oI = __readInt32LE(this, this.l); this.l += 4; return oI; }
|
||||
else { oR = __readUInt32LE(this, this.l); this.l += 4; return oR; } break;
|
||||
case 8: if(t === 'f') { oR = __double(this, this.l); this.l += 8; return oR; }
|
||||
/* falls through */
|
||||
case 16: o = __hexlify(this, this.l, size); break;
|
||||
}}
|
||||
this.l+=size; return o;
|
||||
}
|
||||
|
||||
var __writeUInt32LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); b[idx+2] = ((val >>> 16) & 0xFF); b[idx+3] = ((val >>> 24) & 0xFF); };
|
||||
var __writeInt32LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); };
|
||||
var __writeUInt16LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); };
|
||||
|
||||
function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/)/*:any*/ {
|
||||
var size = 0, i = 0;
|
||||
function WriteShift(t, val, f) {
|
||||
var size, i;
|
||||
if(f === 'dbcs') {
|
||||
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
|
||||
for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i);
|
||||
for(i = 0; i != val.length; ++i) this.writeUInt16LE(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 === '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);
|
||||
} return this;
|
||||
} else if(f === 'utf16le') {
|
||||
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
|
||||
var end/*:number*/ = Math.min(this.l + t, this.length);
|
||||
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);
|
||||
}
|
||||
while(this.l < end) this[this.l++] = 0;
|
||||
return this;
|
||||
} else /*:: if(typeof val === 'number') */ switch(t) {
|
||||
case 1: size = 1; this[this.l] = val&0xFF; break;
|
||||
case 2: size = 2; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; break;
|
||||
case 3: size = 3; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; val >>>= 8; this[this.l+2] = val&0xFF; break;
|
||||
case 4: size = 4; __writeUInt32LE(this, val, this.l); break;
|
||||
case 8: size = 8; if(f === 'f') { write_double_le(this, val, this.l); break; }
|
||||
} else switch(t) {
|
||||
case 1: size = 1; this[this.l] = val&255; break;
|
||||
case 3: size = 3; this[this.l+2] = val & 255; val >>>= 8; this[this.l+1] = val&255; val >>>= 8; this[this.l] = val&255; break;
|
||||
case 4: size = 4; this.writeUInt32LE(val, this.l); break;
|
||||
case 8: size = 8; if(f === 'f') { this.writeDoubleLE(val, this.l); break; }
|
||||
/* falls through */
|
||||
case 16: break;
|
||||
case -4: size = 4; __writeInt32LE(this, val, this.l); break;
|
||||
case -4: size = 4; this.writeInt32LE(val, this.l); break;
|
||||
}
|
||||
this.l += size; return this;
|
||||
}
|
||||
|
||||
function CheckField(hexstr/*:string*/, fld/*:string*/)/*:void*/ {
|
||||
function CheckField(hexstr, fld) {
|
||||
var m = __hexlify(this,this.l,hexstr.length>>1);
|
||||
if(m !== hexstr) throw new Error(fld + 'Expected ' + hexstr + ' saw ' + m);
|
||||
if(m !== hexstr) throw fld + 'Expected ' + hexstr + ' saw ' + m;
|
||||
this.l += hexstr.length>>1;
|
||||
}
|
||||
|
||||
function prep_blob(blob, pos/*:number*/)/*:void*/ {
|
||||
function prep_blob(blob, pos) {
|
||||
blob.l = pos;
|
||||
blob.read_shift = /*::(*/ReadShift/*:: :any)*/;
|
||||
blob.read_shift = ReadShift;
|
||||
blob.chk = CheckField;
|
||||
blob.write_shift = WriteShift;
|
||||
}
|
||||
|
||||
function parsenoop(blob, length/*:: :number, opts?:any */) { blob.l += length; }
|
||||
function parsenoop(blob, length) { blob.l += length; }
|
||||
|
||||
function new_buf(sz/*:number*/)/*:Block*/ {
|
||||
function writenoop(blob, length) { blob.l += length; }
|
||||
|
||||
function new_buf(sz) {
|
||||
var o = new_raw_buf(sz);
|
||||
prep_blob(o, 0);
|
||||
return o;
|
||||
|
@ -1,71 +1,56 @@
|
||||
/* [MS-XLSB] 2.1.4 Record */
|
||||
function recordhopper(data, cb/*:RecordHopperCB*/, opts/*:?any*/) {
|
||||
if(!data) return;
|
||||
function recordhopper(data, cb, opts) {
|
||||
var tmpbyte, cntbyte, length;
|
||||
prep_blob(data, data.l || 0);
|
||||
var L = data.length, RT = 0, tgt = 0;
|
||||
while(data.l < L) {
|
||||
RT = data.read_shift(1);
|
||||
while(data.l < data.length) {
|
||||
var RT = data.read_shift(1);
|
||||
if(RT & 0x80) RT = (RT & 0x7F) + ((data.read_shift(1) & 0x7F)<<7);
|
||||
var R = XLSBRecordEnum[RT] || XLSBRecordEnum[0xFFFF];
|
||||
tmpbyte = data.read_shift(1);
|
||||
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);
|
||||
data.l = tgt;
|
||||
var d = R.f(data, length, opts);
|
||||
if(cb(d, R, RT)) return;
|
||||
}
|
||||
}
|
||||
|
||||
/* control buffer usage for fixed-length buffers */
|
||||
function buf_array()/*:BufArray*/ {
|
||||
var bufs/*:Array<Block>*/ = [], blksz = has_buf ? 16384 : 2048;
|
||||
var has_buf_copy = has_buf && (typeof new_buf(blksz).copy == "function");
|
||||
var newblk = function ba_newblk(sz/*:number*/)/*:Block*/ {
|
||||
var o/*:Block*/ = (new_buf(sz)/*:any*/);
|
||||
function buf_array() {
|
||||
var bufs = [], blksz = 2048;
|
||||
var newblk = function ba_newblk(sz) {
|
||||
var o = new_buf(sz);
|
||||
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);
|
||||
}
|
||||
curbuf.length = 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(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);
|
||||
};
|
||||
var end2 = function() {
|
||||
endbuf(); return bufs;
|
||||
return __toBuffer([bufs]);
|
||||
};
|
||||
|
||||
var push = function ba_push(buf) {
|
||||
endbuf(); curbuf = buf; if(curbuf.l == null) curbuf.l = curbuf.length; next(blksz);
|
||||
};
|
||||
var push = function ba_push(buf) { endbuf(); curbuf = buf; next(blksz); };
|
||||
|
||||
return ({ next:next, push:push, end:end, _bufs:bufs, end2:end2 }/*:any*/);
|
||||
return { next:next, push:push, end:end, _bufs:bufs };
|
||||
}
|
||||
|
||||
function write_record(ba/*:BufArray*/, type/*:number*/, payload, length/*:?number*/) {
|
||||
var t/*:number*/ = +type, l;
|
||||
if(isNaN(t)) return; // TODO: throw something here?
|
||||
function write_record(ba, type, payload, length) {
|
||||
var t = evert_RE[type], l;
|
||||
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);
|
||||
@ -77,5 +62,5 @@ function write_record(ba/*:BufArray*/, type/*:number*/, payload, length/*:?numbe
|
||||
if(length >= 0x80) { o.write_shift(1, (length & 0x7F)+0x80); length >>= 7; }
|
||||
else { o.write_shift(1, length); break; }
|
||||
}
|
||||
if(/*:: length != null &&*/length > 0 && is_buf(payload)) ba.push(payload);
|
||||
if(length > 0 && is_buf(payload)) ba.push(payload);
|
||||
}
|
||||
|
@ -1,46 +1,21 @@
|
||||
/* XLS ranges enforced */
|
||||
function shift_cell_xls(cell/*:CellAddress*/, tgt/*:any*/, opts/*:?any*/)/*:CellAddress*/ {
|
||||
var out = dup(cell);
|
||||
function shift_cell_xls(cell, tgt) {
|
||||
if(tgt.s) {
|
||||
if(out.cRel) out.c += tgt.s.c;
|
||||
if(out.rRel) out.r += tgt.s.r;
|
||||
if(cell.cRel) cell.c += tgt.s.c;
|
||||
if(cell.rRel) cell.r += tgt.s.r;
|
||||
} else {
|
||||
if(out.cRel) out.c += tgt.c;
|
||||
if(out.rRel) out.r += tgt.r;
|
||||
cell.c += tgt.c;
|
||||
cell.r += tgt.r;
|
||||
}
|
||||
if(!opts || opts.biff < 12) {
|
||||
while(out.c >= 0x100) out.c -= 0x100;
|
||||
while(out.r >= 0x10000) out.r -= 0x10000;
|
||||
}
|
||||
return out;
|
||||
cell.cRel = cell.rRel = 0;
|
||||
while(cell.c >= 0x100) cell.c -= 0x100;
|
||||
while(cell.r >= 0x10000) cell.r -= 0x10000;
|
||||
return cell;
|
||||
}
|
||||
|
||||
function shift_range_xls(cell, range, opts) {
|
||||
var out = dup(cell);
|
||||
out.s = shift_cell_xls(out.s, range.s, opts);
|
||||
out.e = shift_cell_xls(out.e, range.s, opts);
|
||||
return out;
|
||||
function shift_range_xls(cell, range) {
|
||||
cell.s = shift_cell_xls(cell.s, range.s);
|
||||
cell.e = shift_cell_xls(cell.e, range.s);
|
||||
return cell;
|
||||
}
|
||||
|
||||
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); }
|
||||
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);
|
||||
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) {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
@ -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'));
|
||||
}
|
35
bits/26_crypto.js
Normal file
35
bits/26_crypto.js
Normal file
@ -0,0 +1,35 @@
|
||||
var OFFCRYPTO = {};
|
||||
var make_offcrypto = function(O, _crypto) {
|
||||
var crypto;
|
||||
if(typeof _crypto !== 'undefined') crypto = _crypto;
|
||||
else if(typeof require !== 'undefined') {
|
||||
try { crypto = require('cry'+'pto'); }
|
||||
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;
|
||||
}
|
||||
i = j = 0; 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;
|
||||
};
|
||||
|
||||
if(crypto) {
|
||||
O.md5 = function(hex) { return crypto.createHash('md5').update(hex).digest('hex'); };
|
||||
} else {
|
||||
O.md5 = function(hex) { throw "unimplemented"; };
|
||||
}
|
||||
};
|
||||
make_offcrypto(OFFCRYPTO, typeof crypto !== "undefined" ? crypto : undefined);
|
||||
|
@ -1,198 +0,0 @@
|
||||
function decode_row(rowstr/*:string*/)/*:number*/ { return parseInt(unfix_row(rowstr),10) - 1; }
|
||||
function encode_row(row/*:number*/)/*:string*/ { return "" + (row + 1); }
|
||||
function fix_row(cstr/*:string*/)/*:string*/ { return cstr.replace(/([A-Z]|^)(\d+)$/,"$1$$$2"); }
|
||||
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 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)) };
|
||||
}
|
||||
/*# 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') {
|
||||
/*:: if(!(cs instanceof Range)) throw "unreachable"; */
|
||||
return encode_range(cs.s, cs.e);
|
||||
}
|
||||
/*:: if((cs instanceof Range)) throw "unreachable"; */
|
||||
if(typeof cs !== 'string') cs = encode_cell((cs/*:any*/));
|
||||
if(typeof ce !== 'string') ce = encode_cell((ce/*:any*/));
|
||||
/*:: if(typeof cs !== 'string') throw "unreachable"; */
|
||||
/*:: 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}};
|
||||
var idx = 0, i = 0, cc = 0;
|
||||
var len = range.length;
|
||||
for(idx = 0; i < len; ++i) {
|
||||
if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
|
||||
idx = 26*idx + cc;
|
||||
}
|
||||
o.s.c = --idx;
|
||||
|
||||
for(idx = 0; i < len; ++i) {
|
||||
if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
|
||||
idx = 10*idx + cc;
|
||||
}
|
||||
o.s.r = --idx;
|
||||
|
||||
if(i === len || cc != 10) { o.e.c=o.s.c; o.e.r=o.s.r; return o; }
|
||||
++i;
|
||||
|
||||
for(idx = 0; i != len; ++i) {
|
||||
if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
|
||||
idx = 26*idx + cc;
|
||||
}
|
||||
o.e.c = --idx;
|
||||
|
||||
for(idx = 0; i != len; ++i) {
|
||||
if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
|
||||
idx = 10*idx + cc;
|
||||
}
|
||||
o.e.r = --idx;
|
||||
return o;
|
||||
}
|
||||
|
||||
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; }
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ {
|
||||
var n = opts && opts.sheet ? opts.sheet : "Sheet1";
|
||||
var sheets = {}; sheets[n] = sheet;
|
||||
return { SheetNames: [n], Sheets: sheets };
|
||||
}
|
||||
|
||||
function sheet_new(opts) {
|
||||
var out = {};
|
||||
var o = opts || {};
|
||||
if(o.dense) out["!data"] = [];
|
||||
return out;
|
||||
}
|
||||
|
||||
function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
|
||||
var o = opts || {};
|
||||
var dense = _ws ? (_ws["!data"] != null) : o.dense;
|
||||
if(DENSE != null && dense == null) dense = DENSE;
|
||||
var ws/*:Worksheet*/ = _ws || (dense ? ({"!data": []}) : ({}/*: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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
if(dense) {
|
||||
if(!ws["!data"][__R]) ws["!data"][__R] = [];
|
||||
row = ws["!data"][__R];
|
||||
}
|
||||
var data_R = data[R];
|
||||
for(var C = 0; C != data_R.length; ++C) {
|
||||
if(typeof data_R[C] === 'undefined') continue;
|
||||
var cell/*:Cell*/ = ({v: data_R[C], t:"" }/*:any*/);
|
||||
var __C = _C + C;
|
||||
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') {
|
||||
if(isFinite(cell.v)) cell.t = 'n';
|
||||
else if(isNaN(cell.v)) { cell.t = 'e'; cell.v = 0x0F; /* #VALUE! */ }
|
||||
else { cell.t = 'e'; cell.v = 0x07; /*# DIV/0 */ }
|
||||
}
|
||||
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(dense) {
|
||||
if(row[__C] && row[__C].z) cell.z = row[__C].z;
|
||||
row[__C] = cell;
|
||||
} else {
|
||||
var cell_ref = encode_col(__C) + (__R + 1)/*:any*/;
|
||||
if(ws[cell_ref] && ws[cell_ref].z) cell.z = ws[cell_ref].z;
|
||||
ws[cell_ref] = cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(seen && range.s.c < 10400000) ws['!ref'] = encode_range(range);
|
||||
return ws;
|
||||
}
|
||||
function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { return sheet_add_aoa(null, data, opts); }
|
@ -1,164 +1,109 @@
|
||||
function parse_Int32LE(data) {
|
||||
return data.read_shift(4, 'i');
|
||||
}
|
||||
function write_UInt32LE(x/*:number*/, o) {
|
||||
if (!o) o = new_buf(4);
|
||||
o.write_shift(4, x);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.168 */
|
||||
function parse_XLWideString(data/*::, length*/)/*:string*/ {
|
||||
var cchCharacters = data.read_shift(4);
|
||||
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); }
|
||||
o.write_shift(4, data.length);
|
||||
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) {
|
||||
return { ich: data.read_shift(2), ifnt: data.read_shift(2) };
|
||||
}
|
||||
function write_StrRun(run, o) {
|
||||
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 */
|
||||
function parse_RichStr(data, length/*:number*/)/*:XLString*/ {
|
||||
/* [MS-XLSB] 2.1.7.121 */
|
||||
function parse_RichStr(data, length) {
|
||||
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 */
|
||||
var z = { t: str, h: str };
|
||||
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 }];
|
||||
//if((flags & 2) !== 0) { /* fExtStr */
|
||||
// /* TODO: phonetic string */
|
||||
//}
|
||||
else z.r = "<t>" + escapexml(str) + "</t>";
|
||||
if((flags & 2) !== 0) { /* fExtStr */
|
||||
/* TODO: phonetic string */
|
||||
}
|
||||
data.l = start + length;
|
||||
return z;
|
||||
}
|
||||
function write_RichStr(str/*:XLString*/, o/*:?Block*/)/*:Block*/ {
|
||||
function write_RichStr(str, o) {
|
||||
/* TODO: formatted string */
|
||||
var _null = false; if (o == null) { _null = true; o = new_buf(15 + 4 * str.t.length); }
|
||||
o.write_shift(1, 0);
|
||||
if(o == null) o = new_buf(5+2*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) */
|
||||
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);
|
||||
write_XLWideString(str.t, o);
|
||||
o.write_shift(4, 1);
|
||||
write_StrRun({ ich: 0, ifnt: 0 }, o);
|
||||
return _null ? o.slice(0, o.l) : o;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.9 */
|
||||
function parse_XLSBCell(data)/*:any*/ {
|
||||
function parse_XLSBCell(data) {
|
||||
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);
|
||||
function write_XLSBCell(cell, o) {
|
||||
if(o == null) o = new_buf(8);
|
||||
o.write_shift(-4, cell.c);
|
||||
o.write_shift(3, cell.iStyleRef || cell.s);
|
||||
o.write_shift(3, cell.iStyleRef === undefined ? 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;
|
||||
var write_XLSBCodeName = write_XLWideString;
|
||||
function parse_XLSBCodeName (data, length) { return parse_XLWideString(data, length); }
|
||||
|
||||
/* [MS-XLSB] 2.5.166 */
|
||||
function parse_XLNullableWideString(data/*::, length*/)/*:string*/ {
|
||||
function parse_XLNullableWideString(data) {
|
||||
var cchCharacters = data.read_shift(4);
|
||||
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); }
|
||||
function write_XLNullableWideString(data, o) {
|
||||
if(!o) o = new_buf(127);
|
||||
o.write_shift(4, data.length > 0 ? data.length : 0xFFFFFFFF);
|
||||
if (data.length > 0) o.write_shift(0, data, 'dbcs');
|
||||
return _null ? o.slice(0, o.l) : o;
|
||||
if(data.length > 0) o.write_shift(0, data, 'dbcs');
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.165 */
|
||||
var parse_XLNameWideString = parse_XLWideString;
|
||||
//var write_XLNameWideString = write_XLWideString;
|
||||
/* [MS-XLSB] 2.5.168 */
|
||||
function parse_XLWideString(data) {
|
||||
var cchCharacters = data.read_shift(4);
|
||||
return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, 'dbcs');
|
||||
}
|
||||
function write_XLWideString(data, o) {
|
||||
if(o == null) o = new_buf(4+2*data.length);
|
||||
o.write_shift(4, data.length);
|
||||
if(data.length > 0) o.write_shift(0, data, 'dbcs');
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [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 */
|
||||
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;
|
||||
}
|
||||
function write_RkNumber(data/*:number*/, o) {
|
||||
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));
|
||||
else throw new Error("unsupported RkNumber " + data); // TODO
|
||||
/* [MS-XLSB] 2.5.122 */
|
||||
/* [MS-XLS] 2.5.217 */
|
||||
function parse_RkNumber(data) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* [MS-XLSB] 2.5.117 RfX */
|
||||
function parse_RfX(data /*::, length*/)/*:Range*/ {
|
||||
var cell/*:Range*/ = ({ s: {}, e: {} }/*:any*/);
|
||||
/* [MS-XLSB] 2.5.153 */
|
||||
function parse_UncheckedRfX(data) {
|
||||
var cell = {s: {}, e: {}};
|
||||
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);
|
||||
|
||||
function write_UncheckedRfX(r, o) {
|
||||
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);
|
||||
@ -166,112 +111,46 @@ function write_RfX(r/*:Range*/, o) {
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.153 UncheckedRfX */
|
||||
var parse_UncheckedRfX = parse_RfX;
|
||||
var write_UncheckedRfX = write_RfX;
|
||||
/* [MS-XLSB] 2.5.171 */
|
||||
/* [MS-XLS] 2.5.342 */
|
||||
function parse_Xnum(data, length) { return data.read_shift(8, 'f'); }
|
||||
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, 'f', data); }
|
||||
|
||||
/* [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-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-XLS] 2.5.342 ; [MS-XLSB] 2.5.171 */
|
||||
/* 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 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.4.321 BrtColor */
|
||||
function parse_BrtColor(data, length) {
|
||||
var out = {};
|
||||
var d = data.read_shift(1);
|
||||
|
||||
//var fValidRGB = d & 1;
|
||||
var xColorType = d >>> 1;
|
||||
|
||||
var index = data.read_shift(1);
|
||||
var nTS = data.read_shift(2, 'i');
|
||||
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);
|
||||
|
||||
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);
|
||||
break;
|
||||
case 2:
|
||||
/* if(!fValidRGB) throw new Error("invalid"); */
|
||||
out.rgb = rgb2Hex([bR, bG, bB]);
|
||||
break;
|
||||
case 3: out.theme = index; break;
|
||||
}
|
||||
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) {
|
||||
o.write_shift(1, 0x02);
|
||||
o.write_shift(1, color.index);
|
||||
} else if (color.theme != null) {
|
||||
o.write_shift(1, 0x06);
|
||||
o.write_shift(1, color.theme);
|
||||
} else {
|
||||
o.write_shift(1, 0x05);
|
||||
o.write_shift(1, 0);
|
||||
}
|
||||
var nTS = color.tint || 0;
|
||||
if (nTS > 0) nTS *= 32767;
|
||||
else if (nTS < 0) nTS *= 32768;
|
||||
o.write_shift(2, nTS);
|
||||
if (!color.rgb || color.theme != null) {
|
||||
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, 0xFF);
|
||||
}
|
||||
return o;
|
||||
out.fValidRGB = d & 1;
|
||||
out.xColorType = d >>> 1;
|
||||
out.index = data.read_shift(1);
|
||||
out.nTintAndShade = data.read_shift(2, 'i');
|
||||
out.bRed = data.read_shift(1);
|
||||
out.bGreen = data.read_shift(1);
|
||||
out.bBlue = data.read_shift(1);
|
||||
out.bAlpha = data.read_shift(1);
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.52 */
|
||||
function parse_FontFlags(data/*::, length, opts*/) {
|
||||
function parse_FontFlags(data, length) {
|
||||
var d = data.read_shift(1);
|
||||
data.l++;
|
||||
var out = {
|
||||
fBold: d & 0x01,
|
||||
fItalic: d & 0x02,
|
||||
fUnderline: d & 0x04,
|
||||
fStrikeout: d & 0x08,
|
||||
fItalic: d & 0x2,
|
||||
fStrikeout: d & 0x8,
|
||||
fOutline: d & 0x10,
|
||||
fShadow: d & 0x20,
|
||||
fCondense: d & 0x40,
|
||||
@ -279,33 +158,3 @@ function parse_FontFlags(data/*::, length, opts*/) {
|
||||
};
|
||||
return out;
|
||||
}
|
||||
function write_FontFlags(font, o) {
|
||||
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.condense ? 0x40 : 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); }
|
||||
|
||||
|
@ -1,46 +1,45 @@
|
||||
/* [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;
|
||||
var VT_I4 = 0x0003;
|
||||
//var VT_R4 = 0x0004;
|
||||
//var VT_R8 = 0x0005;
|
||||
//var VT_CY = 0x0006;
|
||||
//var VT_DATE = 0x0007;
|
||||
//var VT_BSTR = 0x0008;
|
||||
//var VT_ERROR = 0x000A;
|
||||
var VT_BOOL = 0x000B;
|
||||
var VT_VARIANT = 0x000C;
|
||||
//var VT_DECIMAL = 0x000E;
|
||||
//var VT_I1 = 0x0010;
|
||||
//var VT_UI1 = 0x0011;
|
||||
//var VT_UI2 = 0x0012;
|
||||
var VT_UI4 = 0x0013;
|
||||
//var VT_I8 = 0x0014;
|
||||
//var VT_UI8 = 0x0015;
|
||||
//var VT_INT = 0x0016;
|
||||
//var VT_UINT = 0x0017;
|
||||
//var VT_LPSTR = 0x001E;
|
||||
//var VT_LPWSTR = 0x001F;
|
||||
var VT_FILETIME = 0x0040;
|
||||
var VT_BLOB = 0x0041;
|
||||
//var VT_STREAM = 0x0042;
|
||||
//var VT_STORAGE = 0x0043;
|
||||
//var VT_STREAMED_Object = 0x0044;
|
||||
//var VT_STORED_Object = 0x0045;
|
||||
//var VT_BLOB_Object = 0x0046;
|
||||
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_ARRAY = 0x2000;
|
||||
{
|
||||
var VT_EMPTY = 0x0000;
|
||||
var VT_NULL = 0x0001;
|
||||
var VT_I2 = 0x0002;
|
||||
var VT_I4 = 0x0003;
|
||||
var VT_R4 = 0x0004;
|
||||
var VT_R8 = 0x0005;
|
||||
var VT_CY = 0x0006;
|
||||
var VT_DATE = 0x0007;
|
||||
var VT_BSTR = 0x0008;
|
||||
var VT_ERROR = 0x000A;
|
||||
var VT_BOOL = 0x000B;
|
||||
var VT_VARIANT = 0x000C;
|
||||
var VT_DECIMAL = 0x000E;
|
||||
var VT_I1 = 0x0010;
|
||||
var VT_UI1 = 0x0011;
|
||||
var VT_UI2 = 0x0012;
|
||||
var VT_UI4 = 0x0013;
|
||||
var VT_I8 = 0x0014;
|
||||
var VT_UI8 = 0x0015;
|
||||
var VT_INT = 0x0016;
|
||||
var VT_UINT = 0x0017;
|
||||
var VT_LPSTR = 0x001E;
|
||||
var VT_LPWSTR = 0x001F;
|
||||
var VT_FILETIME = 0x0040;
|
||||
var VT_BLOB = 0x0041;
|
||||
var VT_STREAM = 0x0042;
|
||||
var VT_STORAGE = 0x0043;
|
||||
var VT_STREAMED_Object = 0x0044;
|
||||
var VT_STORED_Object = 0x0045;
|
||||
var VT_BLOB_Object = 0x0046;
|
||||
var VT_CF = 0x0047;
|
||||
var VT_CLSID = 0x0048;
|
||||
var VT_VERSIONED_STREAM = 0x0049;
|
||||
var VT_VECTOR = 0x1000;
|
||||
var VT_ARRAY = 0x2000;
|
||||
|
||||
var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
|
||||
var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString
|
||||
var VT_CUSTOM = [VT_STRING, VT_USTR];
|
||||
var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
|
||||
var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString
|
||||
var VT_CUSTOM = [VT_STRING, VT_USTR];
|
||||
}
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */
|
||||
var DocSummaryPIDDSI = {
|
||||
@ -54,26 +53,21 @@ var DocSummaryPIDDSI = {
|
||||
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 */ },
|
||||
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: 'LinksUpToDate', t: VT_BOOL },
|
||||
0x10: { n: 'LinksDirty', t: VT_BOOL },
|
||||
0x11: { n: 'CharacterCount', t: VT_I4 },
|
||||
0x13: { n: 'SharedDoc', t: VT_BOOL },
|
||||
0x16: { n: 'HyperlinksChanged', t: VT_BOOL },
|
||||
0x16: { n: 'HLinksChanged', 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: {}
|
||||
0xFF: {}
|
||||
};
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.2.1.1 Summary Information Property Set PIDSI */
|
||||
@ -95,15 +89,23 @@ var SummaryPIDSI = {
|
||||
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 */
|
||||
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
|
||||
@ -181,11 +183,10 @@ 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([
|
||||
var XLSIcv = rgbify([
|
||||
/* Color Constants */
|
||||
0x000000,
|
||||
0xFFFFFF,
|
||||
@ -196,7 +197,7 @@ var _XLSIcv = /*#__PURE__*/ rgbify([
|
||||
0xFF00FF,
|
||||
0x00FFFF,
|
||||
|
||||
/* Overridable Defaults */
|
||||
/* Defaults */
|
||||
0x000000,
|
||||
0xFFFFFF,
|
||||
0xFF0000,
|
||||
@ -257,67 +258,8 @@ var _XLSIcv = /*#__PURE__*/ rgbify([
|
||||
0x333399,
|
||||
0x333333,
|
||||
|
||||
/* Other entries to appease BIFF8/12 */
|
||||
0x000000, /* 0x40 icvForeground ?? */
|
||||
0xFFFFFF, /* 0x41 icvBackground ?? */
|
||||
0x000000, /* 0x42 icvFrame ?? */
|
||||
0x000000, /* 0x43 icv3D ?? */
|
||||
0x000000, /* 0x44 icv3DText ?? */
|
||||
0x000000, /* 0x45 icv3DHilite ?? */
|
||||
0x000000, /* 0x46 icv3DShadow ?? */
|
||||
0x000000, /* 0x47 icvHilite ?? */
|
||||
0x000000, /* 0x48 icvCtlText ?? */
|
||||
0x000000, /* 0x49 icvCtlScrl ?? */
|
||||
0x000000, /* 0x4A icvCtlInv ?? */
|
||||
0x000000, /* 0x4B icvCtlBody ?? */
|
||||
0x000000, /* 0x4C icvCtlFrame ?? */
|
||||
0x000000, /* 0x4D icvCtlFore ?? */
|
||||
0x000000, /* 0x4E icvCtlBack ?? */
|
||||
0x000000, /* 0x4F icvCtlNeutral */
|
||||
0x000000, /* 0x50 icvInfoBk ?? */
|
||||
0x000000 /* 0x51 icvInfoText ?? */
|
||||
/* Sheet */
|
||||
0xFFFFFF,
|
||||
0x000000
|
||||
]);
|
||||
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"
|
||||
];
|
||||
|
||||
|
235
bits/30_ctype.js
235
bits/30_ctype.js
@ -1,41 +1,28 @@
|
||||
/* 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 */
|
||||
var ct2type/*{[string]:string}*/ = ({
|
||||
/* [MS-XLSX] 2.1 Part Enumerations */
|
||||
/* [MS-XLSB] 2.1.7 Part Enumeration */
|
||||
var ct2type = {
|
||||
/* 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 */
|
||||
"application/vnd.ms-excel.chartsheet": "TODO",
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml": "TODO",
|
||||
|
||||
/* Dialogsheet */
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml": "dialogs",
|
||||
"application/vnd.ms-excel.dialogsheet": "dialogs",
|
||||
"application/vnd.ms-excel.dialogsheet": "TODO",
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml": "TODO",
|
||||
|
||||
/* 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",
|
||||
/* Macrosheet */
|
||||
"application/vnd.ms-excel.macrosheet": "TODO",
|
||||
"application/vnd.ms-excel.macrosheet+xml": "TODO",
|
||||
"application/vnd.ms-excel.intlmacrosheet": "TODO",
|
||||
"application/vnd.ms-excel.binIndexMs": "TODO", /* Binary Index */
|
||||
|
||||
/* File Properties */
|
||||
"application/vnd.openxmlformats-package.core-properties+xml": "coreprops",
|
||||
@ -44,34 +31,15 @@ var ct2type/*{[string]:string}*/ = ({
|
||||
|
||||
/* Custom Data Properties */
|
||||
"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",
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": "comments",
|
||||
|
||||
/* 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",
|
||||
@ -91,8 +59,12 @@ var ct2type/*{[string]:string}*/ = ({
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml": "TODO",
|
||||
|
||||
/* External Links */
|
||||
"application/vnd.ms-excel.externalLink": "links",
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml": "links",
|
||||
"application/vnd.ms-excel.externalLink": "TODO",
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml": "TODO",
|
||||
|
||||
/* Metadata */
|
||||
"application/vnd.ms-excel.sheetMetadata": "TODO",
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml": "TODO",
|
||||
|
||||
/* PivotCache */
|
||||
"application/vnd.ms-excel.pivotCacheDefinition": "TODO",
|
||||
@ -132,16 +104,13 @@ var ct2type/*{[string]:string}*/ = ({
|
||||
/* Themes */
|
||||
"application/vnd.openxmlformats-officedocument.theme+xml": "themes",
|
||||
|
||||
/* Theme Override */
|
||||
"application/vnd.openxmlformats-officedocument.themeOverride+xml": "TODO",
|
||||
|
||||
/* Timeline */
|
||||
"application/vnd.ms-excel.Timeline+xml": "TODO", /* verify */
|
||||
"application/vnd.ms-excel.TimelineCache+xml": "TODO", /* verify */
|
||||
|
||||
/* 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",
|
||||
@ -157,7 +126,8 @@ var ct2type/*{[string]:string}*/ = ({
|
||||
"application/vnd.ms-excel.Survey+xml": "TODO",
|
||||
|
||||
/* Drawing */
|
||||
"application/vnd.openxmlformats-officedocument.drawing+xml": "drawings",
|
||||
"application/vnd.openxmlformats-officedocument.drawing+xml": "TODO",
|
||||
"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",
|
||||
@ -170,75 +140,54 @@ var ct2type/*{[string]:string}*/ = ({
|
||||
"application/vnd.openxmlformats-package.relationships+xml": "rels",
|
||||
"application/vnd.openxmlformats-officedocument.oleObject": "TODO",
|
||||
|
||||
/* Image */
|
||||
"image/png": "TODO",
|
||||
|
||||
"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"
|
||||
}
|
||||
};
|
||||
|
||||
function new_ct()/*:any*/ {
|
||||
return ({
|
||||
workbooks:[], sheets:[], charts:[], dialogs:[], macros:[],
|
||||
rels:[], strs:[], comments:[], threadedcomments:[], links:[],
|
||||
coreprops:[], extprops:[], custprops:[], themes:[], styles:[],
|
||||
calcchains:[], vba: [], drawings: [], metadata: [], people:[],
|
||||
TODO:[], xmlns: "" }/*:any*/);
|
||||
}
|
||||
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"
|
||||
},
|
||||
sheets: {
|
||||
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
|
||||
xlsb: "application/vnd.ms-excel.worksheet"
|
||||
},
|
||||
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;
|
||||
})();
|
||||
|
||||
function parse_ct(data/*:?string*/) {
|
||||
var ct = new_ct();
|
||||
if(!data || !data.match) return ct;
|
||||
var type2ct = evert_arr(ct2type);
|
||||
|
||||
XMLNS.CT = 'http://schemas.openxmlformats.org/package/2006/content-types';
|
||||
|
||||
function parse_ct(data, opts) {
|
||||
var ctext = {};
|
||||
if(!data || !data.match) return data;
|
||||
var ct = { workbooks: [], sheets: [], calcchains: [], themes: [], styles: [],
|
||||
coreprops: [], extprops: [], custprops: [], strs:[], comments: [], vba: [],
|
||||
TODO:[], rels:[], xmlns: "" };
|
||||
(data.match(tagregex)||[]).forEach(function(x) {
|
||||
var y = parsexmltag(x);
|
||||
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);
|
||||
else if(opts.WTF) console.error(y);
|
||||
break;
|
||||
}
|
||||
});
|
||||
@ -251,60 +200,42 @@ 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 o/*:Array<string>*/ = [], v;
|
||||
var CTYPE_DEFAULTS = [
|
||||
['xml', 'application/xml'],
|
||||
['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
|
||||
['rels', type2ct.rels[0]]
|
||||
].map(function(x) {
|
||||
return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
|
||||
});
|
||||
|
||||
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 */
|
||||
function write_ct(ct, opts) {
|
||||
var o = [], v;
|
||||
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) {
|
||||
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,19 +244,11 @@ function write_ct(ct, opts, raw)/*:string*/ {
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
f1('workbooks');
|
||||
f2('sheets');
|
||||
f2('charts');
|
||||
f3('themes');
|
||||
['strs', 'styles'].forEach(f1);
|
||||
['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("");
|
||||
}
|
||||
|
107
bits/31_rels.js
107
bits/31_rels.js
@ -1,59 +1,38 @@
|
||||
/* 9.3 Relationships */
|
||||
var RELS = ({
|
||||
/* 9.3.2 OPC Relationships Markup */
|
||||
var RELS = {
|
||||
WB: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
|
||||
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*/);
|
||||
SHEET: "http://sheetjs.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
|
||||
};
|
||||
|
||||
/* 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";
|
||||
}
|
||||
|
||||
function parse_rels(data/*:?string*/, currentFilePath/*:string*/) {
|
||||
var rels = {"!id":{}};
|
||||
if (!data) return rels;
|
||||
function parse_rels(data, currentFilePath) {
|
||||
if (!data) return data;
|
||||
if (currentFilePath.charAt(0) !== '/') {
|
||||
currentFilePath = '/'+currentFilePath;
|
||||
}
|
||||
var rels = {};
|
||||
var hash = {};
|
||||
var resolveRelativePathIntoAbsolute = function (to) {
|
||||
var toksFrom = currentFilePath.split('/');
|
||||
toksFrom.pop(); // folder path
|
||||
var toksTo = to.split('/');
|
||||
var reversed = [];
|
||||
while (toksTo.length !== 0) {
|
||||
var tokTo = toksTo.shift();
|
||||
if (tokTo === '..') {
|
||||
toksFrom.pop();
|
||||
} else if (tokTo !== '.') {
|
||||
toksFrom.push(tokTo);
|
||||
}
|
||||
}
|
||||
return toksFrom.join('/');
|
||||
};
|
||||
|
||||
(data.match(tagregex)||[]).forEach(function(x) {
|
||||
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 canonictarget = y.TargetMode === 'External' ? y.Target : resolve_path(y.Target, currentFilePath);
|
||||
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 : resolveRelativePathIntoAbsolute(y.Target);
|
||||
rels[canonictarget] = rel;
|
||||
hash[y.Id] = rel;
|
||||
}
|
||||
@ -62,33 +41,21 @@ 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
|
||||
})];
|
||||
keys(rels['!id']).forEach(function(rid) {
|
||||
o[o.length] = (writextag('Relationship', null, rels['!id'][rid]));
|
||||
function write_rels(rels) {
|
||||
var o = [];
|
||||
o[o.length] = (XML_HEADER);
|
||||
o[o.length] = (RELS_ROOT);
|
||||
keys(rels['!id']).forEach(function(rid) { var rel = rels['!id'][rid];
|
||||
o[o.length] = (writextag('Relationship', null, rel));
|
||||
});
|
||||
if(o.length>2){ o[o.length] = ('</Relationships>'); o[1]=o[1].replace("/>",">"); }
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
function add_rels(rels, rId/*:number*/, f, type, relobj, targetmode/*:?string*/)/*:number*/ {
|
||||
if(!relobj) relobj = {};
|
||||
if(!rels['!id']) rels['!id'] = {};
|
||||
if(!rels['!idx']) rels['!idx'] = 1;
|
||||
if(rId < 0) for(rId = rels['!idx']; rels['!id']['rId' + rId]; ++rId){/* empty */}
|
||||
rels['!idx'] = rId + 1;
|
||||
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(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId);
|
||||
rels['!id'][relobj.Id] = relobj;
|
||||
rels[('/' + relobj.Target).replace("//","/")] = relobj;
|
||||
return rId;
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
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_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("");
|
||||
}
|
||||
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(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>";
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/* ECMA-376 Part II 11.1 Core Properties Part */
|
||||
/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
|
||||
var CORE_PROPS/*:Array<Array<string> >*/ = [
|
||||
var CORE_PROPS = [
|
||||
["cp:category", "Category"],
|
||||
["cp:contentStatus", "ContentStatus"],
|
||||
["cp:keywords", "Keywords"],
|
||||
@ -18,51 +18,62 @@ 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 = (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 + "[^>]*>(.*)<\/" + 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]);
|
||||
if(f[2] === 'date' && p[f[1]]) p[f[1]] = parseDate(p[f[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]] = new Date(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 = {};
|
||||
if(!cp && !opts.Props) return o.join("");
|
||||
function write_core_props(cp, opts) {
|
||||
var o = [XML_HEADER, CORE_PROPS_XML_ROOT], p = {};
|
||||
if (opts && opts.Props) {
|
||||
if (opts.Props.title) o[o.length] = '<dc:title>' + opts.Props.title + '</dc:title>';
|
||||
if (opts.Props.subject) o[o.length] = '<dc:subject>' + opts.Props.subject + '</dc:subject>';
|
||||
if (opts.Props.creator) o[o.length] = '<dc:creator>' + opts.Props.creator + '</dc:creator>';
|
||||
if (opts.Props.keywords) o[o.length] = '<cp:keywords>' + opts.Props.keywords + '</cp:keywords>';
|
||||
if (opts.Props.description) o[o.length] = '<dc:description>' + opts.Props.description + '</dc:description>';
|
||||
}
|
||||
if(cp) {
|
||||
|
||||
if(cp) {
|
||||
if(cp.CreatedDate != null) cp_doit("dcterms:created", typeof cp.CreatedDate === "string" ? cp.CreatedDate : write_w3cdtf(cp.CreatedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
|
||||
if(cp.ModifiedDate != null) cp_doit("dcterms:modified", typeof cp.ModifiedDate === "string" ? cp.ModifiedDate : write_w3cdtf(cp.ModifiedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
|
||||
}
|
||||
if(cp.CreatedDate != null) cp_doit("dcterms:created", typeof cp.CreatedDate === "string" ? cp.CreatedDate : write_w3cdtf(cp.CreatedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
|
||||
if(cp.ModifiedDate != null) cp_doit("dcterms:modified", typeof cp.ModifiedDate === "string" ? cp.ModifiedDate : write_w3cdtf(cp.ModifiedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
|
||||
|
||||
for(var i = 0; i != CORE_PROPS.length; ++i) {
|
||||
var f = CORE_PROPS[i];
|
||||
var v = opts.Props && opts.Props[f[1]] != null ? opts.Props[f[1]] : cp ? cp[f[1]] : null;
|
||||
if(v === true) v = "1";
|
||||
else if(v === false) v = "0";
|
||||
else if(typeof v == "number") v = String(v);
|
||||
if(v != null) cp_doit(f[0], v, null, o, p);
|
||||
}
|
||||
if(o.length>2){ o[o.length] = ('</cp:coreProperties>'); o[1]=o[1].replace("/>",">"); }
|
||||
return o.join("");
|
||||
for(var i = 0; i != CORE_PROPS.length; ++i) { var f = CORE_PROPS[i]; cp_doit(f[0], cp[f[1]], null, o, p); }
|
||||
}
|
||||
if(o.length>2){ o[o.length] = ('</cp:coreProperties>'); o[1]=o[1].replace("/>",">"); }
|
||||
return o.join("");
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* 15.2.12.3 Extended File Properties Part */
|
||||
/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
|
||||
var EXT_PROPS/*:Array<Array<string> >*/ = [
|
||||
var EXT_PROPS = [
|
||||
["Application", "Application", "string"],
|
||||
["AppVersion", "AppVersion", "string"],
|
||||
["Company", "Company", "string"],
|
||||
@ -14,94 +14,55 @@ 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;
|
||||
XMLNS.EXT_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
|
||||
RELS.EXT_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
function parse_ext_props(data, p, opts) {
|
||||
function parse_ext_props(data, p) {
|
||||
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] + "[^>]*>(.*)<\/" + 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);
|
||||
var j = 0, widx = 0;
|
||||
for(var i = 0; i !== v.length; ++i) {
|
||||
switch(v[i].v) {
|
||||
case "Worksheets": widx = j; p.Worksheets = +(v[++i].v); break;
|
||||
case "Named Ranges": ++i; break; // TODO: Handle Named Ranges
|
||||
}
|
||||
}
|
||||
var parts = parseVector(q.TitlesOfParts).map(function(x) { return utf8read(x.v); });
|
||||
p.SheetNames = parts.slice(widx, widx + p.Worksheets);
|
||||
}
|
||||
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) {
|
||||
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 = cp[f[1]]; break;
|
||||
case 'bool': v = cp[f[1]] ? 'true' : 'false'; break;
|
||||
}
|
||||
if(v !== undefined) o[o.length] = (W(f[0], v));
|
||||
@ -109,7 +70,7 @@ function write_ext_props(cp/*::, opts*/)/*:string*/ {
|
||||
|
||||
/* TODO: HeadingPairs, TitlesOfParts */
|
||||
o[o.length] = (W('HeadingPairs', W('vt:vector', W('vt:variant', '<vt:lpstr>Worksheets</vt:lpstr>')+W('vt:variant', W('vt:i4', String(cp.Worksheets))), {size:2, baseType:"variant"})));
|
||||
o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + escapexml(s) + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
|
||||
o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + s + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
|
||||
if(o.length>2){ o[o.length] = ('</Properties>'); o[1]=o[1].replace("/>",">"); }
|
||||
return o.join("");
|
||||
}
|
||||
|
@ -1,25 +1,31 @@
|
||||
/* 15.2.12.2 Custom File Properties Part */
|
||||
var custregex = /<[^<>]+>[^<]*/g;
|
||||
function parse_cust_props(data/*:string*/, opts) {
|
||||
var p = {}, name = "";
|
||||
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, 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 '<Properties':
|
||||
if(y.xmlns !== XMLNS.CUST_PROPS) throw "unrecognized xmlns " + y.xmlns;
|
||||
if(y.xmlnsvt && y.xmlnsvt !== XMLNS.vt) throw "unrecognized vt " + y.xmlnsvt;
|
||||
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':
|
||||
case 'lpstr': case 'lpwstr': 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);
|
||||
@ -28,34 +34,35 @@ function parse_cust_props(data/*:string*/, opts) {
|
||||
p[name] = parseFloat(text);
|
||||
break;
|
||||
case 'filetime': case 'date':
|
||||
p[name] = parseDate(text);
|
||||
p[name] = new Date(text);
|
||||
break;
|
||||
case 'cy': case 'error':
|
||||
p[name] = unescapexml(text);
|
||||
break;
|
||||
default:
|
||||
if(type.slice(-1) == '/') break;
|
||||
if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks);
|
||||
if(typeof console !== 'undefined') console.warn('Unexpected', x, type, toks);
|
||||
}
|
||||
} else if(x.slice(0,2) === "</") {/* empty */
|
||||
} else if(x.substr(0,2) === "</") {
|
||||
} 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) {
|
||||
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), {
|
||||
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("/>",">"); }
|
||||
|
@ -1,92 +1,8 @@
|
||||
/* Common Name -> XLML Name */
|
||||
var XLMLDocPropsMap = {
|
||||
Title: 'Title',
|
||||
Subject: 'Subject',
|
||||
Author: 'Author',
|
||||
Keywords: 'Keywords',
|
||||
Comments: 'Description',
|
||||
LastAuthor: 'LastAuthor',
|
||||
RevNumber: 'Revision',
|
||||
Application: 'AppName',
|
||||
/* TotalTime: 'TotalTime', */
|
||||
LastPrinted: 'LastPrinted',
|
||||
CreatedDate: 'Created',
|
||||
ModifiedDate: 'LastSaved',
|
||||
/* Pages */
|
||||
/* Words */
|
||||
/* Characters */
|
||||
Category: 'Category',
|
||||
/* PresentationFormat */
|
||||
Manager: 'Manager',
|
||||
Company: 'Company',
|
||||
/* Guid */
|
||||
/* HyperlinkBase */
|
||||
/* Bytes */
|
||||
/* Lines */
|
||||
/* Paragraphs */
|
||||
/* CharactersWithSpaces */
|
||||
AppVersion: 'Version',
|
||||
|
||||
ContentStatus: 'ContentStatus', /* NOTE: missing from schema */
|
||||
Identifier: 'Identifier', /* NOTE: missing from schema */
|
||||
Language: 'Language' /* NOTE: missing from schema */
|
||||
};
|
||||
var evert_XLMLDPM;
|
||||
|
||||
function xlml_set_prop(Props, tag/*:string*/, val) {
|
||||
if(!evert_XLMLDPM) evert_XLMLDPM = evert(XLMLDocPropsMap);
|
||||
tag = evert_XLMLDPM[tag] || tag;
|
||||
function xlml_set_prop(Props, tag, val) {
|
||||
/* TODO: Normalize the properties */
|
||||
switch(tag) {
|
||||
case 'Description': tag = 'Comments'; break;
|
||||
}
|
||||
Props[tag] = val;
|
||||
}
|
||||
|
||||
function xlml_write_docprops(Props, opts) {
|
||||
var o/*:Array<string>*/ = [];
|
||||
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];
|
||||
throw m;
|
||||
}).forEach(function(p) {
|
||||
if(Props[p[1]] == null) return;
|
||||
var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]];
|
||||
switch(p[2]) {
|
||||
case 'date': m = new Date(m).toISOString().replace(/\.\d*Z/,"Z"); break;
|
||||
}
|
||||
if(typeof m == 'number') m = String(m);
|
||||
else if(m === true || m === false) { m = m ? "1" : "0"; }
|
||||
else if(m instanceof Date) m = new Date(m).toISOString().replace(/\.\d*Z/,"");
|
||||
o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m));
|
||||
});
|
||||
return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o });
|
||||
}
|
||||
function xlml_write_custprops(Props, Custprops/*::, opts*/) {
|
||||
var BLACKLIST = ["Worksheets","SheetNames"];
|
||||
var T = 'CustomDocumentProperties';
|
||||
var o/*:Array<string>*/ = [];
|
||||
if(Props) keys(Props).forEach(function(k) {
|
||||
/*:: if(!Props) return; */
|
||||
if(!Object.prototype.hasOwnProperty.call(Props, 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;
|
||||
|
||||
var m = Props[k];
|
||||
var t = "string";
|
||||
if(typeof m == 'number') { t = "float"; m = String(m); }
|
||||
else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
|
||||
else m = String(m);
|
||||
o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
|
||||
});
|
||||
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;
|
||||
var m = Custprops[k];
|
||||
var t = "string";
|
||||
if(typeof m == 'number') { t = "float"; m = String(m); }
|
||||
else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
|
||||
else if(m instanceof Date) { t = "dateTime.tz"; m = m.toISOString(); }
|
||||
else m = String(m);
|
||||
o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
|
||||
});
|
||||
return '<' + T + ' xmlns="' + XLMLNS.o + '">' + o.join("") + '</' + T + '>';
|
||||
}
|
||||
|
@ -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;
|
||||
function parse_lpstr(blob, type, pad) {
|
||||
var str = blob.read_shift(0, 'lpstr');
|
||||
if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3;
|
||||
return str;
|
||||
}
|
||||
|
||||
@ -38,35 +28,25 @@ function parse_VtStringBase(blob, stringType, pad) {
|
||||
return parse_lpstr(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;
|
||||
}
|
||||
function parse_VtString(blob, t, pad) { return parse_VtStringBase(blob, t, pad === false ? 0: 4); }
|
||||
function parse_VtUnalignedString(blob, t) { if(!t) throw new Error("dafuq?"); return parse_VtStringBase(blob, t, 0); }
|
||||
|
||||
/* [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,19 +55,24 @@ 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);
|
||||
var dict/*:{[number]:string}*/ = ({}/*:any*/);
|
||||
var dict = {};
|
||||
for(var j = 0; j != cnt; ++j) {
|
||||
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,8 +82,7 @@ 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;
|
||||
if(size & 3 > 0) blob.l += (4 - (size & 3)) & 3;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@ -108,55 +92,55 @@ 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*/ {
|
||||
function parse_TypedPropertyValue(blob, type, _opts) {
|
||||
var t = blob.read_shift(2), ret, opts = _opts||{};
|
||||
blob.l += 2;
|
||||
if(type !== VT_VARIANT)
|
||||
if(t !== type && VT_CUSTOM.indexOf(type)===-1 && !((type & 0xFFFE) == 0x101E && (t & 0xFFFE) == 0x101E)) throw new Error('Expected type ' + type + ' saw ' + t);
|
||||
if(t !== type && VT_CUSTOM.indexOf(type)===-1) throw new Error('Expected type ' + type + ' saw ' + t);
|
||||
switch(type === VT_VARIANT ? t : type) {
|
||||
case 0x02 /*VT_I2*/: ret = blob.read_shift(2, 'i'); if(!opts.raw) blob.l += 2; return ret;
|
||||
case 0x03 /*VT_I4*/: ret = blob.read_shift(4, 'i'); return ret;
|
||||
case 0x0B /*VT_BOOL*/: return blob.read_shift(4) !== 0x0;
|
||||
case 0x13 /*VT_UI4*/: ret = blob.read_shift(4); return ret;
|
||||
case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
|
||||
case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
|
||||
case 0x1E /*VT_LPSTR*/: return parse_lpstr(blob, t, 4).replace(chr0,'');
|
||||
case 0x1F /*VT_LPWSTR*/: return parse_lpwstr(blob);
|
||||
case 0x40 /*VT_FILETIME*/: return parse_FILETIME(blob);
|
||||
case 0x41 /*VT_BLOB*/: return parse_BLOB(blob);
|
||||
case 0x47 /*VT_CF*/: return parse_ClipboardData(blob);
|
||||
case 0x50 /*VT_STRING*/: return parse_VtString(blob, t, !opts.raw).replace(chr0,'');
|
||||
case 0x51 /*VT_USTR*/: return parse_VtUnalignedString(blob, t/*, 4*/).replace(chr0,'');
|
||||
case 0x100C /*VT_VECTOR|VT_VARIANT*/: return parse_VtVecHeadingPairValue(blob);
|
||||
case 0x101E /*VT_VECTOR|VT_LPSTR*/:
|
||||
case 0x101F /*VT_VECTOR|VT_LPWSTR*/:
|
||||
return t == 0x101F ? parse_VtVecLpwstrValue(blob) : parse_VtVecUnalignedLpstrValue(blob);
|
||||
case 0x50 /*VT_STRING*/: return parse_VtString(blob, t, !opts.raw && 4).replace(chr0,'');
|
||||
case 0x51 /*VT_USTR*/: return parse_VtUnalignedString(blob, t, 4).replace(chr0,'');
|
||||
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) {
|
||||
@ -165,58 +149,59 @@ function parse_PropertySet(blob, PIDSI) {
|
||||
var NumProps = blob.read_shift(4);
|
||||
var Props = [], i = 0;
|
||||
var CodePage = 0;
|
||||
var Dictionary = -1, DictObj/*:{[number]:string}*/ = ({}/*:any*/);
|
||||
var Dictionary = -1, DictObj;
|
||||
for(i = 0; i != NumProps; ++i) {
|
||||
var PropID = blob.read_shift(4);
|
||||
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 */
|
||||
case 874:
|
||||
case 932:
|
||||
case 936:
|
||||
case 949:
|
||||
case 950:
|
||||
case 1250:
|
||||
case 1251:
|
||||
case 1253:
|
||||
case 1254:
|
||||
case 1255:
|
||||
case 1256:
|
||||
case 1257:
|
||||
case 1258:
|
||||
case 10000:
|
||||
case 1200:
|
||||
case 1201:
|
||||
case 1252:
|
||||
case 65000: case -536:
|
||||
case 65001: case -535:
|
||||
set_cp(CodePage = (PropH[piddsi.n]>>>0) & 0xFFFF); break;
|
||||
case 10000: // OSX Roman
|
||||
case 1252: // Windows Latin
|
||||
|
||||
case 874: // SB Windows Thai
|
||||
case 1250: // SB Windows Central Europe
|
||||
case 1251: // SB Windows Cyrillic
|
||||
case 1253: // SB Windows Greek
|
||||
case 1254: // SB Windows Turkish
|
||||
case 1255: // SB Windows Hebrew
|
||||
case 1256: // SB Windows Arabic
|
||||
case 1257: // SB Windows Baltic
|
||||
case 1258: // SB Windows Vietnam
|
||||
|
||||
case 932: // DB Windows Japanese Shift-JIS
|
||||
case 936: // DB Windows Simplified Chinese GBK
|
||||
case 949: // DB Windows Korean
|
||||
case 950: // DB Windows Traditional Chinese Big5
|
||||
|
||||
case 1200: // UTF16LE
|
||||
case 1201: // UTF16BE
|
||||
case 65000: case -536: // UTF-7
|
||||
case 65001: case -535: // UTF-8
|
||||
set_cp(CodePage = PropH[piddsi.n]); break;
|
||||
default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
|
||||
}
|
||||
} else {
|
||||
if(Props[i][0] === 0x1) {
|
||||
CodePage = PropH.CodePage = (parse_TypedPropertyValue(blob, VT_I2)/*:number*/);
|
||||
CodePage = PropH.CodePage = parse_TypedPropertyValue(blob, VT_I2);
|
||||
set_cp(CodePage);
|
||||
if(Dictionary !== -1) {
|
||||
var oldpos = blob.l;
|
||||
@ -233,13 +218,13 @@ 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;
|
||||
case 0x0B /*VT_BOOL*/: blob.l += 4; val = parsebool(blob, 4); break;
|
||||
case 0x40 /*VT_FILETIME*/: blob.l += 4; val = parseDate(parse_FILETIME(blob)); break;
|
||||
case 0x40 /*VT_FILETIME*/: blob.l += 4; val = new Date(parse_FILETIME(blob)); break;
|
||||
default: throw new Error("unparsed value: " + blob[blob.l]);
|
||||
}
|
||||
PropH[name] = val;
|
||||
@ -249,143 +234,42 @@ 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);
|
||||
|
||||
var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;
|
||||
var NumSets, FMTID0, FMTID1, Offset0, Offset1;
|
||||
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);
|
||||
if(NumSets !== 1 && NumSets !== 2) throw "Unrecognized #Sets: " + NumSets;
|
||||
FMTID0 = blob.read_shift(16); Offset0 = blob.read_shift(4);
|
||||
|
||||
if(NumSets === 1 && Offset0 !== blob.l) throw new Error("Length mismatch: " + Offset0 + " !== " + blob.l);
|
||||
if(NumSets === 1 && Offset0 !== blob.l) throw "Length mismatch";
|
||||
else if(NumSets === 2) { FMTID1 = blob.read_shift(16); Offset1 = blob.read_shift(4); }
|
||||
var PSet0 = parse_PropertySet(blob, PIDSI);
|
||||
|
||||
var rval = ({ SystemIdentifier: SystemIdentifier }/*:any*/);
|
||||
var rval = { SystemIdentifier: SystemIdentifier };
|
||||
for(var y in PSet0) rval[y] = PSet0[y];
|
||||
//rval.blob = blob;
|
||||
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);
|
||||
if(blob.l !== Offset1) throw "Length mismatch 2: " + blob.l + " !== " + Offset1;
|
||||
var PSet1;
|
||||
try { PSet1 = parse_PropertySet(blob, null); } catch(e) {/* empty */}
|
||||
try { PSet1 = parse_PropertySet(blob, null); } catch(e) { }
|
||||
for(y in PSet1) rval[y] = PSet1[y];
|
||||
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; }
|
||||
|
||||
function parslurp(blob, length, cb) {
|
||||
var arr = [], target = blob.l + length;
|
||||
@ -394,40 +278,39 @@ function parslurp(blob, length, cb) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
function parsebool(blob, length/*:number*/) { return blob.read_shift(length) === 0x1; }
|
||||
function writebool(v/*:any*/, o) { if(!o) o=new_buf(2); o.write_shift(2, +!!v); return o; }
|
||||
function parslurp2(blob, length, cb) {
|
||||
var arr = [], target = blob.l + length, len = blob.read_shift(2);
|
||||
while(len-- !== 0) arr.push(cb(blob, target - blob.l));
|
||||
if(target !== blob.l) throw new Error("Slurp error");
|
||||
return arr;
|
||||
}
|
||||
|
||||
function parseuint16(blob/*::, length:?number, opts:?any*/) { return blob.read_shift(2, 'u'); }
|
||||
function writeuint16(v/*:number*/, o) { if(!o) o=new_buf(2); o.write_shift(2, v); return o; }
|
||||
function parseuint16a(blob, length/*:: :?number, opts:?any*/) { return parslurp(blob,length,parseuint16);}
|
||||
function parsebool(blob, length) { return blob.read_shift(length) === 0x1; }
|
||||
|
||||
function parseuint16(blob) { return blob.read_shift(2, 'u'); }
|
||||
function parseuint16a(blob, length) { return parslurp(blob,length,parseuint16);}
|
||||
|
||||
/* --- 2.5 Structures --- */
|
||||
|
||||
/* [MS-XLS] 2.5.14 Boolean */
|
||||
var parse_Boolean = parsebool;
|
||||
|
||||
/* [MS-XLS] 2.5.10 Bes (boolean or error) */
|
||||
function parse_Bes(blob/*::, length*/) {
|
||||
function parse_Bes(blob) {
|
||||
var v = blob.read_shift(1), t = blob.read_shift(1);
|
||||
return t === 0x01 ? v : v === 0x01;
|
||||
}
|
||||
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));
|
||||
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 cch = blob.read_shift(1);
|
||||
var width = 1, encoding = 'sbcs-cont';
|
||||
var cp = current_codepage;
|
||||
if(opts && opts.biff >= 8) current_codepage = 1200;
|
||||
if(!opts || opts.biff == 8 ) {
|
||||
if(opts === undefined || opts.biff !== 5) {
|
||||
var fHighByte = blob.read_shift(1);
|
||||
if(fHighByte) { encoding = 'dbcs-cont'; }
|
||||
} else if(opts.biff == 12) {
|
||||
encoding = 'wstr';
|
||||
if(fHighByte) { width = 2; encoding = 'dbcs-cont'; }
|
||||
}
|
||||
if(opts.biff >= 2 && opts.biff <= 5) encoding = 'cpstr';
|
||||
var o = cch ? blob.read_shift(cch, encoding) : "";
|
||||
current_codepage = cp;
|
||||
return o;
|
||||
@ -438,13 +321,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 cRun, 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,29 +336,10 @@ 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 >= 12) return blob.read_shift(cch, 'dbcs-cont');
|
||||
}
|
||||
var fHighByte = blob.read_shift(1);
|
||||
if(fHighByte===0) { retval = blob.read_shift(cch, 'sbcs-cont'); }
|
||||
else { retval = blob.read_shift(cch, 'dbcs-cont'); }
|
||||
@ -484,37 +348,23 @@ function parse_XLUnicodeStringNoCch(blob, cch, opts) {
|
||||
|
||||
/* 2.5.294 XLUnicodeString */
|
||||
function parse_XLUnicodeString(blob, length, opts) {
|
||||
var cch = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
|
||||
var cch = blob.read_shift(opts !== undefined && opts.biff > 0 && opts.biff < 8 ? 1 : 2);
|
||||
if(cch === 0) { blob.l++; return ""; }
|
||||
return parse_XLUnicodeStringNoCch(blob, cch, opts);
|
||||
}
|
||||
/* BIFF5 override */
|
||||
function parse_XLUnicodeString2(blob, length, opts) {
|
||||
if(opts.biff > 5) return parse_XLUnicodeString(blob, length, opts);
|
||||
if(opts.biff !== 5 && opts.biff !== 2) 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');
|
||||
}
|
||||
/* TODO: BIFF5 and lower, codepage awareness */
|
||||
function write_XLUnicodeString(str, opts, o) {
|
||||
if(!o) o = new_buf(3 + 2 * str.length);
|
||||
o.write_shift(2, str.length);
|
||||
o.write_shift(1, 1);
|
||||
o.write_shift(31, str, 'utf16le');
|
||||
return o;
|
||||
return blob.read_shift(cch, 'sbcs-cont');
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.5.61 ControlInfo */
|
||||
function parse_ControlInfo(blob/*::, length, opts*/) {
|
||||
var flags = blob.read_shift(1);
|
||||
blob.l++;
|
||||
var accel = blob.read_shift(2);
|
||||
blob.l += 2;
|
||||
return [flags, accel];
|
||||
}
|
||||
var parse_ControlInfo = parsenoop;
|
||||
|
||||
/* [MS-OSHARED] 2.3.7.6 URLMoniker TODO: flags */
|
||||
function parse_URLMoniker(blob/*::, length, opts*/) {
|
||||
var parse_URLMoniker = function(blob, length) {
|
||||
var len = blob.read_shift(4), start = blob.l;
|
||||
var extra = false;
|
||||
if(len > 24) {
|
||||
@ -526,111 +376,63 @@ function parse_URLMoniker(blob/*::, length, opts*/) {
|
||||
var url = blob.read_shift((extra?len-24:len)>>1, 'utf16le').replace(chr0,"");
|
||||
if(extra) blob.l += 24;
|
||||
return url;
|
||||
}
|
||||
};
|
||||
|
||||
/* [MS-OSHARED] 2.3.7.8 FileMoniker TODO: all fields */
|
||||
function parse_FileMoniker(blob/*::, length*/) {
|
||||
var parse_FileMoniker = function(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 */
|
||||
function parse_HyperlinkMoniker(blob, length) {
|
||||
var parse_HyperlinkMoniker = function(blob, length) {
|
||||
var clsid = blob.read_shift(16); length -= 16;
|
||||
switch(clsid) {
|
||||
case "e0c9ea79f9bace118c8200aa004ba90b": return parse_URLMoniker(blob, length);
|
||||
case "0303000000000000c000000000000046": return parse_FileMoniker(blob, length);
|
||||
default: throw new Error("Unsupported Moniker " + clsid);
|
||||
default: throw "unsupported moniker " + clsid;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* [MS-OSHARED] 2.3.7.9 HyperlinkString */
|
||||
function parse_HyperlinkString(blob/*::, length*/) {
|
||||
var parse_HyperlinkString = function(blob, length) {
|
||||
var len = blob.read_shift(4);
|
||||
var o = len > 0 ? blob.read_shift(len, 'utf16le').replace(chr0, "") : "";
|
||||
var o = blob.read_shift(len, 'utf16le').replace(chr0, "");
|
||||
return o;
|
||||
}
|
||||
function write_HyperlinkString(str/*:string*/, o) {
|
||||
if(!o) o = new_buf(6 + str.length * 2);
|
||||
o.write_shift(4, 1 + str.length);
|
||||
for(var i = 0; i < str.length; ++i) o.write_shift(2, str.charCodeAt(i));
|
||||
o.write_shift(2, 0);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
/* [MS-OSHARED] 2.3.7.1 Hyperlink Object */
|
||||
function parse_Hyperlink(blob, length)/*:Hyperlink*/ {
|
||||
/* [MS-OSHARED] 2.3.7.1 Hyperlink Object TODO: unify params with XLSX */
|
||||
var parse_Hyperlink = function(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*/);
|
||||
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; }
|
||||
|
1314
bits/39_xlsbiff.js
1314
bits/39_xlsbiff.js
File diff suppressed because it is too large
Load Diff
1140
bits/40_harb.js
1140
bits/40_harb.js
File diff suppressed because it is too large
Load Diff
1182
bits/41_lotus.js
1182
bits/41_lotus.js
File diff suppressed because it is too large
Load Diff
@ -1,190 +1,157 @@
|
||||
/* 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 */
|
||||
};
|
||||
|
||||
/* 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 = /<r>/g, rend = /<\/r>/, nlregex = /\r\n/g;
|
||||
/* 18.4.7 rPr CT_RPrElt */
|
||||
var parse_rpr = function parse_rpr(rpr, intro, outro) {
|
||||
var font = {}, cp = 65001;
|
||||
var m = rpr.match(tagregex), i = 0;
|
||||
if(m) for(;i!=m.length; ++i) {
|
||||
var y = parsexmltag(m[i]);
|
||||
switch(y[0]) {
|
||||
/* 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':
|
||||
/* falls through */
|
||||
case '<shadow/>': break;
|
||||
|
||||
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.outline) style.push("text-effect: outline;");
|
||||
if(font.shadow) style.push("text-shadow: auto;");
|
||||
/* 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':
|
||||
/* falls through */
|
||||
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/>': font.strike = 1; break;
|
||||
case '</strike>': break;
|
||||
|
||||
/* 18.4.13 u CT_UnderlineProperty */
|
||||
case '<u':
|
||||
if(!y.val) break;
|
||||
/* falls through */
|
||||
case '<u/>': font.u = 1; break;
|
||||
case '</u>': break;
|
||||
|
||||
/* 18.8.2 b */
|
||||
case '<b':
|
||||
if(!y.val) break;
|
||||
/* falls through */
|
||||
case '<b/>': font.b = 1; break;
|
||||
case '</b>': break;
|
||||
|
||||
/* 18.8.26 i */
|
||||
case '<i':
|
||||
if(!y.val) break;
|
||||
/* falls through */
|
||||
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': break;
|
||||
|
||||
/* 18.8.35 scheme CT_FontScheme TODO */
|
||||
case '<scheme': break;
|
||||
|
||||
default:
|
||||
if(y[0].charCodeAt(1) !== 47) throw 'Unrecognized rich format ' + y[0];
|
||||
}
|
||||
}
|
||||
/* TODO: These should be generated styles, not inline */
|
||||
var style = [];
|
||||
if(font.b) style.push("font-weight: bold;");
|
||||
if(font.i) style.push("font-style: italic;");
|
||||
intro.push('<span style="' + style.join("") + '">');
|
||||
|
||||
if(font.b) { intro.push("<b>"); outro.push("</b>"); }
|
||||
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";
|
||||
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)) return "";
|
||||
terms[1] = t[1];
|
||||
|
||||
if(r.s) parse_rpr2(r.s, terms[0], terms[2]);
|
||||
var rpr = r.match(rpregex);
|
||||
if(isval(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 = /<t[^>]*>([^<]*)<\/t>/g, sirregex = /<r>/;
|
||||
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.r = utf8read(x);
|
||||
if(html) z.h = escapehtml(z.t);
|
||||
if(x.charCodeAt(1) === 116) {
|
||||
z.t = utf8read(unescapexml(x.substr(x.indexOf(">")+1).split(/<\/t>/)[0]));
|
||||
z.r = x;
|
||||
if(html) z.h = z.t;
|
||||
}
|
||||
/* 18.4.4 r CT_RElt (Rich Text Run) */
|
||||
else if((/*y = */x.match(sirregex))) {
|
||||
z.r = utf8read(x);
|
||||
z.t = unescapexml(utf8read((str_remove_xml_ns_g(x, "rPh").match(sitregex)||[]).join("").replace(tagregex,"")), true);
|
||||
if(html) z.h = rs_to_html(parse_rs(z.r));
|
||||
else if((y = x.match(sirregex))) {
|
||||
z.r = x;
|
||||
z.t = utf8read(unescapexml(x.match(sitregex).join("").replace(tagregex,"")));
|
||||
if(html) z.h = parse_rs(x);
|
||||
}
|
||||
/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
|
||||
/* 18.4.6 rPh CT_PhoneticRun (TODO: needed for Asian support) */
|
||||
@ -192,41 +159,40 @@ function parse_si(x, opts) {
|
||||
}
|
||||
|
||||
/* 18.4 Shared String Table */
|
||||
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;
|
||||
var sstr0 = /<sst([^>]*)>([\s\S]*)<\/sst>/;
|
||||
var sstr1 = /<(?:si|sstItem)>/g;
|
||||
var sstr2 = /<\/(?:si|sstItem)>/;
|
||||
function parse_sst_xml(data, opts) {
|
||||
var s = [], ss;
|
||||
/* 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)) {
|
||||
ss = sst[2].replace(sstr1,"").split(sstr2);
|
||||
for(var i = 0; i != ss.length; ++i) {
|
||||
var o = parse_si(ss[i].trim(), opts);
|
||||
var o = parse_si(ss[i], 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*/ {
|
||||
function write_sst_xml(sst, opts) {
|
||||
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
|
||||
}));
|
||||
for(var i = 0; i != sst.length; ++i) { if(sst[i] == null) continue;
|
||||
var s/*:XLString*/ = sst[i];
|
||||
var s = sst[i];
|
||||
var sitag = "<si>";
|
||||
if(s.r) sitag += s.r;
|
||||
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>";
|
||||
}
|
||||
|
@ -1,29 +1,21 @@
|
||||
/* [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)];
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.45 Shared Strings */
|
||||
function parse_sst_bin(data, opts)/*:SST*/ {
|
||||
var s/*:SST*/ = ([]/*:any*/);
|
||||
function parse_sst_bin(data, opts) {
|
||||
var s = [];
|
||||
var pass = false;
|
||||
recordhopper(data, function hopper_sst(val, R, RT) {
|
||||
switch(RT) {
|
||||
case 0x009F: /* BrtBeginSst */
|
||||
s.Count = val[0]; s.Unique = val[1]; break;
|
||||
case 0x0013: /* BrtSSTItem */
|
||||
s.push(val); break;
|
||||
case 0x00A0: /* BrtEndSst */
|
||||
return true;
|
||||
|
||||
case 0x0023: /* BrtFRTBegin */
|
||||
pass = true; break;
|
||||
case 0x0024: /* BrtFRTEnd */
|
||||
pass = false; break;
|
||||
|
||||
default:
|
||||
if(R.T){}
|
||||
if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
|
||||
switch(R.n) {
|
||||
case 'BrtBeginSst': s.Count = val[0]; s.Unique = val[1]; break;
|
||||
case 'BrtSSTItem': s.push(val); break;
|
||||
case 'BrtEndSst': return true;
|
||||
/* TODO: produce a test case with a future record */
|
||||
case 'BrtFRTBegin': pass = true; break;
|
||||
case 'BrtFRTEnd': pass = false; break;
|
||||
default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
|
||||
}
|
||||
});
|
||||
return s;
|
||||
@ -38,11 +30,10 @@ 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]));
|
||||
/* FRTSST */
|
||||
write_record(ba, 0x00A0 /* BrtEndSst */);
|
||||
write_record(ba, "BrtBeginSst", write_BrtBeginSst(sst));
|
||||
for(var i = 0; i < sst.length; ++i) write_record(ba, "BrtSSTItem", write_BrtSSTItem(sst[i]));
|
||||
write_record(ba, "BrtEndSst");
|
||||
return ba.end();
|
||||
}
|
||||
|
@ -1,176 +1,40 @@
|
||||
function _JS2ANSI(str/*:string*/)/*:Array<number>*/ {
|
||||
if(typeof $cptable !== 'undefined') return $cptable.utils.encode(current_ansi, str);
|
||||
var o/*:Array<number>*/ = [], oo = str.split("");
|
||||
for(var i = 0; i < oo.length; ++i) o[i] = oo[i].charCodeAt(0);
|
||||
return o;
|
||||
}
|
||||
function _JS2ANSI(str) { if(typeof cptable !== 'undefined') return cptable.utils.encode(1252, str); return str.split("").map(function(x) { return x.charCodeAt(0); }); }
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.1.4 Version */
|
||||
function parse_CRYPTOVersion(blob, length/*:?number*/) {
|
||||
var o/*:any*/ = {};
|
||||
function parse_Version(blob, length) {
|
||||
var o = {};
|
||||
o.Major = blob.read_shift(2);
|
||||
o.Minor = blob.read_shift(2);
|
||||
/*:: if(length == null) return o; */
|
||||
if(length >= 4) blob.l += length - 4;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.1.5 DataSpaceVersionInfo */
|
||||
function parse_DataSpaceVersionInfo(blob) {
|
||||
var o = {};
|
||||
o.id = blob.read_shift(0, 'lpp4');
|
||||
o.R = parse_CRYPTOVersion(blob, 4);
|
||||
o.U = parse_CRYPTOVersion(blob, 4);
|
||||
o.W = parse_CRYPTOVersion(blob, 4);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.1.6.1 DataSpaceMapEntry Structure */
|
||||
function parse_DataSpaceMapEntry(blob) {
|
||||
var len = blob.read_shift(4);
|
||||
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') });
|
||||
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) {
|
||||
var o = [];
|
||||
blob.l += 4; // must be 0x8
|
||||
var cnt = blob.read_shift(4);
|
||||
while(cnt-- > 0) o.push(parse_DataSpaceMapEntry(blob));
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.1.7 DataSpaceDefinition */
|
||||
function parse_DataSpaceDefinition(blob)/*:Array<string>*/ {
|
||||
var o/*:Array<string>*/ = [];
|
||||
blob.l += 4; // must be 0x8
|
||||
var cnt = blob.read_shift(4);
|
||||
while(cnt-- > 0) o.push(blob.read_shift(0, 'lpp4'));
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.1.8 DataSpaceDefinition */
|
||||
function parse_TransformInfoHeader(blob) {
|
||||
var o = {};
|
||||
/*var len = */blob.read_shift(4);
|
||||
blob.l += 4; // must be 0x1
|
||||
o.id = blob.read_shift(0, 'lpp4');
|
||||
o.name = blob.read_shift(0, 'lpp4');
|
||||
o.R = parse_CRYPTOVersion(blob, 4);
|
||||
o.U = parse_CRYPTOVersion(blob, 4);
|
||||
o.W = parse_CRYPTOVersion(blob, 4);
|
||||
return o;
|
||||
}
|
||||
|
||||
function parse_Primary(blob) {
|
||||
/* [MS-OFFCRYPTO] 2.2.6 IRMDSTransformInfo */
|
||||
var hdr = parse_TransformInfoHeader(blob);
|
||||
/* [MS-OFFCRYPTO] 2.1.9 EncryptionTransformInfo */
|
||||
hdr.ename = blob.read_shift(0, '8lpp4');
|
||||
hdr.blksz = blob.read_shift(4);
|
||||
hdr.cmode = blob.read_shift(4);
|
||||
if(blob.read_shift(4) != 0x04) throw new Error("Bad !Primary record");
|
||||
return hdr;
|
||||
}
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.3.2 Encryption Header */
|
||||
function parse_EncryptionHeader(blob, length/*:number*/) {
|
||||
var tgt = blob.l + length;
|
||||
function parse_EncryptionHeader(blob, length) {
|
||||
var o = {};
|
||||
o.Flags = (blob.read_shift(4) & 0x3F);
|
||||
blob.l += 4;
|
||||
o.Flags = blob.read_shift(4);
|
||||
|
||||
// Check if SizeExtra is 0x00000000
|
||||
var tmp = blob.read_shift(4);
|
||||
if(tmp !== 0) throw 'Unrecognized SizeExtra: ' + tmp;
|
||||
|
||||
o.AlgID = blob.read_shift(4);
|
||||
var valid = false;
|
||||
switch(o.AlgID) {
|
||||
case 0x660E: case 0x660F: case 0x6610: valid = (o.Flags == 0x24); break;
|
||||
case 0x6801: valid = (o.Flags == 0x04); break;
|
||||
case 0: valid = (o.Flags == 0x10 || o.Flags == 0x04 || o.Flags == 0x24); break;
|
||||
case 0: case 0x6801: case 0x660E: case 0x660F: case 0x6610: break;
|
||||
default: throw 'Unrecognized encryption algorithm: ' + o.AlgID;
|
||||
}
|
||||
if(!valid) throw new Error("Encryption Flags/AlgID mismatch");
|
||||
o.AlgIDHash = blob.read_shift(4);
|
||||
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');
|
||||
blob.l = tgt;
|
||||
parsenoop(blob, length-12);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.3.3 Encryption Verifier */
|
||||
function parse_EncryptionVerifier(blob, length/*:number*/) {
|
||||
var o = {}, tgt = blob.l + length;
|
||||
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;
|
||||
return o;
|
||||
function parse_EncryptionVerifier(blob, length) {
|
||||
return parsenoop(blob, length);
|
||||
}
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.3.4.* EncryptionInfo Stream */
|
||||
function parse_EncryptionInfo(blob) {
|
||||
var vers = parse_CRYPTOVersion(blob);
|
||||
switch(vers.Minor) {
|
||||
case 0x02: return [vers.Minor, parse_EncInfoStd(blob, vers)];
|
||||
case 0x03: return [vers.Minor, parse_EncInfoExt(blob, vers)];
|
||||
case 0x04: return [vers.Minor, parse_EncInfoAgl(blob, vers)];
|
||||
}
|
||||
throw new Error("ECMA-376 Encrypted file unrecognized Version: " + vers.Minor);
|
||||
}
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.3.4.5 EncryptionInfo Stream (Standard Encryption) */
|
||||
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 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"); }
|
||||
/* [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"];
|
||||
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;
|
||||
}
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.3.5.1 RC4 CryptoAPI Encryption Header */
|
||||
function parse_RC4CryptoHeader(blob, length/*:number*/) {
|
||||
function parse_RC4CryptoHeader(blob, length) {
|
||||
var o = {};
|
||||
var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4); length -= 4;
|
||||
if(vers.Minor != 2) throw new Error('unrecognized minor version code: ' + vers.Minor);
|
||||
if(vers.Major > 4 || vers.Major < 2) throw new Error('unrecognized major version code: ' + vers.Major);
|
||||
var vers = o.EncryptionVersionInfo = parse_Version(blob, 4); length -= 4;
|
||||
if(vers.Minor != 2) throw 'unrecognized minor version code: ' + vers.Minor;
|
||||
if(vers.Major > 4 || vers.Major < 2) throw 'unrecognized major version code: ' + vers.Major;
|
||||
o.Flags = blob.read_shift(4); length -= 4;
|
||||
var sz = blob.read_shift(4); length -= 4;
|
||||
o.EncryptionHeader = parse_EncryptionHeader(blob, sz); length -= sz;
|
||||
@ -178,9 +42,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) {
|
||||
var o = {};
|
||||
var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4);
|
||||
var vers = o.EncryptionVersionInfo = parse_Version(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);
|
||||
@ -189,7 +53,7 @@ function parse_RC4Header(blob/*::, length*/) {
|
||||
}
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.3.7.1 Binary Document Password Verifier Derivation */
|
||||
function crypto_CreatePasswordVerifier_Method1(Password/*:string*/) {
|
||||
function crypto_CreatePasswordVerifier_Method1(Password) {
|
||||
var Verifier = 0x0000, PasswordArray;
|
||||
var PasswordDecoded = _JS2ANSI(Password);
|
||||
var len = PasswordDecoded.length + 1, i, PasswordByte;
|
||||
@ -208,7 +72,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];
|
||||
@ -226,7 +90,7 @@ var crypto_CreateXorArray_Method1 = /*#__PURE__*/(function() {
|
||||
}
|
||||
return XorKey;
|
||||
};
|
||||
return function(password/*:string*/) {
|
||||
return function(password) {
|
||||
var Password = _JS2ANSI(password);
|
||||
var XorKey = CreateXorKey_Method1(Password);
|
||||
var Index = Password.length;
|
||||
@ -266,7 +130,7 @@ var crypto_CreateXorArray_Method1 = /*#__PURE__*/(function() {
|
||||
})();
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.3.7.3 Binary Document XOR Data Transformation Method 1 */
|
||||
var crypto_DecryptData_Method1 = function(password/*:string*/, Data, XorArrayIndex, XorArray, O) {
|
||||
var crypto_DecryptData_Method1 = function(password, Data, XorArrayIndex, XorArray, O) {
|
||||
/* If XorArray is set, use it; if O is not set, make changes in-place */
|
||||
if(!O) O = Data;
|
||||
if(!XorArray) XorArray = crypto_CreateXorArray_Method1(password);
|
||||
@ -281,10 +145,10 @@ var crypto_DecryptData_Method1 = function(password/*:string*/, Data, XorArrayInd
|
||||
return [O, XorArrayIndex, XorArray];
|
||||
};
|
||||
|
||||
var crypto_MakeXorDecryptor = function(password/*:string*/) {
|
||||
var crypto_MakeXorDecryptor = function(password) {
|
||||
var XorArrayIndex = 0, XorArray = crypto_CreateXorArray_Method1(password);
|
||||
return function(Data) {
|
||||
var O = crypto_DecryptData_Method1("", Data, XorArrayIndex, XorArray);
|
||||
var O = crypto_DecryptData_Method1(null, Data, XorArrayIndex, XorArray);
|
||||
XorArrayIndex = O[1];
|
||||
return O[0];
|
||||
};
|
||||
@ -292,24 +156,24 @@ var crypto_MakeXorDecryptor = function(password/*:string*/) {
|
||||
|
||||
/* 2.5.343 */
|
||||
function parse_XORObfuscation(blob, length, opts, out) {
|
||||
var o = ({ key: parseuint16(blob), verificationBytes: parseuint16(blob) }/*:any*/);
|
||||
var o = { key: parseuint16(blob), verificationBytes: parseuint16(blob) };
|
||||
if(opts.password) o.verifier = crypto_CreatePasswordVerifier_Method1(opts.password);
|
||||
out.valid = o.verificationBytes === o.verifier;
|
||||
if(out.valid) out.insitu = crypto_MakeXorDecryptor(opts.password);
|
||||
if(out.valid) out.insitu_decrypt = crypto_MakeXorDecryptor(opts.password);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.4.117 */
|
||||
function parse_FilePassHeader(blob, length/*:number*/, oo) {
|
||||
function parse_FilePassHeader(blob, length, oo) {
|
||||
var o = oo || {}; o.Info = blob.read_shift(2); blob.l -= 2;
|
||||
if(o.Info === 1) o.Data = parse_RC4Header(blob, length);
|
||||
else o.Data = parse_RC4CryptoHeader(blob, length);
|
||||
return o;
|
||||
}
|
||||
function parse_FilePass(blob, length/*:number*/, opts) {
|
||||
var o = ({ Type: opts.biff >= 8 ? blob.read_shift(2) : 0 }/*:any*/); /* wEncryptionType */
|
||||
function parse_FilePass(blob, length, opts) {
|
||||
var o = { Type: blob.read_shift(2) }; /* 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;
|
||||
}
|
||||
|
||||
|
107
bits/45_rtf.js
107
bits/45_rtf.js
@ -1,107 +0,0 @@
|
||||
function rtf_to_sheet(d, opts) {
|
||||
switch (opts.type) {
|
||||
case "base64":
|
||||
return rtf_to_sheet_str(Base64_decode(d), opts);
|
||||
case "binary":
|
||||
return rtf_to_sheet_str(d, opts);
|
||||
case "buffer":
|
||||
return rtf_to_sheet_str(has_buf && Buffer.isBuffer(d) ? d.toString("binary") : a2s(d), opts);
|
||||
case "array":
|
||||
return rtf_to_sheet_str(cc2str(d), opts);
|
||||
}
|
||||
throw new Error("Unrecognized type " + opts.type);
|
||||
}
|
||||
function rtf_to_sheet_str(str, opts) {
|
||||
var o = opts || {};
|
||||
var ws = {};
|
||||
var dense = o.dense;
|
||||
if (dense)
|
||||
ws["!data"] = [];
|
||||
var rows = str_match_ng(str, "\\trowd", "\\row");
|
||||
if (!rows)
|
||||
throw new Error("RTF missing table");
|
||||
var range = { s: { c: 0, r: 0 }, e: { c: 0, r: rows.length - 1 } };
|
||||
var row = [];
|
||||
rows.forEach(function(rowtf, R) {
|
||||
if (dense)
|
||||
row = ws["!data"][R] = [];
|
||||
var rtfre = /\\[\w\-]+\b/g;
|
||||
var last_index = 0;
|
||||
var res;
|
||||
var C = -1;
|
||||
var payload = [];
|
||||
while ((res = rtfre.exec(rowtf)) != null) {
|
||||
var data = rowtf.slice(last_index, rtfre.lastIndex - res[0].length);
|
||||
if (data.charCodeAt(0) == 32)
|
||||
data = data.slice(1);
|
||||
if (data.length)
|
||||
payload.push(data);
|
||||
switch (res[0]) {
|
||||
case "\\cell":
|
||||
++C;
|
||||
if (payload.length) {
|
||||
var cell = { v: payload.join(""), t: "s" };
|
||||
if (cell.v == "TRUE" || cell.v == "FALSE") {
|
||||
cell.v = cell.v == "TRUE";
|
||||
cell.t = "b";
|
||||
} else if (!isNaN(fuzzynum(cell.v))) {
|
||||
cell.t = "n";
|
||||
if (o.cellText !== false)
|
||||
cell.w = cell.v;
|
||||
cell.v = fuzzynum(cell.v);
|
||||
} else if (RBErr[cell.v] != null) {
|
||||
cell.t = "e";
|
||||
cell.w = cell.v;
|
||||
cell.v = RBErr[cell.v];
|
||||
}
|
||||
if (dense)
|
||||
row[C] = cell;
|
||||
else
|
||||
ws[encode_cell({ r: R, c: C })] = cell;
|
||||
}
|
||||
payload = [];
|
||||
break;
|
||||
case "\\par":
|
||||
payload.push("\n");
|
||||
break;
|
||||
}
|
||||
last_index = rtfre.lastIndex;
|
||||
}
|
||||
if (C > range.e.c)
|
||||
range.e.c = C;
|
||||
});
|
||||
ws["!ref"] = encode_range(range);
|
||||
return ws;
|
||||
}
|
||||
function rtf_to_workbook(d, opts) {
|
||||
var wb = sheet_to_workbook(rtf_to_sheet(d, opts), opts);
|
||||
wb.bookType = "rtf";
|
||||
return wb;
|
||||
}
|
||||
function sheet_to_rtf(ws, opts) {
|
||||
var o = ["{\\rtf1\\ansi"];
|
||||
if (!ws["!ref"])
|
||||
return o[0] + "}";
|
||||
var r = safe_decode_range(ws["!ref"]), cell;
|
||||
var dense = ws["!data"] != null, row = [];
|
||||
for (var R = r.s.r; R <= r.e.r; ++R) {
|
||||
o.push("\\trowd\\trautofit1");
|
||||
for (var C = r.s.c; C <= r.e.c; ++C)
|
||||
o.push("\\cellx" + (C + 1));
|
||||
o.push("\\pard\\intbl");
|
||||
if (dense)
|
||||
row = ws["!data"][R] || [];
|
||||
for (C = r.s.c; C <= r.e.c; ++C) {
|
||||
var coord = encode_cell({ r: R, c: C });
|
||||
cell = dense ? row[C] : ws[coord];
|
||||
if (!cell || cell.v == null && (!cell.f || cell.F)) {
|
||||
o.push(" \\cell");
|
||||
continue;
|
||||
}
|
||||
o.push(" " + (cell.w || (format_cell(cell), cell.w) || "").replace(/[\r\n]/g, "\\par "));
|
||||
o.push("\\cell");
|
||||
}
|
||||
o.push("\\pard\\intbl\\row");
|
||||
}
|
||||
return o.join("") + "}";
|
||||
}
|
85
bits/45_styutils.js
Normal file
85
bits/45_styutils.js
Normal file
@ -0,0 +1,85 @@
|
||||
function hex2RGB(h) {
|
||||
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().substr(1);
|
||||
}
|
||||
|
||||
function rgb2HSL(rgb) {
|
||||
var R = rgb[0]/255, G = rgb[1]/255, B=rgb[2]/255;
|
||||
var M = Math.max(R, G, B), m = Math.min(R, G, B), C = M - m;
|
||||
if(C === 0) return [0, 0, R];
|
||||
|
||||
var H6 = 0, S = 0, L2 = (M + m);
|
||||
S = C / (L2 > 1 ? 2 - L2 : L2);
|
||||
switch(M){
|
||||
case R: H6 = ((G - B) / C + 6)%6; break;
|
||||
case G: H6 = ((B - R) / C + 2); break;
|
||||
case B: H6 = ((R - G) / C + 4); break;
|
||||
}
|
||||
return [H6 / 6, S, L2 / 2];
|
||||
}
|
||||
|
||||
function hsl2RGB(hsl){
|
||||
var H = hsl[0], S = hsl[1], L = hsl[2];
|
||||
var C = S * 2 * (L < 0.5 ? L : 1 - L), m = L - C/2;
|
||||
var rgb = [m,m,m], h6 = 6*H;
|
||||
|
||||
var X;
|
||||
if(S !== 0) switch(h6|0) {
|
||||
case 0: case 6: X = C * h6; rgb[0] += C; rgb[1] += X; break;
|
||||
case 1: X = C * (2 - h6); rgb[0] += X; rgb[1] += C; break;
|
||||
case 2: X = C * (h6 - 2); rgb[1] += C; rgb[2] += X; break;
|
||||
case 3: X = C * (4 - h6); rgb[1] += X; rgb[2] += C; break;
|
||||
case 4: X = C * (h6 - 4); rgb[2] += C; rgb[0] += X; break;
|
||||
case 5: X = C * (6 - h6); rgb[2] += X; rgb[0] += C; break;
|
||||
}
|
||||
for(var i = 0; i != 3; ++i) rgb[i] = Math.round(rgb[i]*255);
|
||||
return rgb;
|
||||
}
|
||||
|
||||
/* 18.8.3 bgColor tint algorithm */
|
||||
function rgb_tint(hex, tint) {
|
||||
if(tint == 0) return hex;
|
||||
var hsl = rgb2HSL(hex2RGB(hex));
|
||||
if (tint < 0) hsl[2] = hsl[2] * (1 + tint);
|
||||
else hsl[2] = 1 - (1 - hsl[2]) * (1 - tint);
|
||||
var rev =rgb2Hex(hsl2RGB(hsl))
|
||||
return rev;
|
||||
}
|
||||
|
||||
/* 18.3.1.13 width calculations */
|
||||
var DEF_MDW = 7, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
|
||||
function width2px(width) { return (( width + ((128/MDW)|0)/256 )* MDW )|0; }
|
||||
function px2char(px) { return (((px - 5)/MDW * 100 + 0.5)|0)/100; }
|
||||
function char2width(chr) { return (((chr * MDW + 5)/MDW*256)|0)/256; }
|
||||
function cycle_width(collw) { return char2width(px2char(width2px(collw))); }
|
||||
function find_mdw(collw, coll) {
|
||||
if(cycle_width(collw) != collw) {
|
||||
for(MDW=DEF_MDW; MDW>MIN_MDW; --MDW) if(cycle_width(collw) === collw) break;
|
||||
if(MDW === MIN_MDW) for(MDW=DEF_MDW+1; MDW<MAX_MDW; ++MDW) if(cycle_width(collw) === collw) break;
|
||||
if(MDW === MAX_MDW) MDW = DEF_MDW;
|
||||
}
|
||||
}
|
||||
|
||||
/* [MS-EXSPXML3] 2.4.54 ST_enmPattern */
|
||||
var XLMLPatternTypeMap = {
|
||||
"None": "none",
|
||||
"Solid": "solid",
|
||||
"Gray50": "mediumGray",
|
||||
"Gray75": "darkGray",
|
||||
"Gray25": "lightGray",
|
||||
"HorzStripe": "darkHorizontal",
|
||||
"VertStripe": "darkVertical",
|
||||
"ReverseDiagStripe": "darkDown",
|
||||
"DiagStripe": "darkUp",
|
||||
"DiagCross": "darkGrid",
|
||||
"ThickDiagCross": "darkTrellis",
|
||||
"ThinHorzStripe": "lightHorizontal",
|
||||
"ThinVertStripe": "lightVertical",
|
||||
"ThinReverseDiagStripe": "lightDown",
|
||||
"ThinHorzCross": "lightGrid"
|
||||
};
|
||||
|
@ -1,118 +1,4 @@
|
||||
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)];
|
||||
}
|
||||
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);
|
||||
}
|
||||
var styles = {}; // shared styles
|
||||
|
||||
function rgb2HSL(rgb) {
|
||||
var R = rgb[0]/255, G = rgb[1]/255, B=rgb[2]/255;
|
||||
var M = Math.max(R, G, B), m = Math.min(R, G, B), C = M - m;
|
||||
if(C === 0) return [0, 0, R];
|
||||
|
||||
var H6 = 0, S = 0, L2 = (M + m);
|
||||
S = C / (L2 > 1 ? 2 - L2 : L2);
|
||||
switch(M){
|
||||
case R: H6 = ((G - B) / C + 6)%6; break;
|
||||
case G: H6 = ((B - R) / C + 2); break;
|
||||
case B: H6 = ((R - G) / C + 4); break;
|
||||
}
|
||||
return [H6 / 6, S, L2 / 2];
|
||||
}
|
||||
|
||||
function hsl2RGB(hsl){
|
||||
var H = hsl[0], S = hsl[1], L = hsl[2];
|
||||
var C = S * 2 * (L < 0.5 ? L : 1 - L), m = L - C/2;
|
||||
var rgb = [m,m,m], h6 = 6*H;
|
||||
|
||||
var X;
|
||||
if(S !== 0) switch(h6|0) {
|
||||
case 0: case 6: X = C * h6; rgb[0] += C; rgb[1] += X; break;
|
||||
case 1: X = C * (2 - h6); rgb[0] += X; rgb[1] += C; break;
|
||||
case 2: X = C * (h6 - 2); rgb[1] += C; rgb[2] += X; break;
|
||||
case 3: X = C * (4 - h6); rgb[1] += X; rgb[2] += C; break;
|
||||
case 4: X = C * (h6 - 4); rgb[2] += C; rgb[0] += X; break;
|
||||
case 5: X = C * (6 - h6); rgb[2] += X; rgb[0] += C; break;
|
||||
}
|
||||
for(var i = 0; i != 3; ++i) rgb[i] = Math.round(rgb[i]*255);
|
||||
return rgb;
|
||||
}
|
||||
|
||||
/* 18.8.3 bgColor tint algorithm */
|
||||
function rgb_tint(hex, tint) {
|
||||
if(tint === 0) return hex;
|
||||
var hsl = rgb2HSL(hex2RGB(hex));
|
||||
if (tint < 0) hsl[2] = hsl[2] * (1 + tint);
|
||||
else hsl[2] = 1 - (1 - hsl[2]) * (1 - tint);
|
||||
return rgb2Hex(hsl2RGB(hsl));
|
||||
}
|
||||
|
||||
/* 18.3.1.13 width calculations */
|
||||
/* [MS-OI29500] 2.1.595 Column Width & Formatting */
|
||||
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 cycle_width(collw) { return char2width(px2char(width2px(collw))); }
|
||||
/* XLSX/XLSB/XLS specify width in units of MDW */
|
||||
function find_mdw_colw(collw) {
|
||||
var delta = Math.abs(collw - cycle_width(collw)), _MDW = MDW;
|
||||
if(delta > 0.005) for(MDW=MIN_MDW; MDW<MAX_MDW; ++MDW) if(Math.abs(collw - cycle_width(collw)) <= delta) { delta = Math.abs(collw - cycle_width(collw)); _MDW = MDW; }
|
||||
MDW = _MDW;
|
||||
}
|
||||
/* XLML specifies width in terms of pixels */
|
||||
/*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;
|
||||
guess = (guess) % 1;
|
||||
if(guess > 0.5) guess--;
|
||||
if(Math.abs(guess) < delta) { delta = Math.abs(guess); _MDW = MDW; }
|
||||
}
|
||||
MDW = _MDW;
|
||||
}*/
|
||||
|
||||
function process_col(coll/*:ColInfo*/) {
|
||||
if(coll.width) {
|
||||
coll.wpx = width2px(coll.width);
|
||||
coll.wch = px2char(coll.wpx);
|
||||
coll.MDW = MDW;
|
||||
} else if(coll.wpx) {
|
||||
coll.wch = px2char(coll.wpx);
|
||||
coll.width = char2width(coll.wch);
|
||||
coll.MDW = MDW;
|
||||
} else if(typeof coll.wch == 'number') {
|
||||
coll.width = char2width(coll.wch);
|
||||
coll.wpx = width2px(coll.width);
|
||||
coll.MDW = MDW;
|
||||
}
|
||||
if(coll.customWidth) delete coll.customWidth;
|
||||
}
|
||||
|
||||
var DEF_PPI = 96, PPI = DEF_PPI;
|
||||
function px2pt(px) { return px * 96 / PPI; }
|
||||
function pt2px(pt) { return pt * PPI / 96; }
|
||||
|
||||
/* [MS-EXSPXML3] 2.4.54 ST_enmPattern */
|
||||
var XLMLPatternTypeMap = {
|
||||
"None": "none",
|
||||
"Solid": "solid",
|
||||
"Gray50": "mediumGray",
|
||||
"Gray75": "darkGray",
|
||||
"Gray25": "lightGray",
|
||||
"HorzStripe": "darkHorizontal",
|
||||
"VertStripe": "darkVertical",
|
||||
"ReverseDiagStripe": "darkDown",
|
||||
"DiagStripe": "darkUp",
|
||||
"DiagCross": "darkGrid",
|
||||
"ThickDiagCross": "darkTrellis",
|
||||
"ThinHorzStripe": "lightHorizontal",
|
||||
"ThinVertStripe": "lightVertical",
|
||||
"ThinReverseDiagStripe": "lightDown",
|
||||
"ThinHorzCross": "lightGrid"
|
||||
};
|
||||
var themes = {}; // shared themes
|
||||
|
||||
|
@ -1,434 +1,400 @@
|
||||
/* 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 y = parsexmltag(x);
|
||||
switch(strip_ns(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);
|
||||
styles.Borders.push(border);
|
||||
break;
|
||||
case '</border>': break;
|
||||
|
||||
/* note: not in spec, appears to be CT_BorderPr */
|
||||
case '<left/>': break;
|
||||
case '<left': case '<left>': break;
|
||||
case '</left>': break;
|
||||
|
||||
/* note: not in spec, appears to be CT_BorderPr */
|
||||
case '<right/>': break;
|
||||
case '<right': case '<right>': break;
|
||||
case '</right>': break;
|
||||
|
||||
/* 18.8.43 top CT_BorderPr */
|
||||
case '<top/>': break;
|
||||
case '<top': case '<top>': break;
|
||||
case '</top>': break;
|
||||
|
||||
/* 18.8.6 bottom CT_BorderPr */
|
||||
case '<bottom/>': break;
|
||||
case '<bottom': case '<bottom>': break;
|
||||
case '</bottom>': break;
|
||||
|
||||
/* 18.8.13 diagonal CT_BorderPr */
|
||||
case '<diagonal': case '<diagonal>': case '<diagonal/>': break;
|
||||
case '</diagonal>': break;
|
||||
|
||||
/* 18.8.25 horizontal CT_BorderPr */
|
||||
case '<horizontal': case '<horizontal>': case '<horizontal/>': break;
|
||||
case '</horizontal>': break;
|
||||
|
||||
/* 18.8.44 vertical CT_BorderPr */
|
||||
case '<vertical': case '<vertical>': case '<vertical/>': break;
|
||||
case '</vertical>': break;
|
||||
|
||||
/* 18.8.37 start CT_BorderPr */
|
||||
case '<start': case '<start>': case '<start/>': break;
|
||||
case '</start>': break;
|
||||
|
||||
/* 18.8.16 end CT_BorderPr */
|
||||
case '<end': case '<end>': case '<end/>': break;
|
||||
case '</end>': break;
|
||||
|
||||
/* 18.8.? color CT_Color */
|
||||
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');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* 18.8.21 fills CT_Fills */
|
||||
function parse_fills(t, styles, themes, opts) {
|
||||
styles.Fills = [];
|
||||
var fill = {};
|
||||
var pass = false;
|
||||
(t.match(tagregex)||[]).forEach(function(x) {
|
||||
var y = parsexmltag(x);
|
||||
switch(strip_ns(y[0])) {
|
||||
case '<fills': case '<fills>': case '</fills>': break;
|
||||
function parse_fills(t, opts) {
|
||||
styles.Fills = [];
|
||||
var fill = {};
|
||||
t[0].match(tagregex).forEach(function (x) {
|
||||
var y = parsexmltag(x);
|
||||
switch (y[0]) {
|
||||
case '<fills':
|
||||
case '<fills>':
|
||||
case '</fills>':
|
||||
break;
|
||||
|
||||
/* 18.8.20 fill CT_Fill */
|
||||
case '<fill>': case '<fill': case '<fill/>':
|
||||
fill = {}; styles.Fills.push(fill); break;
|
||||
case '</fill>': break;
|
||||
/* 18.8.20 fill CT_Fill */
|
||||
case '<fill>':
|
||||
break;
|
||||
case '</fill>':
|
||||
styles.Fills.push(fill);
|
||||
fill = {};
|
||||
break;
|
||||
|
||||
/* 18.8.24 gradientFill CT_GradientFill */
|
||||
case '<gradientFill>': break;
|
||||
case '<gradientFill':
|
||||
case '</gradientFill>': styles.Fills.push(fill); fill = {}; break;
|
||||
/* 18.8.32 patternFill CT_PatternFill */
|
||||
case '<patternFill':
|
||||
if (y.patternType) fill.patternType = y.patternType;
|
||||
break;
|
||||
case '<patternFill/>':
|
||||
case '</patternFill>':
|
||||
break;
|
||||
|
||||
/* 18.8.32 patternFill CT_PatternFill */
|
||||
case '<patternFill': case '<patternFill>':
|
||||
if(y.patternType) fill.patternType = y.patternType;
|
||||
break;
|
||||
case '<patternFill/>': case '</patternFill>': break;
|
||||
/* 18.8.3 bgColor CT_Color */
|
||||
case '<bgColor':
|
||||
if (!fill.bgColor) fill.bgColor = {};
|
||||
if (y.indexed) fill.bgColor.indexed = parseInt(y.indexed, 10);
|
||||
if (y.theme) fill.bgColor.theme = parseInt(y.theme, 10);
|
||||
if (y.tint) fill.bgColor.tint = parseFloat(y.tint);
|
||||
|
||||
/* 18.8.3 bgColor CT_Color */
|
||||
case '<bgColor':
|
||||
if(!fill.bgColor) fill.bgColor = {};
|
||||
if(y.indexed) fill.bgColor.indexed = parseInt(y.indexed, 10);
|
||||
if(y.theme) fill.bgColor.theme = parseInt(y.theme, 10);
|
||||
if(y.tint) fill.bgColor.tint = parseFloat(y.tint);
|
||||
/* Excel uses ARGB strings */
|
||||
if(y.rgb) fill.bgColor.rgb = y.rgb.slice(-6);
|
||||
break;
|
||||
case '<bgColor/>': case '</bgColor>': break;
|
||||
|
||||
/* 18.8.19 fgColor CT_Color */
|
||||
case '<fgColor':
|
||||
if(!fill.fgColor) fill.fgColor = {};
|
||||
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);
|
||||
break;
|
||||
case '<fgColor/>': case '</fgColor>': break;
|
||||
if (y.theme && themes.themeElements && themes.themeElements.clrScheme) {
|
||||
fill.bgColor.rgb = rgb_tint(themes.themeElements.clrScheme[fill.bgColor.theme].rgb, fill.bgColor.tint || 0);
|
||||
if (opts.WTF) fill.bgColor.raw_rgb = rgb_tint(themes.themeElements.clrScheme[fill.bgColor.theme].rgb,0);
|
||||
}
|
||||
/* Excel uses ARGB strings */
|
||||
if (y.rgb) fill.bgColor.rgb = y.rgb;//.substring(y.rgb.length - 6);
|
||||
break;
|
||||
case '<bgColor/>':
|
||||
case '</bgColor>':
|
||||
break;
|
||||
|
||||
/* 18.8.38 stop CT_GradientStop */
|
||||
case '<stop': case '<stop/>': break;
|
||||
case '</stop>': break;
|
||||
/* 18.8.19 fgColor CT_Color */
|
||||
case '<fgColor':
|
||||
if (!fill.fgColor) fill.fgColor = {};
|
||||
if (y.theme) fill.fgColor.theme = parseInt(y.theme, 10);
|
||||
if (y.tint) fill.fgColor.tint = parseFloat(y.tint);
|
||||
|
||||
/* 18.8.? color CT_Color */
|
||||
case '<color': case '<color/>': break;
|
||||
case '</color>': break;
|
||||
if (y.theme && themes.themeElements && themes.themeElements.clrScheme) {
|
||||
fill.fgColor.rgb = rgb_tint(themes.themeElements.clrScheme[fill.fgColor.theme].rgb, fill.fgColor.tint || 0);
|
||||
if (opts.WTF) fill.fgColor.raw_rgb = rgb_tint(themes.themeElements.clrScheme[fill.fgColor.theme].rgb,0);
|
||||
}
|
||||
|
||||
/* 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');
|
||||
}
|
||||
}
|
||||
});
|
||||
/* Excel uses ARGB strings */
|
||||
if (y.rgb) fill.fgColor.rgb = y.rgb;//.substring(y.rgb.length - 6);
|
||||
break;
|
||||
case '<fgColor/>':
|
||||
case '</fgColor>':
|
||||
break;
|
||||
|
||||
default:
|
||||
if (opts.WTF) throw 'unrecognized ' + y[0] + ' in fills';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* 18.8.23 fonts CT_Fonts */
|
||||
function parse_fonts(t, styles, themes, opts) {
|
||||
styles.Fonts = [];
|
||||
var font = {};
|
||||
var pass = false;
|
||||
(t.match(tagregex)||[]).forEach(function(x) {
|
||||
var y = parsexmltag(x);
|
||||
switch(strip_ns(y[0])) {
|
||||
case '<fonts': case '<fonts>': case '</fonts>': break;
|
||||
function parse_fonts(t, opts) {
|
||||
styles.Fonts = [];
|
||||
var font = {};
|
||||
t[0].match(tagregex).forEach(function (x) {
|
||||
var y = parsexmltag(x);
|
||||
switch (y[0]) {
|
||||
|
||||
/* 18.8.22 font CT_Font */
|
||||
case '<font': case '<font>': break;
|
||||
case '</font>': case '<font/>':
|
||||
styles.Fonts.push(font);
|
||||
font = {};
|
||||
break;
|
||||
case '<fonts':
|
||||
case '<fonts>':
|
||||
case '</fonts>':
|
||||
break;
|
||||
case '<font':
|
||||
break;
|
||||
case '</font>':
|
||||
styles.Fonts.push(font);
|
||||
;
|
||||
font = {};
|
||||
break;
|
||||
|
||||
/* 18.8.29 name CT_FontName */
|
||||
case '<name': if(y.val) font.name = utf8read(y.val); break;
|
||||
case '<name/>': case '</name>': break;
|
||||
case '<name':
|
||||
if (y.val) font.name = y.val;
|
||||
break;
|
||||
case '<name/>':
|
||||
case '</name>':
|
||||
break;
|
||||
|
||||
/* 18.8.2 b CT_BooleanProperty */
|
||||
case '<b': font.bold = y.val ? parsexmlbool(y.val) : 1; break;
|
||||
case '<b/>': font.bold = 1; break;
|
||||
case '</b>': case '</b': break;
|
||||
|
||||
/* 18.8.26 i CT_BooleanProperty */
|
||||
case '<i': font.italic = y.val ? parsexmlbool(y.val) : 1; break;
|
||||
case '<i/>': font.italic = 1; break;
|
||||
case '</i>': case '</i': break;
|
||||
case '<b/>':
|
||||
font.bold = true;
|
||||
break;
|
||||
case '<u/>':
|
||||
font.underline = true;
|
||||
break;
|
||||
case '<i/>':
|
||||
font.italic = true;
|
||||
break;
|
||||
case '<strike/>':
|
||||
font.strike = true;
|
||||
break;
|
||||
case '<outline/>':
|
||||
font.outline = true;
|
||||
break;
|
||||
case '<shadow/>':
|
||||
font.shadow = true;
|
||||
break;
|
||||
|
||||
/* 18.4.13 u CT_UnderlineProperty */
|
||||
case '<u':
|
||||
switch(y.val) {
|
||||
case "none": font.underline = 0x00; break;
|
||||
case "single": font.underline = 0x01; break;
|
||||
case "double": font.underline = 0x02; break;
|
||||
case "singleAccounting": font.underline = 0x21; break;
|
||||
case "doubleAccounting": font.underline = 0x22; break;
|
||||
} break;
|
||||
case '<u/>': font.underline = 1; break;
|
||||
case '</u>': case '</u': break;
|
||||
|
||||
/* 18.4.10 strike CT_BooleanProperty */
|
||||
case '<strike': font.strike = y.val ? parsexmlbool(y.val) : 1; break;
|
||||
case '<strike/>': font.strike = 1; break;
|
||||
case '</strike>': case '</strike': break;
|
||||
case '<sz':
|
||||
if (y.val) font.sz = y.val;
|
||||
break;
|
||||
case '<sz/>':
|
||||
case '</sz>':
|
||||
break;
|
||||
|
||||
/* 18.4.2 outline CT_BooleanProperty */
|
||||
case '<outline': font.outline = y.val ? parsexmlbool(y.val) : 1; break;
|
||||
case '<outline/>': font.outline = 1; break;
|
||||
case '</outline>': case '</outline': break;
|
||||
case '<vertAlign':
|
||||
if (y.val) font.vertAlign = y.val;
|
||||
break;
|
||||
case '<vertAlign/>':
|
||||
case '</vertAlign>':
|
||||
break;
|
||||
|
||||
/* 18.8.36 shadow CT_BooleanProperty */
|
||||
case '<shadow': font.shadow = y.val ? parsexmlbool(y.val) : 1; break;
|
||||
case '<shadow/>': font.shadow = 1; break;
|
||||
case '</shadow>': case '</shadow': break;
|
||||
|
||||
/* 18.8.12 condense CT_BooleanProperty */
|
||||
case '<condense': font.condense = y.val ? parsexmlbool(y.val) : 1; break;
|
||||
case '<condense/>': font.condense = 1; break;
|
||||
case '</condense>': case '</condense': break;
|
||||
case '<color':
|
||||
if (!font.color) font.color = {};
|
||||
if (y.theme) font.color.theme = y.theme;
|
||||
if (y.tint) font.color.tint = y.tint;
|
||||
if (y.theme && themes.themeElements && themes.themeElements.clrScheme) {
|
||||
font.color.rgb = rgb_tint(themes.themeElements.clrScheme[font.color.theme].rgb, font.color.tint || 0);
|
||||
}
|
||||
if (y.rgb) font.color.rgb = y.rgb;
|
||||
break;
|
||||
case '<color/>':
|
||||
case '</color>':
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* 18.8.17 extend CT_BooleanProperty */
|
||||
case '<extend': font.extend = y.val ? parsexmlbool(y.val) : 1; break;
|
||||
case '<extend/>': font.extend = 1; break;
|
||||
case '</extend>': case '</extend': break;
|
||||
function parse_borders(t, opts) {
|
||||
styles.Borders = [];
|
||||
var border = {}, sub_border = {};
|
||||
t[0].match(tagregex).forEach(function (x) {
|
||||
var y = parsexmltag(x);
|
||||
switch (y[0]) {
|
||||
case '<borders':
|
||||
case '<borders>':
|
||||
case '</borders>':
|
||||
break;
|
||||
case '<border':
|
||||
case '<border>':
|
||||
border = {};
|
||||
if (y.diagonalUp) { border.diagonalUp = y.diagonalUp; }
|
||||
if (y.diagonalDown) { border.diagonalDown = y.diagonalDown; }
|
||||
styles.Borders.push(border);
|
||||
|
||||
/* 18.4.11 sz CT_FontSize */
|
||||
case '<sz': if(y.val) font.sz = +y.val; break;
|
||||
case '<sz/>': case '</sz>': case '</sz': break;
|
||||
break;
|
||||
break;
|
||||
case '</border>':
|
||||
break;
|
||||
|
||||
/* 18.4.14 vertAlign CT_VerticalAlignFontProperty */
|
||||
case '<vertAlign': if(y.val) font.vertAlign = y.val; break;
|
||||
case '<vertAlign/>': case '</vertAlign>': case '</vertAlign': break;
|
||||
case '<left':
|
||||
sub_border = border.left = {};
|
||||
if (y.style) {
|
||||
sub_border.style = y.style;
|
||||
}
|
||||
break;
|
||||
case '<right':
|
||||
sub_border = border.right = {};
|
||||
if (y.style) {
|
||||
sub_border.style = y.style;
|
||||
}
|
||||
break;
|
||||
case '<top':
|
||||
sub_border = border.top = {};
|
||||
if (y.style) {
|
||||
sub_border.style = y.style;
|
||||
}
|
||||
break;
|
||||
case '<bottom':
|
||||
sub_border = border.bottom = {};
|
||||
if (y.style) {
|
||||
sub_border.style = y.style;
|
||||
}
|
||||
break;
|
||||
case '<diagonal':
|
||||
sub_border = border.diagonal = {};
|
||||
if (y.style) {
|
||||
sub_border.style = y.style;
|
||||
}
|
||||
break;
|
||||
|
||||
/* 18.8.18 family CT_FontFamily */
|
||||
case '<family': if(y.val) font.family = parseInt(y.val,10); break;
|
||||
case '<family/>': case '</family>': case '</family': break;
|
||||
case '<color':
|
||||
sub_border.color = {};
|
||||
if (y.theme) sub_border.color.theme = y.theme;
|
||||
if (y.theme && themes.themeElements && themes.themeElements.clrScheme) {
|
||||
sub_border.color.rgb = rgb_tint(themes.themeElements.clrScheme[sub_border.color.theme].rgb, sub_border.color.tint || 0);
|
||||
}
|
||||
|
||||
/* 18.8.35 scheme CT_FontScheme */
|
||||
case '<scheme': if(y.val) font.scheme = y.val; break;
|
||||
case '<scheme/>': case '</scheme>': case '</scheme': break;
|
||||
if (y.tint) sub_border.color.tint = y.tint;
|
||||
if (y.rgb) sub_border.color.rgb = y.rgb;
|
||||
if (y.auto) sub_border.color.auto = y.auto;
|
||||
break;
|
||||
case '<name/>':
|
||||
case '</name>':
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
/* 18.4.1 charset CT_IntProperty */
|
||||
case '<charset':
|
||||
if(y.val == '1') break;
|
||||
y.codepage = CS2CP[parseInt(y.val, 10)];
|
||||
break;
|
||||
case '<charset/>': case '</charset>': case '</charset': break;
|
||||
|
||||
/* 18.?.? color CT_Color */
|
||||
case '<color':
|
||||
if(!font.color) font.color = {};
|
||||
if(y.auto) font.color.auto = parsexmlbool(y.auto);
|
||||
|
||||
if(y.rgb) font.color.rgb = y.rgb.slice(-6);
|
||||
else if(y.indexed) {
|
||||
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
|
||||
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);
|
||||
if(y.tint) font.color.tint = parseFloat(y.tint);
|
||||
if(y.theme && themes.themeElements && themes.themeElements.clrScheme) {
|
||||
font.color.rgb = rgb_tint(themes.themeElements.clrScheme[font.color.theme].rgb, font.color.tint || 0);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case '<color/>': case '</color>': case '</color': break;
|
||||
|
||||
/* note: sometimes mc:AlternateContent appears bare */
|
||||
case '<AlternateContent': pass = true; break;
|
||||
case '</AlternateContent>': 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');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if(!m) return;
|
||||
for(i=0; i < m.length; ++i) {
|
||||
var y = parsexmltag(m[i]);
|
||||
switch(strip_ns(y[0])) {
|
||||
case '<numFmts': case '</numFmts>': case '<numFmts/>': case '<numFmts>': break;
|
||||
case '<numFmt': {
|
||||
var f=unescapexml(utf8read(y.formatCode)), j=parseInt(y.numFmtId,10);
|
||||
styles.NumberFmt[j] = f;
|
||||
if(j>0) {
|
||||
if(j > 0x188) {
|
||||
for(j = 0x188; j > 0x3c; --j) if(styles.NumberFmt[j] == null) break;
|
||||
styles.NumberFmt[j] = f;
|
||||
}
|
||||
SSF__load(f,j);
|
||||
}
|
||||
} break;
|
||||
case '</numFmt>': break;
|
||||
default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in numFmts');
|
||||
}
|
||||
}
|
||||
function parse_numFmts(t, opts) {
|
||||
styles.NumberFmt = [];
|
||||
var k = keys(SSF._table);
|
||||
for (var i = 0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
|
||||
var m = t[0].match(tagregex);
|
||||
for (i = 0; i < m.length; ++i) {
|
||||
var y = parsexmltag(m[i]);
|
||||
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);
|
||||
styles.NumberFmt[j] = f;
|
||||
if (j > 0) SSF.load(f, j);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (opts.WTF) throw 'unrecognized ' + y[0] + ' in numFmts';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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])}));
|
||||
});
|
||||
if(o.length === 1) return "";
|
||||
o[o.length] = ("</numFmts>");
|
||||
o[0] = writextag('numFmts', null, { count:o.length-2 }).replace("/>", ">");
|
||||
return o.join("");
|
||||
function write_numFmts(NF, opts) {
|
||||
var o = ["<numFmts>"];
|
||||
[
|
||||
[5, 8],
|
||||
[23, 26],
|
||||
[41, 44],
|
||||
[63, 66],
|
||||
[164, 392]
|
||||
].forEach(function (r) {
|
||||
for (var i = r[0]; i <= r[1]; ++i) if (NF[i] !== undefined) o[o.length] = (writextag('numFmt', null, {numFmtId: i, formatCode: escapexml(NF[i])}));
|
||||
});
|
||||
if (o.length === 1) return "";
|
||||
o[o.length] = ("</numFmts>");
|
||||
o[0] = writextag('numFmts', null, { count: o.length - 2 }).replace("/>", ">");
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
/* 18.8.10 cellXfs CT_CellXfs */
|
||||
var cellXF_uint = [ "numFmtId", "fillId", "fontId", "borderId", "xfId" ];
|
||||
var cellXF_bool = [ "applyAlignment", "applyBorder", "applyFill", "applyFont", "applyNumberFormat", "applyProtection", "pivotButton", "quotePrefix" ];
|
||||
function parse_cellXfs(t, styles, opts) {
|
||||
styles.CellXf = [];
|
||||
var xf;
|
||||
var pass = false;
|
||||
(t.match(tagregex)||[]).forEach(function(x) {
|
||||
var y = parsexmltag(x), i = 0;
|
||||
switch(strip_ns(y[0])) {
|
||||
case '<cellXfs': case '<cellXfs>': case '<cellXfs/>': case '</cellXfs>': break;
|
||||
function parse_cellXfs(t, opts) {
|
||||
styles.CellXf = [];
|
||||
var xf;
|
||||
t[0].match(tagregex).forEach(function (x) {
|
||||
var y = parsexmltag(x);
|
||||
switch (y[0]) {
|
||||
case '<cellXfs':
|
||||
case '<cellXfs>':
|
||||
case '<cellXfs/>':
|
||||
case '</cellXfs>':
|
||||
break;
|
||||
|
||||
/* 18.8.45 xf CT_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) {
|
||||
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.45 xf CT_Xf */
|
||||
case '<xf':
|
||||
xf = y;
|
||||
delete xf[0];
|
||||
delete y[0];
|
||||
if (xf.numFmtId) xf.numFmtId = parseInt(xf.numFmtId, 10);
|
||||
if (xf.fillId) xf.fillId = parseInt(xf.fillId, 10);
|
||||
styles.CellXf.push(xf);
|
||||
break;
|
||||
case '</xf>':
|
||||
break;
|
||||
|
||||
/* 18.8.1 alignment CT_CellAlignment */
|
||||
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);
|
||||
xf.alignment = alignment;
|
||||
break;
|
||||
case '</alignment>': break;
|
||||
/* 18.8.1 alignment CT_CellAlignment */
|
||||
case '<alignment':
|
||||
case '<alignment/>':
|
||||
var alignment = {}
|
||||
if (y.vertical) { alignment.vertical = y.vertical;}
|
||||
if (y.horizontal) { alignment.horizontal = y.horizontal;}
|
||||
if (y.textRotation != undefined) { alignment.textRotation = y.textRotation; }
|
||||
if (y.indent) { alignment.indent = y.indent; }
|
||||
if (y.wrapText) { alignment.wrapText = y.wrapText; }
|
||||
xf.alignment = alignment;
|
||||
|
||||
/* 18.8.33 protection CT_CellProtection */
|
||||
case '<protection': case '<protection>':
|
||||
break;
|
||||
case '</protection>': case '<protection/>': break;
|
||||
break;
|
||||
|
||||
/* note: sometimes mc:AlternateContent appears bare */
|
||||
case '<AlternateContent': case '<AlternateContent>': pass = true; break;
|
||||
case '</AlternateContent>': pass = false; break;
|
||||
/* 18.8.33 protection CT_CellProtection */
|
||||
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 'unrecognized ' + y[0] + ' in cellXfs';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function write_cellXfs(cellXfs)/*:string*/ {
|
||||
var o/*:Array<string>*/ = [];
|
||||
o[o.length] = (writextag('cellXfs',null));
|
||||
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("/>",">");
|
||||
return o.join("");
|
||||
function write_cellXfs(cellXfs) {
|
||||
var o = [];
|
||||
o[o.length] = (writextag('cellXfs', null));
|
||||
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("/>", ">");
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
/* 18.8 Styles CT_Stylesheet*/
|
||||
var parse_sty_xml= /*#__PURE__*/(function make_pstyx() {
|
||||
var parse_sty_xml = (function make_pstyx() {
|
||||
var numFmtRegex = /<numFmts([^>]*)>.*<\/numFmts>/;
|
||||
var cellXfRegex = /<cellXfs([^>]*)>.*<\/cellXfs>/;
|
||||
var fillsRegex = /<fills([^>]*)>.*<\/fills>/;
|
||||
var bordersRegex = /<borders([^>]*)>.*<\/borders>/;
|
||||
|
||||
return function parse_sty_xml(data, themes, opts) {
|
||||
var styles = {};
|
||||
if(!data) return styles;
|
||||
data = remove_doctype(str_remove_ng(data, "<!--", "-->"));
|
||||
/* 18.8.39 styleSheet CT_Stylesheet */
|
||||
var t;
|
||||
return function parse_sty_xml(data, opts) {
|
||||
/* 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);
|
||||
/* numFmts CT_NumFmts ? */
|
||||
if ((t = data.match(numFmtRegex))) parse_numFmts(t, opts);
|
||||
|
||||
/* 18.8.23 fonts CT_Fonts ? */
|
||||
if((t=str_match_xml_ns(data, "fonts"))) parse_fonts(t[0], styles, themes, opts);
|
||||
/* fonts CT_Fonts ? */
|
||||
if ((t = data.match(/<fonts([^>]*)>.*<\/fonts>/))) parse_fonts(t, opts)
|
||||
|
||||
/* 18.8.21 fills CT_Fills ? */
|
||||
if((t=str_match_xml_ns(data, "fills"))) parse_fills(t[0], styles, themes, opts);
|
||||
/* fills CT_Fills */
|
||||
if ((t = data.match(fillsRegex))) parse_fills(t, opts);
|
||||
|
||||
/* 18.8.5 borders CT_Borders ? */
|
||||
if((t=str_match_xml_ns(data, "borders"))) parse_borders(t[0], styles, themes, opts);
|
||||
/* borders CT_Borders ? */
|
||||
if ((t = data.match(bordersRegex))) parse_borders(t, opts);
|
||||
/* cellStyleXfs CT_CellStyleXfs ? */
|
||||
|
||||
/* 18.8.9 cellStyleXfs CT_CellStyleXfs ? */
|
||||
/* 18.8.8 cellStyles CT_CellStyles ? */
|
||||
/* cellXfs CT_CellXfs ? */
|
||||
if ((t = data.match(cellXfRegex))) parse_cellXfs(t, opts);
|
||||
|
||||
/* 18.8.10 cellXfs CT_CellXfs ? */
|
||||
if((t=str_match_xml_ns(data, "cellXfs"))) parse_cellXfs(t[0], styles, opts);
|
||||
/* dxfs CT_Dxfs ? */
|
||||
/* tableStyles CT_TableStyles ? */
|
||||
/* colors CT_Colors ? */
|
||||
/* extLst CT_ExtensionList ? */
|
||||
|
||||
/* 18.8.15 dxfs CT_Dxfs ? */
|
||||
/* 18.8.42 tableStyles CT_TableStyles ? */
|
||||
/* 18.8.11 colors CT_Colors ? */
|
||||
/* 18.2.10 extLst CT_ExtensionList ? */
|
||||
|
||||
return styles;
|
||||
};
|
||||
return 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;
|
||||
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>');
|
||||
o[o.length] = ('<borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>');
|
||||
o[o.length] = ('<cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>');
|
||||
if((w = write_cellXfs(opts.cellXfs))) o[o.length] = (w);
|
||||
o[o.length] = ('<cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles>');
|
||||
o[o.length] = ('<dxfs count="0"/>');
|
||||
o[o.length] = ('<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleMedium4"/>');
|
||||
var STYLES_XML_ROOT = writextag('styleSheet', null, {
|
||||
'xmlns': XMLNS.main[0],
|
||||
'xmlns:vt': XMLNS.vt
|
||||
});
|
||||
|
||||
if(o.length>2){ o[o.length] = ('</styleSheet>'); o[1]=o[1].replace("/>",">"); }
|
||||
return o.join("");
|
||||
RELS.STY = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
|
||||
|
||||
function write_sty_xml(wb, opts) {
|
||||
|
||||
if (typeof style_builder != 'undefined' && typeof 'require' != 'undefined') {
|
||||
return style_builder.toXml();
|
||||
}
|
||||
|
||||
var o = [XML_HEADER, STYLES_XML_ROOT], w;
|
||||
if ((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>');
|
||||
o[o.length] = ('<borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>');
|
||||
o[o.length] = ('<cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>');
|
||||
if ((w = write_cellXfs(opts.cellXfs))) o[o.length] = (w);
|
||||
o[o.length] = ('<cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles>');
|
||||
o[o.length] = ('<dxfs count="0"/>');
|
||||
o[o.length] = ('<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleMedium4"/>');
|
||||
|
||||
if (o.length > 2) {
|
||||
o[o.length] = ('</styleSheet>');
|
||||
o[1] = o[1].replace("/>", ">");
|
||||
}
|
||||
return o.join("");
|
||||
}
|
||||
|
@ -1,393 +1,133 @@
|
||||
/* [MS-XLSB] 2.4.657 BrtFmt */
|
||||
function parse_BrtFmt(data, length/*:number*/) {
|
||||
var numFmtId = data.read_shift(2);
|
||||
/* [MS-XLSB] 2.4.651 BrtFmt */
|
||||
function parse_BrtFmt(data, length) {
|
||||
var ifmt = data.read_shift(2);
|
||||
var stFmtCode = parse_XLWideString(data,length-2);
|
||||
return [numFmtId, stFmtCode];
|
||||
}
|
||||
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 [ifmt, stFmtCode];
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.659 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;
|
||||
|
||||
var bls = data.read_shift(2);
|
||||
if(bls === 0x02BC) out.bold = 1;
|
||||
|
||||
switch(data.read_shift(2)) {
|
||||
/* case 0: out.vertAlign = "baseline"; break; */
|
||||
case 1: out.vertAlign = "superscript"; break;
|
||||
case 2: out.vertAlign = "subscript"; break;
|
||||
}
|
||||
|
||||
var underline = data.read_shift(1);
|
||||
if(underline != 0) out.underline = underline;
|
||||
|
||||
var family = data.read_shift(1);
|
||||
if(family > 0) out.family = family;
|
||||
|
||||
var bCharSet = data.read_shift(1);
|
||||
if(bCharSet > 0) out.charset = bCharSet;
|
||||
|
||||
/* [MS-XLSB] 2.4.653 BrtFont TODO */
|
||||
function parse_BrtFont(data, length) {
|
||||
var out = {flags:{}};
|
||||
out.dyHeight = data.read_shift(2);
|
||||
out.grbit = parse_FontFlags(data, 2);
|
||||
out.bls = data.read_shift(2);
|
||||
out.sss = data.read_shift(2);
|
||||
out.uls = data.read_shift(1);
|
||||
out.bFamily = data.read_shift(1);
|
||||
out.bCharSet = data.read_shift(1);
|
||||
data.l++;
|
||||
out.color = parse_BrtColor(data, 8);
|
||||
|
||||
switch(data.read_shift(1)) {
|
||||
/* case 0: out.scheme = "none": break; */
|
||||
case 1: out.scheme = "major"; break;
|
||||
case 2: out.scheme = "minor"; break;
|
||||
}
|
||||
|
||||
out.brtColor = parse_BrtColor(data, 8);
|
||||
out.bFontScheme = data.read_shift(1);
|
||||
out.name = parse_XLWideString(data, length - 21);
|
||||
|
||||
out.flags.Bold = out.bls === 0x02BC;
|
||||
out.flags.Italic = out.grbit.fItalic;
|
||||
out.flags.Strikeout = out.grbit.fStrikeout;
|
||||
out.flags.Outline = out.grbit.fOutline;
|
||||
out.flags.Shadow = out.grbit.fShadow;
|
||||
out.flags.Condense = out.grbit.fCondense;
|
||||
out.flags.Extend = out.grbit.fExtend;
|
||||
out.flags.Sub = out.sss & 0x2;
|
||||
out.flags.Sup = out.sss & 0x1;
|
||||
return out;
|
||||
}
|
||||
function write_BrtFont(font/*:any*/, o) {
|
||||
if(!o) o = new_buf(25+4*32);
|
||||
o.write_shift(2, font.sz * 20);
|
||||
write_FontFlags(font, o);
|
||||
o.write_shift(2, font.bold ? 0x02BC : 0x0190);
|
||||
var sss = 0;
|
||||
if(font.vertAlign == "superscript") sss = 1;
|
||||
else if(font.vertAlign == "subscript") sss = 2;
|
||||
o.write_shift(2, sss);
|
||||
o.write_shift(1, font.underline || 0);
|
||||
o.write_shift(1, font.family || 0);
|
||||
o.write_shift(1, font.charset || 0);
|
||||
o.write_shift(1, 0);
|
||||
write_BrtColor(font.color, o);
|
||||
var scheme = 0;
|
||||
if(font.scheme == "major") scheme = 1;
|
||||
if(font.scheme == "minor") scheme = 2;
|
||||
o.write_shift(1, scheme);
|
||||
write_XLWideString(font.name, o);
|
||||
return o.length > o.l ? o.slice(0, o.l) : o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.650 BrtFill */
|
||||
var XLSBFillPTNames = [
|
||||
"none",
|
||||
"solid",
|
||||
"mediumGray",
|
||||
"darkGray",
|
||||
"lightGray",
|
||||
"darkHorizontal",
|
||||
"darkVertical",
|
||||
"darkDown",
|
||||
"darkUp",
|
||||
"darkGrid",
|
||||
"darkTrellis",
|
||||
"lightHorizontal",
|
||||
"lightVertical",
|
||||
"lightDown",
|
||||
"lightUp",
|
||||
"lightGrid",
|
||||
"lightTrellis",
|
||||
"gray125",
|
||||
"gray0625"
|
||||
];
|
||||
var rev_XLSBFillPTNames/*:EvertNumType*/;
|
||||
/* 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);
|
||||
var j = 0;
|
||||
if(fls != 0x28) {
|
||||
/* TODO: custom FG Color */
|
||||
write_BrtColor({auto:1}, o);
|
||||
/* TODO: custom BG Color */
|
||||
write_BrtColor({auto:1}, o);
|
||||
|
||||
for(; j < 12; ++j) o.write_shift(4, 0);
|
||||
} else {
|
||||
for(; j < 4; ++j) o.write_shift(4, 0);
|
||||
|
||||
for(; j < 12; ++j) o.write_shift(4, 0); /* TODO */
|
||||
/* iGradientType */
|
||||
/* xnumDegree */
|
||||
/* xnumFillToLeft */
|
||||
/* xnumFillToRight */
|
||||
/* xnumFillToTop */
|
||||
/* xnumFillToBottom */
|
||||
/* cNumStop */
|
||||
/* xfillGradientStop */
|
||||
}
|
||||
return o.length > o.l ? o.slice(0, o.l) : o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.824 BrtXF */
|
||||
function parse_BrtXF(data, length/*:number*/) {
|
||||
var tgt = data.l + length;
|
||||
/* [MS-XLSB] 2.4.816 BrtXF */
|
||||
function parse_BrtXF(data, length) {
|
||||
var ixfeParent = data.read_shift(2);
|
||||
var ifmt = data.read_shift(2);
|
||||
data.l = tgt;
|
||||
return {ixfe:ixfeParent, numFmtId:ifmt };
|
||||
}
|
||||
function write_BrtXF(data, ixfeP, o) {
|
||||
if(!o) o = new_buf(16);
|
||||
o.write_shift(2, ixfeP||0);
|
||||
o.write_shift(2, data.numFmtId||0);
|
||||
o.write_shift(2, 0); /* iFont */
|
||||
o.write_shift(2, 0); /* iFill */
|
||||
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); /* xfGrbitAtr */
|
||||
o.write_shift(1, 0);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.4 Blxf TODO */
|
||||
function write_Blxf(data, o) {
|
||||
if(!o) o = new_buf(10);
|
||||
o.write_shift(1, 0); /* dg */
|
||||
o.write_shift(1, 0);
|
||||
o.write_shift(4, 0); /* color */
|
||||
o.write_shift(4, 0); /* color */
|
||||
return o;
|
||||
}
|
||||
/* [MS-XLSB] 2.4.302 BrtBorder TODO */
|
||||
var parse_BrtBorder = parsenoop;
|
||||
function write_BrtBorder(border, o) {
|
||||
if(!o) o = new_buf(51);
|
||||
o.write_shift(1, 0); /* diagonal */
|
||||
write_Blxf(null, o); /* top */
|
||||
write_Blxf(null, o); /* bottom */
|
||||
write_Blxf(null, o); /* left */
|
||||
write_Blxf(null, o); /* right */
|
||||
write_Blxf(null, o); /* diag */
|
||||
return o.length > o.l ? o.slice(0, o.l) : o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.763 BrtStyle TODO */
|
||||
function write_BrtStyle(style, o) {
|
||||
if(!o) o = new_buf(12+4*10);
|
||||
o.write_shift(4, style.xfId);
|
||||
o.write_shift(2, 1);
|
||||
o.write_shift(1, +style.builtinId);
|
||||
o.write_shift(1, 0); /* iLevel */
|
||||
write_XLNullableWideString(style.name || "", o);
|
||||
return o.length > o.l ? o.slice(0, o.l) : o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.272 BrtBeginTableStyles */
|
||||
function write_BrtBeginTableStyles(cnt, defTableStyle, defPivotStyle) {
|
||||
var o = new_buf(4+256*2*4);
|
||||
o.write_shift(4, cnt);
|
||||
write_XLNullableWideString(defTableStyle, o);
|
||||
write_XLNullableWideString(defPivotStyle, o);
|
||||
return o.length > o.l ? o.slice(0, o.l) : o;
|
||||
parsenoop(data, length-4);
|
||||
return {ixfe:ixfeParent, ifmt:ifmt };
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.50 Styles */
|
||||
function parse_sty_bin(data, themes, opts) {
|
||||
var styles = {};
|
||||
styles.NumberFmt = ([]/*:any*/);
|
||||
for(var y in table_fmt) styles.NumberFmt[y] = table_fmt[y];
|
||||
function parse_sty_bin(data, opts) {
|
||||
styles.NumberFmt = [];
|
||||
for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y];
|
||||
|
||||
styles.CellXf = [];
|
||||
styles.Fonts = [];
|
||||
var state/*:Array<string>*/ = [];
|
||||
var state = ""; /* TODO: this should be a stack */
|
||||
var pass = false;
|
||||
recordhopper(data, function hopper_sty(val, R, RT) {
|
||||
switch(RT) {
|
||||
case 0x002C: /* BrtFmt */
|
||||
styles.NumberFmt[val[0]] = val[1]; SSF__load(val[1], val[0]);
|
||||
switch(R.n) {
|
||||
case 'BrtFmt':
|
||||
styles.NumberFmt[val[0]] = val[1]; SSF.load(val[1], val[0]);
|
||||
break;
|
||||
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 'BrtFont': break; /* TODO */
|
||||
case 'BrtKnownFonts': break; /* TODO */
|
||||
case 'BrtFill': break; /* TODO */
|
||||
case 'BrtBorder': break; /* TODO */
|
||||
case 'BrtXF':
|
||||
if(state === "CELLXFS") {
|
||||
styles.CellXf.push(val);
|
||||
}
|
||||
break;
|
||||
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 */
|
||||
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;
|
||||
|
||||
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));
|
||||
break; /* TODO */
|
||||
case 'BrtStyle': break; /* TODO */
|
||||
case 'BrtDXF': break; /* TODO */
|
||||
case 'BrtMRUColor': break; /* TODO */
|
||||
case 'BrtIndexedColor': break; /* TODO */
|
||||
case 'BrtBeginStyleSheet': break;
|
||||
case 'BrtEndStyleSheet': break;
|
||||
case 'BrtBeginTableStyle': break;
|
||||
case 'BrtTableStyleElement': break;
|
||||
case 'BrtEndTableStyle': break;
|
||||
case 'BrtBeginFmts': state = "FMTS"; break;
|
||||
case 'BrtEndFmts': state = ""; break;
|
||||
case 'BrtBeginFonts': state = "FONTS"; break;
|
||||
case 'BrtEndFonts': state = ""; break;
|
||||
case 'BrtACBegin': state = "ACFONTS"; break;
|
||||
case 'BrtACEnd': state = ""; break;
|
||||
case 'BrtBeginFills': state = "FILLS"; break;
|
||||
case 'BrtEndFills': state = ""; break;
|
||||
case 'BrtBeginBorders': state = "BORDERS"; break;
|
||||
case 'BrtEndBorders': state = ""; break;
|
||||
case 'BrtBeginCellStyleXFs': state = "CELLSTYLEXFS"; break;
|
||||
case 'BrtEndCellStyleXFs': state = ""; break;
|
||||
case 'BrtBeginCellXFs': state = "CELLXFS"; break;
|
||||
case 'BrtEndCellXFs': state = ""; break;
|
||||
case 'BrtBeginStyles': state = "STYLES"; break;
|
||||
case 'BrtEndStyles': state = ""; break;
|
||||
case 'BrtBeginDXFs': state = "DXFS"; break;
|
||||
case 'BrtEndDXFs': state = ""; break;
|
||||
case 'BrtBeginTableStyles': state = "TABLESTYLES"; break;
|
||||
case 'BrtEndTableStyles': state = ""; break;
|
||||
case 'BrtBeginColorPalette': state = "COLORPALETTE"; break;
|
||||
case 'BrtEndColorPalette': state = ""; break;
|
||||
case 'BrtBeginIndexedColors': state = "INDEXEDCOLORS"; break;
|
||||
case 'BrtEndIndexedColors': state = ""; break;
|
||||
case 'BrtBeginMRUColors': state = "MRUCOLORS"; break;
|
||||
case 'BrtEndMRUColors': state = ""; break;
|
||||
case 'BrtFRTBegin': pass = true; break;
|
||||
case 'BrtFRTEnd': pass = false; break;
|
||||
case 'BrtBeginStyleSheetExt14': break;
|
||||
case 'BrtBeginSlicerStyles': break;
|
||||
case 'BrtEndSlicerStyles': break;
|
||||
case 'BrtBeginTimelineStylesheetExt15': break;
|
||||
case 'BrtEndTimelineStylesheetExt15': break;
|
||||
case 'BrtBeginTimelineStyles': break;
|
||||
case 'BrtEndTimelineStyles': break;
|
||||
case 'BrtEndStyleSheetExt14': break;
|
||||
default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
|
||||
}
|
||||
});
|
||||
return styles;
|
||||
}
|
||||
|
||||
function write_FMTS_bin(ba, NF/*:?SSFTable*/) {
|
||||
if(!NF) return;
|
||||
var cnt = 0;
|
||||
[[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) ++cnt;
|
||||
});
|
||||
|
||||
if(cnt == 0) return;
|
||||
write_record(ba, 0x0267 /* 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]));
|
||||
});
|
||||
write_record(ba, 0x0268 /* BrtEndFmts */);
|
||||
}
|
||||
|
||||
function write_FONTS_bin(ba/*::, data*/) {
|
||||
var cnt = 1;
|
||||
|
||||
if(cnt == 0) return;
|
||||
write_record(ba, 0x0263 /* BrtBeginFonts */, write_UInt32LE(cnt));
|
||||
write_record(ba, 0x002B /* BrtFont */, write_BrtFont({
|
||||
sz:12,
|
||||
color: {theme:1},
|
||||
name: "Calibri",
|
||||
family: 2,
|
||||
scheme: "minor"
|
||||
}));
|
||||
/* 1*65491BrtFont [ACFONTS] */
|
||||
write_record(ba, 0x0264 /* BrtEndFonts */);
|
||||
}
|
||||
|
||||
function write_FILLS_bin(ba/*::, data*/) {
|
||||
var cnt = 2;
|
||||
|
||||
if(cnt == 0) return;
|
||||
write_record(ba, 0x025B /* BrtBeginFills */, write_UInt32LE(cnt));
|
||||
write_record(ba, 0x002D /* BrtFill */, write_BrtFill({patternType:"none"}));
|
||||
write_record(ba, 0x002D /* BrtFill */, write_BrtFill({patternType:"gray125"}));
|
||||
/* 1*65431BrtFill */
|
||||
write_record(ba, 0x025C /* BrtEndFills */);
|
||||
}
|
||||
|
||||
function write_BORDERS_bin(ba/*::, data*/) {
|
||||
var cnt = 1;
|
||||
|
||||
if(cnt == 0) return;
|
||||
write_record(ba, 0x0265 /* BrtBeginBorders */, write_UInt32LE(cnt));
|
||||
write_record(ba, 0x002E /* BrtBorder */, write_BrtBorder({}));
|
||||
/* 1*65430BrtBorder */
|
||||
write_record(ba, 0x0266 /* BrtEndBorders */);
|
||||
}
|
||||
|
||||
function write_CELLSTYLEXFS_bin(ba/*::, data*/) {
|
||||
var cnt = 1;
|
||||
write_record(ba, 0x0272 /* BrtBeginCellStyleXFs */, write_UInt32LE(cnt));
|
||||
write_record(ba, 0x002F /* BrtXF */, write_BrtXF({
|
||||
numFmtId: 0,
|
||||
fontId: 0,
|
||||
fillId: 0,
|
||||
borderId: 0
|
||||
}, 0xFFFF));
|
||||
/* 1*65430(BrtXF *FRT) */
|
||||
write_record(ba, 0x0273 /* 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)); });
|
||||
/* 1*65430(BrtXF *FRT) */
|
||||
write_record(ba, 0x026A /* BrtEndCellXFs */);
|
||||
}
|
||||
|
||||
function write_STYLES_bin(ba/*::, data*/) {
|
||||
var cnt = 1;
|
||||
|
||||
write_record(ba, 0x026B /* BrtBeginStyles */, write_UInt32LE(cnt));
|
||||
write_record(ba, 0x0030 /* BrtStyle */, write_BrtStyle({
|
||||
xfId:0,
|
||||
builtinId:0,
|
||||
name:"Normal"
|
||||
}));
|
||||
/* 1*65430(BrtStyle *FRT) */
|
||||
write_record(ba, 0x026C /* BrtEndStyles */);
|
||||
}
|
||||
|
||||
function write_DXFS_bin(ba/*::, data*/) {
|
||||
var cnt = 0;
|
||||
|
||||
write_record(ba, 0x01F9 /* BrtBeginDXFs */, write_UInt32LE(cnt));
|
||||
/* *2147483647(BrtDXF *FRT) */
|
||||
write_record(ba, 0x01FA /* BrtEndDXFs */);
|
||||
}
|
||||
|
||||
function write_TABLESTYLES_bin(ba/*::, data*/) {
|
||||
var cnt = 0;
|
||||
|
||||
write_record(ba, 0x01FC /* BrtBeginTableStyles */, write_BrtBeginTableStyles(cnt, "TableStyleMedium9", "PivotStyleMedium4"));
|
||||
/* *TABLESTYLE */
|
||||
write_record(ba, 0x01FD /* BrtEndTableStyles */);
|
||||
}
|
||||
|
||||
function write_COLORPALETTE_bin(/*::ba, data*/) {
|
||||
return;
|
||||
/* BrtBeginColorPalette [INDEXEDCOLORS] [MRUCOLORS] BrtEndColorPalette */
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.50 Styles */
|
||||
function write_sty_bin(wb, opts) {
|
||||
function write_sty_bin(data, opts) {
|
||||
var ba = buf_array();
|
||||
write_record(ba, 0x0116 /* BrtBeginStyleSheet */);
|
||||
write_FMTS_bin(ba, wb.SSF);
|
||||
write_FONTS_bin(ba, wb);
|
||||
write_FILLS_bin(ba, wb);
|
||||
write_BORDERS_bin(ba, wb);
|
||||
write_CELLSTYLEXFS_bin(ba, wb);
|
||||
write_CELLXFS_bin(ba, opts.cellXfs);
|
||||
write_STYLES_bin(ba, wb);
|
||||
write_DXFS_bin(ba, wb);
|
||||
write_TABLESTYLES_bin(ba, wb);
|
||||
write_COLORPALETTE_bin(ba, wb);
|
||||
write_record(ba, "BrtBeginStyleSheet");
|
||||
/* [FMTS] */
|
||||
/* [FONTS] */
|
||||
/* [FILLS] */
|
||||
/* [BORDERS] */
|
||||
/* CELLSTYLEXFS */
|
||||
/* CELLXFS*/
|
||||
/* STYLES */
|
||||
/* DXFS */
|
||||
/* TABLESTYLES */
|
||||
/* [COLORPALETTE] */
|
||||
/* FRTSTYLESHEET*/
|
||||
write_record(ba, 0x0117 /* BrtEndStyleSheet */);
|
||||
write_record(ba, "BrtEndStyleSheet");
|
||||
return ba.end();
|
||||
}
|
||||
|
307
bits/49_theme.js
307
bits/49_theme.js
File diff suppressed because one or more lines are too long
@ -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;
|
||||
function parse_Theme(blob, 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};
|
||||
}
|
||||
@ -75,16 +68,10 @@ function update_xfext(xf, xfext) {
|
||||
switch(xfe[0]) { /* 2.5.108 extPropData */
|
||||
case 0x04: break; /* foreground color */
|
||||
case 0x05: break; /* background color */
|
||||
case 0x06: break; /* gradient fill */
|
||||
case 0x07: break; /* top cell border color */
|
||||
case 0x08: break; /* bottom cell border color */
|
||||
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 0x07: case 0x08: case 0x09: case 0x0a: break;
|
||||
case 0x0d: break; /* text color */
|
||||
case 0x0e: break; /* font scheme */
|
||||
case 0x0f: break; /* indentation level */
|
||||
default: throw "bafuq" + xfe[0].toString(16);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1,111 +0,0 @@
|
||||
function parse_BrtMdtinfo(data, length) {
|
||||
return {
|
||||
flags: data.read_shift(4),
|
||||
version: data.read_shift(4),
|
||||
name: parse_XLWideString(data, length - 8)
|
||||
};
|
||||
}
|
||||
function write_BrtMdtinfo(data) {
|
||||
var o = new_buf(12 + 2 * data.name.length);
|
||||
o.write_shift(4, data.flags);
|
||||
o.write_shift(4, data.version);
|
||||
write_XLWideString(data.name, o);
|
||||
return o.slice(0, o.l);
|
||||
}
|
||||
function parse_BrtMdb(data) {
|
||||
var out = [];
|
||||
var cnt = data.read_shift(4);
|
||||
while (cnt-- > 0)
|
||||
out.push([data.read_shift(4), data.read_shift(4)]);
|
||||
return out;
|
||||
}
|
||||
function write_BrtMdb(mdb) {
|
||||
var o = new_buf(4 + 8 * mdb.length);
|
||||
o.write_shift(4, mdb.length);
|
||||
for (var i = 0; i < mdb.length; ++i) {
|
||||
o.write_shift(4, mdb[i][0]);
|
||||
o.write_shift(4, mdb[i][1]);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
function write_BrtBeginEsfmd(cnt, name) {
|
||||
var o = new_buf(8 + 2 * name.length);
|
||||
o.write_shift(4, cnt);
|
||||
write_XLWideString(name, o);
|
||||
return o.slice(0, o.l);
|
||||
}
|
||||
function parse_BrtBeginEsmdb(data) {
|
||||
data.l += 4;
|
||||
return data.read_shift(4) != 0;
|
||||
}
|
||||
function write_BrtBeginEsmdb(cnt, cm) {
|
||||
var o = new_buf(8);
|
||||
o.write_shift(4, cnt);
|
||||
o.write_shift(4, cm ? 1 : 0);
|
||||
return o;
|
||||
}
|
||||
function parse_xlmeta_bin(data, name, _opts) {
|
||||
var out = { Types: [], Cell: [], Value: [] };
|
||||
var opts = _opts || {};
|
||||
var state = [];
|
||||
var pass = false;
|
||||
var metatype = 2;
|
||||
recordhopper(data, function(val, R, RT) {
|
||||
switch (RT) {
|
||||
case 335:
|
||||
out.Types.push({ name: val.name });
|
||||
break;
|
||||
case 51:
|
||||
val.forEach(function(r) {
|
||||
if (metatype == 1)
|
||||
out.Cell.push({ type: out.Types[r[0] - 1].name, index: r[1] });
|
||||
else if (metatype == 0)
|
||||
out.Value.push({ type: out.Types[r[0] - 1].name, index: r[1] });
|
||||
});
|
||||
break;
|
||||
case 337:
|
||||
metatype = val ? 1 : 0;
|
||||
break;
|
||||
case 338:
|
||||
metatype = 2;
|
||||
break;
|
||||
case 35:
|
||||
state.push(RT);
|
||||
pass = true;
|
||||
break;
|
||||
case 36:
|
||||
state.pop();
|
||||
pass = false;
|
||||
break;
|
||||
default:
|
||||
if (R.T) {
|
||||
} else if (!pass || opts.WTF && state[state.length - 1] != 35)
|
||||
throw new Error("Unexpected record 0x" + RT.toString(16));
|
||||
}
|
||||
});
|
||||
return out;
|
||||
}
|
||||
function write_xlmeta_bin() {
|
||||
var ba = buf_array();
|
||||
write_record(ba, 332);
|
||||
write_record(ba, 334, write_UInt32LE(1));
|
||||
write_record(ba, 335, write_BrtMdtinfo({
|
||||
name: "XLDAPR",
|
||||
version: 12e4,
|
||||
flags: 3496657072
|
||||
}));
|
||||
write_record(ba, 336);
|
||||
write_record(ba, 339, write_BrtBeginEsfmd(1, "XLDAPR"));
|
||||
write_record(ba, 52);
|
||||
write_record(ba, 35, write_UInt32LE(514));
|
||||
write_record(ba, 4096, write_UInt32LE(0));
|
||||
write_record(ba, 4097, writeuint16(1));
|
||||
write_record(ba, 36);
|
||||
write_record(ba, 53);
|
||||
write_record(ba, 340);
|
||||
write_record(ba, 337, write_BrtBeginEsmdb(1, true));
|
||||
write_record(ba, 51, write_BrtMdb([[1, 0]]));
|
||||
write_record(ba, 338);
|
||||
write_record(ba, 333);
|
||||
return ba.end();
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
function parse_xlmeta_xml(data, name, opts) {
|
||||
var out = { Types: [], Cell: [], Value: [] };
|
||||
if (!data)
|
||||
return out;
|
||||
var pass = false;
|
||||
var metatype = 2;
|
||||
var lastmeta;
|
||||
data.replace(tagregex, function(x) {
|
||||
var y = parsexmltag(x);
|
||||
switch (strip_ns(y[0])) {
|
||||
case "<?xml":
|
||||
break;
|
||||
case "<metadata":
|
||||
case "</metadata>":
|
||||
break;
|
||||
case "<metadataTypes":
|
||||
case "</metadataTypes>":
|
||||
break;
|
||||
case "<metadataType":
|
||||
out.Types.push({ name: y.name });
|
||||
break;
|
||||
case "</metadataType>":
|
||||
break;
|
||||
case "<futureMetadata":
|
||||
for (var j = 0; j < out.Types.length; ++j)
|
||||
if (out.Types[j].name == y.name)
|
||||
lastmeta = out.Types[j];
|
||||
break;
|
||||
case "</futureMetadata>":
|
||||
break;
|
||||
case "<bk>":
|
||||
break;
|
||||
case "</bk>":
|
||||
break;
|
||||
case "<rc":
|
||||
if (metatype == 1)
|
||||
out.Cell.push({ type: out.Types[y.t - 1].name, index: +y.v });
|
||||
else if (metatype == 0)
|
||||
out.Value.push({ type: out.Types[y.t - 1].name, index: +y.v });
|
||||
break;
|
||||
case "</rc>":
|
||||
break;
|
||||
case "<cellMetadata":
|
||||
metatype = 1;
|
||||
break;
|
||||
case "</cellMetadata>":
|
||||
metatype = 2;
|
||||
break;
|
||||
case "<valueMetadata":
|
||||
metatype = 0;
|
||||
break;
|
||||
case "</valueMetadata>":
|
||||
metatype = 2;
|
||||
break;
|
||||
case "<extLst":
|
||||
case "<extLst>":
|
||||
case "</extLst>":
|
||||
case "<extLst/>":
|
||||
break;
|
||||
case "<ext":
|
||||
pass = true;
|
||||
break;
|
||||
case "</ext>":
|
||||
pass = false;
|
||||
break;
|
||||
case "<rvb":
|
||||
if (!lastmeta)
|
||||
break;
|
||||
if (!lastmeta.offsets)
|
||||
lastmeta.offsets = [];
|
||||
lastmeta.offsets.push(+y.i);
|
||||
break;
|
||||
default:
|
||||
if (!pass && (opts == null ? void 0 : opts.WTF))
|
||||
throw new Error("unrecognized " + y[0] + " in metadata");
|
||||
}
|
||||
return x;
|
||||
});
|
||||
return out;
|
||||
}
|
||||
function write_xlmeta_xml() {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<metadata xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:xlrd="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata" xmlns:xda="http://schemas.microsoft.com/office/spreadsheetml/2017/dynamicarray">\n <metadataTypes count="1">\n <metadataType name="XLDAPR" minSupportedVersion="120000" copy="1" pasteAll="1" pasteValues="1" merge="1" splitFirst="1" rowColShift="1" clearFormats="1" clearComments="1" assign="1" coerce="1" cellMeta="1"/>\n </metadataTypes>\n <futureMetadata name="XLDAPR" count="1">\n <bk>\n <extLst>\n <ext uri="{bdbb8cdc-fa1e-496e-a857-3c3f30c029c3}">\n <xda:dynamicArrayProperties fDynamic="1" fCollapsed="0"/>\n </ext>\n </extLst>\n </bk>\n </futureMetadata>\n <cellMetadata count="1">\n <bk>\n <rc t="1" v="0"/>\n </bk>\n </cellMetadata>\n</metadata>');
|
||||
return o.join("");
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/* 18.6 Calculation Chain */
|
||||
function parse_cc_xml(data/*::, name, opts*/)/*:Array<any>*/ {
|
||||
var d = [];
|
||||
if(!data) return d;
|
||||
var i = 1;
|
||||
(data.match(tagregex)||[]).forEach(function(x) {
|
||||
var y = parsexmltag(x);
|
||||
switch(y[0]) {
|
||||
case '<?xml': break;
|
||||
/* 18.6.2 calcChain CT_CalcChain 1 */
|
||||
case '<calcChain': case '<calcChain>': case '</calcChain>': break;
|
||||
/* 18.6.1 c CT_CalcCell 1 */
|
||||
case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break;
|
||||
}
|
||||
});
|
||||
return d;
|
||||
}
|
||||
|
||||
//function write_cc_xml(data, opts) { }
|
||||
|
||||
/* [MS-XLSB] 2.6.4.1 */
|
||||
function parse_BrtCalcChainItem$(data) {
|
||||
var out = {};
|
||||
out.i = data.read_shift(4);
|
||||
var cell = {};
|
||||
cell.r = data.read_shift(4);
|
||||
cell.c = data.read_shift(4);
|
||||
out.r = encode_cell(cell);
|
||||
var flags = data.read_shift(1);
|
||||
if(flags & 0x2) out.l = '1';
|
||||
if(flags & 0x8) out.a = '1';
|
||||
return out;
|
||||
}
|
||||
|
||||
/* 18.6 Calculation Chain */
|
||||
function parse_cc_bin(data, name, opts) {
|
||||
var out = [];
|
||||
var pass = false;
|
||||
recordhopper(data, function hopper_cc(val, R, 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));
|
||||
}
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
//function write_cc_bin(data, opts) { }
|
18
bits/52_ccxml.js
Normal file
18
bits/52_ccxml.js
Normal file
@ -0,0 +1,18 @@
|
||||
/* 18.6 Calculation Chain */
|
||||
function parse_cc_xml(data, opts) {
|
||||
var d = [];
|
||||
var l = 0, i = 1;
|
||||
(data.match(tagregex)||[]).forEach(function(x) {
|
||||
var y = parsexmltag(x);
|
||||
switch(y[0]) {
|
||||
case '<?xml': break;
|
||||
/* 18.6.2 calcChain CT_CalcChain 1 */
|
||||
case '<calcChain': case '<calcChain>': case '</calcChain>': break;
|
||||
/* 18.6.1 c CT_CalcCell 1 */
|
||||
case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break;
|
||||
}
|
||||
});
|
||||
return d;
|
||||
}
|
||||
|
||||
function write_cc_xml(data, opts) { }
|
30
bits/53_ccbin.js
Normal file
30
bits/53_ccbin.js
Normal file
@ -0,0 +1,30 @@
|
||||
/* [MS-XLSB] 2.6.4.1 */
|
||||
function parse_BrtCalcChainItem$(data, length) {
|
||||
var out = {};
|
||||
out.i = data.read_shift(4);
|
||||
var cell = {};
|
||||
cell.r = data.read_shift(4);
|
||||
cell.c = data.read_shift(4);
|
||||
out.r = encode_cell(cell);
|
||||
var flags = data.read_shift(1);
|
||||
if(flags & 0x2) out.l = '1';
|
||||
if(flags & 0x8) out.a = '1';
|
||||
return out;
|
||||
}
|
||||
|
||||
/* 18.6 Calculation Chain */
|
||||
function parse_cc_bin(data, opts) {
|
||||
var out = [];
|
||||
var pass = false;
|
||||
recordhopper(data, function hopper_cc(val, R, RT) {
|
||||
switch(R.n) {
|
||||
case 'BrtCalcChainItem$': out.push(val); break;
|
||||
case 'BrtBeginCalcChain$': break;
|
||||
case 'BrtEndCalcChain$': break;
|
||||
default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
|
||||
}
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
function write_cc_bin(data, opts) { }
|
@ -1,50 +0,0 @@
|
||||
/* 18.14 Supplementary Workbook Data */
|
||||
function parse_xlink_xml(/*::data, rel, 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) {
|
||||
if(!data) return data;
|
||||
var opts = _opts || {};
|
||||
|
||||
var pass = false, end = false;
|
||||
|
||||
recordhopper(data, function xlink_parse(val, R, RT) {
|
||||
if(end) return;
|
||||
switch(RT) {
|
||||
case 0x0167: /* 'BrtSupTabs' */
|
||||
case 0x016B: /* 'BrtExternTableStart' */
|
||||
case 0x016C: /* 'BrtExternTableEnd' */
|
||||
case 0x016E: /* 'BrtExternRowHdr' */
|
||||
case 0x016F: /* 'BrtExternCellBlank' */
|
||||
case 0x0170: /* 'BrtExternCellReal' */
|
||||
case 0x0171: /* 'BrtExternCellBool' */
|
||||
case 0x0172: /* 'BrtExternCellError' */
|
||||
case 0x0173: /* 'BrtExternCellString' */
|
||||
case 0x01D8: /* 'BrtExternValueMeta' */
|
||||
case 0x0241: /* 'BrtSupNameStart' */
|
||||
case 0x0242: /* 'BrtSupNameValueStart' */
|
||||
case 0x0243: /* 'BrtSupNameValueEnd' */
|
||||
case 0x0244: /* 'BrtSupNameNum' */
|
||||
case 0x0245: /* 'BrtSupNameErr' */
|
||||
case 0x0246: /* 'BrtSupNameSt' */
|
||||
case 0x0247: /* 'BrtSupNameNil' */
|
||||
case 0x0248: /* 'BrtSupNameBool' */
|
||||
case 0x0249: /* 'BrtSupNameFmla' */
|
||||
case 0x024A: /* 'BrtSupNameBits' */
|
||||
case 0x024B: /* 'BrtSupNameEnd' */
|
||||
break;
|
||||
|
||||
case 0x0023: /* 'BrtFRTBegin' */
|
||||
pass = true; break;
|
||||
case 0x0024: /* 'BrtFRTEnd' */
|
||||
pass = false; break;
|
||||
|
||||
default:
|
||||
if(R.T){/* empty */}
|
||||
else if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
|
||||
}
|
||||
}, opts);
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
/* 20.5 DrawingML - SpreadsheetML Drawing */
|
||||
/* 20.5.2.35 wsDr CT_Drawing */
|
||||
function parse_drawing(data, rels/*:any*/) {
|
||||
if(!data) return "??";
|
||||
/*
|
||||
Chartsheet Drawing:
|
||||
- 20.5.2.35 wsDr CT_Drawing
|
||||
- 20.5.2.1 absoluteAnchor CT_AbsoluteAnchor
|
||||
- 20.5.2.16 graphicFrame CT_GraphicalObjectFrame
|
||||
- 20.1.2.2.16 graphic CT_GraphicalObject
|
||||
- 20.1.2.2.17 graphicData CT_GraphicalObjectData
|
||||
- chart reference
|
||||
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];
|
||||
|
||||
return rels['!id'][id].Target;
|
||||
}
|
||||
|
@ -1,94 +0,0 @@
|
||||
/* 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 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"})
|
||||
];
|
||||
|
||||
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 [
|
||||
'<v:shape' + wxt_helper({
|
||||
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" : "") ,
|
||||
fillcolor:"#ECFAD4",
|
||||
strokecolor:"#edeaa1"
|
||||
}) + '>',
|
||||
fillxml,
|
||||
writextag("v:shadow", null, shadata),
|
||||
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:AutoFill', "False"),
|
||||
writetag('x:Row', String(c.r)),
|
||||
writetag('x:Column', String(c.c)),
|
||||
x[1].hidden ? '' : '<x:Visible/>',
|
||||
'</x:ClientData>',
|
||||
'</v:shape>'
|
||||
].join("");
|
||||
}
|
@ -1,38 +1,42 @@
|
||||
function sheet_insert_comments(sheet/*:WorkSheet*/, comments/*:Array<RawComment>*/, threaded/*:boolean*/, people/*:?Array<any>*/) {
|
||||
var dense = sheet["!data"] != null;
|
||||
var cell/*:Cell*/;
|
||||
|
||||
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) {
|
||||
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];
|
||||
} else cell = sheet[comment.ref];
|
||||
var cell = sheet[comment.ref];
|
||||
if (!cell) {
|
||||
cell = ({t:"z"}/*:any*/);
|
||||
if(dense) sheet["!data"][r.r][r.c] = cell;
|
||||
else sheet[comment.ref] = cell;
|
||||
cell = {};
|
||||
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};
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,186 +1,27 @@
|
||||
/* 18.7 Comments */
|
||||
function parse_comments_xml(data/*:string*/, opts)/*:Array<RawComment>*/ {
|
||||
/* 18.7.6 CT_Comments */
|
||||
/* 18.7.3 CT_Comment */
|
||||
function parse_comments_xml(data, opts) {
|
||||
if(data.match(/<(?:\w+:)?comments *\/>/)) return [];
|
||||
var authors/*:Array<string>*/ = [];
|
||||
var commentList/*:Array<RawComment>*/ = [];
|
||||
var authtag = str_match_xml_ns(data, "authors");
|
||||
if(authtag && authtag[1]) authtag[1].split(/<\/\w*:?author>/).forEach(function(x) {
|
||||
var authors = [];
|
||||
var commentList = [];
|
||||
data.match(/<(?:\w+:)?authors>([^\u2603]*)<\/(?:\w+:)?authors>/)[1].split(/<\/\w*:?author>/).forEach(function(x) {
|
||||
if(x === "" || x.trim() === "") return;
|
||||
var a = x.match(/<(?:\w+:)?author[^<>]*>(.*)/);
|
||||
if(a) authors.push(a[1]);
|
||||
authors.push(x.match(/<(?:\w+:)?author[^>]*>(.*)/)[1]);
|
||||
});
|
||||
var cmnttag = str_match_xml_ns(data, "commentList");
|
||||
if(cmnttag && cmnttag[1]) cmnttag[1].split(/<\/\w*:?comment>/).forEach(function(x) {
|
||||
(data.match(/<(?:\w+:)?commentList>([^\u2603]*)<\/(?:\w+:)?commentList>/)||["",""])[1].split(/<\/\w*:?comment>/).forEach(function(x, index) {
|
||||
if(x === "" || x.trim() === "") return;
|
||||
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 y = parsexmltag(x.match(/<(?:\w+:)?comment[^>]*>/)[0]);
|
||||
var comment = { author: y.authorId && authors[y.authorId] ? authors[y.authorId] : undefined, ref: y.ref, guid: y.guid };
|
||||
var cell = decode_cell(y.ref);
|
||||
if(opts.sheetRows && opts.sheetRows <= cell.r) return;
|
||||
var textMatch = str_match_xml_ns(x, "text");
|
||||
var rt = !!textMatch && !!textMatch[1] && parse_si(textMatch[1]) || {r:"",t:"",h:""};
|
||||
var textMatch = x.match(/<text>([^\u2603]*)<\/text>/);
|
||||
if (!textMatch || !textMatch[1]) return; // a comment may contain an empty text tag.
|
||||
var rt = parse_si(textMatch[1]);
|
||||
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;
|
||||
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 iauthor/*:Array<string>*/ = [];
|
||||
o.push("<authors>");
|
||||
data.forEach(function(x) { x[1].forEach(function(w) { var a = escapexml(w.a);
|
||||
if(iauthor.indexOf(a) == -1) {
|
||||
iauthor.push(a);
|
||||
o.push("<author>" + a + "</author>");
|
||||
}
|
||||
if(w.T && w.ID && iauthor.indexOf("tc=" + w.ID) == -1) {
|
||||
iauthor.push("tc=" + w.ID);
|
||||
o.push("<author>" + "tc=" + w.ID + "</author>");
|
||||
}
|
||||
}); });
|
||||
if(iauthor.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)));
|
||||
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("");
|
||||
}
|
||||
function write_comments_xml(data, opts) { }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* [MS-XLSB] 2.4.28 BrtBeginComment */
|
||||
function parse_BrtBeginComment(data) {
|
||||
function parse_BrtBeginComment(data, length) {
|
||||
var out = {};
|
||||
out.iauthor = data.read_shift(4);
|
||||
var rfx = parse_UncheckedRfX(data, 16);
|
||||
@ -8,97 +8,39 @@ function parse_BrtBeginComment(data) {
|
||||
data.l += 16; /*var guid = parse_GUID(data); */
|
||||
return out;
|
||||
}
|
||||
function write_BrtBeginComment(data, o) {
|
||||
if(o == null) o = new_buf(36);
|
||||
o.write_shift(4, data[1].iauthor);
|
||||
write_UncheckedRfX((data[0]/*:any*/), o);
|
||||
o.write_shift(4, 0);
|
||||
o.write_shift(4, 0);
|
||||
o.write_shift(4, 0);
|
||||
o.write_shift(4, 0);
|
||||
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.4.325 BrtCommentText */
|
||||
var parse_BrtCommentText = parse_RichStr;
|
||||
|
||||
/* [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) {
|
||||
switch(RT) {
|
||||
case 0x0278: /* 'BrtCommentAuthor' */
|
||||
authors.push(val); break;
|
||||
case 0x027B: /* 'BrtBeginComment' */
|
||||
c = val; break;
|
||||
case 0x027D: /* 'BrtCommentText' */
|
||||
c.t = val.t; c.h = val.h; c.r = val.r; break;
|
||||
case 0x027C: /* 'BrtEndComment' */
|
||||
switch(R.n) {
|
||||
case 'BrtCommentAuthor': authors.push(val); break;
|
||||
case 'BrtBeginComment': c = val; break;
|
||||
case 'BrtCommentText': c.t = val.t; c.h = val.h; c.r = val.r; break;
|
||||
case 'BrtEndComment':
|
||||
c.author = authors[c.iauthor];
|
||||
delete (c/*:any*/).iauthor;
|
||||
if(opts.sheetRows && c.rfx && opts.sheetRows <= c.rfx.r) break;
|
||||
if(!c.t) c.t = "";
|
||||
delete c.iauthor;
|
||||
if(opts.sheetRows && opts.sheetRows <= c.rfx.r) break;
|
||||
delete c.rfx; out.push(c); break;
|
||||
|
||||
case 0x0C00: /* 'BrtUid' */
|
||||
break;
|
||||
|
||||
case 0x0023: /* 'BrtFRTBegin' */
|
||||
pass = true; break;
|
||||
case 0x0024: /* 'BrtFRTEnd' */
|
||||
pass = false; break;
|
||||
case 0x0025: /* 'BrtACBegin' */ break;
|
||||
case 0x0026: /* 'BrtACEnd' */ break;
|
||||
|
||||
|
||||
default:
|
||||
if(R.T){/* empty */}
|
||||
else if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
|
||||
case 'BrtBeginComments': break;
|
||||
case 'BrtEndComments': break;
|
||||
case 'BrtBeginCommentAuthors': break;
|
||||
case 'BrtEndCommentAuthors': break;
|
||||
case 'BrtBeginCommentList': break;
|
||||
case 'BrtEndCommentList': break;
|
||||
default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
|
||||
}
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
});
|
||||
});
|
||||
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, 0x027A /* BrtEndCommentList */);
|
||||
|
||||
write_record(ba, 0x0275 /* BrtEndComments */);
|
||||
return ba.end();
|
||||
}
|
||||
function write_comments_bin(data, opts) { }
|
||||
|
@ -1,21 +0,0 @@
|
||||
var CT_VBA = "application/vnd.ms-office.vbaProject";
|
||||
function make_vba_xls(cfb) {
|
||||
var newcfb = CFB.utils.cfb_new({ root: "R" });
|
||||
cfb.FullPaths.forEach(function(p, i) {
|
||||
if (p.slice(-1) === "/" || !p.match(/_VBA_PROJECT_CUR/))
|
||||
return;
|
||||
var newpath = p.replace(/^[^\/]*/, "R").replace(/\/_VBA_PROJECT_CUR\u0000*/, "");
|
||||
CFB.utils.cfb_add(newcfb, newpath, cfb.FileIndex[i].content);
|
||||
});
|
||||
return CFB.write(newcfb);
|
||||
}
|
||||
function fill_vba_xls(cfb, vba) {
|
||||
vba.FullPaths.forEach(function(p, i) {
|
||||
if (i == 0)
|
||||
return;
|
||||
var newpath = p.replace(/^[\/]*[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
|
||||
if (newpath.slice(-1) !== "/")
|
||||
CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content);
|
||||
});
|
||||
}
|
||||
var VBAFMTS = ["xlsb", "xlsm", "xlam", "biff8", "xla"];
|
@ -1,5 +0,0 @@
|
||||
/* 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'}; }
|
@ -1,63 +1,17 @@
|
||||
/* 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 rcbase/*:Cell*/ = ({r:0,c:0}/*:any*/);
|
||||
function rcfunc($$,$1,$2,$3) {
|
||||
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;
|
||||
return $1 + (cRel ? "" : "$") + encode_col(C) + (rRel ? "" : "$") + encode_row(R);
|
||||
var rc_to_a1 = (function(){
|
||||
var rcregex = /(^|[^A-Za-z])R(\[?)(-?\d+|)\]?C(\[?)(-?\d+|)\]?/g;
|
||||
var rcbase;
|
||||
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;
|
||||
if($4.length > 0) C += rcbase.c;
|
||||
if($2.length > 0) R += rcbase.r;
|
||||
return $1 + encode_col(C) + encode_row(R);
|
||||
}
|
||||
return function rc_to_a1(fstr/*:string*/, base/*:Cell*/)/*:string*/ {
|
||||
return function rc_to_a1(fstr, base) {
|
||||
rcbase = base;
|
||||
return fstr.replace(rcregex, rcfunc);
|
||||
};
|
||||
})();
|
||||
|
||||
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;
|
||||
});
|
||||
};
|
||||
})();
|
||||
|
||||
/* 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 $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
|
||||
});
|
||||
}
|
||||
|
||||
function shift_formula_xlsx(f/*:string*/, range/*:string*/, cell/*:string*/)/*:string*/ {
|
||||
var r = decode_range(range), s = r.s, c = decode_cell(cell);
|
||||
var delta = {r:c.r - s.r, c:c.c - s.c};
|
||||
return shift_formula_str(f, delta);
|
||||
}
|
||||
|
||||
/* TODO: parse formula */
|
||||
function fuzzyfmla(f/*:string*/)/*:boolean*/ {
|
||||
if(f.length == 1) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function _xlfn(f/*:string*/)/*:string*/ {
|
||||
return f.replace(/_xlfn\./g,"");
|
||||
}
|
||||
|
1198
bits/62_fxls.js
1198
bits/62_fxls.js
File diff suppressed because it is too large
Load Diff
332
bits/63_fbin.js
332
bits/63_fbin.js
@ -1,331 +1,5 @@
|
||||
/* [MS-XLS] 2.5.198.1 TODO */
|
||||
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];
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.5.198.3 TODO */
|
||||
function parse_XLSCellParsedFormula(blob, length, opts) {
|
||||
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];
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.5.198.21 */
|
||||
function parse_NameParsedFormula(blob, length, opts, cce) {
|
||||
var target = blob.l + length;
|
||||
var rgce = parse_Rgce(blob, cce, opts);
|
||||
var rgcb;
|
||||
if(target !== blob.l) rgcb = parse_RgbExtra(blob, target - blob.l, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.5.198.118 TODO */
|
||||
function parse_SharedParsedFormula(blob, length, opts) {
|
||||
var target = blob.l + length;
|
||||
var rgcb, cce = blob.read_shift(2); // length of rgce
|
||||
var rgce = parse_Rgce(blob, cce, opts);
|
||||
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
|
||||
if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.5.133 TODO: how to emit empty strings? */
|
||||
function parse_FormulaValue(blob/*::, length*/) {
|
||||
var b;
|
||||
if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return [parse_Xnum(blob),'n'];
|
||||
switch(blob[blob.l]) {
|
||||
case 0x00: blob.l += 8; return ["String", 's'];
|
||||
case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return [b,'b'];
|
||||
case 0x02: b = blob[blob.l+2]; blob.l += 8; return [b,'e'];
|
||||
case 0x03: blob.l += 8; return ["",'s'];
|
||||
}
|
||||
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 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 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) {
|
||||
/* [MS-XLSB] 2.5.97.4 CellParsedFormula TODO: use similar logic to js-xls */
|
||||
function parse_XLSBCellParsedFormula(data, length) {
|
||||
var cce = data.read_shift(4);
|
||||
var rgce = parse_Rgce(data, cce, opts);
|
||||
var cb = data.read_shift(4);
|
||||
var rgcb = cb > 0 ? parse_RgbExtra(data, cb, rgce, opts) : null;
|
||||
return [rgce, rgcb];
|
||||
return parsenoop(data, length-4);
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.97.1 ArrayParsedFormula */
|
||||
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;
|
||||
|
2213
bits/64_ftab.js
2213
bits/64_ftab.js
File diff suppressed because it is too large
Load Diff
@ -1,36 +0,0 @@
|
||||
/* Part 3 TODO: actually parse formulae */
|
||||
function ods_to_csf_formula(f/*:string*/)/*:string*/ {
|
||||
if(f.slice(0,3) == "of:") f = f.slice(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.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,";");
|
||||
}
|
||||
|
||||
function csf_to_ods_formula(f/*:string*/)/*:string*/ {
|
||||
var o = "of:=" + f.replace(crefregex, "$1[.$2$3$4$5]").replace(/\]:\[/g,":");
|
||||
/* TODO: something other than this */
|
||||
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; });
|
||||
var a = r.split(":");
|
||||
var s = a[0].split(".")[0];
|
||||
return [s, a[0].split(".")[1] + (a.length > 1 ? (":" + (a[1].split(".")[1] || a[1].split(".")[0])) : "")];
|
||||
}
|
||||
|
||||
function csf_to_ods_3D(r/*:string*/)/*:string*/ {
|
||||
return r.replace(/!/,".").replace(/:/, ":.");
|
||||
}
|
||||
|
@ -1,128 +1,84 @@
|
||||
var strs = {}; // shared strings
|
||||
var _ssfopts = {}; // spreadsheet formatting options
|
||||
|
||||
RELS.WS = "http://schemas.openxmlformats.org/officeDocument/2006/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, str) {
|
||||
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) {
|
||||
var p = ({min:C+1,max:C+1}/*:any*/);
|
||||
/* wch (chars), wpx (pixels) */
|
||||
var wch = -1;
|
||||
if(col.MDW) MDW = col.MDW;
|
||||
if(col.width != null) p.customWidth = 1;
|
||||
else if(col.wpx != null) wch = px2char(col.wpx);
|
||||
else if(col.wch != null) wch = col.wch;
|
||||
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;
|
||||
function get_cell_style(styles, cell, opts) {
|
||||
if (typeof style_builder != 'undefined') {
|
||||
if (/^\d+$/.exec(cell.s)) { return cell.s} // if its already an integer index, let it be
|
||||
if (cell.s && (cell.s == +cell.s)) { return cell.s} // if its already an integer index, let it be
|
||||
var s = cell.s || {};
|
||||
if (cell.z) s.numFmt = cell.z;
|
||||
return style_builder.addStyle(s);
|
||||
}
|
||||
else {
|
||||
var z = opts.revssf[cell.z != null ? cell.z : "General"];
|
||||
for(var i = 0, len = styles.length; i != len; ++i) if(styles[i].numFmtId === z) return i;
|
||||
styles[len] = {
|
||||
numFmtId:z,
|
||||
fontId:0,
|
||||
fillId:0,
|
||||
borderId:0,
|
||||
xfId:0,
|
||||
applyNumberFormat:1
|
||||
};
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
function default_margins(margins/*:Margins*/, mode/*:?string*/) {
|
||||
if(!margins) return;
|
||||
var defs = [0.7, 0.7, 0.75, 0.75, 0.3, 0.3];
|
||||
if(mode == 'xlml') defs = [1, 1, 1, 1, 0.5, 0.5];
|
||||
if(margins.left == null) margins.left = defs[0];
|
||||
if(margins.right == null) margins.right = defs[1];
|
||||
if(margins.top == null) margins.top = defs[2];
|
||||
if(margins.bottom == null) margins.bottom = defs[3];
|
||||
if(margins.header == null) margins.header = defs[4];
|
||||
if(margins.footer == null) margins.footer = defs[5];
|
||||
function get_cell_style_csf(cellXf) {
|
||||
|
||||
if (cellXf) {
|
||||
|
||||
var s = {}
|
||||
|
||||
if (typeof cellXf.numFmtId != undefined) {
|
||||
s.numFmt = SSF._table[cellXf.numFmtId];
|
||||
}
|
||||
|
||||
if(cellXf.fillId) {
|
||||
s.fill = styles.Fills[cellXf.fillId];
|
||||
}
|
||||
|
||||
if (cellXf.fontId) {
|
||||
s.font = styles.Fonts[cellXf.fontId];
|
||||
}
|
||||
if (cellXf.borderId) {
|
||||
s.border = styles.Borders[cellXf.borderId];
|
||||
}
|
||||
if (cellXf.applyAlignment==1) {
|
||||
s.alignment = cellXf.alignment;
|
||||
}
|
||||
|
||||
|
||||
return JSON.parse(JSON.stringify(s));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function get_cell_style(styles/*:Array<any>*/, cell/*: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
|
||||
opts.ssf[i] = cell.z;
|
||||
opts.revssf[cell.z] = z = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(i = 0; i != len; ++i) if(styles[i].numFmtId === z) return i;
|
||||
styles[len] = {
|
||||
numFmtId:z,
|
||||
fontId:0,
|
||||
fillId:0,
|
||||
borderId:0,
|
||||
xfId:0,
|
||||
applyNumberFormat:1
|
||||
};
|
||||
return len;
|
||||
}
|
||||
|
||||
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles, date1904) {
|
||||
function safe_format(p, fmtid, fillid, opts) {
|
||||
try {
|
||||
if(opts.cellNF) p.z = table_fmt[fmtid];
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
if(p.t === 'z' && !opts.cellStyles) return;
|
||||
if(p.t === 'd' && typeof p.v === 'string') p.v = parseDate(p.v);
|
||||
if((!opts || opts.cellText !== false) && p.t !== 'z') try {
|
||||
if(table_fmt[fmtid] == null) SSF__load(SSFImplicit[fmtid] || "General", fmtid);
|
||||
if(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,_ssfopts);
|
||||
else p.w = SSF._general_num(p.v,_ssfopts);
|
||||
}
|
||||
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,_ssfopts);
|
||||
else p.w = SSF._general_num(dd,_ssfopts);
|
||||
}
|
||||
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);
|
||||
if(opts.cellNF) p.z = SSF._table[fmtid];
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
if(!opts.cellStyles) return;
|
||||
if(fillid != null) try {
|
||||
p.s = styles.Fills[fillid];
|
||||
if (p.s.fgColor && p.s.fgColor.theme && !p.s.fgColor.rgb) {
|
||||
p.s.fgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.fgColor.theme].rgb, p.s.fgColor.tint || 0);
|
||||
if(opts.WTF) p.s.fgColor.raw_rgb = themes.themeElements.clrScheme[p.s.fgColor.theme].rgb;
|
||||
}
|
||||
if (p.s.bgColor && p.s.bgColor.theme) {
|
||||
p.s.bgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.bgColor.theme].rgb, p.s.bgColor.tint || 0);
|
||||
if(opts.WTF) p.s.bgColor.raw_rgb = themes.themeElements.clrScheme[p.s.bgColor.theme].rgb;
|
||||
}
|
||||
} 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']);
|
||||
}
|
||||
}
|
||||
|
1043
bits/67_wsxml.js
1043
bits/67_wsxml.js
File diff suppressed because it is too large
Load Diff
1058
bits/68_wsbin.js
1058
bits/68_wsbin.js
File diff suppressed because it is too large
Load Diff
@ -1,48 +0,0 @@
|
||||
function parse_Cache(data/*:string*/)/*:[Array<number|string>, string, ?string]*/ {
|
||||
var col/*:Array<number|string>*/ = [];
|
||||
var num = data.match(/^<c:numCache>/);
|
||||
var f;
|
||||
|
||||
/* 21.2.2.150 pt CT_NumVal */
|
||||
(data.match(/<c:pt idx="(\d*)"[^<>\/]*><c:v>([^<])<\/c:v><\/c:pt>/mg)||[]).forEach(function(pt) {
|
||||
var q = pt.match(/<c:pt idx="(\d*)"[^<>\/]*><c:v>([^<]*)<\/c:v><\/c:pt>/);
|
||||
if(!q) return;
|
||||
col[+q[1]] = num ? +q[2] : q[2];
|
||||
});
|
||||
|
||||
/* 21.2.2.71 formatCode CT_Xstring */
|
||||
var nf = unescapexml((str_match_xml(data, "c:formatCode") || ["","General"])[1]);
|
||||
|
||||
(str_match_ng(data, "<c:f>", "</c:f>")||[]).forEach(function(F) { f = F.replace(/<[^<>]*>/g,""); });
|
||||
|
||||
return [col, nf, f];
|
||||
}
|
||||
|
||||
/* 21.2 DrawingML - Charts */
|
||||
function parse_chart(data/*:?string*/, name/*:string*/, opts, rels, wb, csheet) {
|
||||
var cs/*:Worksheet*/ = ((csheet || {"!type":"chart"})/*:any*/);
|
||||
if(!data) return csheet;
|
||||
/* 21.2.2.27 chart CT_Chart */
|
||||
|
||||
var C = 0, R = 0, col = "A";
|
||||
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);
|
||||
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] };
|
||||
R = i;
|
||||
});
|
||||
if(refguess.e.r < R) refguess.e.r = R;
|
||||
++C;
|
||||
});
|
||||
if(C > 0) cs["!ref"] = encode_range(refguess);
|
||||
return cs;
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
/* 18.3 Worksheets also covers Chartsheets */
|
||||
function parse_cs_xml(data/*:?string*/, opts, idx/*:number*/, 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 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']];
|
||||
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 };
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.7 Chart Sheet */
|
||||
function parse_cs_bin(data, opts, idx/*:number*/, 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 pass = false;
|
||||
recordhopper(data, function cs_parse(val, R, 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 0x0232: /* 'BrtBkHim' */
|
||||
case 0x028C: /* 'BrtCsPageSetup' */
|
||||
case 0x029D: /* 'BrtCsProtection' */
|
||||
case 0x02A7: /* 'BrtCsProtectionIso' */
|
||||
case 0x0227: /* 'BrtLegacyDrawing' */
|
||||
case 0x0228: /* 'BrtLegacyDrawingHF' */
|
||||
case 0x01DC: /* 'BrtMargins' */
|
||||
case 0x0C00: /* 'BrtUid' */
|
||||
break;
|
||||
|
||||
case 0x0023: /* 'BrtFRTBegin' */
|
||||
pass = true; break;
|
||||
case 0x0024: /* 'BrtFRTEnd' */
|
||||
pass = false; break;
|
||||
case 0x0025: /* 'BrtACBegin' */
|
||||
state.push(RT); 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));
|
||||
}
|
||||
}, opts);
|
||||
|
||||
if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
|
||||
return s;
|
||||
}
|
||||
//function write_cs_bin(/*::idx:number, opts, wb:Workbook, rels*/) {
|
||||
// var ba = buf_array();
|
||||
// write_record(ba, 0x0081 /* BrtBeginSheet */);
|
||||
// /* [BrtCsProp] */
|
||||
// /* CSVIEWS */
|
||||
// /* [[BrtCsProtectionIso] BrtCsProtection] */
|
||||
// /* [USERCSVIEWS] */
|
||||
// /* [BrtMargins] */
|
||||
// /* [BrtCsPageSetup] */
|
||||
// /* [HEADERFOOTER] */
|
||||
// /* BrtDrawing */
|
||||
// /* [BrtLegacyDrawing] */
|
||||
// /* [BrtLegacyDrawingHF] */
|
||||
// /* [BrtBkHim] */
|
||||
// /* [WEBPUBITEMS] */
|
||||
// /* FRTCHARTSHEET */
|
||||
// write_record(ba, 0x0082 /* BrtEndSheet */);
|
||||
// return ba.end();
|
||||
//}
|
@ -1,158 +0,0 @@
|
||||
/* 18.2.28 (CT_WorkbookProtection) Defaults */
|
||||
var WBPropsDef = [
|
||||
['allowRefreshQuery', false, "bool"],
|
||||
['autoCompressPictures', true, "bool"],
|
||||
['backupFile', false, "bool"],
|
||||
['checkCompatibility', false, "bool"],
|
||||
['CodeName', ''],
|
||||
['date1904', false, "bool"],
|
||||
['defaultThemeVersion', 0, "int"],
|
||||
['filterPrivacy', false, "bool"],
|
||||
['hidePivotFieldList', false, "bool"],
|
||||
['promptedSolutions', false, "bool"],
|
||||
['publishItems', false, "bool"],
|
||||
['refreshAllConnections', false, "bool"],
|
||||
['saveExternalLinkValues', true, "bool"],
|
||||
['showBorderUnselectedTables', true, "bool"],
|
||||
['showInkAnnotation', true, "bool"],
|
||||
['showObjects', 'all'],
|
||||
['showPivotChartFilter', false, "bool"],
|
||||
['updateLinks', 'userSet']
|
||||
];
|
||||
|
||||
/* 18.2.30 (CT_BookView) Defaults */
|
||||
var WBViewDef = [
|
||||
['activeTab', 0, "int"],
|
||||
['autoFilterDateGrouping', true, "bool"],
|
||||
['firstSheet', 0, "int"],
|
||||
['minimized', false, "bool"],
|
||||
['showHorizontalScroll', true, "bool"],
|
||||
['showSheetTabs', true, "bool"],
|
||||
['showVerticalScroll', true, "bool"],
|
||||
['tabRatio', 600, "int"],
|
||||
['visibility', 'visible']
|
||||
//window{Height,Width}, {x,y}Window
|
||||
];
|
||||
|
||||
/* 18.2.19 (CT_Sheet) Defaults */
|
||||
var SheetDef = [
|
||||
//['state', 'visible']
|
||||
];
|
||||
|
||||
/* 18.2.2 (CT_CalcPr) Defaults */
|
||||
var CalcPrDef = [
|
||||
['calcCompleted', 'true'],
|
||||
['calcMode', 'auto'],
|
||||
['calcOnSave', 'true'],
|
||||
['concurrentCalc', 'true'],
|
||||
['fullCalcOnLoad', 'false'],
|
||||
['fullPrecision', 'true'],
|
||||
['iterate', 'false'],
|
||||
['iterateCount', '100'],
|
||||
['iterateDelta', '0.001'],
|
||||
['refMode', 'A1']
|
||||
];
|
||||
|
||||
/* 18.2.3 (CT_CustomWorkbookView) Defaults */
|
||||
/*var CustomWBViewDef = [
|
||||
['autoUpdate', 'false'],
|
||||
['changesSavedWin', 'false'],
|
||||
['includeHiddenRowCol', 'true'],
|
||||
['includePrintSettings', 'true'],
|
||||
['maximized', 'false'],
|
||||
['minimized', 'false'],
|
||||
['onlySync', 'false'],
|
||||
['personalView', 'false'],
|
||||
['showComments', 'commIndicator'],
|
||||
['showFormulaBar', 'true'],
|
||||
['showHorizontalScroll', 'true'],
|
||||
['showObjects', 'all'],
|
||||
['showSheetTabs', 'true'],
|
||||
['showStatusbar', 'true'],
|
||||
['showVerticalScroll', 'true'],
|
||||
['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 "int": if(typeof w[z[0]] == "string") w[z[0]] = parseInt(w[z[0]], 10); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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 "int": if(typeof target[z[0]] == "string") target[z[0]] = parseInt(target[z[0]], 10); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parse_wb_defaults(wb) {
|
||||
push_defaults(wb.WBProps, WBPropsDef);
|
||||
push_defaults(wb.CalcPr, CalcPrDef);
|
||||
|
||||
push_defaults_array(wb.WBView, WBViewDef);
|
||||
push_defaults_array(wb.Sheets, SheetDef);
|
||||
|
||||
_ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904);
|
||||
}
|
||||
|
||||
function safe1904(wb/*:Workbook*/)/*:string*/ {
|
||||
/* TODO: store date1904 somewhere else */
|
||||
if(!wb.Workbook) return "false";
|
||||
if(!wb.Workbook.WBProps) return "false";
|
||||
return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false";
|
||||
}
|
||||
|
||||
var badchars = /*#__PURE__*/":][*?\/\\".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;
|
||||
}
|
||||
function check_wb_names(N, S, codes) {
|
||||
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});
|
||||
});
|
||||
/* TODO: validate workbook */
|
||||
}
|
247
bits/72_wbxml.js
247
bits/72_wbxml.js
@ -1,247 +0,0 @@
|
||||
/* 18.2 Workbook */
|
||||
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 pass = false, xmlns = "xmlns";
|
||||
var dname = {}, dnstart = 0;
|
||||
data.replace(tagregex, function xml_wb(x, idx) {
|
||||
var y/*:any*/ = parsexmltag(x);
|
||||
switch(strip_ns(y[0])) {
|
||||
case '<?xml': break;
|
||||
|
||||
/* 18.2.27 workbook CT_Workbook 1 */
|
||||
case '<workbook':
|
||||
if(x.match(wbnsregex)) xmlns = "xmlns" + x.match(/<(\w+):/)[1];
|
||||
wb.xmlns = y[xmlns];
|
||||
break;
|
||||
case '</workbook>': break;
|
||||
|
||||
/* 18.2.13 fileVersion CT_FileVersion ? */
|
||||
case '<fileVersion': delete y[0]; wb.AppVersion = y; break;
|
||||
case '<fileVersion/>': case '</fileVersion>': break;
|
||||
|
||||
/* 18.2.12 fileSharing CT_FileSharing ? */
|
||||
case '<fileSharing':
|
||||
break;
|
||||
case '<fileSharing/>': break;
|
||||
|
||||
/* 18.2.28 workbookPr CT_WorkbookPr ? */
|
||||
case '<workbookPr':
|
||||
case '<workbookPr/>':
|
||||
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 "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;
|
||||
|
||||
/* 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>': break;
|
||||
|
||||
/* 18.2.20 sheets CT_Sheets 1 */
|
||||
case '<sheets': case '<sheets>': case '</sheets>': break; // aggregate sheet
|
||||
/* 18.2.19 sheet CT_Sheet + */
|
||||
case '<sheet':
|
||||
switch(y.state) {
|
||||
case "hidden": y.Hidden = 1; break;
|
||||
case "veryHidden": y.Hidden = 2; break;
|
||||
default: y.Hidden = 0;
|
||||
}
|
||||
delete y.state;
|
||||
y.name = unescapexml(utf8read(y.name));
|
||||
delete y[0]; wb.Sheets.push(y); break;
|
||||
case '</sheet>': break;
|
||||
|
||||
/* 18.2.15 functionGroups CT_FunctionGroups ? */
|
||||
case '<functionGroups': case '<functionGroups/>': break;
|
||||
/* 18.2.14 functionGroup CT_FunctionGroup + */
|
||||
case '<functionGroup': break;
|
||||
|
||||
/* 18.2.9 externalReferences CT_ExternalReferences ? */
|
||||
case '<externalReferences': case '</externalReferences>': case '<externalReferences>': break;
|
||||
/* 18.2.8 externalReference CT_ExternalReference + */
|
||||
case '<externalReference': break;
|
||||
|
||||
/* 18.2.6 definedNames CT_DefinedNames ? */
|
||||
case '<definedNames/>': break;
|
||||
case '<definedNames>': case '<definedNames': pass=true; break;
|
||||
case '</definedNames>': pass=false; break;
|
||||
/* 18.2.5 definedName CT_DefinedName + */
|
||||
case '<definedName': {
|
||||
dname = {};
|
||||
dname.Name = utf8read(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)));
|
||||
wb.Names.push(dname);
|
||||
} break;
|
||||
case '<definedName/>': break;
|
||||
|
||||
/* 18.2.2 calcPr CT_CalcPr ? */
|
||||
case '<calcPr': delete y[0]; wb.CalcPr = y; break;
|
||||
case '<calcPr/>': delete y[0]; wb.CalcPr = y; break;
|
||||
case '</calcPr>': break;
|
||||
|
||||
/* 18.2.16 oleSize CT_OleSize ? (ref required) */
|
||||
case '<oleSize': break;
|
||||
|
||||
/* 18.2.4 customWorkbookViews CT_CustomWorkbookViews ? */
|
||||
case '<customWorkbookViews>': case '</customWorkbookViews>': case '<customWorkbookViews': break;
|
||||
/* 18.2.3 customWorkbookView CT_CustomWorkbookView + */
|
||||
case '<customWorkbookView': case '</customWorkbookView>': break;
|
||||
|
||||
/* 18.2.18 pivotCaches CT_PivotCaches ? */
|
||||
case '<pivotCaches>': case '</pivotCaches>': case '<pivotCaches': break;
|
||||
/* 18.2.17 pivotCache CT_PivotCache ? */
|
||||
case '<pivotCache': break;
|
||||
|
||||
/* 18.2.21 smartTagPr CT_SmartTagPr ? */
|
||||
case '<smartTagPr': case '<smartTagPr/>': break;
|
||||
|
||||
/* 18.2.23 smartTagTypes CT_SmartTagTypes ? */
|
||||
case '<smartTagTypes': case '<smartTagTypes>': case '</smartTagTypes>': break;
|
||||
/* 18.2.22 smartTagType CT_SmartTagType ? */
|
||||
case '<smartTagType': break;
|
||||
|
||||
/* 18.2.24 webPublishing CT_WebPublishing ? */
|
||||
case '<webPublishing': case '<webPublishing/>': break;
|
||||
|
||||
/* 18.2.11 fileRecoveryPr CT_FileRecoveryPr ? */
|
||||
case '<fileRecoveryPr': case '<fileRecoveryPr/>': break;
|
||||
|
||||
/* 18.2.26 webPublishObjects CT_WebPublishObjects ? */
|
||||
case '<webPublishObjects>': case '<webPublishObjects': case '</webPublishObjects>': break;
|
||||
/* 18.2.25 webPublishObject CT_WebPublishObject ? */
|
||||
case '<webPublishObject': 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; //TODO: check with versions of excel
|
||||
case '</ext>': pass=false; break;
|
||||
|
||||
/* Others */
|
||||
case '<ArchID': break;
|
||||
case '<AlternateContent':
|
||||
case '<AlternateContent>': pass=true; break;
|
||||
case '</AlternateContent>': pass=false; break;
|
||||
|
||||
/* TODO */
|
||||
case '<revisionPtr': break;
|
||||
|
||||
default: if(!pass && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in workbook');
|
||||
}
|
||||
return x;
|
||||
});
|
||||
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 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
|
||||
});
|
||||
|
||||
var write_names = (wb.Workbook && (wb.Workbook.Names||[]).length > 0);
|
||||
|
||||
/* fileVersion */
|
||||
/* fileSharing */
|
||||
|
||||
var workbookPr/*:any*/ = ({codeName:"ThisWorkbook"}/*:any*/);
|
||||
if(wb.Workbook && wb.Workbook.WBProps) {
|
||||
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>";
|
||||
}
|
||||
|
||||
o[o.length] = "<sheets>";
|
||||
for(i = 0; i != wb.SheetNames.length; ++i) {
|
||||
var sht = ({name:escapexml(wb.SheetNames[i].slice(0,31))}/*:any*/);
|
||||
sht.sheetId = ""+(i+1);
|
||||
sht["r:id"] = "rId"+(i+1);
|
||||
if(sheets[i]) switch(sheets[i].Hidden) {
|
||||
case 1: sht.state = "hidden"; break;
|
||||
case 2: sht.state = "veryHidden"; break;
|
||||
}
|
||||
o[o.length] = (writextag('sheet',null,sht));
|
||||
}
|
||||
o[o.length] = "</sheets>";
|
||||
|
||||
/* functionGroups */
|
||||
/* externalReferences */
|
||||
|
||||
if(write_names) {
|
||||
o[o.length] = "<definedNames>";
|
||||
if(wb.Workbook && wb.Workbook.Names) wb.Workbook.Names.forEach(function(n) {
|
||||
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] = "</definedNames>";
|
||||
}
|
||||
|
||||
/* calcPr */
|
||||
/* oleSize */
|
||||
/* customWorkbookViews */
|
||||
/* pivotCaches */
|
||||
/* smartTagPr */
|
||||
/* smartTagTypes */
|
||||
/* webPublishing */
|
||||
/* fileRecoveryPr */
|
||||
/* webPublishObjects */
|
||||
/* extLst */
|
||||
|
||||
if(o.length>2){ o[o.length] = '</workbook>'; o[1]=o[1].replace("/>",">"); }
|
||||
return o.join("");
|
||||
}
|
362
bits/73_wbbin.js
362
bits/73_wbbin.js
@ -1,362 +0,0 @@
|
||||
/* [MS-XLSB] 2.4.304 BrtBundleSh */
|
||||
function parse_BrtBundleSh(data, length/*:number*/) {
|
||||
var z = {};
|
||||
z.Hidden = data.read_shift(4); //hsState ST_SheetState
|
||||
z.iTabID = data.read_shift(4);
|
||||
z.strRelID = parse_RelID(data,length-8);
|
||||
z.name = parse_XLWideString(data);
|
||||
return z;
|
||||
}
|
||||
function write_BrtBundleSh(data, o) {
|
||||
if(!o) o = new_buf(127);
|
||||
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);
|
||||
return o.length > o.l ? o.slice(0, o.l) : o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.815 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;
|
||||
o.autoCompressPictures = !!(flags & 0x10000);
|
||||
o.backupFile = !!(flags & 0x40);
|
||||
o.checkCompatibility = !!(flags & 0x1000);
|
||||
o.date1904 = !!(flags & 0x01);
|
||||
o.filterPrivacy = !!(flags & 0x08);
|
||||
o.hidePivotFieldList = !!(flags & 0x400);
|
||||
o.promptedSolutions = !!(flags & 0x10);
|
||||
o.publishItems = !!(flags & 0x800);
|
||||
o.refreshAllConnections = !!(flags & 0x40000);
|
||||
o.saveExternalLinkValues = !!(flags & 0x80);
|
||||
o.showBorderUnselectedTables = !!(flags & 0x04);
|
||||
o.showInkAnnotation = !!(flags & 0x20);
|
||||
o.showObjects = ["all", "placeholders", "none"][(flags >> 13) & 0x03];
|
||||
o.showPivotChartFilter = !!(flags & 0x8000);
|
||||
o.updateLinks = ["userSet", "never", "always"][(flags >> 8) & 0x03];
|
||||
return o;
|
||||
}
|
||||
function write_BrtWbProp(data/*:?WBProps*/, o) {
|
||||
if(!o) o = new_buf(72);
|
||||
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);
|
||||
return o.slice(0, o.l);
|
||||
}
|
||||
|
||||
function parse_BrtFRTArchID$(data, length) {
|
||||
var o = {};
|
||||
data.read_shift(4);
|
||||
o.ArchID = data.read_shift(4);
|
||||
data.l += length - 8;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.687 BrtName */
|
||||
function parse_BrtName(data, length, opts) {
|
||||
var end = data.l + length;
|
||||
var flags = data.read_shift(4);
|
||||
data.l += 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;
|
||||
//if(0 /* fProc */) {
|
||||
// unusedstring1: XLNullableWideString
|
||||
// description: XLNullableWideString
|
||||
// helpTopic: XLNullableWideString
|
||||
// unusedstring2: XLNullableWideString
|
||||
//}
|
||||
data.l = end;
|
||||
var out = ({Name:name, Ptg:formula, Flags: flags}/*:any*/);
|
||||
if(itab < 0xFFFFFFF) out.Sheet = itab;
|
||||
if(comment) out.Comment = comment;
|
||||
return out;
|
||||
}
|
||||
function write_BrtName(name, wb) {
|
||||
var o = new_buf(9);
|
||||
var flags = 0;
|
||||
var dname = name.Name;
|
||||
if(XLSLblBuiltIn.indexOf(dname) > -1) { flags |= 0x20; dname = dname.slice(6); }
|
||||
o.write_shift(4, flags); // flags
|
||||
o.write_shift(1, 0); // chKey
|
||||
o.write_shift(4, name.Sheet == null ? 0xFFFFFFFF : name.Sheet);
|
||||
|
||||
var arr = [
|
||||
o,
|
||||
write_XLWideString(dname),
|
||||
write_XLSBNameParsedFormula(name.Ref, wb)
|
||||
];
|
||||
if(name.Comment) arr.push(write_XLNullableWideString(name.Comment));
|
||||
else {
|
||||
var x = new_buf(4);
|
||||
x.write_shift(4, 0xFFFFFFFF);
|
||||
arr.push(x);
|
||||
}
|
||||
|
||||
// if macro (flags & 0x0F):
|
||||
// write_shift(4, 0xFFFFFFFF);
|
||||
// write_XLNullableWideString(description)
|
||||
// write_XLNullableWideString(helpTopic)
|
||||
// write_shift(4, 0xFFFFFFFF);
|
||||
|
||||
return bconcat(arr);
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.61 Workbook */
|
||||
function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
|
||||
var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
|
||||
var state/*:Array<string>*/ = [];
|
||||
var pass = false;
|
||||
|
||||
if(!opts) opts = {};
|
||||
opts.biff = 12;
|
||||
|
||||
var Names = [];
|
||||
var supbooks = ([[]]/*:any*/);
|
||||
supbooks.SheetNames = [];
|
||||
supbooks.XTI = [];
|
||||
|
||||
XLSBRecordEnum[0x0010] = { n:"BrtFRTArchID$", f:parse_BrtFRTArchID$ };
|
||||
|
||||
recordhopper(data, function hopper_wb(val, R, RT) {
|
||||
switch(RT) {
|
||||
case 0x009C: /* 'BrtBundleSh' */
|
||||
supbooks.SheetNames.push(val.name);
|
||||
wb.Sheets.push(val); break;
|
||||
|
||||
case 0x0099: /* 'BrtWbProp' */
|
||||
wb.WBProps = val; break;
|
||||
|
||||
case 0x0027: /* 'BrtName' */
|
||||
if(val.Sheet != null) opts.SID = val.Sheet;
|
||||
val.Ref = val.Ptg ? stringify_formula(val.Ptg, null, null, supbooks, opts) : "#REF!";
|
||||
delete opts.SID;
|
||||
delete val.Ptg;
|
||||
Names.push(val);
|
||||
break;
|
||||
case 0x040C: /* 'BrtNameExt' */ break;
|
||||
|
||||
case 0x0165: /* 'BrtSupSelf' */
|
||||
case 0x0166: /* 'BrtSupSame' */
|
||||
case 0x0163: /* 'BrtSupBookSrc' */
|
||||
case 0x029B: /* 'BrtSupAddin' */
|
||||
if(!supbooks[0].length) supbooks[0] = [RT, val];
|
||||
else supbooks.push([RT, val]);
|
||||
supbooks[supbooks.length - 1].XTI = [];
|
||||
break;
|
||||
case 0x016A: /* 'BrtExternSheet' */
|
||||
if(supbooks.length === 0) { supbooks[0] = []; supbooks[0].XTI = []; }
|
||||
supbooks[supbooks.length - 1].XTI = supbooks[supbooks.length - 1].XTI.concat(val);
|
||||
supbooks.XTI = supbooks.XTI.concat(val);
|
||||
break;
|
||||
case 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 0x0216: /* 'BrtBookProtection' */
|
||||
case 0x02A5: /* 'BrtBookProtectionIso' */
|
||||
case 0x009D: /* 'BrtCalcProp' */
|
||||
case 0x0262: /* 'BrtCrashRecErr' */
|
||||
case 0x0802: /* 'BrtDecoupledPivotCacheID' */
|
||||
case 0x009B: /* 'BrtFileRecover' */
|
||||
case 0x0224: /* 'BrtFileSharing' */
|
||||
case 0x02A4: /* 'BrtFileSharingIso' */
|
||||
case 0x0080: /* 'BrtFileVersion' */
|
||||
case 0x0299: /* 'BrtFnGroup' */
|
||||
case 0x0850: /* 'BrtModelRelationship' */
|
||||
case 0x084D: /* 'BrtModelTable' */
|
||||
case 0x0225: /* 'BrtOleSize' */
|
||||
case 0x0805: /* 'BrtPivotTableRef' */
|
||||
case 0x0254: /* 'BrtSmartTagType' */
|
||||
case 0x081C: /* 'BrtTableSlicerCacheID' */
|
||||
case 0x081B: /* 'BrtTableSlicerCacheIDs' */
|
||||
case 0x0822: /* 'BrtTimelineCachePivotCacheID' */
|
||||
case 0x018D: /* 'BrtUserBookView' */
|
||||
case 0x009A: /* 'BrtWbFactoid' */
|
||||
case 0x045D: /* 'BrtWbProp14' */
|
||||
case 0x0229: /* 'BrtWebOpt' */
|
||||
case 0x082B: /* 'BrtWorkBookPr15' */
|
||||
break;
|
||||
|
||||
case 0x0023: /* 'BrtFRTBegin' */
|
||||
state.push(RT); 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;
|
||||
|
||||
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));
|
||||
}
|
||||
}, opts);
|
||||
|
||||
parse_wb_defaults(wb);
|
||||
|
||||
// $FlowIgnore
|
||||
wb.Names = Names;
|
||||
|
||||
(wb/*:any*/).supbooks = supbooks;
|
||||
return wb;
|
||||
}
|
||||
|
||||
function write_BUNDLESHS(ba, wb/*::, opts*/) {
|
||||
write_record(ba, 0x008F /* 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, 0x0090 /* BrtEndBundleShs */);
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.649 BrtFileVersion */
|
||||
function write_BrtFileVersion(data, o) {
|
||||
if(!o) o = new_buf(127);
|
||||
for(var i = 0; i != 4; ++i) o.write_shift(4, 0);
|
||||
write_XLWideString("SheetJS", o);
|
||||
write_XLWideString(XLSX.version, o);
|
||||
write_XLWideString(XLSX.version, o);
|
||||
write_XLWideString("7262", o);
|
||||
return o.length > o.l ? o.slice(0, o.l) : o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.301 BrtBookView */
|
||||
function write_BrtBookView(idx, o) {
|
||||
if(!o) o = new_buf(29);
|
||||
o.write_shift(-4, 0);
|
||||
o.write_shift(-4, 460);
|
||||
o.write_shift(4, 28800);
|
||||
o.write_shift(4, 17600);
|
||||
o.write_shift(4, 500);
|
||||
o.write_shift(4, idx);
|
||||
o.write_shift(4, idx);
|
||||
var flags = 0x78;
|
||||
o.write_shift(1, flags);
|
||||
return o.length > o.l ? o.slice(0, o.l) : o;
|
||||
}
|
||||
|
||||
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;
|
||||
var i = 0, vistab = -1, hidden = -1;
|
||||
for(; i < sheets.length; ++i) {
|
||||
if(!sheets[i] || !sheets[i].Hidden && vistab == -1) vistab = i;
|
||||
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));
|
||||
/* 1*(BrtBookView *FRT) */
|
||||
write_record(ba, 0x0088 /* BrtEndBookViews */);
|
||||
}
|
||||
|
||||
function write_BRTNAMES(ba, wb) {
|
||||
if(!wb.Workbook || !wb.Workbook.Names) return;
|
||||
wb.Workbook.Names.forEach(function(name) { try {
|
||||
if(name.Flags & 0x0e) return; // TODO: macro name write
|
||||
write_record(ba, 0x0027 /* BrtName */, write_BrtName(name, wb));
|
||||
} catch(e) {
|
||||
console.error("Could not serialize defined name " + JSON.stringify(name));
|
||||
} });
|
||||
}
|
||||
|
||||
function write_SELF_EXTERNS_xlsb(wb) {
|
||||
var L = wb.SheetNames.length;
|
||||
var o = new_buf(12 * L + 28);
|
||||
o.write_shift(4, L + 2);
|
||||
o.write_shift(4, 0); o.write_shift(4, -2); o.write_shift(4, -2); // workbook-level reference
|
||||
o.write_shift(4, 0); o.write_shift(4, -1); o.write_shift(4, -1); // #REF!...
|
||||
for(var i = 0; i < L; ++i) {
|
||||
o.write_shift(4, 0); o.write_shift(4, i); o.write_shift(4, i);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
function write_EXTERNALS_xlsb(ba, wb) {
|
||||
write_record(ba, 0x0161 /* BrtBeginExternals */);
|
||||
write_record(ba, 0x0165 /* BrtSupSelf */);
|
||||
write_record(ba, 0x016A /* BrtExternSheet */, write_SELF_EXTERNS_xlsb(wb, 0));
|
||||
write_record(ba, 0x0162 /* BrtEndExternals */);
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.305 BrtCalcProp */
|
||||
/*function write_BrtCalcProp(data, o) {
|
||||
if(!o) o = new_buf(26);
|
||||
o.write_shift(4,0); // force recalc
|
||||
o.write_shift(4,1);
|
||||
o.write_shift(4,0);
|
||||
write_Xnum(0, o);
|
||||
o.write_shift(-4, 1023);
|
||||
o.write_shift(1, 0x33);
|
||||
o.write_shift(1, 0x00);
|
||||
return o;
|
||||
}*/
|
||||
|
||||
/* [MS-XLSB] 2.4.646 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 */
|
||||
function write_wb_bin(wb, opts) {
|
||||
var ba = buf_array();
|
||||
write_record(ba, 0x0083 /* BrtBeginBook */);
|
||||
write_record(ba, 0x0080 /* BrtFileVersion */, write_BrtFileVersion());
|
||||
/* [[BrtFileSharingIso] BrtFileSharing] */
|
||||
write_record(ba, 0x0099 /* 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()); */
|
||||
/* [BrtOleSize] */
|
||||
/* *(BrtUserBookView *FRT) */
|
||||
/* [PIVOTCACHEIDS] */
|
||||
/* [BrtWbFactoid] */
|
||||
/* [SMARTTAGTYPES] */
|
||||
/* [BrtWebOpt] */
|
||||
/* write_record(ba, 0x009B BrtFileRecover, write_BrtFileRecover()); */
|
||||
/* [WEBPUBITEMS] */
|
||||
/* [CRERRS] */
|
||||
/* FRTWORKBOOK */
|
||||
write_record(ba, 0x0084 /* BrtEndBook */);
|
||||
|
||||
return ba.end();
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
function parse_wb(data, name/*:string*/, opts)/*:WorkbookFile*/ {
|
||||
if(name.slice(-4)===".bin") return parse_wb_bin((data/*:any*/), opts);
|
||||
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_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_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_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_sty(data, name/*:string*/, themes, opts) {
|
||||
if(name.slice(-4)===".bin") return parse_sty_bin((data/*:any*/), themes, opts);
|
||||
return parse_sty_xml((data/*:any*/), themes, 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>*/ {
|
||||
if(name.slice(-4)===".bin") return parse_comments_bin((data/*:any*/), opts);
|
||||
return parse_comments_xml((data/*:any*/), opts);
|
||||
}
|
||||
|
||||
function parse_cc(data, name/*:string*/, opts) {
|
||||
if(name.slice(-4)===".bin") return parse_cc_bin((data/*:any*/), name, 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_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);
|
||||
}
|
1265
bits/75_xlml.js
1265
bits/75_xlml.js
File diff suppressed because it is too large
Load Diff
100
bits/76_wbcommon.js
Normal file
100
bits/76_wbcommon.js
Normal file
@ -0,0 +1,100 @@
|
||||
/* 18.2.28 (CT_WorkbookProtection) Defaults */
|
||||
var WBPropsDef = [
|
||||
['allowRefreshQuery', '0'],
|
||||
['autoCompressPictures', '1'],
|
||||
['backupFile', '0'],
|
||||
['checkCompatibility', '0'],
|
||||
['codeName', ''],
|
||||
['date1904', '0'],
|
||||
['dateCompatibility', '1'],
|
||||
//['defaultThemeVersion', '0'],
|
||||
['filterPrivacy', '0'],
|
||||
['hidePivotFieldList', '0'],
|
||||
['promptedSolutions', '0'],
|
||||
['publishItems', '0'],
|
||||
['refreshAllConnections', false],
|
||||
['saveExternalLinkValues', '1'],
|
||||
['showBorderUnselectedTables', '1'],
|
||||
['showInkAnnotation', '1'],
|
||||
['showObjects', 'all'],
|
||||
['showPivotChartFilter', '0']
|
||||
//['updateLinks', 'userSet']
|
||||
];
|
||||
|
||||
/* 18.2.30 (CT_BookView) Defaults */
|
||||
var WBViewDef = [
|
||||
['activeTab', '0'],
|
||||
['autoFilterDateGrouping', '1'],
|
||||
['firstSheet', '0'],
|
||||
['minimized', '0'],
|
||||
['showHorizontalScroll', '1'],
|
||||
['showSheetTabs', '1'],
|
||||
['showVerticalScroll', '1'],
|
||||
['tabRatio', '600'],
|
||||
['visibility', 'visible']
|
||||
//window{Height,Width}, {x,y}Window
|
||||
];
|
||||
|
||||
/* 18.2.19 (CT_Sheet) Defaults */
|
||||
var SheetDef = [
|
||||
['state', 'visible']
|
||||
];
|
||||
|
||||
/* 18.2.2 (CT_CalcPr) Defaults */
|
||||
var CalcPrDef = [
|
||||
['calcCompleted', 'true'],
|
||||
['calcMode', 'auto'],
|
||||
['calcOnSave', 'true'],
|
||||
['concurrentCalc', 'true'],
|
||||
['fullCalcOnLoad', 'false'],
|
||||
['fullPrecision', 'true'],
|
||||
['iterate', 'false'],
|
||||
['iterateCount', '100'],
|
||||
['iterateDelta', '0.001'],
|
||||
['refMode', 'A1']
|
||||
];
|
||||
|
||||
/* 18.2.3 (CT_CustomWorkbookView) Defaults */
|
||||
var CustomWBViewDef = [
|
||||
['autoUpdate', 'false'],
|
||||
['changesSavedWin', 'false'],
|
||||
['includeHiddenRowCol', 'true'],
|
||||
['includePrintSettings', 'true'],
|
||||
['maximized', 'false'],
|
||||
['minimized', 'false'],
|
||||
['onlySync', 'false'],
|
||||
['personalView', 'false'],
|
||||
['showComments', 'commIndicator'],
|
||||
['showFormulaBar', 'true'],
|
||||
['showHorizontalScroll', 'true'],
|
||||
['showObjects', 'all'],
|
||||
['showSheetTabs', 'true'],
|
||||
['showStatusbar', 'true'],
|
||||
['showVerticalScroll', 'true'],
|
||||
['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];
|
||||
}
|
||||
}
|
||||
}
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
function parse_wb_defaults(wb) {
|
||||
push_defaults(wb.WBProps, WBPropsDef);
|
||||
push_defaults(wb.CalcPr, CalcPrDef);
|
||||
|
||||
push_defaults_array(wb.WBView, WBViewDef);
|
||||
push_defaults_array(wb.Sheets, SheetDef);
|
||||
|
||||
_ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904, 'date1904');
|
||||
}
|
735
bits/76_xls.js
735
bits/76_xls.js
@ -1,735 +0,0 @@
|
||||
/* [MS-OLEDS] 2.3.8 CompObjStream */
|
||||
function parse_compobj(obj/*:CFBEntry*/) {
|
||||
var v = {};
|
||||
var o = obj.content;
|
||||
/*:: if(o == null) return; */
|
||||
|
||||
/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
|
||||
o.l = 28;
|
||||
|
||||
v.AnsiUserType = o.read_shift(0, "lpstr-ansi");
|
||||
v.AnsiClipboardFormat = parse_ClipboardFormatOrAnsiString(o);
|
||||
|
||||
if(o.length - o.l <= 4) return v;
|
||||
|
||||
var m/*:number*/ = o.read_shift(4);
|
||||
if(m == 0 || m > 40) return v;
|
||||
o.l-=4; v.Reserved1 = o.read_shift(0, "lpstr-ansi");
|
||||
|
||||
if(o.length - o.l <= 4) return v;
|
||||
m = o.read_shift(4);
|
||||
if(m !== 0x71b239f4) return v;
|
||||
v.UnicodeClipboardFormat = parse_ClipboardFormatOrUnicodeString(o);
|
||||
|
||||
m = o.read_shift(4);
|
||||
if(m == 0 || m > 40) return v;
|
||||
o.l-=4; v.Reserved2 = o.read_shift(0, "lpwstr");
|
||||
}
|
||||
|
||||
/*
|
||||
Continue logic for:
|
||||
- 2.4.58 Continue 0x003c
|
||||
- 2.4.59 ContinueBigName 0x043c
|
||||
- 2.4.60 ContinueFrt 0x0812
|
||||
- 2.4.61 ContinueFrt11 0x0875
|
||||
- 2.4.62 ContinueFrt12 0x087f
|
||||
*/
|
||||
var CONTINUE_RT = [ 0x003c, 0x043c, 0x0812, 0x0875, 0x087f ];
|
||||
function slurp(RecordType, R, blob, length/*:number*/, opts)/*:any*/ {
|
||||
var l = length;
|
||||
var bufs = [];
|
||||
var d = blob.slice(blob.l,blob.l+l);
|
||||
if(opts && opts.enc && opts.enc.insitu && d.length > 0) switch(RecordType) {
|
||||
case 0x0009: case 0x0209: case 0x0409: case 0x0809/* BOF */: case 0x002F /* FilePass */: case 0x0195 /* FileLock */: case 0x00E1 /* InterfaceHdr */: case 0x0196 /* RRDInfo */: case 0x0138 /* RRDHead */: case 0x0194 /* UsrExcl */: case 0x000a /* EOF */:
|
||||
break;
|
||||
case 0x0085 /* BoundSheet8 */:
|
||||
break;
|
||||
default:
|
||||
opts.enc.insitu(d);
|
||||
}
|
||||
bufs.push(d);
|
||||
blob.l += l;
|
||||
var nextrt = __readUInt16LE(blob,blob.l), next = XLSRecordEnum[nextrt];
|
||||
var start = 0;
|
||||
while(next != null && CONTINUE_RT.indexOf(nextrt) > -1) {
|
||||
l = __readUInt16LE(blob,blob.l+2);
|
||||
start = blob.l + 4;
|
||||
if(nextrt == 0x0812 /* ContinueFrt */) start += 4;
|
||||
else if(nextrt == 0x0875 || nextrt == 0x087f) {
|
||||
start += 12;
|
||||
}
|
||||
d = blob.slice(start,blob.l+4+l);
|
||||
bufs.push(d);
|
||||
blob.l += 4+l;
|
||||
next = (XLSRecordEnum[nextrt = __readUInt16LE(blob, blob.l)]);
|
||||
}
|
||||
var b = (bconcat(bufs)/*:any*/);
|
||||
prep_blob(b, 0);
|
||||
var ll = 0; b.lens = [];
|
||||
for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; }
|
||||
if(b.length < length) throw "XLS Record 0x" + RecordType.toString(16) + " Truncated: " + b.length + " < " + length;
|
||||
return R.f(b, b.length, opts);
|
||||
}
|
||||
|
||||
function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
|
||||
if(p.t === 'z') return;
|
||||
if(!p.XF) return;
|
||||
var fmtid = 0;
|
||||
try {
|
||||
fmtid = p.z || p.XF.numFmtId || 0;
|
||||
if(opts.cellNF && p.z == null) p.z = table_fmt[fmtid];
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
if(!opts || opts.cellText !== false) try {
|
||||
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
|
||||
else if(fmtid === 0 || fmtid == "General") {
|
||||
if(p.t === 'n') {
|
||||
if((p.v|0) === p.v) p.w = p.v.toString(10);
|
||||
else p.w = SSF_general_num(p.v);
|
||||
}
|
||||
else p.w = SSF_general(p.v);
|
||||
}
|
||||
else p.w = SSF_format(fmtid,p.v, {date1904:!!date1904, dateNF: opts && opts.dateNF});
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
if(opts.cellDates && fmtid && p.t == 'n' && fmt_is_date(table_fmt[fmtid] || String(fmtid))) {
|
||||
var _d = SSF_parse_date_code(p.v + (date1904 ? 1462 : 0)); if(_d) { p.t = 'd'; p.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
|
||||
}
|
||||
}
|
||||
|
||||
function make_cell(val, ixfe, t)/*:Cell*/ {
|
||||
return ({v:val, ixfe:ixfe, t:t}/*:any*/);
|
||||
}
|
||||
|
||||
// 2.3.2
|
||||
function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
var wb = ({opts:{}}/*:any*/);
|
||||
var Sheets = {};
|
||||
if(DENSE != null && options.dense == null) options.dense = DENSE;
|
||||
var out/*:Worksheet*/ = ({}/*:any*/); if(options.dense) out["!data"] = [];
|
||||
var Directory = {};
|
||||
var range/*:Range*/ = ({}/*:any*/);
|
||||
var last_formula = null;
|
||||
var sst/*:SST*/ = ([]/*:any*/);
|
||||
var cur_sheet = "";
|
||||
var Preamble = {};
|
||||
var lastcell, last_cell = "", cc/*:Cell*/, cmnt, rngC, rngR;
|
||||
var sharedf = {};
|
||||
var arrayf/*:Array<[Range, string]>*/ = [];
|
||||
var temp_val/*:Cell*/;
|
||||
var country;
|
||||
var XFs = []; /* XF records */
|
||||
var palette/*:Array<[number, number, number]>*/ = [];
|
||||
var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false}, Views:[{}] }/*:any*/), wsprops = {};
|
||||
var biff4w = false;
|
||||
var get_rgb = function getrgb(icv/*:number*/)/*:[number, number, number]*/ {
|
||||
if(icv < 8) return XLSIcv[icv];
|
||||
if(icv < 64) return palette[icv-8] || XLSIcv[icv];
|
||||
return XLSIcv[icv];
|
||||
};
|
||||
var process_cell_style = function pcs(line/*:any*/, options) {
|
||||
var xfd = line.XF.data;
|
||||
if(!xfd || !xfd.patternType || !options || !options.cellStyles) return;
|
||||
line.s = ({}/*:any*/);
|
||||
line.s.patternType = xfd.patternType;
|
||||
var t;
|
||||
if((t = rgb2Hex(get_rgb(xfd.icvFore)))) { line.s.fgColor = {rgb:t}; }
|
||||
if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; }
|
||||
};
|
||||
var addcell = function addcell(cell/*:any*/, line/*:any*/, options/*:any*/) {
|
||||
if(!biff4w && file_depth > 1) return;
|
||||
if(options.sheetRows && cell.r >= options.sheetRows) return;
|
||||
if(options.cellStyles && line.XF && line.XF.data) process_cell_style(line, options);
|
||||
delete line.ixfe; delete line.XF;
|
||||
lastcell = cell;
|
||||
last_cell = encode_cell(cell);
|
||||
if(!range || !range.s || !range.e) range = {s:{r:0,c:0},e:{r:0,c:0}};
|
||||
if(cell.r < range.s.r) range.s.r = cell.r;
|
||||
if(cell.c < range.s.c) range.s.c = cell.c;
|
||||
if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1;
|
||||
if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1;
|
||||
if(options.cellFormula && line.f) {
|
||||
for(var afi = 0; afi < arrayf.length; ++afi) {
|
||||
if(arrayf[afi][0].s.c > cell.c || arrayf[afi][0].s.r > cell.r) continue;
|
||||
if(arrayf[afi][0].e.c < cell.c || arrayf[afi][0].e.r < cell.r) continue;
|
||||
line.F = encode_range(arrayf[afi][0]);
|
||||
if(arrayf[afi][0].s.c != cell.c || arrayf[afi][0].s.r != cell.r) delete line.f;
|
||||
if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
if(options.dense) {
|
||||
if(!out["!data"][cell.r]) out["!data"][cell.r] = [];
|
||||
out["!data"][cell.r][cell.c] = line;
|
||||
} else out[last_cell] = line;
|
||||
}
|
||||
};
|
||||
var opts = ({
|
||||
enc: false, // encrypted
|
||||
sbcch: 0, // cch in the preceding SupBook
|
||||
snames: [], // sheetnames
|
||||
sharedf: sharedf, // shared formulae by address
|
||||
arrayf: arrayf, // array formulae array
|
||||
rrtabid: [], // RRTabId
|
||||
lastuser: "", // Last User from WriteAccess
|
||||
biff: 8, // BIFF version
|
||||
codepage: 0, // CP from CodePage record
|
||||
winlocked: 0, // fLockWn from WinProtect
|
||||
cellStyles: !!options && !!options.cellStyles,
|
||||
WTF: !!options && !!options.wtf
|
||||
}/*:any*/);
|
||||
if(options.password) opts.password = options.password;
|
||||
var themes;
|
||||
var merges/*:Array<Range>*/ = [];
|
||||
var objects = [];
|
||||
var colinfo/*:Array<ColInfo>*/ = [], rowinfo/*:Array<RowInfo>*/ = [];
|
||||
var seencol = false;
|
||||
var supbooks = ([]/*:any*/); // 1-indexed, will hold extern names
|
||||
supbooks.SheetNames = opts.snames;
|
||||
supbooks.sharedf = opts.sharedf;
|
||||
supbooks.arrayf = opts.arrayf;
|
||||
supbooks.names = [];
|
||||
supbooks.XTI = [];
|
||||
var last_RT = 0;
|
||||
var file_depth = 0; /* TODO: make a real stack */
|
||||
var BIFF2Fmt = 0, BIFF2FmtTable/*:Array<string>*/ = [];
|
||||
var FilterDatabases = []; /* TODO: sort out supbooks and process elsewhere */
|
||||
var last_lbl/*:?DefinedName*/;
|
||||
|
||||
/* explicit override for some broken writers */
|
||||
opts.codepage = 1200;
|
||||
set_cp(1200);
|
||||
var seen_codepage = false;
|
||||
while(blob.l < blob.length - 1) {
|
||||
var s = blob.l;
|
||||
var RecordType = blob.read_shift(2);
|
||||
if(RecordType === 0 && last_RT === 0x000a /* EOF */) break;
|
||||
var length = (blob.l === blob.length ? 0 : blob.read_shift(2));
|
||||
var R = XLSRecordEnum[RecordType];
|
||||
if(file_depth == 0 && [0x0009, 0x0209, 0x0409, 0x0809].indexOf(RecordType) == -1 /* BOF */) break;
|
||||
//console.log(RecordType.toString(16), RecordType, R, blob.l, length, blob.length);
|
||||
//if(!R) console.log(blob.slice(blob.l, blob.l + length));
|
||||
if(R && R.f) {
|
||||
if(options.bookSheets) {
|
||||
if(last_RT === 0x0085 /* BoundSheet8 */ && RecordType !== 0x0085 /* R.n !== 'BoundSheet8' */) break;
|
||||
}
|
||||
last_RT = RecordType;
|
||||
if(R.r === 2 || R.r == 12) {
|
||||
var rt = blob.read_shift(2); length -= 2;
|
||||
if(!opts.enc && rt !== RecordType && (((rt&0xFF)<<8)|(rt>>8)) !== RecordType) throw new Error("rt mismatch: " + rt + "!=" + RecordType);
|
||||
if(R.r == 12){
|
||||
blob.l += 10; length -= 10;
|
||||
} // skip FRT
|
||||
}
|
||||
//console.error(R,blob.l,length,blob.length);
|
||||
var val/*:any*/ = ({}/*:any*/);
|
||||
if(RecordType === 0x000a /* EOF */) val = /*::(*/R.f(blob, length, opts)/*:: :any)*/;
|
||||
else val = /*::(*/slurp(RecordType, R, blob, length, opts)/*:: :any)*/;
|
||||
/*:: val = (val:any); */
|
||||
if(file_depth == 0 && [0x0009, 0x0209, 0x0409, 0x0809].indexOf(last_RT) === -1 /* BOF */) continue;
|
||||
switch(RecordType) {
|
||||
case 0x0022 /* Date1904 */:
|
||||
/*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
|
||||
wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
|
||||
case 0x0086 /* WriteProtect */: wb.opts.WriteProtect = true; break;
|
||||
case 0x002f /* FilePass */:
|
||||
if(!opts.enc) blob.l = 0;
|
||||
opts.enc = val;
|
||||
if(!options.password) throw new Error("File is password-protected");
|
||||
if(val.valid == null) throw new Error("Encryption scheme unsupported");
|
||||
if(!val.valid) throw new Error("Password is incorrect");
|
||||
break;
|
||||
case 0x005c /* WriteAccess */: opts.lastuser = val; break;
|
||||
case 0x0042 /* CodePage */:
|
||||
var cpval = Number(val);
|
||||
/* overrides based on test cases */
|
||||
switch(cpval) {
|
||||
case 0x5212: cpval = 1200; break;
|
||||
case 0x8000: cpval = 10000; break;
|
||||
case 0x8001: cpval = 1252; break;
|
||||
}
|
||||
set_cp(opts.codepage = cpval);
|
||||
seen_codepage = true;
|
||||
break;
|
||||
case 0x013d /* RRTabId */: opts.rrtabid = val; break;
|
||||
case 0x0019 /* WinProtect */: opts.winlocked = val; break;
|
||||
case 0x01b7 /* RefreshAll */: wb.opts["RefreshAll"] = val; break;
|
||||
case 0x000c /* CalcCount */: wb.opts["CalcCount"] = val; break;
|
||||
case 0x0010 /* CalcDelta */: wb.opts["CalcDelta"] = val; break;
|
||||
case 0x0011 /* CalcIter */: wb.opts["CalcIter"] = val; break;
|
||||
case 0x000d /* CalcMode */: wb.opts["CalcMode"] = val; break;
|
||||
case 0x000e /* CalcPrecision */: wb.opts["CalcPrecision"] = val; break;
|
||||
case 0x005f /* CalcSaveRecalc */: wb.opts["CalcSaveRecalc"] = val; break;
|
||||
case 0x000f /* CalcRefMode */: opts.CalcRefMode = val; break; // TODO: implement R1C1
|
||||
case 0x08a3 /* ForceFullCalculation */: wb.opts.FullCalc = val; break;
|
||||
case 0x0081 /* WsBool */:
|
||||
if(val.fDialog) out["!type"] = "dialog";
|
||||
if(!val.fBelow) (out["!outline"] || (out["!outline"] = {})).above = true;
|
||||
if(!val.fRight) (out["!outline"] || (out["!outline"] = {})).left = true;
|
||||
break; // TODO
|
||||
case 0x0043: /* BIFF2XF */ case 0x0243: /* BIFF3XF */ case 0x0443: /* BIFF4XF */
|
||||
case 0x00e0 /* XF */:
|
||||
XFs.push(val); break;
|
||||
case 0x01ae /* SupBook */:
|
||||
supbooks.push([val]);
|
||||
supbooks[supbooks.length-1].XTI = [];
|
||||
break;
|
||||
case 0x0023: case 0x0223 /* ExternName */:
|
||||
supbooks[supbooks.length-1].push(val);
|
||||
break;
|
||||
case 0x0018: case 0x0218 /* Lbl */:
|
||||
last_lbl = ({
|
||||
Name: val.Name,
|
||||
Ref: stringify_formula(val.rgce,range,null,supbooks,opts)
|
||||
}/*:DefinedName*/);
|
||||
if(val.itab > 0) last_lbl.Sheet = val.itab - 1;
|
||||
supbooks.names.push(last_lbl);
|
||||
if(!supbooks[0]) { supbooks[0] = []; supbooks[0].XTI = []; }
|
||||
supbooks[supbooks.length-1].push(val);
|
||||
if(val.Name == "_xlnm._FilterDatabase" && val.itab > 0)
|
||||
if(val.rgce && val.rgce[0] && val.rgce[0][0] && val.rgce[0][0][0] == 'PtgArea3d')
|
||||
FilterDatabases[val.itab - 1] = { ref: encode_range(val.rgce[0][0][1][2]) };
|
||||
break;
|
||||
case 0x0016 /* ExternCount */: opts.ExternCount = val; break;
|
||||
case 0x0017 /* ExternSheet */:
|
||||
if(supbooks.length == 0) { supbooks[0] = []; supbooks[0].XTI = []; }
|
||||
supbooks[supbooks.length - 1].XTI = supbooks[supbooks.length - 1].XTI.concat(val); supbooks.XTI = supbooks.XTI.concat(val); break;
|
||||
case 0x0894 /* NameCmt */:
|
||||
/* TODO: search for correct name */
|
||||
if(opts.biff < 8) break;
|
||||
if(last_lbl != null) last_lbl.Comment = val[1];
|
||||
break;
|
||||
case 0x0012 /* Protect */: out["!protect"] = val; break; /* for sheet or book */
|
||||
case 0x0013 /* Password */: if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
|
||||
case 0x0085 /* BoundSheet8 */: {
|
||||
Directory[opts.biff == 4 ? opts.snames.length : val.pos] = val;
|
||||
opts.snames.push(val.name);
|
||||
} break;
|
||||
case 0x000a /* EOF */: {
|
||||
if(--file_depth ? !biff4w : biff4w) break;
|
||||
if(range.e) {
|
||||
if(range.e.r > 0 && range.e.c > 0) {
|
||||
range.e.r--; range.e.c--;
|
||||
out["!ref"] = encode_range(range);
|
||||
if(options.sheetRows && options.sheetRows <= range.e.r) {
|
||||
var tmpri = range.e.r;
|
||||
range.e.r = options.sheetRows - 1;
|
||||
out["!fullref"] = out["!ref"];
|
||||
out["!ref"] = encode_range(range);
|
||||
range.e.r = tmpri;
|
||||
}
|
||||
range.e.r++; range.e.c++;
|
||||
}
|
||||
if(merges.length > 0) out["!merges"] = merges;
|
||||
if(objects.length > 0) out["!objects"] = objects;
|
||||
if(colinfo.length > 0) out["!cols"] = colinfo;
|
||||
if(rowinfo.length > 0) out["!rows"] = rowinfo;
|
||||
Workbook.Sheets.push(wsprops);
|
||||
}
|
||||
if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out;
|
||||
out = ({}/*:any*/); if(options.dense) out["!data"] = [];
|
||||
} break;
|
||||
case 0x0009: case 0x0209: case 0x0409: case 0x0809 /* BOF */: {
|
||||
if(opts.biff === 8) opts.biff = {
|
||||
0x0009: 2,
|
||||
0x0209: 3,
|
||||
0x0409: 4
|
||||
}[RecordType] || {
|
||||
0x0200: 2,
|
||||
0x0300: 3,
|
||||
0x0400: 4,
|
||||
0x0500: 5,
|
||||
0x0600: 8,
|
||||
0x0002: 2,
|
||||
0x0007: 2
|
||||
}[val.BIFFVer] || 8;
|
||||
opts.biffguess = val.BIFFVer == 0;
|
||||
if(val.BIFFVer == 0 && val.dt == 0x1000) { opts.biff = 5; seen_codepage = true; set_cp(opts.codepage = 28591); }
|
||||
if(opts.biff == 4 && val.dt & 0x100) biff4w = true;
|
||||
if(opts.biff == 8 && val.BIFFVer == 0 && val.dt == 16) opts.biff = 2;
|
||||
if(file_depth++ && !biff4w) break;
|
||||
out = ({}/*:any*/); if(options.dense) out["!data"] = [];
|
||||
|
||||
if(opts.biff < 8 && !seen_codepage) { seen_codepage = true; set_cp(opts.codepage = options.codepage || 1252); }
|
||||
if(opts.biff == 4 && biff4w) {
|
||||
cur_sheet = (Directory[opts.snames.indexOf(cur_sheet)+1] || {name:""}).name;
|
||||
} else if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) {
|
||||
if(cur_sheet === "") cur_sheet = "Sheet1";
|
||||
range = {s:{r:0,c:0},e:{r:0,c:0}};
|
||||
/* fake BoundSheet8 */
|
||||
var fakebs8 = {pos: blob.l - length, name:cur_sheet};
|
||||
Directory[fakebs8.pos] = fakebs8;
|
||||
opts.snames.push(cur_sheet);
|
||||
}
|
||||
else cur_sheet = (Directory[s] || {name:""}).name;
|
||||
if(val.dt == 0x20) out["!type"] = "chart";
|
||||
if(val.dt == 0x40) out["!type"] = "macro";
|
||||
merges = [];
|
||||
objects = [];
|
||||
opts.arrayf = arrayf = [];
|
||||
colinfo = []; rowinfo = [];
|
||||
seencol = false;
|
||||
wsprops = {Hidden:(Directory[s]||{hs:0}).hs, name:cur_sheet };
|
||||
} break;
|
||||
case 0x0203 /* Number */: case 0x0003 /* BIFF2NUM */: case 0x0002 /* BIFF2INT */: {
|
||||
if(out["!type"] == "chart") if(options.dense ? (out["!data"][val.r]||[])[val.c]: out[encode_col(val.c) + encode_row(val.r)]) ++val.c;
|
||||
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe]||{}, v:val.val, t:'n'}/*:any*/);
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
} break;
|
||||
case 0x0005: case 0x0205 /* BoolErr */: {
|
||||
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t}/*:any*/);
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
} break;
|
||||
case 0x027e /* RK */: {
|
||||
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'}/*:any*/);
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
} break;
|
||||
case 0x00bd /* MulRk */: {
|
||||
for(var j = val.c; j <= val.C; ++j) {
|
||||
var ixfe = val.rkrec[j-val.c][0];
|
||||
temp_val= ({ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'}/*:any*/);
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:j, r:val.r}, temp_val, options);
|
||||
}
|
||||
} break;
|
||||
case 0x0006: case 0x0206: case 0x0406 /* Formula */: {
|
||||
if(val.val == 'String') { last_formula = val; break; }
|
||||
temp_val = make_cell(val.val, val.cell.ixfe, val.tt);
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) {
|
||||
var _f = val.formula;
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = ((options.dense ? (out["!data"][_fr]||[])[_fc]: out[_fe]) || {}).F;
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(val.cell, temp_val, options);
|
||||
last_formula = val;
|
||||
} break;
|
||||
case 0x0007: case 0x0207 /* String */: {
|
||||
if(last_formula) { /* technically always true */
|
||||
last_formula.val = val;
|
||||
temp_val = make_cell(val, last_formula.cell.ixfe, 's');
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) {
|
||||
temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
}
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(last_formula.cell, temp_val, options);
|
||||
last_formula = null;
|
||||
} else throw new Error("String record expects Formula");
|
||||
} break;
|
||||
case 0x0021: case 0x0221 /* Array */: {
|
||||
arrayf.push(val);
|
||||
var _arraystart = encode_cell(val[0].s);
|
||||
cc = options.dense ? (out["!data"][val[0].s.r]||[])[val[0].s.c] : out[_arraystart];
|
||||
if(options.cellFormula && cc) {
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
if(!_arraystart || !cc) break;
|
||||
cc.f = ""+stringify_formula(val[1], range, val[0], supbooks, opts);
|
||||
cc.F = encode_range(val[0]);
|
||||
}
|
||||
} break;
|
||||
case 0x04bc /* ShrFmla */: {
|
||||
if(!options.cellFormula) break;
|
||||
if(last_cell) {
|
||||
/* TODO: capture range */
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
sharedf[encode_cell(last_formula.cell)]= val[0];
|
||||
cc = options.dense ? (out["!data"][last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
|
||||
(cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
}
|
||||
} break;
|
||||
case 0x00fd /* LabelSst */:
|
||||
temp_val=make_cell(sst[val.isst].t, val.ixfe, 's');
|
||||
if(sst[val.isst].h) temp_val.h = sst[val.isst].h;
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
break;
|
||||
case 0x0201 /* Blank */: if(options.sheetStubs) {
|
||||
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'}/*:any*/);
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
} break;
|
||||
case 0x00be /* MulBlank */: if(options.sheetStubs) {
|
||||
for(var _j = val.c; _j <= val.C; ++_j) {
|
||||
var _ixfe = val.ixfe[_j-val.c];
|
||||
temp_val= ({ixfe:_ixfe, XF:XFs[_ixfe], t:'z'}/*:any*/);
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:_j, r:val.r}, temp_val, options);
|
||||
}
|
||||
} break;
|
||||
case 0x00d6 /* RString */:
|
||||
case 0x0204 /* Label */: case 0x0004 /* BIFF2STR */:
|
||||
temp_val=make_cell(val.val, val.ixfe, 's');
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
break;
|
||||
|
||||
case 0x0000: case 0x0200 /* Dimensions */: {
|
||||
if(file_depth === 1) range = val; /* TODO: stack */
|
||||
} break;
|
||||
case 0x00fc /* SST */: {
|
||||
sst = val;
|
||||
} break;
|
||||
case 0x041e /* Format */: { /* val = [id, fmt] */
|
||||
if(opts.biff >= 3 && opts.biff <= 4) {
|
||||
BIFF2FmtTable[BIFF2Fmt++] = val[1];
|
||||
for(var b4idx = 0; b4idx < BIFF2Fmt + 163; ++b4idx) if(table_fmt[b4idx] == val[1]) break;
|
||||
if(b4idx >= 163) SSF__load(val[1], BIFF2Fmt + 163);
|
||||
}
|
||||
else SSF__load(val[1], val[0]);
|
||||
} break;
|
||||
case 0x001e /* BIFF2FORMAT */: {
|
||||
BIFF2FmtTable[BIFF2Fmt++] = val;
|
||||
for(var b2idx = 0; b2idx < BIFF2Fmt + 163; ++b2idx) if(table_fmt[b2idx] == val) break;
|
||||
if(b2idx >= 163) SSF__load(val, BIFF2Fmt + 163);
|
||||
} break;
|
||||
|
||||
case 0x00e5 /* MergeCells */: merges = merges.concat(val); break;
|
||||
|
||||
case 0x005d /* Obj */: objects[val.cmo[0]] = opts.lastobj = val; break;
|
||||
case 0x01b6 /* TxO */: opts.lastobj.TxO = val; break;
|
||||
case 0x007f /* ImData */: opts.lastobj.ImData = val; break;
|
||||
|
||||
case 0x01b8 /* HLink */: {
|
||||
for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
|
||||
for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
|
||||
cc = options.dense ? (out["!data"][rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
|
||||
if(cc) cc.l = val[1];
|
||||
}
|
||||
} break;
|
||||
case 0x0800 /* HLinkTooltip */: {
|
||||
for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
|
||||
for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
|
||||
cc = options.dense ? (out["!data"][rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
|
||||
if(cc && cc.l) cc.l.Tooltip = val[1];
|
||||
}
|
||||
} break;
|
||||
case 0x001c /* Note */: {
|
||||
/* TODO: comment continuation (row == -1 / 0xFFFF) */
|
||||
cc = options.dense ? (out["!data"][val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
|
||||
if(!cc) {
|
||||
if(options.dense) {
|
||||
if(!out["!data"][val[0].r]) out["!data"][val[0].r] = [];
|
||||
cc = out["!data"][val[0].r][val[0].c] = ({t:"z"}/*:any*/);
|
||||
} else {
|
||||
cc = out[encode_cell(val[0])] = ({t:"z"}/*:any*/);
|
||||
}
|
||||
range.e.r = Math.max(range.e.r, val[0].r);
|
||||
range.s.r = Math.min(range.s.r, val[0].r);
|
||||
range.e.c = Math.max(range.e.c, val[0].c);
|
||||
range.s.c = Math.min(range.s.c, val[0].c);
|
||||
}
|
||||
if(!cc.c) cc.c = [];
|
||||
if(opts.biff <= 5 && opts.biff >= 2) cmnt = {a:"SheetJ5", t:val[1]};
|
||||
else {
|
||||
var noteobj = objects[val[2]];
|
||||
cmnt = {a:val[1],t:noteobj.TxO.t};
|
||||
if(val[3] != null && !(val[3] & 0x02)) cc.c.hidden = true;
|
||||
}
|
||||
cc.c.push(cmnt);
|
||||
} break;
|
||||
case 0x087d /* XFExt */: update_xfext(XFs[val.ixfe], val.ext); break;
|
||||
case 0x007d /* ColInfo */: {
|
||||
if(!opts.cellStyles) break;
|
||||
while(val.e >= val.s) {
|
||||
colinfo[val.e--] = { width: val.w/256, level: (val.level || 0), hidden: !!(val.flags & 1) };
|
||||
if(!seencol) { seencol = true; find_mdw_colw(val.w/256); }
|
||||
process_col(colinfo[val.e+1]);
|
||||
}
|
||||
} break;
|
||||
case 0x0208 /* Row */: {
|
||||
var rowobj = {};
|
||||
if(val.level != null) { rowinfo[val.r] = rowobj; rowobj.level = val.level; }
|
||||
if(val.hidden) { rowinfo[val.r] = rowobj; rowobj.hidden = true; }
|
||||
if(val.hpt) {
|
||||
rowinfo[val.r] = rowobj;
|
||||
rowobj.hpt = val.hpt; rowobj.hpx = pt2px(val.hpt);
|
||||
}
|
||||
} break;
|
||||
case 0x0026 /* LeftMargin */:
|
||||
case 0x0027 /* RightMargin */:
|
||||
case 0x0028 /* TopMargin */:
|
||||
case 0x0029 /* BottomMargin */:
|
||||
if(!out['!margins']) default_margins(out['!margins'] = {});
|
||||
out['!margins'][({0x26: "left", 0x27:"right", 0x28:"top", 0x29:"bottom"})[RecordType]] = val;
|
||||
break;
|
||||
case 0x00a1 /* Setup */: // TODO
|
||||
if(!out['!margins']) default_margins(out['!margins'] = {});
|
||||
out['!margins'].header = val.header;
|
||||
out['!margins'].footer = val.footer;
|
||||
break;
|
||||
case 0x023e /* Window2 */: // TODO
|
||||
// $FlowIgnore
|
||||
if(val.RTL) Workbook.Views[0].RTL = true;
|
||||
break;
|
||||
case 0x0092 /* Palette */: palette = val; break;
|
||||
case 0x0896 /* Theme */: themes = val; break;
|
||||
case 0x008c /* Country */: country = val; break;
|
||||
case 0x01ba /* CodeName */: {
|
||||
/*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
|
||||
if(!cur_sheet) Workbook.WBProps.CodeName = val || "ThisWorkbook";
|
||||
else wsprops.CodeName = val || wsprops.name;
|
||||
} break;
|
||||
}
|
||||
} else {
|
||||
if(!R) console.error("Missing Info for XLS Record 0x" + RecordType.toString(16));
|
||||
blob.l += length;
|
||||
}
|
||||
}
|
||||
wb.SheetNames=keys(Directory).sort(function(a,b) { return Number(a) - Number(b); }).map(function(x){return Directory[x].name;});
|
||||
if(!options.bookSheets) wb.Sheets=Sheets;
|
||||
if(!wb.SheetNames.length && Preamble["!ref"]) {
|
||||
wb.SheetNames.push("Sheet1");
|
||||
/*jshint -W069 */
|
||||
if(wb.Sheets) wb.Sheets["Sheet1"] = Preamble;
|
||||
/*jshint +W069 */
|
||||
} else wb.Preamble=Preamble;
|
||||
if(wb.Sheets) FilterDatabases.forEach(function(r,i) { wb.Sheets[wb.SheetNames[i]]['!autofilter'] = r; });
|
||||
wb.Strings = sst;
|
||||
wb.SSF = dup(table_fmt);
|
||||
if(opts.enc) wb.Encryption = opts.enc;
|
||||
if(themes) wb.Themes = themes;
|
||||
wb.Metadata = {};
|
||||
if(country !== undefined) wb.Metadata.Country = country;
|
||||
if(supbooks.names.length > 0) Workbook.Names = supbooks.names;
|
||||
wb.Workbook = Workbook;
|
||||
return wb;
|
||||
}
|
||||
|
||||
/* TODO: split props*/
|
||||
var PSCLSID = {
|
||||
SI: "e0859ff2f94f6810ab9108002b27b3d9",
|
||||
DSI: "02d5cdd59c2e1b10939708002b2cf9ae",
|
||||
UDI: "05d5cdd59c2e1b10939708002b2cf9ae"
|
||||
};
|
||||
function parse_xls_props(cfb/*:CFBContainer*/, props, o) {
|
||||
/* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
|
||||
var DSI = CFB.find(cfb, '/!DocumentSummaryInformation');
|
||||
if(DSI && DSI.size > 0) try {
|
||||
var DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI, PSCLSID.DSI);
|
||||
for(var d in DocSummary) props[d] = DocSummary[d];
|
||||
} catch(e) {if(o.WTF) console.error(e && e.message || e);}
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
|
||||
var SI = CFB.find(cfb, '/!SummaryInformation');
|
||||
if(SI && SI.size > 0) try {
|
||||
var Summary = parse_PropertySetStream(SI, SummaryPIDSI, PSCLSID.SI);
|
||||
for(var s in Summary) if(props[s] == null) props[s] = Summary[s];
|
||||
} catch(e) {if(o.WTF) console.error(e && e.message || e);}
|
||||
|
||||
if(props.HeadingPairs && props.TitlesOfParts) {
|
||||
load_props_pairs(props.HeadingPairs, props.TitlesOfParts, props, o);
|
||||
delete props.HeadingPairs; delete props.TitlesOfParts;
|
||||
}
|
||||
}
|
||||
function write_xls_props(wb/*:Workbook*/, cfb/*:CFBContainer*/) {
|
||||
var DSEntries = [], SEntries = [], CEntries = [];
|
||||
var i = 0, Keys;
|
||||
var DocSummaryRE/*:{[key:string]:string}*/ = evert_key(DocSummaryPIDDSI, "n");
|
||||
var SummaryRE/*:{[key:string]:string}*/ = evert_key(SummaryPIDSI, "n");
|
||||
if(wb.Props) {
|
||||
Keys = keys(wb.Props);
|
||||
// $FlowIgnore
|
||||
for(i = 0; i < Keys.length; ++i) (Object.prototype.hasOwnProperty.call(DocSummaryRE, Keys[i]) ? DSEntries : Object.prototype.hasOwnProperty.call(SummaryRE, Keys[i]) ? SEntries : CEntries).push([Keys[i], wb.Props[Keys[i]]]);
|
||||
}
|
||||
if(wb.Custprops) {
|
||||
Keys = keys(wb.Custprops);
|
||||
// $FlowIgnore
|
||||
for(i = 0; i < Keys.length; ++i) if(!Object.prototype.hasOwnProperty.call((wb.Props||{}), Keys[i])) (Object.prototype.hasOwnProperty.call(DocSummaryRE, Keys[i]) ? DSEntries : Object.prototype.hasOwnProperty.call(SummaryRE, Keys[i]) ? SEntries : CEntries).push([Keys[i], wb.Custprops[Keys[i]]]);
|
||||
}
|
||||
var CEntries2 = [];
|
||||
for(i = 0; i < CEntries.length; ++i) {
|
||||
if(XLSPSSkip.indexOf(CEntries[i][0]) > -1 || PseudoPropsPairs.indexOf(CEntries[i][0]) > -1) continue;
|
||||
if(CEntries[i][1] == null) continue;
|
||||
CEntries2.push(CEntries[i]);
|
||||
}
|
||||
if(SEntries.length) CFB.utils.cfb_add(cfb, "/\u0005SummaryInformation", write_PropertySetStream(SEntries, PSCLSID.SI, SummaryRE, SummaryPIDSI));
|
||||
if(DSEntries.length || CEntries2.length) CFB.utils.cfb_add(cfb, "/\u0005DocumentSummaryInformation", write_PropertySetStream(DSEntries, PSCLSID.DSI, DocSummaryRE, DocSummaryPIDDSI, CEntries2.length ? CEntries2 : null, PSCLSID.UDI));
|
||||
}
|
||||
|
||||
function parse_xlscfb(cfb/*:any*/, options/*:?ParseOpts*/)/*:Workbook*/ {
|
||||
if(!options) options = {};
|
||||
fix_read_opts(options);
|
||||
reset_cp();
|
||||
if(options.codepage) set_ansi(options.codepage);
|
||||
var CompObj/*:?CFBEntry*/, WB/*:?any*/;
|
||||
if(cfb.FullPaths) {
|
||||
if(CFB.find(cfb, '/encryption')) throw new Error("File is password-protected");
|
||||
CompObj = CFB.find(cfb, '!CompObj');
|
||||
WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
|
||||
} else {
|
||||
switch(options.type) {
|
||||
case 'base64': cfb = s2a(Base64_decode(cfb)); break;
|
||||
case 'binary': cfb = s2a(cfb); break;
|
||||
case 'buffer': break;
|
||||
case 'array': if(!Array.isArray(cfb)) cfb = Array.prototype.slice.call(cfb); break;
|
||||
}
|
||||
prep_blob(cfb, 0);
|
||||
WB = ({content: cfb}/*:any*/);
|
||||
}
|
||||
var /*::CompObjP, */WorkbookP/*:: :Workbook = XLSX.utils.book_new(); */;
|
||||
|
||||
var _data/*:?any*/;
|
||||
if(CompObj) /*::CompObjP = */parse_compobj(CompObj);
|
||||
if(options.bookProps && !options.bookSheets) WorkbookP = ({}/*:any*/);
|
||||
else/*:: if(cfb instanceof CFBContainer) */ {
|
||||
var T = has_buf ? 'buffer' : 'array';
|
||||
if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options);
|
||||
/* Quattro Pro 7-8 */
|
||||
else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
|
||||
/* Quattro Pro 9 */
|
||||
else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
|
||||
/* Works 4 for Mac */
|
||||
else if((_data=CFB.find(cfb, 'MN0')) && _data.content) throw new Error("Unsupported Works 4 for Mac file");
|
||||
else throw new Error("Cannot find Workbook stream");
|
||||
if(options.bookVBA && cfb.FullPaths && CFB.find(cfb, '/_VBA_PROJECT_CUR/VBA/dir')) WorkbookP.vbaraw = make_vba_xls(cfb);
|
||||
}
|
||||
|
||||
var props = {};
|
||||
if(cfb.FullPaths) parse_xls_props(/*::((*/cfb/*:: :any):CFBContainer)*/, props, options);
|
||||
|
||||
WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
|
||||
if(options.bookFiles) WorkbookP.cfb = cfb;
|
||||
/*WorkbookP.CompObjP = CompObjP; // TODO: storage? */
|
||||
return WorkbookP;
|
||||
}
|
||||
|
||||
|
||||
function write_xlscfb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:CFBContainer*/ {
|
||||
var o = opts || {};
|
||||
var cfb = CFB.utils.cfb_new({root:"R"});
|
||||
var wbpath = "/Workbook";
|
||||
switch(o.bookType || "xls") {
|
||||
case "xls": o.bookType = "biff8";
|
||||
/* falls through */
|
||||
case "xla": if(!o.bookType) o.bookType = "xla";
|
||||
/* falls through */
|
||||
case "biff8": wbpath = "/Workbook"; o.biff = 8; break;
|
||||
case "biff5": wbpath = "/Book"; o.biff = 5; break;
|
||||
default: throw new Error("invalid type " + o.bookType + " for XLS CFB");
|
||||
}
|
||||
CFB.utils.cfb_add(cfb, wbpath, write_biff_buf(wb, o));
|
||||
if(o.biff == 8 && (wb.Props || wb.Custprops)) write_xls_props(wb, cfb);
|
||||
// TODO: SI, DSI, CO
|
||||
if(o.biff == 8 && wb.vbaraw) fill_vba_xls(cfb, CFB.read(wb.vbaraw, {type: typeof wb.vbaraw == "string" ? "binary" : "buffer"}));
|
||||
return cfb;
|
||||
}
|
1334
bits/77_parsetab.js
1334
bits/77_parsetab.js
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user