Compare commits

...

203 Commits

Author SHA1 Message Date
SheetJS 947a5178bd ssf format NaN and Infinity values 2024-04-27 19:49:12 -04:00
Ben Halverson 87a695747e docs: ✏️ Fixed broken links in contributing.md 2024-04-10 02:09:14 -07:00
SheetJS a0bed2a97d version bump 0.20.2
see https://regexide.com for more details
2024-04-04 21:30:28 -04:00
SheetJS 0941ff97a3 dta v0.0.2 2024-03-22 00:39:09 -04:00
SheetJS e4a66516e4 remove flow array comment workarounds
- XLSB use #REF! for unsupported defined name ref (fixes #3059 h/t @NenadC2)
2024-02-02 01:52:14 -05:00
SheetJS d4d4ff3da2 SYLK error cells read/write (fixes #3049) 2024-01-10 04:54:10 -05:00
SheetJS 29d46c07a8 version bump 0.20.1 2023-12-05 03:19:42 -05:00
SheetJS 9199c2600c dta initial 2023-11-13 06:13:07 -05:00
SheetJS cd5fafda32 ssf v0.11.3 2023-10-23 21:22:11 -04:00
David Szajngarten c8e6d5c20f ssf seconds/hours time rounding 2023-10-23 13:25:42 -04:00
SheetJS ad0fb7766b import and export blank worksheets 2023-10-17 04:53:37 -04:00
SheetJS 4cc980975b QPW string formula results
- mujs-compatible regices
- NUMBERS use row offsets (fixes #3009 h/t @relaxsnow)
2023-10-15 23:03:39 -04:00
SheetJS 432ac1fda7 xlsx-cli v1.1.4 2023-10-11 16:22:42 -04:00
MarlousKottenhagen 53283217e9 xlsx-cli support dateFormat option (#3005)
Co-authored-by: Marlous Kottenhagen <m.kottenhagen@bigmile.eu>
Reviewed-on: #3005
Co-authored-by: MarlousKottenhagen <marlouskottenhagen@noreply.git.sheetjs.com>
Co-committed-by: MarlousKottenhagen <marlouskottenhagen@noreply.git.sheetjs.com>
2023-10-10 06:50:32 +00:00
SheetJS 248108b667 `dense` types 2023-09-21 04:12:13 -04:00
julitork 766fc4f4d2 allow rawNumber override raw option 2023-08-29 16:04:32 +03:00
SheetJS 485a4f30f1 set CSV formula cell value to raw fmla text 2023-08-23 13:38:14 -04:00
SheetJS 68cce77d23 package.json exports (fixes #2977 h/t @stof) 2023-08-20 21:01:07 -04:00
sheetjs c0b9e229a0 Delete .github/ISSUE_TEMPLATE/config.yml 2023-08-18 15:26:54 +00:00
SheetJS 955543147d version bump 0.20.0 2023-06-23 05:48:47 -04:00
SheetJS 36c5b7c0f5 NUMBERS read/write threaded comments 2023-06-14 03:47:51 -04:00
SheetJS 6e260c9185 cell comments
- `sheet_to_json` handle arrays (h/t AaronWoodrow)
- XLS parse comment visibility (h/t Godrules500)
- chrome manifest v3 writeFile support
- raw v8 (no TextEncoder/TextDecoder) optimization
- handle empty shared formula body (h/t florian)
2023-06-13 00:49:18 -04:00
SheetJS d3a480750b NUMBERS read/write external links 2023-05-13 01:23:26 -04:00
SheetJS 5b33acfaf4 parse self-closing text:p uof:文本串 (fixes #2927) 2023-04-30 03:57:30 -04:00
SheetJS b68eaed726 Export NaN/Infinity to error cells (fixes #2897) 2023-04-23 03:58:36 -04:00
SheetJS 333e4e40f9 version bump 0.19.3 2023-04-17 23:39:28 -04:00
SheetJS af8e3d9171 build fixes for macOS Ventura 2023-04-14 03:51:02 -04:00
Vsevolod Kokorin dca90c8024 XLSX Ensure comment address is valid 2023-04-12 03:48:54 -04:00
SheetJS c06a32043f Add ESM helper methods to CJS build (fixes #2909) 2023-04-10 01:15:44 -04:00
SheetJS ffbea71bc2 XLS ExternSheet record (fixes #2907) 2023-04-05 15:34:55 -04:00
SheetJS 16dd8a6eae UTF16LE sans codepage (fixes #2898 h/t @brismuth) 2023-03-15 04:17:09 -04:00
SheetJS 0577bb7a45 version bump 0.19.2 2023-01-25 16:17:34 -05:00
SheetJS b150dea21d denoized otorp [ci skip] 2023-01-06 02:37:53 -05:00
SheetJS e9cf1ad0fb ignore unexpected attributes in rich text part
Co-authored-by: colin4 <colin4@noreply.sheetjs.com>
2023-01-04 12:35:13 -05:00
SheetJS 5141222c24 `sheet_to_json` type include `origin` option
Co-authored-by: Hulusi <chsdwn@noreply.sheetjs.com>
2023-01-01 16:53:44 -05:00
SheetJS 51a8619000 version bump 0.19.1 2022-11-17 04:35:34 -05:00
SheetJS e7e129e417 type fix (fixes #2828 h/t @younes-io) 2022-11-16 14:03:42 -05:00
SheetJS df48489211 Numbers 12.2 skip ActivityStream.iwa 2022-11-06 21:58:41 -05:00
SheetJS 050f66ce1b version bump 0.19.0 2022-10-23 21:05:59 -04:00
SheetJS 2f329b64e2 DBF truncate numeric fields 2022-10-04 20:09:43 -04:00
SheetJS 515d1c6f2e mini refresh [ci skip] 2022-10-04 16:50:55 -04:00
SheetJS 654d6f98c3 stringify all 's' cell values (fixes #2795) 2022-09-28 23:08:10 -04:00
SheetJS 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
SheetJS 81b231d866 version bump 0.18.12 2022-09-22 05:06:45 -04:00
SheetJS 1491302aa4 package.json exports types 2022-09-21 18:17:14 -04:00
SheetJS 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
SheetJS 6a5be04e3d Ś╫êëτ⌡ś and Š╫ěéτ⌡š 2022-09-09 16:59:22 -04:00
SheetJS e90a61bf09 version bump 0.18.11 2022-09-06 02:18:12 -04:00
SheetJS 26cbfe37be DBF write encoding (fixes #2781 h/t @ZJS248) 2022-09-06 00:02:39 -04:00
SheetJS df0e7b5f25 NUMBERS duration cell number format 2022-09-04 17:51:49 -04:00
SheetJS 6c9010f9d1 comment fallback (fixes #2779 h/t @AbhinanduReddy) 2022-09-02 03:30:10 -04:00
SheetJS 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
SheetJS 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
SheetJS 917a69e394 XLSX custprops strip ns [ci skip] 2022-08-15 01:20:14 -04:00
SheetJS 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
SheetJS fdbbf2d6bf precise time parse (h/t @ragearino @MyAddonsDev ) 2022-08-06 22:50:58 -04:00
SheetJS c02eb14255 stox skip blank worksheets [ci skip] 2022-08-03 12:40:26 -04:00
SheetJS d55b7a3063 numbers OperationStorage iwa warning 2022-07-31 19:48:04 -04:00
SheetJS ba94ffba35 version bump 0.18.10 2022-07-25 22:27:52 -04:00
SheetJS 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
SheetJS 6c41339fc0 proper subarray resolution 2022-07-16 20:02:22 -04:00
SheetJS dbc30ef188 numbers parser prefer subarray 2022-07-13 06:10:24 -04:00
SheetJS ef6d3086ac bun test 2022-07-12 00:30:22 -04:00
SheetJS fad98cf64a bun utf16le workaround 2022-07-10 00:12:15 -04:00
SheetJS ad1ce0d9b0 parsers expose original book type 2022-07-08 18:45:00 -04:00
SheetJS 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
SheetJS ecfa614dd8 parse icloud.com numbers exports 2022-07-05 02:52:55 -04:00
SheetJS ee8b37b3a6 ODS XML Parse nit 2022-06-27 02:02:21 -04:00
SheetJS 4a31cb9810 warn on codepage override in mini build [ci skip] 2022-06-22 15:59:45 -04:00
SheetJS a373597294 version bump 0.18.9 2022-06-09 00:45:22 -04:00
SheetJS 08f5678c98 ODS read/write number formats 2022-06-08 18:06:49 -04:00
SheetJS 4cc0412154 roundtrip 1904 date setting 2022-06-06 19:10:33 -04:00
SheetJS 83ddb4c120 unified autofilter defined name sync on export 2022-05-30 04:42:10 -04:00
SheetJS 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
SheetJS e6ae86df55 XLSB/ODS write defined names 2022-05-24 21:45:55 -04:00
SheetJS 2022f7f4b0 version bump 0.18.8: dateless meridien time values 2022-05-22 19:51:41 -04:00
SheetJS 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
SheetJS 9f8ec25845 refresh browser tests 2022-05-17 17:48:05 -04:00
SheetJS 0b72cc592b wsl build sequence fixes 2022-05-16 21:26:22 -04:00
SheetJS 5d49b7326d sheet_set_array_formula adjust range 2022-05-15 23:39:11 -04:00
SheetJS e43071fc64 more lotus 1-2-3 formula functions 2022-05-10 04:02:52 -04:00
SheetJS 2ff31276b0 slk defined name parse 2022-05-09 02:49:17 -04:00
SheetJS 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
SheetJS 87e826f299 SYLK process 1904 dates (fixes #1545 h/t @Slayess) 2022-04-27 04:26:35 -04:00
SheetJS eee39946e3 version bump 0.18.7 2022-04-25 18:13:46 -04:00
SheetJS 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
SheetJS 8124fcbae0 newline normalization 2022-04-20 13:31:11 -04:00
SheetJS 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
SheetJS af421e3161 xlsx-cli 1.1.3 [ci skip] 2022-04-16 02:18:29 -04:00
SheetJS 79e2773b58 x-spreadsheet demo [ci skip] fixes #2656 2022-04-15 19:06:45 -04:00
SheetJS ed18acd63d version bump 0.18.6 2022-04-14 03:27:38 -04:00
SheetJS b1dca24a0b next.js demo refresh [ci skip] 2022-04-12 07:59:15 -04:00
SheetJS 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
SheetJS 623364a148 extendscript workaround for esbuild bug (#2629) 2022-03-27 15:02:51 -04:00
SheetJS 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
SheetJS 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
SheetJS 0f0b3de821 popping IIFEs to appease rollup tree shaking 2022-03-22 16:19:05 -04:00
SheetJS 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
SheetJS 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
SheetJS 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
SheetJS 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
SheetJS 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
SheetJS 0044f3be82 clean cptable global pollution 2022-03-11 01:16:24 -05:00
SheetJS 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
SheetJS b738e5d3f1 pulling ssf into main project [ci skip] 2022-03-09 06:31:53 -05:00
SheetJS d97fce4424 ssf repo reorg 2022-03-09 06:28:19 -05:00
SheetJS 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
SheetJS 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
SheetJS 6ede9dcfb9 xlsx-cli v1.1.2 [ci skip] 2022-03-03 14:11:20 -05:00
SheetJS e71eeda4d2 updated travis tests
Co-authored-by: Garrett Luu <garrettluu131@gmail.com>
2020-07-02 02:24:11 -04:00
SheetJS 6cdd7ac629 ssf-cli 1.0.1 [ci skip] 2020-06-27 20:21:36 -04:00
SheetJS 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
SheetJS 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
SheetJS 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
SheetJS 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
SheetJS fefb415467 fmt_is_date properly handle string literals 2020-01-25 21:32:32 -05:00
SheetJS 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
SheetJS f6de1799c4 version bump 0.10.2: infrastructure
- typescript definitions
- fixed vulnerable regexes (h/t @davisjam)
2018-02-20 22:35:31 -05:00
SheetJS 71f827c4fa version bump 0.10.1: fixed deps 2017-07-31 22:28:37 -04:00
SheetJS 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
SheetJS 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
SheetJS 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
SheetJS 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
SheetJS 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
SheetJS 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
SheetJS ecb4515847 Use `charAt` for IE6-8 compat (fixes #9) 2017-03-24 01:07:28 -04:00
SheetJS 56b414b496 increased travis timeout 2017-03-21 10:31:33 -04:00
SheetJS 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
SheetJS 695452bffb flow typing and cleanup 2017-03-12 03:34:36 -04:00
SheetJS 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
SheetJS 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
SheetJS 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
SheetJS 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
SheetJS 82ead811b7 README fix CI badge [ci skip] 2014-04-25 11:27:27 -07:00
SheetJS 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
SheetJS 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
SheetJS 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
SheetJS 95b338304b whitespace and semicolons to satiate jshint 2014-03-29 03:34:43 -07:00
SheetJS af23ae85b4 version bump 0.6.2: special formats
- zip + 4
- telephone
- better handling of conditional formats
2014-03-29 02:41:59 -07:00
SheetJS 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
SheetJS e2b0e6e0de coveralls target uses min test
coveralls target was timing out on travis :/
2014-03-27 14:31:10 -07:00
SheetJS 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
SheetJS 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
SheetJS 4404d216c2 version bump 0.5.11: improper fractions
- ??/?? and friends
- stub for 'g' date format
2014-03-25 01:48:52 -07:00
SheetJS b2940bac21 version bump 0.5.10: support trailing commas 2014-03-25 00:42:14 -07:00
SheetJS 0b3732c443 version bump 0.5.9: strip leading # before 0 2014-03-18 20:58:45 -07:00
SheetJS 02285784a7 adding coveralls badge [ci skip] 2014-02-17 04:28:06 -05:00
SheetJS 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
SheetJS 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
SheetJS 71a974653d added gh-pages demo 2014-02-11 00:46:45 -05:00
SheetJS 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
SheetJS 2f9e0dbc01 version bump 0.5.5: eliminate double-negatives 2014-01-29 20:43:21 -05:00
SheetJS e5fe385335 version bump 0.5.4: empty text is empty 2014-01-28 20:02:46 -05:00
SheetJS 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
SheetJS 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
SheetJS 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
SheetJS 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
SheetJS acdc0d5fff support for LO Calc's 'GENERAL' format 2014-01-03 11:45:11 -05:00
SheetJS 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
SheetJS 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
SheetJS 5a49d84ae6 version bump 0.3.1: vagaries in the general format 2013-12-16 19:03:07 -05:00
SheetJS 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
SheetJS e1b753f797 tweaking general format
[ci skip]
2013-12-15 01:13:59 -05:00
SheetJS 30c8c4c071 version bump 0.2.3: negative number love 2013-12-14 23:50:54 -05:00
SheetJS cfb6a520ae version bump 0.2.2: fraction love 2013-12-14 21:36:52 -05:00
SheetJS 22f04832e3 version bump 0.2.1: more support for implied types 2013-12-13 22:28:57 -05:00
SheetJS e176abd8de Initial commit 2013-12-06 11:49:25 -05:00
699 changed files with 2483051 additions and 60791 deletions

12
.eslintmjs Normal file
View File

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

View File

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

View File

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

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

20
.github/workflows/bun.yml vendored Normal file
View 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'

View File

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

View File

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

View File

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

View File

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

6
.gitignore vendored
View File

@ -14,6 +14,7 @@ tmp
*.[pP][mM][dD]*
*.[pP][dD][fF]
*.[sS][lL][kK]
*.[sS][yY][lL][kK]
*.socialcalc
*.[xX][lL][sSwWcCaAtTmMrR]
*.[xX][lL][sSaAtT][xXmMbB]
@ -22,13 +23,16 @@ tmp
*.[xX][mM][lL]
*.[xX][lL][mM][lL]
*.[uU][oO][sS]
*.[wW][kKqQbB][S1234567890]
*.[wW][kKqQbB][sS1234567890]
*.[qQ][pP][wW]
*.[fF][mM][3tT]
*.[bB][iI][fF][fF][23458]
*.[rR][tT][fF]
*.[eE][tT]
*.[eE][tT][hH]
*.[nN][uU][mM][bB][eE][rR][sS]
*.[mM][oO][dD]
*.[dD][tT][aA]
*.123
*.htm
*.html

1
.gitmodules vendored
View File

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

View File

@ -8,8 +8,10 @@ index.html
misc/
node_modules
*.tgz
*.jsx
_book
book.json
v8.log
tmp
*.[tT][xX][tT]
*.[cC][sS][vV]
@ -18,18 +20,24 @@ tmp
*.[pP][mM][dD]*
*.[pP][dD][fF]
*.[sS][lL][kK]
*.[sS][yY][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]
*.[eE][tT][hH]
*.[nN][uU][mM][bB][eE][rR][sS]
*.[mM][oO][dD]
*.123
*.htm
*.html
@ -42,6 +50,7 @@ tmp
.spelling
.eslintignore
.eslintrc
.eslintmjs
.jshintrc
xlsx.mini.js
CONTRIBUTING.md
@ -54,6 +63,9 @@ shim.js
test.js
test.mjs
test.ts
test.mts
testnocp.ts
testbun.mjs
.jscs.json
.gitmodules
.travis.yml

View File

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

View File

@ -4,6 +4,110 @@ This log is intended to keep track of backwards-incompatible changes, including
but not limited to API changes and file location changes. Minor behavioral
changes may not be included if they are not expected to break existing code.
## v0.20.2
* Reworked parsing methods to avoid slow regexes (CVE-2024-22363)
* HTML properly encode data-v attribute
* SYLK read and write error cells
## v0.20.1
* `init` use packaged test files to work around GitHub breaking changes
* SSF date code rounding to 15 decimal digits (h/t @davidtamaki)
* `sheet_to_json` force UTC interpretation for formatted strings (h/t @Blanay)
* QPW extract result of string formula
* XLSX parse non-compliant merge cell expressions
* NUMBERS correctly handle rows omitted from official exports
* DBF parse empty logical field (h/t @Roman91)
* `dense` option added to types
* package.json add mini and core scripts to export map (h/t @stof)
## v0.20.0
* Use UTC interpretation of Date objects for date cells (potentially breaking)
* API functions support UTC and local time value interpretations
* Export `NaN` values to `#NUM!` and infinite values to `#DIV/0!`
## v0.19.3
* XLSX Ensure comment address is valid (h/t @slonser)
* Enforce Excel worksheet name restrictions
* Fixed "Prototype Pollution" vulnerability (CVE-2023-30533)
## v0.19.2
* XLSX proper decoding of hyperlinks (h/t @tw-yaxu)
* XLSX ignore unexpected attributes in rich text (h/t @colin4)
* `sheet_to_json` type fix (h/t @chsdwn)
## v0.19.1
* Fixed types issue in strict mode (h/t @younes-io)
* Numbers 12.2 parsing skip ActivityStream.iwa
## v0.19.0
* XLSX export hyperlinks compatible with google sheets (h/t Evan Bovie)
* NUMBERS export multiple sheets, full worksheet range
* formalized `dense` mode
## v0.18.12
* `package.json` added types in `exports` structure
* uncapped NUMBERS single-sheet single-table export
* DBF export records using supported codepages
## v0.18.11
* Base64 input ignore data URI wrapper
* Parse ZIP files that use ZIP64 extended information field
* More precise handling of time-only values
* Threaded Comment fallback text for older Excel
## v0.18.10
* `exports` field in package.json to satiate ViteJS and newer tooling
* JSC (Safari / Bun) perf, see <https://bugs.webkit.org/show_bug.cgi?id=243148>
* workbook `bookType` property to denote the origin format when parsed from file
* XLSX force export of stub cells with number formats when `sheetStubs` is set
## v0.18.9
* XLSX / ODS write defined names
* sync defined names to AutoFilter setting on export
* 1904 date system setting properly roundtripped
* ODS read/write number formats
## v0.18.8
* Plaintext parsing of dateless meridien time values (`1:23:45 PM`)
* Legacy format (SYLK / WK# / Multiplan) minutiae
## v0.18.7
* Normalized handling of `\r` and `\n` newline characters
## v0.18.6
* Removed all npm dependencies
* Auto-correct bad Google Sheets format `d.m`
* NUMBERS write merge cells, cells up to column "ALL"
## v0.18.5
* Enabled `sideEffects: false` in package.json
* Basic NUMBERS write support
## v0.18.4
* CSV output omits trailing record separator
* Properly terminate NodeJS Streams
* DBF preserve column types on import and use when applicable on export
## v0.18.3
* Removed references to `require` and `process` in browser builds
## v0.18.2
* Hotfix for unicode processing of XLSX exports

View File

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

108
Makefile
View File

@ -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:
@ -67,10 +67,9 @@ clean-data:
.PHONY: init
init: ## Initial setup for development
git submodule init
git submodule update
#git submodule foreach git pull origin master
git submodule foreach make
rm -rf test_files
if [ ! -e test_files.zip ]; then curl -LO https://test-files.sheetjs.com/test_files.zip; fi
unzip test_files.zip
mkdir -p tmp
DISTHDR=misc/suppress_export.js
@ -93,7 +92,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)
@ -105,23 +106,18 @@ dist-deps: ## Copy dependencies for distribution
.PHONY: aux
aux: $(AUXTARGETS)
BYTEFILEC=dist/xlsx.{full,core,mini}.min.js
BYTEFILER=dist/xlsx.extendscript.js xlsx.mjs
BYTEFILEC=dist/xlsx.{full,core,mini}.min.js xlsx.mjs
BYTEFILER=dist/xlsx.extendscript.js
.PHONY: bytes
bytes: ## Display minified and gzipped file sizes
@for i in $(BYTEFILEC); do 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
@npx printj "%-30s %10d" "treeshake" "$$(npx -y esbuild@0.14.14 --bundle misc/import.js | wc -c)"
.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,31 +137,62 @@ 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: testdot
testdot: test.js ## Run test suite using dot reporter
mocha -R dot -t 30000
.PHONY: test-esm
test-esm: test.mjs ## Run Node ESM test suite
npx 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_%:
FMTS=$* make test
TESTFMT=$(patsubst %,testdot_%,$(FMT))
.PHONY: $(TESTFMT)
$(TESTFMT): testdot_%:
FMTS=$* make testdot
TESTESMFMT=$(patsubst %,test-esm_%,$(FMT))
.PHONY: $(TESTESMFMT)
$(TESTESMFMT): test-esm_%:
FMTS=$* make test-esm
TESTDENOFMT=$(patsubst %,test-deno_%,$(FMT))
.PHONY: $(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 +203,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 +212,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 +234,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 +254,7 @@ 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=README.md
.PHONY: mdlint
mdlint: $(MDLINT) ## Check markdown documents
./node_modules/.bin/alex $^

4370
README.md

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -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, Set:false, Float32Array:false */
var XLSX = {};
function make_xlsx_lib(XLSX){

View File

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

View File

@ -1,37 +1,31 @@
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 */
/*::[*/1/*::]*/: 65001, /* DEFAULT */
/*::[*/2/*::]*/: 65001, /* SYMBOL */
/*::[*/77/*::]*/: 10000, /* MAC */
/*::[*/128/*::]*/: 932, /* SHIFTJIS */
/*::[*/129/*::]*/: 949, /* HANGUL */
/*::[*/130/*::]*/: 1361, /* JOHAB */
/*::[*/134/*::]*/: 936, /* GB2312 */
/*::[*/136/*::]*/: 950, /* CHINESEBIG5 */
/*::[*/161/*::]*/: 1253, /* GREEK */
/*::[*/162/*::]*/: 1254, /* TURKISH */
/*::[*/163/*::]*/: 1258, /* VIETNAMESE */
/*::[*/177/*::]*/: 1255, /* HEBREW */
/*::[*/178/*::]*/: 1256, /* ARABIC */
/*::[*/186/*::]*/: 1257, /* BALTIC */
/*::[*/204/*::]*/: 1251, /* RUSSIAN */
/*::[*/222/*::]*/: 874, /* THAI */
/*::[*/238/*::]*/: 1250, /* EASTEUROPE */
/*::[*/255/*::]*/: 1252, /* OEM */
/*::[*/69/*::]*/: 6969 /* MISC */
0: 1252, /* ANSI */
1: 65001, /* DEFAULT */
2: 65001, /* SYMBOL */
77: 10000, /* MAC */
128: 932, /* SHIFTJIS */
129: 949, /* HANGUL */
130: 1361, /* JOHAB */
134: 936, /* GB2312 */
136: 950, /* CHINESEBIG5 */
161: 1253, /* GREEK */
162: 1254, /* TURKISH */
163: 1258, /* VIETNAMESE */
177: 1255, /* HEBREW */
178: 1256, /* ARABIC */
186: 1257, /* BALTIC */
204: 1251, /* RUSSIAN */
222: 874, /* THAI */
238: 1250, /* EASTEUROPE */
255: 1252, /* OEM */
69: 6969 /* MISC */
}/*:any*/);
var set_ansi = function(cp/*:number*/) { if(VALID_ANSI.indexOf(cp) == -1) return; current_ansi = CS2CP[0] = cp; };
@ -47,6 +41,11 @@ function utf16leread(data/*:string*/)/*:string*/ {
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i) + (data.charCodeAt(2*i+1)<<8));
return o.join("");
}
function utf16lereadu(data/*:Uint8Array*/)/*:string*/ {
var o/*:Array<string>*/ = [];
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data[2*i] + (data[2*i+1]<<8));
return o.join("");
}
function utf16beread(data/*:string*/)/*:string*/ {
var o/*:Array<string>*/ = [];
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i+1) + (data.charCodeAt(2*i)<<8));
@ -63,17 +62,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();
}

View File

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

View File

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

View File

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

View File

@ -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,8 +173,20 @@ 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_normalize_xl_unsafe(v/*:number*/)/*:number*/ {
var s = v.toPrecision(16);
if(s.indexOf("e") > -1) {
var m = s.slice(0, s.indexOf("e"));
m = m.indexOf(".") > -1 ? m.slice(0, (m.slice(0,2) == "0." ? 17 : 16)) : (m.slice(0,15) + fill("0", m.length - 15));
return m + s.slice(s.indexOf("e"));
}
var n = s.indexOf(".") > -1 ? s.slice(0, (s.slice(0,2) == "0." ? 17 : 16)) : (s.slice(0,15) + fill("0", s.length - 15));
return Number(n);
}
function SSF_parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
if(v > 2958465 || v < 0) return null;
v = SSF_normalize_xl_unsafe(v);
var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
var dout=[];
var out={D:date, T:time, u:86400*(v-date)-time,y:0,m:0,d:0,H:0,M:0,S:0,q:0};
@ -169,7 +206,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 +215,44 @@ 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);
function datenum_local(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
var epoch = v.getTime();
if(date1904) epoch -= 1461*24*60*60*1000;
else if(v >= base1904) epoch += 24*60*60*1000;
return (epoch - (dnthresh + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
}
/* The longest 32-bit integer text is "-4294967296", exactly 11 chars */
function general_fmt_int(v/*:number*/)/*:string*/ { return v.toString(10); }
SSF._general_int = general_fmt_int;
/* ECMA-376 18.8.30 numFmt*/
/* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
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 +261,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(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 +285,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 */
@ -323,7 +340,7 @@ function write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*:str
switch(fmt) {
case '[h]': case '[hh]': out = val.D*24+val.H; break;
case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+(ss0 == 0 ? Math.round(val.S+val.u) : val.S); break;
default: throw 'bad abstime format: ' + fmt;
} outl = fmt.length === 3 ? 1 : 2; break;
case 101: /* 'e' era */
@ -332,6 +349,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 +360,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;
@ -387,7 +408,7 @@ function write_num_f2(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:s
return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
}
var dec1 = /^#*0*\.([0#]+)/;
var closeparen = /\).*[0#]/;
var closeparen = /\)[^)]*[0#]/;
var phone = /\(###\) ###\\?-####/;
function hashq(str/*:string*/)/*:string*/ {
var o = "", cc;
@ -459,7 +480,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 +492,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 +600,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 +612,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 +638,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 +657,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 +682,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 +700,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 +708,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 +720,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 +729,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 +747,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) {
@ -767,10 +788,11 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
switch(out[i].t) {
case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
case 's':
if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
if((ssm=out[i].v.match(/\.0+$/))) { ss0=Math.max(ss0,ssm[0].length-1); bt = 4;}
if(bt < 3) bt = 3;
/* falls through */
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
case 'd': case 'y': case 'e': lst=out[i].t; break;
case 'M': lst=out[i].t; if(bt < 2) bt = 2; break;
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
case 'X': /*if(out[i].v === "B2");*/
break;
@ -780,19 +802,29 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
}
}
/* time rounding depends on presence of minute / second / usec fields */
var _dt;
switch(bt) {
case 0: break;
case 1:
/*::if(!dt) break;*/
case 2:
case 3:
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
if(dt.H >= 24) { dt.H = 0; ++dt.D; _dt = SSF_parse_date_code(dt.D); _dt.u = dt.u; _dt.S = dt.S; _dt.M = dt.M; _dt.H = dt.H; dt = _dt; }
break;
case 2:
/*::if(!dt) break;*/
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
case 4:
switch(ss0) {
case 1: dt.u = Math.round(dt.u * 10)/10; break;
case 2: dt.u = Math.round(dt.u * 100)/100; break;
case 3: dt.u = Math.round(dt.u * 1000)/1000; break;
}
if(dt.u >= 1) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
if(dt.H >= 24) { dt.H = 0; ++dt.D; _dt = SSF_parse_date_code(dt.D); _dt.u = dt.u; _dt.S = dt.S; _dt.M = dt.M; _dt.H = dt.H; dt = _dt; }
break;
}
@ -804,7 +836,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 +851,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 +919,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,11 +935,13 @@ 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("|") + "|");
if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
/* NOTE: most spreadsheet software do not support NaN or infinities */
if(typeof v === "number" && !isFinite(v)) v = 0;
switch(fmt.length) {
case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
@ -917,14 +950,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 +968,21 @@ 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(v instanceof Date) v = datenum_local(v, o.date1904);
if(SSF_isgeneral(sfmt,0)) return SSF_general(v, o);
if(v instanceof Date) v = datenum(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 "";
else if(isNaN(v) && f[1].indexOf("0") > -1) return "#VALUE!";
else if(!isFinite(v) && f[1].indexOf("0") > -1) return "#DIV/0!";
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 +998,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);

View File

@ -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,8 +41,9 @@ 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+)");
dateNFregex.lastIndex = 0;
return new RegExp("^" + fmt + "$");
}
function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/*:string*/ {
@ -75,6 +56,7 @@ function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/
case 'm': if(H >= 0) M = v; else m = v; break;
}
});
dateNFregex.lastIndex = 0;
if(S >= 0 && M == -1 && m >= 0) { M = m; m = -1; }
var datestr = (("" + (Y>=0?Y: new Date().getFullYear())).slice(-4) + "-" + ("00" + (m>=1?m:1)).slice(-2) + "-" + ("00" + (d>=1?d:1)).slice(-2));
if(datestr.length == 7) datestr = "0" + datestr;
@ -85,3 +67,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);
}

View File

@ -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 */
@ -82,7 +73,7 @@ function slice_by_16_tables(T) {
for(c = 256 + n; c < 4096; c += 256) v = table[c] = (v >>> 8) ^ T[v & 0xFF];
}
var out = [];
for(n = 1; n != 16; ++n) out[n - 1] = typeof Int32Array !== 'undefined' ? table.subarray(n * 256, n * 256 + 256) : table.slice(n * 256, n * 256 + 256);
for(n = 1; n != 16; ++n) out[n - 1] = typeof Int32Array !== 'undefined' && typeof table.subarray == "function" ? table.subarray(n * 256, n * 256 + 256) : table.slice(n * 256, n * 256 + 256);
return out;
}
var TT = slice_by_16_tables(T0);
@ -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 > 31) {
console.error("Name " + _nm + " will be truncated to " + _nm.slice(0,31));
_nm = _nm.slice(0, 31);
}
flen = 2*(_nm.length+1);
o.write_shift(64, _nm, "utf16le");
o.write_shift(2, flen);
@ -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";
@ -1663,7 +1683,7 @@ function parse_mime(cfb/*:CFBContainer*/, data/*:Array<string>*/, root/*:string*
for(;di < 10; ++di) {
var line = data[di];
if(!line || line.match(/^\s*$/)) break;
var m = line.match(/^(.*?):\s*([^\s].*)$/);
var m = line.match(/^([^:]*?):\s*([^\s].*)$/);
if(m) switch(m[1].toLowerCase()) {
case "content-location": fname = m[2].trim(); break;
case "content-type": ctype = m[2].trim(); break;
@ -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; }

View File

@ -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) {
@ -35,7 +35,7 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
/*:: declare var chrome: any; */
if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
return chrome.downloads.download({ url: url, filename: fname, saveAs: true });
}
var a = document.createElement("a");
if(a.download != null) {
@ -45,6 +45,10 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
return url;
}
} else if(typeof URL !== 'undefined' && !URL.createObjectURL && typeof chrome === 'object') {
/* manifest v3 extensions -- no URL.createObjectURL */
var b64 = "data:application/octet-stream;base64," + Base64_encode_arr(new Uint8Array(blobify(data)));
return chrome.downloads.download({ url: b64, filename: fname, saveAs: true });
}
}
// $FlowIgnore
@ -53,7 +57,7 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
var out = File(fname); out.open("w"); out.encoding = "binary";
if(Array.isArray(payload)) payload = a2s(payload);
out.write(payload); out.close(); return payload;
} catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; }
} catch(e) { if(!e.message || e.message.indexOf("onstruct") == -1) throw e; }
throw new Error("cannot save file " + fname);
}
@ -67,6 +71,6 @@ function read_binary(path/*:string*/) {
var infile = File(path); infile.open("r"); infile.encoding = "binary";
var data = infile.read(); infile.close();
return data;
} catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; }
} catch(e) { if(!e.message || e.message.indexOf("onstruct") == -1) throw e; }
throw new Error("Cannot access file " + path);
}

View File

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

View File

@ -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 attregexg=/\s([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex1=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?<>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'"<>\s=]+))*\s*[\/\?]?>/mg, tagregex2 = /<[^<>]*>/g;
var tagregex = /*#__PURE__*/XML_HEADER.match(tagregex1) ? tagregex1 : tagregex2;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*/)/*:any*/ {
var z = ({}/*:any*/);
@ -12,7 +11,7 @@ function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*
if(eq === tag.length) return z;
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1;
if(m) for(i = 0; i != m.length; ++i) {
cc = m[i];
cc = m[i].slice(1);
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
q = cc.slice(0,c).trim();
while(cc.charCodeAt(c+1) == 32) ++c;
@ -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,42 +161,7 @@ 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 mtcache/*:{[k:string]:RegExp}*/ = ({}/*:any*/);
return function matchtag(f/*:string*/,g/*:?string*/)/*:RegExp*/ {
var t = f+"|"+(g||"");
if(mtcache[t]) return mtcache[t];
return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([\\s\\S]*?)</(?:\\w+:)?'+f+'>',((g||"")/*:any*/)));
};
})();
var htmldecode/*:{(s:string):string}*/ = (function() {
var htmldecode/*:{(s:string):string}*/ = /*#__PURE__*/(function() {
var entities/*:Array<[RegExp, string]>*/ = [
['nbsp', ' '], ['middot', '·'],
['quot', '"'], ['apos', "'"], ['gt', '>'], ['lt', '<'], ['amp', '&']
@ -181,30 +171,25 @@ var htmldecode/*:{(s:string):string}*/ = (function() {
// Remove new lines and spaces from start of content
.replace(/^[\t\n\r ]+/, "")
// Remove new lines and spaces from end of content
.replace(/[\t\n\r ]+$/,"")
.replace(/(^|[^\t\n\r ])[\t\n\r ]+$/,"$1")
// Added line which removes any white space characters after and before html tags
.replace(/>\s+/g,">").replace(/\s+</g,"<")
.replace(/>\s+/g,">").replace(/\b\s+</g,"<")
// Replace remaining new lines and spaces with space
.replace(/[\t\n\r ]+/g, " ")
// Replace <br> tags with new lines
.replace(/<\s*[bB][rR]\s*\/?>/g,"\n")
// Strip HTML elements
.replace(/<[^>]*>/g,"");
.replace(/<[^<>]*>/g,"");
for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]);
return o;
};
})();
var vtregex = (function(){ var vt_cache = {};
return function vt_regex(bt) {
if(vt_cache[bt] !== undefined) return vt_cache[bt];
return (vt_cache[bt] = new RegExp("<(?:vt:)?" + bt + ">([\\s\\S]*?)</(?:vt:)?" + bt + ">", 'g') );
};})();
var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^>]*)>([\s\S]*)</;
var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^<"'>]*)>([\s\S]*)</;
function parseVector(data/*:string*/, opts)/*:Array<{v:string,t:string}>*/ {
var h = parsexmltag(data);
var matches/*:Array<string>*/ = data.match(vtregex(h.baseType))||[];
var matches/*:Array<string>*/ = str_match_xml_ns_g(data, h.baseType)||[];
var res/*:Array<any>*/ = [];
if(matches.length != h.size) {
if(opts.WTF) throw new Error("unexpected vector length " + matches.length + " != " + h.size);
@ -238,7 +223,23 @@ function write_vt(s, xlsx/*:?boolean*/)/*:string*/ {
throw new Error("Unable to serialize " + s);
}
function xlml_normalize(d)/*:string*/ {
if(has_buf &&/*::typeof Buffer !== "undefined" && d != null && d instanceof Buffer &&*/ Buffer.isBuffer(d)) return d.toString('utf8');
if(typeof d === 'string') return d;
/* duktape */
if(typeof Uint8Array !== 'undefined' && d instanceof Uint8Array) return utf8read(a2s(ab2a(d)));
throw new Error("Bad input format: expected Buffer or string");
}
/* UOS uses CJK in tags, ODS uses invalid XML */
var xlmlregex = /<([\/]?)([^\s?><!\/:"]*:|)([^\s?<>:\/"]+)(?:\s+[^<>=?"'\s]+="[^"]*?")*\s*[\/]?>/mg;
var XMLNS = ({
CORE_PROPS: 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties',
CUST_PROPS: "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties",
EXT_PROPS: "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties",
CT: 'http://schemas.openxmlformats.org/package/2006/content-types',
RELS: 'http://schemas.openxmlformats.org/package/2006/relationships',
TCMNT: 'http://schemas.microsoft.com/office/spreadsheetml/2018/threadedcomments',
'dc': 'http://purl.org/dc/elements/1.1/',
'dcterms': 'http://purl.org/dc/terms/',
'dcmitype': 'http://purl.org/dc/dcmitype/',
@ -250,7 +251,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',

View File

@ -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"); */

View File

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

View File

@ -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*/) {
@ -99,11 +108,19 @@ function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ {
return { SheetNames: [n], Sheets: sheets };
}
function sheet_new(opts) {
var out = {};
var o = opts || {};
if(o.dense) out["!data"] = [];
return out;
}
function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
var o = opts || {};
var dense = _ws ? 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;
@ -111,28 +128,36 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
_R = _origin.r; _C = _origin.c;
}
if(!ws["!ref"]) ws["!ref"] = "A1:A1";
}
var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/);
if(ws['!ref']) {
if(ws["!ref"]){
var _range = safe_decode_range(ws['!ref']);
range.s.c = _range.s.c;
range.s.r = _range.s.r;
range.e.c = Math.max(range.e.c, _range.e.c);
range.e.r = Math.max(range.e.r, _range.e.r);
if(_R == -1) range.e.r = _R = _range.e.r + 1;
if(_R == -1) range.e.r = _R = (ws["!ref"] ? _range.e.r + 1 : 0);
} else {
range.s.c = range.e.c = range.s.r = range.e.r = 0;
}
var row = [], seen = false;
for(var R = 0; R != data.length; ++R) {
if(!data[R]) continue;
if(!Array.isArray(data[R])) throw new Error("aoa_to_sheet expects an array of arrays");
var __R = _R + R, __Rstr = "" + (__R + 1);
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;
if(range.e.c < __C) range.e.c = __C;
seen = true;
if(data[R][C] && typeof data[R][C] === 'object' && !Array.isArray(data[R][C]) && !(data[R][C] instanceof Date)) cell = data[R][C];
else {
if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
@ -142,28 +167,31 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
else if(!o.sheetStubs) continue;
else cell.t = 'z';
}
else if(typeof cell.v === 'number') cell.t = 'n';
else if(typeof cell.v === 'number') {
if(isFinite(cell.v)) cell.t = 'n';
else if(isNaN(cell.v)) { cell.t = 'e'; cell.v = 0x0F; /* #VALUE! */ }
else { cell.t = 'e'; cell.v = 0x07; /*# DIV/0 */ }
}
else if(typeof cell.v === 'boolean') cell.t = 'b';
else if(cell.v instanceof Date) {
cell.z = o.dateNF || 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.UTC) cell.v = local_to_utc(cell.v);
if(o.cellDates) { cell.t = 'd'; cell.w = SSF_format(cell.z, datenum(cell.v, o.date1904)); }
else { cell.t = 'n'; cell.v = datenum(cell.v, o.date1904); cell.w = SSF_format(cell.z, cell.v); }
}
else cell.t = 's';
}
if(dense) {
if(!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;
}
}
}
if(range.s.c < 10000000) ws['!ref'] = encode_range(range);
if(seen && range.s.c < 10400000) ws['!ref'] = encode_range(range);
return ws;
}
function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { return sheet_add_aoa(null, data, opts); }

View File

@ -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
@ -41,121 +44,118 @@ var VT_CUSTOM = [VT_STRING, VT_USTR];
/* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */
var DocSummaryPIDDSI = {
/*::[*/0x01/*::]*/: { n: 'CodePage', t: VT_I2 },
/*::[*/0x02/*::]*/: { n: 'Category', t: VT_STRING },
/*::[*/0x03/*::]*/: { n: 'PresentationFormat', t: VT_STRING },
/*::[*/0x04/*::]*/: { n: 'ByteCount', t: VT_I4 },
/*::[*/0x05/*::]*/: { n: 'LineCount', t: VT_I4 },
/*::[*/0x06/*::]*/: { n: 'ParagraphCount', t: VT_I4 },
/*::[*/0x07/*::]*/: { n: 'SlideCount', t: VT_I4 },
/*::[*/0x08/*::]*/: { n: 'NoteCount', t: VT_I4 },
/*::[*/0x09/*::]*/: { n: 'HiddenCount', t: VT_I4 },
/*::[*/0x0a/*::]*/: { n: 'MultimediaClipCount', t: VT_I4 },
/*::[*/0x0b/*::]*/: { n: 'ScaleCrop', t: VT_BOOL },
/*::[*/0x0c/*::]*/: { n: 'HeadingPairs', t: VT_VECTOR | VT_VARIANT },
/*::[*/0x0d/*::]*/: { n: 'TitlesOfParts', t: VT_VECTOR | VT_LPSTR },
/*::[*/0x0e/*::]*/: { n: 'Manager', t: VT_STRING },
/*::[*/0x0f/*::]*/: { n: 'Company', t: VT_STRING },
/*::[*/0x10/*::]*/: { n: 'LinksUpToDate', t: VT_BOOL },
/*::[*/0x11/*::]*/: { n: 'CharacterCount', t: VT_I4 },
/*::[*/0x13/*::]*/: { n: 'SharedDoc', t: VT_BOOL },
/*::[*/0x16/*::]*/: { n: 'HyperlinksChanged', t: VT_BOOL },
/*::[*/0x17/*::]*/: { n: 'AppVersion', t: VT_I4, p: 'version' },
/*::[*/0x18/*::]*/: { n: 'DigSig', t: VT_BLOB },
/*::[*/0x1A/*::]*/: { n: 'ContentType', t: VT_STRING },
/*::[*/0x1B/*::]*/: { n: 'ContentStatus', t: VT_STRING },
/*::[*/0x1C/*::]*/: { n: 'Language', t: VT_STRING },
/*::[*/0x1D/*::]*/: { n: 'Version', t: VT_STRING },
/*::[*/0xFF/*::]*/: {},
0x01: { n: 'CodePage', t: VT_I2 },
0x02: { n: 'Category', t: VT_STRING },
0x03: { n: 'PresentationFormat', t: VT_STRING },
0x04: { n: 'ByteCount', t: VT_I4 },
0x05: { n: 'LineCount', t: VT_I4 },
0x06: { n: 'ParagraphCount', t: VT_I4 },
0x07: { n: 'SlideCount', t: VT_I4 },
0x08: { n: 'NoteCount', t: VT_I4 },
0x09: { n: 'HiddenCount', t: VT_I4 },
0x0a: { n: 'MultimediaClipCount', t: VT_I4 },
0x0b: { n: 'ScaleCrop', t: VT_BOOL },
0x0c: { n: 'HeadingPairs', t: VT_VECTOR_VARIANT /* VT_VECTOR | VT_VARIANT */ },
0x0d: { n: 'TitlesOfParts', t: VT_VECTOR_LPSTR /* VT_VECTOR | VT_LPSTR */ },
0x0e: { n: 'Manager', t: VT_STRING },
0x0f: { n: 'Company', t: VT_STRING },
0x10: { n: 'LinksUpToDate', t: VT_BOOL },
0x11: { n: 'CharacterCount', t: VT_I4 },
0x13: { n: 'SharedDoc', t: VT_BOOL },
0x16: { n: 'HyperlinksChanged', t: VT_BOOL },
0x17: { n: 'AppVersion', t: VT_I4, p: 'version' },
0x18: { n: 'DigSig', t: VT_BLOB },
0x1A: { n: 'ContentType', t: VT_STRING },
0x1B: { n: 'ContentStatus', t: VT_STRING },
0x1C: { n: 'Language', t: VT_STRING },
0x1D: { n: 'Version', t: VT_STRING },
0xFF: {},
/* [MS-OLEPS] 2.18 */
/*::[*/0x80000000/*::]*/: { n: 'Locale', t: VT_UI4 },
/*::[*/0x80000003/*::]*/: { n: 'Behavior', t: VT_UI4 },
/*::[*/0x72627262/*::]*/: {}
0x80000000: { n: 'Locale', t: VT_UI4 },
0x80000003: { n: 'Behavior', t: VT_UI4 },
0x72627262: {}
};
/* [MS-OSHARED] 2.3.3.2.1.1 Summary Information Property Set PIDSI */
var SummaryPIDSI = {
/*::[*/0x01/*::]*/: { n: 'CodePage', t: VT_I2 },
/*::[*/0x02/*::]*/: { n: 'Title', t: VT_STRING },
/*::[*/0x03/*::]*/: { n: 'Subject', t: VT_STRING },
/*::[*/0x04/*::]*/: { n: 'Author', t: VT_STRING },
/*::[*/0x05/*::]*/: { n: 'Keywords', t: VT_STRING },
/*::[*/0x06/*::]*/: { n: 'Comments', t: VT_STRING },
/*::[*/0x07/*::]*/: { n: 'Template', t: VT_STRING },
/*::[*/0x08/*::]*/: { n: 'LastAuthor', t: VT_STRING },
/*::[*/0x09/*::]*/: { n: 'RevNumber', t: VT_STRING },
/*::[*/0x0A/*::]*/: { n: 'EditTime', t: VT_FILETIME },
/*::[*/0x0B/*::]*/: { n: 'LastPrinted', t: VT_FILETIME },
/*::[*/0x0C/*::]*/: { n: 'CreatedDate', t: VT_FILETIME },
/*::[*/0x0D/*::]*/: { n: 'ModifiedDate', t: VT_FILETIME },
/*::[*/0x0E/*::]*/: { n: 'PageCount', t: VT_I4 },
/*::[*/0x0F/*::]*/: { n: 'WordCount', t: VT_I4 },
/*::[*/0x10/*::]*/: { n: 'CharCount', t: VT_I4 },
/*::[*/0x11/*::]*/: { n: 'Thumbnail', t: VT_CF },
/*::[*/0x12/*::]*/: { n: 'Application', t: VT_STRING },
/*::[*/0x13/*::]*/: { n: 'DocSecurity', t: VT_I4 },
/*::[*/0xFF/*::]*/: {},
0x01: { n: 'CodePage', t: VT_I2 },
0x02: { n: 'Title', t: VT_STRING },
0x03: { n: 'Subject', t: VT_STRING },
0x04: { n: 'Author', t: VT_STRING },
0x05: { n: 'Keywords', t: VT_STRING },
0x06: { n: 'Comments', t: VT_STRING },
0x07: { n: 'Template', t: VT_STRING },
0x08: { n: 'LastAuthor', t: VT_STRING },
0x09: { n: 'RevNumber', t: VT_STRING },
0x0A: { n: 'EditTime', t: VT_FILETIME },
0x0B: { n: 'LastPrinted', t: VT_FILETIME },
0x0C: { n: 'CreatedDate', t: VT_FILETIME },
0x0D: { n: 'ModifiedDate', t: VT_FILETIME },
0x0E: { n: 'PageCount', t: VT_I4 },
0x0F: { n: 'WordCount', t: VT_I4 },
0x10: { n: 'CharCount', t: VT_I4 },
0x11: { n: 'Thumbnail', t: VT_CF },
0x12: { n: 'Application', t: VT_STRING },
0x13: { n: 'DocSecurity', t: VT_I4 },
0xFF: {},
/* [MS-OLEPS] 2.18 */
/*::[*/0x80000000/*::]*/: { n: 'Locale', t: VT_UI4 },
/*::[*/0x80000003/*::]*/: { n: 'Behavior', t: VT_UI4 },
/*::[*/0x72627262/*::]*/: {}
0x80000000: { n: 'Locale', t: VT_UI4 },
0x80000003: { n: 'Behavior', t: VT_UI4 },
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
/*::[*/0x0002/*::]*/: "CA", // Canada
/*::[*/0x0003/*::]*/: "", // Latin America (except Brazil)
/*::[*/0x0007/*::]*/: "RU", // Russia
/*::[*/0x0014/*::]*/: "EG", // Egypt
/*::[*/0x001E/*::]*/: "GR", // Greece
/*::[*/0x001F/*::]*/: "NL", // Netherlands
/*::[*/0x0020/*::]*/: "BE", // Belgium
/*::[*/0x0021/*::]*/: "FR", // France
/*::[*/0x0022/*::]*/: "ES", // Spain
/*::[*/0x0024/*::]*/: "HU", // Hungary
/*::[*/0x0027/*::]*/: "IT", // Italy
/*::[*/0x0029/*::]*/: "CH", // Switzerland
/*::[*/0x002B/*::]*/: "AT", // Austria
/*::[*/0x002C/*::]*/: "GB", // United Kingdom
/*::[*/0x002D/*::]*/: "DK", // Denmark
/*::[*/0x002E/*::]*/: "SE", // Sweden
/*::[*/0x002F/*::]*/: "NO", // Norway
/*::[*/0x0030/*::]*/: "PL", // Poland
/*::[*/0x0031/*::]*/: "DE", // Germany
/*::[*/0x0034/*::]*/: "MX", // Mexico
/*::[*/0x0037/*::]*/: "BR", // Brazil
/*::[*/0x003d/*::]*/: "AU", // Australia
/*::[*/0x0040/*::]*/: "NZ", // New Zealand
/*::[*/0x0042/*::]*/: "TH", // Thailand
/*::[*/0x0051/*::]*/: "JP", // Japan
/*::[*/0x0052/*::]*/: "KR", // Korea
/*::[*/0x0054/*::]*/: "VN", // Viet Nam
/*::[*/0x0056/*::]*/: "CN", // China
/*::[*/0x005A/*::]*/: "TR", // Turkey
/*::[*/0x0069/*::]*/: "JS", // Ramastan
/*::[*/0x00D5/*::]*/: "DZ", // Algeria
/*::[*/0x00D8/*::]*/: "MA", // Morocco
/*::[*/0x00DA/*::]*/: "LY", // Libya
/*::[*/0x015F/*::]*/: "PT", // Portugal
/*::[*/0x0162/*::]*/: "IS", // Iceland
/*::[*/0x0166/*::]*/: "FI", // Finland
/*::[*/0x01A4/*::]*/: "CZ", // Czech Republic
/*::[*/0x0376/*::]*/: "TW", // Taiwan
/*::[*/0x03C1/*::]*/: "LB", // Lebanon
/*::[*/0x03C2/*::]*/: "JO", // Jordan
/*::[*/0x03C3/*::]*/: "SY", // Syria
/*::[*/0x03C4/*::]*/: "IQ", // Iraq
/*::[*/0x03C5/*::]*/: "KW", // Kuwait
/*::[*/0x03C6/*::]*/: "SA", // Saudi Arabia
/*::[*/0x03CB/*::]*/: "AE", // United Arab Emirates
/*::[*/0x03CC/*::]*/: "IL", // Israel
/*::[*/0x03CE/*::]*/: "QA", // Qatar
/*::[*/0x03D5/*::]*/: "IR", // Iran
/*::[*/0xFFFF/*::]*/: "US" // United States
0x0001: "US", // United States
0x0002: "CA", // Canada
0x0003: "", // Latin America (except Brazil)
0x0007: "RU", // Russia
0x0014: "EG", // Egypt
0x001E: "GR", // Greece
0x001F: "NL", // Netherlands
0x0020: "BE", // Belgium
0x0021: "FR", // France
0x0022: "ES", // Spain
0x0024: "HU", // Hungary
0x0027: "IT", // Italy
0x0029: "CH", // Switzerland
0x002B: "AT", // Austria
0x002C: "GB", // United Kingdom
0x002D: "DK", // Denmark
0x002E: "SE", // Sweden
0x002F: "NO", // Norway
0x0030: "PL", // Poland
0x0031: "DE", // Germany
0x0034: "MX", // Mexico
0x0037: "BR", // Brazil
0x003d: "AU", // Australia
0x0040: "NZ", // New Zealand
0x0042: "TH", // Thailand
0x0051: "JP", // Japan
0x0052: "KR", // Korea
0x0054: "VN", // Viet Nam
0x0056: "CN", // China
0x005A: "TR", // Turkey
0x0069: "JS", // Ramastan
0x00D5: "DZ", // Algeria
0x00D8: "MA", // Morocco
0x00DA: "LY", // Libya
0x015F: "PT", // Portugal
0x0162: "IS", // Iceland
0x0166: "FI", // Finland
0x01A4: "CZ", // Czech Republic
0x0376: "TW", // Taiwan
0x03C1: "LB", // Lebanon
0x03C2: "JO", // Jordan
0x03C3: "SY", // Syria
0x03C4: "IQ", // Iraq
0x03C5: "KW", // Kuwait
0x03C6: "SA", // Saudi Arabia
0x03CB: "AE", // United Arab Emirates
0x03CC: "IL", // Israel
0x03CE: "QA", // Qatar
0x03D5: "IR", // Iran
0xFFFF: "US" // United States
};
/* [MS-XLS] 2.5.127 */
@ -185,7 +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,18 +277,47 @@ 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 = {
/*::[*/0x00/*::]*/: "#NULL!",
/*::[*/0x07/*::]*/: "#DIV/0!",
/*::[*/0x0F/*::]*/: "#VALUE!",
/*::[*/0x17/*::]*/: "#REF!",
/*::[*/0x1D/*::]*/: "#NAME?",
/*::[*/0x24/*::]*/: "#NUM!",
/*::[*/0x2A/*::]*/: "#N/A",
/*::[*/0x2B/*::]*/: "#GETTING_DATA",
/*::[*/0xFF/*::]*/: "#WTF?"
0x00: "#NULL!",
0x07: "#DIV/0!",
0x0F: "#VALUE!",
0x17: "#REF!",
0x1D: "#NAME?",
0x24: "#NUM!",
0x2A: "#N/A",
0x2B: "#GETTING_DATA",
0xFF: "#WTF?"
};
var RBErr = evert_num(BErr);
//var RBErr = evert_num(BErr);
var RBErr = {
"#NULL!": 0x00,
"#DIV/0!": 0x07,
"#VALUE!": 0x0F,
"#REF!": 0x17,
"#NAME?": 0x1D,
"#NUM!": 0x24,
"#N/A": 0x2A,
"#GETTING_DATA": 0x2B,
"#WTF?": 0xFF
};
var XLSLblBuiltIn = [
"_xlnm.Consolidate_Area",
"_xlnm.Auto_Open",
"_xlnm.Auto_Close",
"_xlnm.Extract",
"_xlnm.Database",
"_xlnm.Criteria",
"_xlnm.Print_Area",
"_xlnm.Print_Titles",
"_xlnm.Recorder",
"_xlnm.Data_Form",
"_xlnm.Auto_Activate",
"_xlnm.Auto_Deactivate",
"_xlnm.Sheet_Title",
"_xlnm._FilterDatabase"
];

View File

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

View File

@ -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*/);
@ -30,7 +52,7 @@ function parse_rels(data/*:?string*/, currentFilePath/*:string*/) {
var y = parsexmltag(x);
/* 9.3.2.2 OPC_Relationships */
if (y[0] === '<Relationship') {
var rel = {}; rel.Type = y.Type; rel.Target = y.Target; rel.Id = y.Id; if(y.TargetMode) rel.TargetMode = y.TargetMode;
var rel = {}; rel.Type = y.Type; rel.Target = unescapexml(y.Target); rel.Id = y.Id; if(y.TargetMode) rel.TargetMode = y.TargetMode;
var canonictarget = y.TargetMode === 'External' ? y.Target : resolve_path(y.Target, currentFilePath);
rels[canonictarget] = rel;
hash[y.Id] = rel;
@ -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;

View File

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

View File

@ -18,25 +18,12 @@ var CORE_PROPS/*:Array<Array<string> >*/ = [
["dcterms:modified", "ModifiedDate", 'date']
];
XMLNS.CORE_PROPS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
RELS.CORE_PROPS = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';
var CORE_PROPS_REGEX/*:Array<RegExp>*/ = (function() {
var r = new Array(CORE_PROPS.length);
for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i];
var g = "(?:"+ f[0].slice(0,f[0].indexOf(":")) +":)"+ f[0].slice(f[0].indexOf(":")+1);
r[i] = new RegExp("<" + g + "[^>]*>([\\s\\S]*?)<\/" + g + ">");
}
return r;
})();
function parse_core_props(data) {
var p = {};
data = utf8read(data);
for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
var f = CORE_PROPS[i], cur = str_match_xml(data, f[0]);
if(cur != null && cur.length > 0) p[f[1]] = unescapexml(cur[1]);
if(f[2] === 'date' && p[f[1]]) p[f[1]] = parseDate(p[f[1]]);
}
@ -44,15 +31,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 +40,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) {

View File

@ -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",
@ -74,12 +71,12 @@ function parse_ext_props(data, p, opts) {
data = utf8read(data);
EXT_PROPS.forEach(function(f) {
var xml = (data.match(matchtag(f[0]))||[])[1];
var xml = (str_match_xml_ns(data, f[0])||[])[1];
switch(f[2]) {
case "string": if(xml) p[f[1]] = unescapexml(xml); break;
case "bool": p[f[1]] = xml === "true"; break;
case "raw":
var cur = data.match(new RegExp("<" + f[0] + "[^>]*>([\\s\\S]*?)<\/" + f[0] + ">"));
var cur = str_match_xml(data, f[0]);
if(cur && cur.length > 0) q[f[1]] = cur[1];
break;
}
@ -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;

View File

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

View File

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

View File

@ -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);
@ -232,8 +233,8 @@ function parse_PropertySet(blob, PIDSI) {
/* [MS-OSHARED] 2.3.3.2.3.1.2 + PROPVARIANT */
switch(blob[blob.l]) {
case 0x41 /*VT_BLOB*/: blob.l += 4; val = parse_BLOB(blob); break;
case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break;
case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break;
case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
case 0x03 /*VT_I4*/: blob.l += 4; val = blob.read_shift(4, 'i'); break;
case 0x13 /*VT_UI4*/: blob.l += 4; val = blob.read_shift(4); break;
case 0x05 /*VT_R8*/: blob.l += 4; val = blob.read_shift(8, 'f'); break;
@ -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;

View File

@ -1,9 +1,20 @@
/* [MS-XLS] 2.5.19 */
function parse_XLSCell(blob/*::, length*/)/*:Cell*/ {
function parse_XLSCell(blob, length, opts)/*:Cell*/ {
var rw = blob.read_shift(2); // 0-indexed
var col = blob.read_shift(2);
var ixfe = blob.read_shift(2);
return ({r:rw, c:col, ixfe:ixfe}/*:any*/);
var ret = ({r:rw, c:col, ixfe:0}/*:any*/);
if(opts && opts.biff == 2 || length == 7) {
/* TODO: pass back flags */
var flags = blob.read_shift(1);
ret.ixfe = flags & 0x3F;
blob.l += 2;
/*
var ifntifmt = blob.read_shift(1);
var ifmt = ifntifmt & 0x3f, ifnt = ifntifmt >> 6;
var flags3 = blob.read_shift(1);
*/
} else ret.ixfe = blob.read_shift(2);
return ret;
}
function write_XLSCell(R/*:number*/, C/*:number*/, ixfe/*:?number*/, o) {
if(!o) o = new_buf(6);
@ -111,25 +122,25 @@ function parse_FtCf(blob) {
/* [MS-XLS] 2.5.140 - 2.5.154 and friends */
function parse_FtSkip(blob) { blob.l += 2; blob.l += blob.read_shift(2); }
var FtTab = {
/*::[*/0x00/*::]*/: parse_FtSkip, /* FtEnd */
/*::[*/0x04/*::]*/: parse_FtSkip, /* FtMacro */
/*::[*/0x05/*::]*/: parse_FtSkip, /* FtButton */
/*::[*/0x06/*::]*/: parse_FtSkip, /* FtGmo */
/*::[*/0x07/*::]*/: parse_FtCf, /* FtCf */
/*::[*/0x08/*::]*/: parse_FtSkip, /* FtPioGrbit */
/*::[*/0x09/*::]*/: parse_FtSkip, /* FtPictFmla */
/*::[*/0x0A/*::]*/: parse_FtSkip, /* FtCbls */
/*::[*/0x0B/*::]*/: parse_FtSkip, /* FtRbo */
/*::[*/0x0C/*::]*/: parse_FtSkip, /* FtSbs */
/*::[*/0x0D/*::]*/: parse_FtNts, /* FtNts */
/*::[*/0x0E/*::]*/: parse_FtSkip, /* FtSbsFmla */
/*::[*/0x0F/*::]*/: parse_FtSkip, /* FtGboData */
/*::[*/0x10/*::]*/: parse_FtSkip, /* FtEdoData */
/*::[*/0x11/*::]*/: parse_FtSkip, /* FtRboData */
/*::[*/0x12/*::]*/: parse_FtSkip, /* FtCblsData */
/*::[*/0x13/*::]*/: parse_FtSkip, /* FtLbsData */
/*::[*/0x14/*::]*/: parse_FtSkip, /* FtCblsFmla */
/*::[*/0x15/*::]*/: parse_FtCmo
0x00: parse_FtSkip, /* FtEnd */
0x04: parse_FtSkip, /* FtMacro */
0x05: parse_FtSkip, /* FtButton */
0x06: parse_FtSkip, /* FtGmo */
0x07: parse_FtCf, /* FtCf */
0x08: parse_FtSkip, /* FtPioGrbit */
0x09: parse_FtSkip, /* FtPictFmla */
0x0A: parse_FtSkip, /* FtCbls */
0x0B: parse_FtSkip, /* FtRbo */
0x0C: parse_FtSkip, /* FtSbs */
0x0D: parse_FtNts, /* FtNts */
0x0E: parse_FtSkip, /* FtSbsFmla */
0x0F: parse_FtSkip, /* FtGboData */
0x10: parse_FtSkip, /* FtEdoData */
0x11: parse_FtSkip, /* FtRboData */
0x12: parse_FtSkip, /* FtCblsData */
0x13: parse_FtSkip, /* FtLbsData */
0x14: parse_FtSkip, /* FtCblsFmla */
0x15: parse_FtCmo
};
function parse_FtArray(blob, length/*::, ot*/) {
var tgt = blob.l + length;
@ -138,7 +149,7 @@ function parse_FtArray(blob, length/*::, ot*/) {
var ft = blob.read_shift(2);
blob.l-=2;
try {
fts.push(FtTab[ft](blob, tgt - blob.l));
fts[ft] = FtTab[ft](blob, tgt - blob.l);
} catch(e) { blob.l = tgt; return fts; }
}
if(blob.l != tgt) blob.l = tgt; //throw new Error("bad Object Ft-sequence");
@ -228,6 +239,12 @@ function parse_WsBool(blob, length, opts) {
/* [MS-XLS] 2.4.28 */
function parse_BoundSheet8(blob, length, opts) {
var name = "";
if(opts.biff == 4) {
name = parse_ShortXLUnicodeString(blob, 0, opts);
if(name.length === 0) name = "Sheet1";
return { name:name };
}
var pos = blob.read_shift(4);
var hidden = blob.read_shift(1) & 0x03;
var dt = blob.read_shift(1);
@ -237,7 +254,7 @@ function parse_BoundSheet8(blob, length, opts) {
case 2: dt = 'Chartsheet'; break;
case 6: dt = 'VBAModule'; break;
}
var name = parse_ShortXLUnicodeString(blob, 0, opts);
name = parse_ShortXLUnicodeString(blob, 0, opts);
if(name.length === 0) name = "Sheet1";
return { pos:pos, hs:hidden, dt:dt, name:name };
}
@ -408,8 +425,8 @@ function write_Font(data, opts) {
}
/* [MS-XLS] 2.4.149 */
function parse_LabelSst(blob) {
var cell = parse_XLSCell(blob);
function parse_LabelSst(blob, length, opts) {
var cell = parse_XLSCell(blob, length, opts);
cell.isst = blob.read_shift(4);
return cell;
}
@ -424,8 +441,7 @@ function write_LabelSst(R/*:number*/, C/*:number*/, v/*:number*/, os/*:number*/
function parse_Label(blob, length, opts) {
if(opts.biffguess && opts.biff == 2) opts.biff = 5;
var target = blob.l + length;
var cell = parse_XLSCell(blob, 6);
if(opts.biff == 2) blob.l++;
var cell = parse_XLSCell(blob, length, opts);
var str = parse_XLUnicodeString(blob, target - blob.l, opts);
cell.val = str;
return cell;
@ -459,6 +475,19 @@ function write_Format(i/*:number*/, f/*:string*/, opts, o) {
return out;
}
var parse_BIFF2Format = parse_XLUnicodeString2;
function write_BIFF2Format(f/*:string*/) {
var o = new_buf(1 + f.length);
o.write_shift(1, f.length);
o.write_shift(f.length, f, "sbcs");
return o;
}
function write_BIFF4Format(f/*:string*/) {
var o = new_buf(3 + f.length);
o.l += 2;
o.write_shift(1, f.length);
o.write_shift(f.length, f, "sbcs");
return o;
}
/* [MS-XLS] 2.4.90 */
function parse_Dimensions(blob, length, opts) {
@ -582,6 +611,44 @@ function write_XF(data, ixfeP, opts, o) {
o.write_shift(2, 0);
return o;
}
function parse_BIFF2XF(blob/*::, length, opts*/) {
var o = {};
o.ifnt = blob.read_shift(1); blob.l++; o.flags = blob.read_shift(1);
o.numFmtId = o.flags & 0x3F; o.flags>>=6;
o.fStyle = 0;
o.data = {}; // TODO
return o;
}
function write_BIFF2XF(xf) {
var o = new_buf(4);
o.l+=2;
o.write_shift(1, xf.numFmtId);
o.l++;
return o;
}
function write_BIFF3XF(xf) {
var o = new_buf(12);
o.l++;
o.write_shift(1, xf.numFmtId);
o.l += 10;
return o;
}
/* TODO: check other fields */
var write_BIFF4XF = write_BIFF3XF;
function parse_BIFF3XF(blob/*::, length, opts*/) {
var o = {};
o.ifnt = blob.read_shift(1); o.numFmtId = blob.read_shift(1); o.flags = blob.read_shift(2);
o.fStyle = (o.flags >> 2) & 0x01;
o.data = {}; // TODO
return o;
}
function parse_BIFF4XF(blob/*::, length, opts*/) {
var o = {};
o.ifnt = blob.read_shift(1); o.numFmtId = blob.read_shift(1); o.flags = blob.read_shift(2);
o.fStyle = (o.flags >> 2) & 0x01;
o.data = {}; // TODO
return o;
}
/* [MS-XLS] 2.4.134 */
function parse_Guts(blob) {
@ -602,8 +669,7 @@ function write_Guts(guts/*:Array<number>*/) {
/* [MS-XLS] 2.4.24 */
function parse_BoolErr(blob, length, opts) {
var cell = parse_XLSCell(blob, 6);
if(opts.biff == 2 || length == 9) ++blob.l;
var cell = parse_XLSCell(blob, 6, opts);
var val = parse_Bes(blob, 2);
cell.val = val;
cell.t = (val === true || val === false) ? 'b' : 'e';
@ -619,7 +685,7 @@ function write_BoolErr(R/*:number*/, C/*:number*/, v, os/*:number*/, opts, t/*:s
/* [MS-XLS] 2.4.180 Number */
function parse_Number(blob, length, opts) {
if(opts.biffguess && opts.biff == 2) opts.biff = 5;
var cell = parse_XLSCell(blob, 6);
var cell = parse_XLSCell(blob, 6, opts);
var xnum = parse_Xnum(blob, 8);
cell.val = xnum;
return cell;
@ -669,22 +735,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);
@ -712,9 +762,11 @@ function parse_Lbl(blob, length, opts) {
};
}
/* [MS-XLS] 2.4.106 TODO: verify filename encoding */
/* [MS-XLS] 2.4.106 TODO: legacy record filename encoding */
function parse_ExternSheet(blob, length, opts) {
if(opts.biff < 8) return parse_BIFF5ExternSheet(blob, length, opts);
/* see issue 2907 */
if(!(opts.biff > 8) && (length == blob[blob.l] + (blob[blob.l+1] == 0x03 ? 1 : 0) + 1)) return parse_BIFF5ExternSheet(blob, length, opts);
var o = [], target = blob.l + length, len = blob.read_shift(opts.biff > 8 ? 4 : 2);
while(len-- !== 0) o.push(parse_XTI(blob, opts.biff > 8 ? 12 : 6, opts));
// [iSupBook, itabFirst, itabLast];
@ -766,21 +818,34 @@ function parse_MTRSettings(blob) {
return [fMTREnabled, fUserSetThreadCount, cUserThreadCount];
}
/* [MS-XLS] 2.5.186 TODO: BIFF5 */
/* [MS-XLS] 2.5.186 */
function parse_NoteSh(blob, length, opts) {
if(opts.biff < 8) return;
var row = blob.read_shift(2), col = blob.read_shift(2);
var flags = blob.read_shift(2), idObj = blob.read_shift(2);
var stAuthor = parse_XLUnicodeString2(blob, 0, opts);
if(opts.biff < 8) blob.read_shift(1);
return [{r:row,c:col}, stAuthor, idObj, flags];
}
/* [MS-XLS] 2.4.179 */
function parse_Note(blob, length, opts) {
if(opts && (opts.biff < 8)) {
var row = blob.read_shift(2), col = blob.read_shift(2);
if(row == 0xFFFF || row == -1) return; // TODO: test continuation
var cch = blob.read_shift(2);
var cmnt = blob.read_shift(Math.min(cch,2048), 'cpstr');
return [{r:row, c:col}, cmnt];
}
/* TODO: Support revisions */
return parse_NoteSh(blob, length, opts);
}
function write_NOTE_BIFF2(text/*:string*/, R/*:number*/, C/*:number*/, len/*?:number*/) {
var o = new_buf(6 + (len || text.length));
o.write_shift(2, R);
o.write_shift(2, C);
o.write_shift(2, len || text.length);
o.write_shift(text.length, text, "sbcs");
return o;
}
/* [MS-XLS] 2.4.168 */
function parse_MergeCells(blob, length)/*:Array<Range>*/ {
@ -804,8 +869,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 +883,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 +916,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);
@ -1029,43 +1095,50 @@ function parse_ImData(blob) {
return o;
}
function write_BIFF2Cell(out, r/*:number*/, c/*:number*/, ixfe/*:number*/, ifmt/*:number*/) {
if(!out) out = new_buf(7);
out.write_shift(2, r);
out.write_shift(2, c);
out.write_shift(1, ixfe||0/* & 0x3F */);
out.write_shift(1, ifmt||0/* & 0x3F */);
out.write_shift(1, 0);
return out;
}
/* BIFF2_??? where ??? is the name from [XLS] */
function parse_BIFF2STR(blob, length, opts) {
if(opts.biffguess && opts.biff == 5) opts.biff = 2;
var cell = parse_XLSCell(blob, 6);
++blob.l;
var cell = parse_XLSCell(blob, 7, opts);
var str = parse_XLUnicodeString2(blob, length-7, opts);
cell.t = 'str';
cell.val = str;
return cell;
}
function parse_BIFF2NUM(blob/*::, length*/) {
var cell = parse_XLSCell(blob, 6);
++blob.l;
function parse_BIFF2NUM(blob, length, opts) {
var cell = parse_XLSCell(blob, 7, opts);
var num = parse_Xnum(blob, 8);
cell.t = 'n';
cell.val = num;
return cell;
}
function write_BIFF2NUM(r/*:number*/, c/*:number*/, val/*:number*/) {
function write_BIFF2NUM(r/*:number*/, c/*:number*/, val/*:number*/, ixfe, ifmt) {
var out = new_buf(15);
write_BIFF2Cell(out, r, c);
write_BIFF2Cell(out, r, c, ixfe||0, ifmt||0);
out.write_shift(8, val, 'f');
return out;
}
function parse_BIFF2INT(blob) {
var cell = parse_XLSCell(blob, 6);
++blob.l;
function parse_BIFF2INT(blob, length, opts) {
var cell = parse_XLSCell(blob, 7, opts);
var num = blob.read_shift(2);
cell.t = 'n';
cell.val = num;
return cell;
}
function write_BIFF2INT(r/*:number*/, c/*:number*/, val/*:number*/) {
function write_BIFF2INT(r/*:number*/, c/*:number*/, val/*:number*/, ixfe/*:number*/, ifmt/*:number*/) {
var out = new_buf(9);
write_BIFF2Cell(out, r, c);
write_BIFF2Cell(out, r, c, ixfe||0, ifmt||0);
out.write_shift(2, val);
return out;
}
@ -1076,6 +1149,16 @@ function parse_BIFF2STRING(blob) {
return blob.read_shift(cch, 'sbcs-cont');
}
function parse_BIFF2BOOLERR(blob, length, opts) {
var bestart = blob.l + 7;
var cell = parse_XLSCell(blob, 6, opts);
blob.l = bestart;
var val = parse_Bes(blob, 2);
cell.val = val;
cell.t = (val === true || val === false) ? 'b' : 'e';
return cell;
}
/* TODO: convert to BIFF8 font struct */
function parse_BIFF2FONTXTRA(blob, length) {
blob.l += 6; // unknown
@ -1089,7 +1172,7 @@ function parse_BIFF2FONTXTRA(blob, length) {
/* TODO: parse rich text runs */
function parse_RString(blob, length, opts) {
var end = blob.l + length;
var cell = parse_XLSCell(blob, 6);
var cell = parse_XLSCell(blob, 6, opts);
var cch = blob.read_shift(2);
var str = parse_XLUnicodeStringNoCch(blob, cch, opts);
blob.l = end;
@ -1097,3 +1180,10 @@ function parse_RString(blob, length, opts) {
cell.val = str;
return cell;
}
function parse_BIFF4SheetInfo(blob/*::, length, opts*/) {
var flags = blob.read_shift(4);
var cch = blob.read_shift(1), name = blob.read_shift(cch, "sbcs");
if(name.length === 0) name = "Sheet1";
return { flags: flags, name:name };
}

View File

@ -1,69 +1,68 @@
/* 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,
/*::[*/0x03/*::]*/: 1252, /*::[*/0x04/*::]*/: 10000,
/*::[*/0x64/*::]*/: 852, /*::[*/0x65/*::]*/: 866,
/*::[*/0x66/*::]*/: 865, /*::[*/0x67/*::]*/: 861,
/*::[*/0x68/*::]*/: 895, /*::[*/0x69/*::]*/: 620,
/*::[*/0x6A/*::]*/: 737, /*::[*/0x6B/*::]*/: 857,
/*::[*/0x78/*::]*/: 950, /*::[*/0x79/*::]*/: 949,
/*::[*/0x7A/*::]*/: 936, /*::[*/0x7B/*::]*/: 932,
/*::[*/0x7C/*::]*/: 874, /*::[*/0x7D/*::]*/: 1255,
/*::[*/0x7E/*::]*/: 1256, /*::[*/0x96/*::]*/: 10007,
/*::[*/0x97/*::]*/: 10029, /*::[*/0x98/*::]*/: 10006,
/*::[*/0xC8/*::]*/: 1250, /*::[*/0xC9/*::]*/: 1251,
/*::[*/0xCA/*::]*/: 1254, /*::[*/0xCB/*::]*/: 1253,
0x01: 437, 0x02: 850,
0x03: 1252, 0x04: 10000,
0x64: 852, 0x65: 866,
0x66: 865, 0x67: 861,
0x68: 895, 0x69: 620,
0x6A: 737, 0x6B: 857,
0x78: 950, 0x79: 949,
0x7A: 936, 0x7B: 932,
0x7C: 874, 0x7D: 1255,
0x7E: 1256, 0x96: 10007,
0x97: 10029, 0x98: 10006,
0xC8: 1250, 0xC9: 1251,
0xCA: 1254, 0xCB: 1253,
/* shapefile DBF extension */
/*::[*/0x00/*::]*/: 20127, /*::[*/0x08/*::]*/: 865,
/*::[*/0x09/*::]*/: 437, /*::[*/0x0A/*::]*/: 850,
/*::[*/0x0B/*::]*/: 437, /*::[*/0x0D/*::]*/: 437,
/*::[*/0x0E/*::]*/: 850, /*::[*/0x0F/*::]*/: 437,
/*::[*/0x10/*::]*/: 850, /*::[*/0x11/*::]*/: 437,
/*::[*/0x12/*::]*/: 850, /*::[*/0x13/*::]*/: 932,
/*::[*/0x14/*::]*/: 850, /*::[*/0x15/*::]*/: 437,
/*::[*/0x16/*::]*/: 850, /*::[*/0x17/*::]*/: 865,
/*::[*/0x18/*::]*/: 437, /*::[*/0x19/*::]*/: 437,
/*::[*/0x1A/*::]*/: 850, /*::[*/0x1B/*::]*/: 437,
/*::[*/0x1C/*::]*/: 863, /*::[*/0x1D/*::]*/: 850,
/*::[*/0x1F/*::]*/: 852, /*::[*/0x22/*::]*/: 852,
/*::[*/0x23/*::]*/: 852, /*::[*/0x24/*::]*/: 860,
/*::[*/0x25/*::]*/: 850, /*::[*/0x26/*::]*/: 866,
/*::[*/0x37/*::]*/: 850, /*::[*/0x40/*::]*/: 852,
/*::[*/0x4D/*::]*/: 936, /*::[*/0x4E/*::]*/: 949,
/*::[*/0x4F/*::]*/: 950, /*::[*/0x50/*::]*/: 874,
/*::[*/0x57/*::]*/: 1252, /*::[*/0x58/*::]*/: 1252,
/*::[*/0x59/*::]*/: 1252, /*::[*/0x6C/*::]*/: 863,
/*::[*/0x86/*::]*/: 737, /*::[*/0x87/*::]*/: 852,
/*::[*/0x88/*::]*/: 857, /*::[*/0xCC/*::]*/: 1257,
0x00: 20127, 0x08: 865,
0x09: 437, 0x0A: 850,
0x0B: 437, 0x0D: 437,
0x0E: 850, 0x0F: 437,
0x10: 850, 0x11: 437,
0x12: 850, 0x13: 932,
0x14: 850, 0x15: 437,
0x16: 850, 0x17: 865,
0x18: 437, 0x19: 437,
0x1A: 850, 0x1B: 437,
0x1C: 863, 0x1D: 850,
0x1F: 852, 0x22: 852,
0x23: 852, 0x24: 860,
0x25: 850, 0x26: 866,
0x37: 850, 0x40: 852,
0x4D: 936, 0x4E: 949,
0x4F: 950, 0x50: 874,
0x57: 1252, 0x58: 1252,
0x59: 1252, 0x6C: 863,
0x86: 737, 0x87: 852,
0x88: 857, 0xCC: 1257,
/*::[*/0xFF/*::]*/: 16969
0xFF: 16969
};
var dbf_reverse_map = evert({
/*::[*/0x01/*::]*/: 437, /*::[*/0x02/*::]*/: 850,
/*::[*/0x03/*::]*/: 1252, /*::[*/0x04/*::]*/: 10000,
/*::[*/0x64/*::]*/: 852, /*::[*/0x65/*::]*/: 866,
/*::[*/0x66/*::]*/: 865, /*::[*/0x67/*::]*/: 861,
/*::[*/0x68/*::]*/: 895, /*::[*/0x69/*::]*/: 620,
/*::[*/0x6A/*::]*/: 737, /*::[*/0x6B/*::]*/: 857,
/*::[*/0x78/*::]*/: 950, /*::[*/0x79/*::]*/: 949,
/*::[*/0x7A/*::]*/: 936, /*::[*/0x7B/*::]*/: 932,
/*::[*/0x7C/*::]*/: 874, /*::[*/0x7D/*::]*/: 1255,
/*::[*/0x7E/*::]*/: 1256, /*::[*/0x96/*::]*/: 10007,
/*::[*/0x97/*::]*/: 10029, /*::[*/0x98/*::]*/: 10006,
/*::[*/0xC8/*::]*/: 1250, /*::[*/0xC9/*::]*/: 1251,
/*::[*/0xCA/*::]*/: 1254, /*::[*/0xCB/*::]*/: 1253,
/*::[*/0x00/*::]*/: 20127
0x01: 437, 0x02: 850,
0x03: 1252, 0x04: 10000,
0x64: 852, 0x65: 866,
0x66: 865, 0x67: 861,
0x68: 895, 0x69: 620,
0x6A: 737, 0x6B: 857,
0x78: 950, 0x79: 949,
0x7A: 936, 0x7B: 932,
0x7C: 874, 0x7D: 1255,
0x7E: 1256, 0x96: 10007,
0x97: 10029, 0x98: 10006,
0xC8: 1250, 0xC9: 1251,
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][\S\s]*$/g,"");
d.l += ww;
field.type = String.fromCharCode(d.read_shift(1));
if(ft != 0x02 && !l7) field.offset = d.read_shift(4);
@ -173,14 +172,17 @@ 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
if(s.trim().length) out[R][C] = s.replace(/\s+$/,"");
if(s.trim().length) out[R][C] = s.replace(/([^\s])\s+$/,"$1");
break;
case 'D':
if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8));
if(s.length === 8) {
out[R][C] = new Date(Date.UTC(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8), 0, 0, 0, 0));
if(!(opts && opts.UTC)) { out[R][C] = utc_to_local(out[R][C]); }
}
else out[R][C] = s;
break;
case 'F': out[R][C] = parseFloat(s.trim()); break;
@ -188,7 +190,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
case 'L': switch(s.trim().toUpperCase()) {
case 'Y': case 'T': out[R][C] = true; break;
case 'N': case 'F': out[R][C] = false; break;
case '': case '?': break;
case '': case '\x00': case '?': break;
default: throw new Error("DBF Unrecognized L:|" + s + "|");
} break;
case 'M': /* TODO: handle memo files */
@ -203,8 +205,13 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
// NOTE: dBASE specs appear to be incorrect
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 'T': {
var hi = dd.read_shift(4), lo = dd.read_shift(4);
if(hi == 0 && lo == 0) break;
out[R][C] = new Date((hi - 0x253D8C) * 0x5265C00 + lo);
if(!(opts && opts.UTC)) out[R][C] = utc_to_local(out[R][C]);
} 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 +225,45 @@ 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*/) {
if(!ws["!ref"]) throw new Error("Cannot export empty sheet to DBF");
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 +272,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 +290,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 +317,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 +353,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 +368,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,
@ -353,20 +404,25 @@ var SYLK = (function() {
KC:'Ç', Kc:'ç', q:'æ', z:'œ', a:'Æ', j:'Œ',
DN:209, Dn:241, Hy:255,
S:169, c:170, R:174, "B ":180,
/*::[*/0/*::]*/:176, /*::[*/1/*::]*/:177, /*::[*/2/*::]*/:178,
/*::[*/3/*::]*/:179, /*::[*/5/*::]*/:181, /*::[*/6/*::]*/:182,
/*::[*/7/*::]*/:183, Q:185, k:186, b:208, i:216, l:222, s:240, y:248,
0:176, 1:177, 2:178,
3:179, 5:181, 6:182,
7:183, Q:185, k:186, b:208, i:216, l:222, s:240, y:248,
"!":161, '"':162, "#":163, "(":164, "%":165, "'":167, "H ":168,
"+":171, ";":187, "<":188, "=":189, ">":190, "?":191, "{":223
}/*:any*/);
var sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1") + "|\\|)", "gm");
var sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1").replace("{", "\\{") + "|\\|)", "gm");
try {
sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1") + "|\\|)", "gm");
} catch(e) {}
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 */
/* TODO: evert the escape map */
var encode_sylk_str = function($$) { return $$.replace(/\n/g, "\x1b :").replace(/\r/g, "\x1b ="); };
/* 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 +435,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 +446,102 @@ var SYLK = (function() {
case 'ID': break; /* header */
case 'E': break; /* EOF */
case 'B': break; /* dimensions */
case 'O': break; /* options? */
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;
case 'O': /* workbook options */
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 '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':
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";
var cmnt = "";
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
case 'A': cmnt = record[rj].slice(1); break; // TODO: comment
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(val.charAt(0) == "#" && RBErr[val] != null) { cell_t = "e"; val = RBErr[val]; }
else if(!isNaN(fuzzynum(val))) {
val = fuzzynum(val);
if(next_cell_format !== null && SSF.is_date(next_cell_format)) val = numdate(val);
} else if(!isNaN(fuzzydate(val).getDate())) {
val = parseDate(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 = typeof val == "number" ? "n" : "d";
}
}
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;
}
if(cmnt) {
if(!arr[R][C]) arr[R][C] = { t: 'z' };
arr[R][C].c = [{a:"SheetJSYLK", t: cmnt}];
}
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 +550,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,34 +572,44 @@ 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*/ {
function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/)/*:string*/ {
var o = "C;Y" + (R+1) + ";X" + (C+1) + ";K";
switch(cell.t) {
case 'n':
o += (cell.v||0);
if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break;
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 'e': o += cell.w || BErr[cell.v] || cell.v; break;
case 'd': o += datenum(parseDate(cell.v, date1904), date1904); break;
case 's': o += '"' + (cell.v == null ? "" : String(cell.v)).replace(/"/g,"").replace(/;/g, ";;") + '"'; break;
}
return o;
}
function write_ws_cmnt_sylk(cmnt/*:Comment*/, R/*:number*/, C/*:number*/)/*:string*/ {
var o = "C;Y" + (R+1) + ";X" + (C+1) + ";A";
/* TODO: max length? */
o += encode_sylk_str(cmnt.map(function(c) { return c.t; }).join(""));
return o;
}
function write_ws_cols_sylk(out, cols) {
cols.forEach(function(col, i) {
var rec = "F;W" + (i+1) + " " + (i+1) + " ";
@ -536,40 +633,66 @@ var SYLK = (function() {
});
}
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
var preamble/*:Array<string>*/ = ["ID;PWXL;N;E"], o/*:Array<string>*/ = [];
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = Array.isArray(ws);
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/, wb/*:?WorkBook*/)/*:string*/ {
if(!opts) opts = {}; opts._formats = ["General"];
/* TODO: codepage */
var preamble/*:Array<string>*/ = ["ID;PSheetJS;N;E"], o/*:Array<string>*/ = [];
var r = safe_decode_range(ws['!ref']||"A1"), cell/*:Cell*/;
var dense = ws["!data"] != null;
var RS = "\r\n";
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
var _lastfmt = "General";
preamble.push("P;PGeneral");
/* Excel has been inconsistent in comment placement */
var R = r.s.r, C = r.s.c, p = [];
if(ws["!ref"]) for(R = r.s.r; R <= r.e.r; ++R) {
if(dense && !ws["!data"][R]) continue;
p = [];
for(C = r.s.c; C <= r.e.c; ++C) {
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
if(!cell || !cell.c) continue;
p.push(write_ws_cmnt_sylk(cell.c, R, C));
}
if(p.length) o.push(p.join(RS));
}
if(ws["!ref"]) for(R = r.s.r; R <= r.e.r; ++R) {
if(dense && !ws["!data"][R]) continue;
p = [];
for(C = r.s.c; C <= r.e.c; ++C) {
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
if((cell.z||(cell.t == "d" ? table_fmt[14] : "General")) != _lastfmt) {
var ifmt = opts._formats.indexOf(cell.z);
if(ifmt == -1) { opts._formats.push(cell.z); ifmt = opts._formats.length - 1; preamble.push("P;P" + cell.z.replace(/;/g, ";;")); }
p.push("F;P" + ifmt + ";Y" + (R+1) + ";X" + (C+1));
}
p.push(write_ws_cell_sylk(cell, ws, R, C, opts, d1904));
}
o.push(p.join(RS));
}
preamble.push("F;P0;DG0G8;M255");
if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
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(" "));
for(var R = r.s.r; R <= r.e.r; ++R) {
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 || (cell.v == null && (!cell.f || cell.F))) continue;
o.push(write_ws_cell_sylk(cell, ws, R, C, opts));
}
}
if(ws["!ref"]) 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");
delete opts._formats;
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);
@ -596,7 +719,10 @@ var DIF = (function() {
if(data === 'TRUE') arr[R][C] = true;
else if(data === 'FALSE') arr[R][C] = false;
else if(!isNaN(fuzzynum(value))) arr[R][C] = fuzzynum(value);
else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value);
else if(!isNaN(fuzzydate(value).getDate())) {
arr[R][C] = parseDate(value);
if(!(opts && opts.UTC)) { arr[R][C] = utc_to_local(arr[R][C]); }
}
else arr[R][C] = value;
++C; break;
case 1:
@ -613,64 +739,62 @@ 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;
if(!ws["!ref"]) throw new Error("Cannot export empty sheet to DIF");
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 +802,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 +857,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 +877,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 +902,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 */}
@ -817,18 +941,18 @@ var PRN = (function() {
// List of accepted CSV separators
var guess_seps = {
/*::[*/0x2C/*::]*/: ',',
/*::[*/0x09/*::]*/: "\t",
/*::[*/0x3B/*::]*/: ';',
/*::[*/0x7C/*::]*/: '|'
0x2C: ',',
0x09: "\t",
0x3B: ';',
0x7C: '|'
};
// CSV separator weights to be used in case of equal numbers
var guess_sep_weights = {
/*::[*/0x2C/*::]*/: 3,
/*::[*/0x09/*::]*/: 2,
/*::[*/0x3B/*::]*/: 1,
/*::[*/0x7C/*::]*/: 0
0x2C: 3,
0x09: 2,
0x3B: 1,
0x7C: 0
};
function guess_sep(str) {
@ -859,7 +983,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,36 +1002,37 @@ 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);
/* TODO: fuzzy parsers should pass back assumed number format */
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(o.cellText !== false) cell.w = s;
if(s.length === 0) cell.t = 'z';
else if(o.raw) { cell.t = 's'; cell.v = s; }
else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; }
else if(s.charCodeAt(0) == 0x3D) {
if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); }
else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.slice(1); }
else if(fuzzyfmla(s)) { cell.t = 's'; cell.f = s.slice(1); cell.v = s; }
else { cell.t = 's'; cell.v = s; } }
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];
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);
else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; cell.v = v; }
else if(!isNaN((v = fuzzydate(s)).getDate()) || _re && s.match(_re)) {
cell.z = o.dateNF || table_fmt[14];
if(_re && s.match(_re)){ var news=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); v = parseDate(news); if(o && o.UTC === false) v = utc_to_local(v); }
else if(o && o.UTC === false) v = utc_to_local(v);
else if(o.cellText !== false && o.dateNF) cell.w = SSF_format(cell.z, v);
if(o.cellDates) { cell.t = 'd'; cell.v = v; }
else { cell.t = 'n'; cell.v = datenum(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 +1041,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 +1065,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 +1078,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);
}
@ -957,13 +1087,14 @@ var PRN = (function() {
function sheet_to_prn(ws/*:Worksheet*//*::, opts:?any*/)/*:string*/ {
var o/*:Array<string>*/ = [];
if(!ws["!ref"]) return "";
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 += " ";
@ -990,7 +1121,7 @@ function read_wb_ID(d, opts) {
return out;
} catch(e) {
o.WTF = OLD_WTF;
if(!e.message.match(/SYLK bad record ID/) && OLD_WTF) throw e;
if((e.message.indexOf("SYLK bad record ID") == -1) && OLD_WTF) throw e;
return PRN.to_workbook(d, opts);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@ function parse_rpr(rpr) {
var pass = false;
if(m) for(;i!=m.length; ++i) {
var y = parsexmltag(m[i]);
switch(y[0].replace(/\w*:/g,"")) {
switch(y[0].replace(/<\w*:/g,"<")) {
/* 18.8.12 condense CT_BooleanProperty */
/* ** not required . */
case '<condense': break;
@ -106,16 +106,15 @@ function parse_rpr(rpr) {
return font;
}
var parse_rs = (function() {
var tregex = matchtag("t"), rpregex = matchtag("rPr");
var parse_rs = /*#__PURE__*/(function() {
/* 18.4.4 r CT_RElt */
function parse_r(r) {
/* 18.4.12 t ST_Xstring */
var t = r.match(tregex)/*, cp = 65001*/;
var t = str_match_xml_ns(r, "t")/*, cp = 65001*/;
if(!t) return {t:"s", v:""};
var o/*:Cell*/ = ({t:'s', v:unescapexml(t[1])}/*:any*/);
var rpr = r.match(rpregex);
var rpr = str_match_xml_ns(r, "rPr");
if(rpr) o.s = parse_rpr(rpr[1]);
return o;
}
@ -127,7 +126,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>*/ = [];
@ -168,8 +167,7 @@ var rs_to_html = (function parse_rs_factory() {
})();
/* 18.4.8 si CT_Rst */
var sitregex = /<(?:\w+:)?t[^>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r>/;
var sirphregex = /<(?:\w+:)?rPh.*?>([\s\S]*?)<\/(?:\w+:)?rPh>/g;
var sitregex = /<(?:\w+:)?t\b[^<>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r\b[^<>]*>/;
function parse_si(x, opts) {
var html = opts ? opts.cellHTML : true;
var z = {};
@ -178,14 +176,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((str_remove_xml_ns_g(x, "rPh").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) */
@ -194,32 +192,30 @@ function parse_si(x, opts) {
}
/* 18.4 Shared String Table */
var sstr0 = /<(?:\w+:)?sst([^>]*)>([\s\S]*)<\/(?:\w+:)?sst>/;
var sstr1 = /<(?:\w+:)?(?:si|sstItem)>/g;
var sstr2 = /<\/(?:\w+:)?(?:si|sstItem)>/;
function parse_sst_xml(data/*:string*/, opts)/*:SST*/ {
var s/*:SST*/ = ([]/*:any*/), ss = "";
if(!data) return s;
/* 18.4.9 sst CT_Sst */
var sst = data.match(sstr0);
var sst = str_match_xml_ns(data, "sst");
if(sst) {
ss = sst[2].replace(sstr1,"").split(sstr2);
ss = sst[1].replace(sstr1,"").split(sstr2);
for(var i = 0; i != ss.length; ++i) {
var o = parse_si(ss[i].trim(), opts);
if(o != null) s[s.length] = o;
}
sst = parsexmltag(sst[1]); s.Count = sst.count; s.Unique = sst.uniqueCount;
sst = parsexmltag(sst[0].slice(0, sst[0].indexOf(">"))); s.Count = sst.count; s.Unique = sst.uniqueCount;
}
return s;
}
RELS.SST = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
var straywsregex = /^\s|\s$|[\t\n\r]/;
function write_sst_xml(sst/*:SST*/, opts)/*:string*/ {
if(!opts.bookSST) return "";
var o = [XML_HEADER];
o[o.length] = (writextag('sst', null, {
xmlns: XMLNS.main[0],
xmlns: XMLNS_main[0],
count: sst.Count,
uniqueCount: sst.Unique
}));
@ -230,6 +226,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>";
}

View File

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

View File

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

View File

@ -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_ng(str, "\\trowd", "\\row");
if (!rows)
throw new Error("RTF missing table");
var range = { s: { c: 0, r: 0 }, e: { c: 0, r: rows.length - 1 } };
var row = [];
rows.forEach(function(rowtf, R) {
if (dense)
row = ws["!data"][R] = [];
var rtfre = /\\[\w\-]+\b/g;
var last_index = 0;
var res;
var C = -1;
var payload = [];
while ((res = rtfre.exec(rowtf)) != null) {
var data = rowtf.slice(last_index, rtfre.lastIndex - res[0].length);
if (data.charCodeAt(0) == 32)
data = data.slice(1);
if (data.length)
payload.push(data);
switch (res[0]) {
case "\\cell":
++C;
if (payload.length) {
var cell = { v: payload.join(""), t: "s" };
if (cell.v == "TRUE" || cell.v == "FALSE") {
cell.v = cell.v == "TRUE";
cell.t = "b";
} else if (!isNaN(fuzzynum(cell.v))) {
cell.t = "n";
if (o.cellText !== false)
cell.w = cell.v;
cell.v = fuzzynum(cell.v);
}
if (dense)
row[C] = cell;
else
ws[encode_cell({ r: R, c: C })] = cell;
}
payload = [];
break;
case "\\par":
payload.push("\n");
break;
}
last_index = rtfre.lastIndex;
}
if (C > range.e.c)
range.e.c = C;
});
ws["!ref"] = encode_range(range);
return ws;
}
function rtf_to_workbook(d, opts) {
var wb = sheet_to_workbook(rtf_to_sheet(d, opts), opts);
wb.bookType = "rtf";
return wb;
}
function sheet_to_rtf(ws, opts) {
var o = ["{\\rtf1\\ansi"];
if (!ws["!ref"])
return o[0] + "}";
var r = safe_decode_range(ws["!ref"]), cell;
var dense = ws["!data"] != null, row = [];
for (var R = r.s.r; R <= r.e.r; ++R) {
o.push("\\trowd\\trautofit1");
for (var C = r.s.c; C <= r.e.c; ++C)
o.push("\\cellx" + (C + 1));
o.push("\\pard\\intbl");
if (dense)
row = ws["!data"][R] || [];
for (C = r.s.c; C <= r.e.c; ++C) {
var coord = encode_cell({ r: R, c: C });
cell = dense ? row[C] : ws[coord];
if (!cell || cell.v == null && (!cell.f || cell.F)) {
o.push(" \\cell");
continue;
}
o.push(" " + (cell.w || (format_cell(cell), cell.w) || "").replace(/[\r\n]/g, "\\par "));
o.push("\\cell");
}
o.push("\\pard\\intbl\\row");
}
return o.join("") + "}";
}

View File

@ -3,7 +3,7 @@ function parse_borders(t, styles, themes, opts) {
styles.Borders = [];
var border = {};
var pass = false;
(t[0].match(tagregex)||[]).forEach(function(x) {
(t.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<borders': case '<borders>': case '</borders>': break;
@ -78,7 +78,7 @@ function parse_fills(t, styles, themes, opts) {
styles.Fills = [];
var fill = {};
var pass = false;
(t[0].match(tagregex)||[]).forEach(function(x) {
(t.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<fills': case '<fills>': case '</fills>': break;
@ -144,7 +144,7 @@ function parse_fonts(t, styles, themes, opts) {
styles.Fonts = [];
var font = {};
var pass = false;
(t[0].match(tagregex)||[]).forEach(function(x) {
(t.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<fonts': case '<fonts>': case '</fonts>': break;
@ -262,9 +262,9 @@ function parse_fonts(t, styles, themes, opts) {
/* 18.8.31 numFmts CT_NumFmts */
function parse_numFmts(t, styles, opts) {
styles.NumberFmt = [];
var k/*Array<number>*/ = (keys(SSF._table)/*:any*/);
for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
var m = t[0].match(tagregex);
var k/*Array<number>*/ = (keys(table_fmt)/*:any*/);
for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = table_fmt[k[i]];
var m = t.match(tagregex);
if(!m) return;
for(i=0; i < m.length; ++i) {
var y = parsexmltag(m[i]);
@ -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;
@ -305,13 +305,13 @@ function parse_cellXfs(t, styles, opts) {
styles.CellXf = [];
var xf;
var pass = false;
(t[0].match(tagregex)||[]).forEach(function(x) {
(t.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x), i = 0;
switch(strip_ns(y[0])) {
case '<cellXfs': case '<cellXfs>': case '<cellXfs/>': case '</cellXfs>': break;
/* 18.8.45 xf CT_Xf */
case '<xf': case '<xf/>':
case '<xf': case '<xf/>': case '<xf>':
xf = y;
delete xf[0];
for(i = 0; i < cellXF_uint.length; ++i) if(xf[cellXF_uint[i]])
@ -325,7 +325,7 @@ function parse_cellXfs(t, styles, opts) {
case '</xf>': break;
/* 18.8.1 alignment CT_CellAlignment */
case '<alignment': case '<alignment/>':
case '<alignment': case '<alignment/>': case '<alignment>':
var alignment = {};
if(y.vertical) alignment.vertical = y.vertical;
if(y.horizontal) alignment.horizontal = y.horizontal;
@ -337,12 +337,12 @@ function parse_cellXfs(t, styles, opts) {
case '</alignment>': break;
/* 18.8.33 protection CT_CellProtection */
case '<protection':
case '<protection': case '<protection>':
break;
case '</protection>': case '<protection/>': break;
/* note: sometimes mc:AlternateContent appears bare */
case '<AlternateContent': pass = true; break;
case '<AlternateContent': case '<AlternateContent>': pass = true; break;
case '</AlternateContent>': pass = false; break;
/* 18.2.10 extLst CT_ExtensionList ? */
@ -369,37 +369,32 @@ function write_cellXfs(cellXfs)/*:string*/ {
}
/* 18.8 Styles CT_Stylesheet*/
var parse_sty_xml= (function make_pstyx() {
var numFmtRegex = /<(?:\w+:)?numFmts([^>]*)>[\S\s]*?<\/(?:\w+:)?numFmts>/;
var cellXfRegex = /<(?:\w+:)?cellXfs([^>]*)>[\S\s]*?<\/(?:\w+:)?cellXfs>/;
var fillsRegex = /<(?:\w+:)?fills([^>]*)>[\S\s]*?<\/(?:\w+:)?fills>/;
var fontsRegex = /<(?:\w+:)?fonts([^>]*)>[\S\s]*?<\/(?:\w+:)?fonts>/;
var bordersRegex = /<(?:\w+:)?borders([^>]*)>[\S\s]*?<\/(?:\w+:)?borders>/;
var parse_sty_xml= /*#__PURE__*/(function make_pstyx() {
return function parse_sty_xml(data, themes, opts) {
var styles = {};
if(!data) return styles;
data = data.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
data = remove_doctype(str_remove_ng(data, "<!--", "-->"));
/* 18.8.39 styleSheet CT_Stylesheet */
var t;
/* 18.8.31 numFmts CT_NumFmts ? */
if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts);
if((t=str_match_xml_ns(data, "numFmts"))) parse_numFmts(t[0], styles, opts);
/* 18.8.23 fonts CT_Fonts ? */
if((t=data.match(fontsRegex))) parse_fonts(t, styles, themes, opts);
if((t=str_match_xml_ns(data, "fonts"))) parse_fonts(t[0], styles, themes, opts);
/* 18.8.21 fills CT_Fills ? */
if((t=data.match(fillsRegex))) parse_fills(t, styles, themes, opts);
if((t=str_match_xml_ns(data, "fills"))) parse_fills(t[0], styles, themes, opts);
/* 18.8.5 borders CT_Borders ? */
if((t=data.match(bordersRegex))) parse_borders(t, styles, themes, opts);
if((t=str_match_xml_ns(data, "borders"))) parse_borders(t[0], styles, themes, opts);
/* 18.8.9 cellStyleXfs CT_CellStyleXfs ? */
/* 18.8.8 cellStyles CT_CellStyles ? */
/* 18.8.10 cellXfs CT_CellXfs ? */
if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts);
if((t=str_match_xml_ns(data, "cellXfs"))) parse_cellXfs(t[0], styles, opts);
/* 18.8.15 dxfs CT_Dxfs ? */
/* 18.8.42 tableStyles CT_TableStyles ? */
@ -410,15 +405,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>');

View File

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

View File

@ -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>',
@ -20,10 +18,12 @@ function parse_clrScheme(t, themes, opts) {
/* 20.1.2.3.32 srgbClr CT_SRgbColor */
case '<a:srgbClr':
color.rgb = y.val; break;
case '</a:srgbClr>': break;
/* 20.1.2.3.33 sysClr CT_SystemColor */
case '<a:sysClr':
color.rgb = y.lastClr; break;
case '</a:sysClr>': break;
/* 20.1.4.1.1 accent1 (Accent 1) */
/* 20.1.4.1.2 accent2 (Accent 2) */
@ -37,8 +37,10 @@ function parse_clrScheme(t, themes, opts) {
/* 20.1.4.1.19 hlink (Hyperlink) */
/* 20.1.4.1.22 lt1 (Light 1) */
/* 20.1.4.1.23 lt2 (Light 2) */
case '<a:dk1>': case '</a:dk1>':
case '<a:lt1>': case '</a:lt1>':
case '</a:dk1>':
case '</a:lt1>':
case '<a:dk1>':
case '<a:lt1>':
case '<a:dk2>': case '</a:dk2>':
case '<a:lt2>': case '</a:lt2>':
case '<a:accent1>': case '</a:accent1>':
@ -68,41 +70,35 @@ function parse_fontScheme(/*::t, themes, opts*/) { }
/* 20.1.4.1.15 fmtScheme CT_StyleMatrix */
function parse_fmtScheme(/*::t, themes, opts*/) { }
var clrsregex = /<a:clrScheme([^>]*)>[\s\S]*<\/a:clrScheme>/;
var fntsregex = /<a:fontScheme([^>]*)>[\s\S]*<\/a:fontScheme>/;
var fmtsregex = /<a:fmtScheme([^>]*)>[\s\S]*<\/a:fmtScheme>/;
/* 20.1.6.10 themeElements CT_BaseStyles */
function parse_themeElements(data, themes, opts) {
themes.themeElements = {};
var t;
[
/* clrScheme CT_ColorScheme */
['clrScheme', clrsregex, parse_clrScheme],
/* fontScheme CT_FontScheme */
['fontScheme', fntsregex, parse_fontScheme],
/* fmtScheme CT_StyleMatrix */
['fmtScheme', fmtsregex, parse_fmtScheme]
].forEach(function(m) {
if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements');
m[2](t, themes, opts);
});
}
/* clrScheme CT_ColorScheme */
if(!(t=str_match_xml(data, "a:clrScheme"))) throw new Error('clrScheme not found in themeElements');
parse_clrScheme(t, themes, opts);
var themeltregex = /<a:themeElements([^>]*)>[\s\S]*<\/a:themeElements>/;
/* fontScheme CT_FontScheme */
if(!(t=str_match_xml(data, "a:fontScheme"))) throw new Error('fontScheme not found in themeElements');
parse_fontScheme(t, themes, opts);
/* fmtScheme CT_StyleMatrix */
if(!(t=str_match_xml(data, "a:fmtScheme"))) throw new Error('fmtScheme not found in themeElements');
parse_fmtScheme(t, themes, opts);
}
/* 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 = {};
/* themeElements CT_BaseStyles */
if(!(t=data.match(themeltregex))) throw new Error('themeElements not found in theme');
if(!(t=str_match_xml(data, "a:themeElements"))) throw new Error('themeElements not found in theme');
parse_themeElements(t[0], themes, opts);
themes.raw = data;
return themes;

View File

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

View File

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

View File

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

View File

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

View File

@ -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 "??";
@ -16,7 +13,7 @@ function parse_drawing(data, rels/*:any*/) {
the actual type is based on the URI of the graphicData
TODO: handle embedded charts and other types of graphics
*/
var id = (data.match(/<c:chart [^>]*r:id="([^"]*)"/)||["",""])[1];
var id = (data.match(/<c:chart [^<>]*r:id="([^<>"]*)"/)||["",""])[1];
return rels['!id'][id].Target;
}

View File

@ -1,20 +1,64 @@
/* L.5.5.2 SpreadsheetML Comments + VML Schema */
var _shapeid = 1024;
function write_comments_vml(rId/*:number*/, comments) {
function parse_vml(data/*:string*/, sheet, comments) {
var cidx = 0;
(str_match_xml_ns_g(data, "shape")||[]).forEach(function(m) {
var type = "";
var hidden = true;
var aidx = -1;
var R = -1, C = -1;
m.replace(tagregex, function(x/*:string*/, idx/*:number*/) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<ClientData': if(y.ObjectType) type = y.ObjectType; break;
case '<Visible': case '<Visible/>': hidden = false; break;
case '<Row': case '<Row>': aidx = idx + x.length; break;
case '</Row>': R = +m.slice(aidx, idx).trim(); break;
case '<Column': case '<Column>': aidx = idx + x.length; break;
case '</Column>': C = +m.slice(aidx, idx).trim(); break;
}
return "";
});
switch(type) {
case 'Note':
var cell = ws_get_cell_stub(sheet, ((R>=0 && C>=0) ? encode_cell({r:R,c:C}) : comments[cidx].ref));
if(cell.c) {
cell.c.hidden = hidden;
}
++cidx;
break;
}
});
}
/* comment boxes */
function write_vml(rId/*:number*/, comments, ws) {
var csize = [21600, 21600];
/* L.5.2.1.2 Path Attribute */
var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(",");
var o = [
writextag("xml", null, { 'xmlns:v': XLMLNS.v, 'xmlns:o': XLMLNS.o, 'xmlns:x': XLMLNS.x, 'xmlns:mv': XLMLNS.mv }).replace(/\/>/,">"),
writextag("o:shapelayout", writextag("o:idmap", null, {'v:ext':"edit", 'data':rId}), {'v:ext':"edit"}),
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, ws)/*:string*/ {
var c = decode_cell(x[0]);
var fillopts = /*::(*/{'color2':"#BEFF82", 'type':"gradient"}/*:: :any)*/;
if(fillopts.type == "gradient") fillopts.angle = "-180";
@ -22,9 +66,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 +90,5 @@ function write_comments_vml(rId/*:number*/, comments) {
x[1].hidden ? '' : '<x:Visible/>',
'</x:ClientData>',
'</v:shape>'
]); });
o.push('</xml>');
return o.join("");
].join("");
}

View File

@ -1,17 +1,16 @@
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(r.r < 0 || r.c < 0) return;
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 +18,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);
});
}

View File

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

View File

@ -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,39 @@ 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));
if(c.T && c.ID && iauthor.indexOf("tc=" + c.ID) == -1) {
iauthor.push("tc=" + c.ID);
write_record(ba, 0x0278 /* BrtCommentAuthor */, write_BrtCommentAuthor("tc=" + c.ID));
}
});
});
write_record(ba, "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 _ia = -1;
if(c.ID) _ia = iauthor.indexOf("tc=" + c.ID);
if(_ia == -1 && comment[1][0].T && comment[1][0].ID) _ia = iauthor.indexOf("tc=" + comment[1][0].ID);
if(_ia == -1) _ia = iauthor.indexOf(c.a);
c.iauthor = _ia;
var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])};
write_record(ba, "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();
}

View File

@ -13,7 +13,7 @@ function fill_vba_xls(cfb, vba) {
vba.FullPaths.forEach(function(p, i) {
if (i == 0)
return;
var newpath = p.replace(/[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
var newpath = p.replace(/^[\/]*[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
if (newpath.slice(-1) !== "/")
CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content);
});

View File

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

View File

@ -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) {
@ -23,14 +23,17 @@ 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 crefregex = /(^|[^._A-Z0-9])(\$?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])(\$?)(\d{1,7})(?![_.\(A-Za-z0-9])/g;
try {
crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)(10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})(?![_.\(A-Za-z0-9])/g;
}catch(e){}
var a1_to_rc = /*#__PURE__*/(function(){
return function a1_to_rc(fstr/*:string*/, base/*:CellAddress*/) {
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
var c = decode_col($3) - ($2 ? 0 : base.c);
var r = decode_row($5) - ($4 ? 0 : base.r);
var R = (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;
});
};

View File

@ -495,114 +495,113 @@ function parse_PtgAttrNoop(blob/*::, length, opts*/) {
/* [MS-XLS] 2.5.198.25 ; [MS-XLSB] 2.5.97.16 */
var PtgTypes = {
/*::[*/0x01/*::]*/: { n:'PtgExp', f:parse_PtgExp },
/*::[*/0x02/*::]*/: { n:'PtgTbl', f:parse_PtgTbl },
/*::[*/0x03/*::]*/: { n:'PtgAdd', f:parseread1 },
/*::[*/0x04/*::]*/: { n:'PtgSub', f:parseread1 },
/*::[*/0x05/*::]*/: { n:'PtgMul', f:parseread1 },
/*::[*/0x06/*::]*/: { n:'PtgDiv', f:parseread1 },
/*::[*/0x07/*::]*/: { n:'PtgPower', f:parseread1 },
/*::[*/0x08/*::]*/: { n:'PtgConcat', f:parseread1 },
/*::[*/0x09/*::]*/: { n:'PtgLt', f:parseread1 },
/*::[*/0x0A/*::]*/: { n:'PtgLe', f:parseread1 },
/*::[*/0x0B/*::]*/: { n:'PtgEq', f:parseread1 },
/*::[*/0x0C/*::]*/: { n:'PtgGe', f:parseread1 },
/*::[*/0x0D/*::]*/: { n:'PtgGt', f:parseread1 },
/*::[*/0x0E/*::]*/: { n:'PtgNe', f:parseread1 },
/*::[*/0x0F/*::]*/: { n:'PtgIsect', f:parseread1 },
/*::[*/0x10/*::]*/: { n:'PtgUnion', f:parseread1 },
/*::[*/0x11/*::]*/: { n:'PtgRange', f:parseread1 },
/*::[*/0x12/*::]*/: { n:'PtgUplus', f:parseread1 },
/*::[*/0x13/*::]*/: { n:'PtgUminus', f:parseread1 },
/*::[*/0x14/*::]*/: { n:'PtgPercent', f:parseread1 },
/*::[*/0x15/*::]*/: { n:'PtgParen', f:parseread1 },
/*::[*/0x16/*::]*/: { n:'PtgMissArg', f:parseread1 },
/*::[*/0x17/*::]*/: { n:'PtgStr', f:parse_PtgStr },
/*::[*/0x1A/*::]*/: { n:'PtgSheet', f:parse_PtgSheet },
/*::[*/0x1B/*::]*/: { n:'PtgEndSheet', f:parse_PtgEndSheet },
/*::[*/0x1C/*::]*/: { n:'PtgErr', f:parse_PtgErr },
/*::[*/0x1D/*::]*/: { n:'PtgBool', f:parse_PtgBool },
/*::[*/0x1E/*::]*/: { n:'PtgInt', f:parse_PtgInt },
/*::[*/0x1F/*::]*/: { n:'PtgNum', f:parse_PtgNum },
/*::[*/0x20/*::]*/: { n:'PtgArray', f:parse_PtgArray },
/*::[*/0x21/*::]*/: { n:'PtgFunc', f:parse_PtgFunc },
/*::[*/0x22/*::]*/: { n:'PtgFuncVar', f:parse_PtgFuncVar },
/*::[*/0x23/*::]*/: { n:'PtgName', f:parse_PtgName },
/*::[*/0x24/*::]*/: { n:'PtgRef', f:parse_PtgRef },
/*::[*/0x25/*::]*/: { n:'PtgArea', f:parse_PtgArea },
/*::[*/0x26/*::]*/: { n:'PtgMemArea', f:parse_PtgMemArea },
/*::[*/0x27/*::]*/: { n:'PtgMemErr', f:parse_PtgMemErr },
/*::[*/0x28/*::]*/: { n:'PtgMemNoMem', f:parse_PtgMemNoMem },
/*::[*/0x29/*::]*/: { n:'PtgMemFunc', f:parse_PtgMemFunc },
/*::[*/0x2A/*::]*/: { n:'PtgRefErr', f:parse_PtgRefErr },
/*::[*/0x2B/*::]*/: { n:'PtgAreaErr', f:parse_PtgAreaErr },
/*::[*/0x2C/*::]*/: { n:'PtgRefN', f:parse_PtgRefN },
/*::[*/0x2D/*::]*/: { n:'PtgAreaN', f:parse_PtgAreaN },
/*::[*/0x2E/*::]*/: { n:'PtgMemAreaN', f:parse_PtgMemAreaN },
/*::[*/0x2F/*::]*/: { n:'PtgMemNoMemN', f:parse_PtgMemNoMemN },
/*::[*/0x39/*::]*/: { n:'PtgNameX', f:parse_PtgNameX },
/*::[*/0x3A/*::]*/: { n:'PtgRef3d', f:parse_PtgRef3d },
/*::[*/0x3B/*::]*/: { n:'PtgArea3d', f:parse_PtgArea3d },
/*::[*/0x3C/*::]*/: { n:'PtgRefErr3d', f:parse_PtgRefErr3d },
/*::[*/0x3D/*::]*/: { n:'PtgAreaErr3d', f:parse_PtgAreaErr3d },
/*::[*/0xFF/*::]*/: {}
0x01: { n:'PtgExp', f:parse_PtgExp },
0x02: { n:'PtgTbl', f:parse_PtgTbl },
0x03: { n:'PtgAdd', f:parseread1 },
0x04: { n:'PtgSub', f:parseread1 },
0x05: { n:'PtgMul', f:parseread1 },
0x06: { n:'PtgDiv', f:parseread1 },
0x07: { n:'PtgPower', f:parseread1 },
0x08: { n:'PtgConcat', f:parseread1 },
0x09: { n:'PtgLt', f:parseread1 },
0x0A: { n:'PtgLe', f:parseread1 },
0x0B: { n:'PtgEq', f:parseread1 },
0x0C: { n:'PtgGe', f:parseread1 },
0x0D: { n:'PtgGt', f:parseread1 },
0x0E: { n:'PtgNe', f:parseread1 },
0x0F: { n:'PtgIsect', f:parseread1 },
0x10: { n:'PtgUnion', f:parseread1 },
0x11: { n:'PtgRange', f:parseread1 },
0x12: { n:'PtgUplus', f:parseread1 },
0x13: { n:'PtgUminus', f:parseread1 },
0x14: { n:'PtgPercent', f:parseread1 },
0x15: { n:'PtgParen', f:parseread1 },
0x16: { n:'PtgMissArg', f:parseread1 },
0x17: { n:'PtgStr', f:parse_PtgStr },
0x1A: { n:'PtgSheet', f:parse_PtgSheet },
0x1B: { n:'PtgEndSheet', f:parse_PtgEndSheet },
0x1C: { n:'PtgErr', f:parse_PtgErr },
0x1D: { n:'PtgBool', f:parse_PtgBool },
0x1E: { n:'PtgInt', f:parse_PtgInt },
0x1F: { n:'PtgNum', f:parse_PtgNum },
0x20: { n:'PtgArray', f:parse_PtgArray },
0x21: { n:'PtgFunc', f:parse_PtgFunc },
0x22: { n:'PtgFuncVar', f:parse_PtgFuncVar },
0x23: { n:'PtgName', f:parse_PtgName },
0x24: { n:'PtgRef', f:parse_PtgRef },
0x25: { n:'PtgArea', f:parse_PtgArea },
0x26: { n:'PtgMemArea', f:parse_PtgMemArea },
0x27: { n:'PtgMemErr', f:parse_PtgMemErr },
0x28: { n:'PtgMemNoMem', f:parse_PtgMemNoMem },
0x29: { n:'PtgMemFunc', f:parse_PtgMemFunc },
0x2A: { n:'PtgRefErr', f:parse_PtgRefErr },
0x2B: { n:'PtgAreaErr', f:parse_PtgAreaErr },
0x2C: { n:'PtgRefN', f:parse_PtgRefN },
0x2D: { n:'PtgAreaN', f:parse_PtgAreaN },
0x2E: { n:'PtgMemAreaN', f:parse_PtgMemAreaN },
0x2F: { n:'PtgMemNoMemN', f:parse_PtgMemNoMemN },
0x39: { n:'PtgNameX', f:parse_PtgNameX },
0x3A: { n:'PtgRef3d', f:parse_PtgRef3d },
0x3B: { n:'PtgArea3d', f:parse_PtgArea3d },
0x3C: { n:'PtgRefErr3d', f:parse_PtgRefErr3d },
0x3D: { n:'PtgAreaErr3d', f:parse_PtgAreaErr3d },
0xFF: {}
};
/* These are duplicated in the PtgTypes table */
var PtgDupes = {
/*::[*/0x40/*::]*/: 0x20, /*::[*/0x60/*::]*/: 0x20,
/*::[*/0x41/*::]*/: 0x21, /*::[*/0x61/*::]*/: 0x21,
/*::[*/0x42/*::]*/: 0x22, /*::[*/0x62/*::]*/: 0x22,
/*::[*/0x43/*::]*/: 0x23, /*::[*/0x63/*::]*/: 0x23,
/*::[*/0x44/*::]*/: 0x24, /*::[*/0x64/*::]*/: 0x24,
/*::[*/0x45/*::]*/: 0x25, /*::[*/0x65/*::]*/: 0x25,
/*::[*/0x46/*::]*/: 0x26, /*::[*/0x66/*::]*/: 0x26,
/*::[*/0x47/*::]*/: 0x27, /*::[*/0x67/*::]*/: 0x27,
/*::[*/0x48/*::]*/: 0x28, /*::[*/0x68/*::]*/: 0x28,
/*::[*/0x49/*::]*/: 0x29, /*::[*/0x69/*::]*/: 0x29,
/*::[*/0x4A/*::]*/: 0x2A, /*::[*/0x6A/*::]*/: 0x2A,
/*::[*/0x4B/*::]*/: 0x2B, /*::[*/0x6B/*::]*/: 0x2B,
/*::[*/0x4C/*::]*/: 0x2C, /*::[*/0x6C/*::]*/: 0x2C,
/*::[*/0x4D/*::]*/: 0x2D, /*::[*/0x6D/*::]*/: 0x2D,
/*::[*/0x4E/*::]*/: 0x2E, /*::[*/0x6E/*::]*/: 0x2E,
/*::[*/0x4F/*::]*/: 0x2F, /*::[*/0x6F/*::]*/: 0x2F,
/*::[*/0x58/*::]*/: 0x22, /*::[*/0x78/*::]*/: 0x22,
/*::[*/0x59/*::]*/: 0x39, /*::[*/0x79/*::]*/: 0x39,
/*::[*/0x5A/*::]*/: 0x3A, /*::[*/0x7A/*::]*/: 0x3A,
/*::[*/0x5B/*::]*/: 0x3B, /*::[*/0x7B/*::]*/: 0x3B,
/*::[*/0x5C/*::]*/: 0x3C, /*::[*/0x7C/*::]*/: 0x3C,
/*::[*/0x5D/*::]*/: 0x3D, /*::[*/0x7D/*::]*/: 0x3D
0x40: 0x20, 0x60: 0x20,
0x41: 0x21, 0x61: 0x21,
0x42: 0x22, 0x62: 0x22,
0x43: 0x23, 0x63: 0x23,
0x44: 0x24, 0x64: 0x24,
0x45: 0x25, 0x65: 0x25,
0x46: 0x26, 0x66: 0x26,
0x47: 0x27, 0x67: 0x27,
0x48: 0x28, 0x68: 0x28,
0x49: 0x29, 0x69: 0x29,
0x4A: 0x2A, 0x6A: 0x2A,
0x4B: 0x2B, 0x6B: 0x2B,
0x4C: 0x2C, 0x6C: 0x2C,
0x4D: 0x2D, 0x6D: 0x2D,
0x4E: 0x2E, 0x6E: 0x2E,
0x4F: 0x2F, 0x6F: 0x2F,
0x58: 0x22, 0x78: 0x22,
0x59: 0x39, 0x79: 0x39,
0x5A: 0x3A, 0x7A: 0x3A,
0x5B: 0x3B, 0x7B: 0x3B,
0x5C: 0x3C, 0x7C: 0x3C,
0x5D: 0x3D, 0x7D: 0x3D
};
(function(){for(var y in PtgDupes) PtgTypes[y] = PtgTypes[PtgDupes[y]];})();
var Ptg18 = {
/*::[*/0x01/*::]*/: { n:'PtgElfLel', f:parse_PtgElfLel },
/*::[*/0x02/*::]*/: { n:'PtgElfRw', f:parse_PtgElfRw },
/*::[*/0x03/*::]*/: { n:'PtgElfCol', f:parse_PtgElfCol },
/*::[*/0x06/*::]*/: { n:'PtgElfRwV', f:parse_PtgElfRwV },
/*::[*/0x07/*::]*/: { n:'PtgElfColV', f:parse_PtgElfColV },
/*::[*/0x0A/*::]*/: { n:'PtgElfRadical', f:parse_PtgElfRadical },
/*::[*/0x0B/*::]*/: { n:'PtgElfRadicalS', f:parse_PtgElfRadicalS },
/*::[*/0x0D/*::]*/: { n:'PtgElfColS', f:parse_PtgElfColS },
/*::[*/0x0F/*::]*/: { n:'PtgElfColSV', f:parse_PtgElfColSV },
/*::[*/0x10/*::]*/: { n:'PtgElfRadicalLel', f:parse_PtgElfRadicalLel },
/*::[*/0x19/*::]*/: { n:'PtgList', f:parse_PtgList },
/*::[*/0x1D/*::]*/: { n:'PtgSxName', f:parse_PtgSxName },
/*::[*/0xFF/*::]*/: {}
0x01: { n:'PtgElfLel', f:parse_PtgElfLel },
0x02: { n:'PtgElfRw', f:parse_PtgElfRw },
0x03: { n:'PtgElfCol', f:parse_PtgElfCol },
0x06: { n:'PtgElfRwV', f:parse_PtgElfRwV },
0x07: { n:'PtgElfColV', f:parse_PtgElfColV },
0x0A: { n:'PtgElfRadical', f:parse_PtgElfRadical },
0x0B: { n:'PtgElfRadicalS', f:parse_PtgElfRadicalS },
0x0D: { n:'PtgElfColS', f:parse_PtgElfColS },
0x0F: { n:'PtgElfColSV', f:parse_PtgElfColSV },
0x10: { n:'PtgElfRadicalLel', f:parse_PtgElfRadicalLel },
0x19: { n:'PtgList', f:parse_PtgList },
0x1D: { n:'PtgSxName', f:parse_PtgSxName },
0xFF: {}
};
var Ptg19 = {
/*::[*/0x00/*::]*/: { n:'PtgAttrNoop', f:parse_PtgAttrNoop },
/*::[*/0x01/*::]*/: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
/*::[*/0x02/*::]*/: { n:'PtgAttrIf', f:parse_PtgAttrIf },
/*::[*/0x04/*::]*/: { n:'PtgAttrChoose', f:parse_PtgAttrChoose },
/*::[*/0x08/*::]*/: { n:'PtgAttrGoto', f:parse_PtgAttrGoto },
/*::[*/0x10/*::]*/: { n:'PtgAttrSum', f:parse_PtgAttrSum },
/*::[*/0x20/*::]*/: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
/*::[*/0x40/*::]*/: { n:'PtgAttrSpace', f:parse_PtgAttrSpace },
/*::[*/0x41/*::]*/: { n:'PtgAttrSpaceSemi', f:parse_PtgAttrSpaceSemi },
/*::[*/0x80/*::]*/: { n:'PtgAttrIfError', f:parse_PtgAttrIfError },
/*::[*/0xFF/*::]*/: {}
0x00: { n:'PtgAttrNoop', f:parse_PtgAttrNoop },
0x01: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
0x02: { n:'PtgAttrIf', f:parse_PtgAttrIf },
0x04: { n:'PtgAttrChoose', f:parse_PtgAttrChoose },
0x08: { n:'PtgAttrGoto', f:parse_PtgAttrGoto },
0x10: { n:'PtgAttrSum', f:parse_PtgAttrSum },
0x20: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
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];
}

View File

@ -68,8 +68,7 @@ function write_FormulaValue(value) {
/* [MS-XLS] 2.4.127 TODO */
function parse_Formula(blob, length, opts) {
var end = blob.l + length;
var cell = parse_XLSCell(blob, 6);
if(opts.biff == 2) ++blob.l;
var cell = parse_XLSCell(blob, 6, opts);
var val = parse_FormulaValue(blob,8);
var flags = blob.read_shift(1);
if(opts.biff != 2) {
@ -124,3 +123,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(":");
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;

View File

@ -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(/!/,".").replace(/:/, ":.");
}

View File

@ -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;
@ -85,30 +81,30 @@ function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) {
return len;
}
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) {
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles, date1904) {
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);
var dd = datenum(p.v, !!date1904);
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, !!date1904),_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 {

View File

@ -2,16 +2,13 @@ function parse_ws_xml_dim(ws/*:Worksheet*/, s/*:string*/) {
var d = safe_decode_range(s);
if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d);
}
var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*[\/]?>/g;
var sheetdataregex = /<(?:\w+:)?sheetData[^>]*>([\s\S]*)<\/(?:\w+:)?sheetData>/;
var hlinkregex = /<(?:\w:)?hyperlink [^>]*>/mg;
var mergecregex = /<(?:\w+:)?mergeCell ref=["'][A-Z0-9:]+['"]\s*[\/]?>/g;
var hlinkregex = /<(?:\w+:)?hyperlink [^<>]*>/mg;
var dimregex = /"(\w*:\w*)"/;
var colregex = /<(?:\w:)?col\b[^>]*[\/]?>/g;
var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g;
var sheetprregex = /<(?:\w:)?sheetPr\b(?:[^>a-z][^>]*)?\/>/;
var sheetprregex2= /<(?:\w:)?sheetPr[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetPr)>/;
var svsregex = /<(?:\w:)?sheetViews[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetViews)>/;
var colregex = /<(?:\w+:)?col\b[^<>]*[\/]?>/g;
var afregex = /<(?:\w+:)?autoFilter[^>]*/g;
var marginregex= /<(?:\w+:)?pageMargins[^<>]*\/>/g;
var sheetprregex = /<(?:\w+:)?sheetPr\b[^<>]*?\/>/;
/* 18.3 Worksheets */
function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ {
@ -20,11 +17,11 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
/* 18.3.1.99 worksheet CT_Worksheet */
var s = 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 = "";
var mtch/*:?any*/ = data.match(sheetdataregex);
var mtch/*:?any*/ = str_match_xml_ns(data, "sheetData");
if(mtch) {
data1 = data.slice(0, mtch.index);
data2 = data.slice(mtch.index + mtch[0].length);
@ -33,17 +30,17 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
/* 18.3.1.82 sheetPr CT_SheetPr */
var sheetPr = data1.match(sheetprregex);
if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
else if((sheetPr = data1.match(sheetprregex2))) parse_ws_xml_sheetpr2(sheetPr[0], sheetPr[1]||"", s, wb, idx, styles, themes);
else if((sheetPr = str_match_xml_ns(data1, "sheetPr"))) parse_ws_xml_sheetpr2(sheetPr[0], sheetPr[1]||"", s, wb, idx, styles, themes);
/* 18.3.1.35 dimension CT_SheetDimension */
var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
if(ridx > 0) {
var ref = data1.slice(ridx,ridx+50).match(dimregex);
if(ref) 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 */
var svs = data1.match(svsregex);
var svs = str_match_xml_ns(data1, "sheetViews");
if(svs && svs[1]) parse_ws_xml_sheetviews(svs[1], wb);
/* 18.3.1.17 cols CT_Cols */
@ -55,7 +52,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
}
/* 18.3.1.80 sheetData CT_SheetData ? */
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles, wb);
/* 18.3.1.2 autoFilter CT_AutoFilter */
var afilter = data2.match(afregex);
@ -75,6 +72,11 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
var margins = data2.match(marginregex);
if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));
/* legacyDrawing */
var m;
if((m = data2.match(/legacyDrawing r:id="(.*?)"/))) s['!legrel'] = m[1];
if(opts && opts.nodim) refguess.s.c = refguess.s.r = 0;
if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
if(opts.sheetRows > 0 && s["!ref"]) {
var tmpref = safe_decode_range(s["!ref"]);
@ -90,6 +92,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
}
if(columns.length > 0) s["!cols"] = columns;
if(merges.length > 0) s["!merges"] = merges;
if(rels['!id'][s['!legrel']]) s['!legdrawel'] = rels['!id'][s['!legrel']];
return s;
}
@ -106,7 +109,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 +152,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 +168,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 +231,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 +239,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 +249,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*/ {
@ -256,26 +259,33 @@ function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
return writextag("sheetViews", writextag("sheetView", null, sview), {});
}
function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string*/ {
if(cell.v === undefined && typeof cell.f !== "string" || cell.t === 'z') return "";
function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb, date1904)/*:string*/ {
if(cell.c) ws['!comments'].push([ref, cell.c]);
if((cell.v === undefined || cell.t === "z" && !(opts||{}).sheetStubs) && typeof cell.f !== "string" && typeof cell.z == "undefined") return "";
var vv = "";
var oldt = cell.t, oldv = cell.v;
if(cell.t !== "z") switch(cell.t) {
case 'b': vv = cell.v ? "1" : "0"; break;
case 'n': vv = ''+cell.v; break;
case 'n':
if(isNaN(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x24]; } // #NUM!
else if(!isFinite(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x07]; } // #DIV/0!
else vv = ''+cell.v; break;
case 'e': vv = BErr[cell.v]; break;
case 'd':
if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
else {
if(opts && opts.cellDates) {
var _vv = parseDate(cell.v, date1904);
vv = _vv.toISOString();
if(_vv.getUTCFullYear() < 1900) vv = vv.slice(vv.indexOf("T") + 1).replace("Z","");
} else {
cell = dup(cell);
cell.t = 'n';
vv = ''+(cell.v = datenum(parseDate(cell.v)));
vv = ''+(cell.v = datenum(parseDate(cell.v, date1904), date1904));
}
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,26 +301,27 @@ 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 rregex = /r=["']([^"']*)["']/;
var refregex = /ref=["']([^"']*)["']/;
var match_v = matchtag("v"), match_f = matchtag("f");
return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles) {
return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles, wb) {
var ri = 0, x = "", cells/*:Array<string>*/ = [], cref/*:?Array<string>*/ = [], idx=0, i=0, cc=0, d="", p/*:any*/;
var tag, tagr = 0, tagc = 0;
var sstr, ftag;
@ -318,9 +329,10 @@ 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;
var date1904 = !!((wb||{}).WBProps||{}).date1904;
for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
x = marr[mt].trim();
var xlen = x.length;
@ -338,7 +350,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 +361,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;
}
@ -384,23 +398,31 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
d = x.slice(i);
p = ({t:""}/*:any*/);
if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
if((cref=str_match_xml_ns(d, "v"))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
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");
if(!opts.xlfn) p.f = _xlfn(p.f);
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
p.F = (d.match(refregex)||[])[1];
if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
} else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
// TODO: parse formula
ftag = parsexmltag(cref[0]);
var ___f = unescapexml(utf8read(cref[1]));
if(!opts.xlfn) ___f = _xlfn(___f);
sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
if((cref=str_match_xml_ns(d, "f"))!= null /*:: && cref != null*/) {
if(cref[1] == "") {
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
// TODO: parse formula
ftag = parsexmltag(cref[0]);
if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
}
} else {
/* TODO: match against XLSXFutureFunctions */
p.f=unescapexml(utf8read(cref[1]), true);
if(!opts.xlfn) p.f = _xlfn(p.f);
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
p.F = (d.match(refregex)||[])[1];
if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
} else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
// TODO: parse formula
ftag = parsexmltag(cref[0]);
var ___f = unescapexml(utf8read(cref[1]));
if(!opts.xlfn) ___f = _xlfn(___f);
sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
}
}
} else if((cref=d.match(/<f[^>]*\/>/))) {
} else if((cref=d.match(/<f[^<>]*\/>/))) {
ftag = parsexmltag(cref[0]);
if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
}
@ -442,11 +464,11 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
break;
case 'str':
p.t = "s";
p.v = (p.v!=null) ? utf8read(p.v) : '';
p.v = (p.v!=null) ? unescapexml(utf8read(p.v), true) : '';
if(opts.cellHTML) p.h = escapehtml(p.v);
break;
case 'inlineStr':
cref = d.match(isregex);
cref = str_match_xml_ns(d, "is");
p.t = 's';
if(cref != null && (sstr = parse_si(cref[1]))) {
p.v = sstr.t;
@ -455,8 +477,8 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
break;
case 'b': p.v = parsexmlbool(p.v); break;
case 'd':
if(opts.cellDates) p.v = parseDate(p.v, 1);
else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; }
if(opts.cellDates) p.v = parseDate(p.v, date1904);
else { p.v = datenum(parseDate(p.v, date1904), date1904); p.t = 'n'; }
break;
/* error string in .w, number in .v */
case 'e':
@ -475,16 +497,22 @@ 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); }
safe_format(p, fmtid, fillid, opts, themes, styles, date1904);
if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.v = numdate(p.v + (date1904 ? 1462 : 0)); p.t = typeof p.v == "number" ? 'n' : 'd'; }
if(tag.cm && opts.xlmeta) {
var cm = (opts.xlmeta.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,17 +521,18 @@ 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;
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
for(R = range.s.r; R <= range.e.r; ++R) {
r = [];
rr = encode_row(R);
for(C = range.s.c; C <= range.e.c; ++C) {
ref = cols[C] + rr;
var _cell = dense ? (ws[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);
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb, date1904)) != null) r.push(cell);
}
if(r.length > 0 || (rows && rows[R])) {
params = ({r:rr}/*:any*/);
@ -535,13 +564,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 = {};
@ -606,11 +633,12 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
if(!l[1].Target) return;
rel = ({"ref":l[0]}/*:any*/);
if(l[1].Target.charAt(0) != "#") {
rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), RELS.HLINK);
rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#[\s\S]*$/, ""), RELS.HLINK);
rel["r:id"] = "rId"+rId;
}
if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1));
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>";

View File

@ -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} };
@ -539,8 +542,9 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
XLSBRecordEnum[0x0010] = { n:"BrtShortReal", f:parse_BrtShortReal };
var cm, vm;
var date1904 = 1462 * +!!((wb||{}).WBProps||{}).date1904;
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' */
@ -582,9 +586,9 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 'str': p.t = 's'; p.v = val[1]; break;
case 'is': p.t = 's'; p.v = val[1].t; break;
}
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles, date1904>0);
C = val[0].c == -1 ? C + 1 : val[0].c;
if(opts.dense) { if(!s[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 +606,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 + date1904); if(_d) { p.t = 'd'; p.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
}
if(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 +621,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 +638,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 +652,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 +666,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;
@ -683,6 +687,10 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
}
break;
case 0x0227: /* 'BrtLegacyDrawing' */
if(val) s["!legrel"] = val;
break;
case 0x00A1: /* 'BrtBeginAFilter' */
s['!autofilter'] = { ref:encode_range(val) };
break;
@ -739,7 +747,6 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x0499: /* 'BrtFilter14' */
case 0x00A9: /* 'BrtIconFilter' */
case 0x049D: /* 'BrtIconFilter14' */
case 0x0227: /* 'BrtLegacyDrawing' */
case 0x0228: /* 'BrtLegacyDrawingHF' */
case 0x0295: /* 'BrtListPart' */
case 0x027F: /* 'BrtOleObject' */
@ -769,14 +776,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);
@ -799,71 +805,79 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
if(merges.length > 0) s["!merges"] = merges;
if(colinfo.length > 0) s["!cols"] = colinfo;
if(rowinfo.length > 0) s["!rows"] = rowinfo;
if(rels['!id'][s['!legrel']]) s['!legdrawel'] = rels['!id'][s['!legrel']];
return s;
}
/* TODO: something useful -- this is a stub */
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/)/*:boolean*/ {
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/, date1904/*:boolean*/)/*:boolean*/ {
var o/*:any*/ = ({r:R, c:C}/*:any*/);
if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
if(cell.v === undefined) return false;
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.v = datenum(parseDate(cell.v)); cell.t = 'n';
cell.z = cell.z || table_fmt[14];
cell.v = datenum(parseDate(cell.v, date1904), date1904); 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(isNaN(cell.v)) {
if(last_seen) write_record(ba, 0x000E /* BrtShortError */, write_BrtShortError({t:"e", v: 0x24}, o)); // #NUM!
else write_record(ba, 0x0003 /* BrtCellError */, write_BrtCellError({t:"e", v: 0x24}, o)); // #NUM!
} else if(!isFinite(cell.v)) {
if(last_seen) write_record(ba, 0x000E /* BrtShortError */, write_BrtShortError({t:"e", v: 0x07}, o)); // #DIV/0!
else write_record(ba, 0x0003 /* BrtCellError */, write_BrtCellError({t:"e", v: 0x07}, o)); // #DIV/0!
} else {
if(last_seen) write_record(ba, "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*/) {
function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols/*:Array<string>*/ = [];
write_record(ba, 'BrtBeginSheetData');
var dense = Array.isArray(ws);
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
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,42 +890,42 @@ 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);
last_seen = write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen, date1904);
}
}
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) {
/* *BrtHLink */
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));
var rId = add_rels(rels, -1, l[1].Target.replace(/#[\s\S]*$/, ""), RELS.HLINK);
write_record(ba, 0x01EE /* BrtHLink */, write_BrtHLink(l, rId));
});
delete ws['!links'];
}
@ -919,7 +933,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 +953,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 +1003,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 +1024,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 +1042,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();
}

View File

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

View File

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

View File

@ -113,16 +113,19 @@ 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;
badchars.forEach(function(c) {
if(n.indexOf(c) == -1) return;
if(!safe) throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
_good = false;
});
return _good;
try {
if(n == "") throw new Error("Sheet name cannot be blank");
if(n.length > 31) throw new Error("Sheet name cannot exceed 31 chars");
if(n.charCodeAt(0) == 0x27 || n.charCodeAt(n.length - 1) == 0x27) throw new Error("Sheet name cannot start or end with apostrophe (')");
if(n.toLowerCase() == "history") throw new Error("Sheet name cannot be 'History'");
badchars.forEach(function(c) {
if(n.indexOf(c) == -1) return;
throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
});
} catch(e) { if(safe) return false; throw e; }
return true;
}
function check_wb_names(N, S, codes) {
N.forEach(function(n,i) {
@ -140,5 +143,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 */
}

View File

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

View File

@ -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,19 @@ 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);
var formula;
var comment = "";
try {
formula = parse_XLSBNameParsedFormula(data, 0, opts);
try {
comment = parse_XLNullableWideString(data);
} catch(e){}
} catch(e) { console.error("Could not parse defined name " + name); }
if(flags & 0x20) name = "_xlnm." + name;
//if(0 /* fProc */) {
// unusedstring1: XLNullableWideString
// description: XLNullableWideString
@ -77,11 +85,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 +136,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);
@ -110,7 +147,7 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
case 0x0027: /* 'BrtName' */
if(val.Sheet != null) opts.SID = val.Sheet;
val.Ref = stringify_formula(val.Ptg, null, null, supbooks, opts);
val.Ref = val.Ptg ? stringify_formula(val.Ptg, null, null, supbooks, opts) : "#REF!";
delete opts.SID;
delete val.Ptg;
Names.push(val);
@ -169,20 +206,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 +232,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 +277,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 +334,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();
}

View File

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

View File

@ -1,5 +1,5 @@
var attregexg2=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
var attregex2=/([\w:]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;
var attregexg2=/\b((?:\w+:)?[\w]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
var attregex2=/\b((?:\w+:)?[\w]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;
function xlml_parsexmltag(tag/*:string*/, skip_root/*:?boolean*/) {
var words = tag.split(/\s+/);
var z/*:any*/ = ([]/*:any*/); if(!skip_root) z[0] = words[0];
@ -37,10 +37,13 @@ function xlml_parsexmltagobj(tag/*:string*/) {
// ----
function xlml_format(format, value)/*:string*/ {
/* map from xlml named formats to SSF TODO: localize */
var XLMLFormatMap/*: {[string]:string}*/;
function xlml_format(format, value, date1904)/*: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, {date1904: !!date1904});
}
function xlml_set_custprop(Custprops, key, cp, val/*:string*/) {
@ -56,24 +59,24 @@ function xlml_set_custprop(Custprops, key, cp, val/*:string*/) {
Custprops[unescapexml(key)] = oval;
}
function safe_format_xlml(cell/*:Cell*/, nf, o) {
function safe_format_xlml(cell/*:Cell*/, nf, o, date1904) {
if(cell.t === 'z') return;
if(!o || o.cellText !== false) try {
if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
else if(nf === "General") {
if(cell.t === 'n') {
if((cell.v|0) === cell.v) cell.w = 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);
else cell.w = xlml_format(nf||"General", cell.v, date1904);
} 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 + (date1904 ? 1462 : 0)); if(_d) { cell.t = 'd'; cell.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
}
} catch(e) { if(o.WTF) throw e; }
}
@ -89,17 +92,18 @@ function process_style_xlml(styles, stag, opts) {
}
/* TODO: there must exist some form of OSP-blessed spec */
function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o) {
function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o, date1904) {
var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
var interiors = [];
var i = 0;
if(sid === undefined && row) sid = row.StyleID;
if(sid === undefined && csty) sid = csty.StyleID;
while(styles[sid] !== undefined) {
if(styles[sid].nf) nf = styles[sid].nf;
if(styles[sid].Interior) interiors.push(styles[sid].Interior);
if(!styles[sid].Parent) break;
sid = styles[sid].Parent;
var ssid = styles[sid];
if(ssid.nf) nf = ssid.nf;
if(ssid.Interior) interiors.push(ssid.Interior);
if(!ssid.Parent) break;
sid = ssid.Parent;
}
switch(data.Type) {
case 'Boolean':
@ -108,13 +112,12 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
break;
case 'String':
cell.t = 's'; cell.r = xlml_fixstr(unescapexml(xml));
cell.v = (xml.indexOf("<") > -1 ? unescapexml(ss||xml).replace(/<.*?>/g, "") : cell.r); // todo: BR etc
cell.v = (xml.indexOf("<") > -1 ? unescapexml(ss||xml).replace(/<[^<>]*>/g, "") : cell.r); // todo: BR etc
break;
case 'DateTime':
if(xml.slice(-1) != "Z") xml += "Z";
cell.v = (parseDate(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
cell.v = datenum(parseDate(xml, date1904), date1904);
if(cell.v !== cell.v) cell.v = unescapexml(xml);
else if(cell.v<60) cell.v = cell.v -1;
if(!nf || nf == "General") nf = "yyyy-mm-dd";
/* falls through */
case 'Number':
@ -127,7 +130,7 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
else { cell.t = 's'; cell.v = xlml_fixstr(ss||xml); }
break;
}
safe_format_xlml(cell, nf, o);
safe_format_xlml(cell, nf, o, date1904);
if(o.cellFormula !== false) {
if(cell.Formula) {
var fstr = unescapexml(cell.Formula);
@ -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} };
@ -205,7 +222,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
var rowinfo/*:Array<RowInfo>*/ = [], rowobj = {}, cc = 0, rr = 0;
var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false} }/*:any*/), wsprops = {};
xlmlregex.lastIndex = 0;
str = str.replace(/<!--([\s\S]*?)-->/mg,"");
str = str_remove_ng(str, "<!--", "-->");
var raw_Rn3 = "";
while((Rn = xlmlregex.exec(str))) switch((Rn[3] = (raw_Rn3 = Rn[3]).toLowerCase())) {
case 'data' /*case 'Data'*/:
@ -215,16 +232,16 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
break;
}
if(state[state.length-1][1]) break;
if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]==/*"Comment"*/"comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts);
if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]==/*"Comment"*/"comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts, Workbook.WBProps.date1904);
else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; }
break;
case 'cell' /*case 'Cell'*/:
if(Rn[1]==='/'){
if(comments.length > 0) cell.c = comments;
if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== 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;
@ -426,6 +443,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
} else {
state.push([Rn[3], false]);
tmp = xlml_parsexmltag(Rn[0]);
if(!parsexmlbool(tmp["ShowAlways"]||"0")) comments.hidden = true;
comment = ({a:tmp.Author}/*:any*/);
}
break;
@ -517,6 +535,9 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
/*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
Workbook.WBProps.date1904 = true;
break;
case 'hidehorizontalscrollbar' /*case 'HideHorizontalScrollBar'*/: break;
case 'hideverticalscrollbar' /*case 'HideVerticalScrollBar'*/: break;
case 'hideworkbooktabs' /*case 'HideWorkbookTabs'*/: break;
case 'windowheight' /*case 'WindowHeight'*/: break;
case 'windowwidth' /*case 'WindowWidth'*/: break;
case 'windowtopx' /*case 'WindowTopX'*/: break;
@ -899,16 +920,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 +947,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 +959,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"); */
@ -1083,11 +1106,15 @@ function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workb
return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x});
}
function write_ws_xlml_comment(comments/*:Array<any>*/)/*:string*/ {
/* TODO: test multiple comments */
return comments.map(function(c) {
// TODO: formatted text
var t = xlml_unfixstr(c.t||"");
var d =writextag("ss:Data", t, {"xmlns":"http://www.w3.org/TR/REC-html40"});
return writextag("Comment", d, {"ss:Author":c.a});
var p = {};
if(c.a) p["ss:Author"] = c.a;
if(!comments.hidden) p["ss:ShowAlways"] = "1";
return writextag("Comment", d, p);
}).join("");
}
function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, addr)/*:string*/{
@ -1120,7 +1147,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 +1185,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 +1200,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 +1223,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;

View File

@ -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 == null) p.z = table_fmt[fmtid];
} catch(e) { if(opts.WTF) throw e; }
if(!opts || opts.cellText !== false) try {
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
else if(fmtid === 0 || fmtid == "General") {
if(p.t === 'n') {
if((p.v|0) === p.v) p.w = 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 + (date1904 ? 1462 : 0)); if(_d) { p.t = 'd'; p.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
}
}
@ -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;
@ -118,12 +119,13 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
var XFs = []; /* XF records */
var palette/*:Array<[number, number, number]>*/ = [];
var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false}, Views:[{}] }/*:any*/), wsprops = {};
var biff4w = false;
var get_rgb = function getrgb(icv/*:number*/)/*:[number, number, number]*/ {
if(icv < 8) return XLSIcv[icv];
if(icv < 64) return palette[icv-8] || XLSIcv[icv];
return XLSIcv[icv];
};
var process_cell_style = function pcs(cell, line/*:any*/, options) {
var process_cell_style = function pcs(line/*:any*/, options) {
var xfd = line.XF.data;
if(!xfd || !xfd.patternType || !options || !options.cellStyles) return;
line.s = ({}/*:any*/);
@ -133,9 +135,9 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; }
};
var addcell = function addcell(cell/*:any*/, line/*:any*/, options/*:any*/) {
if(file_depth > 1) return;
if(!biff4w && file_depth > 1) return;
if(options.sheetRows && cell.r >= options.sheetRows) return;
if(options.cellStyles && line.XF && line.XF.data) process_cell_style(cell, line, options);
if(options.cellStyles && line.XF && line.XF.data) process_cell_style(line, options);
delete line.ixfe; delete line.XF;
lastcell = cell;
last_cell = encode_cell(cell);
@ -156,8 +158,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 +182,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 +189,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 +202,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 +222,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 +250,33 @@ 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 0x0043: /* BIFF2XF */ case 0x0243: /* BIFF3XF */ case 0x0443: /* BIFF4XF */
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,26 +289,23 @@ 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': {
Directory[val.pos] = val;
case 0x0012 /* Protect */: out["!protect"] = val; break; /* for sheet or book */
case 0x0013 /* Password */: if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
case 0x0085 /* BoundSheet8 */: {
Directory[opts.biff == 4 ? opts.snames.length : val.pos] = val;
opts.snames.push(val.name);
} break;
case 'EOF': {
if(--file_depth) break;
case 0x000a /* EOF */: {
if(--file_depth ? !biff4w : biff4w) break;
if(range.e) {
if(range.e.r > 0 && range.e.c > 0) {
range.e.r--; range.e.c--;
@ -343,31 +326,33 @@ 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,
/*::[*/0x0409/*::]*/:4
0x0009: 2,
0x0209: 3,
0x0409: 4
}[RecordType] || {
/*::[*/0x0200/*::]*/:2,
/*::[*/0x0300/*::]*/:3,
/*::[*/0x0400/*::]*/:4,
/*::[*/0x0500/*::]*/:5,
/*::[*/0x0600/*::]*/:8,
/*::[*/0x0002/*::]*/:2,
/*::[*/0x0007/*::]*/:2
0x0200: 2,
0x0300: 3,
0x0400: 4,
0x0500: 5,
0x0600: 8,
0x0002: 2,
0x0007: 2
}[val.BIFFVer] || 8;
opts.biffguess = val.BIFFVer == 0;
if(val.BIFFVer == 0 && val.dt == 0x1000) { opts.biff = 5; seen_codepage = true; set_cp(opts.codepage = 28591); }
if(opts.biff == 4 && val.dt & 0x100) biff4w = true;
if(opts.biff == 8 && val.BIFFVer == 0 && val.dt == 16) opts.biff = 2;
if(file_depth++) break;
out = ((options.dense ? [] : {})/*:any*/);
if(file_depth++ && !biff4w) break;
out = ({}/*:any*/); if(options.dense) out["!data"] = [];
if(opts.biff < 8 && !seen_codepage) { seen_codepage = true; set_cp(opts.codepage = options.codepage || 1252); }
if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) {
if(opts.biff == 4 && biff4w) {
cur_sheet = (Directory[opts.snames.indexOf(cur_sheet)+1] || {name:""}).name;
} else if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) {
if(cur_sheet === "") cur_sheet = "Sheet1";
range = {s:{r:0,c:0},e:{r:0,c:0}};
/* fake BoundSheet8 */
@ -382,40 +367,38 @@ 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];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
case '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];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
case '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];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
case '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*/);
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:j, r:val.r}, temp_val, options);
}
} break;
case '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,15 +408,15 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
var _fe = encode_cell({r:_fr, c:_fc});
if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
else temp_val.F = ((options.dense ? (out[_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];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell(val.cell, temp_val, options);
last_formula = val;
} break;
case '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');
@ -441,16 +424,16 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
if(options.cellFormula) {
temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
}
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell(last_formula.cell, temp_val, options);
last_formula = null;
} else throw new Error("String record expects Formula");
} break;
case '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,98 +441,95 @@ 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];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
break;
case '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];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
case '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*/);
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:_j, r:val.r}, temp_val, options);
}
} break;
case '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];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
break;
case '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] */
if(opts.biff == 4) {
case 0x041e /* Format */: { /* val = [id, fmt] */
if(opts.biff >= 3 && opts.biff <= 4) {
BIFF2FmtTable[BIFF2Fmt++] = val[1];
for(var b4idx = 0; b4idx < BIFF2Fmt + 163; ++b4idx) if(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': {
if(opts.biff <= 5 && opts.biff >= 2) break; /* TODO: BIFF5 */
cc = options.dense ? (out[val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
var noteobj = objects[val[2]];
case 0x001c /* Note */: {
/* TODO: comment continuation (row == -1 / 0xFFFF) */
cc = options.dense ? (out["!data"][val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
if(!cc) {
if(options.dense) {
if(!out[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*/);
}
@ -559,18 +539,16 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
range.s.c = Math.min(range.s.c, val[0].c);
}
if(!cc.c) cc.c = [];
cmnt = {a:val[1],t:noteobj.TxO.t};
if(opts.biff <= 5 && opts.biff >= 2) cmnt = {a:"SheetJ5", t:val[1]};
else {
var noteobj = objects[val[2]];
cmnt = {a:val[1],t:noteobj.TxO.t};
if(val[3] != null && !(val[3] & 0x02)) cc.c.hidden = true;
}
cc.c.push(cmnt);
} break;
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 +556,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 +565,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 +605,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 +644,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 +658,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 +678,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

View File

@ -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;
@ -31,15 +31,6 @@ function write_biff_continue(ba/*:BufArray*/, type/*:number|string*/, payload, l
}
}
function write_BIFF2Cell(out, r/*:number*/, c/*:number*/) {
if(!out) out = new_buf(7);
out.write_shift(2, r);
out.write_shift(2, c);
out.write_shift(2, 0);
out.write_shift(1, 0);
return out;
}
function write_BIFF2BERR(r/*:number*/, c/*:number*/, val, t/*:?string*/) {
var out = new_buf(9);
write_BIFF2Cell(out, r, c);
@ -56,64 +47,373 @@ function write_BIFF2LABEL(r/*:number*/, c/*:number*/, val) {
return out.l < out.length ? out.slice(0, out.l) : out;
}
function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*//*::, opts*/) {
function write_comments_biff2(ba/*:BufArray*/, comments/*:Array<[Comment[], number, number]>*/) {
comments.forEach(function(data) {
var text = data[0].map(function(cc) { return cc.t; }).join("");
// TODO: should '\n' be translated to '\r' to correct for Excel 5.0 bug when exporting to BIFF2/3 ?
if(text.length <= 2048) return write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text, data[1], data[2]));
write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text.slice(0, 2048), data[1], data[2], text.length));
for(var i = 2048; i < text.length; i += 2048)
write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text.slice(i, Math.min(i+2048, text.length)), -1, -1, Math.min(2048, text.length - i)));
});
}
/* TODO: BIFF3/4 use different records -- see comments*/
function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/) {
var ifmt = 0;
if(cell.z != null) {
ifmt = opts._BIFF2FmtTable.indexOf(cell.z);
if(ifmt == -1) { opts._BIFF2FmtTable.push(cell.z); ifmt = opts._BIFF2FmtTable.length - 1; }
}
var ixfe = 0;
if(cell.z != null) {
for(; ixfe < opts.cellXfs.length; ++ixfe) if(opts.cellXfs[ixfe].numFmtId == ifmt) break;
if(ixfe == opts.cellXfs.length) opts.cellXfs.push({numFmtId: ifmt});
}
if(cell.v != null) switch(cell.t) {
case 'd': case 'n':
var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
if((v == (v|0)) && (v >= 0) && (v < 65536))
write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v));
var v = cell.t == 'd' ? datenum(parseDate(cell.v, date1904), date1904) : cell.v;
if(opts.biff == 2 && (v == (v|0)) && (v >= 0) && (v < 65536))
// 0x027E (RK) in BIFF3/4
write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v, ixfe, ifmt));
else if(isNaN(v))
// 0x0205 in BIFF3/4
write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x24, "e")); // #NUM!
else if(!isFinite(v))
// 0x0205 in BIFF3/4
write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x07, "e")); // #DIV/0!
else
write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v));
// 0x0203 in BIFF3/4
write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v, ixfe, ifmt));
return;
case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
case 'b': case 'e':
// 0x0205 in BIFF3/4
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)));
// 0x0204 in BIFF3/4
write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v == null ? "" : String(cell.v).slice(0,255)));
return;
}
// 0x0201 in BIFF3/4
write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
}
function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
var dense = Array.isArray(ws);
var range = safe_decode_range(ws['!ref'] || "A1"), ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
var dense = ws["!data"] != null;
var range = safe_decode_range(ws['!ref'] || "A1"), rr = "", cols/*:Array<string>*/ = [];
if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
range.e.r = Math.min(range.e.c, 0x3FFF);
ref = encode_range(range);
}
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
var row = [], comments = [];
/* TODO: 0x0000 / 0x0200 dimensions? */
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
for(var R = range.s.r; R <= range.e.r; ++R) {
if(dense) row = ws["!data"][R] || [];
rr = encode_row(R);
for(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);
write_ws_biff2_cell(ba, cell, R, C, opts, date1904);
if(cell.c) comments.push([cell.c, R, C]);
}
}
/* ... 0x12 0x19 0x13 (Password) */
write_comments_biff2(ba, comments);
/* 0x3d (Window1) ... */
}
/* Based on test files */
function write_biff2_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
var o = opts || {};
if(DENSE != null && o.dense == null) o.dense = DENSE;
var ba = buf_array();
var idx = 0;
for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i;
if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
write_biff_rec(ba, (o.biff == 4 ? 0x0409 : (o.biff == 3 ? 0x0209 : 0x0009)), write_BOF(wb, 0x10, o));
/* ... */
write_ws_biff2(ba, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
/* ... */
if(((wb.Workbook||{}).WBProps||{}).date1904) write_biff_rec(ba, 0x0022, writebool(true));
o.cellXfs = [{numFmtId: 0}];
o._BIFF2FmtTable/*:Array<string>*/ = ["General"]; o._Fonts = [];
var body = buf_array();
write_ws_biff2(body, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
o._BIFF2FmtTable.forEach(function(f) {
if(o.biff <= 3) write_biff_rec(ba, 0x001E, write_BIFF2Format(f));
else write_biff_rec(ba, 0x041E, write_BIFF4Format(f));
});
o.cellXfs.forEach(function(xf) {
switch(o.biff) {
case 2: write_biff_rec(ba, 0x0043, write_BIFF2XF(xf)); break;
case 3: write_biff_rec(ba, 0x0243, write_BIFF3XF(xf)); break;
case 4: write_biff_rec(ba, 0x0443, write_BIFF4XF(xf)); break;
}
});
delete o._BIFF2FmtTable; delete o.cellXfs; delete o._Fonts;
ba.push(body.end());
write_biff_rec(ba, 0x000A);
return ba.end();
}
var b8oid = 1, b8ocnts/*:Array<[number, number, number]>*/ = [];
function write_MsoDrawingGroup() {
var buf = new_buf(82 + 8 * b8ocnts.length);
/* [MS-ODRAW] 2.2.12 OfficeArtDggContainer */
buf.write_shift(2, 0x0F);
buf.write_shift(2, 0xF000);
buf.write_shift(4, 74 + 8 * b8ocnts.length);
/* 2.2.48 OfficeArtFDGGBlock */
{
buf.write_shift(2, 0);
buf.write_shift(2, 0xF006);
buf.write_shift(4, 16 + 8 * b8ocnts.length);
/* 2.2.47 OfficeArtFDGG */
{
buf.write_shift(4, b8oid);
buf.write_shift(4, b8ocnts.length+1);
var acc = 0; for(var i = 0; i < b8ocnts.length; ++i) acc += (b8ocnts[i] && b8ocnts[i][1] || 0); buf.write_shift(4, acc);
buf.write_shift(4, b8ocnts.length);
}
/* 2.2.46 OfficeArtIDCL + */
b8ocnts.forEach(function(b8) {
buf.write_shift(4, b8[0]);
buf.write_shift(4, b8[2]);
});
}
/* 2.2.9 OfficeArtFOPT */
{
buf.write_shift(2, 0x33); // 0x03 | (3 << 4)
buf.write_shift(2, 0xF00B);
buf.write_shift(4, 0x12); // 3 * 6
/* 2.3.21.15 Text Boolean Properties */
buf.write_shift(2, 0xBF); buf.write_shift(4, 0x00080008);
/* 2.3.7.2 fillColor */
buf.write_shift(2, 0x0181); buf.write_shift(4, 0x08000041);
/* 2.3.8.1 lineColor */
buf.write_shift(2, 0x01C0); buf.write_shift(4, 0x08000040);
}
/* 2.2.45 OfficeArtSplitMenuColorContainer */
{
buf.write_shift(2, 0x40);
buf.write_shift(2, 0xF11E);
buf.write_shift(4, 16);
buf.write_shift(4, 0x0800000D);
buf.write_shift(4, 0x0800000C);
buf.write_shift(4, 0x08000017);
buf.write_shift(4, 0x100000F7);
}
return buf;
}
function write_comments_biff8(ba/*:BufArray*/, comments/*:Array<[Comment[], number, number]>*/) {
var notes/*:Array<RawData>*/ = [], sz = 0, pl = buf_array(), baseid = b8oid;
var _oasc;
comments.forEach(function(c, ci) {
var author = "";
var text = c[0].map(function(t) { if(t.a && !author) author = t.a; return t.t; }).join("");
++b8oid;
/* 2.2.14 OfficeArtSpContainer */
{
var oasc = new_buf(0x96);
oasc.write_shift(2, 0x0F);
oasc.write_shift(2, 0xF004);
oasc.write_shift(4, 0x96);
/* 2.2.40 OfficeArtFSP */
{
oasc.write_shift(2, 0xca2); // 0x02 | (0xca << 4)
oasc.write_shift(2, 0xF00A);
oasc.write_shift(4, 8);
oasc.write_shift(4, b8oid);
oasc.write_shift(4, 0xA00);
}
/* 2.2.9 OfficeArtFOPT */
{
oasc.write_shift(2, 0xE3); // 0x03 | (14 << 4)
oasc.write_shift(2, 0xF00B);
oasc.write_shift(4, 0x54); // 14 * 6
/* 2.3.21.1 ITxid */
oasc.write_shift(2, 0x80); oasc.write_shift(4, 0);
/* 2.3.21.12 txdir */
oasc.write_shift(2, 0x8B); oasc.write_shift(4, 0x02);
/* 2.3.21.15 Text Boolean Properties */
oasc.write_shift(2, 0xBF); oasc.write_shift(4, 0x00080008);
/* 2.3.6.30 cxk */
oasc.write_shift(2, 0x0158); oasc.l += 4;
/* 2.3.7.2 fillColor */
oasc.write_shift(2, 0x0181); oasc.write_shift(4, 0x08000050);
/* 2.3.7.4 fillBackColor */
oasc.write_shift(2, 0x0183); oasc.write_shift(4, 0x08000050);
/* 2.3.7.6 fillCrMod */
oasc.write_shift(2, 0x0185); oasc.write_shift(4, 0x100000F4);
/* 2.3.7.43 Fill Style Boolean Properties */
oasc.write_shift(2, 0x01BF); oasc.write_shift(4, 0x00100010);
/* 2.3.8.1 lineColor */
oasc.write_shift(2, 0x01C0); oasc.write_shift(4, 0x08000051);
/* 2.3.8.4 lineCrMod */
oasc.write_shift(2, 0x01C3); oasc.write_shift(4, 0x100000F4);
/* 2.3.13.2 shadowColor */
oasc.write_shift(2, 0x0201); oasc.write_shift(4, 0x08000051);
/* 2.3.13.4 shadowCrMod */
oasc.write_shift(2, 0x0203); oasc.write_shift(4, 0x100000F4);
/* 2.3.13.23 Shadow Style Boolean Properties */
oasc.write_shift(2, 0x023F); oasc.write_shift(4, 0x00030001);
/* 2.3.4.44 Group Shape Boolean Properties */
oasc.write_shift(2, 0x03BF); oasc.write_shift(4, 0x00020000 | (c[0].hidden ? 2 : 0));
}
/* [MS-XLS] 2.5.193 OfficeArtClientAnchorSheet */
{
oasc.l += 2;
oasc.write_shift(2, 0xF010);
oasc.write_shift(4, 0x12);
oasc.write_shift(2, 0x3); // do not move or size with cells
oasc.write_shift(2, c[2] + 2); oasc.l += 2;
oasc.write_shift(2, c[1] + 1); oasc.l += 2;
oasc.write_shift(2, c[2] + 4); oasc.l += 2;
oasc.write_shift(2, c[1] + 5); oasc.l += 2;
}
/* [MS-XLS] 2.5.194 OfficeArtClientData */
{
oasc.l += 2;
oasc.write_shift(2, 0xF011);
oasc.l += 4;
}
oasc.l = 0x96;
if(ci == 0) /* write_biff_rec(pl, 0x003C, oasc); */ _oasc = oasc;
else write_biff_rec(pl, 0x00EC, oasc);
}
sz += 0x96;
/* [MS-XLS] 2.4.181 Obj */
{
var obj = new_buf(52); // 22 + 26 + 4
/* [MS-XLS] 2.5.143 FtCmo */
obj.write_shift(2, 0x15);
obj.write_shift(2, 0x12);
obj.write_shift(2, 0x19);
obj.write_shift(2, b8oid);
obj.write_shift(2, 0);
obj.l = 22;
/* [MS-XLS] 2.5.149 FtNts */
obj.write_shift(2, 0x0D);
obj.write_shift(2, 0x16);
obj.write_shift(4, 0x62726272);
obj.write_shift(4, 0x95374305);
obj.write_shift(4, 0x80301328);
obj.write_shift(4, 0x69696904 + b8oid*256);
obj.write_shift(2,0);
obj.write_shift(4,0);
// reserved
obj.l += 4;
write_biff_rec(pl, 0x005D, obj);
}
/* [MS-XLS] 2.5.195 OfficeArtClientTextbox */
{
var oact = new_buf(8);
oact.l += 2;
oact.write_shift(2, 0xF00D);
oact.l += 4;
write_biff_rec(pl, 0x00EC, oact);
}
sz += 8;
/* [MS-XLS] 2.4.329 TxO */
{
var txo = new_buf(18);
txo.write_shift(2, 0x12);
txo.l += 8;
txo.write_shift(2, text.length);
txo.write_shift(2, 0x10);
txo.l += 4;
write_biff_rec(pl, 0x01b6, txo);
/* text continue record TODO: switch to wide strings */
{
var cont = new_buf(1 + text.length);
cont.write_shift(1, 0);
cont.write_shift(text.length, text, "sbcs");
write_biff_rec(pl, 0x003C, cont);
}
/* formatting continue records */
{
var conf = new_buf(0x10);
conf.l += 8;
conf.write_shift(2, text.length);
conf.l += 6;
write_biff_rec(pl, 0x003C, conf);
}
}
/* 2.4.179 Note */
{
var notesh = new_buf(12 + author.length);
notesh.write_shift(2, c[1]);
notesh.write_shift(2, c[2]);
notesh.write_shift(2, 0 | (c[0].hidden ? 0 : 2));
notesh.write_shift(2, b8oid);
notesh.write_shift(2, author.length);
notesh.write_shift(1, 0);
notesh.write_shift(author.length, author, "sbcs");
notesh.l ++;
notes.push(notesh);
}
});
/* [MS-ODRAW] 2.2.13 OfficeArtDgContainer */
{
var hdr = new_buf(80);
hdr.write_shift(2, 0x0F);
hdr.write_shift(2, 0xF002);
hdr.write_shift(4, sz + hdr.length - 8);
/* [MS-ODRAW] 2.2.49 OfficeArtFDG */
{
hdr.write_shift(2, 0x10);
hdr.write_shift(2, 0xF008);
hdr.write_shift(4, 0x08);
hdr.write_shift(4, comments.length + 1);
hdr.write_shift(4, b8oid);
}
/* [MS-ODRAW] 2.2.16 OfficeArtSpgrContainer */
{
hdr.write_shift(2, 0x0f);
hdr.write_shift(2, 0xF003);
hdr.write_shift(4, sz + 0x30);
/* [MS-ODRAW] 2.2.14 OfficeArtSpContainer */
{
hdr.write_shift(2, 0x0f);
hdr.write_shift(2, 0xF004);
hdr.write_shift(4, 0x28);
/* [MS-ODRAW] 2.2.38 OfficeArtFSPGR */
{
hdr.write_shift(2, 0x01);
hdr.write_shift(2, 0xF009);
hdr.write_shift(4, 0x10);
hdr.l += 16;
}
/* [MS-ODRAW] 2.2.40 OfficeArtFSP */
{
hdr.write_shift(2, 0x02);
hdr.write_shift(2, 0xF00A);
hdr.write_shift(4, 0x08);
hdr.write_shift(4, baseid);
hdr.write_shift(4, 0x05);
}
}
}
write_biff_rec(ba, 0x00EC, /* hdr */ _oasc ? bconcat([hdr, _oasc]) : hdr);
}
ba.push(pl.end());
notes.forEach(function(n) { write_biff_rec(ba, 0x001C, n); });
b8ocnts.push([baseid, comments.length + 1, b8oid]);
++b8oid;
}
function write_FONTS_biff8(ba, data, opts) {
write_biff_rec(ba, "Font", write_Font({
write_biff_rec(ba, 0x0031 /* Font */, write_Font({
sz:12,
color: {theme:1},
name: "Arial",
@ -127,7 +427,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 +436,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,60 +444,62 @@ 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));
}
});
}
function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) {
function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/) {
var os = 16 + get_cell_style(opts.cellXfs, cell, opts);
if(cell.v == null && !cell.bf) {
write_biff_rec(ba, "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;
var v = cell.t == 'd' ? datenum(parseDate(cell.v, date1904), date1904) : cell.v;
if(isNaN(v)) write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, 0x24, os, opts, "e")); // #NUM!
else if(!isFinite(v)) write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, 0x07, os, opts, "e")); // #DIV/0!
/* TODO: emit RK as appropriate */
write_biff_rec(ba, "Number", write_Number(R, C, v, os, opts));
else 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 +509,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 +522,60 @@ 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));
/* ... */
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
if(b8) ws['!links'] = [];
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
var comments = [];
var row = [];
for(var R = range.s.r; R <= range.e.r; ++R) {
if(dense) row = ws["!data"][R] || [];
rr = encode_row(R);
for(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);
write_ws_biff8_cell(ba, cell, R, C, opts, date1904);
if(b8 && cell.l) ws['!links'].push([ref, cell.l]);
if(cell.c) comments.push([cell.c, R, C]);
}
}
var cname/*:string*/ = _sheet.CodeName || _sheet.name || s;
/* ... */
if(b8) write_biff_rec(ba, "Window2", write_Window2((_WB.Views||[])[0]));
if(b8) write_comments_biff8(ba, comments); else write_comments_biff2(ba, comments);
/* ... */
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 +587,61 @@ 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());
/* *SUPBOOK *LBL *RTD [RecalcId] *HFPicture *MSODRAWINGGROUP */
if(b8) write_biff_rec(C, 0x008C /* Country */, write_Country());
/* *SUPBOOK *LBL *RTD [RecalcId] *HFPicture */
/* BIFF8: MsoDrawingGroup [*Continue] */
if(b8 && b8ocnts.length) write_biff_rec(C, 0x00EB /* MsoDrawingGroup */, write_MsoDrawingGroup());
/* 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 +650,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,15 +670,16 @@ 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;
}
b8oid = 1; b8ocnts = [];
o.Strings = /*::((*/[]/*:: :any):SST)*/; o.Strings.Count = 0; o.Strings.Unique = 0;
fix_write_opts(o);
@ -387,7 +699,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.");
}
}

View File

@ -1,136 +1,143 @@
/* 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_remove_ng(str, "<!--", "-->");
var mtch/*:any*/ = str.match(/<table/i);
if(!mtch) throw new Error("Invalid HTML: could not find <table>");
var mtch2/*:any*/ = str.match(/<\/table/i);
var i/*:number*/ = mtch.index, j/*:number*/ = mtch2 && mtch2.index || str.length;
var rows = split_regex(str.slice(i, j), /(:?<tr[^<>]*>)/i, "<tr>");
var R = -1, C = 0, RS = 0, CS = 0;
var range/*:Range*/ = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
var merges/*:Array<Range>*/ = [];
for(i = 0; i < rows.length; ++i) {
var row = rows[i].trim();
var hd = row.slice(0,3).toLowerCase();
if(hd == "<tr") { ++R; if(opts.sheetRows && opts.sheetRows <= R) { --R; break; } C = 0; continue; }
if(hd != "<td" && hd != "<th") continue;
var cells = row.split(/<\/t[dh]>/i);
for(j = 0; j < cells.length; ++j) {
var cell = cells[j].trim();
if(!cell.match(/<t[dh]/i)) continue;
var m = cell, cc = 0;
/* TODO: parse styles etc */
while(m.charAt(0) == "<" && (cc = m.indexOf(">")) > -1) m = m.slice(cc+1);
for(var midx = 0; midx < merges.length; ++midx) {
var _merge/*:Range*/ = merges[midx];
if(_merge.s.c == C && _merge.s.r < R && R <= _merge.e.r) { C = _merge.e.c + 1; midx = -1; }
}
var tag = parsexmltag(cell.slice(0, cell.indexOf(">")));
CS = tag.colspan ? +tag.colspan : 1;
if((RS = +tag.rowspan)>1 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
var _t/*:string*/ = tag.t || tag["data-t"] || "";
/* TODO: generate stub cells */
if(!m.length) { C += CS; continue; }
m = htmldecode(m);
if(range.s.r > R) range.s.r = R; if(range.e.r < R) range.e.r = R;
if(range.s.c > C) range.s.c = C; if(range.e.c < C) range.e.c = C;
if(!m.length) { C += CS; continue; }
var o/*:Cell*/ = {t:'s', v:m};
if(opts.raw || !m.trim().length || _t == 's'){}
else if(m === 'TRUE') o = {t:'b', v:true};
else if(m === 'FALSE') o = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)};
else if(!isNaN(fuzzydate(m).getDate())) {
o = ({t:'d', v:parseDate(m)}/*:any*/);
if(opts.UTC === false) o.v = utc_to_local(o.v);
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
o.z = opts.dateNF || table_fmt[14];
}
if(o.cellText !== false) o.w = m;
if(dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = o; }
else ws[encode_cell({r:R, c:C})] = o;
C += CS;
}
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';
// note: data-v is unaffected by the timezone interpretation
if(cell.v != null) sp["data-v"] = escapehtml(cell.v instanceof Date ? cell.v.toISOString() : cell.v);
if(cell.z != null) sp["data-z"] = cell.z;
if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + escapehtml(cell.l.Target) +'">' + w + '</a>';
}
sp.id = (o.id || "sjs") + "-" + coord;
oo.push(writextag('td', w, sp));
}
function make_html_preamble(ws/*:Worksheet*/, R/*:Range*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
var out/*: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_xml_ig(str, "table");
if(!mtch || mtch.length == 0) throw new Error("Invalid HTML: could not find <table>");
if(mtch.length == 1) {
var w = sheet_to_workbook(html_to_sheet(mtch[0], opts), opts);
w.bookType = "html";
return w;
}
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'] || "A1");
out.push(make_html_preamble(ws, r, o));
if(ws["!ref"]) for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
out.push("</table>" + footer);
return out.join("");
}
function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
var rows/*:HTMLCollection<HTMLTableRowElement>*/ = table.rows;
if(!rows) {
/* not an HTML TABLE */
throw "Unsupported origin when " + table.tagName + " is not a TABLE";
}
var 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 +147,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 +167,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;
@ -184,8 +190,9 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
else if(!isNaN(fuzzydate(v).getDate())) {
o = ({t:'d', v:parseDate(v)}/*:any*/);
if(opts.UTC) o.v = local_to_utc(o.v);
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
o.z = opts.dateNF || SSF._table[14];
o.z = opts.dateNF || table_fmt[14];
}
}
if(o.z === undefined && z != null) o.z = z;
@ -195,8 +202,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 +219,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*/ {

View File

@ -1,56 +1,262 @@
/* 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 = remove_doctype(str_remove_ng(str, "<!--", "-->"));
var Rn, NFtag, NF = "", tNF = "", y, etpos = 0, tidx = -1, infmt = false, payload = "";
while((Rn = xlmlregex.exec(str))) {
switch((Rn[3]=Rn[3].replace(/_[\s\S]*$/,""))) {
/* Number Format Definitions */
case 'number-style': // <number:number-style> 16.29.2
case 'currency-style': // <number:currency-style> 16.29.8
case 'percentage-style': // <number:percentage-style> 16.29.10
case 'date-style': // <number:date-style> 16.29.11
case 'time-style': // <number:time-style> 16.29.19
case 'text-style': // <number:text-style> 16.29.26
if(Rn[1]==='/') {
infmt = false;
if(NFtag['truncate-on-overflow'] == "false") {
if(NF.match(/h/)) NF = NF.replace(/h+/, "[$&]");
else if(NF.match(/m/)) NF = NF.replace(/m+/, "[$&]");
else if(NF.match(/s/)) NF = NF.replace(/s+/, "[$&]");
}
number_format_map[NFtag.name] = NF;
NF = "";
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
infmt = true;
NF = "";
NFtag = parsexmltag(Rn[0], false);
} break;
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 textp = "", textpidx = 0, textptag/*:: = {}*/, oldtextp = "", oldtextpidx = 0;
var textR = [], oldtextR = [];
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*/);
@ -58,8 +264,8 @@ var parse_content_xml = (function() {
var isstub = false, intable = false;
var i = 0;
xlmlregex.lastIndex = 0;
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
str = remove_doctype(str_remove_ng(str, "<!--", "-->"));
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_[\s\S]*$/,""))) {
case 'table': case '工作表': // 9.1.2 <table:table>
if(Rn[1]==='/') {
@ -82,7 +288,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 +308,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,19 +320,20 @@ 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;
} else if(Rn[1]!=='/') {
++C;
textp = ""; textpidx = 0; textR = [];
textp = oldtextp = ""; textpidx = oldtextpidx = 0; textR = []; oldtextR = [];
colpeat = 1;
var rptR = rowpeat ? R + rowpeat - 1 : R;
if(C > range.e.c) range.e.c = C;
@ -136,6 +343,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']) {
@ -161,19 +369,23 @@ var parse_content_xml = (function() {
/* 19.675.2 table:number-columns-repeated */
if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10);
/* 19.385 office:value-type */
/* 19.385 office:value-type TODO: verify ODS and UOS */
switch(q.t) {
case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break;
case 'float': q.t = 'n'; q.v = parseFloat(ctag.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);
if(opts.cellDates && q.z && fmt_is_date(q.z)) { q.v = numdate(q.v + (WB.WBProps.date1904 ? 1462 : 0)); q.t = typeof q.v == "number" ? 'n' : 'd'; }
break;
case '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;
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value'], WB.WBProps.date1904);
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904); }
if(!q.z) q.z = 'm/d/yy'; break;
/* NOTE: for `time`, Excel ODS export incorrectly uses durations relative to 1900 epoch even if 1904 is specified */
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400;
if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); }
q.z = 'HH:MM:SS'; break;
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
if(opts.cellDates) { q.v = numdate(q.v); q.t = typeof q.v == "number" ? 'n' : 'd'; }
if(!q.z) q.z = 'HH:MM:SS'; break;
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']);
break;
default:
if(q.t === 'string' || q.t === 'text' || !q.t) {
q.t = 's';
@ -196,9 +408,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);
@ -234,10 +446,17 @@ var parse_content_xml = (function() {
if(textR.length) /*::(*/comment/*:: :any)*/.R = textR;
comment.a = creator;
comments.push(comment);
textp = oldtextp; textpidx = oldtextpidx; textR = oldtextR;
}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
state.push([Rn[3], false]);
var annotag = parsexmltag(Rn[0], true);
/* office:display TODO: check if there is a global override */
if(!(annotag["display"] && parsexmlbool(annotag["display"]))) comments.hidden = true;
oldtextp = textp; oldtextpidx = textpidx; oldtextR = textR;
textp = ""; textpidx = 0; textR = [];
}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);}
creator = ""; creatoridx = 0;
textp = ""; textpidx = 0; textR = [];
break;
case 'creator': // 4.3.2.7 <dc:creator>
@ -267,23 +486,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 +512,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 +526,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 +541,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 +579,12 @@ 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; break;
}
break;
case 'graphic-properties': break; // 17.21 <style:graphic-properties>
case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
@ -389,6 +604,9 @@ var parse_content_xml = (function() {
if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) {
var ptp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0];
} else if(Rn[0].slice(-2) == "/>") {
/* TODO: is self-closing 文本串 valid? */
textp += "\n";
} else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
break; // <text:p>
case 's': break; // <text:s>
@ -418,10 +636,13 @@ var parse_content_xml = (function() {
case 'help-message': break; // 9.4.6 <table:
case 'error-message': break; // 9.4.7 <table:
case 'database-ranges': break; // 9.4.14 <table:database-ranges>
/* 9.5 Filters */
case 'filter': break; // 9.5.2 <table:filter>
case 'filter-and': break; // 9.5.3 <table:filter-and>
case 'filter-or': break; // 9.5.4 <table:filter-or>
case 'filter-condition': break; // 9.5.5 <table:filter-condition>
case 'filter-set-item': break; // 9.5.6 <table:filter-condition>
case 'list-level-style-bullet': break; // 16.31 <text:
case 'list-level-style-number': break; // 16.32 <text:
@ -552,19 +773,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;
}

View File

@ -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,25 +30,194 @@ 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(/\b(\d+)(|\.\d+)%/))) { type = "percentage"; payload += writextag("number:number", null, {"number:decimal-places": t[2] && t.length - 1 || 0, "number:min-decimal-places": t[2] && t.length - 1 || 0, "number:min-integer-digits": t[1].length }) + "<number:text>%</number:text>"; break j; }
/* datetime */
var has_time = false;
if(["y","m","d"].indexOf(nf[0]) > -1) {
type = "date";
k: for(; i < nf.length; ++i) switch((c = nf[i].toLowerCase())) {
case "h": case "s": has_time = true; --i; break k;
case "m":
l: for(var h = i+1; h < nf.length; ++h) switch(nf[h]) {
case "y": case "d": break l;
case "h": case "s": has_time = true; --i; break k;
}
/* falls through */
case "y": case "d":
while((nf[++i]||"").toLowerCase() == c[0]) c += c[0]; --i;
switch(c) {
case "y": case "yy": payload += "<number:year/>"; break;
case "yyy": case "yyyy": payload += '<number:year number:style="long"/>'; break;
case "mmmmm": console.error("ODS has no equivalent of format |mmmmm|");
/* falls through */
case "m": case "mm": case "mmm": case "mmmm":
payload += '<number:month number:style="' + (c.length % 2 ? "short" : "long") + '" number:textual="' + (c.length >= 3 ? "true" : "false") + '"/>';
break;
case "d": case "dd": payload += '<number:day number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break;
case "ddd": case "dddd": payload += '<number:day-of-week number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break;
}
break;
case '"':
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
break;
case '\\': c = nf[++i];
payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
default: console.error("unrecognized character " + c + " in ODF format " + nf);
}
if(!has_time) break j;
nf = nf.slice(i+1); i = 0;
}
if(nf.match(/^\[?[hms]/)) {
if(type == "number") type = "time";
if(nf.match(/\[/)) {
nf = nf.replace(/[\[\]]/g, "");
nopts['number:truncate-on-overflow'] = "false";
}
for(; i < nf.length; ++i) switch((c = nf[i].toLowerCase())) {
case "h": case "m": case "s":
while((nf[++i]||"").toLowerCase() == c[0]) c += c[0]; --i;
switch(c) {
case "h": case "hh": payload += '<number:hours number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break;
case "m": case "mm": payload += '<number:minutes number:style="' + (c.length % 2 ? "short" : "long") + '"/>'; break;
case "s": case "ss":
if(nf[i+1] == ".") do { c += nf[i+1]; ++i; } while(nf[i+1] == "0");
payload += '<number:seconds number:style="' + (c.match("ss") ? "long" : "short") + '"' + (c.match(/\./) ? ' number:decimal-places="' + (c.match(/0+/)||[""])[0].length + '"' : "")+ '/>'; break;
}
break;
case '"':
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
break;
case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
case "a":
if(nf.slice(i, i+3).toLowerCase() == "a/p") { payload += '<number:am-pm/>'; i += 2; break; } // Note: ODF does not support A/P
if(nf.slice(i, i+5).toLowerCase() == "am/pm") { payload += '<number:am-pm/>'; i += 4; break; }
/* falls through */
default: console.error("unrecognized character " + c + " in ODF format " + nf);
}
break j;
}
/* currency flag */
if(nf.indexOf(/\$/) > -1) { type = "currency"; }
/* should be in a char loop */
if(nf[0] == "$") { payload += '<number:currency-symbol number:language="en" number:country="US">$</number:currency-symbol>'; nf = nf.slice(1); i = 0; }
i = 0; if(nf[i] == '"') {
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
if(nf[i+1] == "*") {
i++;
payload += '<number:fill-character>' + escapexml(c.replace(/""/g, '"')) + '</number:fill-character>';
} else {
payload += '<number:text>' + escapexml(c.replace(/""/g, '"')) + '</number:text>';
}
nf = nf.slice(i+1); i = 0;
}
/* number TODO: interstitial text e.g. 000)000-0000 */
var np = nf.match(/([#0][0#,]*)(\.[0#]*|)(E[+]?0*|)/i);
if(!np || !np[0]) console.error("Could not find numeric part of " + nf);
else {
var base = np[1].replace(/,/g, "");
payload += '<number:' + (np[3] ? "scientific-" : "")+ 'number' +
' number:min-integer-digits="' + (base.indexOf("0") == -1 ? "0" : base.length - base.indexOf("0")) + '"' +
(np[0].indexOf(",") > -1 ? ' number:grouping="true"' : "") +
(np[2] && ' number:decimal-places="' + (np[2].length - 1) + '"' || ' number:decimal-places="0"') +
(np[3] && np[3].indexOf("+") > -1 ? ' number:forced-exponent-sign="true"' : "" ) +
(np[3] ? ' number:min-exponent-digits="' + np[3].match(/0+/)[0].length + '"' : "" ) +
'>' +
/* TODO: interstitial text placeholders */
'</number:' + (np[3] ? "scientific-" : "") + 'number>';
i = np.index + np[0].length;
}
/* residual text */
if(nf[i] == '"') {
c = "";
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
payload += '<number:text>' + escapexml(c.replace(/""/g, '"')) + '</number:text>';
}
}
if(!payload) { console.error("Could not generate ODS number format for |" + nf + "|"); return ""; }
return writextag("number:" + type + "-style", payload, nopts);
}
function write_names_ods(Names, SheetNames, idx) {
//var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
var scoped = []; for(var namei = 0; namei < Names.length; ++namei) {
var name = Names[namei];
if(!name) continue;
if(name.Sheet == (idx == -1 ? null : idx)) scoped.push(name);
}
if(!scoped.length) return "";
return " <table:named-expressions>\n" + scoped.map(function(name) {
var odsref = (idx == -1 ? "$" : "") + csf_to_ods_3D(name.Ref);
return " " + writextag("table:named-range", null, {
"table:name": name.Name,
"table:cell-range-address": odsref,
"table:base-cell-address": odsref.replace(/[\.][^\.]*$/, ".$A$1")
});
}).join("\n") + "\n </table:named-expressions>\n";
}
var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function() {
/* 6.1.2 White Space Characters */
var write_text_p = function(text/*:string*/)/*:string*/ {
var write_text_p = function(text/*:string*/, span)/*:string*/ {
return escapexml(text)
.replace(/ +/g, function($$){return '<text:s text:c="'+$$.length+'"/>';})
.replace(/\t/g, "<text:tab/>")
.replace(/\n/g, "</text:p><text:p>")
.replace(/\n/g, span ? "<text:line-break/>": "</text:p><text:p>")
.replace(/^ /, "<text:s/>").replace(/ $/, "<text:s/>");
};
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, date1904)/*: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');
}
@ -73,8 +242,8 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
ct['table:number-rows-spanned'] = (marr[mi].e.r - marr[mi].s.r + 1);
break;
}
if(skip) { o.push(covered_cell_xml); continue; }
var ref = encode_cell({r:R, c:C}), cell = dense ? (ws[R]||[])[C]: ws[ref];
if(skip) { o.push(' <table:covered-table-cell/>\n'); continue; }
var ref = encode_cell({r:R, c:C}), cell = dense ? (ws["!data"][R]||[])[C]: ws[ref];
if(cell && cell.f) {
ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f));
if(cell.F) {
@ -102,13 +271,13 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
ct['office:value-type'] = "string";
break;
case 'd':
textp = (cell.w||(parseDate(cell.v).toISOString()));
textp = (cell.w||(parseDate(cell.v, date1904).toISOString()));
ct['office:value-type'] = "date";
ct['office:date-value'] = (parseDate(cell.v).toISOString());
ct['office:date-value'] = (parseDate(cell.v, date1904).toISOString());
ct['table:style-name'] = "ce1";
break;
//case 'e':
default: o.push(null_cell_xml); continue;
//case 'e': // TODO: translate to ODS errors
default: o.push(null_cell_xml); continue; // TODO: empty cell with comments
}
var text_p = write_text_p(textp);
if(cell.l && cell.l.Target) {
@ -118,10 +287,22 @@ 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;")});
}
o.push(' ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n');
if(nfs[cell.z]) ct["table:style-name"] = "ce" + nfs[cell.z].slice(1);
var payload = writextag('text:p', text_p, {});
if(cell.c) {
var acreator = "", apayload = "", aprops = {};
for(var ci = 0; ci < cell.c.length; ++ci) {
if(!acreator && cell.c[ci].a) acreator = cell.c[ci].a;
apayload += "<text:p>" + write_text_p(cell.c[ci].t) + "</text:p>";
}
if(!cell.c.hidden) aprops["office:display"] = true;
payload = writextag('office:annotation', apayload, aprops) + payload;
}
o.push(' ' + writextag('table:table-cell', payload, ct) + '\n');
}
o.push(' </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 +310,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 +350,40 @@ 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);
if(!ws["!ref"]) return;
var range = decode_range(ws["!ref"]);
for(var R = 0; R <= range.e.r; ++R) for(var C = 0; C <= range.e.c; ++C) {
var c = dense ? (ws["!data"][R]||[])[C] : ws[encode_cell({r:R,c:C})];
if(!c || !c.z || c.z.toLowerCase() == "general") continue;
if(!nfs[c.z]) {
var out = write_number_format_ods(c.z, "N" + nfi);
if(out) { nfs[c.z] = "N" + nfi; ++nfi; o.push(out + "\n"); }
}
}
});
o.push(' <style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N37"/>\n');
keys(nfs).forEach(function(nf) {
o.push('<style:style style:name="ce' + nfs[nf].slice(1) + '" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="' + nfs[nf] + '"/>\n');
});
/* page-layout */
o.push(' </office:automatic-styles>\n');
return nfs;
};
return function wcx(wb, opts) {
@ -235,14 +436,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, ((wb.Workbook||{}).WBProps||{}).date1904));
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

View File

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

View File

@ -13,6 +13,13 @@ function safe_parse_wbrels(wbrels, sheets) {
return !wbrels || wbrels.length === 0 ? null : wbrels;
}
function parse_sheet_legacy_drawing(sheet, type, zip, path, idx, opts, wb, comments) {
if(!sheet || !sheet['!legdrawel']) return;
var dfile = resolve_path(sheet['!legdrawel'].Target, path);
var draw = getzipstr(zip, dfile, true);
if(draw) parse_vml(utf8read(draw), sheet, comments||[]);
}
function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/*:number*/, sheetRels, sheets, stype/*:string*/, opts, wb, themes, styles) {
try {
sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
@ -35,23 +42,30 @@ 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 || []);
parse_sheet_legacy_drawing(_ws, stype, zip, path, idx, opts, wb, comments);
} catch(e) { if(opts.WTF) throw e; }
}
function strip_front_slash(x/*:string*/)/*:string*/ { return x.charAt(0) == '/' ? x.slice(1) : x; }
function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
make_ssf(SSF);
make_ssf();
opts = opts || {};
fix_read_opts(opts);
@ -62,17 +76,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 +121,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 +191,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;
@ -178,7 +204,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
if(wbrels && wbrels[i]) {
path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
if(!safegetzipfile(zip, path)) path = wbrels[i][1];
if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/.*$/,"") + wbrels[i][1];
if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/[\S\s]*$/,"") + wbrels[i][1];
stype = wbrels[i][2];
} else {
path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
@ -211,7 +237,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 +257,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 metadata for xlsm/xlsx resolution
out.bookType = xlsb ? "xlsb" : "xlsx";
return out;
}

View File

@ -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();
@ -57,6 +51,9 @@ function write_zip_xlsxb(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]];
@ -66,7 +63,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 +71,27 @@ 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));
var needtc = false;
comments.forEach(function(carr) {
carr[1].forEach(function(c) { if(c.T == true) needtc = true; });
});
if(needtc) {
cf = "xl/threadedComments/threadedComment" + rId + ".xml";
zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts));
ct.threadedcomments.push(cf);
add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + ".xml", RELS.TCMNT);
}
cf = "xl/comments" + rId + "." + wbext;
zip_add_file(zip, cf, write_comments_bin(comments, opts));
ct.comments.push(cf);
add_rels(wsrels, -1, "../comments" + rId + "." + wbext, RELS.CMNT);
need_vml = true;
}
if(ws['!legacy']) {
if(need_vml) zip_add_file(zip, "xl/drawings/vmlDrawing" + (rId) + ".vml", write_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 +102,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,10 +135,17 @@ 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);
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));
@ -137,14 +154,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 +207,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 +227,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 +294,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));

View File

@ -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,14 @@ 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);
if(typeof ArrayBuffer !== "undefined" && data instanceof ArrayBuffer) d = new Uint8Array(data);
d = typeof $cptable !== "undefined" ? $cptable.utils.decode(1200, d.slice(2), 'str') : (
(has_buf && Buffer.isBuffer(data)) ? data.slice(2).toString("utf16le") :
(typeof Uint8Array !== "undefined" && d instanceof Uint8Array) ? (
typeof TextDecoder !== "undefined" ? new TextDecoder("utf-16le").decode(d.slice(2)) : utf16lereadu(d.slice(2))
) : utf16leread(d.slice(2))
);
o.type = "binary";
return read_plaintext(d, o);
}
@ -67,6 +73,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 +111,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);
}

View File

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

View File

@ -4,18 +4,18 @@ type MJRObject = {
isempty: boolean;
};
*/
function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, header/*:number*/, hdr/*:Array<any>*/, 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(val === undefined || val.t === undefined) {
if(!dense || sheet["!data"][R]) for (var C = r.s.c; C <= r.e.c; ++C) {
var val = dense ? (sheet["!data"][R]||[])[C] : sheet[cols[C] + rr];
if(val == null || val.t === undefined) {
if(defval === undefined) continue;
if(hdr[C] != null) { row[hdr[C]] = defval; }
continue;
@ -24,7 +24,12 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
switch(val.t){
case 'z': if(v == null) break; continue;
case 'e': v = (v == 0 ? null : void 0); break;
case 's': case 'd': case 'b': case 'n': break;
case 's': case 'b':
case 'n': if(!val.z || !fmt_is_date(val.z)) break;
v = numdate(v); // TODO: date1904 setting should also be stored in worksheet object
if(typeof v == "number") break;
/* falls through */
case 'd': if(!(o && (o.UTC||(o.raw === false)))) v = utc_to_local(new Date(v)); break;
default: throw new Error('unrecognized type ' + val.t);
}
if(hdr[C] != null) {
@ -34,7 +39,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]] = (val.t === 'n' && typeof o.rawNumbers === 'boolean' ? o.rawNumbers : raw) ? v : format_cell(val, v, o);
}
if(v != null) isempty = false;
}
@ -63,12 +68,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 +85,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 +107,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;
@ -109,6 +125,7 @@ function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Arr
/* NOTE: Excel CSV does not support array formulae */
row.push(txt);
}
if(o.strip) while(row[row.length - 1] === "") --row.length;
if(o.blankrows === false && isempty) return null;
return row.join(FS);
}
@ -120,28 +137,25 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ {
var r = safe_decode_range(sheet["!ref"]);
var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
var row = "", cols/*:Array<string>*/ = [];
o.dense = Array.isArray(sheet);
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
var rowinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!rows"] || [];
for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
var w = 0;
for(var R = r.s.r; R <= r.e.r; ++R) {
if ((rowinfo[R]||{}).hidden) continue;
row = make_csv_row(sheet, r, R, cols, fs, rs, FS, 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 +164,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 +195,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 +208,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,29 +218,35 @@ 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';
else if(typeof v == 'string') t = 's';
else if(v instanceof Date) {
t = 'd';
if(!o.UTC) v = local_to_utc(v);
if(!o.cellDates) { t = 'n'; v = datenum(v); }
z = (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 +257,132 @@ 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 or single-sheet workbook object */
function book_new(ws/*:?Worksheet*/, wsname/*:?string*/)/*:Workbook*/ {
var wb = { SheetNames: [], Sheets: {} };
if(ws) book_append_sheet(wb, ws, wsname || "Sheet1");
return wb;
}
/* add a worksheet to the end of a given workbook */
function book_append_sheet(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/, roll/*:?boolean*/)/*:string*/ {
var i = 1;
if(!name) for(; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break;
if(!name || wb.SheetNames.length >= 0xFFFF) throw new Error("Too many worksheets");
if(roll && wb.SheetNames.indexOf(name) >= 0 && name.length < 32) {
var m = name.match(/\d+$/); // at this point, name length is capped at 32
i = m && +m[0] || 0;
var root = m && name.slice(0, m.index) || name;
for(++i; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf(name = root + i) == -1) break;
}
check_ws_name(name);
if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!");
wb.SheetNames.push(name);
wb.Sheets[name] = ws;
return name;
}
/* set sheet visibility (visible/hidden/very hidden) */
function book_set_sheet_visibility(wb/*:Workbook*/, sh/*:number|string*/, vis/*:number*/) {
if(!wb.Workbook) wb.Workbook = {};
if(!wb.Workbook.Sheets) wb.Workbook.Sheets = [];
var idx = wb_sheet_idx(wb, sh);
// $FlowIgnore
if(!wb.Workbook.Sheets[idx]) wb.Workbook.Sheets[idx] = {};
switch(vis) {
case 0: case 1: case 2: break;
default: throw new Error("Bad sheet visibility setting " + vis);
}
// $FlowIgnore
wb.Workbook.Sheets[idx].Hidden = vis;
}
/* set number format */
function cell_set_number_format(cell/*:Cell*/, fmt/*:string|number*/) {
cell.z = fmt;
return cell;
}
/* set cell hyperlink */
function cell_set_hyperlink(cell/*:Cell*/, target/*:string*/, tooltip/*:?string*/) {
if(!target) {
delete cell.l;
} else {
cell.l = ({ Target: target }/*:Hyperlink*/);
if(tooltip) cell.l.Tooltip = tooltip;
}
return cell;
}
function cell_set_internal_link(cell/*:Cell*/, range/*:string*/, tooltip/*:?string*/) { return cell_set_hyperlink(cell, "#" + range, tooltip); }
/* add to cell comments */
function cell_add_comment(cell/*:Cell*/, text/*:string*/, author/*:?string*/) {
if(!cell.c) cell.c = [];
cell.c.push({t:text, a:author||"SheetJS"});
}
/* set array formula and flush related cells */
function sheet_set_array_formula(ws/*:Worksheet*/, range, formula/*:string*/, dynamic/*:boolean*/) {
var rng = typeof range != "string" ? range : safe_decode_range(range);
var rngstr = typeof range == "string" ? range : encode_range(range);
for(var R = rng.s.r; R <= rng.e.r; ++R) for(var C = rng.s.c; C <= rng.e.c; ++C) {
var cell = ws_get_cell_stub(ws, R, C);
cell.t = 'n';
cell.F = rngstr;
delete cell.v;
if(R == rng.s.r && C == rng.s.c) {
cell.f = formula;
if(dynamic) cell.D = true;
}
}
var wsr = decode_range(ws["!ref"]);
if(wsr.s.r > rng.s.r) wsr.s.r = rng.s.r;
if(wsr.s.c > rng.s.c) wsr.s.c = rng.s.c;
if(wsr.e.r < rng.e.r) wsr.e.r = rng.e.r;
if(wsr.e.c < rng.e.c) wsr.e.c = rng.e.c;
ws["!ref"] = encode_range(wsr);
return ws;
}

View File

@ -1,119 +1,41 @@
(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_new: sheet_new,
sheet_add_aoa: sheet_add_aoa,
sheet_add_json: sheet_add_json,
sheet_add_dom: sheet_add_dom,
aoa_to_sheet: aoa_to_sheet,
json_to_sheet: json_to_sheet,
table_to_sheet: parse_dom_table,
table_to_book: table_to_book,
sheet_to_csv: sheet_to_csv,
sheet_to_txt: sheet_to_txt,
sheet_to_json: sheet_to_json,
sheet_to_html: sheet_to_html,
sheet_to_formulae: sheet_to_formulae,
sheet_to_row_object_array: sheet_to_json,
sheet_get_cell: ws_get_cell_stub,
book_new: book_new,
book_append_sheet: book_append_sheet,
book_set_sheet_visibility: book_set_sheet_visibility,
cell_set_number_format: cell_set_number_format,
cell_set_hyperlink: cell_set_hyperlink,
cell_set_internal_link: cell_set_internal_link,
cell_add_comment: cell_add_comment,
sheet_set_array_formula: sheet_set_array_formula,
consts: {
SHEET_VISIBLE: 0,
SHEET_HIDDEN: 1,
SHEET_VERY_HIDDEN: 2
}
/* 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);

View File

@ -1,125 +1,124 @@
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 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(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
};

View File

@ -10,5 +10,13 @@ XLSX.writeFileAsync = writeFileAsync;
XLSX.utils = utils;
XLSX.writeXLSX = writeSyncXLSX;
XLSX.writeFileXLSX = writeFileSyncXLSX;
XLSX.set_fs = set_fs;
XLSX.set_cptable = set_cptable;
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) {}
}

View File

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

View File

@ -1,58 +0,0 @@
# Demos
These demos are intended to demonstrate how to load this library in various
ecosystems. The library is designed to be used in the web browser and in node
contexts, using dynamic feature tests to pull in features when necessary. This
works extremely well in common use cases: script tag insertion and node require.
Systems like webpack try to be clever by performing simple static analysis to
pull in code. However, they do not support dynamic type tests, breaking
compatibility with traditional scripts. Configuration is required. The demos
cover basic configuration steps for various systems and should "just work".
Mobile app and other larger demos do not include the full build structure. The
demos have `Makefile` scripts that show how to reproduce the full projects. The
scripts have been tested against iOS and OSX. For Windows platforms, GNU make
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/)
**Bundlers and Tooling**
- [`browserify`](browserify/)
- [`fusebox`](fusebox/)
- [`parcel`](parcel/)
- [`requirejs`](requirejs/)
- [`rollup`](rollup/)
- [`systemjs`](systemjs/)
- [`typescript`](typescript/)
- [`webpack 2.x`](webpack/)
**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/)
Other examples are included in the [showcase](demos/showcase/).
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

View File

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

View File

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

View File

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

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