Compare commits

..

168 Commits

Author SHA1 Message Date
51a8619000 version bump 0.19.1 2022-11-17 04:35:34 -05:00
e7e129e417 type fix (fixes #2828 h/t @younes-io) 2022-11-16 14:03:42 -05:00
df48489211 Numbers 12.2 skip ActivityStream.iwa 2022-11-06 21:58:41 -05:00
050f66ce1b version bump 0.19.0 2022-10-23 21:05:59 -04:00
2f329b64e2 DBF truncate numeric fields 2022-10-04 20:09:43 -04:00
515d1c6f2e mini refresh [ci skip] 2022-10-04 16:50:55 -04:00
654d6f98c3 stringify all 's' cell values (fixes #2795) 2022-09-28 23:08:10 -04:00
4ae4f0fad9 NUMBERS write multiple worksheets [ci skip] 2022-09-26 13:52:50 -04:00
Evan Bovie
1ca49a50bd
add display property to XLSX hyperlinks (#2791)
Resolves import bug in Google Sheets
2022-09-23 13:36:38 -04:00
81b231d866 version bump 0.18.12 2022-09-22 05:06:45 -04:00
1491302aa4 package.json exports types 2022-09-21 18:17:14 -04:00
bd5878e7c7 NUMBERS write up to ALL1000000 (h/t @masaccio) 2022-09-20 01:35:34 -04:00
Evan Bovie
4dd092a076 Add types to subpath exports in package.json 2022-09-18 23:26:24 -04:00
390910131
04dc18e742
fix vue3-table-lite demo url typo 2022-09-13 13:58:09 +08:00
6a5be04e3d Ś╫êëτ⌡ś and Š╫ěéτ⌡š 2022-09-09 16:59:22 -04:00
e90a61bf09 version bump 0.18.11 2022-09-06 02:18:12 -04:00
26cbfe37be DBF write encoding (fixes #2781 h/t @ZJS248) 2022-09-06 00:02:39 -04:00
df0e7b5f25 NUMBERS duration cell number format 2022-09-04 17:51:49 -04:00
6c9010f9d1 comment fallback (fixes #2779 h/t @AbhinanduReddy) 2022-09-02 03:30:10 -04:00
0a6ddcaf44 removed sheet_to_dif IIFE 2022-08-30 03:00:32 -04:00
reviewher
0de9479053
Fixed ESM default export 2022-08-22 21:51:24 -04:00
045adba80d parse ZIP64 length (fixes #2766 h/t @silvialeung) 2022-08-21 20:51:51 -04:00
wangkai53
199373e918 feat(98_esmxport): add esm default export 2022-08-17 09:52:36 +08:00
917a69e394 XLSX custprops strip ns [ci skip] 2022-08-15 01:20:14 -04:00
838ee58a49 update tests 2022-08-08 19:55:25 -04:00
Hafez
6bea47aaef allow reading base64 files from a dataURI scheme (#2763) 2022-08-08 16:41:08 -04:00
Garret Premo
aea2157036 Fix an issue where, if a file is corrupted in a specific way, the Record Type check would pass, but the length check would fail 2022-08-08 14:23:27 -04:00
fdbbf2d6bf precise time parse (h/t @ragearino @MyAddonsDev ) 2022-08-06 22:50:58 -04:00
c02eb14255 stox skip blank worksheets [ci skip] 2022-08-03 12:40:26 -04:00
d55b7a3063 numbers OperationStorage iwa warning 2022-07-31 19:48:04 -04:00
ba94ffba35 version bump 0.18.10 2022-07-25 22:27:52 -04:00
c03bc18803 package.json exports 2022-07-22 05:02:23 -04:00
scottysseus
9a36af0830 SSF time rounding tests
Co-authored-by: Joe Cool <snoopyjc@gmail.com>
2022-07-17 21:09:02 -04:00
Brian Hung
71b14b63da
package.json exports (vite compatibility) 2022-07-17 17:51:39 -04:00
6c41339fc0 proper subarray resolution 2022-07-16 20:02:22 -04:00
dbc30ef188 numbers parser prefer subarray 2022-07-13 06:10:24 -04:00
ef6d3086ac bun test 2022-07-12 00:30:22 -04:00
fad98cf64a bun utf16le workaround 2022-07-10 00:12:15 -04:00
ad1ce0d9b0 parsers expose original book type 2022-07-08 18:45:00 -04:00
61262617ec parse number values from RTF cells 2022-07-07 02:30:44 -04:00
Dhruv Gajjar
efa36be102
docs(license): Link added to license badge #2730 2022-07-05 14:28:21 +05:30
ecfa614dd8 parse icloud.com numbers exports 2022-07-05 02:52:55 -04:00
ee8b37b3a6 ODS XML Parse nit 2022-06-27 02:02:21 -04:00
4a31cb9810 warn on codepage override in mini build [ci skip] 2022-06-22 15:59:45 -04:00
a373597294 version bump 0.18.9 2022-06-09 00:45:22 -04:00
08f5678c98 ODS read/write number formats 2022-06-08 18:06:49 -04:00
4cc0412154 roundtrip 1904 date setting 2022-06-06 19:10:33 -04:00
83ddb4c120 unified autofilter defined name sync on export 2022-05-30 04:42:10 -04:00
5d18f82664 common XLSB name ranges 2022-05-27 16:26:39 -04:00
alonkh2
d4beb13723 (ssf) export choose_fmt (closes #2691) [ci skip] 2022-05-27 04:45:05 +03:00
e6ae86df55 XLSB/ODS write defined names 2022-05-24 21:45:55 -04:00
2022f7f4b0 version bump 0.18.8: dateless meridien time values 2022-05-22 19:51:41 -04:00
b7d3eae3b7 estk test [ci skip] 2022-05-20 04:56:18 -04:00
Thibaut
f1480ebd2e x-spreadsheet demo avoid parseFloat [ci skip] 2022-05-18 07:42:59 +02:00
9f8ec25845 refresh browser tests 2022-05-17 17:48:05 -04:00
0b72cc592b wsl build sequence fixes 2022-05-16 21:26:22 -04:00
5d49b7326d sheet_set_array_formula adjust range 2022-05-15 23:39:11 -04:00
e43071fc64 more lotus 1-2-3 formula functions 2022-05-10 04:02:52 -04:00
2ff31276b0 slk defined name parse 2022-05-09 02:49:17 -04:00
cfe4da2e56 clarify Multiplan DOS support 2022-05-05 02:27:25 -04:00
calcscout
f38191d266 HTML DOM parser skip links with inline javascript 2022-05-03 03:59:29 -04:00
Sukka
47eeaa367d
docs: replace all git.io link (#2666) 2022-04-28 03:59:37 -04:00
87e826f299 SYLK process 1904 dates (fixes #1545 h/t @Slayess) 2022-04-27 04:26:35 -04:00
eee39946e3 version bump 0.18.7 2022-04-25 18:13:46 -04:00
694cdcb75a QPW and newline tests 2022-04-25 05:30:09 -04:00
Łukasz Kaczmarek
fb85dfbedc https://github.com/SheetJS/sheetjs/issues/2660
- fix Invalid character (https://www.w3.org/TR/REC-xml/#charsets)
2022-04-25 10:21:00 +02:00
evilmanimani
c641efbd0a
Fixed 'ReadableStream' function example.
The function as it is written doesn't work, replaced reference to 'arr' with 'buffers' and added '{type: "array"}' to XLSX.read arguments.
2022-04-24 14:55:50 -07:00
8124fcbae0 newline normalization 2022-04-20 13:31:11 -04:00
e6b6f382c0 xsd:boolean strict truthy parsing (fixes #2658)
Co-authored-by: Dmitry Kostochko <dkostochko@users.noreply.github.com>
2022-04-18 17:31:41 -04:00
edulecca
90747905ad Fixed writeFileAsync doc [ci skip] 2022-04-18 03:23:01 +00:00
af421e3161 xlsx-cli 1.1.3 [ci skip] 2022-04-16 02:18:29 -04:00
79e2773b58 x-spreadsheet demo [ci skip] fixes #2656 2022-04-15 19:06:45 -04:00
ed18acd63d version bump 0.18.6 2022-04-14 03:27:38 -04:00
b1dca24a0b next.js demo refresh [ci skip] 2022-04-12 07:59:15 -04:00
19e0f8f358 NUMBERS write to max column (ALL) 2022-04-11 00:11:47 -04:00
Joe Cool
9ca1243448 a/p use actual format case (fixes #2570) 2022-04-10 01:41:52 -04:00
reviewher
e0fc89246a Fix bad google sheets format 'd.m' 2022-04-05 19:14:12 -07:00
Gwanghyeon Gim
3b19491ee9 fix readme link [ci skip] 2022-04-05 15:11:09 +09:00
623364a148 extendscript workaround for esbuild bug (#2629) 2022-03-27 15:02:51 -04:00
3c23b6ce35 test for KEY/PAGES files 2022-03-26 17:50:27 -04:00
reviewher
d5b54855ec NUMBERS write merges [ci skip] 2022-03-24 17:12:55 -07:00
0400a87e62 version bump 0.18.5: basic NUMBERS write 2022-03-24 09:59:49 -04:00
reviewher
e69ecd42a6 remove broken CDNs [ci skip] 2022-03-22 15:38:02 -07:00
0f0b3de821 popping IIFEs to appease rollup tree shaking 2022-03-22 16:19:05 -04:00
2f274dd48c book_append_sheet rolling names 2022-03-20 22:01:28 -04:00
Andrew Lessels
a5b387716c Fix rawNumber support inside sheet_to_json 2022-03-20 16:29:24 +11:00
69bb1e79a3 "side-effect free" 2022-03-19 21:54:41 -04:00
reviewher
90a7b4ee91 remove SSF._general_int 2022-03-16 21:38:06 -07:00
Vitor Santos
61487bcb76 use TextEncoder for zip strings (fixes #2616) 2022-03-16 21:39:30 -04:00
61b17a8bc8 version bump 0.18.4 2022-03-15 23:23:39 -04:00
0xc0Der
2cbc28d6ed vue-modify demo [ci skip] 2022-03-15 12:46:06 -04:00
9a3294c955 phasing out patterns with side effects
- add ssf test to actions
- support for threaded comments (fixes #2542)
2022-03-14 02:51:33 -04:00
0xc0Der
f443aa8475 react-modify demo [ci skip]
Co-authored-by: SheetJS <dev@sheetjs.com>
2022-03-12 17:15:34 +02:00
b9e7d0d8f4 XLSB/XLS Record Name refactor 2022-03-12 09:05:57 -05:00
reviewher
02707848ad skipHidden for sheet_to_json [ci skip] 2022-03-11 16:26:02 -08:00
0044f3be82 clean cptable global pollution 2022-03-11 01:16:24 -05:00
0b6ebc67da DBF preserve field properties
- DBF write type N and roundtrip C length (fixes #1888 h/t@bandizsolt)
- clean up xhr demo (fixes #2604 h/t @UP2022742)
- clean up vue / nuxt demo
2022-03-10 00:31:13 -05:00
KurtMar
b3793e2ea7 HTML Parsing fix misaligned cells (fixes #1621) 2022-03-09 22:24:43 +02:00
b738e5d3f1 pulling ssf into main project [ci skip] 2022-03-09 06:31:53 -05:00
d97fce4424 ssf repo reorg 2022-03-09 06:28:19 -05:00
c6a86cfe98 make stream utils available to Node ESM
- sheet_to_csv blankrows/strip (fixes #2274 h/t @dmongit)
- sheet_to_json fix dedupe (see #2460 h/t @giuliohome)
- mini build browser tests
2022-03-08 20:44:10 -05:00
a32b30414b CSV omit trailing record separator [ci skip] 2022-03-07 20:17:32 -05:00
Rohan Dhamapurkar
467020fc69 stream.to_json end (fixes #1779) 2022-03-08 05:38:45 +05:30
reviewher
ba3280ee8a Demos [ci skip] 2022-03-07 00:46:23 -08:00
6ede9dcfb9 xlsx-cli v1.1.2 [ci skip] 2022-03-03 14:11:20 -05:00
e71eeda4d2 updated travis tests
Co-authored-by: Garrett Luu <garrettluu131@gmail.com>
2020-07-02 02:24:11 -04:00
6cdd7ac629 ssf-cli 1.0.1 [ci skip] 2020-06-27 20:21:36 -04:00
577070b8d7 version bump 0.11.2
- simplified and documented General format processing
- moved CLI to ssf-cli package (h/t @garrettluu)
2020-06-27 18:39:56 -04:00
Garrett Luu
15c017bc5b CLI refactor
* Moved cli to packages/ssf-cli

* Modified bin in package.json files
2020-06-24 12:45:39 -07:00
885b27fda5 version bump 0.11.1
- support 上午/下午 (like AM/PM, supported in en-US and other locales)
- `format(number)` guess format if table is missing value
- removed entry 65535 from table
2020-06-17 01:13:59 -04:00
b00f11ce33 version bump 0.11.0 2020-05-09 01:00:04 -04:00
tryan
791bf255f5 handle negative numbers in parens 2020-05-09 00:57:20 -04:00
9eaba42493 version bump 0.10.3
- toString suffices for integers in the general format
- separate currency sigil token
2020-03-08 18:32:23 -04:00
fefb415467 fmt_is_date properly handle string literals 2020-01-25 21:32:32 -05:00
e267d1d667 flow switch to module.exports 2018-04-21 11:03:20 -04:00
Bryan Braun
e3efc1ad7d
Add a section to the README for examples. 2018-02-24 11:39:12 -05:00
f6de1799c4 version bump 0.10.2: infrastructure
- typescript definitions
- fixed vulnerable regexes (h/t @davisjam)
2018-02-20 22:35:31 -05:00
71f827c4fa version bump 0.10.1: fixed deps 2017-07-31 22:28:37 -04:00
80c1a0fec7 version bump 0.10.0:
- pin dependencies
- JS Date object support
- resolved some out of bounds accesses
- load scans for available index if not specified
- flow improvements
2017-07-28 16:24:37 -04:00
aa25491492 version bump 0.9.4
- correct am/pm to AM/PM and a/p to A/P (h/t @vvaldersteins)
- trailing hashes (h/t @kuhu19)
2017-06-08 20:59:13 -04:00
Valters Valdersteins
73d8168a9e am/pm time format fix for google sheets 2017-06-08 13:36:17 +03:00
5bcd966b22 version bump 0.9.3
- fix rollover for near-integral dates (h/t @HuFlungDu)
- removed ssf.md from npm dist
2017-05-16 15:22:19 -04:00
842415c41d ExtendScript
- explicit logical association (&& and ||)
- test for negative pounds (fixes #17 h/t @cesarhermosilla)
- eslint recommended
2017-05-10 01:57:43 -04:00
d273a28d54 version bump 0.9.2: more formats
- do not consume trailing currency symbol (fixes #19 h/t @wilg)
- detect minutes following absolute hour (fixes #23 h/t @tedbeer)
- verify the miscellaneous formats (fixes #27 h/t @reviewher)
2017-05-07 23:49:05 -04:00
f335d310ac version bump 0.9.1: dateNF + sign
- dateNF option for default date format override
- general format renders undefined/null as empty string
- ignore text elements when searching for decimal point
- bubble negative sign to the front when format starts with text
- fixes for eslint + closure
- updated frac to 1.0.6

Issues:
- fixes #10 h/t @adamgundy @SegFaultx64 @RichardCzechowski
- fixes #15 h/t @wilg
- fixes #25 h/t @dougschiller
- fixes #26 h/t @rjmcguire
2017-04-30 02:40:29 -04:00
ecb4515847 Use charAt for IE6-8 compat (fixes #9) 2017-03-24 01:07:28 -04:00
56b414b496 increased travis timeout 2017-03-21 10:31:33 -04:00
354f2bce4f version bump 0.9.0: is_date helper 2017-03-21 03:50:08 -04:00
Max Walker
4fd36de071 rounding carry 2017-03-16 20:33:29 -04:00
695452bffb flow typing and cleanup 2017-03-12 03:34:36 -04:00
097f026d03 version bump 0.8.1: more weird formats
- handle formats like ???00.00
- return empty string with bad dates under A/P and AM/PM formats
2014-06-24 20:07:30 -04:00
e32a2894c4 version bump 0.8.0: performance
- separate i4/r8 code (core functions optimized by v8)
- prefer faster methods when convenient
- node-based performance tests
2014-06-13 11:02:06 -04:00
9f4aa161e6 version bump 0.7.1: performance
- eliminated functional constructs
- simplified fraction handling
- better linting w/jscs
2014-06-04 20:14:59 -04:00
4183a44351 version bump 0.7.0: more intelligent tokenizer
- Literal characters between numbers (fixes #7, h/t @sysarchitect)
- .0/.00/.000 recognized as potential date tokens
- s+.0+ generates two tokens (with proper handling for `hh .00 .000`)
- proper handling of format strings with mixed 0 and #
2014-05-21 21:16:26 -07:00
82ead811b7 README fix CI badge [ci skip] 2014-04-25 11:27:27 -07:00
2dd9c7ec99 version bump 0.6.5: eliminating bad idioms
- cleaned up implicit boolean to number conversions
- web demo improved (h/t /u/SpsD3GoiFSmXBAl on reddit)
2014-04-25 11:22:36 -07:00
c156693778 version bump 0.6.4: alternate forms with literal -
Some versions of Excel render formats with literal hyphens, like `00000\-0000` that
should be properly handled
2014-04-03 01:11:44 -07:00
be19bcd01e version bump 0.6.3: B2 stubs, b format
- B2 hijri stubs (TODO: find the algorithm)
- b* correspond to the equivalent year in buddhist calendar
2014-04-02 11:47:03 -07:00
95b338304b whitespace and semicolons to satiate jshint 2014-03-29 03:34:43 -07:00
af23ae85b4 version bump 0.6.2: special formats
- zip + 4
- telephone
- better handling of conditional formats
2014-03-29 02:41:59 -07:00
5c12b601fa version bump 0.6.1: ** #,###,#00,000.00,**
Due to IEEE754 overflow, there are slight differences in one order of magnitude.
2014-03-28 14:28:39 -07:00
e2b0e6e0de coveralls target uses min test
coveralls target was timing out on travis :/
2014-03-27 14:31:10 -07:00
70ec8b0769 version bump 0.6.0: proper time rounding
based on the actual time format, date codes are properly rounded.

All time tests pass :)
2014-03-27 12:50:19 -07:00
c428205723 version bump 0.5.12: correcting for subseconds
h/t @notatestuser

Fixes https://github.com/SheetJS/ssf/issues/5

Also fixes https://github.com/SheetJS/js-xlsx/issues/51
2014-03-27 11:38:12 -07:00
4404d216c2 version bump 0.5.11: improper fractions
- ??/?? and friends
- stub for 'g' date format
2014-03-25 01:48:52 -07:00
b2940bac21 version bump 0.5.10: support trailing commas 2014-03-25 00:42:14 -07:00
0b3732c443 version bump 0.5.9: strip leading # before 0 2014-03-18 20:58:45 -07:00
02285784a7 adding coveralls badge [ci skip] 2014-02-17 04:28:06 -05:00
703b051c15 version bump 0.5.8: 0.##-type formats
- cleaned up tower of cases of the form /^#,##0.0+$/
- formats like 0.## handled
2014-02-17 03:29:07 -05:00
a866c9eabf version bump 0.5.7: addressing extraneous '['
- extraneous '[' does not cause infinite loop
- dates follow excel form (`yyyyyy` treated as `yyyy`)
- more general exponential form (more tests)
- unreachable default cases removed
- 100% test coverage
- added test_min and cov_min targets
2014-02-11 14:20:34 -05:00
71a974653d added gh-pages demo 2014-02-11 00:46:45 -05:00
9cef36086c version bump 0.5.6: exponential love
- better handling of exponential formats (all tests enabled)
- euro symbol recognized
2014-02-11 00:33:45 -05:00
2f9e0dbc01 version bump 0.5.5: eliminate double-negatives 2014-01-29 20:43:21 -05:00
e5fe385335 version bump 0.5.4: empty text is empty 2014-01-28 20:02:46 -05:00
216fe0459e version bump 0.5.3: 時分秒
- zh-tw 56 ("上午/下午 "hh"時"mm"分"ss"秒 " currently hardcoded)
- 65535 -> general (silly writers generating noncompliant formats)
- more general handling of #/0-based formats (removed hardcoded cases)
- more general fraction handling (up to 7 digit denominators)
- date comma separators
- mysterious LO -?? formats (really should be -##)
2014-01-22 23:23:34 -05:00
b0b3ffea84 version bump 0.5.2: cleanup
more formats:
o fractional seconds
o absolute time formats
o generalized engineering notation
o better resolution in splitting format strings
o support for LO uppercase date+time formats

other changes
- no more prototype pollution
- many many more tests
- passes jshint
- code coverage: blanket + coveralls + travis
- npmignore test files
2014-01-20 03:37:48 -05:00
c299585bfb version bump 0.5.1: more fixes needed for xls
- Updated frac to 0.3.1 (issue with numbers exceeding 2**32)
- Invalid dates render empty string
- Sub-second string format
- First steps towards Engineering format
- Fraction formats don't render blanks in the case of zero
- Trailing spaces removed
- More implied tests
2014-01-12 03:31:44 -05:00
d31879d702 version bump 0.5.0: cleanup
- removed ssf_node.js: scripts should define DO_NOT_EXPORT_SSF to prevent export
- added ssf binary
- updated frac to 0.3.0
- entire table can be pulled and saved
- choose_fmt and format functions can take an external table
- LICENSE year updated
- removed unused tests
2014-01-10 14:09:11 -05:00
acdc0d5fff support for LO Calc's 'GENERAL' format 2014-01-03 11:45:11 -05:00
e9482bfa26 version bump 0.4.1: terminating infinite loop
Infinite loop caused by invalid format string without proper end check.  It was
introduced :)
2013-12-31 11:38:31 -05:00
43f8f00ef5 version bump 0.4.0: improvements across the board
- Proper fraction handling (using frac.cont)
- Better handling of negative number cases
- More tests!
2013-12-26 17:35:42 -05:00
5a49d84ae6 version bump 0.3.1: vagaries in the general format 2013-12-16 19:03:07 -05:00
fc9835e819 version bump 0.3.0: support for standard formats
Many cases are hard-coded and should be parsed before version 1.0
2013-12-16 10:36:22 -05:00
e1b753f797 tweaking general format
[ci skip]
2013-12-15 01:13:59 -05:00
30c8c4c071 version bump 0.2.3: negative number love 2013-12-14 23:50:54 -05:00
cfb6a520ae version bump 0.2.2: fraction love 2013-12-14 21:36:52 -05:00
22f04832e3 version bump 0.2.1: more support for implied types 2013-12-13 22:28:57 -05:00
e176abd8de Initial commit 2013-12-06 11:49:25 -05:00
671 changed files with 2465782 additions and 55061 deletions

12
.eslintmjs Normal file

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

@ -13,6 +13,7 @@
"no-bitwise": 0,
"no-console": 0,
"no-control-regex": 0,
"no-unused-vars": 1,
"no-empty": 0,
"no-trailing-spaces": 2,
"no-use-before-define": [ 1, {

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

2
.gitattributes vendored

@ -13,3 +13,5 @@ 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

6
.github/ISSUE_TEMPLATE/config.yml vendored Normal file

@ -0,0 +1,6 @@
blank_issues_enabled: false
contact_links:
- name: Issues and Questions
url: https://git.sheetjs.com/sheetjs/sheetjs/issues
about: Please report issues to the official code repository.

20
.github/workflows/bun.yml vendored Normal file

@ -0,0 +1,20 @@
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'

@ -3,29 +3,10 @@ name: 'Tests: deno 1.x'
on: [pull_request, push]
jobs:
# small test
misc:
runs-on: ubuntu-latest
env:
FMTS: misc
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 test.ts
# full test
full:
name: 'full (with codepage)'
runs-on: ubuntu-latest
env:
FMTS: misc # TODO: remove this
steps:
- uses: actions/checkout@v2
- uses: denoland/setup-deno@main
@ -38,4 +19,21 @@ jobs:
- 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 test.ts
- 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

@ -82,6 +82,7 @@ jobs:
- 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+'

@ -35,6 +35,7 @@ jobs:
- 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'

@ -51,6 +51,7 @@ jobs:
- 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]

1
.gitignore vendored

@ -29,6 +29,7 @@ tmp
*.[rR][tT][fF]
*.[eE][tT][hH]
*.[nN][uU][mM][bB][eE][rR][sS]
*.[mM][oO][dD]
*.123
*.htm
*.html

1
.gitmodules vendored

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

@ -8,6 +8,7 @@ index.html
misc/
node_modules
*.tgz
*.jsx
_book
book.json
tmp
@ -19,17 +20,21 @@ tmp
*.[pP][dD][fF]
*.[sS][lL][kK]
*.socialcalc
*.[xX][lL][sSwWcCaAtTmM]
*.[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][hH]
*.[nN][uU][mM][bB][eE][rR][sS]
*.[mM][oO][dD]
*.123
*.htm
*.html
@ -42,6 +47,7 @@ tmp
.spelling
.eslintignore
.eslintrc
.eslintmjs
.jshintrc
xlsx.mini.js
CONTRIBUTING.md
@ -54,6 +60,9 @@ shim.js
test.js
test.mjs
test.ts
test.mts
testnocp.ts
testbun.mjs
.jscs.json
.gitmodules
.travis.yml

@ -1,5 +1,6 @@
# xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com
SheetJS
sheetjs
js-xlsx
xls
xlsb
@ -38,18 +39,22 @@ CommonJS
Deno
Ethercalc
ExtendScript
InDesign
IndexedDB
JavaScriptCore
LocalStorage
NestJS
NPM
Nuxt.js
Nuxt
PhantomJS
Photoshop
Redis
RequireJS
Rollup
SessionStorage
SQLite
SystemJS
Vite
VueJS
WebKit
WebSQL
@ -82,6 +87,7 @@ FileReader
JS
NoSQL
README
UTF-8
UTF-16
VBScript
XHR
@ -93,6 +99,7 @@ codepage
config
customizable
datagrid
dataset
deduplication
destructuring
embeddable
@ -117,6 +124,7 @@ utils
commonjs
async
uncheck
vendoring
- demos/altjs/README.md
ChakraCore

@ -4,6 +4,74 @@ This log is intended to keep track of backwards-incompatible changes, including
but not limited to API changes and file location changes. Minor behavioral
changes may not be included if they are not expected to break existing code.
## v0.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

@ -9,7 +9,7 @@ HTMLLINT=index.html
MINITGT=xlsx.mini.js
MINIFLOW=xlsx.mini.flow.js
MINIDEPS=$(shell cat mini.lst)
MINIDEPS=$(shell cat misc/mini.lst)
ESMJSTGT=xlsx.mjs
ESMJSDEPS=$(shell cat misc/mjs.lst)
@ -47,8 +47,8 @@ $(ESMJSTGT): $(ESMJSDEPS)
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 $^ $@
#bits/18_cfb.js: node_modules/cfb/xlscfb.flow.js
# cp $^ $@
$(TSBITS): bits/%: modules/%
cp $^ $@
@ -59,7 +59,7 @@ $(MTSBITS): misc/%: modules/%
.PHONY: clean
clean: ## Remove targets and build artifacts
rm -f $(TARGET) $(FLOWTARGET)
rm -f $(TARGET) $(FLOWTARGET) $(ESMJSTGT) $(MINITGT) $(MINIFLOW)
.PHONY: clean-data
clean-data:
@ -70,7 +70,7 @@ init: ## Initial setup for development
git submodule init
git submodule update
#git submodule foreach git pull origin master
git submodule foreach make
git submodule foreach make all
mkdir -p tmp
DISTHDR=misc/suppress_export.js
@ -93,7 +93,9 @@ dist: dist-deps $(TARGET) bower.json ## Prepare JS files for distribution
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 <(head -n 1 bits/00_header.js) shim.js $(DISTHDR) $(REQS) dist/$(TARGET) > dist/$(LIB).extendscript.js
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)
@ -109,19 +111,13 @@ BYTEFILEC=dist/xlsx.{full,core,mini}.min.js
BYTEFILER=dist/xlsx.extendscript.js xlsx.mjs
.PHONY: bytes
bytes: ## Display minified and gzipped file sizes
@for i in $(BYTEFILEC); do printj "%-30s %7d %10d" $$i $$(wc -c < $$i) $$(gzip --best --stdout $$i | wc -c); done
@for i in $(BYTEFILER); do printj "%-30s %7d" $$i $$(wc -c < $$i); done
@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
.PHONY: graph
graph: formats.png legend.png ## Rebuild format conversion graph
misc/formats.svg: misc/formats.dot
circo -Tsvg -o$@ $<
misc/legend.svg: misc/legend.dot
dot -Tsvg -o$@ $<
formats.png legend.png: %.png: misc/%.svg
node misc/coarsify.js misc/$*.svg misc/$*.svg.svg
npx svgexport misc/$*.svg.svg $@ 0.5x
.PHONY: git
git: ## show version string
@echo "$$(node -pe 'require("./package.json").version')"
.PHONY: nexe
nexe: xlsx.exe ## Build nexe standalone executable
@ -141,16 +137,28 @@ pkg: bin/xlsx.njs xlsx.js ## Build pkg standalone executable
test mocha: test.js ## Run test suite
mocha -R spec -t 30000
#* To run tests for one format, make test_<fmt>
#* To run the core test suite, make test_misc
.PHONY: test-esm
test-esm: test.mjs ## Run Node ESM test suite
npx mocha -r esm -R spec -t 30000 $<
npx -y mocha@9 -R spec -t 30000 $<
test.ts: test.mts
node -pe 'var data = fs.readFileSync("'$<'", "utf8"); data.split("\n").map(function(l) { return l.replace(/^describe\((.*?)function\(\)/, "Deno.test($$1async function(t)").replace(/\b(?:it|describe)\((.*?)function\(\)/g, "await t.step($$1async function(t)").replace("assert.ok", "assert.assert"); }).join("\n")' > $@
.PHONY: test-bun
test-bun: testbun.mjs ## Run Bun test suite
bun $<
.PHONY: test-deno
test-deno: test.ts ## Run Deno test suite
deno test --allow-env --allow-read --allow-write $<
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 $<
#* To run tests for one format, make test_<fmt>
#* To run the core test suite, make test_misc
TESTFMT=$(patsubst %,test_%,$(FMT))
.PHONY: $(TESTFMT)
$(TESTFMT): test_%:
@ -162,10 +170,20 @@ $(TESTESMFMT): test-esm_%:
FMTS=$* make test-esm
TESTDENOFMT=$(patsubst %,test-deno_%,$(FMT))
.PHONY: $(TESTESMFMT)
.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
@ -176,7 +194,7 @@ ctest: ## Build browser test fixtures
.PHONY: ctestserv
ctestserv: ## Start a test server on port 8000
@cd tests && python -mSimpleHTTPServer
@cd tests && python -mSimpleHTTPServer || python3 -mhttp.server || npx -y http-server -p 8000 .
## Code Checking
@ -185,16 +203,16 @@ 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 $(TARGET) $(AUXTARGETS) $(CMDS) $(HTMLLINT) package.json bower.json
@./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
.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)
@./node_modules/.bin/jscs $(TARGET) $(AUXTARGETS) test.js
@if [ -x "$(CLOSURE)" ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi
.PHONY: tslint
@ -207,6 +225,10 @@ tslint: $(TARGET) ## Run typescript checks
flow: lint ## Run flow checker
@./node_modules/.bin/flow check --all --show-all-errors --include-warnings
.PHONY: mjslint
mjslint: $(ESMJSTGT) ## Lint the ESM build
@npx eslint -c .eslintmjs $<
.PHONY: cov
cov: misc/coverage.html ## Run coverage test
@ -223,22 +245,8 @@ misc/coverage.html: $(TARGET) test.js
coveralls: ## Coverage Test + Send to coveralls.io
mocha --require blanket --reporter mocha-lcov-reporter -t 30000 | node ./node_modules/coveralls/bin/coveralls.js
READEPS=$(sort $(wildcard docbits/*.md))
README.md: $(READEPS)
awk 'FNR==1{p=0}/#/{p=1}p' $^ | tr -d '\15\32' > $@
.PHONY: readme
readme: README.md ## Update README Table of Contents
markdown-toc -i README.md
.PHONY: book
book: readme graph ## Update summary for documentation
printf "# Summary\n\n- [xlsx](README.md#sheetjs-js-xlsx)\n" > misc/docs/SUMMARY.md
markdown-toc README.md | sed 's/(#/(README.md#/g'>> misc/docs/SUMMARY.md
<README.md grep -vE "(details|summary)>" > misc/docs/README.md
DEMOMDS=$(sort $(wildcard demos/*/README.md))
MDLINT=$(DEMOMDS) $(READEPS) demos/README.md
MDLINT=$(DEMOMDS) README.md demos/README.md
.PHONY: mdlint
mdlint: $(MDLINT) ## Check markdown documents
./node_modules/.bin/alex $^

4365
README.md

File diff suppressed because it is too large Load Diff

@ -44,6 +44,7 @@ program
.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)')
@ -90,6 +91,7 @@ var workbook_formats = [
['xls', 'xls', 'xls'],
['xla', 'xla', 'xla'],
['biff5', 'biff5', 'xls'],
['numbers', 'numbers', 'numbers'],
['ods', 'ods', 'ods'],
['fods', 'fods', 'fods'],
['wk3', 'wk3', 'wk3']
@ -154,6 +156,7 @@ if(program.all) {
opts.cellStyles = true;
opts.sheetStubs = true;
opts.cellDates = true;
wopts.cellFormula = true;
wopts.cellStyles = true;
wopts.sheetStubs = true;
wopts.bookVBA = true;
@ -191,6 +194,10 @@ if(program.props) {
/* full workbook formats */
workbook_formats.forEach(function(m) { if(program[m[0]] || isfmt(m[0])) {
wopts.bookType = m[1];
if(wopts.bookType == "numbers") try {
var XLSX_ZAHL = require("../dist/xlsx.zahl");
wopts.numbers = XLSX_ZAHL;
} catch(e) {}
if(wb) X.writeFile(wb, program.output || sheetname || ((filename || "") + "." + m[2]), wopts);
process.exit(0);
} });

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

@ -1 +1 @@
XLSX.version = '0.18.3';
XLSX.version = '0.19.1';

@ -1,15 +1,9 @@
var current_codepage = 1200, current_ansi = 1252;
/*:: declare var cptable:any; */
/*global cptable:true, window */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
if(typeof cptable === 'undefined') {
if(typeof global !== 'undefined') global.cptable = require('./dist/cpexcel.js');
else if(typeof window !== 'undefined') window.cptable = require('./dist/cpexcel.js');
}
}
var $cptable;
var VALID_ANSI = [ 874, 932, 936, 949, 950, 10000 ];
for(var i = 0; i <= 8; ++i) VALID_ANSI.push(1250 + i);
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 */
@ -63,17 +57,20 @@ var debom = function(data/*:string*/)/*:string*/ {
var _getchar = function _gc1(x/*:number*/)/*:string*/ { return String.fromCharCode(x); };
var _getansi = function _ga1(x/*:number*/)/*:string*/ { return String.fromCharCode(x); };
if(typeof cptable !== 'undefined') {
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))); }
if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return $cptable.utils.decode(1200, char_codes(data.slice(2))); }
return data;
};
_getchar = function _gc2(x/*:number*/)/*:string*/ {
if(current_codepage === 1200) return String.fromCharCode(x);
return cptable.utils.decode(current_codepage, [x&255,x>>8])[0];
return $cptable.utils.decode(current_codepage, [x&255,x>>8])[0];
};
_getansi = function _ga2(x/*:number*/)/*:string*/ {
return cptable.utils.decode(current_ansi, [x])[0];
return $cptable.utils.decode(current_ansi, [x])[0];
};
cpdoit();
}

@ -1,47 +1,69 @@
var Base64 = function() {
var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
return {
encode: function(input) {
var o = "";
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
for (var i = 0; i < input.length; ) {
c1 = input.charCodeAt(i++);
e1 = c1 >> 2;
c2 = input.charCodeAt(i++);
e2 = (c1 & 3) << 4 | c2 >> 4;
c3 = input.charCodeAt(i++);
e3 = (c2 & 15) << 2 | c3 >> 6;
e4 = c3 & 63;
if (isNaN(c2)) {
e3 = e4 = 64;
} else if (isNaN(c3)) {
e4 = 64;
}
o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4);
}
return o;
},
decode: function(input) {
var o = "";
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
input = input.replace(/[^\w\+\/\=]/g, "");
for (var i = 0; i < input.length; ) {
e1 = map.indexOf(input.charAt(i++));
e2 = map.indexOf(input.charAt(i++));
c1 = e1 << 2 | e2 >> 4;
o += String.fromCharCode(c1);
e3 = map.indexOf(input.charAt(i++));
c2 = (e2 & 15) << 4 | e3 >> 2;
if (e3 !== 64) {
o += String.fromCharCode(c2);
}
e4 = map.indexOf(input.charAt(i++));
c3 = (e3 & 3) << 6 | e4;
if (e4 !== 64) {
o += String.fromCharCode(c3);
}
}
return o;
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_decode(input) {
var o = "";
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
input = input.replace(/^data:([^\/]+\/[^\/]+)?;base64\,/, "").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;
}

@ -1,26 +1,33 @@
var has_buf = (typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.node);
var has_buf = /*#__PURE__*/(function() { return typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.node; })();
var Buffer_from = /*::(*/function(){}/*:: :any)*/;
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;
})();
if(typeof Buffer !== 'undefined') {
var nbfs = !Buffer.from;
if(!nbfs) try { Buffer.from("foo", "utf8"); } catch(e) { nbfs = true; }
Buffer_from = nbfs ? function(buf, enc) { return (enc) ? new Buffer(buf, enc) : new Buffer(buf); } : Buffer.from.bind(Buffer);
// $FlowIgnore
if(!Buffer.alloc) Buffer.alloc = function(n) { return new Buffer(n); };
// $FlowIgnore
if(!Buffer.allocUnsafe) Buffer.allocUnsafe = function(n) { return new Buffer(n); };
}
function new_raw_buf(len/*:number*/) {
/* jshint -W056 */
return has_buf ? Buffer.alloc(len) : typeof Uint8Array != "undefined" ? new Uint8Array(len) : new Array(len);
if(has_buf) return Buffer.alloc ? Buffer.alloc(len) : new Buffer(len);
return typeof Uint8Array != "undefined" ? new Uint8Array(len) : new Array(len);
/* jshint +W056 */
}
function new_unsafe_buf(len/*:number*/) {
/* jshint -W056 */
return has_buf ? Buffer.allocUnsafe(len) : typeof Uint8Array != "undefined" ? new Uint8Array(len) : new Array(len);
if(has_buf) return Buffer.allocUnsafe ? Buffer.allocUnsafe(len) : new Buffer(len);
return typeof Uint8Array != "undefined" ? new Uint8Array(len) : new Array(len);
/* jshint +W056 */
}
@ -55,6 +62,23 @@ function ab2a(data/*:ArrayBuffer|Uint8Array*/)/*:Array<number>*/ {
return o;
}
var bconcat = has_buf ? function(bufs) { return Buffer.concat(bufs.map(function(buf) { return Buffer.isBuffer(buf) ? buf : Buffer_from(buf); })); } : function(bufs) {
if(typeof Uint8Array !== "undefined") {
var i = 0, maxlen = 0;
for(i = 0; i < bufs.length; ++i) maxlen += bufs[i].length;
var o = new Uint8Array(maxlen);
var len = 0;
for(i = 0, maxlen = 0; i < bufs.length; maxlen += len, ++i) {
len = bufs[i].length;
if(bufs[i] instanceof Uint8Array) o.set(bufs[i], maxlen);
else if(typeof bufs[i] == "string") o.set(new Uint8Array(s2a(bufs[i])), maxlen);
else o.set(new Uint8Array(bufs[i]), maxlen);
}
return o;
}
return [].concat.apply([], bufs.map(function(buf) { return Array.isArray(buf) ? buf : [].slice.call(buf); }));
};
function utf8decode(content/*:string*/) {
var out = [], widx = 0, L = content.length + 250;
var o = new_raw_buf(content.length + 255);
@ -87,21 +111,4 @@ function utf8decode(content/*:string*/) {
return bconcat(out);
}
var bconcat = 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") { throw "wtf"; }
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); }));
};
var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/g;

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

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

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

@ -1,6 +1,4 @@
var DO_NOT_EXPORT_CFB = true;
/*::
declare var Base64:any;
declare var ReadShift:any;
declare var CheckField:any;
declare var prep_blob:any;
@ -22,10 +20,9 @@ declare var Buffer_from:any;
/* vim: set ts=2: */
/*jshint eqnull:true */
/*exported CFB */
/*global module, require:false, process:false, Buffer:false, Uint8Array:false, Uint16Array:false */
/*global Uint8Array:false, Uint16Array:false */
/*::
declare var DO_NOT_EXPORT_CFB:?boolean;
type SectorEntry = {
name?:string;
nodes?:Array<number>;
@ -42,14 +39,8 @@ type CFBFiles = {[n:string]:CFBEntry};
/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*exported CRC32 */
var CRC32;
(function (factory) {
/*jshint ignore:start */
/*eslint-disable */
factory(CRC32 = {});
/*eslint-enable */
/*jshint ignore:end */
}(function(CRC32) {
var CRC32 = /*#__PURE__*/(function() {
var CRC32 = {};
CRC32.version = '1.2.0';
/* see perf/crc32table.js */
/*global Int32Array */
@ -137,11 +128,12 @@ CRC32.table = T0;
CRC32.bstr = crc32_bstr;
CRC32.buf = crc32_buf;
CRC32.str = crc32_str;
}));
return CRC32;
})();
/* [MS-CFB] v20171201 */
var CFB = (function _CFB(){
var CFB = /*#__PURE__*/(function _CFB(){
var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
exports.version = '1.2.1';
exports.version = '1.2.2';
/* [MS-CFB] 2.6.4 */
function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
var L = l.split("/"), R = r.split("/");
@ -219,8 +211,15 @@ function parse_extra_field(blob/*:CFBlob*/)/*:any*/ {
if(flags & 4) p.ctime = blob.read_shift(4);
}
if(p.mtime) p.mt = new Date(p.mtime*1000);
}
break;
} break;
/* ZIP64 Extended Information Field */
case 0x0001: {
var sz1 = blob.read_shift(4), sz2 = blob.read_shift(4);
p.usz = (sz2 * Math.pow(2,32) + sz1);
sz1 = blob.read_shift(4); sz2 = blob.read_shift(4);
p.csz = (sz2 * Math.pow(2,32) + sz1);
// NOTE: volume fields are skipped
} break;
}
blob.l = tgt;
o[type] = p;
@ -228,7 +227,7 @@ function parse_extra_field(blob/*:CFBlob*/)/*:any*/ {
return o;
}
var fs/*:: = require('fs'); */;
function get_fs() { return fs || (fs = require('fs')); }
function get_fs() { return fs || (fs = _fs); }
function parse(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/ {
if(file[0] == 0x50 && file[1] == 0x4b) return parse_zip(file, options);
if((file[0] | 0x20) == 0x6d && (file[1]|0x20) == 0x69) return parse_mad(file, options);
@ -307,7 +306,7 @@ sleuth_fat(difat_start, difat_sec_cnt, sectors, ssz, fat_addrs);
/** Chains */
var sector_list/*:SectorList*/ = make_sector_list(sectors, dir_start, fat_addrs, ssz);
sector_list[dir_start].name = "!Directory";
if(dir_start < sector_list.length) sector_list[dir_start].name = "!Directory";
if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
sector_list[fat_addrs[0]].name = "!FAT";
sector_list.fat_addrs = fat_addrs;
@ -441,7 +440,7 @@ function sleuth_fat(idx/*:number*/, cnt/*:number*/, sectors/*:Array<RawBytes>*/,
if((q = __readInt32LE(sector,i*4)) === ENDOFCHAIN) break;
fat_addrs.push(q);
}
sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs);
if(cnt >= 1) sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs);
}
}
@ -559,7 +558,7 @@ function read(blob/*:RawBytes|string*/, options/*:CFBReadOpts*/) {
}
switch(type || "base64") {
case "file": /*:: if(typeof blob !== 'string') throw "Must pass a filename when type='file'"; */return read_file(blob, options);
case "base64": /*:: if(typeof blob !== 'string') throw "Must pass a base64-encoded binary string when type='file'"; */return parse(s2a(Base64.decode(blob)), options);
case "base64": /*:: if(typeof blob !== 'string') throw "Must pass a base64-encoded binary string when type='file'"; */return parse(s2a(Base64_decode(blob)), options);
case "binary": /*:: if(typeof blob !== 'string') throw "Must pass a binary string when type='file'"; */return parse(s2a(blob), options);
}
return parse(/*::typeof blob == 'string' ? new Buffer(blob, 'utf-8') : */blob, options);
@ -617,7 +616,9 @@ function rebuild_cfb(cfb/*:CFBContainer*/, f/*:?boolean*/)/*:void*/ {
for(i = 0; i < data.length; ++i) {
var dad = dirname(data[i][0]);
s = fullPaths[dad];
if(!s) {
while(!s) {
while(dirname(dad) && !fullPaths[dirname(dad)]) dad = dirname(dad);
data.push([dad, ({
name: filename(dad).replace("/",""),
type: 1,
@ -625,8 +626,12 @@ function rebuild_cfb(cfb/*:CFBContainer*/, f/*:?boolean*/)/*:void*/ {
ct: now, mt: now,
content: null
}/*:any*/)]);
// Add name to set
fullPaths[dad] = true;
dad = dirname(data[i][0]);
s = fullPaths[dad];
}
}
@ -674,7 +679,6 @@ function _write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes|strin
for(var i = 0; i < cfb.FileIndex.length; ++i) {
var file = cfb.FileIndex[i];
if(!file.content) continue;
/*:: if(file.content == null) throw new Error("unreachable"); */
var flen = file.content.length;
if(flen > 0){
if(flen < 0x1000) mini_size += (flen + 0x3F) >> 6;
@ -765,6 +769,10 @@ function _write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes|strin
file = cfb.FileIndex[i];
if(i === 0) file.start = file.size ? file.start - 1 : ENDOFCHAIN;
var _nm/*:string*/ = (i === 0 && _opts.root) || file.name;
if(_nm.length > 32) {
console.error("Name " + _nm + " will be truncated to " + _nm.slice(0,32));
_nm = _nm.slice(0, 32);
}
flen = 2*(_nm.length+1);
o.write_shift(64, _nm, "utf16le");
o.write_shift(2, flen);
@ -882,7 +890,7 @@ function write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes|string
switch(options && options.type || "buffer") {
case "file": get_fs(); fs.writeFileSync(options.filename, (o/*:any*/)); return o;
case "binary": return typeof o == "string" ? o : a2s(o);
case "base64": return Base64.encode(typeof o == "string" ? o : a2s(o));
case "base64": return Base64_encode(typeof o == "string" ? o : a2s(o));
case "buffer": if(has_buf) return Buffer.isBuffer(o) ? o : Buffer_from(o);
/* falls through */
case "array": return typeof o == "string" ? s2a(o) : o;
@ -1072,7 +1080,7 @@ if(!use_typed_arrays) {
for(; i<=279; i++) clens.push(7);
for(; i<=287; i++) clens.push(8);
build_tree(clens, fix_lmap, 288);
})();var _deflateRaw = (function _deflateRawIIFE() {
})();var _deflateRaw = /*#__PURE__*/(function _deflateRawIIFE() {
var DST_LN_RE = use_typed_arrays ? new Uint8Array(0x8000) : [];
var j = 0, k = 0;
for(; j < DST_LN.length - 1; ++j) {
@ -1400,9 +1408,15 @@ function parse_zip(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/
var L = blob.l;
blob.l = offset + 4;
/* ZIP64 lengths */
if(EF && EF[0x0001]) {
if((EF[0x0001]||{}).usz) usz = EF[0x0001].usz;
if((EF[0x0001]||{}).csz) csz = EF[0x0001].csz;
}
parse_local_file(blob, csz, usz, o, EF);
blob.l = L;
}
return o;
}
@ -1428,7 +1442,13 @@ function parse_local_file(blob/*:CFBlob*/, csz/*:number*/, usz/*:number*/, o/*:C
if(efsz) {
var ef = parse_extra_field(/*::(*/blob.slice(blob.l, blob.l + efsz)/*:: :any)*/);
if((ef[0x5455]||{}).mt) date = ef[0x5455].mt;
if(((EF||{})[0x5455]||{}).mt) date = EF[0x5455].mt;
if((ef[0x0001]||{}).usz) _usz = ef[0x0001].usz;
if((ef[0x0001]||{}).csz) _csz = ef[0x0001].csz;
if(EF) {
if((EF[0x5455]||{}).mt) date = EF[0x5455].mt;
if((EF[0x0001]||{}).usz) _usz = ef[0x0001].usz;
if((EF[0x0001]||{}).csz) _csz = ef[0x0001].csz;
}
}
blob.l += efsz;
@ -1480,9 +1500,9 @@ function write_zip(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes*/
var namebuf = new_buf(fp.length);
for(j = 0; j < fp.length; ++j) namebuf.write_shift(1, fp.charCodeAt(j) & 0x7F);
namebuf = namebuf.slice(0, namebuf.l);
crcs[fcnt] = CRC32.buf(/*::((*/fi.content/*::||[]):any)*/, 0);
crcs[fcnt] = typeof fi.content == "string" ? CRC32.bstr(fi.content, 0) : CRC32.buf(/*::((*/fi.content/*::||[]):any)*/, 0);
var outbuf = fi.content/*::||[]*/;
var outbuf = typeof fi.content == "string" ? s2a(fi.content) : fi.content/*::||[]*/;
if(method == 8) outbuf = _deflateRawSync(outbuf);
/* local file header */
@ -1591,7 +1611,7 @@ function get_content_type(fi/*:CFBEntry*/, fp/*:string*/)/*:string*/ {
/* 76 character chunks TODO: intertwine encoding */
function write_base64_76(bstr/*:string*/)/*:string*/ {
var data = Base64.encode(bstr);
var data = Base64_encode(bstr);
var o = [];
for(var i = 0; i < data.length; i+= 76) o.push(data.slice(i, i+76));
return o.join("\r\n") + "\r\n";
@ -1672,7 +1692,7 @@ function parse_mime(cfb/*:CFBContainer*/, data/*:Array<string>*/, root/*:string*
}
++di;
switch(cte.toLowerCase()) {
case 'base64': fdata = s2a(Base64.decode(data.slice(di).join(""))); break;
case 'base64': fdata = s2a(Base64_decode(data.slice(di).join(""))); break;
case 'quoted-printable': fdata = parse_quoted_printable(data.slice(di)); break;
default: throw new Error("Unsupported Content-Transfer-Encoding " + cte);
}
@ -1849,4 +1869,3 @@ exports.utils = {
return exports;
})();
if(typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO_NOT_EXPORT_CFB === 'undefined') { module.exports = CFB; }

@ -1,5 +1,5 @@
var _fs;
if(typeof require !== 'undefined') try { _fs = require('fs'); } catch(e) {}
function set_fs(fs) { _fs = fs; }
/* normalize data for blob ctor */
function blobify(data) {

@ -31,16 +31,16 @@ function evert_arr(obj/*:any*/)/*:EvertArrType*/ {
return o;
}
var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
var basedate = /*#__PURE__*/new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
var epoch = v.getTime();
var epoch = /*#__PURE__*/v.getTime();
if(date1904) epoch -= 1462*24*60*60*1000;
var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
var dnthresh = /*#__PURE__*/basedate.getTime() + (/*#__PURE__*/v.getTimezoneOffset() - /*#__PURE__*/basedate.getTimezoneOffset()) * 60000;
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
}
var refdate = new Date();
var dnthresh = basedate.getTime() + (refdate.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
var refoffset = refdate.getTimezoneOffset();
var refdate = /*#__PURE__*/new Date();
var dnthresh = /*#__PURE__*/basedate.getTime() + (/*#__PURE__*/refdate.getTimezoneOffset() - /*#__PURE__*/basedate.getTimezoneOffset()) * 60000;
var refoffset = /*#__PURE__*/refdate.getTimezoneOffset();
function numdate(v/*:number*/)/*:Date*/ {
var out = new Date();
out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh);
@ -77,9 +77,9 @@ function parse_isodur(s) {
return sec;
}
var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
var good_pd = good_pd_date.getFullYear() == 2017;
var good_pd_date_1 = /*#__PURE__*/new Date('2017-02-19T19:06:09.000Z');
var good_pd_date = /*#__PURE__*/isNaN(/*#__PURE__*/good_pd_date_1.getFullYear()) ? /*#__PURE__*/new Date('2/19/17') : good_pd_date_1;
var good_pd = /*#__PURE__*/good_pd_date.getFullYear() == 2017;
/* parses a date as a local date */
function parseDate(str/*:string|Date*/, fixdate/*:?number*/)/*:Date*/ {
var d = new Date(str);
@ -103,13 +103,32 @@ function parseDate(str/*:string|Date*/, fixdate/*:?number*/)/*:Date*/ {
function cc2str(arr/*:Array<number>*/, debomit)/*:string*/ {
if(has_buf && Buffer.isBuffer(arr)) {
if(debomit) {
if(arr[0] == 0xFF && arr[1] == 0xFE) return arr.slice(2).toString("utf16le");
if(arr[1] == 0xFE && arr[2] == 0xFF) return utf16beread(arr.slice(2).toString("binary"));
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");
}
/* TODO: investigate performance degradation of TextEncoder in Edge 13 */
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 = [];
for(var i = 0; i != arr.length; ++i) o.push(String.fromCharCode(arr[i]));
return o.join("");
@ -129,8 +148,7 @@ function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length
/* TODO: stress test */
function fuzzynum(s/*:string*/)/*:number*/ {
var v/*:number*/ = Number(s);
if(isFinite(v)) return v;
if(!isNaN(v)) return NaN;
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 "";});
@ -139,26 +157,44 @@ function fuzzynum(s/*:string*/)/*:number*/ {
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?$/;
function fuzzytime1(M) /*:Date*/ {
/* TODO: 1904 adjustment, keep in sync with base date */
if(!M[2]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0);
if(M[3]) {
if(M[4]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000);
else return new Date(1899,11,30,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000);
}
else if(M[5]) return new Date(1899,11,30, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0);
else return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0);
}
var lower_months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'];
function fuzzydate(s/*:string*/)/*:Date*/ {
var lower = s.toLowerCase();
var lnos = lower.replace(/\s+/g, " ").trim();
var M = lnos.match(FDRE1);
if(M) return fuzzytime1(M);
var o = new Date(s), n = new Date(NaN);
var y = o.getYear(), m = o.getMonth(), d = o.getDate();
if(isNaN(d)) return n;
var lower = s.toLowerCase();
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.match(/[a-z]/)) return n;
if(y < 0 || y > 8099) return n;
if((m > 0 || d > 1) && y != 101) return o;
if(s.match(/[^-0-9:,\/\\]/)) return n;
} else if(lower.replace(/[ap]m?/, "").match(/[a-z]/)) return n;
if(y < 0 || y > 8099 || s.match(/[^-0-9:,\/\\]/)) return n;
return o;
}
var safe_split_regex = "abacaba".split(/(:?b)/i).length == 5;
function split_regex(str/*:string*/, re, def/*:string*/)/*:Array<string>*/ {
if(safe_split_regex || typeof re == "string") return str.split(re);
var p = str.split(re), o = [p[0]];
for(var i = 1; i < p.length; ++i) { o.push(def); o.push(p[i]); }
return o;
}
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;
};
})();

@ -1,8 +1,7 @@
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s*[\/\?]?>/mg;
if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
var tagregex1=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s*[\/\?]?>/mg, tagregex2 = /<[^>]*>/g;
var tagregex = /*#__PURE__*/XML_HEADER.match(tagregex1) ? tagregex1 : tagregex2;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*/)/*:any*/ {
var z = ({}/*:any*/);
@ -42,22 +41,26 @@ var encodings = {
'&lt;': '<',
'&amp;': '&'
};
var rencoding = evert(encodings);
var rencoding = /*#__PURE__*/evert(encodings);
//var rencstr = "&<>'\"".split("");
// TODO: CP remap (need to read file version to determine OS)
var unescapexml/*:StringConv*/ = (function() {
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})_/ig;
return function unescapexml(text/*:string*/)/*:string*/ {
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 unescapexml(s.slice(0, i)) + s.slice(i+9,j) + unescapexml(s.slice(j+3));
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 decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f\uFFFE-\uFFFF]/g;
function escapexml(text/*:string*/)/*:string*/{
var s = text + '';
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";});
@ -76,24 +79,24 @@ function escapexlml(text/*:string*/)/*:string*/{
}
/* TODO: handle codepages */
var xlml_fixstr/*:StringConv*/ = (function() {
var xlml_fixstr/*:StringConv*/ = /*#__PURE__*/(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); };
})();
var xlml_unfixstr/*:StringConv*/ = (function() {
return function xlml_unfixstr(str/*:string*/)/*:string*/ { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); };
})();
function xlml_unfixstr(str/*:string*/)/*:string*/ { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); }
/* note: xsd:boolean valid values: true / 1 / false / 0 */
function parsexmlbool(value/*:any*/)/*:boolean*/ {
switch(value) {
case 1: case true: case '1': case 'true': case 'TRUE': return true;
/* case '0': case 'false': case 'FALSE':*/
default: return false;
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);
}
return false;
}
var utf8read/*:StringConv*/ = function utf8reada(orig/*:string*/)/*:string*/ {
function utf8reada(orig/*:string*/)/*:string*/ {
var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
while (i < orig.length) {
c = orig.charCodeAt(i++);
@ -108,9 +111,31 @@ var utf8read/*:StringConv*/ = function utf8reada(orig/*:string*/)/*:string*/ {
out += String.fromCharCode(0xDC00 + (w&1023));
}
return out;
};
}
var utf8write/*:StringConv*/ = function(orig/*:string*/)/*:string*/ {
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++);
@ -136,33 +161,8 @@ var utf8write/*:StringConv*/ = function(orig/*:string*/)/*:string*/ {
return out.join("");
};
if(has_buf) {
var utf8readb = function utf8readb(data) {
var out = Buffer.alloc(2*data.length), w, i, j = 1, k = 0, ww=0, c;
for(i = 0; i < data.length; i+=j) {
j = 1;
if((c=data.charCodeAt(i)) < 128) w = c;
else if(c < 224) { w = (c&31)*64+(data.charCodeAt(i+1)&63); j=2; }
else if(c < 240) { w=(c&15)*4096+(data.charCodeAt(i+1)&63)*64+(data.charCodeAt(i+2)&63); j=3; }
else { j = 4;
w = (c & 7)*262144+(data.charCodeAt(i+1)&63)*4096+(data.charCodeAt(i+2)&63)*64+(data.charCodeAt(i+3)&63);
w -= 65536; ww = 0xD800 + ((w>>>10)&1023); w = 0xDC00 + (w&1023);
}
if(ww !== 0) { out[k++] = ww&255; out[k++] = ww>>>8; ww = 0; }
out[k++] = w%256; out[k++] = w>>>8;
}
return out.slice(0,k).toString('ucs2');
};
var corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3";
if(utf8read(corpus) == utf8readb(corpus)) utf8read = utf8readb;
var utf8readc = function utf8readc(data) { return Buffer_from(data, 'binary').toString('utf8'); };
if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
utf8write = function(data) { return Buffer_from(data, 'utf8').toString("binary"); };
}
// matches <foo>...</foo> extracts content
var matchtag = (function() {
var matchtag = /*#__PURE__*/(function() {
var mtcache/*:{[k:string]:RegExp}*/ = ({}/*:any*/);
return function matchtag(f/*:string*/,g/*:?string*/)/*:RegExp*/ {
var t = f+"|"+(g||"");
@ -171,7 +171,7 @@ var matchtag = (function() {
};
})();
var htmldecode/*:{(s:string):string}*/ = (function() {
var htmldecode/*:{(s:string):string}*/ = /*#__PURE__*/(function() {
var entities/*:Array<[RegExp, string]>*/ = [
['nbsp', ' '], ['middot', '·'],
['quot', '"'], ['apos', "'"], ['gt', '>'], ['lt', '<'], ['amp', '&']
@ -195,7 +195,7 @@ var htmldecode/*:{(s:string):string}*/ = (function() {
};
})();
var vtregex = (function(){ var vt_cache = {};
var vtregex = /*#__PURE__*/(function(){ var vt_cache = {};
return function vt_regex(bt) {
if(vt_cache[bt] !== undefined) return vt_cache[bt];
return (vt_cache[bt] = new RegExp("<(?:vt:)?" + bt + ">([\\s\\S]*?)</(?:vt:)?" + bt + ">", 'g') );
@ -238,7 +238,24 @@ function write_vt(s, xlsx/*:?boolean*/)/*:string*/ {
throw new Error("Unable to serialize " + s);
}
function xlml_normalize(d)/*:string*/ {
if(has_buf &&/*::typeof Buffer !== "undefined" && d != null && d instanceof Buffer &&*/ Buffer.isBuffer(d)) return d.toString('utf8');
if(typeof d === 'string') return d;
/* duktape */
if(typeof Uint8Array !== 'undefined' && d instanceof Uint8Array) return utf8read(a2s(ab2a(d)));
throw new Error("Bad input format: expected Buffer or string");
}
/* UOS uses CJK in tags */
var xlmlregex = /<(\/?)([^\s?><!\/:]*:|)([^\s?<>:\/]+)(?:[\s?:\/](?:[^>=]|="[^"]*?")*)?>/mg;
//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
var XMLNS = ({
CORE_PROPS: 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties',
CUST_PROPS: "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties",
EXT_PROPS: "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties",
CT: 'http://schemas.openxmlformats.org/package/2006/content-types',
RELS: 'http://schemas.openxmlformats.org/package/2006/relationships',
TCMNT: 'http://schemas.microsoft.com/office/spreadsheetml/2018/threadedcomments',
'dc': 'http://purl.org/dc/elements/1.1/',
'dcterms': 'http://purl.org/dc/terms/',
'dcmitype': 'http://purl.org/dc/dcmitype/',
@ -250,7 +267,7 @@ var XMLNS = ({
'xsd': 'http://www.w3.org/2001/XMLSchema'
}/*:any*/);
XMLNS.main = [
var XMLNS_main = [
'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
'http://purl.oclc.org/ooxml/spreadsheetml/main',
'http://schemas.microsoft.com/office/excel/2006/main',

@ -25,54 +25,59 @@ function write_double_le(b/*:RawBytes|CFBlob*/, v/*:number*/, idx/*:number*/) {
b[idx + 7] = (e >> 4) | bs;
}
var __toBuffer = function(bufs/*:Array<Array<RawBytes> >*/)/*:RawBytes*/ { var x=[],w=10240; for(var i=0;i<bufs[0].length;++i) if(bufs[0][i]) for(var j=0,L=bufs[0][i].length;j<L;j+=w) x.push.apply(x, bufs[0][i].slice(j,j+w)); return x; };
var ___toBuffer = __toBuffer;
var __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join("").replace(chr0,''); };
var ___utf16le = __utf16le;
var __hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); };
var ___hexlify = __hexlify;
var __utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
var ___utf8 = __utf8;
var __lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var ___lpstr = __lpstr;
var __cpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var ___cpstr = __cpstr;
var __lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var ___lpwstr = __lpwstr;
var __lpp4, ___lpp4;
__lpp4 = ___lpp4 = function lpp4_(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
var __8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
var ___8lpp4 = __8lpp4;
var __double, ___double;
__double = ___double = function(b/*:RawBytes|CFBlob*/, idx/*:number*/) { return read_double_le(b, idx);};
var ___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'*/) {
__utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___utf16le(b,s,e); return b.toString('utf16le',s,e).replace(chr0,'')/*.replace(chr1,'!')*/; };
__hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { return Buffer.isBuffer(b)/*:: && b instanceof Buffer*/ ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
__lpstr = function lpstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
__cpstr = function cpstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___cpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
__lpwstr = function lpwstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
__lpp4 = function lpp4_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);};
__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);};
__utf8 = function utf8_b(b/*:RawBytes|CFBlob*/, s/*:number*/, e/*:number*/) { return (Buffer.isBuffer(b)/*:: && (b instanceof Buffer)*/) ? b.toString('utf8',s,e) : ___utf8(b,s,e); };
__toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0].map(function(x) { return Buffer.isBuffer(x) ? x : Buffer_from(x); })) : ___toBuffer(bufs);};
bconcat = function(bufs) { return Buffer.concat(bufs.map(function(buf) { return Buffer.isBuffer(buf) ? buf : Buffer_from(buf); })); };
__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); };
}
/* 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)) : "";};
__utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return $cptable.utils.decode(1200, b.slice(s,e)).replace(chr0, ''); };
__utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return $cptable.utils.decode(65001, b.slice(s,e)); };
__lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(current_ansi, b.slice(i+4, i+4+len-1)) : "";};
__cpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";};
__lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";};
__lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";};
__8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";};
}
if(typeof cptable !== 'undefined') cpdoit();
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]; };
@ -86,7 +91,7 @@ function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
switch(t) {
case 'dbcs':
loc = this.l;
if(has_buf && Buffer.isBuffer(this)) o = this.slice(this.l, this.l+2*size).toString("utf16le");
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; }
size *= 2;
break;
@ -95,7 +100,7 @@ function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
case 'utf16le': size *= 2; o = __utf16le(this, this.l, this.l + size); break;
case 'wstr':
if(typeof cptable !== 'undefined') o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l+2*size));
if(typeof $cptable !== 'undefined') o = $cptable.utils.decode(current_codepage, this.slice(this.l, this.l+2*size));
else return ReadShift.call(this, size, 'dbcs');
size = 2 * size; break;
@ -130,8 +135,8 @@ function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
} o = oo.join(""); size *= 2; break;
case 'cpstr':
if(typeof cptable !== 'undefined') {
o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l + size));
if(typeof $cptable !== 'undefined') {
o = $cptable.utils.decode(current_codepage, this.slice(this.l, this.l + size));
break;
}
/* falls through */
@ -176,21 +181,29 @@ function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/)/*:any*/
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i);
size = 2 * val.length;
} else if(f === 'sbcs') {
if(typeof cptable !== 'undefined' && current_ansi == 874) {
} 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 cppayload = cptable.utils.encode(current_ansi, val.charAt(i));
this[this.l + i] = cppayload[0];
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;
}
size = val.length;
} else if(f === 'hex') {
for(; i < t; ++i) {
/*:: if(typeof val !== "string") throw new Error("unreachable"); */

@ -14,7 +14,7 @@ function recordhopper(data, cb/*:RecordHopperCB*/, opts/*:?any*/) {
tgt = data.l + length;
var d = R.f && R.f(data, length, opts);
data.l = tgt;
if(cb(d, R.n, RT)) return;
if(cb(d, R, RT)) return;
}
}
@ -31,8 +31,11 @@ function buf_array()/*:BufArray*/ {
var endbuf = function ba_endbuf() {
if(!curbuf) return;
if(curbuf.length > curbuf.l) { curbuf = curbuf.slice(0, curbuf.l); curbuf.l = curbuf.length; }
if(curbuf.length > 0) bufs.push(curbuf);
// 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 = null;
};
@ -52,9 +55,8 @@ function buf_array()/*:BufArray*/ {
return ({ next:next, push:push, end:end, _bufs:bufs }/*:any*/);
}
function write_record(ba/*:BufArray*/, type/*:string*/, payload, length/*:?number*/) {
if(!XLSBRE) make_XLSBRE();
var t/*:number*/ = +XLSBRE[type], l;
function write_record(ba/*:BufArray*/, type/*:number*/, payload, length/*:?number*/) {
var t/*:number*/ = +type, l;
if(isNaN(t)) return; // TODO: throw something here?
if(!length) length = XLSBRecordEnum[t].p || (payload||[]).length || 0;
l = 1 + (t >= 0x80 ? 1 : 0) + 1/* + length*/;

4
bits/26_cptable.js Normal file

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

@ -9,7 +9,6 @@ function fix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^([A-Z])/,"$
function unfix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^\$([A-Z])/,"$1"); }
function split_cell(cstr/*:string*/)/*:Array<string>*/ { return cstr.replace(/(\$?[A-Z]*)(\$?\d*)/,"$1,$2").split(","); }
//function decode_cell(cstr/*:string*/)/*:CellAddress*/ { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; }
function decode_cell(cstr/*:string*/)/*:CellAddress*/ {
var R = 0, C = 0;
for(var i = 0; i < cstr.length; ++i) {
@ -19,7 +18,6 @@ function decode_cell(cstr/*:string*/)/*:CellAddress*/ {
}
return { c: C - 1, r:R - 1 };
}
//function encode_cell(cell/*:CellAddress*/)/*:string*/ { return encode_col(cell.c) + encode_row(cell.r); }
function encode_cell(cell/*:CellAddress*/)/*:string*/ {
var col = cell.c + 1;
var s="";
@ -44,6 +42,17 @@ function encode_range(cs/*:CellAddrSpec|Range*/,ce/*:?CellAddrSpec*/)/*:string*/
/*:: if(typeof ce !== 'string') throw "unreachable"; */
return cs == ce ? cs : cs + ":" + ce;
}
function fix_range(a1/*:string*/)/*:string*/ {
var s = decode_range(a1);
return "$" + encode_col(s.s.c) + "$" + encode_row(s.s.r) + ":$" + encode_col(s.e.c) + "$" + encode_row(s.e.r);
}
// List of invalid characters needs to be tested further
function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ {
if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name");
if (/[^\w\u4E00-\u9FFF\u3040-\u30FF]/.test(sname)) return "'" + sname.replace(/'/g, "''") + "'";
return sname;
}
function safe_decode_range(range/*:string*/)/*:Range*/ {
var o = {s:{c:0,r:0},e:{c:0,r:0}};
@ -80,8 +89,8 @@ function safe_decode_range(range/*:string*/)/*:Range*/ {
function safe_format_cell(cell/*:Cell*/, v/*:any*/) {
var q = (cell.t == 'd' && v instanceof Date);
if(cell.z != null) try { return (cell.w = SSF.format(cell.z, q ? datenum(v) : v)); } catch(e) { }
try { return (cell.w = SSF.format((cell.XF||{}).numFmtId||(q ? 14 : 0), q ? datenum(v) : v)); } catch(e) { return ''+v; }
if(cell.z != null) try { return (cell.w = SSF_format(cell.z, q ? datenum(v) : v)); } catch(e) { }
try { return (cell.w = SSF_format((cell.XF||{}).numFmtId||(q ? 14 : 0), q ? datenum(v) : v)); } catch(e) { return ''+v; }
}
function format_cell(cell/*:Cell*/, v/*:any*/, o/*:any*/) {
@ -101,9 +110,10 @@ function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ {
function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
var o = opts || {};
var dense = _ws ? Array.isArray(_ws) : o.dense;
var dense = _ws ? (_ws["!data"] != null) : o.dense;
if(DENSE != null && dense == null) dense = DENSE;
var ws/*:Worksheet*/ = _ws || (dense ? ([]/*:any*/) : ({}/*:any*/));
var ws/*:Worksheet*/ = _ws || ({}/*:any*/);
if(dense && !ws["!data"]) ws["!data"] = [];
var _R = 0, _C = 0;
if(ws && o.origin != null) {
if(typeof o.origin == 'number') _R = o.origin;
@ -122,13 +132,19 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
range.e.r = Math.max(range.e.r, _range.e.r);
if(_R == -1) range.e.r = _R = _range.e.r + 1;
}
var row = [];
for(var R = 0; R != data.length; ++R) {
if(!data[R]) continue;
if(!Array.isArray(data[R])) throw new Error("aoa_to_sheet expects an array of arrays");
var __R = _R + R, __Rstr = "" + (__R + 1);
if(dense) {
if(!ws["!data"][__R]) ws["!data"][__R] = [];
row = ws["!data"][__R];
}
for(var C = 0; C != data[R].length; ++C) {
if(typeof data[R][C] === 'undefined') continue;
var cell/*:Cell*/ = ({v: data[R][C] }/*:any*/);
var __R = _R + R, __C = _C + C;
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;
@ -145,18 +161,17 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
else if(typeof cell.v === 'number') cell.t = 'n';
else if(typeof cell.v === 'boolean') cell.t = 'b';
else if(cell.v instanceof Date) {
cell.z = o.dateNF || SSF._table[14];
if(o.cellDates) { cell.t = 'd'; cell.w = SSF.format(cell.z, datenum(cell.v)); }
else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); }
cell.z = o.dateNF || table_fmt[14];
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(!ws[__R]) ws[__R] = [];
if(ws[__R][__C] && ws[__R][__C].z) cell.z = ws[__R][__C].z;
ws[__R][__C] = cell;
if(row[__C] && row[__C].z) cell.z = row[__C].z;
row[__C] = cell;
} else {
var cell_ref = encode_cell(({c:__C,r:__R}/*:any*/));
var cell_ref = encode_col(__C) + __Rstr/*:any*/;
if(ws[cell_ref] && ws[cell_ref].z) cell.z = ws[cell_ref].z;
ws[cell_ref] = cell;
}

@ -1,4 +1,5 @@
/* [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;
@ -20,7 +21,7 @@ var VT_UI4 = 0x0013;
//var VT_UI8 = 0x0015;
//var VT_INT = 0x0016;
//var VT_UINT = 0x0017;
var VT_LPSTR = 0x001E;
//var VT_LPSTR = 0x001E;
//var VT_LPWSTR = 0x001F;
var VT_FILETIME = 0x0040;
var VT_BLOB = 0x0041;
@ -32,7 +33,9 @@ var VT_BLOB = 0x0041;
var VT_CF = 0x0047;
//var VT_CLSID = 0x0048;
//var VT_VERSIONED_STREAM = 0x0049;
var VT_VECTOR = 0x1000;
//var VT_VECTOR = 0x1000;
var VT_VECTOR_VARIANT = 0x100C;
var VT_VECTOR_LPSTR = 0x101E;
//var VT_ARRAY = 0x2000;
var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
@ -52,8 +55,8 @@ var DocSummaryPIDDSI = {
/*::[*/0x09/*::]*/: { n: 'HiddenCount', t: VT_I4 },
/*::[*/0x0a/*::]*/: { n: 'MultimediaClipCount', t: VT_I4 },
/*::[*/0x0b/*::]*/: { n: 'ScaleCrop', t: VT_BOOL },
/*::[*/0x0c/*::]*/: { n: 'HeadingPairs', t: VT_VECTOR | VT_VARIANT },
/*::[*/0x0d/*::]*/: { n: 'TitlesOfParts', t: VT_VECTOR | VT_LPSTR },
/*::[*/0x0c/*::]*/: { n: 'HeadingPairs', t: VT_VECTOR_VARIANT /* VT_VECTOR | VT_VARIANT */ },
/*::[*/0x0d/*::]*/: { n: 'TitlesOfParts', t: VT_VECTOR_LPSTR /* VT_VECTOR | VT_LPSTR */ },
/*::[*/0x0e/*::]*/: { n: 'Manager', t: VT_STRING },
/*::[*/0x0f/*::]*/: { n: 'Company', t: VT_STRING },
/*::[*/0x10/*::]*/: { n: 'LinksUpToDate', t: VT_BOOL },
@ -101,9 +104,6 @@ var SummaryPIDSI = {
/*::[*/0x72627262/*::]*/: {}
};
var DocSummaryRE/*:{[key:string]:string}*/ = evert_key(DocSummaryPIDDSI, "n");
var SummaryRE/*:{[key:string]:string}*/ = evert_key(SummaryPIDSI, "n");
/* [MS-XLS] 2.4.63 Country/Region codes */
var CountryEnum = {
/*::[*/0x0001/*::]*/: "US", // United States
@ -185,7 +185,7 @@ function rgbify(arr/*:Array<number>*/)/*:Array<[number, number, number]>*/ { ret
/* [MS-XLS] 2.5.161 */
/* [MS-XLSB] 2.5.75 Icv */
var _XLSIcv = rgbify([
var _XLSIcv = /*#__PURE__*/ rgbify([
/* Color Constants */
0x000000,
0xFFFFFF,
@ -258,8 +258,8 @@ var _XLSIcv = rgbify([
0x333333,
/* Other entries to appease BIFF8/12 */
0xFFFFFF, /* 0x40 icvForeground ?? */
0x000000, /* 0x41 icvBackground ?? */
0x000000, /* 0x40 icvForeground ?? */
0xFFFFFF, /* 0x41 icvBackground ?? */
0x000000, /* 0x42 icvFrame ?? */
0x000000, /* 0x43 icv3D ?? */
0x000000, /* 0x44 icv3DText ?? */
@ -277,7 +277,7 @@ var _XLSIcv = rgbify([
0x000000, /* 0x50 icvInfoBk ?? */
0x000000 /* 0x51 icvInfoText ?? */
]);
var XLSIcv = dup(_XLSIcv);
var XLSIcv = /*#__PURE__*/dup(_XLSIcv);
/* [MS-XLSB] 2.5.97.2 */
var BErr = {
@ -291,4 +291,33 @@ var BErr = {
/*::[*/0x2B/*::]*/: "#GETTING_DATA",
/*::[*/0xFF/*::]*/: "#WTF?"
};
var RBErr = evert_num(BErr);
//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"
];

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

@ -9,6 +9,28 @@ var RELS = ({
XLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLink",
CXML: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml",
CXMLP: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXmlProps",
CMNT: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",
CORE_PROPS: "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
EXT_PROPS: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties',
CUST_PROPS: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties',
SST: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings",
STY: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
THEME: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
CHART: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
CHARTEX: "http://schemas.microsoft.com/office/2014/relationships/chartEx",
CS: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet",
WS: [
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
"http://purl.oclc.org/ooxml/officeDocument/relationships/worksheet"
],
DS: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet",
MS: "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet",
IMG: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
DRAW: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing",
XLMETA: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata",
TCMNT: "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment",
PEOPLE: "http://schemas.microsoft.com/office/2017/10/relationships/person",
CONN: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/connections",
VBA: "http://schemas.microsoft.com/office/2006/relationships/vbaProject"
}/*:any*/);
@ -40,16 +62,13 @@ 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, RELS_ROOT];
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]));
});
@ -57,7 +76,6 @@ function write_rels(rels)/*:string*/ {
return o.join("");
}
var RELS_EXTERN = [RELS.HLINK, RELS.XPATH, RELS.XMISS];
function add_rels(rels, rId/*:number*/, f, type, relobj, targetmode/*:?string*/)/*:number*/ {
if(!relobj) relobj = {};
if(!rels['!id']) rels['!id'] = {};
@ -68,7 +86,7 @@ function add_rels(rels, rId/*:number*/, f, type, relobj, targetmode/*:?string*/)
relobj.Type = type;
relobj.Target = f;
if(targetmode) relobj.TargetMode = targetmode;
else if(RELS_EXTERN.indexOf(relobj.Type) > -1) relobj.TargetMode = "External";
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;

@ -56,10 +56,7 @@ function write_rdf(rdf) {
return o.join("");
}
/* TODO: pull properties */
var write_meta_ods/*:{(wb:Workbook, opts:any):string}*/ = (function() {
var payload = '<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
return function wmo(/*:: wb: Workbook, opts: any*/)/*:string*/ {
return payload;
};
})();
function write_meta_ods(/*:: wb: Workbook, opts: any*/)/*:string*/ {
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>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
}

@ -18,10 +18,7 @@ var CORE_PROPS/*:Array<Array<string> >*/ = [
["dcterms:modified", "ModifiedDate", 'date']
];
XMLNS.CORE_PROPS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
RELS.CORE_PROPS = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';
var CORE_PROPS_REGEX/*:Array<RegExp>*/ = (function() {
var CORE_PROPS_REGEX/*:Array<RegExp>*/ = /*#__PURE__*/(function() {
var r = new Array(CORE_PROPS.length);
for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i];
@ -44,15 +41,6 @@ function parse_core_props(data) {
return p;
}
var CORE_PROPS_XML_ROOT = writextag('cp:coreProperties', null, {
//'xmlns': XMLNS.CORE_PROPS,
'xmlns:cp': XMLNS.CORE_PROPS,
'xmlns:dc': XMLNS.dc,
'xmlns:dcterms': XMLNS.dcterms,
'xmlns:dcmitype': XMLNS.dcmitype,
'xmlns:xsi': XMLNS.xsi
});
function cp_doit(f, g, h, o, p) {
if(p[f] != null || g == null || g === "") return;
p[f] = g;
@ -62,7 +50,14 @@ function cp_doit(f, g, h, o, p) {
function write_core_props(cp, _opts) {
var opts = _opts || {};
var o = [XML_HEADER, CORE_PROPS_XML_ROOT], p = {};
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("");
if(cp) {

@ -14,9 +14,6 @@ var EXT_PROPS/*:Array<Array<string> >*/ = [
["TitlesOfParts", "TitlesOfParts", "raw"]
];
XMLNS.EXT_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
RELS.EXT_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';
var PseudoPropsPairs = [
"Worksheets", "SheetNames",
"NamedRanges", "DefinedNames",
@ -90,17 +87,15 @@ function parse_ext_props(data, p, opts) {
return p;
}
var EXT_PROPS_XML_ROOT = writextag('Properties', null, {
'xmlns': XMLNS.EXT_PROPS,
'xmlns:vt': XMLNS.vt
});
function write_ext_props(cp/*::, opts*/)/*:string*/ {
var o/*:Array<string>*/ = [], W = writextag;
if(!cp) cp = {};
cp.Application = "SheetJS";
o[o.length] = (XML_HEADER);
o[o.length] = (EXT_PROPS_XML_ROOT);
o[o.length] = (writextag('Properties', null, {
'xmlns': XMLNS.EXT_PROPS,
'xmlns:vt': XMLNS.vt
}));
EXT_PROPS.forEach(function(f) {
if(cp[f[1]] === undefined) return;

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

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

@ -185,6 +185,7 @@ function parse_PropertySet(blob, PIDSI) {
if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i);
}
if(PIDSI) {
if(Props[i][0] == 0 && Props.length > i+1 && Props[i][1] == Props[i+1][1]) continue; // R9
var piddsi = PIDSI[Props[i][0]];
PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true});
if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + ("0000" + String(PropH[piddsi.n] & 0xFFFF)).slice(-4);
@ -248,7 +249,7 @@ function parse_PropertySet(blob, PIDSI) {
blob.l = start_addr + size; /* step ahead to skip padding */
return PropH;
}
var XLSPSSkip = [ "CodePage", "Thumbnail", "_PID_LINKBASE", "_PID_HLINKS", "SystemIdentifier", "FMTID" ].concat(PseudoPropsPairs);
var XLSPSSkip = [ "CodePage", "Thumbnail", "_PID_LINKBASE", "_PID_HLINKS", "SystemIdentifier", "FMTID" ];
function guess_property_type(val/*:any*/)/*:number*/ {
switch(typeof val) {
case "boolean": return 0x0B;
@ -292,7 +293,7 @@ function write_PropertySet(entries, RE, PIDSI) {
for(i = 0; i < entries.length; ++i) {
if(RE && !RE[entries[i][0]]) continue;
if(XLSPSSkip.indexOf(entries[i][0]) > -1) 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;

@ -669,22 +669,6 @@ function parse_ExternName(blob, length, opts) {
}
/* [MS-XLS] 2.4.150 TODO */
var XLSLblBuiltIn = [
"_xlnm.Consolidate_Area",
"_xlnm.Auto_Open",
"_xlnm.Auto_Close",
"_xlnm.Extract",
"_xlnm.Database",
"_xlnm.Criteria",
"_xlnm.Print_Area",
"_xlnm.Print_Titles",
"_xlnm.Recorder",
"_xlnm.Data_Form",
"_xlnm.Auto_Activate",
"_xlnm.Auto_Deactivate",
"_xlnm.Sheet_Title",
"_xlnm._FilterDatabase"
];
function parse_Lbl(blob, length, opts) {
var target = blob.l + length;
var flags = blob.read_shift(2);
@ -804,8 +788,8 @@ function parse_Obj(blob, length, opts) {
return { cmo: cmo, ft:fts };
}
/* from older spec */
var parse_BIFF5OT = [];
parse_BIFF5OT[0x08] = function(blob, length) {
var parse_BIFF5OT = {
0x08: function(blob, length) {
var tgt = blob.l + length;
blob.l += 10; // todo
var cf = blob.read_shift(2);
@ -818,6 +802,7 @@ parse_BIFF5OT[0x08] = function(blob, length) {
blob.l += cchName; // TODO: stName
blob.l = tgt; // TODO: fmla
return { fmt:cf };
}
};
function parse_BIFF5Obj(blob, length, opts) {
@ -850,7 +835,7 @@ try {
var ot = (opts.lastobj||{cmo:[0,0]}).cmo[1];
var controlInfo; // eslint-disable-line no-unused-vars
if([0,5,7,11,12,14].indexOf(ot) == -1) blob.l += 6;
else controlInfo = parse_ControlInfo(blob, 6, opts);
else controlInfo = parse_ControlInfo(blob, 6, opts); // eslint-disable-line no-unused-vars
var cchText = blob.read_shift(2);
/*var cbRuns = */blob.read_shift(2);
/*var ifntEmpty = */parseuint16(blob, 2);

@ -1,5 +1,5 @@
/* from js-harb (C) 2014-present SheetJS */
var DBF = (function() {
var DBF_SUPPORTED_VERSIONS = [0x02, 0x03, 0x30, 0x31, 0x83, 0x8B, 0x8C, 0xF5];
var DBF = /*#__PURE__*/(function() {
var dbf_codepage_map = {
/* Code Pages Supported by Visual FoxPro */
/*::[*/0x01/*::]*/: 437, /*::[*/0x02/*::]*/: 850,
@ -57,13 +57,12 @@ var dbf_reverse_map = evert({
/*::[*/0xCA/*::]*/: 1254, /*::[*/0xCB/*::]*/: 1253,
/*::[*/0x00/*::]*/: 20127
});
var DBF_SUPPORTED_VERSIONS = [0x02, 0x03, 0x30, 0x31, 0x83, 0x8B, 0x8C, 0xF5];
/* TODO: find an actual specification */
function dbf_to_aoa(buf, opts)/*:AOA*/ {
var out/*:AOA*/ = [];
var d/*:Block*/ = (new_raw_buf(1)/*:any*/);
switch(opts.type) {
case 'base64': d = s2a(Base64.decode(buf)); break;
case 'base64': d = s2a(Base64_decode(buf)); break;
case 'binary': d = s2a(buf); break;
case 'buffer':
case 'array': d = buf; break;
@ -119,7 +118,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
var ww = l7 ? 32 : 11;
while(d.l < hend && d[d.l] != 0x0d) {
field = ({}/*:any*/);
field.name = cptable.utils.decode(current_cp, d.slice(d.l, d.l+ww)).replace(/[\u0000\r\n].*$/g,"");
field.name = (typeof $cptable !== "undefined" ? $cptable.utils.decode(current_cp, d.slice(d.l, d.l+ww)) : a2s(d.slice(d.l, d.l + ww))).replace(/[\u0000\r\n].*$/g,"");
d.l += ww;
field.type = String.fromCharCode(d.read_shift(1));
if(ft != 0x02 && !l7) field.offset = d.read_shift(4);
@ -173,7 +172,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
for(C = 0; C != fields.length; ++C) {
var dd = d.slice(d.l, d.l+fields[C].len); d.l+=fields[C].len;
prep_blob(dd, 0);
var s = cptable.utils.decode(current_cp, dd);
var s = typeof $cptable !== "undefined" ? $cptable.utils.decode(current_cp, dd) : a2s(dd);
switch(fields[C].type) {
case 'C':
// NOTE: it is conventional to write ' / / ' for empty dates
@ -204,7 +203,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
out[R][C] = new Date(dd.read_shift(-8, 'f') - 0x388317533400);
break;
case 'T': out[R][C] = new Date((dd.read_shift(4) - 0x253D8C) * 0x5265C00 + dd.read_shift(4)); break;
case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4; break;
case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4 + (dd.read_shift(4, 'i')/1e4)*Math.pow(2,32); break;
case 'O': out[R][C] = -dd.read_shift(-8, 'f'); break;
case 'B': if(vfp && fields[C].len == 8) { out[R][C] = dd.read_shift(8,'f'); break; }
/* falls through */
@ -218,32 +217,44 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
}
if(ft != 0x02) if(d.l < d.length && d[d.l++] != 0x1A) throw new Error("DBF EOF Marker missing " + (d.l-1) + " of " + d.length + " " + d[d.l-1].toString(16));
if(opts && opts.sheetRows) out = out.slice(0, opts.sheetRows);
opts.DBF = fields;
return out;
}
function dbf_to_sheet(buf, opts)/*:Worksheet*/ {
var o = opts || {};
if(!o.dateNF) o.dateNF = "yyyymmdd";
return aoa_to_sheet(dbf_to_aoa(buf, o), o);
var ws = aoa_to_sheet(dbf_to_aoa(buf, o), o);
ws["!cols"] = o.DBF.map(function(field) { return {
wch: field.len,
DBF: field
};});
delete o.DBF;
return ws;
}
function dbf_to_workbook(buf, opts)/*:Workbook*/ {
try { return sheet_to_workbook(dbf_to_sheet(buf, opts), opts); }
catch(e) { if(opts && opts.WTF) throw e; }
try {
var o = sheet_to_workbook(dbf_to_sheet(buf, opts), opts);
o.bookType = "dbf";
return o;
} catch(e) { if(opts && opts.WTF) throw e; }
return ({SheetNames:[],Sheets:{}});
}
var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 };
function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
var o = opts || {};
var old_cp = current_codepage;
if(+o.codepage >= 0) set_cp(+o.codepage);
if(o.type == "string") throw new Error("Cannot write DBF to JS string");
var ba = buf_array();
var aoa/*:AOA*/ = sheet_to_json(ws, {header:1, raw:true, cellDates:true});
var headers = aoa[0], data = aoa.slice(1);
var headers = aoa[0], data = aoa.slice(1), cols = ws["!cols"] || [];
var i = 0, j = 0, hcnt = 0, rlen = 1;
for(i = 0; i < headers.length; ++i) {
if(i == null) continue;
if(((cols[i]||{}).DBF||{}).name) { headers[i] = cols[i].DBF.name; ++hcnt; continue; }
if(headers[i] == null) continue;
++hcnt;
if(typeof headers[i] === 'number') headers[i] = headers[i].toString(10);
if(typeof headers[i] !== 'string') throw new Error("DBF Invalid column name " + headers[i] + " |" + (typeof headers[i]) + "|");
@ -252,13 +263,15 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
}
var range = safe_decode_range(ws['!ref']);
var coltypes/*:Array<string>*/ = [];
var colwidths/*:Array<number>*/ = [];
var coldecimals/*:Array<number>*/ = [];
for(i = 0; i <= range.e.c - range.s.c; ++i) {
var guess = '', _guess = '', maxlen = 0;
var col/*:Array<any>*/ = [];
for(j=0; j < data.length; ++j) {
if(data[j][i] != null) col.push(data[j][i]);
}
if(col.length == 0 || headers[i] == null) { coltypes[i] = '?'; continue; }
var guess = '', _guess = '';
for(j = 0; j < col.length; ++j) {
switch(typeof col[j]) {
/* TODO: check if L2 compat is desired */
@ -268,10 +281,24 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
case 'object': _guess = col[j] instanceof Date ? 'D' : 'C'; break;
default: _guess = 'C';
}
/* TODO: cache the values instead of encoding twice */
maxlen = Math.max(maxlen, (typeof $cptable !== "undefined" && typeof col[j] == "string" ? $cptable.utils.encode(current_ansi, col[j]): String(col[j])).length);
guess = guess && guess != _guess ? 'C' : _guess;
if(guess == 'C') break;
//if(guess == 'C') break;
}
rlen += _RLEN[guess] || 0;
if(maxlen > 250) maxlen = 250;
_guess = ((cols[i]||{}).DBF||{}).type;
/* TODO: more fine grained control over DBF type resolution */
if(_guess == 'C') {
if(cols[i].DBF.len > maxlen) maxlen = cols[i].DBF.len;
}
if(guess == 'B' && _guess == 'N') {
guess = 'N';
coldecimals[i] = cols[i].DBF.dec;
maxlen = cols[i].DBF.len;
}
colwidths[i] = guess == 'C' || _guess == 'N' ? maxlen : (_RLEN[guess] || 0);
rlen += colwidths[i];
coltypes[i] = guess;
}
@ -281,23 +308,29 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
h.write_shift(2, 296 + 32 * hcnt);
h.write_shift(2, rlen);
for(i=0; i < 4; ++i) h.write_shift(4, 0);
h.write_shift(4, 0x00000000 | ((+dbf_reverse_map[/*::String(*/current_ansi/*::)*/] || 0x03)<<8));
var cp = +dbf_reverse_map[/*::String(*/current_codepage/*::)*/] || 0x03;
h.write_shift(4, 0x00000000 | (cp<<8));
if(dbf_codepage_map[cp] != +o.codepage) {
if(o.codepage) console.error("DBF Unsupported codepage " + current_codepage + ", using 1252");
current_codepage = 1252;
}
for(i = 0, j = 0; i < headers.length; ++i) {
if(headers[i] == null) continue;
var hf = ba.next(32);
/* TODO: test how applications handle non-ASCII field names */
var _f = (headers[i].slice(-10) + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00").slice(0, 11);
hf.write_shift(1, _f, "sbcs");
hf.write_shift(1, coltypes[i] == '?' ? 'C' : coltypes[i], "sbcs");
hf.write_shift(4, j);
hf.write_shift(1, _RLEN[coltypes[i]] || 0);
hf.write_shift(1, 0);
hf.write_shift(1, colwidths[i] || _RLEN[coltypes[i]] || 0);
hf.write_shift(1, coldecimals[i] || 0);
hf.write_shift(1, 0x02);
hf.write_shift(4, 0);
hf.write_shift(1, 0);
hf.write_shift(4, 0);
hf.write_shift(4, 0);
j += _RLEN[coltypes[i]] || 0;
j += (colwidths[i] || _RLEN[coltypes[i]] || 0);
}
var hb = ba.next(264);
@ -311,6 +344,13 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
switch(coltypes[j]) {
case 'L': rout.write_shift(1, data[i][j] == null ? 0x3F : data[i][j] ? 0x54 : 0x46); break;
case 'B': rout.write_shift(8, data[i][j]||0, 'f'); break;
case 'N':
var _n = "0";
if(typeof data[i][j] == "number") _n = data[i][j].toFixed(coldecimals[j]||0);
if(_n.length > colwidths[j]) _n = _n.slice(0, colwidths[j]); // addresses decimal > width
for(hcnt=0; hcnt < colwidths[j]-_n.length; ++hcnt) rout.write_shift(1, 0x20);
rout.write_shift(1, _n, "sbcs");
break;
case 'D':
if(!data[i][j]) rout.write_shift(8, "00000000", "sbcs");
else {
@ -319,25 +359,27 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
rout.write_shift(2, ("00"+data[i][j].getDate()).slice(-2), "sbcs");
} break;
case 'C':
var _s = String(data[i][j]||"");
rout.write_shift(1, _s, "sbcs");
for(hcnt=0; hcnt < 250-_s.length; ++hcnt) rout.write_shift(1, 0x20); break;
var _l = rout.l;
var _s = String(data[i][j] != null ? data[i][j] : "").slice(0, colwidths[j]);
rout.write_shift(1, _s, "cpstr");
_l += colwidths[j] - rout.l;
for(hcnt=0; hcnt < _l; ++hcnt) rout.write_shift(1, 0x20); break;
}
}
// data
}
current_codepage = old_cp;
ba.next(1).write_shift(1, 0x1A);
return ba.end();
}
return {
versions: DBF_SUPPORTED_VERSIONS,
to_workbook: dbf_to_workbook,
to_sheet: dbf_to_sheet,
from_sheet: sheet_to_dbf
};
})();
var SYLK = (function() {
var SYLK = /*#__PURE__*/(function() {
/* TODO: stress test sequences */
var sylk_escapes = ({
AA:'À', BA:'Á', CA:'Â', DA:195, HA:'Ä', JA:197,
@ -363,10 +405,10 @@ var SYLK = (function() {
var sylk_char_fn = function(_, $1){ var o = sylk_escapes[$1]; return typeof o == "number" ? _getansi(o) : o; };
var decode_sylk_char = function($$, $1, $2) { var newcc = (($1.charCodeAt(0) - 0x20)<<4) | ($2.charCodeAt(0) - 0x30); return newcc == 59 ? $$ : _getansi(newcc); };
sylk_escapes["|"] = 254;
/* TODO: find an actual specification */
/* https://oss.sheetjs.com/notes/sylk/ for more details */
function sylk_to_aoa(d/*:RawData*/, opts)/*:[AOA, Worksheet]*/ {
switch(opts.type) {
case 'base64': return sylk_to_aoa_str(Base64.decode(d), opts);
case 'base64': return sylk_to_aoa_str(Base64_decode(d), opts);
case 'binary': return sylk_to_aoa_str(d, opts);
case 'buffer': return sylk_to_aoa_str(has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d), opts);
case 'array': return sylk_to_aoa_str(cc2str(d), opts);
@ -379,6 +421,7 @@ var SYLK = (function() {
var next_cell_format/*:string|null*/ = null;
var sht = {}, rowinfo/*:Array<RowInfo>*/ = [], colinfo/*:Array<ColInfo>*/ = [], cw/*:Array<string>*/ = [];
var Mval = 0, j;
var wb = { Workbook: { WBProps: {}, Names: [] } };
if(+opts.codepage >= 0) set_cp(+opts.codepage);
for (; ri !== records.length; ++ri) {
Mval = 0;
@ -389,74 +432,97 @@ var SYLK = (function() {
case 'ID': break; /* header */
case 'E': break; /* EOF */
case 'B': break; /* dimensions */
case 'O': break; /* options? */
case 'W': break; /* window? */
case 'O': /* workbook options */
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
case 'V': {
var d1904 = parseInt(record[rj].slice(1), 10);
// NOTE: it is technically an error if d1904 >= 5 or < 0
if(d1904 >= 1 && d1904 <= 4) wb.Workbook.WBProps.date1904 = true;
} break;
} break;
case 'W': break; /* window */
case 'P':
if(record[1].charAt(0) == 'P')
formats.push(rstr.slice(3).replace(/;;/g, ";"));
break;
case 'C':
var C_seen_K = false, C_seen_X = false, C_seen_S = false, C_seen_E = false, _R = -1, _C = -1;
switch(record[1].charAt(0)){
case 'P': formats.push(rstr.slice(3).replace(/;;/g, ";")); break;
} break;
case 'NN': { /* defined name */
var nn = {Sheet: 0};
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
case 'N': nn.Name = record[rj].slice(1); break;
case 'E': nn.Ref = (opts && opts.sheet || "Sheet1") + "!" + rc_to_a1(record[rj].slice(1)); break;
}
wb.Workbook.Names.push(nn);
} break;
// case 'NE': // ??
// case 'NU': // ??
case 'C': /* cell */
var C_seen_K = false, C_seen_X = false, C_seen_S = false, C_seen_E = false, _R = -1, _C = -1, formula = "", cell_t = "z";
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
case 'A': break; // TODO: comment
case 'X': C = parseInt(record[rj].slice(1))-1; C_seen_X = true; break;
case 'X': C = parseInt(record[rj].slice(1), 10)-1; C_seen_X = true; break;
case 'Y':
R = parseInt(record[rj].slice(1))-1; if(!C_seen_X) C = 0;
R = parseInt(record[rj].slice(1), 10)-1; if(!C_seen_X) C = 0;
for(j = arr.length; j <= R; ++j) arr[j] = [];
break;
case 'K':
val = record[rj].slice(1);
if(val.charAt(0) === '"') val = val.slice(1,val.length - 1);
else if(val === 'TRUE') val = true;
else if(val === 'FALSE') val = false;
if(val.charAt(0) === '"') { val = val.slice(1,val.length - 1); cell_t = "s"; }
else if(val === 'TRUE' || val === 'FALSE') { val = val === 'TRUE'; cell_t = "b"; }
else if(!isNaN(fuzzynum(val))) {
val = fuzzynum(val);
if(next_cell_format !== null && SSF.is_date(next_cell_format)) val = numdate(val);
val = fuzzynum(val); cell_t = "n";
if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) { val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : val); cell_t = "d"; }
} else if(!isNaN(fuzzydate(val).getDate())) {
val = parseDate(val);
val = parseDate(val); cell_t = "d";
if(!opts.cellDates) { cell_t = "n"; val = datenum(val, wb.Workbook.WBProps.date1904); }
}
if(typeof cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = cptable.utils.decode(opts.codepage, val);
if(typeof $cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = $cptable.utils.decode(opts.codepage, val);
C_seen_K = true;
break;
case 'E':
C_seen_E = true;
var formula = rc_to_a1(record[rj].slice(1), {r:R,c:C});
arr[R][C] = [arr[R][C], formula];
formula = rc_to_a1(record[rj].slice(1), {r:R,c:C});
break;
case 'S':
C_seen_S = true;
arr[R][C] = [arr[R][C], "S5S"];
break;
case 'G': break; // unknown
case 'R': _R = parseInt(record[rj].slice(1))-1; break;
case 'C': _C = parseInt(record[rj].slice(1))-1; break;
case 'R': _R = parseInt(record[rj].slice(1), 10)-1; break;
case 'C': _C = parseInt(record[rj].slice(1), 10)-1; break;
// case 'P': // ??
// case 'D': // ??
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
}
if(C_seen_K) {
if(arr[R][C] && arr[R][C].length == 2) arr[R][C][0] = val;
else arr[R][C] = val;
if(!arr[R][C]) arr[R][C] = { t: cell_t, v: val };
else { arr[R][C].t = cell_t; arr[R][C].v = val; }
if(next_cell_format) arr[R][C].z = next_cell_format;
if(opts.cellText !== false && next_cell_format) arr[R][C].w = SSF_format(arr[R][C].z, arr[R][C].v, { date1904: wb.Workbook.WBProps.date1904 });
next_cell_format = null;
}
if(C_seen_S) {
if(C_seen_E) throw new Error("SYLK shared formula cannot have own formula");
var shrbase = _R > -1 && arr[_R][_C];
if(!shrbase || !shrbase[1]) throw new Error("SYLK shared formula cannot find base");
arr[R][C][1] = shift_formula_str(shrbase[1], {r: R - _R, c: C - _C});
formula = shift_formula_str(shrbase[1], {r: R - _R, c: C - _C});
}
if(formula) {
if(!arr[R][C]) arr[R][C] = { t: 'n', f: formula };
else arr[R][C].f = formula;
}
break;
case 'F':
case 'F': /* Format */
var F_seen = 0;
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
case 'X': C = parseInt(record[rj].slice(1))-1; ++F_seen; break;
case 'X': C = parseInt(record[rj].slice(1), 10)-1; ++F_seen; break;
case 'Y':
R = parseInt(record[rj].slice(1))-1; /*C = 0;*/
R = parseInt(record[rj].slice(1), 10)-1; /*C = 0;*/
for(j = arr.length; j <= R; ++j) arr[j] = [];
break;
case 'M': Mval = parseInt(record[rj].slice(1)) / 20; break;
case 'M': Mval = parseInt(record[rj].slice(1), 10) / 20; break;
case 'F': break; /* ??? */
case 'G': break; /* hide grid */
case 'P':
next_cell_format = formats[parseInt(record[rj].slice(1))];
next_cell_format = formats[parseInt(record[rj].slice(1), 10)];
break;
case 'S': break; /* cell style */
case 'D': break; /* column */
@ -465,18 +531,20 @@ var SYLK = (function() {
cw = record[rj].slice(1).split(" ");
for(j = parseInt(cw[0], 10); j <= parseInt(cw[1], 10); ++j) {
Mval = parseInt(cw[2], 10);
colinfo[j-1] = Mval === 0 ? {hidden:true}: {wch:Mval}; process_col(colinfo[j-1]);
colinfo[j-1] = Mval === 0 ? {hidden:true}: {wch:Mval};
} break;
case 'C': /* default column format */
C = parseInt(record[rj].slice(1))-1;
C = parseInt(record[rj].slice(1), 10)-1;
if(!colinfo[C]) colinfo[C] = {};
break;
case 'R': /* row properties */
R = parseInt(record[rj].slice(1))-1;
R = parseInt(record[rj].slice(1), 10)-1;
if(!rowinfo[R]) rowinfo[R] = {};
if(Mval > 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); }
else if(Mval === 0) rowinfo[R].hidden = true;
break;
// case 'K': // ??
// case 'E': // ??
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
}
if(F_seen < 1) next_cell_format = null; break;
@ -485,20 +553,23 @@ var SYLK = (function() {
}
if(rowinfo.length > 0) sht['!rows'] = rowinfo;
if(colinfo.length > 0) sht['!cols'] = colinfo;
colinfo.forEach(function(col) { process_col(col); });
if(opts && opts.sheetRows) arr = arr.slice(0, opts.sheetRows);
return [arr, sht];
return [arr, sht, wb];
}
function sylk_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
function sylk_to_workbook(d/*:RawData*/, opts)/*:Workbook*/ {
var aoasht = sylk_to_aoa(d, opts);
var aoa = aoasht[0], ws = aoasht[1];
var o = aoa_to_sheet(aoa, opts);
var aoa = aoasht[0], ws = aoasht[1], wb = aoasht[2];
var _opts = dup(opts); _opts.date1904 = (((wb||{}).Workbook || {}).WBProps || {}).date1904;
var o = aoa_to_sheet(aoa, _opts);
keys(ws).forEach(function(k) { o[k] = ws[k]; });
return o;
var outwb = sheet_to_workbook(o, opts);
keys(wb).forEach(function(k) { outwb[k] = wb[k]; });
outwb.bookType = "sylk";
return outwb;
}
function sylk_to_workbook(d/*:RawData*/, opts)/*:Workbook*/ { return sheet_to_workbook(sylk_to_sheet(d, opts), opts); }
function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*//*::, opts*/)/*:string*/ {
var o = "C;Y" + (R+1) + ";X" + (C+1) + ";K";
switch(cell.t) {
@ -508,7 +579,7 @@ var SYLK = (function() {
case 'b': o += cell.v ? "TRUE" : "FALSE"; break;
case 'e': o += cell.w || cell.v; break;
case 'd': o += '"' + (cell.w || cell.v) + '"'; break;
case 's': o += '"' + cell.v.replace(/"/g,"").replace(/;/g, ";;") + '"'; break;
case 's': o += '"' + (cell.v == null ? "" : String(cell.v)).replace(/"/g,"").replace(/;/g, ";;") + '"'; break;
}
return o;
}
@ -536,11 +607,13 @@ var SYLK = (function() {
});
}
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
var preamble/*:Array<string>*/ = ["ID;PWXL;N;E"], o/*:Array<string>*/ = [];
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/, wb/*:?WorkBook*/)/*:string*/ {
/* TODO: codepage */
var preamble/*:Array<string>*/ = ["ID;PSheetJS;N;E"], o/*:Array<string>*/ = [];
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = Array.isArray(ws);
var dense = ws["!data"] != null;
var RS = "\r\n";
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
preamble.push("P;PGeneral");
preamble.push("F;P0;DG0G8;M255");
@ -548,28 +621,30 @@ var SYLK = (function() {
if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
preamble.push("B;Y" + (r.e.r - r.s.r + 1) + ";X" + (r.e.c - r.s.c + 1) + ";D" + [r.s.c,r.s.r,r.e.c,r.e.r].join(" "));
preamble.push("O;L;D;B" + (d1904 ? ";V4" : "") + ";K47;G100 0.001");
for(var R = r.s.r; R <= r.e.r; ++R) {
if(dense && !ws["!data"][R]) continue;
var p = [];
for(var C = r.s.c; C <= r.e.c; ++C) {
var coord = encode_cell({r:R,c:C});
cell = dense ? (ws[R]||[])[C]: ws[coord];
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
o.push(write_ws_cell_sylk(cell, ws, R, C, opts));
p.push(write_ws_cell_sylk(cell, ws, R, C, opts)); // TODO: pass date1904 info
}
o.push(p.join(RS));
}
return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
}
return {
to_workbook: sylk_to_workbook,
to_sheet: sylk_to_sheet,
from_sheet: sheet_to_sylk
};
})();
var DIF = (function() {
var DIF = /*#__PURE__*/(function() {
function dif_to_aoa(d/*:RawData*/, opts)/*:AOA*/ {
switch(opts.type) {
case 'base64': return dif_to_aoa_str(Base64.decode(d), opts);
case 'base64': return dif_to_aoa_str(Base64_decode(d), opts);
case 'binary': return dif_to_aoa_str(d, opts);
case 'buffer': return dif_to_aoa_str(has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d), opts);
case 'array': return dif_to_aoa_str(cc2str(d), opts);
@ -613,64 +688,61 @@ var DIF = (function() {
}
function dif_to_sheet(str/*:string*/, opts)/*:Worksheet*/ { return aoa_to_sheet(dif_to_aoa(str, opts), opts); }
function dif_to_workbook(str/*:string*/, opts)/*:Workbook*/ { return sheet_to_workbook(dif_to_sheet(str, opts), opts); }
function dif_to_workbook(str/*:string*/, opts)/*:Workbook*/ {
var o = sheet_to_workbook(dif_to_sheet(str, opts), opts);
o.bookType = "dif";
return o;
}
var sheet_to_dif = (function() {
var push_field = function pf(o/*:Array<string>*/, topic/*:string*/, v/*:number*/, n/*:number*/, s/*:string*/) {
o.push(topic);
o.push(v + "," + n);
o.push('"' + s.replace(/"/g,'""') + '"');
};
var push_value = function po(o/*:Array<string>*/, type/*:number*/, v/*:any*/, s/*:string*/) {
o.push(type + "," + v);
o.push(type == 1 ? '"' + s.replace(/"/g,'""') + '"' : s);
};
return function sheet_to_dif(ws/*:Worksheet*//*::, opts:?any*/)/*:string*/ {
var o/*:Array<string>*/ = [];
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = Array.isArray(ws);
push_field(o, "TABLE", 0, 1, "sheetjs");
push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,"");
push_field(o, "TUPLES", 0, r.e.c - r.s.c + 1,"");
push_field(o, "DATA", 0, 0,"");
for(var R = r.s.r; R <= r.e.r; ++R) {
push_value(o, -1, 0, "BOT");
for(var C = r.s.c; C <= r.e.c; ++C) {
var coord = encode_cell({r:R,c:C});
cell = dense ? (ws[R]||[])[C] : ws[coord];
if(!cell) { push_value(o, 1, 0, ""); continue;}
switch(cell.t) {
case 'n':
var val = DIF_XL ? cell.w : cell.v;
if(!val && cell.v != null) val = cell.v;
if(val == null) {
if(DIF_XL && cell.f && !cell.F) push_value(o, 1, 0, "=" + cell.f);
else push_value(o, 1, 0, "");
}
else push_value(o, 0, val, "V");
break;
case 'b':
push_value(o, 0, cell.v ? 1 : 0, cell.v ? "TRUE" : "FALSE");
break;
case 's':
push_value(o, 1, 0, (!DIF_XL || isNaN(cell.v)) ? cell.v : '="' + cell.v + '"');
break;
case 'd':
if(!cell.w) cell.w = SSF.format(cell.z || SSF._table[14], datenum(parseDate(cell.v)));
if(DIF_XL) push_value(o, 0, cell.w, "V");
else push_value(o, 1, 0, cell.w);
break;
default: push_value(o, 1, 0, "");
}
function make_value(v/*:number*/, s/*:string*/)/*:string*/ { return "0," + String(v) + "\r\n" + s; }
function make_value_str(s/*:string*/)/*:string*/ { return "1,0\r\n\"" + s.replace(/"/g,'""') + '"'; }
function sheet_to_dif(ws/*:Worksheet*//*::, opts:?any*/)/*:string*/ {
var _DIF_XL = DIF_XL;
var r = safe_decode_range(ws['!ref']);
var dense = ws["!data"] != null;
var o/*:Array<string>*/ = [
"TABLE\r\n0,1\r\n\"sheetjs\"\r\n",
"VECTORS\r\n0," + (r.e.r - r.s.r + 1) + "\r\n\"\"\r\n",
"TUPLES\r\n0," + (r.e.c - r.s.c + 1) + "\r\n\"\"\r\n",
"DATA\r\n0,0\r\n\"\"\r\n"
];
for(var R = r.s.r; R <= r.e.r; ++R) {
var row = dense ? ws["!data"][R] : [];
var p = "-1,0\r\nBOT\r\n";
for(var C = r.s.c; C <= r.e.c; ++C) {
var cell/*:Cell*/ = dense ? (row && row[C]) : ws[encode_cell({r:R,c:C})];
if(cell == null) { p +=("1,0\r\n\"\"\r\n"); continue;}
switch(cell.t) {
case 'n':
if(_DIF_XL) {
if(cell.w != null) p +=("0," + cell.w + "\r\nV");
else if(cell.v != null) p +=(make_value(cell.v, "V")); // TODO: should this call SSF_format?
else if(cell.f != null && !cell.F) p +=(make_value_str("=" + cell.f));
else p +=("1,0\r\n\"\"");
} else {
if(cell.v == null) p +=("1,0\r\n\"\"");
else p +=(make_value(cell.v, "V"));
}
break;
case 'b':
p +=(cell.v ? make_value(1, "TRUE") : make_value(0, "FALSE"));
break;
case 's':
p +=(make_value_str((!_DIF_XL || isNaN(+cell.v)) ? cell.v : '="' + cell.v + '"'));
break;
case 'd':
if(!cell.w) cell.w = SSF_format(cell.z || table_fmt[14], datenum(parseDate(cell.v)));
if(_DIF_XL) p +=(make_value(cell.w, "V"));
else p +=(make_value_str(cell.w));
break;
default: p +=("1,0\r\n\"\"");
}
p += "\r\n";
}
push_value(o, -1, 0, "EOD");
var RS = "\r\n";
var oo = o.join(RS);
//while((oo.length & 0x7F) != 0) oo += "\0";
return oo;
};
})();
o.push(p);
}
return o.join("") + "-1,0\r\nEOD";
}
return {
to_workbook: dif_to_workbook,
to_sheet: dif_to_sheet,
@ -678,7 +750,7 @@ var DIF = (function() {
};
})();
var ETH = (function() {
var ETH = /*#__PURE__*/(function() {
function decode(s/*:string*/)/*:string*/ { return s.replace(/\\b/g,"\\").replace(/\\c/g,":").replace(/\\n/g,"\n"); }
function encode(s/*:string*/)/*:string*/ { return s.replace(/\\/g, "\\b").replace(/:/g, "\\c").replace(/\n/g,"\\n"); }
@ -733,11 +805,11 @@ var ETH = (function() {
if(!ws || !ws['!ref']) return "";
var o/*:Array<string>*/ = [], oo/*:Array<string>*/ = [], cell, coord = "";
var r = decode_range(ws['!ref']);
var dense = Array.isArray(ws);
var dense = ws["!data"] != null;
for(var R = r.s.r; R <= r.e.r; ++R) {
for(var C = r.s.c; C <= r.e.c; ++C) {
coord = encode_cell({r:R,c:C});
cell = dense ? (ws[R]||[])[C] : ws[coord];
cell = dense ? (ws["!data"][R]||[])[C] : ws[coord];
if(!cell || cell.v == null || cell.t === 'z') continue;
oo = ["cell", coord, 't'];
switch(cell.t) {
@ -753,7 +825,7 @@ var ETH = (function() {
case 'd':
var t = datenum(parseDate(cell.v));
oo[2] = 'vtc'; oo[3] = 'nd'; oo[4] = ""+t;
oo[5] = cell.w || SSF.format(cell.z || SSF._table[14], t);
oo[5] = cell.w || SSF_format(cell.z || table_fmt[14], t);
break;
case 'e': continue;
}
@ -778,7 +850,7 @@ var ETH = (function() {
};
})();
var PRN = (function() {
var PRN = /*#__PURE__*/(function() {
function set_text_arr(data/*:string*/, arr/*:AOA*/, R/*:number*/, C/*:number*/, o/*:any*/) {
if(o.raw) arr[R][C] = data;
else if(data === ""){/* empty */}
@ -859,7 +931,8 @@ var PRN = (function() {
var o = opts || {};
var sep = "";
if(DENSE != null && o.dense == null) o.dense = DENSE;
var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/);
var ws/*:Worksheet*/ = ({}/*:any*/);
if(o.dense) ws["!data"] = [];
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:0}}/*:any*/);
if(str.slice(0,4) == "sep=") {
@ -877,10 +950,9 @@ var PRN = (function() {
else sep = guess_sep(str.slice(0,1024));
var R = 0, C = 0, v = 0;
var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0);
str = str.replace(/\r\n/mg, "\n");
var _re/*:?RegExp*/ = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
function finish_cell() {
var s = str.slice(start, end);
var s = str.slice(start, end); if(s.slice(-1) == "\r") s = s.slice(0, -1);
var cell = ({}/*:any*/);
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
if(s.length === 0) cell.t = 'z';
@ -893,20 +965,20 @@ var PRN = (function() {
else if(s == "TRUE") { cell.t = 'b'; cell.v = true; }
else if(s == "FALSE") { cell.t = 'b'; cell.v = false; }
else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; if(o.cellText !== false) cell.w = s; cell.v = v; }
else if(!isNaN(fuzzydate(s).getDate()) || _re && s.match(_re)) {
cell.z = o.dateNF || SSF._table[14];
else if(!isNaN((v = fuzzydate(s)).getDate()) || _re && s.match(_re)) {
cell.z = o.dateNF || table_fmt[14];
var k = 0;
if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; }
if(o.cellDates) { cell.t = 'd'; cell.v = parseDate(s, k); }
else { cell.t = 'n'; cell.v = datenum(parseDate(s, k)); }
if(o.cellText !== false) cell.w = SSF.format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v);
if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; v = parseDate(s, k); }
if(o.cellDates) { cell.t = 'd'; cell.v = v; }
else { cell.t = 'n'; cell.v = datenum(v); }
if(o.cellText !== false) cell.w = SSF_format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v);
if(!o.cellNF) delete cell.z;
} else {
cell.t = 's';
cell.v = s;
}
if(cell.t == 'z'){}
else if(o.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = cell; }
else if(o.dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = cell; }
else ws[encode_cell({c:C,r:R})] = cell;
start = end+1; startcc = str.charCodeAt(start);
if(range.e.c < C) range.e.c = C;
@ -915,7 +987,11 @@ var PRN = (function() {
}
outer: for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) {
case 0x22: if(startcc === 0x22) instr = !instr; break;
case sepcc: case 0x0a: case 0x0d: if(!instr && finish_cell()) break outer; break;
case 0x0d:
if(instr) break;
if(str.charCodeAt(end+1) == 0x0a) ++end;
/* falls through */
case sepcc: case 0x0a: if(!instr && finish_cell()) break outer; break;
default: break;
}
if(end - start > 0) finish_cell();
@ -935,11 +1011,11 @@ var PRN = (function() {
function prn_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
var str = "", bytes = opts.type == 'string' ? [0,0,0,0] : firstbyte(d, opts);
switch(opts.type) {
case 'base64': str = Base64.decode(d); break;
case 'base64': str = Base64_decode(d); break;
case 'binary': str = d; break;
case 'buffer':
if(opts.codepage == 65001) str = d.toString('utf8'); // TODO: test if buf
else if(opts.codepage && typeof cptable !== 'undefined') str = cptable.utils.decode(opts.codepage, d);
else if(opts.codepage && typeof $cptable !== 'undefined') str = $cptable.utils.decode(opts.codepage, d);
else str = has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d);
break;
case 'array': str = cc2str(d); break;
@ -948,7 +1024,7 @@ var PRN = (function() {
}
if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str.slice(3));
else if(opts.type != 'string' && opts.type != 'buffer' && opts.codepage == 65001) str = utf8read(str);
else if((opts.type == 'binary') && typeof cptable !== 'undefined' && opts.codepage) str = cptable.utils.decode(opts.codepage, cptable.utils.encode(28591,str));
else if((opts.type == 'binary') && typeof $cptable !== 'undefined' && opts.codepage) str = $cptable.utils.decode(opts.codepage, $cptable.utils.encode(28591,str));
if(str.slice(0,19) == "socialcalc:version:") return ETH.to_sheet(opts.type == 'string' ? str : utf8read(str), opts);
return prn_to_sheet_str(str, opts);
}
@ -958,12 +1034,12 @@ var PRN = (function() {
function sheet_to_prn(ws/*:Worksheet*//*::, opts:?any*/)/*:string*/ {
var o/*:Array<string>*/ = [];
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = Array.isArray(ws);
var dense = ws["!data"] != null;
for(var R = r.s.r; R <= r.e.r; ++R) {
var oo/*:Array<string>*/ = [];
for(var C = r.s.c; C <= r.e.c; ++C) {
var coord = encode_cell({r:R,c:C});
cell = dense ? (ws[R]||[])[C] : ws[coord];
cell = dense ? (ws["!data"][R]||[])[C] : ws[coord];
if(!cell || cell.v == null) { oo.push(" "); continue; }
var w = (cell.w || (format_cell(cell), cell.w) || "").slice(0,10);
while(w.length < 10) w += " ";

@ -1,4 +1,4 @@
var WK_ = /*#__PURE__*/ (function() {
var WK_ = /*#__PURE__*/(function() {
function lotushopper(data, cb/*:RecordHopperCB*/, opts/*:any*/) {
if(!data) return;
prep_blob(data, data.l || 0);
@ -16,7 +16,7 @@ var WK_ = /*#__PURE__*/ (function() {
function lotus_to_workbook(d/*:RawData*/, opts) {
switch(opts.type) {
case 'base64': return lotus_to_workbook_buf(s2a(Base64.decode(d)), opts);
case 'base64': return lotus_to_workbook_buf(s2a(Base64_decode(d)), opts);
case 'binary': return lotus_to_workbook_buf(s2a(d), opts);
case 'buffer':
case 'array': return lotus_to_workbook_buf(d, opts);
@ -28,12 +28,14 @@ var WK_ = /*#__PURE__*/ (function() {
if(!d) return d;
var o = opts || {};
if(DENSE != null && o.dense == null) o.dense = DENSE;
var s/*:Worksheet*/ = ((o.dense ? [] : {})/*:any*/), n = "Sheet1", next_n = "", sidx = 0;
var sheets = {}, snames = [], realnames = [];
var s/*:Worksheet*/ = ({}/*:any*/), n = "Sheet1", next_n = "", sidx = 0;
var sheets = {}, snames = [], realnames = [], sdata = [];
if(o.dense) sdata = s["!data"] = [];
var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
var sheetRows = o.sheetRows || 0;
if(d[4] == 0x51 && d[5] == 0x50 && d[6] == 0x57) return qpw_to_workbook_buf(d, opts);
if(d[2] == 0x00) {
if(d[3] == 0x08 || d[3] == 0x09) {
if(d.length >= 16 && d[14] == 0x05 && d[15] === 0x6c) throw new Error("Unsupported Works 3 for Mac file");
@ -47,19 +49,24 @@ var WK_ = /*#__PURE__*/ (function() {
o.vers = val;
if(val >= 0x1000) o.qpro = true;
break;
case 0xFF: /* BOF (works 3+) */
o.vers = val;
o.works = true;
break;
case 0x06: refguess = val; break; /* RANGE */
case 0xCC: if(val) next_n = val; break; /* SHEETNAMECS */
case 0xDE: next_n = val; break; /* SHEETNAMELP */
case 0x0F: /* LABEL */
case 0x33: /* STRING */
if(!o.qpro) val[1].v = val[1].v.slice(1);
if((!o.qpro && !o.works || RT == 0x33) && val[1].v.charCodeAt(0) < 0x30) val[1].v = val[1].v.slice(1);
if(o.works || o.works2) val[1].v = val[1].v.replace(/\r\n/g, "\n");
/* falls through */
case 0x0D: /* INTEGER */
case 0x0E: /* NUMBER */
case 0x10: /* FORMULA */
/* TODO: actual translation of the format code */
if(RT == 0x0E && (val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) {
val[1].z = o.dateNF || SSF._table[14];
val[1].z = o.dateNF || table_fmt[14];
if(o.cellDates) { val[1].t = 'd'; val[1].v = numdate(val[1].v); }
}
@ -68,13 +75,13 @@ var WK_ = /*#__PURE__*/ (function() {
s["!ref"] = encode_range(refguess);
sheets[n] = s;
snames.push(n);
s = (o.dense ? [] : {});
s = ({}/*:any*/); if(o.dense) sdata = s["!data"] = [];
refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
sidx = val[3]; n = next_n || "Sheet" + (sidx + 1); next_n = "";
}
}
var tmpcell = o.dense ? (s[val[0].r]||[])[val[0].c] : s[encode_cell(val[0])];
var tmpcell = o.dense ? (sdata[val[0].r]||[])[val[0].c] : s[encode_cell(val[0])];
if(tmpcell) {
tmpcell.t = val[1].t; tmpcell.v = val[1].v;
if(val[1].z != null) tmpcell.z = val[1].z;
@ -82,10 +89,11 @@ var WK_ = /*#__PURE__*/ (function() {
break;
}
if(o.dense) {
if(!s[val[0].r]) s[val[0].r] = [];
s[val[0].r][val[0].c] = val[1];
if(!sdata[val[0].r]) sdata[val[0].r] = [];
sdata[val[0].r][val[0].c] = val[1];
} else s[encode_cell(val[0])] = val[1];
break;
case 0x5405: o.works2 = true; break;
default:
}}, o);
} else if(d[2] == 0x1A || d[2] == 0x0E) {
@ -94,7 +102,9 @@ var WK_ = /*#__PURE__*/ (function() {
lotushopper(d, function(val, R, RT) { switch(RT) {
case 0xCC: n = val; break; /* SHEETNAMECS */
case 0x16: /* LABEL16 */
val[1].v = val[1].v.slice(1);
if(val[1].v.charCodeAt(0) < 0x30) val[1].v = val[1].v.slice(1);
// TODO: R9 appears to encode control codes this way -- verify against other versions
val[1].v = val[1].v.replace(/\x0F./g, function($$) { return String.fromCharCode($$.charCodeAt(1) - 0x20); }).replace(/\r\n/g, "\n");
/* falls through */
case 0x17: /* NUMBER17 */
case 0x18: /* NUMBER18 */
@ -106,14 +116,14 @@ var WK_ = /*#__PURE__*/ (function() {
s["!ref"] = encode_range(refguess);
sheets[n] = s;
snames.push(n);
s = (o.dense ? [] : {});
s = ({}/*:any*/); if(o.dense) sdata = s["!data"] = [];
refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
sidx = val[3]; n = "Sheet" + (sidx + 1);
}
if(sheetRows > 0 && val[0].r >= sheetRows) break;
if(o.dense) {
if(!s[val[0].r]) s[val[0].r] = [];
s[val[0].r][val[0].c] = val[1];
if(!sdata[val[0].r]) sdata[val[0].r] = [];
sdata[val[0].r][val[0].c] = val[1];
} else s[encode_cell(val[0])] = val[1];
if(refguess.e.c < val[0].c) refguess.e.c = val[0].c;
if(refguess.e.r < val[0].r) refguess.e.r = val[0].r;
@ -148,18 +158,17 @@ var WK_ = /*#__PURE__*/ (function() {
if(o.type == "string") throw new Error("Cannot write WK1 to JS string");
var ba = buf_array();
var range = safe_decode_range(ws["!ref"]);
var dense = Array.isArray(ws);
var dense = ws["!data"] != null;
var cols = [];
write_biff_rec(ba, 0x00, write_BOF_WK1(0x0406));
write_biff_rec(ba, 0x06, write_RANGE(range));
var max_R = Math.min(range.e.r, 8191);
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
for(var R = range.s.r; R <= max_R; ++R) {
var rr = encode_row(R);
for(var C = range.s.c; C <= range.e.c; ++C) {
if(R === range.s.r) cols[C] = encode_col(C);
var ref = cols[C] + rr;
var cell = dense ? (ws[R]||[])[C] : ws[ref];
for(C = range.s.c; C <= range.e.c; ++C) {
var cell = dense ? (ws["!data"][R]||[])[C] : ws[cols[C] + rr];
if(!cell || cell.t == "z") continue;
/* TODO: formula records */
if(cell.t == "n") {
@ -191,7 +200,7 @@ var WK_ = /*#__PURE__*/ (function() {
var ws = wb.Sheets[wb.SheetNames[i]];
if(!ws || !ws["!ref"]) continue;
var range = safe_decode_range(ws["!ref"]);
var dense = Array.isArray(ws);
var dense = ws["!data"] != null;
var cols = [];
var max_R = Math.min(range.e.r, 8191);
for(var R = range.s.r; R <= max_R; ++R) {
@ -199,7 +208,7 @@ var WK_ = /*#__PURE__*/ (function() {
for(var C = range.s.c; C <= range.e.c; ++C) {
if(R === range.s.r) cols[C] = encode_col(C);
var ref = cols[C] + rr;
var cell = dense ? (ws[R]||[])[C] : ws[ref];
var cell = dense ? (ws["!data"][R]||[])[C] : ws[ref];
if(!cell || cell.t == "z") continue;
/* TODO: FORMULA19 NUMBER18 records */
if(cell.t == "n") {
@ -289,6 +298,9 @@ var WK_ = /*#__PURE__*/ (function() {
o[3] = blob.read_shift(1);
o[0].r = blob.read_shift(2);
blob.l+=2;
} else if(opts.works) { // TODO: verify with more complex works3-4 examples
o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2);
o[2] = blob.read_shift(2);
} else {
o[2] = blob.read_shift(1);
o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2);
@ -324,6 +336,18 @@ var WK_ = /*#__PURE__*/ (function() {
o.write_shift(1, 0);
return o;
}
function parse_STRING(blob, length, opts) {
var tgt = blob.l + length;
var o = parse_cell(blob, length, opts);
o[1].t = 's';
if(opts.vers == 0x5120) {
var len = blob.read_shift(1);
o[1].v = blob.read_shift(len, 'utf8');
return o;
}
o[1].v = blob.read_shift(tgt - blob.l, 'cstr');
return o;
}
function parse_INTEGER(blob, length, opts) {
var o = parse_cell(blob, length, opts);
@ -373,27 +397,100 @@ var WK_ = /*#__PURE__*/ (function() {
V = (rel ? B : 0) + ((V >= 0x2000) ? V - 0x4000 : V);
return (rel ? "" : "$") + (col ? encode_col(V) : encode_row(V));
}
var oprec = [
/* var oprec = [
8, 8, 8, 8, 8, 8, 8, 8, 6, 4, 4, 5, 5, 7, 3, 3,
3, 3, 3, 3, 1, 1, 2, 6, 8, 8, 8, 8, 8, 8, 8, 8
];
]; */
/* TODO: flesh out */
var FuncTab = {
0x1F: ["NA", 0],
// 0x20: ["ERR", 0],
0x21: ["ABS", 1],
0x22: ["TRUNC", 1],
0x23: ["SQRT", 1],
0x24: ["LOG", 1],
0x25: ["LN", 1],
0x26: ["PI", 0],
0x27: ["SIN", 1],
0x28: ["COS", 1],
0x29: ["TAN", 1],
0x2A: ["ATAN2", 2],
0x2B: ["ATAN", 1],
0x2C: ["ASIN", 1],
0x2D: ["ACOS", 1],
0x2E: ["EXP", 1],
0x2F: ["MOD", 2],
// 0x30
0x31: ["ISNA", 1],
0x32: ["ISERR", 1],
0x33: ["FALSE", 0],
0x34: ["TRUE", 0],
0x35: ["RAND", 0],
// 0x36 DATE
// 0x37 NOW
// 0x38 PMT
// 0x39 PV
// 0x3A FV
// 0x3B IF
// 0x3C DAY
// 0x3D MONTH
// 0x3E YEAR
0x3F: ["ROUND", 2],
// 0x40 TIME
// 0x41 HOUR
// 0x42 MINUTE
// 0x43 SECOND
0x44: ["ISNUMBER", 1],
0x45: ["ISTEXT", 1],
0x46: ["LEN", 1],
0x47: ["VALUE", 1],
// 0x48: ["FIXED", ?? 1],
0x49: ["MID", 3],
0x4A: ["CHAR", 1],
// 0x4B
// 0x4C FIND
// 0x4D DATEVALUE
// 0x4E TIMEVALUE
// 0x4F CELL
0x50: ["SUM", 69],
0x51: ["AVERAGEA", 69],
0x52: ["COUNTA", 69],
0x53: ["MINA", 69],
0x54: ["MAXA", 69],
// 0x55 VLOOKUP
// 0x56 NPV
// 0x57 VAR
// 0x58 STD
// 0x59 IRR
// 0x5A HLOOKUP
// 0x5B DSUM
// 0x5C DAVERAGE
// 0x5D DCOUNTA
// 0x5E DMIN
// 0x5F DMAX
// 0x60 DVARP
// 0x61 DSTDEVP
// 0x62 INDEX
// 0x63 COLS
// 0x64 ROWS
// 0x65 REPEAT
0x66: ["UPPER", 1],
0x67: ["LOWER", 1],
// 0x68 LEFT
// 0x69 RIGHT
// 0x6A REPLACE
0x6B: ["PROPER", 1],
// 0x6C CELL
0x6D: ["TRIM", 1],
// 0x6E CLEAN
0x6F: ["T", 1]
// 0x70 V
};
var BinOpTab = [
"", "", "", "", "", "", "", "",
"", "+", "-", "*", "/", "^", "=", "<>",
"<=", ">=", "<", ">", "", "", "", "",
"&", "", "", "", "", "", "", ""
"", "", "", "", "", "", "", "", // eslint-disable-line no-mixed-spaces-and-tabs
"", "+", "-", "*", "/", "^", "=", "<>", // eslint-disable-line no-mixed-spaces-and-tabs
"<=", ">=", "<", ">", "", "", "", "", // eslint-disable-line no-mixed-spaces-and-tabs
"&", "", "", "", "", "", "", "" // eslint-disable-line no-mixed-spaces-and-tabs
];
function wk1_fmla_to_csf(blob, o) {
@ -423,7 +520,7 @@ var WK_ = /*#__PURE__*/ (function() {
case 0x06: {
/* TODO: text encoding */
var Z = ""; while((cc = blob[blob.l++])) Z += String.fromCharCode(cc);
out.push('"' + Z.replace(/"/g, '""') + '"'); break;
out.push('"' + Z.replace(/"/g, '""') + '"');
} break;
case 0x08: out.push("-" + out.pop()); break;
@ -572,8 +669,8 @@ var WK_ = /*#__PURE__*/ (function() {
}
function parse_FORMULA_28(blob, length) {
var o = parse_NUMBER_27(blob, 14);
blob.l += length - 10; /* TODO: formula */
var o = parse_NUMBER_27(blob, 12);
blob.l += length - 12; /* TODO: formula */
return o;
}
@ -592,7 +689,7 @@ var WK_ = /*#__PURE__*/ (function() {
if(!opts.qpro || length < 21) return;
var id = blob.read_shift(1);
blob.l += 17;
var len = blob.read_shift(1);
blob.l += 1; //var len = blob.read_shift(1);
blob.l += 2;
var nm = blob.read_shift(length - 21, 'cstr');
return [id, nm];
@ -663,7 +760,7 @@ var WK_ = /*#__PURE__*/ (function() {
/*::[*/0x0030/*::]*/: { n:"UNFORMATTED" },
/*::[*/0x0031/*::]*/: { n:"CURSORW12" },
/*::[*/0x0032/*::]*/: { n:"WINDOW" },
/*::[*/0x0033/*::]*/: { n:"STRING", f:parse_LABEL },
/*::[*/0x0033/*::]*/: { n:"STRING", f:parse_STRING },
/*::[*/0x0037/*::]*/: { n:"PASSWORD" },
/*::[*/0x0038/*::]*/: { n:"LOCKED" },
/*::[*/0x003C/*::]*/: { n:"QUERY" },
@ -687,6 +784,7 @@ var WK_ = /*#__PURE__*/ (function() {
/*::[*/0x0069/*::]*/: { n:"MRANGES??" },
/*::[*/0x00CC/*::]*/: { n:"SHEETNAMECS", f:parse_SHEETNAMECS },
/*::[*/0x00DE/*::]*/: { n:"SHEETNAMELP", f:parse_SHEETNAMELP },
/*::[*/0x00FF/*::]*/: { n:"BOF", f:parseuint16 },
/*::[*/0xFFFF/*::]*/: { n:"" }
};
@ -815,6 +913,145 @@ var WK_ = /*#__PURE__*/ (function() {
/*::[*/0x6F44/*::]*/: { n:"??" },
/*::[*/0xFFFF/*::]*/: { n:"" }
};
/* QPW uses a different set of record types */
function qpw_to_workbook_buf(d, opts)/*:Workbook*/ {
prep_blob(d, 0);
var o = opts || {};
if(DENSE != null && o.dense == null) o.dense = DENSE;
var s/*:Worksheet*/ = ({}/*:any*/); if(o.dense) s["!data"] = [];
var SST = [], sname = "", formulae = [];
var range = {s:{r:-1,c:-1}, e:{r:-1,c:-1}};
var cnt = 0, type = 0, C = 0, R = 0;
var wb = { SheetNames: [], Sheets: {} };
outer: while(d.l < d.length) {
var RT = d.read_shift(2), length = d.read_shift(2);
var p = d.slice(d.l, d.l + length);
prep_blob(p, 0);
switch(RT) {
case 0x01: /* BOF */
if(p.read_shift(4) != 0x39575051) throw "Bad QPW9 BOF!";
break;
case 0x02: /* EOF */ break outer;
/* TODO: The behavior here should be consistent with Numbers: QP Notebook ~ .TN.SheetArchive, QP Sheet ~ .TST.TableModelArchive */
case 0x0401: /* BON */ break;
case 0x0402: /* EON */ /* TODO: backfill missing sheets based on BON cnt */ break;
case 0x0407: { /* SST */
p.l += 12;
while(p.l < p.length) {
cnt = p.read_shift(2);
type = p.read_shift(1);
SST.push(p.read_shift(cnt, 'cstr'));
}
} break;
case 0x0408: { /* FORMULAE */
//p.l += 12;
//while(p.l < p.length) {
// cnt = p.read_shift(2);
// formulae.push(p.slice(p.l, p.l + cnt + 1)); p.l += cnt + 1;
//}
} break;
case 0x0601: { /* BOS */
var sidx = p.read_shift(2);
s = ({}/*:any*/); if(o.dense) s["!data"] = [];
range.s.c = p.read_shift(2);
range.e.c = p.read_shift(2);
range.s.r = p.read_shift(4);
range.e.r = p.read_shift(4);
p.l += 4;
if(p.l + 2 < p.length) {
cnt = p.read_shift(2);
type = p.read_shift(1);
sname = cnt == 0 ? "" : p.read_shift(cnt, 'cstr');
}
if(!sname) sname = encode_col(sidx);
/* TODO: backfill empty sheets */
} break;
case 0x0602: { /* EOS */
/* NOTE: QP valid range A1:IV1000000 */
if(range.s.c > 0xFF || range.s.r > 999999) break;
if(range.e.c < range.s.c) range.e.c = range.s.c;
if(range.e.r < range.s.r) range.e.r = range.s.r;
s["!ref"] = encode_range(range);
book_append_sheet(wb, s, sname); // TODO: a barrel roll
} break;
case 0x0A01: { /* COL (like XLS Row, modulo the layout transposition) */
C = p.read_shift(2);
if(range.e.c < C) range.e.c = C;
if(range.s.c > C) range.s.c = C;
R = p.read_shift(4);
if(range.s.r > R) range.s.r = R;
R = p.read_shift(4);
if(range.e.r < R) range.e.r = R;
} break;
case 0x0C01: { /* MulCells (like XLS MulRK, but takes advantage of common column data patterns) */
R = p.read_shift(4), cnt = p.read_shift(4);
if(range.s.r > R) range.s.r = R;
if(range.e.r < R + cnt - 1) range.e.r = R + cnt - 1;
var CC = encode_col(C);
while(p.l < p.length) {
var cell = { t: "z" };
var flags = p.read_shift(1);
if(flags & 0x80) p.l += 2;
var mul = (flags & 0x40) ? p.read_shift(2) - 1: 0;
switch(flags & 0x1F) {
case 1: break;
case 2: cell = { t: "n", v: p.read_shift(2) }; break;
case 3: cell = { t: "n", v: p.read_shift(2, 'i') }; break;
case 5: cell = { t: "n", v: p.read_shift(8, 'f') }; break;
case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break;
case 8: cell = { t: "n", v: p.read_shift(8, 'f') }; p.l += 2; /* cell.f = formulae[p.read_shift(4)]; */ p.l += 4; break;
default: throw "Unrecognized QPW cell type " + (flags & 0x1F);
}
var delta = 0;
if(flags & 0x20) switch(flags & 0x1F) {
case 2: delta = p.read_shift(2); break;
case 3: delta = p.read_shift(2, 'i'); break;
case 7: delta = p.read_shift(2); break;
default: throw "Unsupported delta for QPW cell type " + (flags & 0x1F);
}
if(!(!o.sheetStubs && cell.t == "z")) {
if(s["!data"] != null) {
if(!s["!data"][R]) s["!data"][R] = [];
s["!data"][R][C] = cell;
} else s[CC + encode_row(R)] = cell;
}
++R; --cnt;
while(mul-- > 0 && cnt >= 0) {
if(flags & 0x20) switch(flags & 0x1F) {
case 2: cell = { t: "n", v: (cell.v + delta) & 0xFFFF }; break;
case 3: cell = { t: "n", v: (cell.v + delta) & 0xFFFF }; if(cell.v > 0x7FFF) cell.v -= 0x10000; break;
case 7: cell = { t: "s", v: SST[type = (type + delta) >>> 0] }; break;
default: throw "Cannot apply delta for QPW cell type " + (flags & 0x1F);
} else switch(flags & 0x1F) {
case 1: cell = { t: "z" }; break;
case 2: cell = { t: "n", v: p.read_shift(2) }; break;
case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break;
default: throw "Cannot apply repeat for QPW cell type " + (flags & 0x1F);
}
if(!(!o.sheetStubs && cell.t == "z")) {
if(s["!data"] != null) {
if(!s["!data"][R]) s["!data"][R] = [];
s["!data"][R][C] = cell;
} else s[CC + encode_row(R)] = cell;
}
++R; --cnt;
}
}
} break;
default: break;
}
d.l += length;
}
return wb;
}
return {
sheet_to_wk1: sheet_to_wk1,
book_to_wk3: book_to_wk3,

@ -106,7 +106,7 @@ function parse_rpr(rpr) {
return font;
}
var parse_rs = (function() {
var parse_rs = /*#__PURE__*/(function() {
var tregex = matchtag("t"), rpregex = matchtag("rPr");
/* 18.4.4 r CT_RElt */
function parse_r(r) {
@ -127,7 +127,7 @@ var parse_rs = (function() {
/* Parse a list of <r> tags */
var rs_to_html = (function parse_rs_factory() {
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>*/ = [];
@ -178,14 +178,14 @@ function parse_si(x, opts) {
/* 18.4.12 t ST_Xstring (Plaintext String) */
// TODO: is whitespace actually valid here?
if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) {
z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||""));
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);
}
/* 18.4.4 r CT_RElt (Rich Text Run) */
else if((/*y = */x.match(sirregex))) {
z.r = utf8read(x);
z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")));
z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")), true);
if(html) z.h = rs_to_html(parse_rs(z.r));
}
/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
@ -213,13 +213,12 @@ function parse_sst_xml(data/*:string*/, opts)/*:SST*/ {
return s;
}
RELS.SST = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
var straywsregex = /^\s|\s$|[\t\n\r]/;
function write_sst_xml(sst/*:SST*/, opts)/*:string*/ {
if(!opts.bookSST) return "";
var o = [XML_HEADER];
o[o.length] = (writextag('sst', null, {
xmlns: XMLNS.main[0],
xmlns: XMLNS_main[0],
count: sst.Count,
uniqueCount: sst.Unique
}));
@ -230,6 +229,7 @@ function write_sst_xml(sst/*:SST*/, opts)/*:string*/ {
else {
sitag += "<t";
if(!s.t) s.t = "";
if(typeof s.t !== "string") s.t = String(s.t);
if(s.t.match(straywsregex)) sitag += ' xml:space="preserve"';
sitag += ">" + escapexml(s.t) + "</t>";
}

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

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

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

@ -262,8 +262,8 @@ function parse_fonts(t, styles, themes, opts) {
/* 18.8.31 numFmts CT_NumFmts */
function parse_numFmts(t, styles, opts) {
styles.NumberFmt = [];
var k/*Array<number>*/ = (keys(SSF._table)/*:any*/);
for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
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[0].match(tagregex);
if(!m) return;
for(i=0; i < m.length; ++i) {
@ -278,7 +278,7 @@ function parse_numFmts(t, styles, opts) {
for(j = 0x188; j > 0x3c; --j) if(styles.NumberFmt[j] == null) break;
styles.NumberFmt[j] = f;
}
SSF.load(f,j);
SSF__load(f,j);
}
} break;
case '</numFmt>': break;
@ -369,7 +369,7 @@ function write_cellXfs(cellXfs)/*:string*/ {
}
/* 18.8 Styles CT_Stylesheet*/
var parse_sty_xml= (function make_pstyx() {
var parse_sty_xml= /*#__PURE__*/(function make_pstyx() {
var numFmtRegex = /<(?:\w+:)?numFmts([^>]*)>[\S\s]*?<\/(?:\w+:)?numFmts>/;
var cellXfRegex = /<(?:\w+:)?cellXfs([^>]*)>[\S\s]*?<\/(?:\w+:)?cellXfs>/;
var fillsRegex = /<(?:\w+:)?fills([^>]*)>[\S\s]*?<\/(?:\w+:)?fills>/;
@ -410,15 +410,11 @@ return function parse_sty_xml(data, themes, opts) {
};
})();
var STYLES_XML_ROOT = writextag('styleSheet', null, {
'xmlns': XMLNS.main[0],
'xmlns:vt': XMLNS.vt
});
RELS.STY = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
function write_sty_xml(wb/*:Workbook*/, opts)/*:string*/ {
var o = [XML_HEADER, STYLES_XML_ROOT], w;
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>');

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

@ -1,5 +1,3 @@
RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
/* Even though theme layout is dk1 lt1 dk2 lt2, true order is lt1 dk1 lt2 dk2 */
var XLSXThemeClrScheme = [
'</a:lt1>', '</a:dk1>', '</a:lt2>', '</a:dk2>',
@ -96,7 +94,7 @@ var themeltregex = /<a:themeElements([^>]*)>[\s\S]*<\/a:themeElements>/;
/* 14.2.7 Theme Part */
function parse_theme_xml(data/*:string*/, opts) {
/* 20.1.6.9 theme CT_OfficeStyleSheet */
if(!data || data.length === 0) return parse_theme_xml(write_theme());
if(!data || data.length === 0) data = write_theme();
var t;
var themes = {};

@ -1,151 +0,0 @@
RELS.XLMETA = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata";
function parse_xlmeta_xml(data, name, opts) {
var out = { Types: [] };
if (!data)
return out;
var pass = false;
data.replace(tagregex, function(x, idx) {
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 "<futureMetadata":
break;
case "</futureMetadata>":
break;
case "<bk>":
break;
case "</bk>":
break;
case "<rc":
break;
case "</rc>":
break;
case "<cellMetadata":
case "</cellMetadata>":
break;
case "<valueMetadata":
break;
case "</valueMetadata>":
break;
case "<extLst":
case "<extLst>":
case "</extLst>":
case "<extLst/>":
break;
case "<ext":
pass = true;
break;
case "</ext>":
pass = false;
break;
default:
if (!pass && 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("");
}
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 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 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: [] };
var opts = _opts || {};
var state = [];
var pass = false;
recordhopper(data, function(val, R_n, RT) {
switch (RT) {
case 335:
out.Types.push({ name: val.name });
break;
case 51:
break;
case 35:
state.push(R_n);
pass = true;
break;
case 36:
state.pop();
pass = false;
break;
default:
if ((R_n || "").indexOf("Begin") > 0) {
} else if ((R_n || "").indexOf("End") > 0) {
} else if (!pass || opts.WTF && state[state.length - 1] != "BrtFRTBegin")
throw new Error("Unexpected record " + RT + " " + R_n);
}
});
return out;
}
function write_xlmeta_bin() {
var ba = buf_array();
write_record(ba, "BrtBeginMetadata");
write_record(ba, "BrtBeginEsmdtinfo", write_UInt32LE(1));
write_record(ba, "BrtMdtinfo", write_BrtMdtinfo({
name: "XLDAPR",
version: 12e4,
flags: 3496657072
}));
write_record(ba, "BrtEndEsmdtinfo");
write_record(ba, "BrtBeginEsfmd", write_BrtBeginEsfmd(1, "XLDAPR"));
write_record(ba, "BrtBeginFmd");
write_record(ba, "BrtFRTBegin", write_UInt32LE(514));
write_record(ba, "BrtBeginDynamicArrayPr", write_UInt32LE(0));
write_record(ba, "BrtEndDynamicArrayPr", writeuint16(1));
write_record(ba, "BrtFRTEnd");
write_record(ba, "BrtEndFmd");
write_record(ba, "BrtEndEsfmd");
write_record(ba, "BrtBeginEsmdb", write_BrtBeginEsmdb(1, true));
write_record(ba, "BrtMdb", write_BrtMdb([[1, 0]]));
write_record(ba, "BrtEndEsmdb");
write_record(ba, "BrtEndMetadata");
return ba.end();
}

111
bits/51_xlsbmeta.js Normal file

@ -0,0 +1,111 @@
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,10 +1,11 @@
RELS.XLMETA = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata";
function parse_xlmeta_xml(data, name, opts) {
var out = { Types: [] };
var out = { Types: [], Cell: [], Value: [] };
if (!data)
return out;
var pass = false;
data.replace(tagregex, function(x, idx) {
var metatype = 2;
var lastmeta;
data.replace(tagregex, function(x) {
var y = parsexmltag(x);
switch (strip_ns(y[0])) {
case "<?xml":
@ -18,7 +19,12 @@ function parse_xlmeta_xml(data, name, opts) {
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;
@ -27,15 +33,24 @@ function parse_xlmeta_xml(data, name, opts) {
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>":
@ -48,8 +63,15 @@ function parse_xlmeta_xml(data, name, opts) {
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.WTF)
if (!pass && (opts == null ? void 0 : opts.WTF))
throw new Error("unrecognized " + y[0] + " in metadata");
}
return x;

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

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

@ -1,7 +1,4 @@
/* 20.5 DrawingML - SpreadsheetML Drawing */
RELS.IMG = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
RELS.DRAW = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing";
/* 20.5.2.35 wsDr CT_Drawing */
function parse_drawing(data, rels/*:any*/) {
if(!data) return "??";

@ -1,20 +1,27 @@
/* L.5.5.2 SpreadsheetML Comments + VML Schema */
var _shapeid = 1024;
function write_comments_vml(rId/*:number*/, comments) {
function write_vml(rId/*:number*/, comments) {
var csize = [21600, 21600];
/* L.5.2.1.2 Path Attribute */
var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(",");
var o = [
writextag("xml", null, { 'xmlns:v': XLMLNS.v, 'xmlns:o': XLMLNS.o, 'xmlns:x': XLMLNS.x, 'xmlns:mv': XLMLNS.mv }).replace(/\/>/,">"),
writextag("o:shapelayout", writextag("o:idmap", null, {'v:ext':"edit", 'data':rId}), {'v:ext':"edit"}),
writextag("v:shapetype", [
writextag("v:stroke", null, {joinstyle:"miter"}),
writextag("v:path", null, {gradientshapeok:"t", 'o:connecttype':"rect"})
].join(""), {id:"_x0000_t202", 'o:spt':202, coordsize:csize.join(","),path:bbox})
writextag("o:shapelayout", writextag("o:idmap", null, {'v:ext':"edit", 'data':rId}), {'v:ext':"edit"})
];
while(_shapeid < rId * 1000) _shapeid += 1000;
comments.forEach(function(x) {
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)/*:string*/ {
var c = decode_cell(x[0]);
var fillopts = /*::(*/{'color2':"#BEFF82", 'type':"gradient"}/*:: :any)*/;
if(fillopts.type == "gradient") fillopts.angle = "-180";
@ -22,9 +29,8 @@ function write_comments_vml(rId/*:number*/, comments) {
var fillxml = writextag('v:fill', fillparm, fillopts);
var shadata = ({on:"t", 'obscured':"t"}/*:any*/);
++_shapeid;
o = o.concat([
return [
'<v:shape' + wxt_helper({
id:'_x0000_s' + _shapeid,
type:"#_x0000_t202",
@ -47,7 +53,5 @@ function write_comments_vml(rId/*:number*/, comments) {
x[1].hidden ? '' : '<x:Visible/>',
'</x:ClientData>',
'</v:shape>'
]); });
o.push('</xml>');
return o.join("");
].join("");
}

@ -1,17 +1,15 @@
RELS.CMNT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
function sheet_insert_comments(sheet, comments/*:Array<RawComment>*/) {
var dense = Array.isArray(sheet);
function sheet_insert_comments(sheet/*:WorkSheet*/, comments/*:Array<RawComment>*/, threaded/*:boolean*/, people/*:?Array<any>*/) {
var dense = sheet["!data"] != null;
var cell/*:Cell*/;
comments.forEach(function(comment) {
var r = decode_cell(comment.ref);
if(dense) {
if(!sheet[r.r]) sheet[r.r] = [];
cell = sheet[r.r][r.c];
if(!sheet["!data"][r.r]) sheet["!data"][r.r] = [];
cell = sheet["!data"][r.r][r.c];
} else cell = sheet[comment.ref];
if (!cell) {
cell = ({t:"z"}/*:any*/);
if(dense) sheet[r.r][r.c] = cell;
if(dense) sheet["!data"][r.r][r.c] = cell;
else sheet[comment.ref] = cell;
var range = safe_decode_range(sheet["!ref"]||"BDWGO1000001:A1");
if(range.s.r > r.r) range.s.r = r.r;
@ -19,13 +17,21 @@ function sheet_insert_comments(sheet, comments/*:Array<RawComment>*/) {
if(range.s.c > r.c) range.s.c = r.c;
if(range.e.c < r.c) range.e.c = r.c;
var encoded = encode_range(range);
if (encoded !== sheet["!ref"]) sheet["!ref"] = encoded;
sheet["!ref"] = encoded;
}
if (!cell.c) cell.c = [];
var o/*:Comment*/ = ({a: comment.author, t: comment.t, r: comment.r});
var o/*:Comment*/ = ({a: comment.author, t: comment.t, r: comment.r, T: threaded});
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);
});
}

@ -30,28 +30,156 @@ function parse_comments_xml(data/*:string*/, opts)/*:Array<RawComment>*/ {
return commentList;
}
var CMNT_XML_ROOT = writextag('comments', null, { 'xmlns': XMLNS.main[0] });
function write_comments_xml(data/*::, opts*/) {
var o = [XML_HEADER, CMNT_XML_ROOT];
var 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) return;
iauthor.push(a);
o.push("<author>" + a + "</author>");
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) {
/* 18.7.3 CT_Comment */
o.push('<comment ref="' + d[0] + '" authorId="' + iauthor.indexOf(escapexml(c.a)) + '"><text>');
o.push(writetag("t", c.t == null ? "" : escapexml(c.t)));
o.push('</text></comment>');
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 {
/* 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("");
}

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

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

@ -1,5 +1,5 @@
/* TODO: it will be useful to parse the function str */
var rc_to_a1 = (function(){
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) {
@ -24,13 +24,13 @@ var rc_to_a1 = (function(){
})();
var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)(10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})(?![_.\(A-Za-z0-9])/g;
var a1_to_rc =(function(){
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 = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1));
var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1));
var R = $4 == "$" ? (r+1) : (r == 0 ? "" : "[" + r + "]");
var C = $2 == "$" ? (c+1) : (c == 0 ? "" : "[" + c + "]");
return $1 + "R" + R + "C" + C;
});
};

@ -572,7 +572,6 @@ var PtgDupes = {
/*::[*/0x5C/*::]*/: 0x3C, /*::[*/0x7C/*::]*/: 0x3C,
/*::[*/0x5D/*::]*/: 0x3D, /*::[*/0x7D/*::]*/: 0x3D
};
(function(){for(var y in PtgDupes) PtgTypes[y] = PtgTypes[PtgDupes[y]];})();
var Ptg18 = {
/*::[*/0x01/*::]*/: { n:'PtgElfLel', f:parse_PtgElfLel },
@ -597,12 +596,12 @@ var Ptg19 = {
/*::[*/0x08/*::]*/: { n:'PtgAttrGoto', f:parse_PtgAttrGoto },
/*::[*/0x10/*::]*/: { n:'PtgAttrSum', f:parse_PtgAttrSum },
/*::[*/0x20/*::]*/: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
/*::[*/0x21/*::]*/: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
/*::[*/0x40/*::]*/: { n:'PtgAttrSpace', f:parse_PtgAttrSpace },
/*::[*/0x41/*::]*/: { n:'PtgAttrSpaceSemi', f:parse_PtgAttrSpaceSemi },
/*::[*/0x80/*::]*/: { n:'PtgAttrIfError', f:parse_PtgAttrIfError },
/*::[*/0xFF/*::]*/: {}
};
Ptg19[0x21] = Ptg19[0x20];
/* [MS-XLS] 2.5.198.103 ; [MS-XLSB] 2.5.97.87 */
function parse_RgbExtra(blob, length, rgce, opts) {
@ -646,7 +645,7 @@ function parse_Rgce(blob, length, opts) {
while(target != blob.l) {
length = target - blob.l;
id = blob[blob.l];
R = PtgTypes[id];
R = PtgTypes[id] || PtgTypes[PtgDupes[id]];
if(id === 0x18 || id === 0x19) R = (id === 0x18 ? Ptg18 : Ptg19)[blob[blob.l + 1]];
if(!R || !R.f) { /*ptgs.push*/(parsenoop(blob, length)); }
else { ptgs.push([R.n, R.f(blob, length, opts)]); }
@ -689,13 +688,15 @@ var PtgBinOp = {
PtgSub: "-"
};
// List of invalid characters needs to be tested further
var quoteCharacters /*:RegExp */ = new RegExp(/[^\w\u4E00-\u9FFF\u3040-\u30FF]/);
function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ {
if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name");
if (quoteCharacters.test(sname)) return "'" + sname + "'";
return sname;
// TODO: explore space
function make_3d_range(start, end) {
var s = start.lastIndexOf("!"), e = end.lastIndexOf("!");
if(s == -1 && e == -1) return start + ":" + end;
if(s > 0 && e > 0 && start.slice(0, s).toLowerCase() == end.slice(0, e).toLowerCase()) return start + ":" + end.slice(e+1);
console.error("Cannot hydrate range", start, end);
return start + ":" + end;
}
function get_ixti_raw(supbooks, ixti/*:number*/, opts)/*:string*/ {
if(!supbooks) return "SH33TJSERR0";
if(opts.biff > 8 && (!supbooks.XTI || !supbooks.XTI[ixti])) return supbooks.SheetNames[ixti];
@ -792,7 +793,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
break;
case 'PtgRange': /* [MS-XLS] 2.5.198.83 */
e1 = stack.pop(); e2 = stack.pop();
stack.push(e2+":"+e1);
stack.push(make_3d_range(e2,e1));
break;
case 'PtgAttrChoose': /* [MS-XLS] 2.5.198.34 */
@ -1040,6 +1041,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
}
}
if(stack.length > 1 && opts.WTF) throw new Error("bad formula stack");
if(stack[0] == "TRUE") return true; if(stack[0] == "FALSE") return false;
return stack[0];
}

@ -124,3 +124,209 @@ var parse_XLSBCellParsedFormula = parse_XLSBParsedFormula;
var parse_XLSBNameParsedFormula = parse_XLSBParsedFormula;
/* [MS-XLSB] 2.5.97.98 SharedParsedFormula */
var parse_XLSBSharedParsedFormula = parse_XLSBParsedFormula;
/* Writes a PtgNum or PtgInt */
function write_XLSBFormulaNum(val/*:number*/) {
if((val | 0) == val && val < Math.pow(2,16) && val >= 0) {
var oint = new_buf(11);
oint.write_shift(4, 3);
oint.write_shift(1, 0x1e);
oint.write_shift(2, val);
oint.write_shift(4, 0);
return oint;
}
var num = new_buf(17);
num.write_shift(4, 11);
num.write_shift(1, 0x1f);
num.write_shift(8, val);
num.write_shift(4, 0);
return num;
}
/* Writes a PtgErr */
function write_XLSBFormulaErr(val/*:number*/) {
var oint = new_buf(10);
oint.write_shift(4, 2);
oint.write_shift(1, 0x1C);
oint.write_shift(1, val);
oint.write_shift(4, 0);
return oint;
}
/* Writes a PtgBool */
function write_XLSBFormulaBool(val/*:boolean*/) {
var oint = new_buf(10);
oint.write_shift(4, 2);
oint.write_shift(1, 0x1D);
oint.write_shift(1, val?1:0);
oint.write_shift(4, 0);
return oint;
}
/* Writes a PtgStr */
function write_XLSBFormulaStr(val/*:string*/) {
var preamble = new_buf(7);
preamble.write_shift(4, 3 + 2 * val.length);
preamble.write_shift(1, 0x17);
preamble.write_shift(2, val.length);
var body = new_buf(2 * val.length);
body.write_shift(2 * val.length, val, "utf16le");
var postamble = new_buf(4);
postamble.write_shift(4, 0);
return bconcat([preamble, body, postamble]);
}
/* Writes a PtgRef */
function write_XLSBFormulaRef(str) {
var cell = decode_cell(str);
var out = new_buf(15);
out.write_shift(4, 7);
out.write_shift(1, 0x04 | ((1)<<5));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
out.write_shift(4, 0);
return out;
}
/* Writes a PtgRef3d */
function write_XLSBFormulaRef3D(str, wb) {
var lastbang = str.lastIndexOf("!");
var sname = str.slice(0, lastbang);
str = str.slice(lastbang+1);
var cell = decode_cell(str);
if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
var out = new_buf(17);
out.write_shift(4, 9);
out.write_shift(1, 0x1A | ((1)<<5));
out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase()));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
out.write_shift(4, 0);
return out;
}
/* Writes a PtgRefErr3d */
function write_XLSBFormulaRefErr3D(str, wb) {
var lastbang = str.lastIndexOf("!");
var sname = str.slice(0, lastbang);
str = str.slice(lastbang+1);
if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
var out = new_buf(17);
out.write_shift(4, 9);
out.write_shift(1, 0x1C | ((1)<<5));
out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase()));
out.write_shift(4, 0);
out.write_shift(2, 0); // <== ColRelShort
out.write_shift(4, 0);
return out;
}
/* Writes a single sheet range [PtgRef PtgRef PtgRange] */
function write_XLSBFormulaRange(_str) {
var parts = _str.split(":"), str = parts[0];
var out = new_buf(23);
out.write_shift(4, 15);
/* start cell */
str = parts[0]; var cell = decode_cell(str);
out.write_shift(1, 0x04 | ((1)<<5));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
out.write_shift(4, 0);
/* end cell */
str = parts[1]; cell = decode_cell(str);
out.write_shift(1, 0x04 | ((1)<<5));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
out.write_shift(4, 0);
/* PtgRange */
out.write_shift(1, 0x11);
out.write_shift(4, 0);
return out;
}
/* Writes a range with explicit sheet name [PtgRef3D PtgRef3D PtgRange] */
function write_XLSBFormulaRangeWS(_str, wb) {
var lastbang = _str.lastIndexOf("!");
var sname = _str.slice(0, lastbang);
_str = _str.slice(lastbang+1);
if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
var parts = _str.split(":"); str = parts[0];
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;

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

@ -1,10 +1,6 @@
var strs = {}; // shared strings
var _ssfopts = {}; // spreadsheet formatting options
RELS.WS = [
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
"http://purl.oclc.org/ooxml/officeDocument/relationships/worksheet"
];
/*global Map */
var browser_has_Map = typeof Map !== 'undefined';
@ -66,7 +62,7 @@ function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) {
var i = 0x3c, len = styles.length;
if(z == null && opts.ssf) {
for(; i < 0x188; ++i) if(opts.ssf[i] == null) {
SSF.load(cell.z, i);
SSF__load(cell.z, i);
// $FlowIgnore
opts.ssf[i] = cell.z;
opts.revssf[cell.z] = z = i;
@ -87,28 +83,28 @@ function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) {
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) {
try {
if(opts.cellNF) p.z = SSF._table[fmtid];
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(SSF._table[fmtid] == null) SSF.load(SSFImplicit[fmtid] || "General", fmtid);
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 = SSF._general_int(p.v);
else p.w = SSF._general_num(p.v);
if((p.v|0) === p.v) p.w = p.v.toString(10);
else p.w = SSF_general_num(p.v);
}
else if(p.t === 'd') {
var dd = datenum(p.v);
if((dd|0) === dd) p.w = SSF._general_int(dd);
else p.w = SSF._general_num(dd);
if((dd|0) === dd) p.w = dd.toString(10);
else p.w = SSF_general_num(dd);
}
else if(p.v === undefined) return "";
else p.w = SSF._general(p.v,_ssfopts);
else p.w = SSF_general(p.v,_ssfopts);
}
else if(p.t === 'd') p.w = SSF.format(fmtid,datenum(p.v),_ssfopts);
else p.w = SSF.format(fmtid,p.v,_ssfopts);
else if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v),_ssfopts);
else p.w = SSF_format(fmtid,p.v,_ssfopts);
} catch(e) { if(opts.WTF) throw e; }
if(!opts.cellStyles) return;
if(fillid != null) try {

@ -20,7 +20,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
/* 18.3.1.99 worksheet CT_Worksheet */
var s = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
var s = ({}/*:any*/); if(opts.dense) s["!data"] = [];
var refguess/*:Range*/ = ({s: {r:2000000, c:2000000}, e: {r:0, c:0} }/*:any*/);
var data1 = "", data2 = "";
@ -39,7 +39,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
if(ridx > 0) {
var ref = data1.slice(ridx,ridx+50).match(dimregex);
if(ref) parse_ws_xml_dim(s, ref[1]);
if(ref && !(opts && opts.nodim)) parse_ws_xml_dim(s, ref[1]);
}
/* 18.3.1.88 sheetViews CT_SheetViews */
@ -75,6 +75,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
var margins = data2.match(marginregex);
if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));
if(opts && opts.nodim) refguess.s.c = refguess.s.r = 0;
if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
if(opts.sheetRows > 0 && s["!ref"]) {
var tmpref = safe_decode_range(s["!ref"]);
@ -106,7 +107,7 @@ function parse_ws_xml_sheetpr(sheetPr/*:string*/, s, wb/*:WBWBProps*/, idx/*:num
if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
if(data.codeName) wb.Sheets[idx].CodeName = unescapexml(utf8read(data.codeName));
}
function parse_ws_xml_sheetpr2(sheetPr/*:string*/, body/*:string*/, s, wb/*:WBWBProps*/, idx/*:number*/, styles, themes) {
function parse_ws_xml_sheetpr2(sheetPr/*:string*/, body/*:string*/, s, wb/*:WBWBProps*/, idx/*:number*/) {
parse_ws_xml_sheetpr(sheetPr.slice(0, sheetPr.indexOf(">")), s, wb, idx);
}
function write_ws_xml_sheetpr(ws, wb, idx, opts, o) {
@ -149,7 +150,7 @@ function write_ws_xml_protection(sp)/*:string*/ {
}
function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
var dense = Array.isArray(s);
var dense = s["!data"] != null;
for(var i = 0; i != data.length; ++i) {
var val = parsexmltag(utf8read(data[i]), true);
if(!val.ref) return;
@ -165,11 +166,11 @@ function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
if(val.tooltip) { val.Tooltip = val.tooltip; delete val.tooltip; }
var rng = safe_decode_range(val.ref);
for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
var addr = encode_cell({c:C,r:R});
var addr = encode_col(C) + encode_row(R);
if(dense) {
if(!s[R]) s[R] = [];
if(!s[R][C]) s[R][C] = {t:"z",v:undefined};
s[R][C].l = val;
if(!s["!data"][R]) s["!data"][R] = [];
if(!s["!data"][R][C]) s["!data"][R][C] = {t:"z",v:undefined};
s["!data"][R][C].l = val;
} else {
if(!s[addr]) s[addr] = {t:"z",v:undefined};
s[addr].l = val;
@ -228,7 +229,7 @@ function write_ws_xml_autofilter(data, ws, wb, idx)/*:string*/ {
var name = names[i];
if(name.Name != '_xlnm._FilterDatabase') continue;
if(name.Sheet != idx) continue;
name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break;
name.Ref = formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref); break;
}
if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref });
return writextag("autoFilter", null, {ref:ref});
@ -236,7 +237,7 @@ function write_ws_xml_autofilter(data, ws, wb, idx)/*:string*/ {
/* 18.3.1.88 sheetViews CT_SheetViews */
/* 18.3.1.87 sheetView CT_SheetView */
var sviewregex = /<(?:\w:)?sheetView(?:[^>a-z][^>]*)?\/?>/;
var sviewregex = /<(?:\w:)?sheetView(?:[^>a-z][^>]*)?\/?>/g;
function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) {
if(!wb.Views) wb.Views = [{}];
(data.match(sviewregex)||[]).forEach(function(r/*:string*/, i/*:number*/) {
@ -246,7 +247,7 @@ function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) {
// $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore
if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
if(tag.rightToLeft && parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
});
}
function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
@ -257,7 +258,8 @@ function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
}
function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string*/ {
if(cell.v === undefined && typeof cell.f !== "string" || cell.t === 'z') return "";
if(cell.c) ws['!comments'].push([ref, cell.c]);
if((cell.v === undefined || cell.t === "z" && !(opts||{}).sheetStubs) && typeof cell.f !== "string" && typeof cell.z == "undefined") return "";
var vv = "";
var oldt = cell.t, oldv = cell.v;
if(cell.t !== "z") switch(cell.t) {
@ -271,11 +273,11 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string
cell.t = 'n';
vv = ''+(cell.v = datenum(parseDate(cell.v)));
}
if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
if(typeof cell.z === 'undefined') cell.z = table_fmt[14];
break;
default: vv = cell.v; break;
}
var v = writetag('v', escapexml(vv)), o = ({r:ref}/*:any*/);
var v = (cell.t == "z" || cell.v == null)? "" : writetag('v', escapexml(vv)), o = ({r:ref}/*:any*/);
/* TODO: cell style */
var os = get_cell_style(opts.cellXfs, cell, opts);
if(os !== 0) o.s = os;
@ -291,20 +293,22 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string
v = writetag('v', ''+get_sst_id(opts.Strings, cell.v, opts.revStrings));
o.t = "s"; break;
}
o.t = "str"; break;
else o.t = "str"; break;
}
if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; }
if(typeof cell.f == "string" && cell.f) {
var ff = cell.F && cell.F.slice(0, ref.length) == ref ? {t:"array", ref:cell.F} : null;
v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : "");
}
if(cell.l) ws['!links'].push([ref, cell.l]);
if(cell.c) ws['!comments'].push([ref, cell.c]);
if(cell.l) {
cell.l.display = escapexml(vv);
ws['!links'].push([ref, cell.l]);
}
if(cell.D) o.cm = 1;
return writextag('c', v, o);
}
var parse_ws_xml_data = (function() {
var parse_ws_xml_data = /*#__PURE__*/(function() {
var cellregex = /<(?:\w+:)?c[ \/>]/, rowregex = /<\/(?:\w+:)?row>/;
var rregex = /r=["']([^"']*)["']/, isregex = /<(?:\w+:)?is>([\S\s]*?)<\/(?:\w+:)?is>/;
var refregex = /ref=["']([^"']*)["']/;
@ -318,7 +322,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
var do_format = Array.isArray(styles.CellXf), cf;
var arrayf/*:Array<[Range, string]>*/ = [];
var sharedf = [];
var dense = Array.isArray(s);
var dense = s["!data"] != null;
var rows/*:Array<RowInfo>*/ = [], rowobj = {}, rowrite = false;
var sheetStubs = !!opts.sheetStubs;
for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
@ -338,7 +342,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
if(opts.sheetRows && opts.sheetRows < tagr) continue;
rowobj = {}; rowrite = false;
if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; }
if(tag.hidden && parsexmlbool(tag.hidden)) { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj;
}
@ -349,13 +353,15 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
tag = parsexmltag(x.slice(rstarti,ri), true);
tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
if(opts.sheetRows && opts.sheetRows < tagr) continue;
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
if(!opts.nodim) {
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
}
if(opts && opts.cellStyles) {
rowobj = {}; rowrite = false;
if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; }
if(tag.hidden && parsexmlbool(tag.hidden)) { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj;
}
@ -388,7 +394,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
if(opts.cellFormula) {
if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') {
/* TODO: match against XLSXFutureFunctions */
p.f=unescapexml(utf8read(cref[1])).replace(/\r\n/g, "\n");
p.f=unescapexml(utf8read(cref[1]), true);
if(!opts.xlfn) p.f = _xlfn(p.f);
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
p.F = (d.match(refregex)||[])[1];
@ -442,7 +448,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
break;
case 'str':
p.t = "s";
p.v = (p.v!=null) ? utf8read(p.v) : '';
p.v = (p.v!=null) ? unescapexml(utf8read(p.v), true) : '';
if(opts.cellHTML) p.h = escapehtml(p.v);
break;
case 'inlineStr':
@ -476,15 +482,21 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
}
}
safe_format(p, fmtid, fillid, opts, themes, styles);
if(opts.cellDates && do_format && p.t == 'n' && SSF.is_date(SSF._table[fmtid])) { p.t = 'd'; p.v = numdate(p.v); }
if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.t = 'd'; p.v = numdate(p.v); }
if(tag.cm && opts.xlmeta) {
var cm = (opts.xlmeta.Types||[])[+tag.cm-1];
if(cm && cm.name == 'XLDAPR') p.D = true;
var cm = (opts.xlmeta.Cell||[])[+tag.cm-1];
if(cm && cm.type == 'XLDAPR') p.D = true;
}
var _r;
if(opts.nodim) {
_r = decode_cell(tag.r);
if(guess.s.r > _r.r) guess.s.r = _r.r;
if(guess.e.r < _r.r) guess.e.r = _r.r;
}
if(dense) {
var _r = decode_cell(tag.r);
if(!s[_r.r]) s[_r.r] = [];
s[_r.r][_r.c] = p;
_r = decode_cell(tag.r);
if(!s["!data"][_r.r]) s["!data"][_r.r] = [];
s["!data"][_r.r][_r.c] = p;
} else s[tag.r] = p;
}
}
@ -493,7 +505,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*//*::, rels*/)/*:string*/ {
var o/*:Array<string>*/ = [], r/*:Array<string>*/ = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols/*:Array<string>*/ = [], R=0, C=0, rows = ws['!rows'];
var dense = Array.isArray(ws);
var dense = ws["!data"] != null;
var params = ({r:rr}/*:any*/), row/*:RowInfo*/, height = -1;
for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
for(R = range.s.r; R <= range.e.r; ++R) {
@ -501,7 +513,7 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
rr = encode_row(R);
for(C = range.s.c; C <= range.e.c; ++C) {
ref = cols[C] + rr;
var _cell = dense ? (ws[R]||[])[C]: ws[ref];
var _cell = dense ? (ws["!data"][R]||[])[C]: ws[ref];
if(_cell === undefined) continue;
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
}
@ -535,13 +547,11 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
return o.join("");
}
var WS_XML_ROOT = writextag('worksheet', null, {
'xmlns': XMLNS.main[0],
'xmlns:r': XMLNS.r
});
function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
var o = [XML_HEADER, WS_XML_ROOT];
var o = [XML_HEADER, writextag('worksheet', null, {
'xmlns': XMLNS_main[0],
'xmlns:r': XMLNS.r
})];
var s = wb.SheetNames[idx], sidx = 0, rdata = "";
var ws = wb.Sheets[s];
if(ws == null) ws = {};
@ -611,6 +621,7 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
}
if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1));
if(l[1].Tooltip) rel.tooltip = escapexml(l[1].Tooltip);
rel.display = l[1].display;
o[o.length] = writextag("hyperlink",null,rel);
});
o[o.length] = "</hyperlinks>";

@ -41,12 +41,13 @@ function write_BrtRowHdr(R/*:number*/, range, ws) {
o.l += 4;
var caddr = {r:R, c:0};
var dense = ws["!data"] != null;
for(var i = 0; i < 16; ++i) {
if((range.s.c > ((i+1) << 10)) || (range.e.c < (i << 10))) continue;
var first = -1, last = -1;
for(var j = (i<<10); j < ((i+1)<<10); ++j) {
caddr.c = j;
var cell = Array.isArray(ws) ? (ws[caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)];
var cell = dense ? (ws["!data"][caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)];
if(cell) { if(first < 0) first = j; last = j; }
}
if(first < 0) continue;
@ -64,7 +65,7 @@ function write_BrtRowHdr(R/*:number*/, range, ws) {
}
function write_row_header(ba, ws, range, R) {
var o = write_BrtRowHdr(R, range, ws);
if((o.length > 17) || (ws['!rows']||[])[R]) write_record(ba, 'BrtRowHdr', o);
if((o.length > 17) || (ws['!rows']||[])[R]) write_record(ba, 0x0000 /* BrtRowHdr */, o);
}
/* [MS-XLSB] 2.4.820 BrtWsDim */
@ -258,9 +259,10 @@ function parse_BrtCellSt(data) {
return [cell, value, 'str'];
}
function write_BrtCellSt(cell, ncell, o) {
var data = cell.v == null ? "" : String(cell.v);
if(o == null) o = new_buf(12 + 4 * cell.v.length);
write_XLSBCell(ncell, o);
write_XLWideString(cell.v, o);
write_XLWideString(data, o);
return o.length > o.l ? o.slice(0, o.l) : o;
}
function parse_BrtShortSt(data) {
@ -269,9 +271,10 @@ function parse_BrtShortSt(data) {
return [cell, value, 'str'];
}
function write_BrtShortSt(cell, ncell, o) {
if(o == null) o = new_buf(8 + 4 * cell.v.length);
var data = cell.v == null ? "" : String(cell.v);
if(o == null) o = new_buf(8 + 4 * data.length);
write_XLSBShortCell(ncell, o);
write_XLWideString(cell.v, o);
write_XLWideString(data, o);
return o.length > o.l ? o.slice(0, o.l) : o;
}
@ -508,7 +511,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
var opts = _opts || {};
if(!rels) rels = {'!id':{}};
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
var s/*:Worksheet*/ = (opts.dense ? [] : {});
var s/*:Worksheet*/ = ({}); if(opts.dense) s["!data"] = [];
var ref;
var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
@ -540,7 +543,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
var cm, vm;
recordhopper(data, function ws_parse(val, R_n, RT) {
recordhopper(data, function ws_parse(val, RR, RT) {
if(end) return;
switch(RT) {
case 0x0094: /* 'BrtWsDim' */
@ -584,7 +587,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
}
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
C = val[0].c == -1 ? C + 1 : val[0].c;
if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
if(opts.dense) { if(!s["!data"][R]) s["!data"][R] = []; s["!data"][R][C] = p; }
else s[encode_col(C) + rr] = p;
if(opts.cellFormula) {
af = false;
@ -602,11 +605,11 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
if(refguess.s.c > C) refguess.s.c = C;
if(refguess.e.r < row.r) refguess.e.r = row.r;
if(refguess.e.c < C) refguess.e.c = C;
if(opts.cellDates && cf && p.t == 'n' && SSF.is_date(SSF._table[cf.numFmtId])) {
var _d = SSF.parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
if(opts.cellDates && cf && p.t == 'n' && fmt_is_date(table_fmt[cf.numFmtId])) {
var _d = SSF_parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
}
if(cm) {
if(cm.name == 'XLDAPR') p.D = true;
if(cm.type == 'XLDAPR') p.D = true;
cm = void 0;
}
if(vm) vm = void 0;
@ -617,14 +620,14 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
if(!opts.sheetStubs || pass) break;
p = ({t:'z',v:void 0}/*:any*/);
C = val[0].c == -1 ? C + 1 : val[0].c;
if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
if(opts.dense) { if(!s["!data"][R]) s["!data"][R] = []; s["!data"][R][C] = p; }
else s[encode_col(C) + rr] = p;
if(refguess.s.r > row.r) refguess.s.r = row.r;
if(refguess.s.c > C) refguess.s.c = C;
if(refguess.e.r < row.r) refguess.e.r = row.r;
if(refguess.e.c < C) refguess.e.c = C;
if(cm) {
if(cm.name == 'XLDAPR') p.D = true;
if(cm.type == 'XLDAPR') p.D = true;
cm = void 0;
}
if(vm) vm = void 0;
@ -634,7 +637,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
merges.push(val); break;
case 0x0031: { /* 'BrtCellMeta' */
cm = ((opts.xlmeta||{}).Types||[])[val-1];
cm = ((opts.xlmeta||{}).Cell||[])[val-1];
} break;
case 0x01EE: /* 'BrtHLink' */
@ -648,11 +651,11 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
}
for(R=val.rfx.s.r;R<=val.rfx.e.r;++R) for(C=val.rfx.s.c;C<=val.rfx.e.c;++C) {
if(opts.dense) {
if(!s[R]) s[R] = [];
if(!s[R][C]) s[R][C] = {t:'z',v:undefined};
s[R][C].l = val;
if(!s["!data"][R]) s["!data"][R] = [];
if(!s["!data"][R][C]) s["!data"][R][C] = {t:'z',v:undefined};
s["!data"][R][C].l = val;
} else {
addr = encode_cell({c:C,r:R});
addr = encode_col(C) + encode_row(R);
if(!s[addr]) s[addr] = {t:'z',v:undefined};
s[addr].l = val;
}
@ -662,14 +665,14 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x01AA: /* 'BrtArrFmla' */
if(!opts.cellFormula) break;
arrayf.push(val);
cell = ((opts.dense ? s[R][C] : s[encode_col(C) + rr])/*:any*/);
cell = ((opts.dense ? s["!data"][R][C] : s[encode_col(C) + rr])/*:any*/);
cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
cell.F = encode_range(val[0]);
break;
case 0x01AB: /* 'BrtShrFmla' */
if(!opts.cellFormula) break;
sharedf[encode_cell(val[0].s)] = val[1];
cell = (opts.dense ? s[R][C] : s[encode_col(C) + rr]);
cell = (opts.dense ? s["!data"][R][C] : s[encode_col(C) + rr]);
cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
break;
@ -769,14 +772,13 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x0024: /* 'BrtFRTEnd' */
pass = false; break;
case 0x0025: /* 'BrtACBegin' */
state.push(R_n); pass = true; break;
state.push(RT); pass = true; break;
case 0x0026: /* 'BrtACEnd' */
state.pop(); pass = false; break;
default:
if((R_n||"").indexOf("Begin") > 0){/* empty */}
else if((R_n||"").indexOf("End") > 0){/* empty */}
else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
if(RR.T){/* empty */}
else if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
}
}, opts);
@ -804,66 +806,66 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
/* TODO: something useful -- this is a stub */
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/)/*:boolean*/ {
var o/*:any*/ = ({r:R, c:C}/*:any*/);
if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
if(cell.v === undefined) return false;
var vv = "";
switch(cell.t) {
case 'b': vv = cell.v ? "1" : "0"; break;
case 'd': // no BrtCellDate :(
cell = dup(cell);
cell.z = cell.z || SSF._table[14];
cell.z = cell.z || table_fmt[14];
cell.v = datenum(parseDate(cell.v)); cell.t = 'n';
break;
/* falls through */
case 'n': case 'e': vv = ''+cell.v; break;
default: vv = cell.v; break;
}
var o/*:any*/ = ({r:R, c:C}/*:any*/);
/* TODO: cell style */
o.s = get_cell_style(opts.cellXfs, cell, opts);
if(cell.l) ws['!links'].push([encode_cell(o), cell.l]);
if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
switch(cell.t) {
case 's': case 'str':
if(opts.bookSST) {
vv = get_sst_id(opts.Strings, (cell.v/*:any*/), opts.revStrings);
vv = get_sst_id(opts.Strings, (cell.v == null ? "" : String(cell.v)/*:any*/), opts.revStrings);
o.t = "s"; o.v = vv;
if(last_seen) write_record(ba, "BrtShortIsst", write_BrtShortIsst(cell, o));
else write_record(ba, "BrtCellIsst", write_BrtCellIsst(cell, o));
if(last_seen) write_record(ba, 0x0012 /* BrtShortIsst */, write_BrtShortIsst(cell, o));
else write_record(ba, 0x0007 /* BrtCellIsst */, write_BrtCellIsst(cell, o));
} else {
o.t = "str";
if(last_seen) write_record(ba, "BrtShortSt", write_BrtShortSt(cell, o));
else write_record(ba, "BrtCellSt", write_BrtCellSt(cell, o));
if(last_seen) write_record(ba, 0x0011 /* BrtShortSt */, write_BrtShortSt(cell, o));
else write_record(ba, 0x0006 /* BrtCellSt */, write_BrtCellSt(cell, o));
}
return true;
case 'n':
/* TODO: determine threshold for Real vs RK */
if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) {
if(last_seen) write_record(ba, "BrtShortRk", write_BrtShortRk(cell, o));
else write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o));
if(last_seen) write_record(ba, 0x000D /* BrtShortRk */, write_BrtShortRk(cell, o));
else write_record(ba, 0x0002 /* BrtCellRk */, write_BrtCellRk(cell, o));
} else {
if(last_seen) write_record(ba, "BrtShortReal", write_BrtShortReal(cell, o));
else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o));
if(last_seen) write_record(ba, 0x0010 /* BrtShortReal */, write_BrtShortReal(cell, o));
else write_record(ba, 0x0005 /* BrtCellReal */, write_BrtCellReal(cell, o));
} return true;
case 'b':
o.t = "b";
if(last_seen) write_record(ba, "BrtShortBool", write_BrtShortBool(cell, o));
else write_record(ba, "BrtCellBool", write_BrtCellBool(cell, o));
if(last_seen) write_record(ba, 0x000F /* BrtShortBool */, write_BrtShortBool(cell, o));
else write_record(ba, 0x0004 /* BrtCellBool */, write_BrtCellBool(cell, o));
return true;
case 'e':
o.t = "e";
if(last_seen) write_record(ba, "BrtShortError", write_BrtShortError(cell, o));
else write_record(ba, "BrtCellError", write_BrtCellError(cell, o));
if(last_seen) write_record(ba, 0x000E /* BrtShortError */, write_BrtShortError(cell, o));
else write_record(ba, 0x0003 /* BrtCellError */, write_BrtCellError(cell, o));
return true;
}
if(last_seen) write_record(ba, "BrtShortBlank", write_BrtShortBlank(cell, o));
else write_record(ba, "BrtCellBlank", write_BrtCellBlank(cell, o));
if(last_seen) write_record(ba, 0x000C /* BrtShortBlank */, write_BrtShortBlank(cell, o));
else write_record(ba, 0x0001 /* BrtCellBlank */, write_BrtCellBlank(cell, o));
return true;
}
function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols/*:Array<string>*/ = [];
write_record(ba, 'BrtBeginSheetData');
var dense = Array.isArray(ws);
write_record(ba, 0x0091 /* BrtBeginSheetData */);
var dense = ws["!data"] != null;
var cap = range.e.r;
if(ws['!rows']) cap = Math.max(range.e.r, ws['!rows'].length - 1);
for(var R = range.s.r; R <= cap; ++R) {
@ -876,34 +878,34 @@ function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Work
/* *16384CELL */
if(R === range.s.r) cols[C] = encode_col(C);
ref = cols[C] + rr;
var cell = dense ? (ws[R]||[])[C] : ws[ref];
var cell = dense ? (ws["!data"][R]||[])[C] : ws[ref];
if(!cell) { last_seen = false; continue; }
/* write cell */
last_seen = write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen);
}
}
write_record(ba, 'BrtEndSheetData');
write_record(ba, 0x0092 /* BrtEndSheetData */);
}
function write_MERGECELLS(ba, ws/*:Worksheet*/) {
if(!ws || !ws['!merges']) return;
write_record(ba, 'BrtBeginMergeCells', write_BrtBeginMergeCells(ws['!merges'].length));
ws['!merges'].forEach(function(m) { write_record(ba, 'BrtMergeCell', write_BrtMergeCell(m)); });
write_record(ba, 'BrtEndMergeCells');
write_record(ba, 0x00B1 /* BrtBeginMergeCells */, write_BrtBeginMergeCells(ws['!merges'].length));
ws['!merges'].forEach(function(m) { write_record(ba, 0x00B0 /* BrtMergeCell */, write_BrtMergeCell(m)); });
write_record(ba, 0x00B2 /* BrtEndMergeCells */);
}
function write_COLINFOS(ba, ws/*:Worksheet*//*::, idx:number, opts, wb:Workbook*/) {
if(!ws || !ws['!cols']) return;
write_record(ba, 'BrtBeginColInfos');
ws['!cols'].forEach(function(m, i) { if(m) write_record(ba, 'BrtColInfo', write_BrtColInfo(i, m)); });
write_record(ba, 'BrtEndColInfos');
write_record(ba, 0x0186 /* BrtBeginColInfos */);
ws['!cols'].forEach(function(m, i) { if(m) write_record(ba, 0x003C /* 'BrtColInfo' */, write_BrtColInfo(i, m)); });
write_record(ba, 0x0187 /* BrtEndColInfos */);
}
function write_IGNOREECS(ba, ws/*:Worksheet*/) {
if(!ws || !ws['!ref']) return;
write_record(ba, 'BrtBeginCellIgnoreECs');
write_record(ba, 'BrtCellIgnoreEC', write_BrtCellIgnoreEC(safe_decode_range(ws['!ref'])));
write_record(ba, 'BrtEndCellIgnoreECs');
write_record(ba, 0x0288 /* BrtBeginCellIgnoreECs */);
write_record(ba, 0x0289 /* BrtCellIgnoreEC */, write_BrtCellIgnoreEC(safe_decode_range(ws['!ref'])));
write_record(ba, 0x028A /* BrtEndCellIgnoreECs */);
}
function write_HLINKS(ba, ws/*:Worksheet*/, rels) {
@ -911,7 +913,7 @@ function write_HLINKS(ba, ws/*:Worksheet*/, rels) {
ws['!links'].forEach(function(l) {
if(!l[1].Target) return;
var rId = add_rels(rels, -1, l[1].Target.replace(/#.*$/, ""), RELS.HLINK);
write_record(ba, "BrtHLink", write_BrtHLink(l, rId));
write_record(ba, 0x01EE /* BrtHLink */, write_BrtHLink(l, rId));
});
delete ws['!links'];
}
@ -919,7 +921,7 @@ function write_LEGACYDRAWING(ba, ws/*:Worksheet*/, idx/*:number*/, rels) {
/* [BrtLegacyDrawing] */
if(ws['!comments'].length > 0) {
var rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML);
write_record(ba, "BrtLegacyDrawing", write_RelID("rId" + rId));
write_record(ba, 0x0227 /* BrtLegacyDrawing */, write_RelID("rId" + rId));
ws['!legacy'] = rId;
}
}
@ -939,41 +941,41 @@ function write_AUTOFILTER(ba, ws, wb, idx) {
var name = names[i];
if(name.Name != '_xlnm._FilterDatabase') continue;
if(name.Sheet != idx) continue;
name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break;
name.Ref = formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref); break;
}
if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref });
if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref) });
write_record(ba, "BrtBeginAFilter", write_UncheckedRfX(safe_decode_range(ref)));
write_record(ba, 0x00A1 /* BrtBeginAFilter */, write_UncheckedRfX(safe_decode_range(ref)));
/* *FILTERCOLUMN */
/* [SORTSTATE] */
/* BrtEndAFilter */
write_record(ba, "BrtEndAFilter");
write_record(ba, 0x00A2 /* BrtEndAFilter */);
}
function write_WSVIEWS2(ba, ws, Workbook) {
write_record(ba, "BrtBeginWsViews");
write_record(ba, 0x0085 /* BrtBeginWsViews */);
{ /* 1*WSVIEW2 */
/* [ACUID] */
write_record(ba, "BrtBeginWsView", write_BrtBeginWsView(ws, Workbook));
write_record(ba, 0x0089 /* BrtBeginWsView */, write_BrtBeginWsView(ws, Workbook));
/* [BrtPane] */
/* *4BrtSel */
/* *4SXSELECT */
/* *FRT */
write_record(ba, "BrtEndWsView");
write_record(ba, 0x008A /* BrtEndWsView */);
}
/* *FRT */
write_record(ba, "BrtEndWsViews");
write_record(ba, 0x0086 /* BrtEndWsViews */);
}
function write_WSFMTINFO(/*::ba, ws*/) {
/* [ACWSFMTINFO] */
//write_record(ba, "BrtWsFmtInfo", write_BrtWsFmtInfo(ws));
// write_record(ba, 0x01E5 /* BrtWsFmtInfo */, write_BrtWsFmtInfo(ws));
}
function write_SHEETPROTECT(ba, ws) {
if(!ws['!protect']) return;
/* [BrtSheetProtectionIso] */
write_record(ba, "BrtSheetProtection", write_BrtSheetProtection(ws['!protect']));
write_record(ba, 0x0217 /* BrtSheetProtection */, write_BrtSheetProtection(ws['!protect']));
}
function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
@ -989,9 +991,9 @@ function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
ws['!links'] = [];
/* passed back to write_zip and removed there */
ws['!comments'] = [];
write_record(ba, "BrtBeginSheet");
if(wb.vbaraw || ws['!outline']) write_record(ba, "BrtWsProp", write_BrtWsProp(c, ws['!outline']));
write_record(ba, "BrtWsDim", write_BrtWsDim(r));
write_record(ba, 0x0081 /* BrtBeginSheet */);
if(wb.vbaraw || ws['!outline']) write_record(ba, 0x0093 /* BrtWsProp */, write_BrtWsProp(c, ws['!outline']));
write_record(ba, 0x0094 /* BrtWsDim */, write_BrtWsDim(r));
write_WSVIEWS2(ba, ws, wb.Workbook);
write_WSFMTINFO(ba, ws);
write_COLINFOS(ba, ws, idx, opts, wb);
@ -1010,7 +1012,7 @@ function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
/* [DVALS] */
write_HLINKS(ba, ws, rels);
/* [BrtPrintOptions] */
if(ws['!margins']) write_record(ba, "BrtMargins", write_BrtMargins(ws['!margins']));
if(ws['!margins']) write_record(ba, 0x01DC /* BrtMargins */, write_BrtMargins(ws['!margins']));
/* [BrtPageSetup] */
/* [HEADERFOOTER] */
/* [RWBRK] */
@ -1028,6 +1030,6 @@ function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
/* [WEBPUBITEMS] */
/* [LISTPARTS] */
/* FRTWORKSHEET */
write_record(ba, "BrtEndSheet");
write_record(ba, 0x0082 /* BrtEndSheet */);
return ba.end();
}

@ -1,6 +1,3 @@
RELS.CHART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart";
RELS.CHARTEX = "http://schemas.microsoft.com/office/2014/relationships/chartEx";
function parse_Cache(data/*:string*/)/*:[Array<number|string>, string, ?string]*/ {
var col/*:Array<number|string>*/ = [];
var num = data.match(/^<c:numCache>/);
@ -37,7 +34,10 @@ function parse_chart(data/*:?string*/, name/*:string*/, opts, rels, wb, csheet)
refguess.e.c = C;
col = encode_col(C);
cache[0].forEach(function(n,i) {
cs[col + encode_row(i)] = {t:'n', v:n, z:cache[1] };
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;

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

@ -113,7 +113,7 @@ function safe1904(wb/*:Workbook*/)/*:string*/ {
return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false";
}
var badchars = "][*?\/\\".split("");
var badchars = /*#__PURE__*/":][*?\/\\".split("");
function check_ws_name(n/*:string*/, safe/*:?boolean*/)/*:boolean*/ {
if(n.length > 31) { if(safe) return false; throw new Error("Sheet names cannot exceed 31 chars"); }
var _good = true;
@ -140,5 +140,16 @@ function check_wb(wb) {
var Sheets = (wb.Workbook && wb.Workbook.Sheets) || [];
check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i);
wb.SheetNames.forEach(function(n, i) {
var ws = wb.Sheets[n];
if(!ws || !ws["!autofilter"]) return;
var DN;
if(!wb.Workbook) wb.Workbook = {};
if(!wb.Workbook.Names) wb.Workbook.Names = [];
wb.Workbook.Names.forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == i) DN = dn; });
var nn = formula_quote_sheet_name(n) + "!" + fix_range(ws["!autofilter"].ref);
if(DN) DN.Ref = nn;
else wb.Workbook.Names.push({Name: "_xlnm._FilterDatabase", Sheet: i, Ref: nn});
});
/* TODO: validate workbook */
}

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

@ -45,6 +45,7 @@ function write_BrtWbProp(data/*:?WBProps*/, o) {
var flags = 0;
if(data) {
/* TODO: mirror parse_BrtWbProp fields */
if(data.date1904) flags |= 0x01;
if(data.filterPrivacy) flags |= 0x08;
}
o.write_shift(4, flags);
@ -64,12 +65,13 @@ function parse_BrtFRTArchID$(data, length) {
/* [MS-XLSB] 2.4.687 BrtName */
function parse_BrtName(data, length, opts) {
var end = data.l + length;
data.l += 4; //var flags = data.read_shift(4);
var flags = data.read_shift(4);
data.l += 1; //var chKey = data.read_shift(1);
var itab = data.read_shift(4);
var name = parse_XLNameWideString(data);
var formula = parse_XLSBNameParsedFormula(data, 0, opts);
var comment = parse_XLNullableWideString(data);
if(flags & 0x20) name = "_xlnm." + name;
//if(0 /* fProc */) {
// unusedstring1: XLNullableWideString
// description: XLNullableWideString
@ -77,11 +79,40 @@ function parse_BrtName(data, length, opts) {
// unusedstring2: XLNullableWideString
//}
data.l = end;
var out = ({Name:name, Ptg:formula}/*:any*/);
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*/ {
@ -99,7 +130,7 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
XLSBRecordEnum[0x0010] = { n:"BrtFRTArchID$", f:parse_BrtFRTArchID$ };
recordhopper(data, function hopper_wb(val, R_n, RT) {
recordhopper(data, function hopper_wb(val, R, RT) {
switch(RT) {
case 0x009C: /* 'BrtBundleSh' */
supbooks.SheetNames.push(val.name);
@ -169,20 +200,19 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
break;
case 0x0023: /* 'BrtFRTBegin' */
state.push(R_n); pass = true; break;
state.push(RT); pass = true; break;
case 0x0024: /* 'BrtFRTEnd' */
state.pop(); pass = false; break;
case 0x0025: /* 'BrtACBegin' */
state.push(R_n); pass = true; break;
state.push(RT); pass = true; break;
case 0x0026: /* 'BrtACEnd' */
state.pop(); pass = false; break;
case 0x0010: /* 'BrtFRTArchID$' */ break;
default:
if((R_n||"").indexOf("Begin") > 0){/* empty */}
else if((R_n||"").indexOf("End") > 0){/* empty */}
else if(!pass || (opts.WTF && state[state.length-1] != "BrtACBegin" && state[state.length-1] != "BrtFRTBegin")) throw new Error("Unexpected record " + RT + " " + R_n);
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);
@ -196,13 +226,13 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
}
function write_BUNDLESHS(ba, wb/*::, opts*/) {
write_record(ba, "BrtBeginBundleShs");
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, "BrtBundleSh", write_BrtBundleSh(d));
write_record(ba, 0x009C /* BrtBundleSh */, write_BrtBundleSh(d));
}
write_record(ba, "BrtEndBundleShs");
write_record(ba, 0x0090 /* BrtEndBundleShs */);
}
/* [MS-XLSB] 2.4.649 BrtFileVersion */
@ -241,10 +271,38 @@ function write_BOOKVIEWS(ba, wb/*::, opts*/) {
else if(sheets[i].Hidden == 1 && hidden == -1) hidden = i;
}
if(hidden > vistab) return;
write_record(ba, "BrtBeginBookViews");
write_record(ba, "BrtBookView", write_BrtBookView(vistab));
write_record(ba, 0x0087 /* BrtBeginBookViews */);
write_record(ba, 0x009E /* BrtBookView */, write_BrtBookView(vistab));
/* 1*(BrtBookView *FRT) */
write_record(ba, "BrtEndBookViews");
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 */
@ -270,29 +328,29 @@ function write_BOOKVIEWS(ba, wb/*::, opts*/) {
/* [MS-XLSB] 2.1.7.61 Workbook */
function write_wb_bin(wb, opts) {
var ba = buf_array();
write_record(ba, "BrtBeginBook");
write_record(ba, "BrtFileVersion", write_BrtFileVersion());
write_record(ba, 0x0083 /* BrtBeginBook */);
write_record(ba, 0x0080 /* BrtFileVersion */, write_BrtFileVersion());
/* [[BrtFileSharingIso] BrtFileSharing] */
write_record(ba, "BrtWbProp", write_BrtWbProp(wb.Workbook && wb.Workbook.WBProps || null));
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] */
/* [EXTERNALS] */
/* *BrtName */
/* write_record(ba, "BrtCalcProp", write_BrtCalcProp()); */
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, "BrtFileRecover", write_BrtFileRecover()); */
/* write_record(ba, 0x009B BrtFileRecover, write_BrtFileRecover()); */
/* [WEBPUBITEMS] */
/* [CRERRS] */
/* FRTWORKBOOK */
write_record(ba, "BrtEndBook");
write_record(ba, 0x0084 /* BrtEndBook */);
return ba.end();
}

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

@ -37,10 +37,13 @@ function xlml_parsexmltagobj(tag/*:string*/) {
// ----
/* map from xlml named formats to SSF TODO: localize */
var XLMLFormatMap/*: {[string]:string}*/;
function xlml_format(format, value)/*:string*/ {
var fmt = XLMLFormatMap[format] || unescapexml(format);
if(fmt === "General") return SSF._general(value);
return SSF.format(fmt, value);
if(fmt === "General") return SSF_general(value);
return SSF_format(fmt, value);
}
function xlml_set_custprop(Custprops, key, cp, val/*:string*/) {
@ -62,18 +65,18 @@ function safe_format_xlml(cell/*:Cell*/, nf, o) {
if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
else if(nf === "General") {
if(cell.t === 'n') {
if((cell.v|0) === cell.v) cell.w = SSF._general_int(cell.v);
else cell.w = SSF._general_num(cell.v);
if((cell.v|0) === cell.v) cell.w = cell.v.toString(10);
else cell.w = SSF_general_num(cell.v);
}
else cell.w = SSF._general(cell.v);
else cell.w = SSF_general(cell.v);
}
else cell.w = xlml_format(nf||"General", cell.v);
} catch(e) { if(o.WTF) throw e; }
try {
var z = XLMLFormatMap[nf]||nf||"General";
if(o.cellNF) cell.z = z;
if(o.cellDates && cell.t == 'n' && SSF.is_date(z)) {
var _d = SSF.parse_date_code(cell.v); if(_d) { cell.t = 'd'; cell.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
if(o.cellDates && cell.t == 'n' && fmt_is_date(z)) {
var _d = SSF_parse_date_code(cell.v); if(_d) { cell.t = 'd'; cell.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
}
} catch(e) { if(o.WTF) throw e; }
}
@ -156,42 +159,56 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
if(cell.StyleID !== undefined) cell.ixfe = cell.StyleID;
}
function xlml_prefix_dname(dname) {
return XLSLblBuiltIn.indexOf("_xlnm." + dname) > -1 ? "_xlnm." + dname : dname;
}
function xlml_clean_comment(comment/*:any*/) {
comment.t = comment.v || "";
comment.t = comment.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n");
comment.v = comment.w = comment.ixfe = undefined;
}
function xlml_normalize(d)/*:string*/ {
if(has_buf &&/*::typeof Buffer !== "undefined" && d != null && d instanceof Buffer &&*/ Buffer.isBuffer(d)) return d.toString('utf8');
if(typeof d === 'string') return d;
/* duktape */
if(typeof Uint8Array !== 'undefined' && d instanceof Uint8Array) return utf8read(a2s(ab2a(d)));
throw new Error("Bad input format: expected Buffer or string");
}
/* TODO: Everything */
/* UOS uses CJK in tags */
var xlmlregex = /<(\/?)([^\s?><!\/:]*:|)([^\s?<>:\/]+)(?:[\s?:\/][^>]*)?>/mg;
//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
function parse_xlml_xml(d, _opts)/*:Workbook*/ {
var opts = _opts || {};
make_ssf(SSF);
make_ssf();
var str = debom(xlml_normalize(d));
if(opts.type == 'binary' || opts.type == 'array' || opts.type == 'base64') {
if(typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str));
if(typeof $cptable !== 'undefined') str = $cptable.utils.decode(65001, char_codes(str));
else str = utf8read(str);
}
var opening = str.slice(0, 1024).toLowerCase(), ishtml = false;
opening = opening.replace(/".*?"/g, "");
if((opening.indexOf(">") & 1023) > Math.min((opening.indexOf(",") & 1023), (opening.indexOf(";")&1023))) { var _o = dup(opts); _o.type = "string"; return PRN.to_workbook(str, _o); }
if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; });
if(ishtml) return HTML_.to_workbook(str, opts);
if(ishtml) return html_to_workbook(str, opts);
XLMLFormatMap = ({
"General Number": "General",
"General Date": table_fmt[22],
"Long Date": "dddd, mmmm dd, yyyy",
"Medium Date": table_fmt[15],
"Short Date": table_fmt[14],
"Long Time": table_fmt[19],
"Medium Time": table_fmt[18],
"Short Time": table_fmt[20],
"Currency": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
"Fixed": table_fmt[2],
"Standard": table_fmt[4],
"Percent": table_fmt[10],
"Scientific": table_fmt[11],
"Yes/No": '"Yes";"Yes";"No";@',
"True/False": '"True";"True";"False";@',
"On/Off": '"Yes";"Yes";"No";@'
}/*:any*/);
var Rn;
var state = [], tmp;
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
var sheets = {}, sheetnames/*:Array<string>*/ = [], cursheet/*:Worksheet*/ = (opts.dense ? [] : {}), sheetname = "";
var table = {}, cell = ({}/*:any*/), row = {};// eslint-disable-line no-unused-vars
var sheets = {}, sheetnames/*:Array<string>*/ = [], cursheet/*:Worksheet*/ = ({}), sheetname = ""; if(opts.dense) cursheet["!data"] = [];
var cell = ({}/*:any*/), row = {};// eslint-disable-line no-unused-vars
var dtag = xlml_parsexmltag('<Data ss:Type="String">'), didx = 0;
var c = 0, r = 0;
var refguess/*:Range*/ = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
@ -221,10 +238,10 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
case 'cell' /*case 'Cell'*/:
if(Rn[1]==='/'){
if(comments.length > 0) cell.c = comments;
if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== undefined) {
if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== void 0) {
if(opts.dense) {
if(!cursheet[r]) cursheet[r] = [];
cursheet[r][c] = cell;
if(!cursheet["!data"][r]) cursheet["!data"][r] = [];
cursheet["!data"][r][c] = cell;
} else cursheet[encode_col(c) + encode_row(r)] = cell;
}
if(cell.HRef) {
@ -235,7 +252,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
if(cell.MergeAcross || cell.MergeDown) {
cc = c + (parseInt(cell.MergeAcross,10)|0);
rr = r + (parseInt(cell.MergeDown,10)|0);
merges.push({s:{c:c,r:r},e:{c:cc,r:rr}});
if(cc > c || rr > r) merges.push({s:{c:c,r:r},e:{c:cc,r:rr}});
}
if(!opts.sheetStubs) { if(cell.MergeAcross) c = cc + 1; else ++c; }
else if(cell.MergeAcross || cell.MergeDown) {
@ -244,8 +261,8 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
for(var cmd = r; cmd <= rr; ++cmd) {
if(cma > c || cmd > r) {
if(opts.dense) {
if(!cursheet[cmd]) cursheet[cmd] = [];
cursheet[cmd][cma] = {t:'z'};
if(!cursheet["!data"][cmd]) cursheet["!data"][cmd] = [];
cursheet["!data"][cmd][cma] = {t:'z'};
} else cursheet[encode_col(cma) + encode_row(cmd)] = {t:'z'};
}
}
@ -304,7 +321,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
state.push([Rn[3], false]);
tmp = xlml_parsexmltag(Rn[0]);
sheetname = unescapexml(tmp.Name);
cursheet = (opts.dense ? [] : {});
cursheet = ({}); if(opts.dense) cursheet["!data"] = [];
merges = [];
arrayf = [];
rowinfo = [];
@ -316,7 +333,6 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
else if(Rn[0].slice(-2) == "/>") break;
else {
table = xlml_parsexmltag(Rn[0]);
state.push([Rn[3], false]);
cstys = []; seencol = false;
}
@ -330,12 +346,13 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
case 'numberformat' /*case 'NumberFormat'*/:
stag.nf = unescapexml(xlml_parsexmltag(Rn[0]).Format || "General");
if(XLMLFormatMap[stag.nf]) stag.nf = XLMLFormatMap[stag.nf];
for(var ssfidx = 0; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == stag.nf) break;
if(ssfidx == 0x188) for(ssfidx = 0x39; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == null) { SSF.load(stag.nf, ssfidx); break; }
for(var ssfidx = 0; ssfidx != 0x188; ++ssfidx) if(table_fmt[ssfidx] == stag.nf) break;
if(ssfidx == 0x188) for(ssfidx = 0x39; ssfidx != 0x188; ++ssfidx) if(table_fmt[ssfidx] == null) { SSF__load(stag.nf, ssfidx); break; }
break;
case 'column' /*case 'Column'*/:
if(state[state.length-1][0] !== /*'Table'*/'table') break;
if(Rn[1]==='/') break;
csty = xlml_parsexmltag(Rn[0]);
if(csty.Hidden) { csty.hidden = true; delete csty.Hidden; }
if(csty.Width) csty.wpx = parseInt(csty.Width, 10);
@ -353,7 +370,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
if(!Workbook.Names) Workbook.Names = [];
var _NamedRange = parsexmltag(Rn[0]);
var _DefinedName/*:DefinedName*/ = ({
Name: _NamedRange.Name,
Name: xlml_prefix_dname(_NamedRange.Name),
Ref: rc_to_a1(_NamedRange.RefersTo.slice(1), {r:0, c:0})
}/*:any*/);
if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1;
@ -899,16 +916,17 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
if(!opts.bookSheets && !opts.bookProps) out.Sheets = sheets;
out.SheetNames = sheetnames;
out.Workbook = Workbook;
out.SSF = SSF.get_table();
out.SSF = dup(table_fmt);
out.Props = Props;
out.Custprops = Custprops;
out.bookType = "xlml";
return out;
}
function parse_xlml(data/*:RawBytes|string*/, opts)/*:Workbook*/ {
fix_read_opts(opts=opts||{});
switch(opts.type||"base64") {
case "base64": return parse_xlml_xml(Base64.decode(data), opts);
case "base64": return parse_xlml_xml(Base64_decode(data), opts);
case "binary": case "buffer": case "file": return parse_xlml_xml(data, opts);
case "array": return parse_xlml_xml(a2s(data), opts);
}
@ -925,9 +943,10 @@ function write_props_xlml(wb/*:Workbook*/, opts)/*:string*/ {
return o.join("");
}
/* TODO */
function write_wb_xlml(/*::wb, opts*/)/*:string*/ {
function write_wb_xlml(wb/*::, opts*/)/*:string*/ {
/* OfficeDocumentSettings */
/* ExcelWorkbook */
if((((wb||{}).Workbook||{}).WBProps||{}).date1904) return '<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"><Date1904/></ExcelWorkbook>';
return "";
}
/* TODO */
@ -936,14 +955,14 @@ function write_sty_xlml(wb, opts)/*:string*/ {
var styles/*:Array<string>*/ = ['<Style ss:ID="Default" ss:Name="Normal"><NumberFormat/></Style>'];
opts.cellXfs.forEach(function(xf, id) {
var payload/*:Array<string>*/ = [];
payload.push(writextag('NumberFormat', null, {"ss:Format": escapexml(SSF._table[xf.numFmtId])}));
payload.push(writextag('NumberFormat', null, {"ss:Format": escapexml(table_fmt[xf.numFmtId])}));
var o = /*::(*/{"ss:ID": "s" + (21+id)}/*:: :any)*/;
styles.push(writextag('Style', payload.join(""), o));
});
return writextag("Styles", styles.join(""));
}
function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); }
function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name.slice(0,6) == "_xlnm." ? n.Name.slice(6) : n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); }
function write_names_xlml(wb/*::, opts*/)/*:string*/ {
if(!((wb||{}).Workbook||{}).Names) return "";
/*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */
@ -1120,7 +1139,7 @@ function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb,
case 'n': t = 'Number'; p = String(cell.v); break;
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
case 'e': t = 'Error'; p = BErr[cell.v]; break;
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break;
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || table_fmt[14]; break;
case 's': t = 'String'; p = escapexlml(cell.v||""); break;
}
/* TODO: cell style */
@ -1158,7 +1177,7 @@ function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbo
if(n.hidden) k['ss:Hidden']="1";
o.push(writextag("Column",null,k));
});
var dense = Array.isArray(ws);
var dense = ws["!data"] != null;
for(var R = range.s.r; R <= range.e.r; ++R) {
var row = [write_ws_xlml_row(R, (ws['!rows']||[])[R])];
for(var C = range.s.c; C <= range.e.c; ++C) {
@ -1173,7 +1192,7 @@ function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbo
}
if(skip) continue;
var addr = {r:R,c:C};
var ref = encode_cell(addr), cell = dense ? (ws[R]||[])[C] : ws[ref];
var ref = encode_col(C) + encode_row(R), cell = dense ? (ws["!data"][R]||[])[C] : ws[ref];
row.push(write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr));
}
row.push("</Row>");
@ -1196,13 +1215,15 @@ function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ {
/* WorksheetOptions */
o.push(write_ws_xlml_wsopts(ws, opts, idx, wb));
if(ws["!autofilter"]) o.push('<AutoFilter x:Range="' + a1_to_rc(fix_range(ws["!autofilter"].ref), {r:0,c:0}) + '" xmlns="urn:schemas-microsoft-com:office:excel"></AutoFilter>');
return o.join("");
}
function write_xlml(wb, opts)/*:string*/ {
if(!opts) opts = {};
if(!wb.SSF) wb.SSF = SSF.get_table();
if(!wb.SSF) wb.SSF = dup(table_fmt);
if(wb.SSF) {
make_ssf(SSF); SSF.load_table(wb.SSF);
make_ssf(); SSF_load_table(wb.SSF);
// $FlowIgnore
opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
opts.ssf = wb.SSF;

@ -28,45 +28,46 @@ function parse_compobj(obj/*:CFBEntry*/) {
/*
Continue logic for:
- 2.4.58 Continue
- 2.4.59 ContinueBigName
- 2.4.60 ContinueFrt
- 2.4.61 ContinueFrt11
- 2.4.62 ContinueFrt12
- 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
*/
function slurp(R, blob, length/*:number*/, opts)/*:any*/ {
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(R.n) {
case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': case 'EOF':
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 'BoundSheet8':
case 0x0085 /* BoundSheet8 */:
break;
default:
opts.enc.insitu(d);
}
bufs.push(d);
blob.l += l;
var next = (XLSRecordEnum[__readUInt16LE(blob,blob.l)]);
var nextrt = __readUInt16LE(blob,blob.l), next = XLSRecordEnum[nextrt];
var start = 0;
while(next != null && next.n.slice(0,8) === 'Continue') {
while(next != null && CONTINUE_RT.indexOf(nextrt) > -1) {
l = __readUInt16LE(blob,blob.l+2);
start = blob.l + 4;
if(next.n == 'ContinueFrt') start += 4;
else if(next.n.slice(0,11) == 'ContinueFrt') {
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[__readUInt16LE(blob, blob.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 " + (R && R.n || "??") + " Truncated: " + b.length + " < " + length;
if(b.length < length) throw "XLS Record 0x" + RecordType.toString(16) + " Truncated: " + b.length + " < " + length;
return R.f(b, b.length, opts);
}
@ -76,21 +77,21 @@ function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
var fmtid = 0;
try {
fmtid = p.z || p.XF.numFmtId || 0;
if(opts.cellNF) p.z = SSF._table[fmtid];
if(opts.cellNF) 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 = SSF._general_int(p.v);
else p.w = SSF._general_num(p.v);
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_general(p.v);
}
else p.w = SSF.format(fmtid,p.v, {date1904:!!date1904, dateNF: opts && opts.dateNF});
else p.w = SSF_format(fmtid,p.v, {date1904:!!date1904, dateNF: opts && opts.dateNF});
} catch(e) { if(opts.WTF) throw e; }
if(opts.cellDates && fmtid && p.t == 'n' && SSF.is_date(SSF._table[fmtid] || String(fmtid))) {
var _d = SSF.parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
if(opts.cellDates && fmtid && p.t == 'n' && fmt_is_date(table_fmt[fmtid] || String(fmtid))) {
var _d = SSF_parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
}
}
@ -103,7 +104,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
var wb = ({opts:{}}/*:any*/);
var Sheets = {};
if(DENSE != null && options.dense == null) options.dense = DENSE;
var out/*:Worksheet*/ = ((options.dense ? [] : {})/*:any*/);
var out/*:Worksheet*/ = ({}/*:any*/); if(options.dense) out["!data"] = [];
var Directory = {};
var range/*:Range*/ = ({}/*:any*/);
var last_formula = null;
@ -156,8 +157,8 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
}
{
if(options.dense) {
if(!out[cell.r]) out[cell.r] = [];
out[cell.r][cell.c] = line;
if(!out["!data"][cell.r]) out["!data"][cell.r] = [];
out["!data"][cell.r][cell.c] = line;
} else out[last_cell] = line;
}
};
@ -180,8 +181,6 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
var merges/*:Array<Range>*/ = [];
var objects = [];
var colinfo/*:Array<ColInfo>*/ = [], rowinfo/*:Array<RowInfo>*/ = [];
// eslint-disable-next-line no-unused-vars
var defwidth = 0, defheight = 0; // twips / MDW respectively
var seencol = false;
var supbooks = ([]/*:any*/); // 1-indexed, will hold extern names
supbooks.SheetNames = opts.snames;
@ -189,7 +188,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
supbooks.arrayf = opts.arrayf;
supbooks.names = [];
supbooks.XTI = [];
var last_Rn = '';
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 */
@ -202,16 +201,17 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
while(blob.l < blob.length - 1) {
var s = blob.l;
var RecordType = blob.read_shift(2);
if(RecordType === 0 && last_Rn === 'EOF') break;
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_Rn === 'BoundSheet8' && R.n !== 'BoundSheet8') break;
if(last_RT === 0x0085 /* BoundSheet8 */ && RecordType !== 0x0085 /* R.n !== 'BoundSheet8' */) break;
}
last_Rn = R.n;
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);
@ -221,28 +221,24 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
}
//console.error(R,blob.l,length,blob.length);
var val/*:any*/ = ({}/*:any*/);
if(R.n === 'EOF') val = /*::(*/R.f(blob, length, opts)/*:: :any)*/;
else val = /*::(*/slurp(R, blob, length, opts)/*:: :any)*/;
var Rn = R.n;
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 && Rn != 'BOF') continue;
/* nested switch statements to workaround V8 128 limit */
switch(Rn) {
/* Workbook Options */
case 'Date1904':
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 'WriteProtect': wb.opts.WriteProtect = true; break;
case 'FilePass':
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 'WriteAccess': opts.lastuser = val; break;
case 'FileSharing': break; //TODO
case 'CodePage':
case 0x005c /* WriteAccess */: opts.lastuser = val; break;
case 0x0042 /* CodePage */:
var cpval = Number(val);
/* overrides based on test cases */
switch(cpval) {
@ -253,44 +249,32 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
set_cp(opts.codepage = cpval);
seen_codepage = true;
break;
case 'RRTabId': opts.rrtabid = val; break;
case 'WinProtect': opts.winlocked = val; break;
case 'Template': break; // TODO
case 'BookBool': break; // TODO
case 'UsesELFs': break;
case 'MTRSettings': break;
case 'RefreshAll':
case 'CalcCount':
case 'CalcDelta':
case 'CalcIter':
case 'CalcMode':
case 'CalcPrecision':
case 'CalcSaveRecalc':
wb.opts[Rn] = val; break;
case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
case 'Uncalced': break;
case 'ForceFullCalculation': wb.opts.FullCalc = val; break;
case 'WsBool':
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 'XF':
case 0x00e0 /* XF */:
XFs.push(val); break;
case 'ExtSST': break; // TODO
case 'BookExt': break; // TODO
case 'RichTextStream': break;
case 'BkHim': break;
case 'SupBook':
case 0x01ae /* SupBook */:
supbooks.push([val]);
supbooks[supbooks.length-1].XTI = [];
break;
case 'ExternName':
case 0x0023: case 0x0223 /* ExternName */:
supbooks[supbooks.length-1].push(val);
break;
case 'Index': break; // TODO
case 'Lbl':
case 0x0018: case 0x0218 /* Lbl */:
last_lbl = ({
Name: val.Name,
Ref: stringify_formula(val.rgce,range,null,supbooks,opts)
@ -303,25 +287,22 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
if(val.rgce && val.rgce[0] && val.rgce[0][0] && val.rgce[0][0][0] == 'PtgArea3d')
FilterDatabases[val.itab - 1] = { ref: encode_range(val.rgce[0][0][1][2]) };
break;
case 'ExternCount': opts.ExternCount = val; break;
case 'ExternSheet':
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 'NameCmt':
case 0x0894 /* NameCmt */:
/* TODO: search for correct name */
if(opts.biff < 8) break;
if(last_lbl != null) last_lbl.Comment = val[1];
break;
case 'Protect': out["!protect"] = val; break; /* for sheet or book */
case 'Password': if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
case 'Prot4Rev': case 'Prot4RevPass': break; /*TODO: Revision Control*/
case 'BoundSheet8': {
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[val.pos] = val;
opts.snames.push(val.name);
} break;
case 'EOF': {
case 0x000a /* EOF */: {
if(--file_depth) break;
if(range.e) {
if(range.e.r > 0 && range.e.c > 0) {
@ -343,9 +324,9 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
Workbook.Sheets.push(wsprops);
}
if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out;
out = ((options.dense ? [] : {})/*:any*/);
out = ({}/*:any*/); if(options.dense) out["!data"] = [];
} break;
case 'BOF': {
case 0x0009: case 0x0209: case 0x0409: case 0x0809 /* BOF */: {
if(opts.biff === 8) opts.biff = {
/*::[*/0x0009/*::]*/:2,
/*::[*/0x0209/*::]*/:3,
@ -363,7 +344,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
if(val.BIFFVer == 0 && val.dt == 0x1000) { opts.biff = 5; seen_codepage = true; set_cp(opts.codepage = 28591); }
if(opts.biff == 8 && val.BIFFVer == 0 && val.dt == 16) opts.biff = 2;
if(file_depth++) break;
out = ((options.dense ? [] : {})/*:any*/);
out = ({}/*:any*/); if(options.dense) out["!data"] = [];
if(opts.biff < 8 && !seen_codepage) { seen_codepage = true; set_cp(opts.codepage = options.codepage || 1252); }
@ -382,31 +363,29 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
objects = [];
opts.arrayf = arrayf = [];
colinfo = []; rowinfo = [];
defwidth = defheight = 0;
seencol = false;
wsprops = {Hidden:(Directory[s]||{hs:0}).hs, name:cur_sheet };
} break;
case 'Number': case 'BIFF2NUM': case 'BIFF2INT': {
if(out["!type"] == "chart") if(options.dense ? (out[val.r]||[])[val.c]: out[encode_cell({c:val.c, r:val.r})]) ++val.c;
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 = 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 'BoolErr': {
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 = 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 'RK': {
case 0x027e /* RK */: {
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = 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 'MulRk': {
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*/);
@ -415,7 +394,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
addcell({c:j, r:val.r}, temp_val, options);
}
} break;
case 'Formula': {
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];
@ -425,7 +404,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
var _fe = encode_cell({r:_fr, c:_fc});
if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F;
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 = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
@ -433,7 +412,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
addcell(val.cell, temp_val, options);
last_formula = val;
} break;
case 'String': {
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');
@ -447,10 +426,10 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
last_formula = null;
} else throw new Error("String record expects Formula");
} break;
case 'Array': {
case 0x0021: case 0x0221 /* Array */: {
arrayf.push(val);
var _arraystart = encode_cell(val[0].s);
cc = options.dense ? (out[val[0].s.r]||[])[val[0].s.c] : out[_arraystart];
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;
@ -458,17 +437,17 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
cc.F = encode_range(val[0]);
}
} break;
case 'ShrFmla': {
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[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
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 'LabelSst':
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];
@ -476,13 +455,13 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
break;
case 'Blank': if(options.sheetStubs) {
case 0x0201 /* Blank */: if(options.sheetStubs) {
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = 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 'MulBlank': if(options.sheetStubs) {
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*/);
@ -491,8 +470,8 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
addcell({c:_j, r:val.r}, temp_val, options);
}
} break;
case 'RString':
case 'Label': case 'BIFF2STR':
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 = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
@ -500,56 +479,54 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
addcell({c:val.c, r:val.r}, temp_val, options);
break;
case 'Dimensions': {
case 0x0000: case 0x0200 /* Dimensions */: {
if(file_depth === 1) range = val; /* TODO: stack */
} break;
case 'SST': {
case 0x00fc /* SST */: {
sst = val;
} break;
case 'Format': { /* val = [id, fmt] */
case 0x041e /* Format */: { /* val = [id, fmt] */
if(opts.biff == 4) {
BIFF2FmtTable[BIFF2Fmt++] = val[1];
for(var b4idx = 0; b4idx < BIFF2Fmt + 163; ++b4idx) if(SSF._table[b4idx] == val[1]) break;
if(b4idx >= 163) SSF.load(val[1], BIFF2Fmt + 163);
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]);
else SSF__load(val[1], val[0]);
} break;
case 'BIFF2FORMAT': {
case 0x001e /* BIFF2FORMAT */: {
BIFF2FmtTable[BIFF2Fmt++] = val;
for(var b2idx = 0; b2idx < BIFF2Fmt + 163; ++b2idx) if(SSF._table[b2idx] == val) break;
if(b2idx >= 163) SSF.load(val, BIFF2Fmt + 163);
for(var b2idx = 0; b2idx < BIFF2Fmt + 163; ++b2idx) if(table_fmt[b2idx] == val) break;
if(b2idx >= 163) SSF__load(val, BIFF2Fmt + 163);
} break;
case 'MergeCells': merges = merges.concat(val); break;
case 0x00e5 /* MergeCells */: merges = merges.concat(val); break;
case 'Obj': objects[val.cmo[0]] = opts.lastobj = val; break;
case 'TxO': opts.lastobj.TxO = val; break;
case 'ImData': opts.lastobj.ImData = val; break;
case 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 'HLink': {
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[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
cc = options.dense ? (out["!data"][rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
if(cc) cc.l = val[1];
}
} break;
case 'HLinkTooltip': {
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[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
cc = options.dense ? (out["!data"][rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
if(cc && cc.l) cc.l.Tooltip = val[1];
}
} break;
/* Comments */
case 'Note': {
case 0x001c /* Note */: {
if(opts.biff <= 5 && opts.biff >= 2) break; /* TODO: BIFF5 */
cc = options.dense ? (out[val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
cc = options.dense ? (out["!data"][val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
var noteobj = objects[val[2]];
if(!cc) {
if(options.dense) {
if(!out[val[0].r]) out[val[0].r] = [];
cc = out[val[0].r][val[0].c] = ({t:"z"}/*:any*/);
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*/);
}
@ -562,15 +539,8 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
cmnt = {a:val[1],t:noteobj.TxO.t};
cc.c.push(cmnt);
} break;
default: switch(R.n) { /* nested */
case 'ClrtClient': break;
case 'XFExt': update_xfext(XFs[val.ixfe], val.ext); break;
case 'DefColWidth': defwidth = val; break;
case 'DefaultRowHeight': defheight = val[1]; break; // TODO: flags
case 'ColInfo': {
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) };
@ -578,7 +548,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
process_col(colinfo[val.e+1]);
}
} break;
case 'Row': {
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; }
@ -587,269 +557,35 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
rowobj.hpt = val.hpt; rowobj.hpx = pt2px(val.hpt);
}
} break;
case 'LeftMargin':
case 'RightMargin':
case 'TopMargin':
case 'BottomMargin':
case 0x0026 /* LeftMargin */:
case 0x0027 /* RightMargin */:
case 0x0028 /* TopMargin */:
case 0x0029 /* BottomMargin */:
if(!out['!margins']) default_margins(out['!margins'] = {});
out['!margins'][Rn.slice(0,-6).toLowerCase()] = val;
out['!margins'][({0x26: "left", 0x27:"right", 0x28:"top", 0x29:"bottom"})[RecordType]] = val;
break;
case 'Selection': break;
case 'Setup': // TODO
case 0x00a1 /* Setup */: // TODO
if(!out['!margins']) default_margins(out['!margins'] = {});
out['!margins'].header = val.header;
out['!margins'].footer = val.footer;
break;
case 'Window2': // TODO
case 0x023e /* Window2 */: // TODO
// $FlowIgnore
if(val.RTL) Workbook.Views[0].RTL = true;
break;
case 'Header': break; // TODO
case 'Footer': break; // TODO
case 'HCenter': break; // TODO
case 'VCenter': break; // TODO
case 'Pls': break; // TODO
case 'GCW': break;
case 'LHRecord': break;
case 'DBCell': break; // TODO
case 'EntExU2': break; // TODO
case 'SxView': break; // TODO
case 'Sxvd': break; // TODO
case 'SXVI': break; // TODO
case 'SXVDEx': break; // TODO
case 'SxIvd': break; // TODO
case 'SXString': break; // TODO
case 'Sync': break;
case 'Addin': break;
case 'SXDI': break; // TODO
case 'SXLI': break; // TODO
case 'SXEx': break; // TODO
case 'QsiSXTag': break; // TODO
case 'Feat': break;
case 'FeatHdr': case 'FeatHdr11': break;
case 'Feature11': case 'Feature12': case 'List12': break;
case 'Country': country = val; break;
case 'RecalcId': break;
case 'DxGCol': break; // TODO: htmlify
case 'Fbi': case 'Fbi2': case 'GelFrame': break;
case 'Font': break; // TODO
case 'XFCRC': break; // TODO
case 'Style': break; // TODO
case 'StyleExt': break; // TODO
case 'Palette': palette = val; break;
case 'Theme': themes = val; break;
/* Protection */
case 'ScenarioProtect': break;
case 'ObjProtect': break;
/* Conditional Formatting */
case 'CondFmt12': break;
/* Table */
case 'Table': break; // TODO
case 'TableStyles': break; // TODO
case 'TableStyle': break; // TODO
case 'TableStyleElement': break; // TODO
/* PivotTable */
case 'SXStreamID': break; // TODO
case 'SXVS': break; // TODO
case 'DConRef': break; // TODO
case 'SXAddl': break; // TODO
case 'DConBin': break; // TODO
case 'DConName': break; // TODO
case 'SXPI': break; // TODO
case 'SxFormat': break; // TODO
case 'SxSelect': break; // TODO
case 'SxRule': break; // TODO
case 'SxFilt': break; // TODO
case 'SxItm': break; // TODO
case 'SxDXF': break; // TODO
/* Scenario Manager */
case 'ScenMan': break;
/* Data Consolidation */
case 'DCon': break;
/* Watched Cell */
case 'CellWatch': break;
/* Print Settings */
case 'PrintRowCol': break;
case 'PrintGrid': break;
case 'PrintSize': break;
case 'XCT': break;
case 'CRN': break;
case 'Scl': {
//console.log("Zoom Level:", val[0]/val[1],val);
} break;
case 'SheetExt': {
/* empty */
} break;
case 'SheetExtOptional': {
/* empty */
} break;
/* VBA */
case 'ObNoMacros': {
/* empty */
} break;
case 'ObProj': {
/* empty */
} break;
case 'CodeName': {
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;
case 'GUIDTypeLib': {
/* empty */
} break;
case 'WOpt': break; // TODO: WTF?
case 'PhoneticInfo': break;
case 'OleObjectSize': break;
/* Differential Formatting */
case 'DXF': case 'DXFN': case 'DXFN12': case 'DXFN12List': case 'DXFN12NoCB': break;
/* Data Validation */
case 'Dv': case 'DVal': break;
/* Data Series */
case 'BRAI': case 'Series': case 'SeriesText': break;
/* Data Connection */
case 'DConn': break;
case 'DbOrParamQry': break;
case 'DBQueryExt': break;
case 'OleDbConn': break;
case 'ExtString': break;
/* Formatting */
case 'IFmtRecord': break;
case 'CondFmt': case 'CF': case 'CF12': case 'CFEx': break;
/* Explicitly Ignored */
case 'Excel9File': break;
case 'Units': break;
case 'InterfaceHdr': case 'Mms': case 'InterfaceEnd': case 'DSF': break;
case 'BuiltInFnGroupCount': /* 2.4.30 0x0E or 0x10 but excel 2011 generates 0x11? */ break;
/* View Stuff */
case 'Window1': case 'HideObj': case 'GridSet': case 'Guts':
case 'UserBView': case 'UserSViewBegin': case 'UserSViewEnd': break;
case 'Pane': break;
default: switch(R.n) { /* nested */
/* Chart */
case 'Dat':
case 'Begin': case 'End':
case 'StartBlock': case 'EndBlock':
case 'Frame': case 'Area':
case 'Axis': case 'AxisLine': case 'Tick': break;
case 'AxesUsed':
case 'CrtLayout12': case 'CrtLayout12A': case 'CrtLink': case 'CrtLine': case 'CrtMlFrt': case 'CrtMlFrtContinue': break;
case 'LineFormat': case 'AreaFormat':
case 'Chart': case 'Chart3d': case 'Chart3DBarShape': case 'ChartFormat': case 'ChartFrtInfo': break;
case 'PlotArea': case 'PlotGrowth': break;
case 'SeriesList': case 'SerParent': case 'SerAuxTrend': break;
case 'DataFormat': case 'SerToCrt': case 'FontX': break;
case 'CatSerRange': case 'AxcExt': case 'SerFmt': break;
case 'ShtProps': break;
case 'DefaultText': case 'Text': case 'CatLab': break;
case 'DataLabExtContents': break;
case 'Legend': case 'LegendException': break;
case 'Pie': case 'Scatter': break;
case 'PieFormat': case 'MarkerFormat': break;
case 'StartObject': case 'EndObject': break;
case 'AlRuns': case 'ObjectLink': break;
case 'SIIndex': break;
case 'AttachedLabel': case 'YMult': break;
/* Chart Group */
case 'Line': case 'Bar': break;
case 'Surf': break;
/* Axis Group */
case 'AxisParent': break;
case 'Pos': break;
case 'ValueRange': break;
/* Pivot Chart */
case 'SXViewEx9': break; // TODO
case 'SXViewLink': break;
case 'PivotChartBits': break;
case 'SBaseRef': break;
case 'TextPropsStream': break;
/* Chart Misc */
case 'LnExt': break;
case 'MkrExt': break;
case 'CrtCoopt': break;
/* Query Table */
case 'Qsi': case 'Qsif': case 'Qsir': case 'QsiSXTag': break;
case 'TxtQry': break;
/* Filter */
case 'FilterMode': break;
case 'AutoFilter': case 'AutoFilterInfo': break;
case 'AutoFilter12': break;
case 'DropDownObjIds': break;
case 'Sort': break;
case 'SortData': break;
/* Drawing */
case 'ShapePropsStream': break;
case 'MsoDrawing': case 'MsoDrawingGroup': case 'MsoDrawingSelection': break;
/* Pub Stuff */
case 'WebPub': case 'AutoWebPub': break;
/* Print Stuff */
case 'HeaderFooter': case 'HFPicture': case 'PLV':
case 'HorizontalPageBreaks': case 'VerticalPageBreaks': break;
/* Behavioral */
case 'Backup': case 'CompressPictures': case 'Compat12': break;
/* Should not Happen */
case 'Continue': case 'ContinueFrt12': break;
/* Future Records */
case 'FrtFontList': case 'FrtWrapper': break;
default: switch(R.n) { /* nested */
/* BIFF5 records */
case 'TabIdConf': case 'Radar': case 'RadarArea': case 'DropBar': case 'Intl': case 'CoordList': case 'SerAuxErrBar': break;
/* BIFF2-4 records */
case 'BIFF2FONTCLR': case 'BIFF2FMTCNT': case 'BIFF2FONTXTRA': break;
case 'BIFF2XF': case 'BIFF3XF': case 'BIFF4XF': break;
case 'BIFF2XFINDEX': break;
case 'BIFF4FMTCNT': case 'BIFF2ROW': case 'BIFF2WINDOW2': break;
/* Miscellaneous */
case 'SCENARIO': case 'DConBin': case 'PicF': case 'DataLabExt':
case 'Lel': case 'BopPop': case 'BopPopCustom': case 'RealTimeData':
case 'Name': break;
case 'LHNGraph': case 'FnGroupName': case 'AddMenu': case 'LPr': break;
case 'ListObj': case 'ListField': break;
case 'RRSort': break;
case 'BigName': break;
case 'ToolbarHdr': case 'ToolbarEnd': break;
case 'DDEObjName': break;
case 'FRTArchId$': break;
default: if(options.WTF) throw 'Unrecognized Record ' + R.n;
}}}}
} else blob.l += length;
}
} 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;
@ -861,7 +597,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
} else wb.Preamble=Preamble;
if(wb.Sheets) FilterDatabases.forEach(function(r,i) { wb.Sheets[wb.SheetNames[i]]['!autofilter'] = r; });
wb.Strings = sst;
wb.SSF = SSF.get_table();
wb.SSF = dup(table_fmt);
if(opts.enc) wb.Encryption = opts.enc;
if(themes) wb.Themes = themes;
wb.Metadata = {};
@ -900,6 +636,8 @@ function parse_xls_props(cfb/*:CFBContainer*/, props, o) {
function write_xls_props(wb/*:Workbook*/, cfb/*:CFBContainer*/) {
var DSEntries = [], SEntries = [], CEntries = [];
var i = 0, Keys;
var DocSummaryRE/*:{[key:string]:string}*/ = evert_key(DocSummaryPIDDSI, "n");
var SummaryRE/*:{[key:string]:string}*/ = evert_key(SummaryPIDSI, "n");
if(wb.Props) {
Keys = keys(wb.Props);
// $FlowIgnore
@ -912,7 +650,7 @@ function write_xls_props(wb/*:Workbook*/, cfb/*:CFBContainer*/) {
}
var CEntries2 = [];
for(i = 0; i < CEntries.length; ++i) {
if(XLSPSSkip.indexOf(CEntries[i][0]) > -1) continue;
if(XLSPSSkip.indexOf(CEntries[i][0]) > -1 || PseudoPropsPairs.indexOf(CEntries[i][0]) > -1) continue;
if(CEntries[i][1] == null) continue;
CEntries2.push(CEntries[i]);
}
@ -932,7 +670,7 @@ if(cfb.FullPaths) {
WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
} else {
switch(options.type) {
case 'base64': cfb = s2a(Base64.decode(cfb)); break;
case 'base64': cfb = s2a(Base64_decode(cfb)); break;
case 'binary': cfb = s2a(cfb); break;
case 'buffer': break;
case 'array': if(!Array.isArray(cfb)) cfb = Array.prototype.slice.call(cfb); break;

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
function write_biff_rec(ba/*:BufArray*/, type/*:number|string*/, payload, length/*:?number*/)/*:void*/ {
var t/*:number*/ = typeof type == "number" ? type : (+type || +XLSRE[/*::String(*/type/*::)*/]);
function write_biff_rec(ba/*:BufArray*/, type/*:number*/, payload, length/*:?number*/)/*:void*/ {
var t/*:number*/ = type;
if(isNaN(t)) return;
var len = length || (payload||[]).length || 0;
var o = ba.next(4);
@ -8,10 +8,10 @@ function write_biff_rec(ba/*:BufArray*/, type/*:number|string*/, payload, length
if(/*:: len != null &&*/len > 0 && is_buf(payload)) ba.push(payload);
}
function write_biff_continue(ba/*:BufArray*/, type/*:number|string*/, payload, length/*:?number*/)/*:void*/ {
function write_biff_continue(ba/*:BufArray*/, type/*:number*/, payload, length/*:?number*/)/*:void*/ {
var len = length || (payload||[]).length || 0;
if(len <= 8224) return write_biff_rec(ba, type, payload, len);
var t/*:number*/ = +type || +XLSRE[/*::String(*/type/*::)*/];
var t = type;
if(isNaN(t)) return;
var parts = payload.parts || [], sidx = 0;
var i = 0, w = 0;
@ -68,27 +68,27 @@ function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n
case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
/* TODO: codepage, sst */
case 's': case 'str':
write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, (cell.v||"").slice(0,255)));
write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v == null ? "" : String(cell.v).slice(0,255)));
return;
}
write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
}
function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
var dense = Array.isArray(ws);
var dense = ws["!data"] != null;
var range = safe_decode_range(ws['!ref'] || "A1"), ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
range.e.r = Math.min(range.e.c, 0x3FFF);
ref = encode_range(range);
}
var row = [];
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
for(var R = range.s.r; R <= range.e.r; ++R) {
if(dense) row = ws["!data"][R] || [];
rr = encode_row(R);
for(var C = range.s.c; C <= range.e.c; ++C) {
if(R === range.s.r) cols[C] = encode_col(C);
ref = cols[C] + rr;
var cell = dense ? (ws[R]||[])[C] : ws[ref];
for(C = range.s.c; C <= range.e.c; ++C) {
var cell = dense ? row[C] : ws[cols[C] + rr];
if(!cell) continue;
/* write cell */
write_ws_biff2_cell(ba, cell, R, C, opts);
@ -99,7 +99,6 @@ function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/
/* Based on test files */
function write_biff2_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
var o = opts || {};
if(DENSE != null && o.dense == null) o.dense = DENSE;
var ba = buf_array();
var idx = 0;
for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i;
@ -113,7 +112,7 @@ function write_biff2_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
}
function write_FONTS_biff8(ba, data, opts) {
write_biff_rec(ba, "Font", write_Font({
write_biff_rec(ba, 0x0031 /* Font */, write_Font({
sz:12,
color: {theme:1},
name: "Arial",
@ -127,7 +126,7 @@ function write_FMTS_biff8(ba, NF/*:?SSFTable*/, opts) {
if(!NF) return;
[[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
/*:: if(!NF) return; */
for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_biff_rec(ba, "Format", write_Format(i, NF[i], opts));
for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_biff_rec(ba, 0x041E /* Format */, write_Format(i, NF[i], opts));
});
}
@ -136,7 +135,7 @@ function write_FEAT(ba, ws) {
var o = new_buf(19);
o.write_shift(4, 0x867); o.write_shift(4, 0); o.write_shift(4, 0);
o.write_shift(2, 3); o.write_shift(1, 1); o.write_shift(4, 0);
write_biff_rec(ba, "FeatHdr", o);
write_biff_rec(ba, 0x0867 /* FeatHdr */, o);
/* [MS-XLS] 2.4.111 */
o = new_buf(39);
o.write_shift(4, 0x868); o.write_shift(4, 0); o.write_shift(4, 0);
@ -144,31 +143,31 @@ function write_FEAT(ba, ws) {
o.write_shift(2, 1); o.write_shift(4, 4); o.write_shift(2, 0);
write_Ref8U(safe_decode_range(ws['!ref']||"A1"), o);
o.write_shift(4, 4);
write_biff_rec(ba, "Feat", o);
write_biff_rec(ba, 0x0868 /* Feat */, o);
}
function write_CELLXFS_biff8(ba, opts) {
for(var i = 0; i < 16; ++i) write_biff_rec(ba, "XF", write_XF({numFmtId:0, style:true}, 0, opts));
for(var i = 0; i < 16; ++i) write_biff_rec(ba, 0x00e0 /* XF */, write_XF({numFmtId:0, style:true}, 0, opts));
opts.cellXfs.forEach(function(c) {
write_biff_rec(ba, "XF", write_XF(c, 0, opts));
write_biff_rec(ba, 0x00e0 /* XF */, write_XF(c, 0, opts));
});
}
function write_ws_biff8_hlinks(ba/*:BufArray*/, ws) {
for(var R=0; R<ws['!links'].length; ++R) {
var HL = ws['!links'][R];
write_biff_rec(ba, "HLink", write_HLink(HL));
if(HL[1].Tooltip) write_biff_rec(ba, "HLinkTooltip", write_HLinkTooltip(HL));
write_biff_rec(ba, 0x01b8 /* HLink */, write_HLink(HL));
if(HL[1].Tooltip) write_biff_rec(ba, 0x0800 /* HLinkTooltip */, write_HLinkTooltip(HL));
}
delete ws['!links'];
}
function write_ws_cols_biff8(ba, cols, ws) {
function write_ws_cols_biff8(ba, cols) {
if(!cols) return;
var cnt = 0;
cols.forEach(function(col, idx) {
if(++cnt <= 256 && col) {
write_biff_rec(ba, "ColInfo", write_ColInfo(col_obj_w(idx, col), idx));
write_biff_rec(ba, 0x007d /* ColInfo */, write_ColInfo(col_obj_w(idx, col), idx));
}
});
}
@ -176,28 +175,28 @@ function write_ws_cols_biff8(ba, cols, ws) {
function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) {
var os = 16 + get_cell_style(opts.cellXfs, cell, opts);
if(cell.v == null && !cell.bf) {
write_biff_rec(ba, "Blank", write_XLSCell(R, C, os));
write_biff_rec(ba, 0x0201 /* Blank */, write_XLSCell(R, C, os));
return;
}
if(cell.bf) write_biff_rec(ba, "Formula", write_Formula(cell, R, C, opts, os));
if(cell.bf) write_biff_rec(ba, 0x0006 /* Formula */, write_Formula(cell, R, C, opts, os));
else switch(cell.t) {
case 'd': case 'n':
var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
/* TODO: emit RK as appropriate */
write_biff_rec(ba, "Number", write_Number(R, C, v, os, opts));
write_biff_rec(ba, 0x0203 /* Number */, write_Number(R, C, v, os, opts));
break;
case 'b': case 'e':
write_biff_rec(ba, 0x0205, write_BoolErr(R, C, cell.v, os, opts, cell.t));
write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, cell.v, os, opts, cell.t));
break;
/* TODO: codepage, sst */
case 's': case 'str':
if(opts.bookSST) {
var isst = get_sst_id(opts.Strings, cell.v, opts.revStrings);
write_biff_rec(ba, "LabelSst", write_LabelSst(R, C, isst, os, opts));
} else write_biff_rec(ba, "Label", write_Label(R, C, (cell.v||"").slice(0,255), os, opts));
var isst = get_sst_id(opts.Strings, cell.v == null ? "" : String(cell.v), opts.revStrings);
write_biff_rec(ba, 0x00fd /* LabelSst */, write_LabelSst(R, C, isst, os, opts));
} else write_biff_rec(ba, 0x0204 /* Label */, write_Label(R, C, (cell.v == null ? "" : String(cell.v)).slice(0,255), os, opts));
break;
default:
write_biff_rec(ba, "Blank", write_XLSCell(R, C, os));
write_biff_rec(ba, 0x0201 /* Blank */, write_XLSCell(R, C, os));
}
}
@ -207,7 +206,7 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
var _WB/*:WBWBProps*/ = ((wb||{}).Workbook||{}/*:any*/);
var _sheet/*:WBWSProp*/ = ((_WB.Sheets||[])[idx]||{}/*:any*/);
var dense = Array.isArray(ws);
var dense = ws["!data"] != null;
var b8 = opts.biff == 8;
var ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
var range = safe_decode_range(ws['!ref'] || "A1");
@ -220,53 +219,59 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
write_biff_rec(ba, 0x0809, write_BOF(wb, 0x10, opts));
/* [Uncalced] Index */
write_biff_rec(ba, "CalcMode", writeuint16(1));
write_biff_rec(ba, "CalcCount", writeuint16(100));
write_biff_rec(ba, "CalcRefMode", writebool(true));
write_biff_rec(ba, "CalcIter", writebool(false));
write_biff_rec(ba, "CalcDelta", write_Xnum(0.001));
write_biff_rec(ba, "CalcSaveRecalc", writebool(true));
write_biff_rec(ba, "PrintRowCol", writebool(false));
write_biff_rec(ba, "PrintGrid", writebool(false));
write_biff_rec(ba, "GridSet", writeuint16(1));
write_biff_rec(ba, "Guts", write_Guts([0,0]));
write_biff_rec(ba, 0x000d /* CalcMode */, writeuint16(1));
write_biff_rec(ba, 0x000c /* CalcCount */, writeuint16(100));
write_biff_rec(ba, 0x000f /* CalcRefMode */, writebool(true));
write_biff_rec(ba, 0x0011 /* CalcIter */, writebool(false));
write_biff_rec(ba, 0x0010 /* CalcDelta */, write_Xnum(0.001));
write_biff_rec(ba, 0x005f /* CalcSaveRecalc */, writebool(true));
write_biff_rec(ba, 0x002a /* PrintRowCol */, writebool(false));
write_biff_rec(ba, 0x002b /* PrintGrid */, writebool(false));
write_biff_rec(ba, 0x0082 /* GridSet */, writeuint16(1));
write_biff_rec(ba, 0x0080 /* Guts */, write_Guts([0,0]));
/* DefaultRowHeight WsBool [Sync] [LPr] [HorizontalPageBreaks] [VerticalPageBreaks] */
/* Header (string) */
/* Footer (string) */
write_biff_rec(ba, "HCenter", writebool(false));
write_biff_rec(ba, "VCenter", writebool(false));
write_biff_rec(ba, 0x0083 /* HCenter */, writebool(false));
write_biff_rec(ba, 0x0084 /* VCenter */, writebool(false));
/* ... */
if(b8) write_ws_cols_biff8(ba, ws["!cols"], ws);
if(b8) write_ws_cols_biff8(ba, ws["!cols"]);
/* ... */
write_biff_rec(ba, 0x200, write_Dimensions(range, opts));
write_biff_rec(ba, 0x0200 /* Dimensions */, write_Dimensions(range, opts));
/* ... */
if(b8) ws['!links'] = [];
var comments = [];
var row = [];
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
for(var R = range.s.r; R <= range.e.r; ++R) {
if(dense) row = ws["!data"][R] || [];
rr = encode_row(R);
for(var C = range.s.c; C <= range.e.c; ++C) {
if(R === range.s.r) cols[C] = encode_col(C);
for(C = range.s.c; C <= range.e.c; ++C) {
ref = cols[C] + rr;
var cell = dense ? (ws[R]||[])[C] : ws[ref];
var cell = dense ? row[C] : ws[ref];
if(!cell) continue;
/* write cell */
write_ws_biff8_cell(ba, cell, R, C, opts);
if(b8 && cell.l) ws['!links'].push([ref, cell.l]);
if(b8 && cell.c) comments.push([ref, cell.c]);
}
}
var cname/*:string*/ = _sheet.CodeName || _sheet.name || s;
/* ... */
if(b8) write_biff_rec(ba, "Window2", write_Window2((_WB.Views||[])[0]));
// if(b8) comments.forEach(function(comment) { write_biff_rec(ba, 0x001c /* Note */, write_NoteSh(comment)); });
/* ... */
if(b8 && (ws['!merges']||[]).length) write_biff_rec(ba, "MergeCells", write_MergeCells(ws['!merges']));
if(b8) write_biff_rec(ba, 0x023e /* Window2 */, write_Window2((_WB.Views||[])[0]));
/* ... */
if(b8 && (ws['!merges']||[]).length) write_biff_rec(ba, 0x00e5 /* MergeCells */, write_MergeCells(ws['!merges']));
/* [LRng] *QUERYTABLE [PHONETICINFO] CONDFMTS */
if(b8) write_ws_biff8_hlinks(ba, ws);
/* [DVAL] */
write_biff_rec(ba, "CodeName", write_XLUnicodeString(cname, opts));
write_biff_rec(ba, 0x01ba /* CodeName */, write_XLUnicodeString(cname, opts));
/* *WebPub *CellWatch [SheetExt] */
if(b8) write_FEAT(ba, ws);
/* *FEAT11 *RECORD12 */
write_biff_rec(ba, "EOF");
write_biff_rec(ba, 0x000a /* EOF */);
return ba.end();
}
@ -278,59 +283,59 @@ function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) {
var _wb/*:WBProps*/ = /*::((*/_WB.WBProps||{/*::CodeName:"ThisWorkbook"*/}/*:: ):any)*/;
var b8 = opts.biff == 8, b5 = opts.biff == 5;
write_biff_rec(A, 0x0809, write_BOF(wb, 0x05, opts));
if(opts.bookType == "xla") write_biff_rec(A, "Addin");
write_biff_rec(A, "InterfaceHdr", b8 ? writeuint16(0x04b0) : null);
write_biff_rec(A, "Mms", writezeroes(2));
if(b5) write_biff_rec(A, "ToolbarHdr");
if(b5) write_biff_rec(A, "ToolbarEnd");
write_biff_rec(A, "InterfaceEnd");
write_biff_rec(A, "WriteAccess", write_WriteAccess("SheetJS", opts));
if(opts.bookType == "xla") write_biff_rec(A, 0x0087 /* Addin */);
write_biff_rec(A, 0x00e1 /* InterfaceHdr */, b8 ? writeuint16(0x04b0) : null);
write_biff_rec(A, 0x00c1 /* Mms */, writezeroes(2));
if(b5) write_biff_rec(A, 0x00bf /* ToolbarHdr */);
if(b5) write_biff_rec(A, 0x00c0 /* ToolbarEnd */);
write_biff_rec(A, 0x00e2 /* InterfaceEnd */);
write_biff_rec(A, 0x005c /* WriteAccess */, write_WriteAccess("SheetJS", opts));
/* [FileSharing] */
write_biff_rec(A, "CodePage", writeuint16(b8 ? 0x04b0 : 0x04E4));
write_biff_rec(A, 0x0042 /* CodePage */, writeuint16(b8 ? 0x04b0 : 0x04E4));
/* *2047 Lel */
if(b8) write_biff_rec(A, "DSF", writeuint16(0));
if(b8) write_biff_rec(A, "Excel9File");
write_biff_rec(A, "RRTabId", write_RRTabId(wb.SheetNames.length));
if(b8 && wb.vbaraw) write_biff_rec(A, "ObProj");
if(b8) write_biff_rec(A, 0x0161 /* DSF */, writeuint16(0));
if(b8) write_biff_rec(A, 0x01c0 /* Excel9File */);
write_biff_rec(A, 0x013d /* RRTabId */, write_RRTabId(wb.SheetNames.length));
if(b8 && wb.vbaraw) write_biff_rec(A, 0x00d3 /* ObProj */);
/* [ObNoMacros] */
if(b8 && wb.vbaraw) {
var cname/*:string*/ = _wb.CodeName || "ThisWorkbook";
write_biff_rec(A, "CodeName", write_XLUnicodeString(cname, opts));
write_biff_rec(A, 0x01ba /* CodeName */, write_XLUnicodeString(cname, opts));
}
write_biff_rec(A, "BuiltInFnGroupCount", writeuint16(0x11));
write_biff_rec(A, 0x009c /* BuiltInFnGroupCount */, writeuint16(0x11));
/* *FnGroupName *FnGrp12 */
/* *Lbl */
/* [OleObjectSize] */
write_biff_rec(A, "WinProtect", writebool(false));
write_biff_rec(A, "Protect", writebool(false));
write_biff_rec(A, "Password", writeuint16(0));
if(b8) write_biff_rec(A, "Prot4Rev", writebool(false));
if(b8) write_biff_rec(A, "Prot4RevPass", writeuint16(0));
write_biff_rec(A, "Window1", write_Window1(opts));
write_biff_rec(A, "Backup", writebool(false));
write_biff_rec(A, "HideObj", writeuint16(0));
write_biff_rec(A, "Date1904", writebool(safe1904(wb)=="true"));
write_biff_rec(A, "CalcPrecision", writebool(true));
if(b8) write_biff_rec(A, "RefreshAll", writebool(false));
write_biff_rec(A, "BookBool", writeuint16(0));
write_biff_rec(A, 0x0019 /* WinProtect */, writebool(false));
write_biff_rec(A, 0x0012 /* Protect */, writebool(false));
write_biff_rec(A, 0x0013 /* Password */, writeuint16(0));
if(b8) write_biff_rec(A, 0x01af /* Prot4Rev */, writebool(false));
if(b8) write_biff_rec(A, 0x01bc /* Prot4RevPass */, writeuint16(0));
write_biff_rec(A, 0x003d /* Window1 */, write_Window1(opts));
write_biff_rec(A, 0x0040 /* Backup */, writebool(false));
write_biff_rec(A, 0x008d /* HideObj */, writeuint16(0));
write_biff_rec(A, 0x0022 /* Date1904 */, writebool(safe1904(wb)=="true"));
write_biff_rec(A, 0x000e /* CalcPrecision */, writebool(true));
if(b8) write_biff_rec(A, 0x01b7 /* RefreshAll */, writebool(false));
write_biff_rec(A, 0x00DA /* BookBool */, writeuint16(0));
/* ... */
write_FONTS_biff8(A, wb, opts);
write_FMTS_biff8(A, wb.SSF, opts);
write_CELLXFS_biff8(A, opts);
/* ... */
if(b8) write_biff_rec(A, "UsesELFs", writebool(false));
if(b8) write_biff_rec(A, 0x0160 /* UsesELFs */, writebool(false));
var a = A.end();
var C = buf_array();
/* METADATA [MTRSettings] [ForceFullCalculation] */
if(b8) write_biff_rec(C, "Country", write_Country());
if(b8) write_biff_rec(C, 0x008C /* Country */, write_Country());
/* *SUPBOOK *LBL *RTD [RecalcId] *HFPicture *MSODRAWINGGROUP */
/* BIFF8: [SST *Continue] ExtSST */
if(b8 && opts.Strings) write_biff_continue(C, "SST", write_SST(opts.Strings, opts));
if(b8 && opts.Strings) write_biff_continue(C, 0x00FC /* SST */, write_SST(opts.Strings, opts));
/* *WebPub [WOpt] [CrErr] [BookExt] *FeatHdr *DConn [THEME] [CompressPictures] [Compat12] [GUIDTypeLib] */
write_biff_rec(C, "EOF");
write_biff_rec(C, 0x000A /* EOF */);
var c = C.end();
var B = buf_array();
@ -339,7 +344,7 @@ function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) {
var start = a.length + blen + c.length;
for(j = 0; j < wb.SheetNames.length; ++j) {
var _sheet/*:WBWSProp*/ = _sheets[j] || ({}/*:any*/);
write_biff_rec(B, "BoundSheet8", write_BoundSheet8({pos:start, hs:_sheet.Hidden||0, dt:0, name:wb.SheetNames[j]}, opts));
write_biff_rec(B, 0x0085 /* BoundSheet8 */, write_BoundSheet8({pos:start, hs:_sheet.Hidden||0, dt:0, name:wb.SheetNames[j]}, opts));
start += bufs[j].length;
}
/* 1*BoundSheet8 */
@ -359,10 +364,10 @@ function write_biff8_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
var bufs = [];
if(wb && !wb.SSF) {
wb.SSF = SSF.get_table();
wb.SSF = dup(table_fmt);
}
if(wb && wb.SSF) {
make_ssf(SSF); SSF.load_table(wb.SSF);
make_ssf(); SSF_load_table(wb.SSF);
// $FlowIgnore
o.revssf = evert_num(wb.SSF); o.revssf[wb.SSF[65535]] = 0;
o.ssf = wb.SSF;
@ -387,7 +392,7 @@ function write_biff_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
if(!ws || !ws["!ref"]) continue;
var range = decode_range(ws["!ref"]);
if(range.e.c > 255) { // note: 255 is IV
if(typeof console != "undefined" && console.error) console.error("Worksheet '" + wb.SheetNames[i] + "' extends beyond column IV (255). Data may be lost.");
if(typeof console != "undefined" && console.error) console.error("Worksheet '" + wb.SheetNames[i] + "' extends beyond column IV (255). Data may be lost.");
}
}

@ -1,136 +1,140 @@
/* note: browser DOM element cannot see mso- style attrs, must parse */
var HTML_ = (function() {
function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ {
var opts = _opts || {};
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
str = str.replace(/<!--.*?-->/g, "");
var mtch/*:any*/ = str.match(/<table/i);
if(!mtch) throw new Error("Invalid HTML: could not find <table>");
var mtch2/*:any*/ = str.match(/<\/table/i);
var i/*:number*/ = mtch.index, j/*:number*/ = mtch2 && mtch2.index || str.length;
var rows = split_regex(str.slice(i, j), /(:?<tr[^>]*>)/i, "<tr>");
var R = -1, C = 0, RS = 0, CS = 0;
var range/*:Range*/ = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
var merges/*:Array<Range>*/ = [];
for(i = 0; i < rows.length; ++i) {
var row = rows[i].trim();
var hd = row.slice(0,3).toLowerCase();
if(hd == "<tr") { ++R; if(opts.sheetRows && opts.sheetRows <= R) { --R; break; } C = 0; continue; }
if(hd != "<td" && hd != "<th") continue;
var cells = row.split(/<\/t[dh]>/i);
for(j = 0; j < cells.length; ++j) {
var cell = cells[j].trim();
if(!cell.match(/<t[dh]/i)) continue;
var m = cell, cc = 0;
/* TODO: parse styles etc */
while(m.charAt(0) == "<" && (cc = m.indexOf(">")) > -1) m = m.slice(cc+1);
for(var midx = 0; midx < merges.length; ++midx) {
var _merge/*:Range*/ = merges[midx];
if(_merge.s.c == C && _merge.s.r < R && R <= _merge.e.r) { C = _merge.e.c + 1; midx = -1; }
}
var tag = parsexmltag(cell.slice(0, cell.indexOf(">")));
CS = tag.colspan ? +tag.colspan : 1;
if((RS = +tag.rowspan)>1 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
var _t/*:string*/ = tag.t || tag["data-t"] || "";
/* TODO: generate stub cells */
if(!m.length) { C += CS; continue; }
m = htmldecode(m);
if(range.s.r > R) range.s.r = R; if(range.e.r < R) range.e.r = R;
if(range.s.c > C) range.s.c = C; if(range.e.c < C) range.e.c = C;
if(!m.length) continue;
var o/*:Cell*/ = {t:'s', v:m};
if(opts.raw || !m.trim().length || _t == 's'){}
else if(m === 'TRUE') o = {t:'b', v:true};
else if(m === 'FALSE') o = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)};
else if(!isNaN(fuzzydate(m).getDate())) {
o = ({t:'d', v:parseDate(m)}/*:any*/);
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
o.z = opts.dateNF || SSF._table[14];
}
if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; }
else ws[encode_cell({r:R, c:C})] = o;
C += CS;
function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ {
var opts = _opts || {};
var dense = (opts.dense != null) ? opts.dense : DENSE;
var ws/*:Worksheet*/ = ({}/*:any*/); if(dense) ws["!data"] = [];
str = str.replace(/<!--.*?-->/g, "");
var mtch/*:any*/ = str.match(/<table/i);
if(!mtch) throw new Error("Invalid HTML: could not find <table>");
var mtch2/*:any*/ = str.match(/<\/table/i);
var i/*:number*/ = mtch.index, j/*:number*/ = mtch2 && mtch2.index || str.length;
var rows = split_regex(str.slice(i, j), /(:?<tr[^>]*>)/i, "<tr>");
var R = -1, C = 0, RS = 0, CS = 0;
var range/*:Range*/ = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
var merges/*:Array<Range>*/ = [];
for(i = 0; i < rows.length; ++i) {
var row = rows[i].trim();
var hd = row.slice(0,3).toLowerCase();
if(hd == "<tr") { ++R; if(opts.sheetRows && opts.sheetRows <= R) { --R; break; } C = 0; continue; }
if(hd != "<td" && hd != "<th") continue;
var cells = row.split(/<\/t[dh]>/i);
for(j = 0; j < cells.length; ++j) {
var cell = cells[j].trim();
if(!cell.match(/<t[dh]/i)) continue;
var m = cell, cc = 0;
/* TODO: parse styles etc */
while(m.charAt(0) == "<" && (cc = m.indexOf(">")) > -1) m = m.slice(cc+1);
for(var midx = 0; midx < merges.length; ++midx) {
var _merge/*:Range*/ = merges[midx];
if(_merge.s.c == C && _merge.s.r < R && R <= _merge.e.r) { C = _merge.e.c + 1; midx = -1; }
}
var tag = parsexmltag(cell.slice(0, cell.indexOf(">")));
CS = tag.colspan ? +tag.colspan : 1;
if((RS = +tag.rowspan)>1 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
var _t/*:string*/ = tag.t || tag["data-t"] || "";
/* TODO: generate stub cells */
if(!m.length) { C += CS; continue; }
m = htmldecode(m);
if(range.s.r > R) range.s.r = R; if(range.e.r < R) range.e.r = R;
if(range.s.c > C) range.s.c = C; if(range.e.c < C) range.e.c = C;
if(!m.length) { C += CS; continue; }
var o/*:Cell*/ = {t:'s', v:m};
if(opts.raw || !m.trim().length || _t == 's'){}
else if(m === 'TRUE') o = {t:'b', v:true};
else if(m === 'FALSE') o = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)};
else if(!isNaN(fuzzydate(m).getDate())) {
o = ({t:'d', v:parseDate(m)}/*:any*/);
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
o.z = opts.dateNF || table_fmt[14];
}
if(dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = o; }
else ws[encode_cell({r:R, c:C})] = o;
C += CS;
}
ws['!ref'] = encode_range(range);
if(merges.length) ws["!merges"] = merges;
return ws;
}
function html_to_book(str/*:string*/, opts)/*:Workbook*/ {
var mtch = str.match(/<table.*?>[\s\S]*?<\/table>/gi);
if(!mtch || mtch.length == 0) throw new Error("Invalid HTML: could not find <table>");
if(mtch.length == 1) return sheet_to_workbook(html_to_sheet(mtch[0], opts), opts);
var wb = utils.book_new();
mtch.forEach(function(s, idx) { utils.book_append_sheet(wb, html_to_sheet(s, opts), "Sheet" + (idx+1)); });
return wb;
}
function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
var M/*:Array<Range>*/ = (ws['!merges'] ||[]);
var oo/*:Array<string>*/ = [];
for(var C = r.s.c; C <= r.e.c; ++C) {
var RS = 0, CS = 0;
for(var j = 0; j < M.length; ++j) {
if(M[j].s.r > R || M[j].s.c > C) continue;
if(M[j].e.r < R || M[j].e.c < C) continue;
if(M[j].s.r < R || M[j].s.c < C) { RS = -1; break; }
RS = M[j].e.r - M[j].s.r + 1; CS = M[j].e.c - M[j].s.c + 1; break;
}
if(RS < 0) continue;
var coord = encode_cell({r:R,c:C});
var cell = o.dense ? (ws[R]||[])[C] : ws[coord];
/* TODO: html entities */
var w = (cell && cell.v != null) && (cell.h || escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || "";
var sp = ({}/*:any*/);
if(RS > 1) sp.rowspan = RS;
if(CS > 1) sp.colspan = CS;
if(o.editable) w = '<span contenteditable="true">' + w + '</span>';
else if(cell) {
sp["data-t"] = cell && cell.t || 'z';
if(cell.v != null) sp["data-v"] = cell.v;
if(cell.z != null) sp["data-z"] = cell.z;
if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + cell.l.Target +'">' + w + '</a>';
}
sp.id = (o.id || "sjs") + "-" + coord;
oo.push(writextag('td', w, sp));
ws['!ref'] = encode_range(range);
if(merges.length) ws["!merges"] = merges;
return ws;
}
function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
var M/*:Array<Range>*/ = (ws['!merges'] ||[]);
var oo/*:Array<string>*/ = [];
var sp = ({}/*:any*/);
var dense = ws["!data"] != null;
for(var C = r.s.c; C <= r.e.c; ++C) {
var RS = 0, CS = 0;
for(var j = 0; j < M.length; ++j) {
if(M[j].s.r > R || M[j].s.c > C) continue;
if(M[j].e.r < R || M[j].e.c < C) continue;
if(M[j].s.r < R || M[j].s.c < C) { RS = -1; break; }
RS = M[j].e.r - M[j].s.r + 1; CS = M[j].e.c - M[j].s.c + 1; break;
}
var preamble = "<tr>";
return preamble + oo.join("") + "</tr>";
if(RS < 0) continue;
var coord = encode_col(C) + encode_row(R);
var cell = dense ? (ws["!data"][R]||[])[C] : ws[coord];
/* TODO: html entities */
var w = (cell && cell.v != null) && (cell.h || escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || "";
sp = ({}/*:any*/);
if(RS > 1) sp.rowspan = RS;
if(CS > 1) sp.colspan = CS;
if(o.editable) w = '<span contenteditable="true">' + w + '</span>';
else if(cell) {
sp["data-t"] = cell && cell.t || 'z';
if(cell.v != null) sp["data-v"] = cell.v;
if(cell.z != null) sp["data-z"] = cell.z;
if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + cell.l.Target +'">' + w + '</a>';
}
sp.id = (o.id || "sjs") + "-" + coord;
oo.push(writextag('td', w, sp));
}
function make_html_preamble(ws/*:Worksheet*/, R/*:Range*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
var out/*:Array<string>*/ = [];
return out.join("") + '<table' + (o && o.id ? ' id="' + o.id + '"' : "") + '>';
}
var _BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
var _END = '</body></html>';
function sheet_to_html(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*//*, wb:?Workbook*/)/*:string*/ {
var o = opts || {};
var header = o.header != null ? o.header : _BEGIN;
var footer = o.footer != null ? o.footer : _END;
var out/*:Array<string>*/ = [header];
var r = decode_range(ws['!ref']);
o.dense = Array.isArray(ws);
out.push(make_html_preamble(ws, r, o));
for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
out.push("</table>" + footer);
return out.join("");
var preamble = "<tr>";
return preamble + oo.join("") + "</tr>";
}
var HTML_BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
var HTML_END = '</body></html>';
function html_to_workbook(str/*:string*/, opts)/*:Workbook*/ {
var mtch = str.match(/<table[\s\S]*?>[\s\S]*?<\/table>/gi);
if(!mtch || mtch.length == 0) throw new Error("Invalid HTML: could not find <table>");
if(mtch.length == 1) {
var w = sheet_to_workbook(html_to_sheet(mtch[0], opts), opts);
w.bookType = "html";
return w;
}
return {
to_workbook: html_to_book,
to_sheet: html_to_sheet,
_row: make_html_row,
BEGIN: _BEGIN,
END: _END,
_preamble: make_html_preamble,
from_sheet: sheet_to_html
};
})();
var wb = book_new();
mtch.forEach(function(s, idx) { book_append_sheet(wb, html_to_sheet(s, opts), "Sheet" + (idx+1)); });
wb.bookType = "html";
return wb;
}
function make_html_preamble(ws/*:Worksheet*/, R/*:Range*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
var out/*:Array<string>*/ = [];
return out.join("") + '<table' + (o && o.id ? ' id="' + o.id + '"' : "") + '>';
}
function sheet_to_html(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*//*, wb:?Workbook*/)/*:string*/ {
var o = opts || {};
var header = o.header != null ? o.header : HTML_BEGIN;
var footer = o.footer != null ? o.footer : HTML_END;
var out/*:Array<string>*/ = [header];
var r = decode_range(ws['!ref']);
out.push(make_html_preamble(ws, r, o));
for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
out.push("</table>" + footer);
return out.join("");
}
function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
var rows/*:HTMLCollection<HTMLTableRowElement>*/ = table.rows;
if(!rows) {
/* not an HTML TABLE */
throw "Unsupported origin when " + table.tagName + " is not a TABLE";
}
var opts = _opts || {};
if(DENSE != null) opts.dense = DENSE;
var dense = ws["!data"] != null;
var or_R = 0, or_C = 0;
if(opts.origin != null) {
if(typeof opts.origin == 'number') or_R = opts.origin;
@ -140,7 +144,6 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
}
}
var rows/*:HTMLCollection<HTMLTableRowElement>*/ = table.getElementsByTagName('tr');
var sheetRows = Math.min(opts.sheetRows||10000000, rows.length);
var range/*:Range*/ = {s:{r:0,c:0},e:{r:or_R,c:or_C}};
if(ws["!ref"]) {
@ -161,7 +164,7 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
if (opts.display) continue;
rowinfo[R] = {hidden: true};
}
var elts/*:HTMLCollection<HTMLTableCellElement>*/ = (row.children/*:any*/);
var elts/*:HTMLCollection<HTMLTableCellElement>*/ = (row.cells);
for(_C = C = 0; _C < elts.length; ++_C) {
var elt/*:HTMLTableCellElement*/ = elts[_C];
if (opts.display && is_dom_element_hidden(elt)) continue;
@ -185,7 +188,7 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
else if(!isNaN(fuzzydate(v).getDate())) {
o = ({t:'d', v:parseDate(v)}/*:any*/);
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
o.z = opts.dateNF || SSF._table[14];
o.z = opts.dateNF || table_fmt[14];
}
}
if(o.z === undefined && z != null) o.z = z;
@ -195,8 +198,8 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
if(Aelts && Aelts.length) for(var Aelti = 0; Aelti < Aelts.length; ++Aelti) if(Aelts[Aelti].hasAttribute("href")) {
l = Aelts[Aelti].getAttribute("href"); if(l.charAt(0) != "#") break;
}
if(l && l.charAt(0) != "#") o.l = ({ Target: l });
if(opts.dense) { if(!ws[R + or_R]) ws[R + or_R] = []; ws[R + or_R][C + or_C] = o; }
if(l && l.charAt(0) != "#" && l.slice(0, 11).toLowerCase() != 'javascript:') o.l = ({ Target: l });
if(dense) { if(!ws["!data"][R + or_R]) ws["!data"][R + or_R] = []; ws["!data"][R + or_R][C + or_C] = o; }
else ws[encode_cell({c:C + or_C, r:R + or_R})] = o;
if(range.e.c < C + or_C) range.e.c = C + or_C;
C += CS;
@ -212,12 +215,14 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
var opts = _opts || {};
var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
var ws/*:Worksheet*/ = ({}/*:any*/); if(opts.dense) ws["!data"] = [];
return sheet_add_dom(ws, table, _opts);
}
function table_to_book(table/*:HTMLElement*/, opts/*:?any*/)/*:Workbook*/ {
return sheet_to_workbook(parse_dom_table(table, opts), opts);
var o = sheet_to_workbook(parse_dom_table(table, opts), opts);
//o.bookType = "dom"; // TODO: define a type for this
return o;
}
function is_dom_element_hidden(element/*:HTMLElement*/)/*:boolean*/ {

@ -1,62 +1,269 @@
/* OpenDocument */
var parse_content_xml = (function() {
function parse_text_p(text/*:string*//*::, tag*/)/*:Array<any>*/ {
/* 6.1.2 White Space Characters */
var fixed = text
.replace(/[\t\r\n]/g, " ").trim().replace(/ +/g, " ")
.replace(/<text:s\/>/g," ")
.replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); })
.replace(/<text:tab[^>]*\/>/g,"\t")
.replace(/<text:line-break\/>/g,"\n");
var v = unescapexml(fixed.replace(/<[^>]*>/g,""));
var parse_text_p = function(text/*:string*//*::, tag*/)/*:Array<any>*/ {
/* 6.1.2 White Space Characters */
var fixed = text
.replace(/[\t\r\n]/g, " ").trim().replace(/ +/g, " ")
.replace(/<text:s\/>/g," ")
.replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); })
.replace(/<text:tab[^>]*\/>/g,"\t")
.replace(/<text:line-break\/>/g,"\n");
var v = unescapexml(fixed.replace(/<[^>]*>/g,""));
return [v];
}
return [v];
};
/* Note: ODS can stick styles in content.xml or styles.xml, FODS blurs lines */
function parse_ods_styles(d/*:string*/, _opts, _nfm) {
var number_format_map = _nfm || {};
var str = xlml_normalize(d);
xlmlregex.lastIndex = 0;
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
var Rn, NFtag, NF = "", tNF = "", y, etpos = 0, tidx = -1, infmt = false, payload = "";
while((Rn = xlmlregex.exec(str))) {
switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
/* Number Format Definitions */
case 'number-style': // <number:number-style> 16.29.2
case 'currency-style': // <number:currency-style> 16.29.8
case 'percentage-style': // <number:percentage-style> 16.29.10
case 'date-style': // <number:date-style> 16.29.11
case 'time-style': // <number:time-style> 16.29.19
case 'text-style': // <number:text-style> 16.29.26
if(Rn[1]==='/') {
infmt = false;
if(NFtag['truncate-on-overflow'] == "false") {
if(NF.match(/h/)) NF = NF.replace(/h+/, "[$&]");
else if(NF.match(/m/)) NF = NF.replace(/m+/, "[$&]");
else if(NF.match(/s/)) NF = NF.replace(/s+/, "[$&]");
}
number_format_map[NFtag.name] = NF;
NF = "";
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
infmt = true;
NF = "";
NFtag = parsexmltag(Rn[0], false);
} break;
var number_formats = {
/* ods name: [short ssf fmt, long ssf fmt] */
day: ["d", "dd"],
month: ["m", "mm"],
year: ["y", "yy"],
hours: ["h", "hh"],
minutes: ["m", "mm"],
seconds: ["s", "ss"],
"am-pm": ["A/P", "AM/PM"],
"day-of-week": ["ddd", "dddd"],
era: ["e", "ee"],
/* there is no native representation of LO "Q" format */
quarter: ["\\Qm", "m\\\"th quarter\""]
};
// LibreOffice bug https://bugs.documentfoundation.org/show_bug.cgi?id=149484
case 'boolean-style': // <number:boolean-style> 16.29.24
if(Rn[1]==='/') {
infmt = false;
number_format_map[NFtag.name] = "General";
NF = "";
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
infmt = true;
NF = "";
NFtag = parsexmltag(Rn[0], false);
} break;
return function pcx(d/*:string*/, _opts)/*:Workbook*/ {
/* Number Format Elements */
case 'boolean': // <number:boolean> 16.29.25
NF += "General"; // ODF spec is unfortunately underspecified here
break;
case 'text': // <number:text> 16.29.27
if(Rn[1]==='/') {
payload = str.slice(tidx, xlmlregex.lastIndex - Rn[0].length);
// NOTE: Excel has a different interpretation of "%%" and friends
if(payload == "%" && NFtag[0] == '<number:percentage-style') NF += "%";
else NF += '"' + payload.replace(/"/g, '""') + '"';
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
tidx = xlmlregex.lastIndex;
} break;
case 'day': { // <number:day> 16.29.12
y = parsexmltag(Rn[0], false);
switch(y["style"]) {
case "short": NF += "d"; break;
case "long": NF += "dd"; break;
default: NF += "dd"; break; // TODO: error condition
}
} break;
case 'day-of-week': { // <number:day-of-week> 16.29.16
y = parsexmltag(Rn[0], false);
switch(y["style"]) {
case "short": NF += "ddd"; break;
case "long": NF += "dddd"; break;
default: NF += "ddd"; break;
}
} break;
case 'era': { // <number:era> 16.29.15 TODO: proper mapping
y = parsexmltag(Rn[0], false);
switch(y["style"]) {
case "short": NF += "ee"; break;
case "long": NF += "eeee"; break;
default: NF += "eeee"; break; // TODO: error condition
}
} break;
case 'hours': { // <number:hours> 16.29.20
y = parsexmltag(Rn[0], false);
switch(y["style"]) {
case "short": NF += "h"; break;
case "long": NF += "hh"; break;
default: NF += "hh"; break; // TODO: error condition
}
} break;
case 'minutes': { // <number:minutes> 16.29.21
y = parsexmltag(Rn[0], false);
switch(y["style"]) {
case "short": NF += "m"; break;
case "long": NF += "mm"; break;
default: NF += "mm"; break; // TODO: error condition
}
} break;
case 'month': { // <number:month> 16.29.13
y = parsexmltag(Rn[0], false);
if(y["textual"]) NF += "mm";
switch(y["style"]) {
case "short": NF += "m"; break;
case "long": NF += "mm"; break;
default: NF += "m"; break;
}
} break;
case 'seconds': { // <number:seconds> 16.29.22
y = parsexmltag(Rn[0], false);
switch(y["style"]) {
case "short": NF += "s"; break;
case "long": NF += "ss"; break;
default: NF += "ss"; break; // TODO: error condition
}
if(y["decimal-places"]) NF += "." + fill("0", +y["decimal-places"]);
} break;
case 'year': { // <number:year> 16.29.14
y = parsexmltag(Rn[0], false);
switch(y["style"]) {
case "short": NF += "yy"; break;
case "long": NF += "yyyy"; break;
default: NF += "yy"; break; // TODO: error condition
}
} break;
case 'am-pm': // <number:am-pm> 16.29.23
NF += "AM/PM"; // LO autocorrects A/P -> AM/PM
break;
case 'week-of-year': // <number:week-of-year> 16.29.17
case 'quarter': // <number:quarter> 16.29.18
console.error("Excel does not support ODS format token " + Rn[3]);
break;
case 'fill-character': // <number:fill-character> 16.29.5
if(Rn[1]==='/') {
payload = str.slice(tidx, xlmlregex.lastIndex - Rn[0].length);
// NOTE: Excel has a different interpretation of "%%" and friends
NF += '"' + payload.replace(/"/g, '""') + '"*';
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
tidx = xlmlregex.lastIndex;
} break;
case 'scientific-number': // <number:scientific-number> 16.29.6
// TODO: find a mapping for all parameters
y = parsexmltag(Rn[0], false);
NF += "0." + fill("0", +y["min-decimal-places"] || +y["decimal-places"] || 2) + fill("?", +y["decimal-places"] - +y["min-decimal-places"] || 0) + "E" + (parsexmlbool(y["forced-exponent-sign"]) ? "+" : "") + fill("0", +y["min-exponent-digits"] || 2);
break;
case 'fraction': // <number:fraction> 16.29.7
// TODO: find a mapping for all parameters
y = parsexmltag(Rn[0], false);
if(!+y["min-integer-digits"]) NF += "#";
else NF += fill("0", +y["min-integer-digits"]);
NF += " ";
NF += fill("?", +y["min-numerator-digits"] || 1);
NF += "/";
if(+y["denominator-value"]) NF += y["denominator-value"];
else NF += fill("?", +y["min-denominator-digits"] || 1);
break;
case 'currency-symbol': // <number:currency-symbol> 16.29.9
// TODO: localization with [$-...]
if(Rn[1]==='/') {
NF += '"' + str.slice(tidx, xlmlregex.lastIndex - Rn[0].length).replace(/"/g, '""') + '"';
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
tidx = xlmlregex.lastIndex;
} else NF += "$";
break;
case 'text-properties': // <style:text-properties> 16.29.29
y = parsexmltag(Rn[0], false);
switch((y["color"]||"").toLowerCase().replace("#", "")) {
case "ff0000": case "red": NF = "[Red]" + NF; break;
}
break;
case 'text-content': // <number:text-content> 16.29.28
NF += "@";
break;
case 'map': // <style:map> 16.3
// TODO: handle more complex maps
y = parsexmltag(Rn[0], false);
if(unescapexml(y["condition"]) == "value()>=0") NF = number_format_map[y["apply-style-name"]] + ";" + NF;
else console.error("ODS number format may be incorrect: " + y["condition"]);
break;
case 'number': // <number:number> 16.29.3
// TODO: handle all the attributes
if(Rn[1]==='/') break;
y = parsexmltag(Rn[0], false);
tNF = "";
tNF += fill("0", +y["min-integer-digits"] || 1);
if(parsexmlbool(y["grouping"])) tNF = commaify(fill("#", Math.max(0, 4 - tNF.length)) + tNF);
if(+y["min-decimal-places"] || +y["decimal-places"]) tNF += ".";
if(+y["min-decimal-places"]) tNF += fill("0", +y["min-decimal-places"] || 1);
if(+y["decimal-places"] - (+y["min-decimal-places"]||0)) tNF += fill("0", +y["decimal-places"] - (+y["min-decimal-places"]||0)); // TODO: should this be "#" ?
NF += tNF;
break;
case 'embedded-text': // <number:embedded-text> 16.29.4
// TODO: verify interplay with grouping et al
if(Rn[1]==='/') {
if(etpos == 0) NF += '"' + str.slice(tidx, xlmlregex.lastIndex - Rn[0].length).replace(/"/g, '""') + '"';
else NF = NF.slice(0, etpos) + '"' + str.slice(tidx, xlmlregex.lastIndex - Rn[0].length).replace(/"/g, '""') + '"' + NF.slice(etpos);
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
tidx = xlmlregex.lastIndex;
etpos = -+parsexmltag(Rn[0], false)["position"] || 0;
} break;
}}
return number_format_map;
}
function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
var opts = _opts || {};
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
var str = xlml_normalize(d);
var state/*:Array<any>*/ = [], tmp;
var tag/*:: = {}*/;
var NFtag = {name:""}, NF = "", pidx = 0;
var nfidx, NF = "", pidx = 0;
var sheetag/*:: = {name:"", '名称':""}*/;
var rowtag/*:: = {'行号':""}*/;
var Sheets = {}, SheetNames/*:Array<string>*/ = [];
var ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
var ws = ({}/*:any*/); if(opts.dense) ws["!data"] = [];
var Rn, q/*:: :any = ({t:"", v:null, z:null, w:"",c:[],}:any)*/;
var ctag = ({value:""}/*:any*/);
var textp = "", textpidx = 0, textptag/*:: = {}*/;
var textR = [];
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
var row_ol = 0;
var number_format_map = {};
var number_format_map = _nfm || {}, styles = {};
var merges/*:Array<Range>*/ = [], mrange = {}, mR = 0, mC = 0;
var rowinfo/*:Array<RowInfo>*/ = [], rowpeat = 1, colpeat = 1;
var arrayf/*:Array<[Range, string]>*/ = [];
var WB = {Names:[]};
var WB = {Names:[], WBProps:{}};
var atag = ({}/*:any*/);
var _Ref/*:[string, string]*/ = ["", ""];
var comments/*:Array<Comment>*/ = [], comment/*:Comment*/ = ({}/*:any*/);
var creator = "", creatoridx = 0;
var isstub = false, intable = false;
var i = 0;
var baddate = 0;
xlmlregex.lastIndex = 0;
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
@ -82,7 +289,7 @@ var parse_content_xml = (function() {
sheetag = parsexmltag(Rn[0], false);
R = C = -1;
range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0;
ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/); merges = [];
ws = ({}/*:any*/); if(opts.dense) ws["!data"] = []; merges = [];
rowinfo = [];
intable = true;
}
@ -102,7 +309,7 @@ var parse_content_xml = (function() {
case 'covered-table-cell': // 9.1.5 <table:covered-table-cell>
if(Rn[1] !== '/') ++C;
if(opts.sheetStubs) {
if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = {t:'z'}; }
if(opts.dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = {t:'z'}; }
else ws[encode_cell({r:R,c:C})] = {t:'z'};
}
textp = ""; textR = [];
@ -114,13 +321,14 @@ var parse_content_xml = (function() {
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
q = ({t:'z', v:null/*:: , z:null, w:"",c:[]*/}/*:any*/);
if(ctag.formula && opts.cellFormula != false) q.f = ods_to_csf_formula(unescapexml(ctag.formula));
if(ctag["style-name"] && styles[ctag["style-name"]]) q.z = styles[ctag["style-name"]];
if((ctag['数据类型'] || ctag['value-type']) == "string") {
q.t = "s"; q.v = unescapexml(ctag['string-value'] || "");
if(opts.dense) {
if(!ws[R]) ws[R] = [];
ws[R][C] = q;
if(!ws["!data"][R]) ws["!data"][R] = [];
ws["!data"][R][C] = q;
} else {
ws[encode_cell({r:R,c:C})] = q;
ws[encode_col(C) + encode_row(R)] = q;
}
}
C+= colpeat-1;
@ -136,6 +344,7 @@ var parse_content_xml = (function() {
ctag = parsexmltag(Rn[0], false);
comments = []; comment = ({}/*:any*/);
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:"",c:[]*/}/*:any*/);
if(ctag["style-name"] && styles[ctag["style-name"]]) q.z = styles[ctag["style-name"]];
if(opts.cellFormula) {
if(ctag.formula) ctag.formula = unescapexml(ctag.formula);
if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
@ -163,16 +372,16 @@ var parse_content_xml = (function() {
/* 19.385 office:value-type */
switch(q.t) {
case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break;
case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']) || (+ctag['boolean-value'] >= 1); break;
case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']);
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v); }
q.z = 'm/d/yy'; break;
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904) - baddate; }
if(!q.z) q.z = 'm/d/yy'; break;
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400;
if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); }
q.z = 'HH:MM:SS'; break;
if(!q.z) q.z = 'HH:MM:SS'; break;
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
default:
if(q.t === 'string' || q.t === 'text' || !q.t) {
@ -196,9 +405,9 @@ var parse_content_xml = (function() {
for(var rpt = 0; rpt < rowpeat; ++rpt) {
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
if(opts.dense) {
if(!ws[R + rpt]) ws[R + rpt] = [];
ws[R + rpt][C] = rpt == 0 ? q : dup(q);
while(--colpeat > 0) ws[R + rpt][C + colpeat] = dup(q);
if(!ws["!data"][R + rpt]) ws["!data"][R + rpt] = [];
ws["!data"][R + rpt][C] = rpt == 0 ? q : dup(q);
while(--colpeat > 0) ws["!data"][R + rpt][C + colpeat] = dup(q);
} else {
ws[encode_cell({r:R + rpt,c:C})] = q;
while(--colpeat > 0) ws[encode_cell({r:R + rpt,c:C + colpeat})] = dup(q);
@ -267,23 +476,24 @@ var parse_content_xml = (function() {
textp = ""; textpidx = 0; textR = [];
break;
case 'scientific-number': // TODO: <number:scientific-number>
break;
case 'currency-symbol': // TODO: <number:currency-symbol>
break;
case 'currency-style': // TODO: <number:currency-style>
case 'scientific-number': // <number:scientific-number>
case 'currency-symbol': // <number:currency-symbol>
case 'fill-character': // 16.29.5 <number:fill-character>
break;
case 'text-style': // 16.27.25 <number:text-style>
case 'boolean-style': // 16.27.23 <number:boolean-style>
case 'number-style': // 16.27.2 <number:number-style>
case 'currency-style': // 16.29.8 <number:currency-style>
case 'percentage-style': // 16.27.9 <number:percentage-style>
case 'date-style': // 16.27.10 <number:date-style>
case 'time-style': // 16.27.18 <number:time-style>
if(Rn[1]==='/'){
number_format_map[NFtag.name] = NF;
if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
var xlmlidx = xlmlregex.lastIndex;
parse_ods_styles(str.slice(nfidx, xlmlregex.lastIndex), _opts, number_format_map);
xlmlregex.lastIndex = xlmlidx;
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
NF = "";
NFtag = parsexmltag(Rn[0], false);
state.push([Rn[3], true]);
nfidx = xlmlregex.lastIndex - Rn[0].length;
} break;
case 'script': break; // 3.13 <office:script>
@ -292,8 +502,10 @@ var parse_content_xml = (function() {
case 'default-style': // TODO: <style:default-style>
case 'page-layout': break; // TODO: <style:page-layout>
case 'style': // 16.2 <style:style>
break;
case 'style': { // 16.2 <style:style>
var styletag = parsexmltag(Rn[0], false);
if(styletag["family"] == "table-cell" && number_format_map[styletag["data-style-name"]]) styles[styletag["name"]] = number_format_map[styletag["data-style-name"]];
} break;
case 'map': break; // 16.3 <style:map>
case 'font-face': break; // 16.21 <style:font-face>
@ -304,12 +516,7 @@ var parse_content_xml = (function() {
case 'table-cell-properties': break; // 17.18 <style:table-cell-properties>
case 'number': // 16.27.3 <number:number>
switch(state[state.length-1][0]) {
case 'time-style':
case 'date-style':
tag = parsexmltag(Rn[0], false);
NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
} break;
break;
case 'fraction': break; // TODO 16.27.6 <number:fraction>
@ -324,16 +531,9 @@ var parse_content_xml = (function() {
case 'minutes': // 16.27.20 <number:minutes>
case 'seconds': // 16.27.21 <number:seconds>
case 'am-pm': // 16.27.22 <number:am-pm>
switch(state[state.length-1][0]) {
case 'time-style':
case 'date-style':
tag = parsexmltag(Rn[0], false);
NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
} break;
break;
case 'boolean-style': break; // 16.27.23 <number:boolean-style>
case 'boolean': break; // 16.27.24 <number:boolean>
case 'text-style': break; // 16.27.25 <number:text-style>
case 'text': // 16.27.26 <number:text>
if(Rn[0].slice(-2) === "/>") break;
else if(Rn[1]==="/") switch(state[state.length-1][0]) {
@ -369,7 +569,14 @@ var parse_content_xml = (function() {
case 'table-header-columns': break; // 9.1.11 <table:table-header-columns>
case 'table-columns': break; // 9.1.12 <table:table-columns>
case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
case 'null-date': // 9.4.2 <table:null-date>
tag = parsexmltag(Rn[0], false);
switch(tag["date-value"]) {
case "1904-01-01": WB.WBProps.date1904 = true;
/* falls through */
case "1900-01-01": baddate = 0;
}
break;
case 'graphic-properties': break; // 17.21 <style:graphic-properties>
case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
@ -552,19 +759,23 @@ var parse_content_xml = (function() {
}/*:any*/);
if(opts.bookSheets) delete /*::(*/out/*:: :any)*/.Sheets;
return out;
};
})();
}
function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
opts = opts || ({}/*:any*/);
if(safegetzipfile(zip, 'META-INF/manifest.xml')) parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
var styles = getzipstr(zip, 'styles.xml');
var Styles = styles && parse_ods_styles(utf8read(styles), opts);
var content = getzipstr(zip, 'content.xml');
if(!content) throw new Error("Missing content.xml in ODS / UOF file");
var wb = parse_content_xml(utf8read(content), opts);
var wb = parse_content_xml(utf8read(content), opts, Styles);
if(safegetzipfile(zip, 'meta.xml')) wb.Props = parse_core_props(getzipdata(zip, 'meta.xml'));
wb.bookType = "ods";
return wb;
}
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
return parse_content_xml(data, opts);
var wb = parse_content_xml(data, opts);
wb.bookType = "fods";
return wb;
}

@ -1,5 +1,5 @@
/* OpenDocument */
var write_styles_ods/*:{(wb:any, opts:any):string}*/ = (function() {
var write_styles_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function() {
var master_styles = [
'<office:master-styles>',
'<style:master-page style:name="mp1" style:page-layout-name="mp1">',
@ -30,7 +30,170 @@ var write_styles_ods/*:{(wb:any, opts:any):string}*/ = (function() {
return XML_HEADER + payload;
};
})();
var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
// TODO: find out if anyone actually read the spec. LO has some wild errors
function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
var type = "number", payload = "", nopts = { "style:name": nfidx }, c = "", i = 0;
nf = nf.replace(/"[$]"/g, "$");
/* TODO: replace with an actual parser based on a real grammar */
j: {
// TODO: support style maps
if(nf.indexOf(";") > -1) {
console.error("Unsupported ODS Style Map exported. Using first branch of " + nf);
nf = nf.slice(0, nf.indexOf(";"));
}
if(nf == "@") { type = "text"; payload = "<number:text-content/>"; break j; }
/* currency flag */
if(nf.indexOf(/\$/) > -1) { type = "currency"; }
/* opening string literal */
if(nf[i] == '"') {
c = "";
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
if(nf[i+1] == "*") {
i++;
payload += '<number:fill-character>' + escapexml(c.replace(/""/g, '"')) + '</number:fill-character>';
} else {
payload += '<number:text>' + escapexml(c.replace(/""/g, '"')) + '</number:text>';
}
nf = nf.slice(i+1); i = 0;
}
/* fractions */
var t = nf.match(/# (\?+)\/(\?+)/);
if(t) { payload += writextag("number:fraction", null, {"number:min-integer-digits":0, "number:min-numerator-digits": t[1].length, "number:max-denominator-value": Math.max(+(t[1].replace(/./g, "9")), +(t[2].replace(/./g, "9"))) }); break j; }
if((t=nf.match(/# (\?+)\/(\d+)/))) { payload += writextag("number:fraction", null, {"number:min-integer-digits":0, "number:min-numerator-digits": t[1].length, "number:denominator-value": +t[2]}); break j; }
/* percentages */
if((t=nf.match(/(\d+)(|\.\d+)%/))) { type = "percentage"; payload += writextag("number:number", null, {"number:decimal-places": t[2] && t.length - 1 || 0, "number:min-decimal-places": t[2] && t.length - 1 || 0, "number:min-integer-digits": t[1].length }) + "<number:text>%</number:text>"; break j; }
/* datetime */
var has_time = false;
if(["y","m","d"].indexOf(nf[0]) > -1) {
type = "date";
k: for(; i < nf.length; ++i) switch((c = nf[i].toLowerCase())) {
case "h": case "s": has_time = true; --i; break k;
case "m":
l: for(var h = i+1; h < nf.length; ++h) switch(nf[h]) {
case "y": case "d": break l;
case "h": case "s": has_time = true; --i; break k;
}
/* falls through */
case "y": case "d":
while((nf[++i]||"").toLowerCase() == c[0]) c += c[0]; --i;
switch(c) {
case "y": case "yy": payload += "<number:year/>"; break;
case "yyy": case "yyyy": payload += '<number:year number:style="long"/>'; break;
case "mmmmm": console.error("ODS has no equivalent of format |mmmmm|");
/* falls through */
case "m": case "mm": case "mmm": case "mmmm":
payload += '<number:month number:style="' + (c.length % 2 ? "short" : "long") + '" number:textual="' + (c.length >= 3 ? "true" : "false") + '"/>';
break;
case "d": case "dd": payload += '<number:day number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break;
case "ddd": case "dddd": payload += '<number:day-of-week number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break;
}
break;
case '"':
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
break;
case '/': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
default: console.error("unrecognized character " + c + " in ODF format " + nf);
}
if(!has_time) break j;
nf = nf.slice(i+1); i = 0;
}
if(nf.match(/^\[?[hms]/)) {
if(type == "number") type = "time";
if(nf.match(/\[/)) {
nf = nf.replace(/[\[\]]/g, "");
nopts['number:truncate-on-overflow'] = "false";
}
for(; i < nf.length; ++i) switch((c = nf[i].toLowerCase())) {
case "h": case "m": case "s":
while((nf[++i]||"").toLowerCase() == c[0]) c += c[0]; --i;
switch(c) {
case "h": case "hh": payload += '<number:hours number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break;
case "m": case "mm": payload += '<number:minutes number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break;
case "s": case "ss":
if(nf[i+1] == ".") do { c += nf[i+1]; ++i; } while(nf[i+1] == "0");
payload += '<number:seconds number:style="' + (c.match("ss") ? "long" : "short") + '"' + (c.match(/\./) ? ' number:decimal-places="' + (c.match(/0+/)||[""])[0].length + '"' : "")+ '/>'; break;
}
break;
case '"':
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
break;
case '/': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
case "a":
if(nf.slice(i, i+3).toLowerCase() == "a/p") { payload += '<number:am-pm/>'; i += 2; break; } // Note: ODF does not support A/P
if(nf.slice(i, i+5).toLowerCase() == "am/pm") { payload += '<number:am-pm/>'; i += 4; break; }
/* falls through */
default: console.error("unrecognized character " + c + " in ODF format " + nf);
}
break j;
}
/* currency flag */
if(nf.indexOf(/\$/) > -1) { type = "currency"; }
/* should be in a char loop */
if(nf[0] == "$") { payload += '<number:currency-symbol number:language="en" number:country="US">$</number:currency-symbol>'; nf = nf.slice(1); i = 0; }
i = 0; if(nf[i] == '"') {
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
if(nf[i+1] == "*") {
i++;
payload += '<number:fill-character>' + escapexml(c.replace(/""/g, '"')) + '</number:fill-character>';
} else {
payload += '<number:text>' + escapexml(c.replace(/""/g, '"')) + '</number:text>';
}
nf = nf.slice(i+1); i = 0;
}
/* number TODO: interstitial text e.g. 000)000-0000 */
var np = nf.match(/([#0][0#,]*)(\.[0#]*|)(E[+]?0*|)/i);
if(!np || !np[0]) console.error("Could not find numeric part of " + nf);
else {
var base = np[1].replace(/,/g, "");
payload += '<number:' + (np[3] ? "scientific-" : "")+ 'number' +
' number:min-integer-digits="' + (base.indexOf("0") == -1 ? "0" : base.length - base.indexOf("0")) + '"' +
(np[0].indexOf(",") > -1 ? ' number:grouping="true"' : "") +
(np[2] && ' number:decimal-places="' + (np[2].length - 1) + '"' || ' number:decimal-places="0"') +
(np[3] && np[3].indexOf("+") > -1 ? ' number:forced-exponent-sign="true"' : "" ) +
(np[3] ? ' number:min-exponent-digits="' + np[3].match(/0+/)[0].length + '"' : "" ) +
'>' +
/* TODO: interstitial text placeholders */
'</number:' + (np[3] ? "scientific-" : "") + 'number>';
i = np.index + np[0].length;
}
/* residual text */
if(nf[i] == '"') {
c = "";
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
payload += '<number:text>' + escapexml(c.replace(/""/g, '"')) + '</number:text>';
}
}
if(!payload) { console.error("Could not generate ODS number format for |" + nf + "|"); return ""; }
return writextag("number:" + type + "-style", payload, nopts);
}
function write_names_ods(Names, SheetNames, idx) {
var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
if(!scoped.length) return "";
return " <table:named-expressions>\n" + scoped.map(function(name) {
var odsref = csf_to_ods_3D(name.Ref);
return " " + writextag("table:named-range", null, {
"table:name": name.Name,
"table:cell-range-address": odsref,
"table:base-cell-address": odsref.replace(/[\.]?[^\.]*$/, ".$A$1")
});
}).join("\n") + "\n </table:named-expressions>\n";
}
var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function() {
/* 6.1.2 White Space Characters */
var write_text_p = function(text/*:string*/)/*:string*/ {
return escapexml(text)
@ -42,13 +205,13 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
var null_cell_xml = ' <table:table-cell />\n';
var covered_cell_xml = ' <table:covered-table-cell/>\n';
var write_ws = function(ws, wb/*:Workbook*/, i/*:number*//*::, opts*/)/*:string*/ {
var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts, nfs)/*:string*/ {
/* Section 9 Tables */
var o/*:Array<string>*/ = [];
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="ta1">\n');
var R=0,C=0, range = decode_range(ws['!ref']||"A1");
var marr/*:Array<Range>*/ = ws['!merges'] || [], mi = 0;
var dense = Array.isArray(ws);
var dense = ws["!data"] != null;
if(ws["!cols"]) {
for(C = 0; C <= range.e.c; ++C) o.push(' <table:table-column' + (ws["!cols"][C] ? ' table:style-name="co' + ws["!cols"][C].ods + '"' : '') + '></table:table-column>\n');
}
@ -74,7 +237,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
break;
}
if(skip) { o.push(covered_cell_xml); continue; }
var ref = encode_cell({r:R, c:C}), cell = dense ? (ws[R]||[])[C]: ws[ref];
var ref = encode_cell({r:R, c:C}), cell = dense ? (ws["!data"][R]||[])[C]: ws[ref];
if(cell && cell.f) {
ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f));
if(cell.F) {
@ -118,10 +281,12 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
if(_tgt.charAt(0) != "#" && !_tgt.match(/^\w+:/)) _tgt = '../' + _tgt;
text_p = writextag('text:a', text_p, {'xlink:href': _tgt.replace(/&/g, "&amp;")});
}
if(nfs[cell.z]) ct["table:style-name"] = "ce" + nfs[cell.z].slice(1);
o.push(' ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n');
}
o.push(' </table:table-row>\n');
}
if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, i));
o.push(' </table:table>\n');
return o.join("");
};
@ -129,14 +294,6 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
var write_automatic_styles_ods = function(o/*:Array<string>*/, wb) {
o.push(' <office:automatic-styles>\n');
o.push(' <number:date-style style:name="N37" number:automatic-order="true">\n');
o.push(' <number:month number:style="long"/>\n');
o.push(' <number:text>/</number:text>\n');
o.push(' <number:day number:style="long"/>\n');
o.push(' <number:text>/</number:text>\n');
o.push(' <number:year/>\n');
o.push(' </number:date-style>\n');
/* column styles */
var cidx = 0;
wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
@ -177,12 +334,39 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
o.push(' <style:table-properties table:display="true" style:writing-mode="lr-tb"/>\n');
o.push(' </style:style>\n');
/* table cells, text */
o.push(' <number:date-style style:name="N37" number:automatic-order="true">\n');
o.push(' <number:month number:style="long"/>\n');
o.push(' <number:text>/</number:text>\n');
o.push(' <number:day number:style="long"/>\n');
o.push(' <number:text>/</number:text>\n');
o.push(' <number:year/>\n');
o.push(' </number:date-style>\n');
/* number formats, table cells, text */
var nfs = {};
var nfi = 69;
wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
if(!ws) return;
var dense = (ws["!data"] != null);
var range = decode_range(ws["!ref"]);
for(var R = 0; R <= range.e.r; ++R) for(var C = 0; C <= range.e.c; ++C) {
var c = dense ? (ws["!data"][R]||[])[C] : ws[encode_cell({r:R,c:C})];
if(!c || !c.z || c.z.toLowerCase() == "general") continue;
if(!nfs[c.z]) {
var out = write_number_format_ods(c.z, "N" + nfi);
if(out) { nfs[c.z] = "N" + nfi; ++nfi; o.push(out + "\n"); }
}
}
});
o.push(' <style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N37"/>\n');
keys(nfs).forEach(function(nf) {
o.push('<style:style style:name="ce' + nfs[nf].slice(1) + '" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="' + nfs[nf] + '"/>\n');
});
/* page-layout */
o.push(' </office:automatic-styles>\n');
return nfs;
};
return function wcx(wb, opts) {
@ -235,14 +419,16 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
if(opts.bookType == "fods") {
o.push('<office:document' + attr + fods + '>\n');
o.push(write_meta_ods().replace(/office:document-meta/g, "office:meta"));
o.push(write_meta_ods().replace(/<office:document-meta.*?>/, "").replace(/<\/office:document-meta>/, "") + "\n");
// TODO: settings (equiv of settings.xml for ODS)
} else o.push('<office:document-content' + attr + '>\n');
// o.push(' <office:scripts/>\n');
write_automatic_styles_ods(o, wb);
var nfs = write_automatic_styles_ods(o, wb);
o.push(' <office:body>\n');
o.push(' <office:spreadsheet>\n');
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts));
if(((wb.Workbook||{}).WBProps||{}).date1904) o.push(' <table:calculation-settings table:case-sensitive="false" table:search-criteria-must-apply-to-whole-cell="true" table:use-wildcards="true" table:use-regular-expressions="false" table:automatic-find-labels="false">\n <table:null-date table:date-value="1904-01-01"/>\n </table:calculation-settings>\n');
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs));
if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1));
o.push(' </office:spreadsheet>\n');
o.push(' </office:body>\n');
if(opts.bookType == "fods") o.push('</office:document>');

File diff suppressed because it is too large Load Diff

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

@ -35,23 +35,29 @@ function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/
}
sheets[sheet] = _ws;
/* scan rels for comments */
var comments = [];
/* scan rels for comments and threaded comments */
var comments = [], tcomments = [];
if(sheetRels && sheetRels[sheet]) keys(sheetRels[sheet]).forEach(function(n) {
var dfile = "";
if(sheetRels[sheet][n].Type == RELS.CMNT) {
var dfile = resolve_path(sheetRels[sheet][n].Target, path);
dfile = resolve_path(sheetRels[sheet][n].Target, path);
comments = parse_cmnt(getzipdata(zip, dfile, true), dfile, opts);
if(!comments || !comments.length) return;
sheet_insert_comments(_ws, comments);
sheet_insert_comments(_ws, comments, false);
}
if(sheetRels[sheet][n].Type == RELS.TCMNT) {
dfile = resolve_path(sheetRels[sheet][n].Target, path);
tcomments = tcomments.concat(parse_tcmnt_xml(getzipdata(zip, dfile, true), opts));
}
});
if(tcomments && tcomments.length) sheet_insert_comments(_ws, tcomments, true, opts.people || []);
} catch(e) { if(opts.WTF) throw e; }
}
function strip_front_slash(x/*:string*/)/*:string*/ { return x.charAt(0) == '/' ? x.slice(1) : x; }
function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
make_ssf(SSF);
make_ssf();
opts = opts || {};
fix_read_opts(opts);
@ -62,17 +68,26 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
/* Numbers */
if(safegetzipfile(zip, 'Index/Document.iwa')) {
if(typeof Uint8Array == "undefined") throw new Error('NUMBERS file parsing requires Uint8Array support');
if(typeof NUMBERS != "undefined") {
if(zip.FileIndex) return NUMBERS.parse_numbers(zip);
if(typeof parse_numbers_iwa != "undefined") {
if(zip.FileIndex) return parse_numbers_iwa(zip, opts);
var _zip = CFB.utils.cfb_new();
zipentries(zip).forEach(function(e) { zip_add_file(_zip, e, getzipbin(zip, e)); });
return NUMBERS.parse_numbers(_zip);
return parse_numbers_iwa(_zip, opts);
}
throw new Error('Unsupported NUMBERS file');
}
if(!safegetzipfile(zip, '[Content_Types].xml')) {
if(safegetzipfile(zip, 'index.xml.gz')) throw new Error('Unsupported NUMBERS 08 file');
if(safegetzipfile(zip, 'index.xml')) throw new Error('Unsupported NUMBERS 09 file');
var index_zip = CFB.find(zip, 'Index.zip');
if(index_zip) {
opts = dup(opts);
delete opts.type;
if(typeof index_zip.content == "string") opts.type = "binary";
// TODO: Bun buffer bug
if(typeof Bun !== "undefined" && Buffer.isBuffer(index_zip.content)) return readSync(new Uint8Array(index_zip.content), opts);
return readSync(index_zip.content, opts);
}
throw new Error('Unsupported ZIP file');
}
@ -98,7 +113,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
strs = [];
if(dir.sst) try { strs=parse_sst(getzipdata(zip, strip_front_slash(dir.sst)), dir.sst, opts); } catch(e) { if(opts.WTF) throw e; }
if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts);
if(opts.cellStyles && dir.themes.length) themes = parse_theme_xml(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"", opts);
if(dir.style) styles = parse_sty(getzipdata(zip, strip_front_slash(dir.style)), dir.style, themes, opts);
}
@ -168,8 +183,11 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
opts.xlmeta = parse_xlmeta(getzipdata(zip, strip_front_slash(dir.metadata[0])),dir.metadata[0],opts);
}
if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
if((dir.people || []).length >= 1) {
opts.people = parse_people_xml(getzipdata(zip, strip_front_slash(dir.people[0])),opts);
}
if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
/* Numbers iOS hack */
var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
@ -211,7 +229,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
Strings: strs,
Styles: styles,
Themes: themes,
SSF: SSF.get_table()
SSF: dup(table_fmt)
}/*:any*/);
if(opts && opts.bookFiles) {
if(zip.files) {
@ -231,6 +249,8 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,strip_front_slash(dir.vba[0]),true);
else if(dir.defaults && dir.defaults.bin === CT_VBA) out.vbaraw = getzipdata(zip, 'xl/vbaProject.bin',true);
}
// TODO: pass back content types metdata for xlsm/xlsx resolution
out.bookType = xlsb ? "xlsb" : "xlsx";
return out;
}

@ -1,15 +1,9 @@
function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
if(opts.bookType == "ods") return write_ods(wb, opts);
return write_zip_xlsxb(wb, opts);
}
function write_zip_xlsxb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
_shapeid = 1024;
function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
if(wb && !wb.SSF) {
wb.SSF = SSF.get_table();
wb.SSF = dup(table_fmt);
}
if(wb && wb.SSF) {
make_ssf(SSF); SSF.load_table(wb.SSF);
make_ssf(); SSF_load_table(wb.SSF);
// $FlowIgnore
opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
opts.ssf = wb.SSF;
@ -18,8 +12,8 @@ function write_zip_xlsxb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
opts.Strings = /*::((*/[]/*:: :any):SST)*/; opts.Strings.Count = 0; opts.Strings.Unique = 0;
if(browser_has_Map) opts.revStrings = new Map();
else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; }
var wbext = opts.bookType == "xlsb" ? "bin" : "xml";
var vbafmt = VBAFMTS.indexOf(opts.bookType) > -1;
var wbext = "bin";
var vbafmt = true;
var ct = new_ct();
fix_write_opts(opts = opts || {});
var zip = zip_new();
@ -66,7 +60,7 @@ function write_zip_xlsxb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
/* falls through */
default:
f = "xl/worksheets/sheet" + rId + "." + wbext;
zip_add_file(zip, f, write_ws(rId-1, f, opts, wb, wsrels));
zip_add_file(zip, f, write_ws_bin(rId-1, opts, wb, wsrels));
ct.sheets.push(f);
add_rels(opts.wbrels, -1, "worksheets/sheet" + rId + "." + wbext, RELS.WS[0]);
}
@ -74,15 +68,16 @@ function write_zip_xlsxb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
if(ws) {
var comments = ws['!comments'];
var need_vml = false;
var cf = "";
if(comments && comments.length > 0) {
var cf = "xl/comments" + rId + "." + wbext;
zip_add_file(zip, cf, write_cmnt(comments, cf, opts));
cf = "xl/comments" + rId + "." + wbext;
zip_add_file(zip, cf, write_comments_bin(comments, opts));
ct.comments.push(cf);
add_rels(wsrels, -1, "../comments" + rId + "." + wbext, RELS.CMNT);
need_vml = true;
}
if(ws['!legacy']) {
if(need_vml) zip_add_file(zip, "xl/drawings/vmlDrawing" + (rId) + ".vml", write_comments_vml(rId, ws['!comments']));
if(need_vml) zip_add_file(zip, "xl/drawings/vmlDrawing" + (rId) + ".vml", write_vml(rId, ws['!comments']));
}
delete ws['!comments'];
delete ws['!legacy'];
@ -93,27 +88,28 @@ function write_zip_xlsxb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
if(opts.Strings != null && opts.Strings.length > 0) {
f = "xl/sharedStrings." + wbext;
zip_add_file(zip, f, write_sst(opts.Strings, f, opts));
zip_add_file(zip, f, write_sst_bin(opts.Strings, opts));
ct.strs.push(f);
add_rels(opts.wbrels, -1, "sharedStrings." + wbext, RELS.SST);
}
f = "xl/workbook." + wbext;
zip_add_file(zip, f, write_wb(wb, f, opts));
zip_add_file(zip, f, write_wb_bin(wb, opts));
ct.workbooks.push(f);
add_rels(opts.rels, 1, f, RELS.WB);
/* TODO: something more intelligent with themes */
f = "xl/theme/theme1.xml";
zip_add_file(zip, f, write_theme(wb.Themes, opts));
var ww = write_theme(wb.Themes, opts);
zip_add_file(zip, f, ww);
ct.themes.push(f);
add_rels(opts.wbrels, -1, "theme/theme1.xml", RELS.THEME);
/* TODO: something more intelligent with styles */
f = "xl/styles." + wbext;
zip_add_file(zip, f, write_sty(wb, f, opts));
zip_add_file(zip, f, write_sty_bin(wb, opts));
ct.styles.push(f);
add_rels(opts.wbrels, -1, "styles." + wbext, RELS.STY);
@ -125,7 +121,7 @@ function write_zip_xlsxb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
}
f = "xl/metadata." + wbext;
zip_add_file(zip, f, write_xlmeta(f));
zip_add_file(zip, f, write_xlmeta_bin());
ct.metadata.push(f);
add_rels(opts.wbrels, -1, "metadata." + wbext, RELS.XLMETA);
@ -137,14 +133,12 @@ function write_zip_xlsxb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
return zip;
}
/* this version does not reference XLSB write functions */
function write_zip_xlsx(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
_shapeid = 1024;
if(wb && !wb.SSF) {
wb.SSF = SSF.get_table();
wb.SSF = dup(table_fmt);
}
if(wb && wb.SSF) {
make_ssf(SSF); SSF.load_table(wb.SSF);
make_ssf(); SSF_load_table(wb.SSF);
// $FlowIgnore
opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
opts.ssf = wb.SSF;
@ -192,6 +186,9 @@ function write_zip_xlsx(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
add_rels(opts.rels, 4, f, RELS.CUST_PROPS);
}
var people = ["SheetJ5"];
opts.tcid = 0;
for(rId=1;rId <= wb.SheetNames.length; ++rId) {
var wsrels = {'!id':{}};
var ws = wb.Sheets[wb.SheetNames[rId-1]];
@ -209,15 +206,27 @@ function write_zip_xlsx(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
if(ws) {
var comments = ws['!comments'];
var need_vml = false;
var cf = "";
if(comments && comments.length > 0) {
var cf = "xl/comments" + rId + "." + wbext;
var needtc = false;
comments.forEach(function(carr) {
carr[1].forEach(function(c) { if(c.T == true) needtc = true; });
});
if(needtc) {
cf = "xl/threadedComments/threadedComment" + rId + ".xml";
zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts));
ct.threadedcomments.push(cf);
add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + ".xml", RELS.TCMNT);
}
cf = "xl/comments" + rId + "." + wbext;
zip_add_file(zip, cf, write_comments_xml(comments, opts));
ct.comments.push(cf);
add_rels(wsrels, -1, "../comments" + rId + "." + wbext, RELS.CMNT);
need_vml = true;
}
if(ws['!legacy']) {
if(need_vml) zip_add_file(zip, "xl/drawings/vmlDrawing" + (rId) + ".vml", write_comments_vml(rId, ws['!comments']));
if(need_vml) zip_add_file(zip, "xl/drawings/vmlDrawing" + (rId) + ".vml", write_vml(rId, ws['!comments']));
}
delete ws['!comments'];
delete ws['!legacy'];
@ -264,6 +273,13 @@ function write_zip_xlsx(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
ct.metadata.push(f);
add_rels(opts.wbrels, -1, "metadata." + wbext, RELS.XLMETA);
if(people.length > 1) {
f = "xl/persons/person.xml";
zip_add_file(zip, f, write_people_xml(people, opts));
ct.people.push(f);
add_rels(opts.wbrels, -1, "persons/person.xml", RELS.PEOPLE);
}
zip_add_file(zip, "[Content_Types].xml", write_ct(ct, opts));
zip_add_file(zip, '_rels/.rels', write_rels(opts.rels));
zip_add_file(zip, 'xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));

@ -2,7 +2,7 @@ function firstbyte(f/*:RawData*/,o/*:?TypeOpts*/)/*:Array<number>*/ {
var x = "";
switch((o||{}).type || "base64") {
case 'buffer': return [f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]];
case 'base64': x = Base64.decode(f.slice(0,12)); break;
case 'base64': x = Base64_decode(f.slice(0,12)); break;
case 'binary': x = f; break;
case 'array': return [f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]];
default: throw new Error("Unrecognized type " + (o && o.type || "undefined"));
@ -36,7 +36,7 @@ function read_plaintext(data/*:string*/, o/*:ParseOpts*/)/*:Workbook*/ {
function read_plaintext_raw(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
var str = "", bytes = firstbyte(data, o);
switch(o.type) {
case 'base64': str = Base64.decode(data); break;
case 'base64': str = Base64_decode(data); break;
case 'binary': str = data; break;
case 'buffer': str = data.toString('binary'); break;
case 'array': str = cc2str(data); break;
@ -49,8 +49,8 @@ function read_plaintext_raw(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
function read_utf16(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
var d = data;
if(o.type == 'base64') d = Base64.decode(d);
d = cptable.utils.decode(1200, d.slice(2), 'str');
if(o.type == 'base64') d = Base64_decode(d);
d = typeof $cptable !== "undefined" ? $cptable.utils.decode(1200, d.slice(2), 'str') : utf16leread(d.slice(2));
o.type = "binary";
return read_plaintext(d, o);
}
@ -67,6 +67,7 @@ function read_prn(data, d, o, str) {
function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
reset_cp();
var o = opts||{};
if(o.codepage && typeof $cptable === "undefined") console.error("Codepage tables are not loaded. Non-ASCII characters may not give expected results");
if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), (o = dup(o), o.type = "array", o));
if(typeof Uint8Array !== 'undefined' && data instanceof Uint8Array && !o.type) o.type = typeof Deno !== "undefined" ? "buffer" : "array";
var d = data, n = [0,0,0,0], str = false;
@ -104,11 +105,16 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
}
break;
case 0x03: case 0x83: case 0x8B: case 0x8C: return DBF.to_workbook(d, o);
case 0x7B: if(n[1] === 0x5C && n[2] === 0x72 && n[3] === 0x74) return RTF.to_workbook(d, o); break;
case 0x7B: if(n[1] === 0x5C && n[2] === 0x72 && n[3] === 0x74) return rtf_to_workbook(d, o); break;
case 0x0A: case 0x0D: case 0x20: return read_plaintext_raw(d, o);
case 0x89: if(n[1] === 0x50 && n[2] === 0x4E && n[3] === 0x47) throw new Error("PNG Image File is not a spreadsheet"); break;
case 0x08: if(n[1] === 0xE7) throw new Error("Unsupported Multiplan 1.x file!"); break;
case 0x0C:
if(n[1] === 0xEC) throw new Error("Unsupported Multiplan 2.x file!");
if(n[1] === 0xED) throw new Error("Unsupported Multiplan 3.x file!");
break;
}
if(DBF.versions.indexOf(n[0]) > -1 && n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
if(DBF_SUPPORTED_VERSIONS.indexOf(n[0]) > -1 && n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
return read_prn(data, d, o, str);
}

@ -1,26 +1,3 @@
function write_obj_str(factory/*:WriteObjStrFactory*/) {
return function write_str(wb/*:Workbook*/, o/*:WriteOpts*/)/*:string*/ {
var idx = 0;
if(o.sheet) {
if(typeof o.sheet == "number") idx = o.sheet;
else idx = wb.SheetNames.indexOf(o.sheet);
if(!wb.SheetNames[idx]) throw new Error("Sheet not found: " + o.sheet + " : " + (typeof o.sheet));
}
return factory.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb);
};
}
var write_htm_str = write_obj_str(HTML_);
var write_csv_str = write_obj_str({from_sheet:sheet_to_csv});
var write_slk_str = write_obj_str(typeof SYLK !== "undefined" ? SYLK : {});
var write_dif_str = write_obj_str(typeof DIF !== "undefined" ? DIF : {});
var write_prn_str = write_obj_str(typeof PRN !== "undefined" ? PRN : {});
var write_rtf_str = write_obj_str(typeof RTF !== "undefined" ? RTF : {});
var write_txt_str = write_obj_str({from_sheet:sheet_to_txt});
var write_dbf_buf = write_obj_str(typeof DBF !== "undefined" ? DBF : {});
var write_eth_str = write_obj_str(typeof ETH !== "undefined" ? ETH : {});
var write_wk1_buf = write_obj_str(typeof WK_ !== "undefined" ? {from_sheet:WK_.sheet_to_wk1} : {});
function write_cfb_ctr(cfb/*:CFBContainer*/, o/*:WriteOpts*/)/*:any*/ {
switch(o.type) {
case "base64": case "binary": break;
@ -32,6 +9,15 @@ function write_cfb_ctr(cfb/*:CFBContainer*/, o/*:WriteOpts*/)/*:any*/ {
return CFB.write(cfb, o);
}
function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
switch(opts.bookType) {
case "ods": return write_ods(wb, opts);
case "numbers": return write_numbers_iwa(wb, opts);
case "xlsb": return write_zip_xlsb(wb, opts);
default: return write_zip_xlsx(wb, opts);
}
}
/*:: declare var encrypt_agile:any; */
function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:any*/ {
var o = dup(opts||{});
@ -80,7 +66,7 @@ function write_string_type(out/*:string*/, opts/*:WriteOpts*/, bom/*:?string*/)/
if(!bom) bom = "";
var o = bom + out;
switch(opts.type) {
case "base64": return Base64.encode(utf8write(o));
case "base64": return Base64_encode(utf8write(o));
case "binary": return utf8write(o);
case "string": return out;
case "file": return write_dl(opts.file, o, 'utf8');
@ -95,7 +81,7 @@ function write_string_type(out/*:string*/, opts/*:WriteOpts*/, bom/*:?string*/)/
function write_stxt_type(out/*:string*/, opts/*:WriteOpts*/)/*:any*/ {
switch(opts.type) {
case "base64": return Base64.encode(out);
case "base64": return Base64_encode_pass(out);
case "binary": return out;
case "string": return out; /* override in sheet_to_txt */
case "file": return write_dl(opts.file, out, 'binary');
@ -116,7 +102,7 @@ function write_binary_type(out, opts/*:WriteOpts*/)/*:any*/ {
var bstr = "";
// $FlowIgnore
for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]);
return opts.type == 'base64' ? Base64.encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr;
return opts.type == 'base64' ? Base64_encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr;
case "file": return write_dl(opts.file, out);
case "buffer": return out;
default: throw new Error("Unrecognized type " + opts.type);
@ -138,22 +124,28 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
var o = dup(opts||{});
if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; }
if(o.type == "array") { o.type = "binary"; var out/*:string*/ = (writeSync(wb, o)/*:any*/); o.type = "array"; return s2ab(out); }
var idx = 0;
if(o.sheet) {
if(typeof o.sheet == "number") idx = o.sheet;
else idx = wb.SheetNames.indexOf(o.sheet);
if(!wb.SheetNames[idx]) throw new Error("Sheet not found: " + o.sheet + " : " + (typeof o.sheet));
}
switch(o.bookType || 'xlsb') {
case 'xml':
case 'xlml': return write_string_type(write_xlml(wb, o), o);
case 'slk':
case 'sylk': return write_string_type(write_slk_str(wb, o), o);
case 'sylk': return write_string_type(SYLK.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb), o);
case 'htm':
case 'html': return write_string_type(write_htm_str(wb, o), o);
case 'txt': return write_stxt_type(write_txt_str(wb, o), o);
case 'csv': return write_string_type(write_csv_str(wb, o), o, "\ufeff");
case 'dif': return write_string_type(write_dif_str(wb, o), o);
case 'dbf': return write_binary_type(write_dbf_buf(wb, o), o);
case 'prn': return write_string_type(write_prn_str(wb, o), o);
case 'rtf': return write_string_type(write_rtf_str(wb, o), o);
case 'eth': return write_string_type(write_eth_str(wb, o), o);
case 'html': return write_string_type(sheet_to_html(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'txt': return write_stxt_type(sheet_to_txt(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'csv': return write_string_type(sheet_to_csv(wb.Sheets[wb.SheetNames[idx]], o), o, "\ufeff");
case 'dif': return write_string_type(DIF.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'dbf': return write_binary_type(DBF.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'prn': return write_string_type(PRN.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'rtf': return write_string_type(sheet_to_rtf(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'eth': return write_string_type(ETH.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'fods': return write_string_type(write_ods(wb, o), o);
case 'wk1': return write_binary_type(write_wk1_buf(wb, o), o);
case 'wk1': return write_binary_type(WK_.sheet_to_wk1(wb.Sheets[wb.SheetNames[idx]], o), o);
case 'wk3': return write_binary_type(WK_.book_to_wk3(wb, o), o);
case 'biff2': if(!o.biff) o.biff = 2; /* falls through */
case 'biff3': if(!o.biff) o.biff = 3; /* falls through */
@ -166,6 +158,7 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
case 'xlsm':
case 'xlam':
case 'xlsb':
case 'numbers':
case 'ods': return write_zip_type(wb, o);
default: throw new Error ("Unrecognized bookType |" + o.bookType + "|");
}

@ -4,17 +4,17 @@ type MJRObject = {
isempty: boolean;
};
*/
function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, header/*:number*/, hdr/*:Array<any>*/, dense/*:boolean*/, o/*:Sheet2JSONOpts*/)/*:MJRObject*/ {
function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, header/*:number*/, hdr/*:Array<any>*/, o/*:Sheet2JSONOpts*/)/*:MJRObject*/ {
var rr = encode_row(R);
var defval = o.defval, raw = o.raw || !Object.prototype.hasOwnProperty.call(o, "raw");
var isempty = true;
var isempty = true, dense = (sheet["!data"] != null);
var row/*:any*/ = (header === 1) ? [] : {};
if(header !== 1) {
if(Object.defineProperty) try { Object.defineProperty(row, '__rowNum__', {value:R, enumerable:false}); } catch(e) { row.__rowNum__ = R; }
else row.__rowNum__ = R;
}
if(!dense || sheet[R]) for (var C = r.s.c; C <= r.e.c; ++C) {
var val = dense ? sheet[R][C] : sheet[cols[C] + rr];
if(!dense || sheet["!data"][R]) for (var C = r.s.c; C <= r.e.c; ++C) {
var val = dense ? (sheet["!data"][R]||[])[C] : sheet[cols[C] + rr];
if(val === undefined || val.t === undefined) {
if(defval === undefined) continue;
if(hdr[C] != null) { row[hdr[C]] = defval; }
@ -34,7 +34,7 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
else if(raw && v === null) row[hdr[C]] = null;
else continue;
} else {
row[hdr[C]] = raw || (o.rawNumbers && val.t == "n") ? v : format_cell(val,v,o);
row[hdr[C]] = raw && (val.t !== "n" || (val.t === "n" && o.rawNumbers !== false)) ? v : format_cell(val,v,o);
}
if(v != null) isempty = false;
}
@ -63,12 +63,16 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) {
var cols/*:Array<string>*/ = [];
var out/*:Array<any>*/ = [];
var outi = 0, counter = 0;
var dense = Array.isArray(sheet);
var R = r.s.r, C = 0, CC = 0;
if(dense && !sheet[R]) sheet[R] = [];
var dense = sheet["!data"] != null;
var R = r.s.r, C = 0;
var header_cnt = {};
if(dense && !sheet["!data"][R]) sheet["!data"][R] = [];
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
var rowinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!rows"] || [];
for(C = r.s.c; C <= r.e.c; ++C) {
if(((colinfo[C]||{}).hidden)) continue;
cols[C] = encode_col(C);
val = dense ? sheet[R][C] : sheet[cols[C] + rr];
val = dense ? sheet["!data"][R][C] : sheet[cols[C] + rr];
switch(header) {
case 1: hdr[C] = C - r.s.c; break;
case 2: hdr[C] = cols[C]; break;
@ -76,13 +80,18 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) {
default:
if(val == null) val = {w: "__EMPTY", t: "s"};
vv = v = format_cell(val, null, o);
counter = 0;
for(CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter);
counter = header_cnt[v] || 0;
if(!counter) header_cnt[v] = 1;
else {
do { vv = v + "_" + (counter++); } while(header_cnt[vv]); header_cnt[v] = counter;
header_cnt[vv] = 1;
}
hdr[C] = vv;
}
}
for (R = r.s.r + offset; R <= r.e.r; ++R) {
var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o);
if ((rowinfo[R]||{}).hidden) continue;
var row = make_json_row(sheet, r, R, cols, header, hdr, o);
if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) out[outi++] = row.row;
}
out.length = outi;
@ -93,9 +102,11 @@ var qreg = /"/g;
function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, fs/*:number*/, rs/*:number*/, FS/*:string*/, o/*:Sheet2CSVOpts*/)/*:?string*/ {
var isempty = true;
var row/*:Array<string>*/ = [], txt = "", rr = encode_row(R);
var dense = sheet["!data"] != null;
var datarow = dense && sheet["!data"][R] || [];
for(var C = r.s.c; C <= r.e.c; ++C) {
if (!cols[C]) continue;
var val = o.dense ? (sheet[R]||[])[C]: sheet[cols[C] + rr];
var val = dense ? datarow[C]: sheet[cols[C] + rr];
if(val == null) txt = "";
else if(val.v != null) {
isempty = false;
@ -122,26 +133,25 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ {
var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
var row = "", cols/*:Array<string>*/ = [];
o.dense = Array.isArray(sheet);
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
var rowinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!rows"] || [];
for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
var w = 0;
for(var R = r.s.r; R <= r.e.r; ++R) {
if ((rowinfo[R]||{}).hidden) continue;
row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o);
if(row == null) { continue; }
if(o.strip) row = row.replace(endregex,"");
out.push(row + RS);
if(row || (o.blankrows !== false)) out.push((w++ ? RS : "") + row);
}
delete o.dense;
return out.join("");
}
function sheet_to_txt(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n";
var s = sheet_to_csv(sheet, opts);
if(typeof cptable == 'undefined' || opts.type == 'string') return s;
var o = cptable.utils.encode(1200, s, 'str');
if(typeof $cptable == 'undefined' || opts.type == 'string') return s;
var o = $cptable.utils.encode(1200, s, 'str');
return String.fromCharCode(255) + String.fromCharCode(254) + o;
}
@ -150,13 +160,13 @@ function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
if(sheet == null || sheet["!ref"] == null) return [];
var r = safe_decode_range(sheet['!ref']), rr = "", cols/*:Array<string>*/ = [], C;
var cmds/*:Array<string>*/ = [];
var dense = Array.isArray(sheet);
var dense = sheet["!data"] != null;
for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C);
for(var R = r.s.r; R <= r.e.r; ++R) {
rr = encode_row(R);
for(C = r.s.c; C <= r.e.c; ++C) {
y = cols[C] + rr;
x = dense ? (sheet[R]||[])[C] : sheet[y];
x = dense ? (sheet["!data"][R]||[])[C] : sheet[y];
val = "";
if(x === undefined) continue;
else if(x.F != null) {
@ -181,8 +191,11 @@ function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet*/ {
var o = opts || {};
var dense = _ws ? (_ws["!data"] != null) : o.dense;
if(DENSE != null && dense == null) dense = DENSE;
var offset = +!o.skipHeader;
var ws/*:Worksheet*/ = _ws || ({}/*:any*/);
var ws/*:Worksheet*/ = _ws || ({});
if(!_ws && dense) ws["!data"] = [];
var _R = 0, _C = 0;
if(ws && o.origin != null) {
if(typeof o.origin == 'number') _R = o.origin;
@ -191,7 +204,6 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
_R = _origin.r; _C = _origin.c;
}
}
var cell/*:Cell*/;
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}}/*:any*/);
if(ws['!ref']) {
var _range = safe_decode_range(ws['!ref']);
@ -202,17 +214,20 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
if(_R == -1) { _R = 0; range.e.r = js.length - 1 + offset; }
}
var hdr/*:Array<string>*/ = o.header || [], C = 0;
var ROW = [];
js.forEach(function (JS, R/*:number*/) {
if(dense && !ws["!data"][_R + R + offset]) ws["!data"][_R + R + offset] = [];
if(dense) ROW = ws["!data"][_R + R + offset];
keys(JS).forEach(function(k) {
if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k;
var v = JS[k];
var t = 'z';
var z = "";
var ref = encode_cell({c:_C + C,r:_R + R + offset});
cell = utils.sheet_get_cell(ws, ref);
var ref = dense ? "" : (encode_col(_C + C) + encode_row(_R + R + offset));
var cell/*:Cell*/ = dense ? ROW[_C + C] : ws[ref];
if(v && typeof v === 'object' && !(v instanceof Date)){
ws[ref] = v;
if(dense) ROW[_C + C] = v;
else ws[ref] = v;
} else {
if(typeof v == 'number') t = 'n';
else if(typeof v == 'boolean') t = 'b';
@ -220,11 +235,13 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
else if(v instanceof Date) {
t = 'd';
if(!o.cellDates) { t = 'n'; v = datenum(v); }
z = (o.dateNF || SSF._table[14]);
z = (cell != null && cell.z && fmt_is_date(cell.z)) ? cell.z : (o.dateNF || table_fmt[14]);
}
else if(v === null && o.nullError) { t = 'e'; v = 0; }
if(!cell) ws[ref] = cell = ({t:t, v:v}/*:any*/);
else {
if(!cell) {
if(!dense) ws[ref] = cell = ({t:t, v:v}/*:any*/);
else ROW[_C + C] = cell = ({t:t, v:v}/*:any*/);
} else {
cell.t = t; cell.v = v;
delete cell.w; delete cell.R;
if(z) cell.z = z;
@ -235,35 +252,130 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
});
range.e.c = Math.max(range.e.c, _C + hdr.length - 1);
var __R = encode_row(_R);
if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]};
if(dense && !ws["!data"][_R]) ws["!data"][_R] = [];
if(offset) for(C = 0; C < hdr.length; ++C) {
if(dense) ws["!data"][_R][C + _C] = {t:'s', v:hdr[C]};
else ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]};
}
ws['!ref'] = encode_range(range);
return ws;
}
function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ { return sheet_add_json(null, js, opts); }
var utils/*:any*/ = {
encode_col: encode_col,
encode_row: encode_row,
encode_cell: encode_cell,
encode_range: encode_range,
decode_col: decode_col,
decode_row: decode_row,
split_cell: split_cell,
decode_cell: decode_cell,
decode_range: decode_range,
format_cell: format_cell,
sheet_add_aoa: sheet_add_aoa,
sheet_add_json: sheet_add_json,
sheet_add_dom: sheet_add_dom,
aoa_to_sheet: aoa_to_sheet,
json_to_sheet: json_to_sheet,
table_to_sheet: parse_dom_table,
table_to_book: table_to_book,
sheet_to_csv: sheet_to_csv,
sheet_to_txt: sheet_to_txt,
sheet_to_json: sheet_to_json,
sheet_to_html: HTML_.from_sheet,
sheet_to_formulae: sheet_to_formulae,
sheet_to_row_object_array: sheet_to_json
};
/* get cell, creating a stub if necessary */
function ws_get_cell_stub(ws/*:Worksheet*/, R, C/*:?number*/)/*:Cell*/ {
/* A1 cell address */
if(typeof R == "string") {
if(ws["!data"] != null) {
var RC = decode_cell(R);
if(!ws["!data"][RC.r]) ws["!data"][RC.r] = [];
return ws["!data"][RC.r][RC.c] || (ws["!data"][RC.r][RC.c] = {t:'z'});
}
return ws[R] || (ws[R] = {t:'z'});
}
/* cell address object */
if(typeof R != "number") return ws_get_cell_stub(ws, encode_cell(R));
/* R and C are 0-based indices */
return ws_get_cell_stub(ws, encode_col(C||0) + encode_row(R));
}
/* find sheet index for given name / validate index */
function wb_sheet_idx(wb/*:Workbook*/, sh/*:number|string*/) {
if(typeof sh == "number") {
if(sh >= 0 && wb.SheetNames.length > sh) return sh;
throw new Error("Cannot find sheet # " + sh);
} else if(typeof sh == "string") {
var idx = wb.SheetNames.indexOf(sh);
if(idx > -1) return idx;
throw new Error("Cannot find sheet name |" + sh + "|");
} else throw new Error("Cannot find sheet |" + sh + "|");
}
/* simple blank workbook object */
function book_new()/*:Workbook*/ {
return { SheetNames: [], Sheets: {} };
}
/* add a worksheet to the end of a given workbook */
function book_append_sheet(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/, roll/*:?boolean*/)/*:string*/ {
var i = 1;
if(!name) for(; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break;
if(!name || wb.SheetNames.length >= 0xFFFF) throw new Error("Too many worksheets");
if(roll && wb.SheetNames.indexOf(name) >= 0) {
var m = name.match(/(^.*?)(\d+)$/);
i = m && +m[2] || 0;
var root = m && m[1] || name;
for(++i; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf(name = root + i) == -1) break;
}
check_ws_name(name);
if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!");
wb.SheetNames.push(name);
wb.Sheets[name] = ws;
return name;
}
/* set sheet visibility (visible/hidden/very hidden) */
function book_set_sheet_visibility(wb/*:Workbook*/, sh/*:number|string*/, vis/*:number*/) {
if(!wb.Workbook) wb.Workbook = {};
if(!wb.Workbook.Sheets) wb.Workbook.Sheets = [];
var idx = wb_sheet_idx(wb, sh);
// $FlowIgnore
if(!wb.Workbook.Sheets[idx]) wb.Workbook.Sheets[idx] = {};
switch(vis) {
case 0: case 1: case 2: break;
default: throw new Error("Bad sheet visibility setting " + vis);
}
// $FlowIgnore
wb.Workbook.Sheets[idx].Hidden = vis;
}
/* set number format */
function cell_set_number_format(cell/*:Cell*/, fmt/*:string|number*/) {
cell.z = fmt;
return cell;
}
/* set cell hyperlink */
function cell_set_hyperlink(cell/*:Cell*/, target/*:string*/, tooltip/*:?string*/) {
if(!target) {
delete cell.l;
} else {
cell.l = ({ Target: target }/*:Hyperlink*/);
if(tooltip) cell.l.Tooltip = tooltip;
}
return cell;
}
function cell_set_internal_link(cell/*:Cell*/, range/*:string*/, tooltip/*:?string*/) { return cell_set_hyperlink(cell, "#" + range, tooltip); }
/* add to cell comments */
function cell_add_comment(cell/*:Cell*/, text/*:string*/, author/*:?string*/) {
if(!cell.c) cell.c = [];
cell.c.push({t:text, a:author||"SheetJS"});
}
/* set array formula and flush related cells */
function sheet_set_array_formula(ws/*:Worksheet*/, range, formula/*:string*/, dynamic/*:boolean*/) {
var rng = typeof range != "string" ? range : safe_decode_range(range);
var rngstr = typeof range == "string" ? range : encode_range(range);
for(var R = rng.s.r; R <= rng.e.r; ++R) for(var C = rng.s.c; C <= rng.e.c; ++C) {
var cell = ws_get_cell_stub(ws, R, C);
cell.t = 'n';
cell.F = rngstr;
delete cell.v;
if(R == rng.s.r && C == rng.s.c) {
cell.f = formula;
if(dynamic) cell.D = true;
}
}
var wsr = decode_range(ws["!ref"]);
if(wsr.s.r > rng.s.r) wsr.s.r = rng.s.r;
if(wsr.s.c > rng.s.c) wsr.s.c = rng.s.c;
if(wsr.e.r < rng.e.r) wsr.e.r = rng.e.r;
if(wsr.e.c < rng.e.c) wsr.e.c = rng.e.c;
ws["!ref"] = encode_range(wsr);
return ws;
}

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

@ -1,125 +1,126 @@
if(has_buf && typeof require != 'undefined') (function() {
var strmod = require('stream');
if(!strmod) return;
var Readable = strmod.Readable;
if(!Readable) return;
var _Readable;
function set_readable(R) { _Readable = R; }
var write_csv_stream = function(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
var stream = Readable();
var o = opts == null ? {} : opts;
if(sheet == null || sheet["!ref"] == null) { stream.push(null); return stream; }
var r = safe_decode_range(sheet["!ref"]);
var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
var row/*:?string*/ = "", cols/*:Array<string>*/ = [];
o.dense = Array.isArray(sheet);
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
var rowinfo/*:Array<RowInfo>*/ = o.skipHidden && sheet["!rows"] || [];
for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
var R = r.s.r;
var BOM = false;
stream._read = function() {
if(!BOM) { BOM = true; return stream.push("\uFEFF"); }
while(R <= r.e.r) {
++R;
if ((rowinfo[R-1]||{}).hidden) continue;
row = make_csv_row(sheet, r, R-1, cols, fs, rs, FS, o);
if(row != null) {
if(o.strip) row = row.replace(endregex,"");
stream.push(row + RS);
break;
}
}
if(R > r.e.r) return stream.push(null);
};
return stream;
};
var write_html_stream = function(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*/) {
var stream = Readable();
var o = opts || {};
var header = o.header != null ? o.header : HTML_.BEGIN;
var footer = o.footer != null ? o.footer : HTML_.END;
stream.push(header);
var r = decode_range(ws['!ref']);
o.dense = Array.isArray(ws);
stream.push(HTML_._preamble(ws, r, o));
var R = r.s.r;
var end = false;
stream._read = function() {
if(R > r.e.r) {
if(!end) { end = true; stream.push("</table>" + footer); }
return stream.push(null);
}
while(R <= r.e.r) {
stream.push(HTML_._row(ws, r, R, o));
++R;
break;
}
};
return stream;
};
var write_json_stream = function(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
var stream = Readable({objectMode:true});
if(sheet == null || sheet["!ref"] == null) { stream.push(null); return stream; }
var val = {t:'n',v:0}, header = 0, offset = 1, hdr/*:Array<any>*/ = [], v=0, vv="";
var r = {s:{r:0,c:0},e:{r:0,c:0}};
var o = opts || {};
var range = o.range != null ? o.range : sheet["!ref"];
if(o.header === 1) header = 1;
else if(o.header === "A") header = 2;
else if(Array.isArray(o.header)) header = 3;
switch(typeof range) {
case 'string': r = safe_decode_range(range); break;
case 'number': r = safe_decode_range(sheet["!ref"]); r.s.r = range; break;
default: r = range;
}
if(header > 0) offset = 0;
var rr = encode_row(r.s.r);
var cols/*:Array<string>*/ = [];
var counter = 0;
var dense = Array.isArray(sheet);
var R = r.s.r, C = 0, CC = 0;
if(dense && !sheet[R]) sheet[R] = [];
for(C = r.s.c; C <= r.e.c; ++C) {
cols[C] = encode_col(C);
val = dense ? sheet[R][C] : sheet[cols[C] + rr];
switch(header) {
case 1: hdr[C] = C - r.s.c; break;
case 2: hdr[C] = cols[C]; break;
case 3: hdr[C] = o.header[C - r.s.c]; break;
default:
if(val == null) val = {w: "__EMPTY", t: "s"};
vv = v = format_cell(val, null, o);
counter = 0;
for(CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter);
hdr[C] = vv;
function write_csv_stream(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
var stream = _Readable();
var o = opts == null ? {} : opts;
if(sheet == null || sheet["!ref"] == null) { stream.push(null); return stream; }
var r = safe_decode_range(sheet["!ref"]);
var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
var row/*:?string*/ = "", cols/*:Array<string>*/ = [];
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
var rowinfo/*:Array<RowInfo>*/ = o.skipHidden && sheet["!rows"] || [];
for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
var R = r.s.r;
var BOM = false, w = 0;
stream._read = function() {
if(!BOM) { BOM = true; return stream.push("\uFEFF"); }
while(R <= r.e.r) {
++R;
if ((rowinfo[R-1]||{}).hidden) continue;
row = make_csv_row(sheet, r, R-1, cols, fs, rs, FS, o);
if(row != null) {
if(o.strip) row = row.replace(endregex,"");
if(row || (o.blankrows !== false)) return stream.push((w++ ? RS : "") + row);
}
}
R = r.s.r + offset;
stream._read = function() {
if(R > r.e.r) return stream.push(null);
while(R <= r.e.r) {
//if ((rowinfo[R-1]||{}).hidden) continue;
var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o);
++R;
if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) {
stream.push(row.row);
break;
return stream.push(null);
};
return stream;
}
function write_html_stream(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*/) {
var stream = _Readable();
var o = opts || {};
var header = o.header != null ? o.header : HTML_BEGIN;
var footer = o.footer != null ? o.footer : HTML_END;
stream.push(header);
var r = decode_range(ws['!ref']);
stream.push(make_html_preamble(ws, r, o));
var R = r.s.r;
var end = false;
stream._read = function() {
if(R > r.e.r) {
if(!end) { end = true; stream.push("</table>" + footer); }
return stream.push(null);
}
while(R <= r.e.r) {
stream.push(make_html_row(ws, r, R, o));
++R;
break;
}
};
return stream;
}
function write_json_stream(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
var stream = _Readable({objectMode:true});
if(sheet == null || sheet["!ref"] == null) { stream.push(null); return stream; }
var val = {t:'n',v:0}, header = 0, offset = 1, hdr/*:Array<any>*/ = [], v=0, vv="";
var r = {s:{r:0,c:0},e:{r:0,c:0}};
var o = opts || {};
var range = o.range != null ? o.range : sheet["!ref"];
if(o.header === 1) header = 1;
else if(o.header === "A") header = 2;
else if(Array.isArray(o.header)) header = 3;
switch(typeof range) {
case 'string': r = safe_decode_range(range); break;
case 'number': r = safe_decode_range(sheet["!ref"]); r.s.r = range; break;
default: r = range;
}
if(header > 0) offset = 0;
var rr = encode_row(r.s.r);
var cols/*:Array<string>*/ = [];
var counter = 0;
var dense = sheet["!data"] != null;
var R = r.s.r, C = 0;
var header_cnt = {};
if(dense && !sheet["!data"][R]) sheet["!data"][R] = [];
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
var rowinfo/*:Array<RowInfo>*/ = o.skipHidden && sheet["!rows"] || [];
for(C = r.s.c; C <= r.e.c; ++C) {
if(((colinfo[C]||{}).hidden)) continue;
cols[C] = encode_col(C);
val = dense ? sheet["!data"][R][C] : sheet[cols[C] + rr];
switch(header) {
case 1: hdr[C] = C - r.s.c; break;
case 2: hdr[C] = cols[C]; break;
case 3: hdr[C] = o.header[C - r.s.c]; break;
default:
if(val == null) val = {w: "__EMPTY", t: "s"};
vv = v = format_cell(val, null, o);
counter = header_cnt[v] || 0;
if(!counter) header_cnt[v] = 1;
else {
do { vv = v + "_" + (counter++); } while(header_cnt[vv]); header_cnt[v] = counter;
header_cnt[vv] = 1;
}
hdr[C] = vv;
}
}
R = r.s.r + offset;
stream._read = function() {
while(R <= r.e.r) {
if ((rowinfo[R-1]||{}).hidden) continue;
var row = make_json_row(sheet, r, R, cols, header, hdr, o);
++R;
if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) {
stream.push(row.row);
return;
}
};
return stream;
}
return stream.push(null);
};
return stream;
}
XLSX.stream = {
to_json: write_json_stream,
to_html: write_html_stream,
to_csv: write_csv_stream
};
})();
var __stream = {
to_json: write_json_stream,
to_html: write_html_stream,
to_csv: write_csv_stream,
set_readable: set_readable
};

@ -11,4 +11,10 @@ XLSX.utils = utils;
XLSX.writeXLSX = writeSyncXLSX;
XLSX.writeFileXLSX = writeFileSyncXLSX;
XLSX.SSF = SSF;
if(typeof __stream !== "undefined") XLSX.stream = __stream;
if(typeof CFB !== "undefined") XLSX.CFB = CFB;
if(typeof require !== "undefined") {
var strmod = require('stream');
if((strmod||{}).Readable) set_readable(strmod.Readable);
try { _fs = require('fs'); } catch(e) {}
}

@ -1,27 +0,0 @@
{
"root": "./misc/docs",
"title": "SheetJS js-xlsx",
"author": "sheetjs",
"gitbook": "3.2.2",
"plugins": ["anchorjs", "ga", "sidebar-ad", "-sharing", "-search", "advanced-emoji", "-lunr"],
"pluginsConfig": {
"anchorjs": {
"icon": "#",
"placement": "left",
"visible": "always"
},
"ga": {
"token": "UA-36810333-1"
},
"sidebar-ad": {
"imageUrl": "http://oss.sheetjs.com/assets/img/logo.png",
"url": "http://sheetjs.com"
},
"theme-default": {
"showLevel": false,
"styles": {
"website": "style.css"
}
}
}
}

@ -17,42 +17,62 @@ can be installed with Bash on Windows or with `cygwin`.
### Included Demos
**Frameworks and APIs**
- [`angularjs`](angular/)
- [`angular and ionic`](angular2/)
- [`knockout`](knockout/)
- [`meteor`](meteor/)
- [`react and react-native`](react/)
- [`vue 2.x and weex`](vue/)
- [`XMLHttpRequest and fetch`](xhr/)
- [`nodejs server`](server/)
- [`databases and key/value stores`](database/)
- [`typed arrays and math`](array/)
**JavaScript APIs**
- [`XMLHttpRequest and fetch`](https://docs.sheetjs.com/docs/demos/network)
- [`Clipboard Data`](https://docs.sheetjs.com/docs/demos/clipboard)
- [`Typed Arrays for Machine Learning`](https://docs.sheetjs.com/docs/demos/ml)
- [`LocalStorage and SessionStorage`](https://docs.sheetjs.com/docs/demos/database#localstorage-and-sessionstorage)
- [`Web SQL Database`](https://docs.sheetjs.com/docs/demos/database#websql)
- [`IndexedDB`](https://docs.sheetjs.com/docs/demos/database#indexeddb)
**Bundlers and Tooling**
- [`browserify`](browserify/)
- [`fusebox`](fusebox/)
- [`parcel`](parcel/)
- [`requirejs`](requirejs/)
- [`rollup`](rollup/)
- [`systemjs`](systemjs/)
- [`typescript`](typescript/)
- [`webpack 2.x`](webpack/)
**Frameworks**
- [`Angular 2+ and Ionic`](https://docs.sheetjs.com/docs/demos/angular)
- [`React`](https://docs.sheetjs.com/docs/demos/react)
- [`VueJS`](https://docs.sheetjs.com/docs/demos/vue)
- [`Angular.JS`](https://docs.sheetjs.com/docs/demos/legacy#angularjs)
- [`Knockout`](https://docs.sheetjs.com/docs/demos/legacy#knockoutjs)
**Front-End UI Components**
- [`canvas-datagrid`](https://docs.sheetjs.com/docs/demos/grid#canvas-datagrid)
- [`x-spreadsheet`](https://docs.sheetjs.com/docs/demos/grid#x-spreadsheet)
- [`react-data-grid`](https://docs.sheetjs.com/docs/demos/grid#react-data-grid)
- [`vue3-table-lite`](https://docs.sheetjs.com/docs/demos/grid#vue3-table-lite)
- [`angular-ui-grid`](https://docs.sheetjs.com/docs/demos/grid#angular-ui-grid)
**Platforms and Integrations**
- [`deno`](deno/)
- [`electron application`](electron/)
- [`nw.js application`](nwjs/)
- [`Chrome / Chromium extensions`](chrome/)
- [`Download a Google Sheet locally`](google-sheet/)
- [`Adobe ExtendScript`](extendscript/)
- [`Headless Browsers`](headless/)
- [`canvas-datagrid`](datagrid/)
- [`x-spreadsheet`](xspreadsheet/)
- [`Swift JSC and other engines`](altjs/)
- [`"serverless" functions`](function/)
- [`internet explorer`](oldie/)
- [`Command-Line Tools`](https://docs.sheetjs.com/docs/demos/cli)
- [`iOS and Android Mobile Applications`](https://docs.sheetjs.com/docs/demos/mobile)
- [`NodeJS Server-Side Processing`](https://docs.sheetjs.com/docs/demos/server#nodejs)
- [`Content Management and Static Sites`](https://docs.sheetjs.com/docs/demos/content)
- [`Electron`](https://docs.sheetjs.com/docs/demos/desktop#electron)
- [`NW.js`](https://docs.sheetjs.com/docs/demos/desktop#nwjs)
- [`Tauri`](https://docs.sheetjs.com/docs/demos/desktop#tauri)
- [`Chrome and Chromium Extensions`](https://docs.sheetjs.com/docs/demos/chromium)
- [`Google Sheets API`](https://docs.sheetjs.com/docs/demos/gsheet)
- [`ExtendScript for Adobe Apps`](https://docs.sheetjs.com/docs/demos/extendscript)
- [`NetSuite SuiteScript`](https://docs.sheetjs.com/docs/demos/netsuite)
- [`SalesForce Lightning Web Components`](https://docs.sheetjs.com/docs/demos/salesforce)
- [`Excel JavaScript API`](https://docs.sheetjs.com/docs/demos/excel)
- [`Headless Automation`](https://docs.sheetjs.com/docs/demos/headless)
- [`Other JavaScript Engines`](https://docs.sheetjs.com/docs/demos/engines)
- [`Azure Functions and Storage`](https://docs.sheetjs.com/docs/demos/azure)
- [`Amazon Web Services`](https://docs.sheetjs.com/docs/demos/aws)
- [`Databases and Structured Data Stores`](https://docs.sheetjs.com/docs/demos/database)
- [`NoSQL and Unstructured Data Stores`](https://docs.sheetjs.com/docs/demos/nosql)
- [`Legacy Internet Explorer`](https://docs.sheetjs.com/docs/demos/legacy#internet-explorer)
Other examples are included in the [showcase](demos/showcase/).
**Bundlers and Tooling**
- [`browserify`](https://docs.sheetjs.com/docs/demos/bundler#browserify)
- [`bun`](https://docs.sheetjs.com/docs/demos/bundler#bun)
- [`esbuild`](https://docs.sheetjs.com/docs/demos/bundler#esbuild)
- [`parcel`](https://docs.sheetjs.com/docs/demos/bundler#parcel)
- [`requirejs`](https://docs.sheetjs.com/docs/demos/bundler#requirejs)
- [`rollup`](https://docs.sheetjs.com/docs/demos/bundler#rollup)
- [`snowpack`](https://docs.sheetjs.com/docs/demos/bundler#snowpack)
- [`swc`](https://docs.sheetjs.com/docs/demos/bundler#swc)
- [`systemjs`](https://docs.sheetjs.com/docs/demos/bundler#systemjs)
- [`vite`](https://docs.sheetjs.com/docs/demos/bundler#vite)
- [`webpack`](https://docs.sheetjs.com/docs/demos/bundler#webpack)
- [`wmr`](https://docs.sheetjs.com/docs/demos/bundler#wmr)
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -1,10 +0,0 @@
sheetjs.*
SheetJSSwift
duk*
*.class
*.jar
rhino
shim.min.js
xlsx.*.js
payload.js
goja

@ -1,3 +0,0 @@
disabled_rules:
- trailing_semicolon
- identifier_name

@ -1,60 +0,0 @@
.PHONY: all
all: duktape nashorn rhinojs swift goja
.PHONY: base
base:
if [ ! -e sheetjs.xlsx ]; then node ../../tests/write.js; fi
if [ ! -e xlsx.full.min.js ]; then cp ../../dist/xlsx.full.min.js .; fi
if [ ! -e shim.min.js ]; then cp ../../dist/shim.min.js .; fi
.PHONY: duk
duk: base
bash ./duktape.sh
gcc -std=c99 -Wall -osheetjs.duk sheetjs.duk.c duktape.c -lm
.PHONY: duktape
duktape: duk ## duktape demo
for ext in xlsx xlsb biff8.xls xml.xls; do ./sheetjs.duk sheetjs.$$ext; done
.PHONY: nashorn
nashorn: base ## nashorn demo
jjs nashorn.js
.PHONY: swift
swift: base ## swift demo
swiftc SheetJSCore.swift main.swift -o SheetJSSwift
./SheetJSSwift
.PHONY: goja
goja: base ## goja demo
go build goja.go
for ext in xlsx xlsb biff8.xls xml.xls; do ./goja sheetjs.$$ext; done
.PHONY: chakra
chakra: base ## Chakra demo
node -pe "fs.writeFileSync('payload.js', 'var payload = \"' + fs.readFileSync('sheetjs.xlsx').toString('base64') + '\";')"
cat global.js xlsx.full.min.js payload.js chakra.js > xlsx.chakra.js
chakra ./xlsx.chakra.js
.PHONY: rhinojs ## rhino demo
rhinojs: base SheetJSRhino.class
for ext in xlsx xlsb biff8.xls xml.xls; do java -cp .:SheetJS.jar:rhino.jar SheetJSRhino sheetjs.$$ext; done
RHDEPS=$(filter-out SheetJSRhino.class,$(patsubst %.java,%.class,$(wildcard com/sheetjs/*.java)))
$(RHDEPS): %.class: %.java rhino.jar
javac -cp .:SheetJS.jar:rhino.jar $*.java
SheetJSRhino.class: $(RHDEPS)
jar -cf SheetJS.jar $^ xlsx.full.min.js
javac -cp .:SheetJS.jar:rhino.jar SheetJSRhino.java
rhino.jar:
if [ ! -e rhino ]; then git clone --depth=1 https://github.com/mozilla/rhino; fi
#if [ ! -e rhino/build/rhino*/js.jar ]; then cd rhino; ant jar; fi
#cp rhino/build/rhino*/js.jar rhino.jar
if [ ! -e rhino/buildGradle/libs/rhino-[0-1]*.jar ]; then cd rhino; ./gradlew jar; fi
cp rhino/buildGradle/libs/rhino-[0-9]*.jar rhino.jar
.PHONY: clean
clean:
rm SheetJS.jar *.class com/sheetjs/*.class

@ -1,186 +1,7 @@
# Other JS Engines and Deployments
There are many JS engines and deployments outside of web browsers. NodeJS is the
most popular deployment, but there are many others for special use cases. Some
optimize for low overhead and others optimize for ease of embedding within other
applications. Since it was designed for ES3 engines, the library can be used in
those settings! This demo tries to demonstrate a few alternative deployments.
[The new demo](https://docs.sheetjs.com/docs/demos/engines)
includes more detailed instructions and more JS engines.
Some engines provide no default global object. To create a global reference:
```js
var global = (function(){ return this; }).call(null);
```
## Swift + JavaScriptCore
iOS and OSX ship with the JavaScriptCore framework for running JS scripts from
Swift and Objective-C. Hybrid function invocation is tricky, but explicit data
passing is straightforward. The demo shows a standalone example for OSX. For
playgrounds, the library should be copied to shared playground data directory
(usually `~/Documents/Shared Playground Data`):
```swift
/* This only works in a playground, see SheetJSCore.swift for standalone use */
import JavaScriptCore;
import PlaygroundSupport;
/* build path variable for the library */
let shared_dir = PlaygroundSupport.playgroundSharedDataDirectory;
let lib_path = shared_dir.appendingPathComponent("xlsx.full.min.js");
/* prepare JS context */
var context: JSContext! = JSContext();
var src = "var global = (function(){ return this; }).call(null);";
context.evaluateScript(src);
/* load library */
var lib = try? String(contentsOf: lib_path);
context.evaluateScript(lib);
let XLSX: JSValue! = context.objectForKeyedSubscript("XLSX");
/* to verify the library was loaded, get the version string */
let XLSXversion: JSValue! = XLSX.objectForKeyedSubscript("version")
var version = XLSXversion.toString();
```
Binary strings can be passed back and forth using `String.Encoding.isoLatin1`:
```swift
/* parse sheetjs.xls */
let file_path = shared_dir.appendingPathComponent("sheetjs.xls");
let data: String! = try String(contentsOf: file_path, encoding: String.Encoding.isoLatin1);
context.setObject(data, forKeyedSubscript: "payload" as (NSCopying & NSObjectProtocol));
src = "var wb = XLSX.read(payload, {type:'binary'});";
context.evaluateScript(src);
/* write to sheetjsw.xlsx */
let out_path = shared_dir.appendingPathComponent("sheetjsw.xlsx");
src = "var out = XLSX.write(wb, {type:'binary', bookType:'xlsx'})";
context.evaluateScript(src);
let outvalue: JSValue! = context.objectForKeyedSubscript("out");
var out: String! = outvalue.toString();
try? out.write(to: out_path, atomically: false, encoding: String.Encoding.isoLatin1);
```
## Nashorn
Nashorn ships with Java 8. It includes a command-line tool `jjs` for running JS
scripts. It is somewhat limited but does offer access to the full Java runtime.
The `load` function in `jjs` can load the minified source directly:
```js
var global = (function(){ return this; }).call(null);
load('xlsx.full.min.js');
```
The Java `nio` API provides the `Files.readAllBytes` method to read a file into
a byte array. To use in `XLSX.read`, the demo copies the bytes into a plain JS
array and calls `XLSX.read` with type `"array"`.
## Rhino
[Rhino](http://www.mozilla.org/rhino) is an ES3+ engine written in Java. The
`SheetJSRhino` class and `com.sheetjs` package show a complete JAR deployment,
including the full XLSX source.
Due to code generation errors, optimization must be turned off:
```java
Context context = Context.enter();
context.setOptimizationLevel(-1);
```
## ChakraCore
ChakraCore is an embeddable JS engine written in C++. The library and binary
distributions include a command-line tool `chakra` for running JS scripts.
The simplest way to interact with the engine is to pass Base64 strings. The make
target builds a very simple payload with the data.
## Duktape
[Duktape](http://duktape.org/) is an embeddable JS engine written in C. The
amalgamation makes integration extremely simple! It supports `Buffer` natively
but should be sliced before processing:
```C
/* parse a C char array as a workbook object */
duk_push_external_buffer(ctx);
duk_config_buffer(ctx, -1, buf, len);
duk_put_global_string(ctx, "buf");
duk_eval_string_noresult("workbook = XLSX.read(buf.slice(0, buf.length), {type:'buffer'});");
/* write a workbook object to a C char array */
duk_eval_string(ctx, "XLSX.write(workbook, {type:'array', bookType:'xlsx'})");
duk_size_t sz;
char *buf = (char *)duk_get_buffer_data(ctx, -1, sz);
duk_pop(ctx);
```
## QuickJS
QuickJS is an embeddable JS engine written in C. It provides a separate set of
functions for interacting with the filesystem and the global object. It can run
the browser dist build.
The `global` object is available as `std.global`. To make it visible to the
loader, create a reference to itself:
```js
std.global.global = std.global;
std.loadScript("xlsx.full.min.js");
```
The filesystem interaction mirrors POSIX, including separate allocations:
```js
/* read file */
var rh = std.open(filename, "rb"); rh.seek(0, std.SEEK_END);
var sz = rh.tell(); rh.seek();
var ab = new ArrayBuffer(sz); rh.read(ab, 0, sz); rh.close();
var wb = XLSX.read(ab, {type: 'array'});
/* write file */
var ab = XLSX.write(wb, {type: 'array'});
var wh = std.open("sheetjs.qjs.xlsx", "wb");
wh.write(out, 0, ab.byteLength); wh.close();
```
## Goja
Goja is a pure Go implementation of ECMAScript 5. `[]byte` should be converted
to a binary string in the engine:
```go
/* read file */
data, _ := ioutil.ReadFile("sheetjs.xlsx")
/* load into engine */
vm.Set("buf", data)
/* convert to binary string */
_, _ = vm.RunString("var bstr = ''; for(var i = 0; i < buf.length; ++i) bstr += String.fromCharCode(buf[i]);")
/* parse */
wb, _ = vm.RunString("wb = XLSX.read(bstr, {type:'binary', cellNF:true});")
```
On the write side, `"base64"` strings can be decoded in Go:
```go
b64str, _ := vm.RunString("XLSX.write(wb, {type:'base64', bookType:'xlsx'})")
buf, _ := base64.StdEncoding.DecodeString(b64str.String())
_ = ioutil.WriteFile("sheetjs.xlsx", buf, 0644)
```
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

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