Compare commits

...

637 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 e14aee3e51 version bump 0.18.3
- XLSX / XLSB dynamic array formulae
- use Uint8Array when available in write (fixes #2539 h/t @RScherzer)
- mini build cleanup to satiate webpack (fixes #2526 #2530)
2022-03-03 03:35:39 -05:00
reviewher 4f6a849a59
simplify rels scan (fixes #2537) 2022-03-01 04:14:41 -05:00
Dan Mlodecki 56e23ca8e0 NestJS/SheetJS demo instructions 2022-02-26 01:48:40 -04:00
SheetJS d50a7812c4 workarounds for webpack 5 2022-02-25 23:32:40 -05:00
SheetJS fbf43d4b73 version bump 0.18.2: hotfix for unicode woes
- fixes #2521 h/t @lanchengkai
- fixes #2522 h/t @duchm12
2022-02-15 02:23:59 -05:00
SheetJS 8e6c0411d9 version bump 0.18.1: ESM 2022-02-13 20:45:57 -05:00
SheetJS fbdd43a3f4 deno and node ESM tests 2022-02-13 04:49:30 -05:00
reviewher 46360a180a CFB zip compression option
fixes #600 and fixes #1638
2022-02-12 15:26:50 -08:00
SheetJS 88225f5fd5 esm support and deno demo 2022-02-12 01:31:47 -05:00
reviewher dd6bb022e2 fixes for reading dates in Chrome 2022-02-10 23:13:41 -08:00
SheetJS 43a7a5ea07 switch to `cfb` for zip operations 2022-02-10 08:22:36 -05:00
SheetJS f78c866cf4 Parse non-conformant records from Access export 2022-02-08 04:57:56 -05:00
Hugo Aboud 92d8a38ef6 avoid utf-8 buffer re-decoding 2022-02-08 00:19:27 -03:00
SheetJS 6c436ae277 README cleanup in anticipation of node fetch 2022-02-05 09:04:02 -05:00
Pedro Arantes 3cbe83c855 Base64 TypeScript 2022-02-04 17:57:47 -03:00
SheetJS 55924668a7 NUMBERS primary cell storage parse
docs clarified row and column props (fixes #2486) (fixes #2511)
2022-02-04 00:48:09 -05:00
reviewher 0000a09c41 Angular 13 demo 2022-02-01 11:07:03 -08:00
SheetJS d54774cbad CI fixes 2022-02-01 03:58:37 -05:00
SheetJS 5f0f2c91c5 version bump 0.18.0
- Removed global variables `XLS` and `ODS` from standalone browser build
- Removed `dist/jszip.js` from the package
- XLSX SST parse, fixes #2503
2022-02-01 00:58:45 -05:00
SheetJS cb8046c447 arithmancy 2022-01-31 06:41:23 -05:00
SheetJS bb997654ef very basic numbers iwa parser 2022-01-28 21:54:11 -05:00
László Bulik d01661565a
Fixes xls with embedded doc may show wrong props 2022-01-25 08:52:05 +01:00
Michael Marziani 59538ee78f Extract SheetOption interface
Have WritingOptions and Table2SheetOpts inherit. Fixes TS error setting
sheet name when using table_to_book and other table_to functions.
2022-01-18 19:05:40 +01:00
SheetJS 0ddeba4fc3 version bump 0.17.5 2022-01-10 13:45:50 -05:00
JeiHO 5b25a430f2 fixed variable name in README example 2021-12-29 04:36:44 -06:00
SheetJS d6161103b1 works minutiae 2021-12-29 04:16:02 -05:00
aritrakoley b3bc49afe8 add console error when columns exceed IV 2021-12-11 19:55:52 +05:30
Zaheer Ud Din 10ae7c9fec Strip quoted delims in file type magic 0x3C 2021-12-05 10:19:25 +05:00
SheetJS fcf9182fa6 version bump 0.17.4: Lotus WK3 workbook writer 2021-11-13 23:49:38 -05:00
Louis Jackson-Rees 9e9e4bcb45 FS option skip PRN parse [ci skip] 2021-11-09 04:45:31 +00:00
AndrewGlago ef21e2bea2 DSV Field Separator override [ci skip] 2021-11-09 00:31:56 +00:00
SheetJS 29e3bb4c1f Lotus WK1 worksheet writer [ci skip]
- unpack errors from WK3 long double
- explicitly ignore ss:Null in XLML (fixes #2447)
2021-11-08 00:01:12 -05:00
Garrett Luu c1f5f041a4 xlsx-cli separate package [ci skip] 2021-11-06 20:34:44 -04:00
reviewher 3a26260c84 HTML string parse multiple tables [ci skip] 2021-11-05 20:36:59 -07:00
Author: Austin Peterson b5c697e5ed ODS Text Parsing (fixes #2446) [ci skip] 2021-11-05 02:26:41 -06:00
Logan Houp 4d00394678 XLSX !protect check on write [ci skip] 2021-11-04 01:14:09 -04:00
notchris a7405c4a55 Fixed RequireJS export name [ci skip] 2021-11-03 00:45:24 -04:00
SheetJS ebfb5bc7c9 properly detect encrypted ODS 2021-10-27 03:50:23 -04:00
dnviyth 222995ebdf fix: #2432 2021-10-27 14:26:17 +08:00
Luudoo 2b4548098e
Update index.d.ts
Fix issue #2427 correct Table2SheetOpts type
2021-10-21 11:19:46 +02:00
Amy Benson e73f0e18f4 Fix #2425: ods files opening in excel 2021-10-19 14:23:42 +01:00
reviewher cb8fc656fd CFB Fix [ci skip] 2021-10-16 16:07:27 -04:00
SheetJS 09bd0755b5 version bump 0.17.3 2021-10-13 03:26:40 -04:00
ThibautSF 5c02c819f6 x-spreadsheet demo merges and formulae [ci skip]
Co-authored-by: SheetJS <dev@sheetjs.com>
2021-10-13 06:43:07 +02:00
SheetJS e110fe8952 Lightning Web Component support [ci skip] 2021-10-12 20:18:30 -04:00
reviewher cb61a67d17
`safegetzipfile` fix 2021-10-12 04:55:29 -04:00
Richard Gibson 3af23c31dd
Support UTF-8 decoding for non-buffer input
Fixes #2081
2021-10-05 20:23:44 -04:00
reviewher 71160160d1 Split x-spreadsheet demo script [ci skip] 2021-10-05 10:57:19 -07:00
Felix Zumstein 12597dcf7b Do not quote #REF for unknown 3d ref [ci skip] 2021-10-03 10:34:26 +02:00
SheetJS b98a40235f XLS Unicode Property Lists [ci skip] 2021-10-02 21:41:36 -04:00
gfyoung a376a6c78c
Use named define for requireJS
Two benefits:
    
* Helps avoid with mismatched anonymous errors
    
ref: https://requirejs.org/docs/errors.html#mismatch
    
* Allows for uglification in the demo
2021-10-02 11:58:53 -07:00
Jimmy Wärting 7c0b869c7f webpack demo avoid readAsBinaryString [ci skip] 2021-09-30 19:31:52 +02:00
David Rault 0a0244cdfa DSV Pipe (|) potential delimiter [ci skip] 2021-09-30 10:46:35 +02:00
SheetJS e59de73f99 Hyperlink cleanup [ci skip]
- XLS normalize URLs and use moniker (fixes #2385)
- ODS row heights and column widths (fixes #2378)
- DSV parse of files with leading <, deviating from Excel (fixes #1238)
- read `ArrayBuffer` with no type (fixes #2316)
- removed invalid test files that throw errors due to string length
- AOA/JSON null optional map to #NULL! (fixes #1196)
2021-09-30 03:28:03 -04:00
SheetJS 8658054872 BIFF3/4 write support
- more precise support for unknown BIFF type (see #2390)
- `format_cell` render error strings
2021-09-26 18:51:19 -04:00
reviewher 88e662af99 empty row parsing (fixes #1413) [ci skip] 2021-09-23 00:19:42 -07:00
SheetJS a4ee0ef05a outline minutiae
- column levels (fixes #1655)
- XLSX parse sheetPr with children (fixes #1798)
- XLSX enforce 32768 string limit (fixes #1537)
2021-09-22 02:45:08 -04:00
notchris 4518cc8967 VueJS 3 demo [ci skip] 2021-09-21 15:03:05 -04:00
Austin Peterson 7fd172f2fc ODS Time date value (fixes #1381) [ci skip] 2021-09-20 22:22:45 -06:00
reviewher 5104ec1c63 require.js demo cleanup [ci skip] 2021-09-20 20:41:37 -07:00
William Krell ef4aec8796 zip path resolution 2021-09-20 20:31:27 -05:00
Hailong Wang bb9faf7caf writeFileAsync type def [ci skip] 2021-09-21 09:09:24 +08:00
Jimmy Wärting 82d0faa183 demos avoid readAsBinaryString [ci skip] 2021-09-20 09:37:16 +02:00
Robbie 37624cf990 XLS review [ci skip]
- truncate XLS Label Strings to 255 chars (fixes #1341)
- read column hidden attribute (fixes #2117)
- dateNF for XLS (fixes #1693 fixes #2305)
2021-09-20 08:10:53 +01:00
Jimmy Wärting bca646a1ad vue demo avoid readAsBinaryString [ci skip] 2021-09-19 06:11:54 +02:00
SheetJS 18ce6212c4 HTML cleanup
- HTML do not emit content attributes when editable (fixes #2137)
- HTML import hyperlinks (fixes #1384 #1509 #2188)
- HTML export hyperlinks (fixes #2326)
- Default color index (fixes #1412)
2021-09-18 17:27:42 -04:00
jefleponot 161da6c56c ODS writeFile default range [ci skip]
Co-authored-by: reviewher <reviewher@sheetjs.com>
2021-09-18 04:13:30 +02:00
Peter Lüderitz 4f154fd0fd date parsing test based on IE11 bug 2021-09-17 13:11:42 +02:00
Austin Peterson 361975f33a Bare single-sheet BIFF XLS parsing [ci skip] 2021-09-16 17:40:52 -06:00
Vishal Uchil c8a424f3da
Fix corruption of XLS file in 0.15.2 2021-09-16 19:32:47 +01:00
SheetJS 6670c8448e version bump 0.17.2: basic node/browser ESM 2021-09-15 21:50:33 -04:00
ustiloff 6c0ada1790 Read styles for stub cells [ci skip] 2021-09-15 09:47:27 +02:00
Owen Craig 27c457be99 Bower use unminified files [ci skip] 2021-09-15 02:09:42 -04:00
Cyberiaaxis f9e2d6dd11 fixed datagrid demo [ci skip] 2021-09-15 09:35:06 +05:30
Betsy Gamrat 7a00f3986d DSV double quote parsing (fixes #2270) [ci skip] 2021-09-14 05:53:11 -04:00
Meriam 07c354cecf Doc Replaced confusing emoji [ci skip] 2021-09-14 01:23:31 +02:00
jefleponot b03ad9d40c ODS do not use text:line-break [ci skip] 2021-09-13 08:02:38 +02:00
Puja Sharma af47faa292 XLSB formula parsing guard [ci skip] 2021-09-13 10:31:55 +05:30
Kevin Batdorf e7346ddfbe Add check for finite number [ci skip] 2021-09-12 22:06:46 -04:00
WineBewes 66a9cc79ca TypeScript 2.0.x compatibility [ci skip] 2021-09-13 03:45:24 +02:00
ikeq f384ccd8a8 Fix TypeError when styles don't have NumberFmt 2021-09-13 07:07:08 +08:00
SheetJS 3d35cebe9e Browser and Node ESM support 2021-09-12 07:19:09 -04:00
Josh 326b7c0ca1 package.json `types` point to actual types file 2021-09-12 04:18:17 -04:00
reviewher 6270e0259c knockout demo update [ci skip] 2021-09-12 00:55:10 -07:00
Austin Peterson cc9b791dfa x-spreadsheet demo update [ci skip] 2021-09-11 23:58:37 -06:00
Dan Krusi 38505f769e Doc mini build [ci skip] 2021-09-12 07:43:33 +02:00
Jimmy Wärting 50754f02be browserify demo avoid readAsBinaryString [ci skip] 2021-09-11 11:13:50 +02:00
Dan Dascalescu 96eee3c7eb Doc `json_to_sheet` cell type resolution [ci skip] 2021-09-11 01:33:48 -07:00
Himanshu Saini af34ae4178 Clarification on `json_to_sheet` header array
[ci skip]

Co-authored-by: Austin Turner <paustint@gmail.com>
Co-authored-by: reviewher <reviewher@sheetjs.com>
2021-09-11 13:48:49 +05:30
Austin Peterson 9dda70c773 package.json main point to script [ci skip] 2021-09-11 01:30:51 -06:00
reviewher f07a3d5fc0 XLSX Comment Parse Safeguard [ci skip] 2021-09-11 00:13:02 -07:00
Abdul Basit 297fd39563 updated dependency [ci skip] 2021-09-11 12:37:17 +05:30
Sylvain Lesage f57ba0af4f Documentation nit [ci skip] 2021-09-11 09:01:41 +02:00
Ikko Ashimine 4da25af3aa Comment Spelling [ci skip] 2021-09-11 14:17:00 +09:00
Bryan Ollendyke 5a3e5d91c1 xlsxworker use dist shim [ci skip] 2021-09-11 01:06:44 -04:00
rockboom d960b0adb7 Link to Chinese README Translation [ci skip] 2021-09-10 16:47:23 +08:00
Milo Lee 4257878cf6 Demos updated broken links [ci skip] 2021-09-09 14:02:44 +08:00
Luis Romero 7972d537e5 use HTTPS instead of HTTP [ci skip] 2021-09-08 21:59:26 -05:00
Austin Peterson 9b14cc75e4 Updated electron demo [ci skip] 2021-09-07 19:43:05 -06:00
SheetJS bf4736e966 biff8 write column widths 2021-09-02 05:58:39 -04:00
Jimmy Wärting 36a1a4e9b8 react demo avoid readAsBinaryString [ci skip] 2021-08-29 23:20:15 +02:00
SheetJS 7468f3b635 version bump 0.17.1: short XLSB records 2021-08-18 14:34:02 -04:00
SheetJS 81b7614e45 SYLK shared formulae 2021-08-11 05:05:36 -04:00
Бронякин Даниил c56347eff5 Use opts.codepage as default encoding for DBF 2021-07-29 04:50:50 -04:00
Jeremy Mill 3542d62fff version bump 0.17.0
- Explicit errors on inconsistent XLS records
- DBF cap worksheet to 1<<20 rows
2021-05-13 15:07:05 -04:00
Duncan Phelps 6c5db3663c AWS Lambda Binary Media Types 2021-05-03 22:10:16 -05:00
Akshat Mangal 59b3dae1a1 Tested the MongoDB scripts and fixed them 2021-04-20 21:02:53 +05:30
AmishBaztard e958dbf18e Refresh server demos
- microjs demo removed
- hapi.js demo does not work in latest version
2021-04-16 21:57:41 -04:00
SheetJS 1d7aff45c8 suppress modified test files 2021-04-13 16:06:18 -04:00
Jordan Harband f8c0a86581
[Tests] migrate tests to Github Actions 2021-04-08 11:21:37 -07:00
Taher 58e59dcfd5 updates to react demo
- bump react and babel
- converted to functional components

removed preact demo

renamed jsx to js for next make instruction

removed image component
added pod install for pod linking
2021-03-31 16:39:14 -07:00
Muzi Phiwokuhle Gondwe 333deae63f
write and parse ods in mini build (#2197) 2020-12-15 04:24:35 -05:00
SheetJS 20212e1cc2 version bump 0.16.9: utf-8 codenames 2020-11-20 02:13:01 -05:00
Robin Hu f7835d67b2 Add support for outline configuration
- "Summary rows below detail"
- "Summary columns to right of detail"
2020-11-02 18:08:52 -05:00
Federico Perez eec93b0b85 Fixed parsing for first cell in .fods documents 2020-10-26 16:21:55 -04:00
Francisco Presencia 6ecfeb602b Added google sheet example
Description

Added to readme

Fixed typo
2020-10-20 11:45:59 +09:00
Daniel Yonkov b0e68a9409 Add escape slash to cell matcher 2020-10-12 11:13:22 +03:00
SheetJS 9f1ba60c8d version bump 0.16.8: CRLF in formulae 2020-10-06 17:54:04 -04:00
Nabeel b9323c5502
Update 78_writebiff.js
fix(print): Excel crashes when printing XLS

fix provided by the SheetJSDev in https://github.com/SheetJS/sheetjs/issues/1967.
2020-10-07 01:25:37 +05:00
Janne Kujanpää d4cfadbbd7 Fix #2071
* Implemented with proposed fix
 * Future-proofing for newer major releases
2020-10-04 17:45:52 -04:00
Alex Macleod 5985739e72
Mark generated files as binary
This supresses local text diffs and prevents git from trying to automatically resolve merge conflicts within the files
2020-10-04 21:57:22 +01:00
Geohexamon 542636ba8f
Update 80_parseods.js 2020-10-04 12:45:56 -07:00
SheetJS 82b7ada6c7 version bump 0.16.7
- set active worksheet to first visible (fixes #1433 h/t @ManjunathSVBB)
2020-09-11 04:38:33 -04:00
赵风昭 0cc6cc9627 XLSX verify formula is string (fixes #1703)
Co-authored-by: SheetJS <dev@sheetjs.com>
2020-09-08 20:18:48 -04:00
Sam 2c5a863420 Removed null ws return from 90_utils 2020-08-20 13:29:06 +01:00
SheetJS 2e32611dbb version bump 0.16.6: xlfn option 2020-08-12 17:58:02 -04:00
Martin 3b589f001b XLSX SST treat <si></si> as empty (fixes #2083) 2020-08-12 15:16:01 -04:00
Israel Fraga abed474873 whitespace check (fixes #2075) 2020-08-08 17:24:00 -04:00
Israel Fraga 554d300413 Fixed logic error in `book_append_sheet` 2020-08-01 21:17:42 -04:00
SheetJS 78b0119b20 temporary fix for test suite 2020-07-30 23:54:10 -04:00
SheetJS 227f970ca1 version bump 0.16.5: `sheet_add_dom` (fixes #2073) 2020-07-30 23:38:44 -04:00
Mitkalev Aleksandr 41cc307e2d Fix encoding wb.WBProps.CodeName 2020-07-27 15:46:17 +03:00
wlawt 4fcb49b4d8 fix: move script from 28 to 29 2020-07-17 21:15:12 -04:00
SheetJS 6b1f5a0137 version bump 0.16.4 2020-07-16 19:20:43 -04:00
Alex Baranov 6127e19c02 feat(raw-numbers): optional raw numbers 2020-07-09 20:40:26 -07:00
Srijon Saha 9add78a290 Fix write not working and refactor
[ci skip]
2020-07-07 00:52:00 -07:00
geoffrymichael 57b296e5b5
Added fix for null value cell.v (#1730)
Closes #1717
2020-07-06 13:42:59 -07:00
Janie 6dc5e88a44 update test_files 2020-07-05 02:52:23 -07:00
William Law d45669ba9a
add: unicode test cases for cross-sheet names (#2047) 2020-07-05 02:32:27 -07:00
Mohammed Sahl 5c94936cfd
Add quotes to worksheet references in formulae (#2046) 2020-07-03 19:46:07 -04:00
William Law 5b08ba78a3
change test: buffer to string (#2042) 2020-07-02 20:24:39 -04:00
William Law 8ecbf4dc97
browser test cleanup (#2039)
* browser test cleanup

* add cases to core.js

* apply feedback
2020-07-02 12:57:21 -07:00
SheetJS e71eeda4d2 updated travis tests
Co-authored-by: Garrett Luu <garrettluu131@gmail.com>
2020-07-02 02:24:11 -04:00
Garrett Luu 93ec51ec76
Fixed failing travis builds (#2040)
* Added condition npm install to travis

* Updated node_version.sh perms
2020-07-01 20:56:41 -04:00
Garrett Luu 8795f86e12
Commented out fixed version number 2020-07-01 14:28:50 -07:00
Barron Wei 503fe89f8a
check first 8 bytes for CFB in readSync (#2038)
fix range for base64
2020-06-30 14:55:42 -04:00
SheetJS 768e1bdcf8 version bump 0.16.3
- updated SSF to 0.11.2
- XLS write support for `bookSST`
2020-06-29 04:07:23 -04:00
Srijon Saha 5b1440a186
Update electron demo (#2027)
* Update electron demo to version 9

[ci skip]

Co-authored-by: Ian Jennings <ian@meetjennings.com>
2020-06-28 03:22:46 -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
Srijon Saha 9ec9f4feb4 Add name to SheetProps
[ci skip]
2020-06-26 13:41:24 -07:00
Kevin Kerber cb2d83506e
when range is a single cell, s and e hold the same references and thus modifying properties of one affects the other (#2026) 2020-06-26 13:16:14 -07:00
Albert Mulia Shintra 716bef470e
fix: missing PRN in xlsx.mini (#1908)
- build: update mini script
2020-06-25 12:32:50 -07:00
Garrett Luu 0c7e809e9c
[ci skip] Fixed functions demos (#2025)
* Added test for CRLF newlines

* Initialized firebase functions app

* Updated gitignore

* Implemented csv file conversion

* CSV conversion

* Modified README to include firebase

* Added init-azure script to makefile

* Updated Azure demo

* Updated README
2020-06-25 12:30:56 -07: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
Mrinmay Mukherjee d0457b77c8
change WTF value from 1 to true (#2016) 2020-06-19 18:24:29 -07:00
SheetJS 9fc0ab7fa0 globalThis testing for SuiteScript 2.x [ci skip] 2020-06-19 16:07:13 -04:00
Garrett Luu 9015cdffd3 Added test for CRLF newlines 2020-06-18 16:10:41 -07:00
enghong 486f35b4cc
Add option to force quotes around values in when exporting to csv (#2009) 2020-06-17 18:34:04 -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
Srijon Saha c615f85034
Fix issue with dbf parsing 2020-06-16 13:51:56 -07:00
Srijon Saha c26525d52c
Merge pull request #2004 from garrettluu/master
Fix sep char recognition for CRLF newline files
2020-06-15 10:52:38 -07:00
Garrett Luu 5b356e2528 Fixed separators on files with \r\n at end of line
fixes #1943
2020-06-12 14:39:01 -07:00
Srijon Saha cdfe678571
Update CONTRIBUTING doc for PRs (#2003)
[ci skip]
2020-06-12 14:37:07 -07:00
Garrett Luu 688757ac64
[ci skip] Updated React and React Native demos (#1998) 2020-06-11 19:20:51 -04:00
SheetJS 5c1296a46d version bump 0.16.2 2020-06-05 01:42:28 -04:00
Manthan bef6c7e475 fix: disabling PRN by default
fixes #1976 fixes #1983 fixes #1977
2020-06-04 23:38:41 -04:00
SheetJS baea1798cf version bump 0.16.1
- Custom Properties use correct encoding
- AMD wrapper change (see #1937)
2020-05-16 15:45:54 -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
Michael 91f8c46704 HTML preserve cell number format 2020-04-26 04:19:53 -04:00
sbarstow 0ac53360b2 fix per project team email to parsing issue with empty doc security tag 2020-04-20 13:17:29 -04:00
SheetJS 257d4e6db2 version bump 0.16.0
closes #1904 h/t
- @atcazzual : Adam Cazzolla of the Sonatype Security Research team
- @davisjam  : James (Jamie) Davis of Virginia Tech
2020-04-19 21:17:44 -04:00
SheetJS 3468395494 x-spreadsheet demo 2020-03-22 21:57:53 -04:00
Lalo Martins 548396f87d
Better DST handling
h/t @lalomartins @lemmingworks

Closes #1332 and related date issues
2020-03-20 02:44:37 -04:00
SheetJS c91d2187e6 XLML case insensitive (fixes #1800)
h/t @panraj01, many tags are case insensitive
2020-03-18 02:47:02 -04:00
SheetJS 0a57229d3b version bump 0.15.6: niggles from 2012
- CFB prevent infinite loop (h/t @rossj)
- pass updated eslint checks (fixes #1726 h/t @BjoernRave)
- defined name proper encoding (fixes #1785 h/t @laohe98)
- correct theme color order (fixes #389 h/t @foreverpw)
- ODS / XLML more aggressive flagging of stub cells
- cellStyles implies sheetStubs
- updated SSF to 0.10.3
2020-03-15 03:57:44 -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 a81bb78f18 version bump 0.15.5: `sheets` option 2020-01-27 20:20:38 -05:00
SheetJS fefb415467 fmt_is_date properly handle string literals 2020-01-25 21:32:32 -05:00
SheetJS 6551dd0e05 version bump 0.15.4: number formats
- AOA utilities properly preserve number formats
- empty cell number formats (fixes #1711 h/t @aimergenge)
2019-12-22 22:19:56 -05:00
SheetJS 7ef3f3e531 version bump 0.15.3: Thanksgiving edition
Proper XML Encoding of Props/CustProps (fixes #1690 h/t @karlbecker)
2019-11-27 04:47:16 -05:00
SheetJS 7e932aec00 update badges [ci skip] 2019-11-14 21:01:30 -05:00
SheetJS 1a5bba267b version bump 0.15.2: actually pass lint tests 2019-11-14 20:46:49 -05:00
Tom MacWright 96e44a5ae4 Add unpkg and jsdelivr fields to allow CDNs to automatically pick compatible modules 2019-11-01 15:22:27 -04:00
SheetJS b7c0b0d914 fixed flow typecheck
- update FilterDatabase defined name when writing AutoFilter
- XLML stub cells have blank Data block
- HTML export honor `id` option
- expose `sheet_get_cell`
2019-10-31 23:09:14 -04:00
Jordon Replogle b0d18ed6db TSV Files can start with tab characters
Fixes #1421
2019-10-11 19:34:24 -04:00
sauravhiremath 19ebdd9477 bug: Remove white spaces due to html tags (#1622) 2019-10-05 13:24:06 -04:00
Rohan 4c956ff9de fixing some typos in the documentation 2019-10-02 15:26:14 -04:00
SheetJS e3c5eac99c initial release of S [ci skip] 2019-09-04 02:27:03 -04:00
Patryk Niedźwiedziński 458575184d
Fix #1244
Add error throw on a negative column index
2019-08-31 21:29:50 +02:00
Robin Nilsson ee862e3adf Fix issue #1536
Fix issue #1536
2019-08-30 02:07:58 -04:00
SheetJS 36fcb00045 version bump 0.15.1
- XLSX XML ignore attribute (fixes #1595 h/t @samih-dev)
- HTML capture and persist merge info
- mini build remove errant codepage reference
2019-08-14 16:11:16 -04:00
SheetJS 4aeb0a786a version bump 0.15.0: mini build
- new xlsx.mini build that strips XLS/XLSB/niche formats
- updated CFB to 1.1.3
- removed niche sheet_to_{dif,slk,eth} utilities
- removed exported ODS parse/write funcs, read/write still supports ODS
2019-08-04 16:12:56 -04:00
SheetJS 442c4342df version bump 0.14.5: XLS grind
- XLS force stub for commented cells (fixes #1567 h/t @Krelborn)
- XLS PtgNameX use ixti (fixes #1581 h/t @staperney)
2019-08-03 18:51:31 -04:00
Amir Elemam 90354392dd README Fix (fixes #1546) 2019-07-29 06:14:54 -04:00
SheetJS 9aabf36142 version bump 0.14.4
- CFB update (fixes #1149 h/t @xjnotxj)
- SYLK character encoding (fixes #1544 h/t @Slayess)
- DBF and SYLK ANSI codepage support
2019-07-20 23:32:02 -04:00
SheetJS 2fc52cce3e travis config 2019-06-22 01:48:31 -04:00
Tor Nilsson Öhrn 4109caeadd to_csv skipHidden corner case (fixes #1508) 2019-05-15 15:49:38 -04:00
SheetJS 9a6d8a1d3d version bump 0.14.3: formula niggle (closes #1388) 2019-04-30 03:31:01 -04:00
SheetJS 0c36667c0c version bump 0.14.2: comment xml (fixes #1468) 2019-04-01 10:25:15 -04:00
Jimmy Wärting ca22658b8c README use typed array (fixes #1362)
> The use of readAsArrayBuffer() is preferred over readAsBinaryString(),
> which is provided for backwards compatibility.
2019-04-01 09:33:51 -04:00
SheetJS 1eb1ec985a version bump 0.14.1: AutoFilter issues
- `stream.to_json` fix (fixes #167 h/t @Alex0007)
- AutoFilter `_FilterDatabase` Defined Name (fixes #1262 h/t @nitramL)
2018-11-13 15:25:51 -05:00
suwenxiong 1b731a3ef4 support cell object in sheet_add_aoa
Fixes #1279
2018-10-12 11:08:24 -04:00
SheetJS 4803695d8b update README [ci skip] (h/t @mikelax) 2018-09-06 13:04:46 -04:00
SheetJS 078e5b7eba version bump 0.14.0: sheet_to_json `raw` default
- sheet_to_json defaults to raw values (fixes #1252)
- update dependencies
2018-09-06 03:55:28 -04:00
notchris 5628fa81a3 BIFF8 Write Dimensions Type 0x200 (fixes #1188) 2018-08-29 21:14:04 -04:00
SheetJS eca6b457be version bump 0.13.5: HTML newlines
- HTML Export emits `<br/>` (fixes #1239 h/t @keithbox)
- Unicode Defined Name ODS
2018-08-25 19:44:35 -04:00
Jimmy Wärting d01e10c3f2 update XHR (fetch) demo 2018-08-22 02:59:47 -04:00
Michihito Osanai ab445c8897
introduce fix for issue#1229
https://github.com/SheetJS/js-xlsx/issues/1229
2018-08-22 13:47:23 +09:00
SheetJS d3d5bfc988 version bump 0.13.4: more corner cases
- explicitly throw when expected AOA isn't (fixes #1214 h/t @mnori)
- `ignoreEC` option to suppress IGNOREEC records on write
- workaround for BIFF2 BOF mismatch (fixes #1220 h/t @AhmadZuhdi)
2018-08-15 15:34:41 -04:00
Victor Phung 01de12d24f pass codepage option to DSV `buffer` parser
Fixes #1218 ; Closes #1219
2018-08-14 16:02:29 -04:00
Squillante 82e909e0ed Recognize case-insensitive properties
Fixes #1204 ; Closes #1205
2018-08-07 18:51:11 -04:00
SheetJS 10439f7879 version bump 0.13.3: dynamics export
- repair missing dynamics export metadata
- correct handling of non-DOM whitespace (fixes #1156 h/t @Sakura777)
- removed duplicate entity decode (fixes #1178 h/t @mishaberman)
2018-07-25 02:40:26 -04:00
mishaberman 5396e0231e allow HTML content inside of cells 2018-07-13 12:49:22 -07:00
SheetJS a9b8588e6c version bump 0.13.2: Buffer issues
- node 4.x buffer fix (fixes #1150 h/t @gabyidong)
- dependencies: CFB 1.0.8, codepage 1.14.0
- json object stream
2018-07-08 23:46:11 -04:00
Matt Andrews b6fd433a42 json_to_sheet cell objects
Fixes #1168, #1169
2018-07-07 13:01:21 -04:00
SheetJS 9866dfc010 version bump 0.13.1: SST optimization
- XLSX / XLSB avoid linear scan when emitting SST
- minor nits
2018-06-22 17:40:01 -04:00
SheetJS 64798fd1f9 version bump 0.13.0: AMD support
- library reshaped to support requirejs / amd without shim
- control comment visibility (fixes #998, h/t @cmuruganmsc)
- fixed README code sample error (fixes #1118 h/t @iahmedani)
2018-06-01 12:32:08 -04:00
Surgie Finesse 2918185249 DOM TABLE parse element visibility
- Hidden rows are marked as hidden by default (mimics Excel behavior).
- `display` option for `table_to_*` replicates table as it appears.

Fixes #1115
2018-05-29 11:11:06 +10:00
Tom Bousso 4737d80db4 Support namespaced xml in styles.xml
Fixes #1114 h/t @tombousso
2018-05-22 16:20:22 -04:00
notchris d102b75cad Knockout Demo [ci skip] fixes #1061 2018-05-20 21:41:01 -04:00
SheetJS 233102d172 version bump 0.12.13: sylk niggles
- sylk column-major order support
- third-party extensions in SST
- `string` type codepage
2018-05-19 21:34:59 -04:00
SheetJS c0b4895881 version bump 0.12.12: ecosystem deprecations
- node 10 `Buffer` deprecation workaround (with dependency update)
- Angular 6 global deprecation workaround (fixes #1088 h/t @cristhiank)
- BIFF8 write standard and custom properties
- TH elements in HTML string (fixes #1090 h/t @GigiSan)
- planmaker export quirks
2018-05-05 02:34:37 -04:00
SheetJS eb5fc87be4 version bump 0.12.11: file format range limits 2018-04-27 16:42:58 -04:00
SheetJS 75c49ddbe8 flow update 2018-04-21 11:16:37 -04:00
SheetJS e267d1d667 flow switch to module.exports 2018-04-21 11:03:20 -04:00
SheetJS f032f34c6e version bump 0.12.10: sheet_to_json niggle
- default not treated as value for empty rows (fixes #1078 h/t @cemremengu)
2018-04-19 22:17:09 -04:00
Drew Smith 6916d5fc73 add pt unit to font-size in HTML
fixes #1077
2018-04-19 21:12:58 -04:00
SheetJS 04d5e49e95 version bump 0.12.9: XLSX/XLSB abnormal paths
- support for arbitrary subfile paths in OPC
- updated CFB to 1.0.6
2018-04-13 00:48:21 -04:00
SheetJS 93f7749bec version bump 0.12.8: sheetRows multiformat support
- all formats accept `sheetRows` option (fixes #1062 h/t @prog666)
- `table_to_*` support for `sheetRows`
- demo cleanup
2018-04-06 02:39:48 -04:00
SheetJS 3592efa77b travis npm ssl fix for 0.8
see https://github.com/npm/npm/issues/20191
2018-03-29 11:42:49 -04:00
SheetJS 08bb7e6e60 version bump 0.12.7: chrome extension
- `writeFile` support chrome extension (fixes #1051 h/t @atkinsam)
- demo refresh
2018-03-29 00:31:36 -04:00
SheetJS dc2128caca version bump 0.12.6: BrtUid
- `BrtUid` record (fixes #1044 h/t @gustavosimil)
- `sheet_to_json` allow default for errors (fixes #1035 h/t @arijitkanrar)
- docs and demos update
2018-03-19 17:42:55 -04:00
Tal Bereznitskey 975c7fb57f Fixes xlsb file parsing with BrtRevisionPtr
Fixes #1041 h/t @berzniz
2018-03-19 11:56:04 -04:00
SheetJS 5de62a947f version bump 0.12.5: ancillary utility update
- add BOM to `stream.to_csv` (fixes #1024 h/t @hr5959)
- `utils.format_cell` type (h/t @victorj2307)
- duktape niggles
- demo cleanup
2018-03-12 22:51:54 -04:00
georgiebin 73a5e50f21 Electron README cleanup [ci skip]
use `XLSX` rather than `X` in README
2018-03-07 12:34:02 -05:00
andrisarkameru be4e21c6f1 Updated types list in TS definition [ci skip]
fixes #1026
2018-03-07 10:44:55 -05:00
SheetJS 7149728c7c version bump 0.12.4: zip cleanup
- PK magic number bound (fixes #1013 h/t @wlpeter)
- removed JSZip conflict (fixes #1017 h/t @seanmars)
- updated CFB to 1.0.5
- demo HTML conversion `string`
2018-03-05 19:34:04 -05:00
SheetJS 5dd16ae640 version bump 0.12.3: cleanup
- PtgList and old Ptg record support
- fleshed out ftab constants from macrosheet support
- reimplemented / fixed / removed shim functions
- demo refresh
2018-02-28 05:41:49 -05:00
Bryan Braun e3efc1ad7d
Add a section to the README for examples. 2018-02-24 11:39:12 -05:00
SheetJS 8508ad4e94 version bump 0.12.2: BIFF2-4 features
- correct BIFF-dependent cell reference wrapping
- record layout fixes from sample files
- use BIFF version 2.4.338 for BOF (fixes #995 h/t @benjaminleetmaa)
- fixed potentially vulnerable regexes (h/t @davisjam)
- removed insecure deep dependency (fixes #996 h/t @dcatoday)
2018-02-21 02:10:33 -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
mugai17 88e9e31ebf fix infinite recursion 2018-02-18 12:56:52 +09:00
SheetJS 19620da30b version bump 0.12.1: BIFF5 features
- BIFF5 write number formats and other features
- XLSX/XLSB/BIFF8 Suppress "Number stored as Text" errors
- codename awareness (fixes #992 h/t @samusstrike)
- updated CFB to 1.0.3
- demo refresh
2018-02-14 15:06:35 -05:00
SheetJS f002afae4b version bump 0.12.0: extendscript fixes
- ExtendScript write quirks (fixes #986 h/t @grefel)
- BIFF8 write number formats (fixes #987 h/t @scwood)
- xlsx.extendscript.js library script
- readFile / writeFile support ExtendScript
- flow update
2018-02-08 13:21:39 -05:00
Maxim Kukhtenkov fb97bf1768 VBA CFB test [ci skip] 2018-02-04 19:01:44 -05:00
SheetJS 75845a0ca7 version bump 0.11.19: browser `writeFile`
- IE6-9 ActiveX + VBScript shim
- `writeFile` supported in browser
- `oldie` demo for IE write strategies
2018-02-03 15:46:32 -05:00
SheetJS edf7150ca8 demo refresh [ci skip] 2018-01-26 19:52:46 -05:00
SheetJS c2ec7555fb version bump 0.11.18: infrastructure
- updated dependencies
- fixed eslint config
- fusebox demo
2018-01-23 04:07:55 -05:00
Tony Germaneri 376db8fe9f added height/width constraint to canvas-datagrid 2018-01-22 14:35:11 -08:00
reviewher c654a2656b archaic browser compatibility and testing
IE11 Compatibility View levels 5 and 7 (see #952)
Firefox 5.0+ passes browser test (see #950)
2018-01-11 03:07:07 -05:00
SheetJS 1d74977718 version bump 0.11.17: sheet_add_{aoa,json}
- Skip extraneous trailing records (fixes #938 h/t @benjaminleetmaa)
- XLS -> XLML oddities (fixes #678 h/t @buserror)
- ionic demo
- sheet_add_aoa and sheet_add_json
Issues:
- fixes #947 h/t @fpasxos
- fixes #666 h/t @samuelkavin
- fixes #301 h/t @acgentry
- fixes #561 h/t @Ideandro
2018-01-09 02:36:02 -05:00
html5-李恒逸 a7d3779724 __toBuffer chunking (fixes #937)
10240 threshold from older version of fixdata
2018-01-02 11:49:44 -05:00
SheetJS f277ebe140 version bump 0.11.16: refresh
- HTML whitespace (fixes #849 h/t @laurentauthier)
- XLML number format write (fixes #904 h/t @james-boswell)
- XLAM/XLA write
- 'array' write type
- XLSX/XLSB/XLS/XLML RTL read/write
- XLS merge cells write
- demo and typing refresh
2017-12-30 03:20:00 -05:00
SheetJS 33f96fc6ae version bump 0.11.15: right-to-left write
- XLSX right-to-left support (fixes #927 h/t @mghayour)
- HTML string preserve newline (fixes #929 h/t @Irikos)
2017-12-24 21:25:03 -05:00
Vincent Jaubert 028d7010a5 sheet_to_json: __EMPTY keys for missing headers
closes #864
2017-12-17 11:32:55 -05:00
SheetJS b3873ea615 version bump 0.11.14: links
- BIFF5 + ODS read named ranges
- internal link range normalization
- BIFF8 + ODS link write
- internal link write (fixes #685 h/t @gawi)
2017-12-14 20:18:40 -05:00
大黄蜂coder b17a09849a HTML TD 't' attribute (fixes #917)
note: @sheetjsdev authored commit, original PR date/author used
2017-12-12 02:14:46 -05:00
SheetJS c9cab8078c version bump 0.11.13: codepage
- binary CSV `codepage` read option (fixes #907 h/t @popovserhii)
- BIFF2-5 `codepage` read option (fixes #912 h/t @makcbrain)
- `xlsx` utility `--codepage` override option
- HTML support some common entities (fixes #914 h/t @razvanioan)
2017-12-09 02:17:25 -05:00
SheetJS eff7d153e8 version bump 0.11.12: merging js-harb
- ETH format and utils merged from js-harb
- added shim to npm package (fixes #911 h/t @dackmin)
- TS defs refresh
- updated test_files
2017-12-03 23:41:41 -05:00
SheetJS cd2e639fc2 version bump 0.11.11: CFB miscellany
- export `sheet_to_txt` (fixes #905 h/t @aj4mq)
- BIFF4 Format Record aligned to BIFF 2/3 (fixes #909 h/t @ToujouAya)
- updated CFB to 1.0.1
- typescript standalone demo
- nexe / pkg xlsx.njs demo
2017-12-01 00:48:10 -05:00
TTL a0bc73da69 demo to_json array of arrays (see #896) [ci skip] 2017-11-23 00:07:18 -05:00
SheetJS 547fba56a2 version bump 0.11.10: binary miscellany
- XLSX empty numeric cells stubbed (fixes #891 h/t @mgoku)
- XLS sheet type identification
- XLS/XLSB/XLSM CodeName exposure (fixes #361 h/t @TennisVisuals)
- CFB re-exported
2017-11-19 20:51:14 -05:00
SheetJS 7c7f4a69d4 version bump 0.11.9
- CLI `--book` convert all worksheets (fixes #701 h/t @pmelisko)
- Detect ";"-DSV with no "\t" or "," (fixes #875 h/t @sh977218)
- editable HTML uses spans for IE6+ compat (fixes #851 h/t @elogicmedia)
- XLSB formula structure parallels XLS (fixes #680 h/t @bstiel)
2017-11-15 13:14:02 -05:00
mzvast 687dcc80b9 correct vue and react README typos [ci skip] 2017-11-15 20:35:16 +08:00
SheetJS 3f6f8e93ed version bump 0.11.8: CFB 1.0.0
- travis node 9 test
- demo refresh
2017-11-05 14:18:35 -05:00
Andreas Hjortland 1ab13069cb Remove closing `>` of <br> tag
Use get_dom_element
2017-10-31 20:18:29 +01:00
SheetJS 825830d1cd version bump 0.11.7: VFP DBF write
- DBF writer (dBASE II + VFP extensions)
- updated CFB to 0.13.2
- BIFF8 XLS write VBA
2017-10-27 12:25:54 -04:00
SheetJS ed4348a6b6 XLS cellText option (fixes #841 h/t @cyzeng-Luca) 2017-10-17 23:44:12 -04:00
SheetJS f968dfe4ed version bump 0.11.6: ancillary format update
- BIFF5 XLS write (bookType "biff5")
- DBF Level 7 read
- ODS whitespace and repeated rows
- flow and lint cleanup
2017-10-16 20:14:32 -04:00
Ravelle Kelley ef9f3f9ca5 fix worksheet protection options 2017-10-16 18:19:53 -04:00
Dumitru Uzun 51b4751b95 DSV detect semicolon ';' delimiter 2017-10-16 22:47:04 +03:00
Oliver Yeoh 6d741ebd3a Parse text:s elements containing text:c attribute
Fixes #835
2017-10-10 13:10:52 +08:00
SheetJS c88f83940c RTF write stub
- Empty WS on RTF read, rudimentary write
- reshape XLS VBA blob
- CI adding back old nodejs versions
- refresh tests and docs
2017-10-02 04:15:36 -04:00
SheetJS af3df44633 version bump 0.11.5: "string" type
- proper JS string input / output type
- bower main now uses full version (fixes #820 h/t @newmesiss)
- DOM parse directly acts on innerHTML (see #779 h/t @danxfisher)
- unicode core props and ext props (fixes #822 h/t @fureweb-com)
- shim update for IE10/11
- test refresh and flow checks
2017-09-30 02:18:11 -04:00
SheetJS 1a8f97269e demo refresh [ci skip] 2017-09-24 19:40:09 -04:00
SheetJS d02650055d version bump 0.11.4: BIFF8 XLS write
- xlsx bin script takes `-8, --xls` options for writing BIFF8
- updated CFB to 0.12.1, CRC32 to 1.1.1
- test file spelling error (h/t @jsoref)
- minified script renames write_shift / read_shift
- UTF8 and XML entity processing

Issues:
- fixes #815 h/t @Neroth
- fixes #739 h/t @LittleBreak @PWDream
- fixes #553 h/t @keyiis
- fixes #492 h/t @FlyingSailor @simonchan2013
2017-09-22 18:18:51 -04:00
SheetJS f03e32fc9a updated demos [ci skip]
- frameworks: react, react-native, preact, next.js, weex, nuxt.js
- deployments: nodejs server, duktape, chakra, electron, nw.js
2017-09-12 16:02:06 -04:00
SheetJS ad47cb433c Math.LOG2E precision issue + new demos [ci skip]
- swift + jsc
- java + rhino
- XMLHttpRequest and friends
2017-09-05 01:34:30 -04:00
Josh Soref e34b6e78d2 spelling [ci skip]
- fixed spelling errors in README and code (fixes #802)
- replaced garbled names in property tests (fixes #803)
2017-09-04 03:55:10 +00:00
SheetJS 635310b639 version bump 0.11.3: "array" type
- phased out Array map invocations (fixes #620 h/t @dullin)
- "array" type supports Uint8Array
- Headless browser examples
- blank cells are omitted or stubbed (fixes #779 h/t @domxa)
- removed transferrables from demo
2017-08-19 19:06:34 -04:00
SheetJS 2ea9c95839 HTML and CSV parsing
- blank cells are omitted or stubbed (fixes #770 h/t @doxma)
- bare equals signs are interpred as strings
- CSV / TSV determination based on frequency (fixes #732 h/t @nknapp)
- HTML DOM Element and CSV tests
- XLS do not leak XF and index (fixes #782 h/t @the-spyke)
- cellText and cellNF apply to CSV (fixes #781 h/t @the-spyke)
2017-08-18 14:10:18 -04:00
Hugh Greenish f6981076ec Fix fuzzydate string matching logic 2017-08-17 16:59:17 +01:00
SheetJS 5b67ac0806 version bump 0.11.2: proper plaintext parsing
- dollar currencies and percentages properly detected as numbers
- parse potential CDATA segments in XLSX (fixes #775 h/t @awb99)
- IE8 issues with regex
- altjs demos

Issues:
- fixes #673 h/t @huhm
- fixes #748 h/t @sangpuion
- fixes #749 h/t @GreggOD
- fixes #772 h/t @sangpuion @jyyan
2017-08-10 19:46:34 -04:00
SheetJS 9ba09bab5e improved plaintext parsing
- fuzzy number check disregards commas (fixes #709 h/t @mz121star)
- updated to CFB 0.12.1
- parse_dom_table and html_to_sheet raw option
- canvas-datagrid demo
- docs and TS definition update
2017-08-09 18:38:23 -04:00
SheetJS 5855bcb678 demos and docs [ci skip]
- json_to_sheet options (fixes #771 h/t @enniob)
- demos include HTML files (fixes #770 h/t @jwamsley)
2017-08-08 16:31:17 -04:00
Hugh Greenish 54f380ef2c new tag regex handles angle brackets in attributes
fixes #768
2017-08-08 14:22:17 -04:00
Austin Turner d443860e6d Improved Code Style of Angular 2+ Demo [ci skip] 2017-08-05 18:23:11 -06:00
SheetJS 935821423f version bump 0.11.1: dist cleanup
- dist scripts properly export library
- XLS/XLSB formulae quote sheet names containing spaces
- skipHidden ported to streaming CSV write
- updated codepage to 1.11.0
- flow and TS updates
- webpack demo example using dist scripts
- requirejs demo
2017-08-05 02:32:57 -04:00
David Beaumont 0f39f2818f Don't throw when vt:vector isn't the expected size
Fixes #759
2017-08-03 17:38:30 +01:00
Anton Alexandrenok 2339e13222 `skipHidden` option for sheet_to_csv (fixes #755)
Note: Excel CSV conversion includes hidden rows and columns by default
2017-08-02 19:41:44 +03:00
SheetJS 7d15f35e3e version bump 0.11.0: new minified versions
- build script strips `require` statements
- finally every version is pinned (see #740 h/t @the-spyke)
- removed colloquialisms in README
2017-08-01 01:50:53 -04:00
SheetJS 71f827c4fa version bump 0.10.1: fixed deps 2017-07-31 22:28:37 -04:00
SheetJS ce37f99ec3 version bump 0.10.9: pin dependencies
- updated SSF 0.10.0, codepage 1.10.1, CFB 0.12.0, CRC32 / ADLER32 1.1.0
- pinned all devDependencies (fixes #740 h/t @the-spyke)
- flow type updates
- clarified meteor usage (fixes #751 h/t @NorthDecoder)
2017-07-28 19:27:16 -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 6732eb76f8 hodgepodge of fixes
- missing formula elements rewritten to valid defined names (see #680)
- comment author length limit enforced
- XLS ifmt references renamed to numFmtId for consistency with XLSB
- removed circular symlink
- mangle/compress with uglify
- more flow comments
2017-07-27 17:15:55 -04:00
Roberto Frias 5ffa3e0869 TypeScript 2.2 fixes [ci skip]
fixes #746 h/t @rcfrias
2017-07-27 12:15:13 -04:00
SheetJS 807eac273b miscellany
- systemjs browser example
- more precise file type resolution
- small corner cases from test corpus
- removed neq in tests (fixes #735 h/t @TeamworkGuy2)
- package.json devDependencies versions (fixes #740 h/t @the-spyke)
2017-07-26 04:35:28 -04:00
SheetJS 6a913d3a7b version bump 0.10.8
- TS definition removed DOM references (fixes #724 h/t @shaunc)
- extendscript inconsistent processing of bitwise ops
- updated browser tests
2017-07-10 18:18:18 -04:00
Danwakeem d28cc872c7 XLS/XLSX/XLSB Row Outline Levels (closes #723)
note: @sheetjsdev rewrote implementation, original PR author used
2017-07-10 06:02:06 -04:00
TMiller00 859691b87b Added a check for a raw string in .csv files 2017-07-09 01:15:28 -04:00
avrtau 43795a43bb Update SheetJS-vue.js 2017-07-06 14:55:10 -04:00
SheetJS 00f25cfe1e version bump 0.10.7: autocorrections for bad files
- recalculate SSF for malformed files (fixes #506 h/t @asksahil)
- malformed shared string (fixes #445 h/t @Ramzec)
- SSF added to TS def (fixes #711 h/t @duckywang1)
- Norsk property names
- resolved gitbook processing issues
2017-07-05 18:27:54 -04:00
王达夫 739c4f220c [fix] typescript definition for SSF 2017-07-05 15:15:23 -04:00
SheetJS 1988338deb version bump 0.10.6: encoding tweaks
- updated codepage to 1.9.0
- replaced \u2603 with \s\S (fixes #687 h/t @clgnik)
2017-06-24 02:51:37 -04:00
SheetJS 56cf192615 angular 2 / angular 4 demo [ci skip] 2017-06-21 19:10:36 -04:00
SheetJS 20f22cf7f9 vue demo and typing fixes [ci skip] 2017-06-19 03:14:18 -04:00
Christopher Thielen 5ceb2e01b5 Add missing TS definitions 2017-06-17 22:33:08 -04:00
SheetJS c7e7180ab9 angular 1 demo [ci skip] 2017-06-14 10:29:20 -04:00
James Yang 36022a0f56 fix hyperlink text encoding
see issue https://github.com/SheetJS/js-xlsx/issues/684
2017-06-13 10:26:29 +08:00
SheetJS 5d997df419 version bump 0.10.5
- HTML output new preamble, <table> should not be in header/footer
- XLS Built-In defined names translated to XLSX _xlnm form
- README: streaming read strategies
- If approximation error is sufficiently small, assume MDW is 6
- TS rename Utils type to XLSX$Utils (see #618)
2017-06-09 21:54:33 -04:00
Valters Valdersteins da1c111275 updated SSF to 0.9.4
- fixes #677 h/t @kuhu19
- fixes #676 h/t @vvaldersteins

note: @sheetjsdev authored commit, SSF PR info used
2017-06-08 22:19:15 -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 6a100b9085 rollup demo [ci skip] 2017-06-08 02:19:11 -04:00
SheetJS 81ab4f9b1f version bump 0.10.4: privacy filter 2017-06-03 03:19:09 -04:00
SheetJS aff7b95272 Date/Time Minutiae
- TZ consistency for DBF and others (closes #663 h/t @peeyushsrivastava)
- Date1904 XLSX/XLSB/XLS/XLML consistency (fixes #175 h/t @SheetJSDev)
- dateNF corrects for plaintext date parsing (fixes #658 h/t @mmancosu)
- new travis tests override local time zones
2017-06-01 17:22:11 -04:00
SheetJS 118e9ad9cb meteor example [ci skip] 2017-05-24 18:52:35 -04:00
SheetJS 53e534f2cc systemjs node/browser examples [ci skip] 2017-05-19 12:46:08 -04:00
SheetJS e996df7b67 version bump 0.10.3: flush
- CSV double-quote processing (fixes #656 h/t @jckkong)
- actually updated SSF to 0.9.3 (h/t @HuFlungDu)
- npm module actually includes the types
2017-05-17 13:52:32 -04:00
SheetJS 3ff724e349 version bump 0.10.2: date processing corner cases
- all formats follow cellDates / dateNF (fixes #653 h/t @mmancosu)
- IE6-8 Date corrections
- XLML Date force UTC
- updated SSF to 0.9.3 (fixes #372 h/t @HuFlungDu)
- removed CFB export
2017-05-17 00:23:36 -04: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 3fde651a8c sheet_to_html
- added to TS definition and tests
- clarified behavior of plaintext files (fixes #641 h/t @dskrvk)
- removed old test files
2017-05-16 13:45:35 -04:00
SheetJS 409581b317 TS write test
run `make tslint` to run TS checks
2017-05-15 11:50:46 -04:00
Wolfgang Faust cb6633be18 Rename interfaces to not start with I. 2017-05-13 19:37:23 -04:00
Wolfgang Faust 0af66e171f Use `object` instead of `Object` in type definitions. 2017-05-13 19:31:56 -04:00
Wolfgang Faust 5d433c72b8 Integrate type definitions. 2017-05-13 19:30:01 -04:00
Wolfgang Faust 02d4542ef0 Add typescript definition file from @types/xlsx. 2017-05-13 15:39:33 -04:00
Wolfgang Faust 1b6436c351 Move all files into types/ subdirectory. 2017-05-13 15:38:52 -04:00
SheetJS 99b513875b lint and type fixes
- removed CFB test (fixes #654 h/t @wolfgang42)
- book_append_sheet optional name (fixes #652 h/t @jomel)
- strict mode compliance (h/t @simon-p-r @loongdefect @appersonj)
- flow fixes (h/t @jameskraus for help with Date#getYear)
- fixed minifier to generate ExtendScript-compatible code
2017-05-13 14:21:22 -04:00
Wolfgang Faust 8385d5c889 xlsx: Linter: Require interfaces to start with 'I'
The default rule for DT is that they're *not*,
but changing that now would break existing usages of the xlsx typings.
2017-05-13 13:05:21 -04:00
Wolfgang Faust cda05f3b45 xlsx: Fix miscellaneous lints. 2017-05-13 13:05:20 -04:00
Wolfgang Faust 0fb38af783 xlsx: Fix whitespace lints. 2017-05-13 13:05:18 -04:00
Wolfgang Faust bf73d62903 xlsx: Add new ExcelDataType type.
This allows variables to be declared as this type
so an error will be raised if an incorrect value is used.
2017-05-13 13:05:17 -04:00
Wolfgang Faust 29ed597df6 xlsx: Add properties of IWorkSheet. 2017-05-13 13:05:16 -04:00
SheetJS c3c0bc5266 version bump 0.10.1: json_to_sheet, misc fmts
- SYLK auto fail into DSV on bad header (fixes #651 h/t @mmancosu)
- CSV automatically wrap `ID` in quotes
- json_to_sheet (see issue #610)
2017-05-11 14:36:32 -04:00
SheetJS 7b4bafba49 Miscellaneous format fixes
- SSF update to address extendscript issue (fixes #608 h/t @mjdb3d)
- XLSX cellDates set date format (fixes #647 h/t @psalmody)
- ODS add stub stylesheet for Excel (fixes #649 h/t @WaqasJaved1)
- CSV with UTF8 BOM (fixes #650 h/t @charlesread)
- DIF/CSV fuzzy date speculation
- SYLK parse RC formulae
- CSF utils for manipulating workbooks
2017-05-11 03:29:59 -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 a8736580a5 version bump 0.10.0: cleanup
- updated SSF to 0.9.2
- XLSB style records and number format writing
- CSV avoid parseFloat (fixes #646 h/t @jabbermarky)
- CSV recognize mac line ending (fixes #648 h/t @charlesread)
- BIFF2 format table refactored to align with SSF
- BIFF5 image data exposure
- SSF custom format auto table update (fixes #267 h/t @Fangmingdu)
- eslint more checks
- browser test timeout extended to 10 seconds
2017-05-09 14:07:57 -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 810c447bf9 browser tests and doc cleanup [ci skip] 2017-05-01 01:00:00 -04:00
SheetJS b9bc0a1627 version bump 0.9.13: string formatting
- dateNF parse option controls interpretation of code 14
- SSF updated to 0.9.1
- SYLK write formulae
- DIF support Excel-style data storage
- ODS/FODS automatic styles for date formatting

Issues:
- Fixes #181 h/t @CharlesNo
- Fixes #200 h/t @JohnJeong123
- Fixes #208 h/t @jerryhe88
- Fixes #262 h/t @JohnJeong123
- Fixes #269 h/t @calebeaires
- Fixes #326 h/t @railty
- Fixes #392 h/t @FourLeafClover
- Fixes #449 h/t @dougschiller
- Fixes #560 h/t @dpackage
2017-04-30 12:27:03 -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 dcee744e4e row and column size and visibility
- XLSX/XLSB/XLS/XLML/SYLK rows and columns
- corrected pixel/point calculations using PPI
- XLSX/XLSB generate sheet view
- clarified sheet protection default behavior
- fixed eslintrc semi check
2017-04-28 03:40:40 -04:00
Patrick Lehmhecker c6f96c3df7 converting to json with a selected range and header: 1 now lets the array start at zero 2017-04-26 17:32:42 +02:00
SheetJS 95a377c0e4 more format parity
- XLS/XLSX/XLSB/XML/ODS cellFormula option + test
- XLS/XLSX/XLSB/XML/ODS cellText option + test
- XML document property order
- XML write margins + protection
- removed gitbook search
2017-04-25 22:27:12 -04:00
reviewher 83ec60688f Windows build (fixes #589 h/t @simon-p-r)
run `make help` for more info
2017-04-24 06:39:00 -04:00
SheetJS 0fd11047bb remove gitbook link [ci skip] 2017-04-21 20:52:45 -04:00
SheetJS 8c4f1f4e84 version bump 0.9.12
`cellText` parse option controls `.w` output (fixes #640 h/t @SCullman)
2017-04-21 18:02:05 -04:00
SheetJS 6853c99ce5 rich text HTML + preview 2017-04-19 23:43:43 -04:00
Siguza c356e91fdc XLSX write page margins
changes distilled from Siguza/js-xlsx
see https://github.com/protobi/js-xlsx/pull/19 for discussion
2017-04-16 22:31:33 -04:00
SheetJS 09fba37eac switch to eslint
- eslint pass (eliminates jshint and jscs)
- moved cell reference functions to reduce forward references
- themeXLSX override XLSX/XLSB/XLSM theme
2017-04-16 22:08:23 -04:00
SheetJS f51feb375a version bump 0.9.11: streaming HTML write 2017-04-16 03:31:21 -04:00
SheetJS 1d61054602 HTML Write support
- 'html' bookType write format
- basic HTML entity encoding (fixes #629 h/t @xkr47)
- HTML string and table merge cell fixes
- doc notes on nodejs streaming
2017-04-16 00:32:13 -04:00
Tim Burnell d0a59ae283 fix error 2017-04-14 15:49:38 -05:00
Tim Burnell 8b9a008159 fix formatting and types 2017-04-14 15:37:22 -05:00
Tim Burnell a5b8313ff4 add aoa_to_sheet because it was missing
below are still missing, but i require aoa only.
split_cell:
format_cell
get_formulae
make_csv
make_json
make_formulae
table_to_sheet
table_to_book
sheet_to_row_object_array
2017-04-14 14:16:23 -05:00
Jonas Berlin 616d2e534f XLSX Proper HTML entity escaping for .h 2017-04-13 14:33:00 -04:00
reviewher b3ace1e5a9 Doc Improvements [ci skip] 2017-04-13 13:05:42 -04:00
Jani Hartikainen c9d0aa140d Small Test and Doc Fixes 2017-04-13 03:10:18 -04:00
SheetJS 1587688aea Page Margins
- XLSB read/write page margins
- XLSX/XLS/XLML read page margins
- separated encrypted XLSX/XLSB document logic from XLS
2017-04-12 21:29:38 -04:00
SheetJS 0189bc23ca Defined Names
- XLSX read/write defined names
- XLSB/XLS/XLML read defined names

Issues:
- fixes #83 h/t @developergdd
- fixes #6 , fixes #599
2017-04-11 18:15:36 -04:00
SheetJS 5187bc0b63 Basic AutoFilter Read/Write
- XLSX/XLSB read/write autofilter
- XLS/XLML/*ODS read autofilter
- Workbook Properties override via Props option
- XLSB write sheet protection

Issues:
- fixes #472 h/t @nishthasb
- fixes #478 h/t @yonatannn
- see #623 h/t @jcarvin
2017-04-10 01:11:32 -04:00
SheetJS c13170fbd5 windows build (see #589 h/t @simon-p-r) [ci skip] 2017-04-09 03:11:08 -04:00
SheetJS 51182e57ef version bump 0.9.10: nodejs performance
- xlsx.njs use dense mode by default
- CSV Streaming output for nodejs
- XLSX/XLSB error on password protected documents
- record hoppers switch on record number rather than name
2017-04-09 00:04:46 -04:00
SheetJS f43cacaf5e experimental dense representation
- browser demo save file in global (fixes #573 h/t @WildDusk)
- flesh out XLSB record expectations (fixes #624 h/t @pgeeh)
- `dense` mode (fixes #34 h/t @schleumer)
2017-04-08 02:55:35 -04:00
Mior d086dbecbf XLSX write Sheet Protection
fixes #363 h/t @Mior

note: @sheetjsdev rewrote implementation, original PR author used
2017-04-04 14:46:10 -04:00
SheetJS 6a3afe56c2 Lotus / Quattro Pro read support 2017-04-04 12:09:41 -04:00
SheetJS 01d1c32fa1 version bump 0.9.9: basic TXT/CSV read
fixes #489 h/t @vijayst
fixes #617 h/t @ayush000
2017-04-03 02:02:05 -04:00
SheetJS b9dae134f2 TXT/PRN
- UTF-16 Unicode Text (TXT) write
- Lotus Formatted Text (PRN) read/write
- DBF version 2 field length adjustments
- throw errors if SheetNames is invalid (fixes #376 h/t @pietersv)
2017-04-02 20:16:03 -04:00
SheetJS 3a310bd3a7 Read/Write Comments
- XLSB/XLSX/XLML write comments
- BIFF2 write date cells (see #586 h/t @roccomuso)
- ODS read cell comments (fixed #315 h/t @yisk)
- XLSX / XLSB emit empty comments when necessary
- changed node detection logic (fixes #614 h/t @mhenris)

- fixes #605 h/t @ylbweb
- fixes #233 h/t @hanxi @osecki
- fixes #192 h/t @abarik1981 @stla
- fixes #183 h/t @aravindkoneru @ryangallen
2017-04-02 02:47:25 -04:00
SheetJS b93569badf more formats from js-harb
- clarify usage of Props and Custprops (fixes #274 h/t @michahell)
- SYLK from js-harb
- DIF from js-harb
- HTML empty string bug fix
2017-04-01 03:32:12 -04:00
SheetJS e42cf43c02 version bump 0.9.8 2017-03-31 17:46:02 -04:00
SheetJS 97f7c1d4bf sheet visibility
- XLSB read V H VH + write V H VH
- XLSX read V H VH + write V H VH
- XLML read V H VH + write V H VH
- XLS  read V H VH

- fixes #123 h/t @rla-dev @Mior
- fixes #464 h/t @enobufs @thowk
- fixes #498 h/t @digity
- fixes #503 h/t @digity
2017-03-31 14:46:42 -04:00
Paul Ishenin 233eae2f4e !rows processing (fixes #188)
based on comment from @sheetjsdev:
https://github.com/SheetJS/js-xlsx/issues/81#issuecomment-48360276

fixes #81 h/t @neversaid
2017-03-31 00:00:42 -04:00
Benjamin Boudreau 563efd88f1 XLSX write sheetFormat option (fixes #437)
note: @sheetjsdev authored commit, original PR date/author used
2017-03-30 23:30:25 -04:00
SheetJS 4743085cb5 XLSB/XLSM sheet rels and hyperlinks
- XLSB/XLSM workbook/worksheet code names for VBA
- XLSX/XLSB write hyperlinks
- updated CFB to 0.11.1

Fixes:
- fixes #615 h/t @johnothetree (XLSM CodeName)
- fixes #93 h/t @SheetJSDev (Write Hyperlinks)
- fixes #156 h/t @MayaGi (XLSX Write Hyperlinks)
- fixes #344 h/t @slonoed (XLSX Write Hyperlinks)
2017-03-30 20:47:35 -04:00
SheetJS 65f1c7e58b HTML DOM Element read
- DOM <table> element parsing (fixes #576 h/t @axolo)
- removed InterfaceHdr check (fixes #209 h/t @Batistleman)
- gitbook docs
2017-03-29 15:14:15 -04:00
SheetJS b89a876076 version bump 0.9.7: write features
- write !cols widths : XLSX XLSB XLML
- write hyperlinks   :           XLML
- XLSB convert date cell to numeric on write
- fixed issue with assigning self in jszip

issues:
- closes #607 h/t @jscheid
- closes #195 h/t @asfman
2017-03-28 18:03:03 -04:00
SheetJS 085150db3b DBF from js-harb
- merged DBF from js-harb (fixes #407 h/t @joefreire)
- updated codepage to 1.8.0
- stub for macro/dialog sheet parsing (fixes #292 h/t @GenoD)
- XLSB/XLSM write vbaraw (fixes #606 h/t @johnothetree)
- phantomjs demo (fixes #184 h/t @machinewu)
2017-03-28 00:41:01 -04:00
SheetJS 663270b762 XLS/XLSX/XLSB Interpret Chartsheets as Data Tables
- chartsheets are now stored as sheets with "!type" set to "chart"
- fixed Strict XML Workbook Relationships
- stubbed support for dialog and macro sheets
- removed legacy XLS `!range` field
2017-03-27 17:41:14 -04:00
SheetJS 471275b761 version bump 0.9.6
- new ExtendScript demo
- Base64 shim improvements h/t @davidchambers @sheetjsdev
- jszip improvements to support extendscript
2017-03-25 18:18:50 -04:00
OliverZ 1038400859 International Properties
Excel localizes "Worksheets" and other names in XLS[XMB] Properties

Fixes #33

note: @oliverz contributed a file with "Arbeitsblätter"
      @sheetjsdev tested against test suite, PR #32 details used
2017-03-25 14:32:59 -04:00
SheetJS 70c48a74b9 API Improvements
- `aoa_to_sheet` function (fixes #314 h/t @fonzy2013 @rvdwijngaard)
- `writeFileAsync` function (fixes #396 h/t @barbalex)
- `sheet_to_json` tests + docs + blankrows (fixes #602 h/t @EEaglehouse)
- write number format scan now includes every index >= 50
- propagate SSF IE8 fixes (fixes #171 h/t @sheetjsdev)
- update shim for extendscript (see #603 h/t @firas3d)
- more flow type definitions
2017-03-24 21:36:40 -04:00
SheetJS ecb4515847 Use `charAt` for IE6-8 compat (fixes #9) 2017-03-24 01:07:28 -04:00
SheetJS 60e8905bcb systemjs and angular demos [ci skip]
closes #447 h/t @channara
closes #453 h/t @Adtiv @paustint
closes #538 h/t @hsbilgen
closes #547 h/t @Mani2693
2017-03-23 13:11:31 -04:00
Jim 9ae3a64af8 `sheet_to_json` default value
uses `defval` key in options object

fixes #583 h/t @jimjin
fixes #582 h/t @jimjin
fixes #147 h/t @jtadmor
2017-03-23 01:58:08 -04:00
SheetJS 69782ca211 version bump 0.9.5: IE8+ browser tests
- minor changes to work around IE incompatibilities
- updated shim and browser tests
2017-03-22 21:18:40 -04:00
LieJiang d83986d31c SSF undefined string guard (fixes #584)
note: @sheetjsdev authored commit, original PR date/author used
2017-03-22 11:23:13 -04:00
SheetJS a846f7184d utility improvements
- sheet_to_csv strip option (fixes #182 h/t @davidworkman9)
- sheet_to_json dateNF option (fixes #134 h/t @rotemtam)
- file type detection expanded to 4 byte magic number
2017-03-22 03:50:11 -04:00
SheetJS c7010eec35 XLS/XLSX/XLSB/XLML cellDates support
- uniform number->date cell conversion
- update SSF to 0.9.0 (for is_date)
- namespaced rich str xml
- license file changed to appease GH automatic license detector

|     id      | author       | comment                                 |
|:------------|:-------------|:----------------------------------------|
| closes #581 | @Aymkdn      | XLSX cellDates + SSF.is_date            |
| closes #126 | @elad        | same as #581 h/t @SystemParadox         |
| closes #59  | @vratiu      | same as #581                            |
| closes #279 | @varunoberoi | raw json output uses date               |
2017-03-21 16:44:35 -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
SheetJS 3cacfc406c version bump 0.9.4
- changed regexes to handle odd XML (fixes #191 h/t @chk- @imsaquib)
- XLML roundtrip 1252 encoding
- browser core tests added to main repo
2017-03-20 17:42:12 -04:00
SheetJS 245dd7fd82 Documentation improvements
- multiformat column widths (fixes #591 h/t @sheeeeep)
- skip nested BIFF files
2017-03-20 05:02:25 -04:00
František Žiačik ea7a951506 better dup check (fixes #316) 2017-03-19 19:48:49 -04:00
elad 912d586e8b Add notes about working with date cells
[ci skip]

fixes #127 h/t @elad
2017-03-19 19:05:51 -04:00
SheetJS 8ac3cf6ff7 enable semaphore ci for old node tests 2017-03-19 18:15:30 -04:00
Alex Litskevich 8938336e1c XLSX Defined Names
closes #162 h/t @alitskevich
2017-03-19 13:29:04 -04:00
Pieter Sheth-Voss f90fbd32e5 Parse XLSX Styles
some changes picked from #263
2017-03-19 02:50:30 -04:00
SheetJS 7888070603 explicitly share styles and themes 2017-03-18 19:25:50 -04:00
SheetJS 5a3774e36e Formula write support
- XLSX/XLML/ODS/CSV formula write
- XLS Array/Formula record parsing
- ODS to/from CSF formula conversion
- XLML parse negative dates
- formula multiformat and roundtrip tests
- update SSF

Closes issues:
- closes #549 h/t @omershelef
- closes #306 h/t @akaustel
- closes #300 h/t @wawanopoulos
- closes #152 h/t @florf
- closes #103 h/t @christocracy
- closes #112 h/t @johnyesberg
- closes #307 h/t @alexanderknapstein
2017-03-17 20:45:06 -04:00
Max Walker 4fd36de071 rounding carry 2017-03-16 20:33:29 -04:00
SheetJS ea1873e572 version bump 0.9.3: multiformat alignment
- merge cells and stubs consistency
- character entity decoding
- cellDates processing for other formats
2017-03-15 21:17:24 -04:00
SheetJS d3eaa62d45 unify stub cells with type `z`
- fixes #382 h/t @jugaltheshah @pimpelsang
- fixes #333 h/t @xushuheng0623 @abhishek1234321 @mateuszkrzeszowiec
- fixes #79 h/t @volodymyrl @elad
2017-03-15 04:19:02 -04:00
MURAKAMI Masahiko 05185e13f2 Fixed `vbaraw` parsing
- fixes #594 h/t @fossamagna
- fixes #348 h/t @aleramesh
2017-03-14 14:40:29 -04:00
DMan577 0537ed70aa Update index.d.ts 2017-03-14 20:02:19 +02:00
SheetJS 88eb98587c reduced build output on travis 2017-03-14 13:24:40 -04:00
SheetJS 7cb978b846 XLML write support
- XLML write (fixes #173 h/t @SheetJSDev)
- removed old iteration style from README (see #592)
- CellXF & StyleXF fields (fixes #414 h/t @ronnywang)
2017-03-14 04:19:51 -04:00
SheetJS 456ab63dc4 version bump 0.9.2: more bugfixes
- decode sheet name for XLSX and XLML (fixes #203 h/t @rocketmonkeys)
- XFExt (fixes #298 h/t @aetna-softwares @aimcom @baharudinafif)
- handle truly empty `<is>` elements (fixes #506 h/t @asksahil)
- pin version numbers for dependencies (fixes #469 h/t @nhtera)
- sed usage fix (see #572 h/t @liryna)
- fix hex2RGB substr indices (fixes #294 h/t @kamorahul)
- removed stale typescript files (see #442)
- reworked shift formula regex (fixed #551 h/t @SheetJSDev)
- README note on webpack codepage suppression (fixes #438 h/t @rusty1s)
- README note on WTF (fixes #487 h/t @livesoftware)
2017-03-13 02:46:37 -04:00
SheetJS 8cd9e81569 flow annotations
no errors when running flow!
2017-03-12 14:02:46 -04:00
SheetJS 695452bffb flow typing and cleanup 2017-03-12 03:34:36 -04:00
DMan577 aa86eef7fc Update index.d.ts 2017-03-12 09:21:11 +02:00
Yusuke Kawasaki 4684914723 18.4.6 rPh CT_PhoneticRun (ignored)
added namespace to regex (closes #476 h/t @kawanet)

note: @sheetjsdev authored commit, original PR date/author used
2017-03-11 13:08:52 -05:00
SheetJS 71c23d9e2a version bump 0.9.1: cpexcel update
- codepage upgraded to 1.7.0
- remove require dark pattern (closes #554 h/t @keyiis)
- test for JSON header disambiguation
- utility functions documentation (fixes #424 h/t @dskrvk)
2017-03-10 18:39:17 -05:00
Patrick Lam b0a72c8b0e disambiguate duplicate header names
closes #194 h/t @patricklam

note: @sheetjsdev authored commit, original PR date/author used
2017-03-10 14:15:39 -05:00
Takashi Fujita d4829476f7 fix parse_si for Japanese excel files
fixes #141 h/t @tgfjt .  Original message:

using #parse_si 'Phonetic Properties' items for Japanese excel files,
the Phonetic items(KATAKANA) represents pronunciation hints of String(KANJI).

```xml
<si>
 <t>漢字(japanese KANJI)</t>
 <rPh>
  <t>フリガナ(this is KATAKANA for pronounciation:漢字)</t>
 </rPh>
</si>
```

It expected get '漢字' . but got '漢字フリガナ'.
so replace these string, because this can be caused by only `<rPh>`.
2017-03-10 13:27:11 -05:00
SheetJS ba1d2ea2be README [ci skip] 2017-03-10 12:33:08 -05:00
SheetJS 4880e9219f more formula parsing logic
- added more function argc counts and cleaned up error rendering
- disabled XLS error on MTRSettings (fixes #466 h/t @dskrvk)
- handle more unexpected XML empty tags (fixes #510 h/t @rahulsindc)
- throw error if SheetNames is not unique (fixes #231 h/t @zippy1981)
2017-03-10 03:39:51 -05:00
SheetJS 54b528eaed version bump 0.9.0: merged ODS into XLSX
The optional ODS module has been completely merged into xlsx.js and the
corresponding scripts have been removed.  The new xlsx.js file provides
appropriate ODS exports, so fixing is a matter of removing ods.js refs.
2017-03-09 20:09:18 -05:00
SheetJS 7b6fb7b327 version bump 0.8.8: HTML
- read MSO HTML (fixes #419 h/t @vineetl fixes #458 h/t @tienne)
- roll out xml namespace fix (closes #362 h/t @PierreOCXP)
- cellDates clarifications
2017-03-09 00:24:32 -05:00
Giovanni Bruno d2b5506dec parse rich strings with bare boolean tags
h/t @giowe fixes #309

note: @sheetjsdev authored commit, original PR date/author used
2017-03-07 14:09:28 -05:00
Sebastian Metzger 1b44629a2c Added 'var' to example to be strict mode compliant
closes #206

[ci skip]
2017-03-06 01:46:30 -05:00
Francis Crick f113fb1bf1 fixing an issue where _xd_ is getting escaped 2017-03-05 18:39:56 -08:00
SheetJS 3d1f0f79ca version bump 0.8.7: bundlers
demos for browserify/requirejs/webpack
2017-03-04 20:14:08 -05:00
SheetJS 5ae6b1965b version bump 0.8.6: module flush
- fixes #571 h/t @FredrikL @mooyoul
- pin npm version in travis, see https://github.com/npm/npm/issues/15855
- updated CFB (fixes #569 h/t @e12009)
- remove BOM for some SpreadsheetML files

case insensitive zip file search fixes:
- fixes #439 h/t @chikh
- fixes #440 h/t @chikh
- fixes #567 h/t @duzun
2017-02-24 02:33:01 -08:00
SheetJS 7683e213ea README fix [ci skip] 2017-02-21 23:25:10 -08:00
SheetJS 7408679252 version bump 0.8.5: FODS/UOS and IE6+ support
- read and write support for Flat ODS files
- read support for Uniform Office Spreadsheet (UOS)
- IE6-8 cell regex split fix (fixes #350 #140 #268 h/t @Aymkdn @C0d3ine)
- replace substr negative index with slices (fixes #351 h/t @Aymkdn)
- ODS parsexmltag ignores ext overrides (fixes #548 h/t @lgodard)
- csv can be written using write/writeFile with csv type
- added `type` to README (fixes #432 h/t @tomkel)
2017-02-21 22:57:59 -08:00
SheetJS d7ecca0e8b version bump 0.8.4: formula parsing
- BIFF 2-12 formula parsing
- more content type coverage
- unified `.f` form: A1-style string
- `.F` field for array formulae
- formula output groups array formulae
- bin script -A --arrays output JS row objects
- whitespace robustness in inline string xml
- UTF-8 parsing in rich text runs (fixes #505 h/t @fuchsc)
- bold/italic/underline accept null val attr (h/t @qqilihq)
- sst trimming (fixes #176 h/t @shakhal @oising)
2017-02-19 12:36:32 -08:00
SheetJS ab2ecebac9 version bump 0.8.3: BIFF2 read/write
- basic support for parsing BIFF2-4
- basic support for writing BIFF2
- cleaned up some bad substr uses for IE6 compatibility
- added flow type annotations for xlsx.flow.js
- added numerous null guards (fixes #255 h/t @martinheidegger)
- README cleanup (fixes #539 h/t @oliversalzburg)
- pin jszip to local version (closes #408 h/t @limouri)

bower issues:

|  id  | author            | comment                                   |
|-----:|:------------------|:------------------------------------------|
| #254 | @kkirsche         | fixes #254 by removing version from json  |
| #165 | @vincentcialdella | fixes #165 by changing default script     |
| #180 | @owencraig        | fixes #180 by using xlsx.core.min.js      |

format issues:

|  id  | author            | comment                                   |
|-----:|:------------------|:------------------------------------------|
| #271 | @morstaine        | fixes #271 by reworking related parse fns |
| #504 | @JanSchuermannPH  | fixes #504 detect FullPaths h/t @Mithgol  |
| #508 | @basma-emad       | fixes #508 offending file used `x:` NS    |
2017-02-10 11:23:29 -08:00
rinzeb a234ec5915 Update xlsx typings
Add optional 'options' parameter to function sheet_to_csv. (53f7f6d944/bits/90_utils.js (L132))
2017-02-07 13:21:31 +01:00
SheetJS 06670ae181 removing node 0.11 from travis 2017-02-03 19:09:09 -05:00
SheetJS 86d6a093f0 version bump 0.8.2: ODS and cleanup
- README and example cleanup
- basic XLSB and ODS write support
- flow typecheck for ODS file
  Note: xlsx.js flow fails: https://github.com/facebook/flow/issues/380
- exposed jszip compression (fixes #220, closes #284)

README issues:

|  id  | author         | comment                                      |
|-----:|:---------------|:---------------------------------------------|
| #202 | @sao93859      | closes #202                                  |
| #211 | @alexanderchan | closes #211 corrected examples               |
| #327 | @cskaandorp    | changed saveAs example to match write tests  |
| #424 | @dskrvk        | added note about s2roa h/t @LeonardoPatignio |
| #496 | @jimmywarting  | closes #496 adapted rABS examples with rAAS  |

ODS file format issues:

|  id  | author         | comment                                      |
|-----:|:---------------|:---------------------------------------------|
| #148 | @user4815162342| closes #148 h/t @ziacik                      |
| #166 | @paulproteus   | closes #166 rudimentary ODS write support    |
| #177 | @ziacik        | closes #177                                  |
| #179 | @ziacik        | closes #179 use JSON when available          |
| #317 | @ziacik        | closes #317                                  |
| #328 | @think01       | closes #328                                  |
| #383 | @mdamt         | closes #383 duplicate cells should be copied |
| #430 | @RB-Lab        | closes #430                                  |
| #546 | @lgodard       | closes #546 thanks to other changes          |
2017-02-03 15:50:45 -05:00
Andy 276b1ae79f Use "lib" in tsconfigs instead of "target". (#13968)
* Use "lib" in tsconfigs instead of "target".

Only add "dom" to libraries that need it. This is determined by a script, so many libraries that have "dom" maybe should not.

* Update new-package and readme

* Add back "target" where necessary
2017-01-18 07:51:51 -08:00
SheetJS 2a756fffcc version bump 0.8.1: fixes to support node 4+
- codepage updated to 1.6.0 (latest)
- clean up Makefile
- adapted .travis.yml to support 0.8
- removed test files that drifted from baseline
- removed XLSB pseudo-inverse tests due to fails in node 4+
2016-12-31 03:20:45 -05:00
Andy 01a3806eb5 Add "noImplicitThis" to all tsconfig.json (#13446)
* Add "noImplicitThis" to all tsconfig.json

* Use `"noImplicitThis": false` on packages with broken tests.
2016-12-19 14:11:46 -08:00
Nathan Shively-Sanders 573a08aaaf Merge remote-tracking branch 'origin/master' into types-merge-20161122 2016-11-22 15:08:50 -08:00
groetzi 7c89b6e9b1 Update xlsx.d.ts
added signatures for decode_[cell|range]
2016-11-14 17:50:08 -06:00
Nathan Shively-Sanders d8ea26cbac Merge branch 'master' into types-2.0-2016-08-12 2016-08-12 14:53:54 -07:00
Hagai Cohen 4de60e9ca9 Aligned xlsx types to master xlsx/xlsx.d.ts 2016-08-11 23:18:32 +03:00
Hagai Cohen 09c3f9db84 Fixed XLSX typings 2016-08-11 22:51:52 +03:00
Kārlis Gaņģis 5e2768ac84 Added `opts` parameter to sheet_to_json method. 2016-08-11 14:10:56 +03:00
Ryan Cavanaugh d8a13d0dc2 Fix tsconfig files for new option name / behavior.
Also fixes some inconsistent whitespace.
2016-07-12 13:54:56 -07:00
Raghav Katyal bc12a8d2b3 Turning on consistent casing flag and fixing failures 2016-06-30 15:14:49 -07:00
Ryan Cavanaugh 22c1dca6e0 Add noEmit to all config files 2016-05-10 12:24:49 -07:00
Ryan Cavanaugh 4039f599e7 Change relative reference paths to types references. Errors incoming... 2016-05-09 18:06:27 -07:00
Ryan Cavanaugh 5ceec62f2a Rename all entry points to index.d.ts and explicitify all file lists 2016-05-09 17:29:10 -07:00
Ryan Cavanaugh 20a8552199 Add typesRoot to all config files 2016-05-09 13:52:25 -07:00
Ryan Cavanaugh c265359abd Turn off strict null checks 2016-05-04 15:08:38 -07:00
Ryan Cavanaugh 7e32abdb26 Add tsconfig.json files 2016-05-04 14:14:39 -07:00
Ryan Cavanaugh 82537cbca4 Remove obsolesced reference comments 2016-04-27 21:53:46 -07:00
Ryan Cavanaugh c73e83fab5 Rename external modules to index.d.ts 2016-04-27 21:30:22 -07:00
Ryan Cavanaugh 2b42c39913 Merge remote-tracking branch 'upstream/master' into types2.0
Add tsconfig files everywhere

# Conflicts:
#	azure-mobile-services-client/AzureMobileServicesClient.d.ts
#	bookshelf/bookshelf.d.ts
#	hapi/hapi.d.ts
#	helmet/helmet.d.ts
#	mongodb/mongodb.d.ts
#	nock/nock.d.ts
#	react-bootstrap/react-bootstrap.d.ts
#	react-helmet/react-helmet.d.ts
#	restify/restify.d.ts
#	sequelize/sequelize.d.ts
2016-04-27 20:40:21 -07:00
Ryan Cavanaugh 14d28e6a6a Fix angularjs/angular; 'export declare'/'declare export' 2016-04-25 13:02:25 -07:00
Ryan Cavanaugh 96df2958ab Unwrap all lone ambient external modules 2016-04-22 14:12:45 -07:00
vvakame a102a3adb1 replace https://github.com/borisyankov/DefinitelyTyped to https://github.com/DefinitelyTyped/DefinitelyTyped 2016-03-17 00:55:26 +09:00
Josh Petersen a345c332ac minor fix. sheet_to_json only accepts worksheet as a parameter. 2015-06-03 14:25:05 -04:00
Josh Petersen 3a496db468 added definitions and tests for project xlsx https://github.com/SheetJS/js-xlsx 2015-06-03 09:34:42 -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
508 changed files with 2616797 additions and 48067 deletions

1
.eslintignore Normal file
View File

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

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

26
.eslintrc Normal file
View File

@ -0,0 +1,26 @@
{
"env": { "shared-node-browser":true },
"globals": {},
"parserOptions": {
"ecmaVersion": 3
},
"plugins": [ "html", "json" ],
"extends": "eslint:recommended",
"rules": {
"comma-style": [ 2, "last" ],
"comma-dangle": [ 2, "never" ],
"curly": 0,
"no-bitwise": 0,
"no-cond-assign": 1,
"no-console": 0,
"no-control-regex": 0,
"no-unused-vars": 1,
"no-empty": 0,
"no-trailing-spaces": 2,
"no-use-before-define": [ 1, {
"functions":false, "classes":true, "variables":false
}],
"no-useless-escape": 0,
"semi": [ 2, "always" ]
}
}

40
.flowconfig Normal file
View File

@ -0,0 +1,40 @@
[ignore]
.*/node_modules/.*
.*/dist/.*
.*/tmp/.*
.*/bits/.*
.*/ctest/.*
.*/misc/.*
.*/perf/.*
.*/_book/.*
.*/packages/.*
.*/demo/browser.js
.*/shim.js
.*/xlsx.js
.*/xlsx.mini.js
.*/xlsx.mini.flow.js
.*/xlsxworker.js
.*/tests/.*
.*/demos/.*
#.*/xlsx.flow.js
[include]
xlsxworker.flow.js
xlsx.flow.js
.*/bin/.*.njs
.*/demo/browser.flow.js
test.js
[libs]
bits/09_types.js
misc/flow.js
misc/flowdeps.js
[options]
module.file_ext=.js
module.file_ext=.njs
module.ignore_non_literal_requires=true
suppress_comment= \\(.\\|\n\\)*\\$FlowIgnore

17
.gitattributes vendored Normal file
View File

@ -0,0 +1,17 @@
*.html linguist-documentation
*.md text eol=lf
bits/*.js text eol=lf
test.js text eol=lf
xlsx*.js text eol=lf
*.flow.js text eol=lf
docbits/* linguist-documentation
dist/* linguist-generated=true binary
*.mjs linguist-generated=true binary
xlsx.js linguist-generated=true binary
xlsxworker.js linguist-generated=true binary
tests/core.js linguist-generated=true binary
tests/fixtures.js linguist-generated=true binary
test.mjs lingust-generated=false binary=false text eol=lf

3
.github/FUNDING.yml vendored Normal file
View File

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

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'

39
.github/workflows/deno.yml vendored Normal file
View File

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

92
.github/workflows/node-4+.yml vendored Normal file
View File

@ -0,0 +1,92 @@
name: 'Tests: node.js'
on: [pull_request, push]
jobs:
matrix:
runs-on: ubuntu-latest
outputs:
latest: ${{ steps.set-matrix.outputs.requireds }}
steps:
- uses: ljharb/actions/node/matrix@main
id: set-matrix
with:
versionsAsRoot: true
type: 'majors'
preset: '>=4'
latest:
needs: [matrix]
name: 'latest majors'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
include:
- node-version: '14.'
env:
TZ: America/New_York
- node-version: '13.'
env:
TZ: Europe/London
- node-version: '12.'
env:
TZ: Asia/Seoul
- node-version: '11.'
env:
TZ: America/Los_Angeles
FMTS: misc
- node-version: '10.'
env:
TZ: Europe/Berlin
FMTS: misc
- node-version: '9.'
env:
TZ: Asia/Kolkata
FMTS: misc
- node-version: '8.'
env:
TZ: Asia/Shanghai
FMTS: misc
- node-version: '7.'
env:
TZ: America/Cancun
FMTS: misc
- node-version: '6.'
env:
TZ: Asia/Seoul
FMTS: misc
- node-version: '5.'
env:
TZ: America/Anchorage
FMTS: misc
- node-version: '4.'
env:
TZ: America/Barbados
FMTS: misc
- node-version: '4.4.7' # see GH issue #1150
env:
TZ: Asia/Tokyo
FMTS: misc
steps:
- uses: actions/checkout@v2
- uses: ljharb/actions/node/install@main
name: 'nvm install ${{ matrix.node-version }} && npm install'
with:
node-version: ${{ matrix.node-version }}
- run: sudo curl -Lo /usr/bin/rooster https://github.com/SheetJS/rooster/releases/download/v0.2.0/rooster-v0.2.0-linux-amd64
- run: sudo chmod a+x /usr/bin/rooster
- run: make init
- run: 'cd test_files; make all; cd -'
- run: npm run tests-only
- run: 'cd packages/ssf; npm install; npm run tests-only; cd -'
node:
name: 'node 4+'
needs: [latest]
runs-on: ubuntu-latest
steps:
- run: 'echo tests completed'

45
.github/workflows/node-iojs.yml vendored Normal file
View File

@ -0,0 +1,45 @@
name: 'Tests: node.js (io.js)'
on: [pull_request, push]
jobs:
matrix:
runs-on: ubuntu-latest
outputs:
latest: ${{ steps.set-matrix.outputs.requireds }}
steps:
- uses: ljharb/actions/node/matrix@main
id: set-matrix
with:
type: 'majors'
preset: 'iojs'
latest:
needs: [matrix]
name: 'latest majors'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.matrix.outputs.latest) }}
steps:
- uses: actions/checkout@v2
- uses: ljharb/actions/node/install@main
name: 'nvm install ${{ matrix.node-version }} && npm install'
with:
node-version: ${{ matrix.node-version }}
skip-ls-check: true
- run: sudo curl -Lo /usr/bin/rooster https://github.com/SheetJS/rooster/releases/download/v0.2.0/rooster-v0.2.0-linux-amd64
- run: sudo chmod a+x /usr/bin/rooster
- run: make init
- run: 'cd test_files; make all; cd -'
- run: npm run tests-only
#- run: 'cd packages/ssf; npm run tests-only; cd -'
node:
name: 'io.js'
needs: [latest]
runs-on: ubuntu-latest
steps:
- run: 'echo tests completed'

32
.github/workflows/node-pretest.yml vendored Normal file
View File

@ -0,0 +1,32 @@
name: 'Tests: pretest/posttest'
on: [pull_request, push]
jobs:
pretest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ljharb/actions/node/install@main
name: 'nvm install lts/* && npm install'
with:
node-version: 'lts/*'
- run: sudo curl -Lo /usr/bin/rooster https://github.com/SheetJS/rooster/releases/download/v0.2.0/rooster-v0.2.0-linux-amd64
- run: sudo chmod a+x /usr/bin/rooster
- run: make init
- run: 'cd test_files; make all; cd -'
- run: npm run pretest
# posttest:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v2
# - uses: ljharb/actions/node/install@main
# name: 'nvm install lts/* && npm install'
# with:
# node-version: 'lts/*'
# - run: make init
# - run: 'cd test_files; make all; cd -'
# - run: npm run posttest

88
.github/workflows/node-zero.yml vendored Normal file
View File

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

15
.github/workflows/rebase.yml vendored Normal file
View File

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

View File

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

44
.gitignore vendored
View File

@ -1,21 +1,41 @@
node_modules
package-lock.json
*.tgz
_book/
misc/coverage.html
misc/prof.js
misc/*.[sS][vV][gG]
v8.log
tmp
*.txt
*.csv
*.dif
*.prn
*.slk
*.[tT][xX][tT]
*.[cC][sS][vV]
*.[dD][iIbB][fF]
*.[pP][rR][nN]
*.[pP][mM][dD]*
*.[pP][dD][fF]
*.[sS][lL][kK]
*.[sS][yY][lL][kK]
*.socialcalc
*.xls
*.xlsb
*.xlsm
*.xlsx
*.xlsm
*.xlsb
*.xml
*.[xX][lL][sSwWcCaAtTmMrR]
*.[xX][lL][sSaAtT][xXmMbB]
*.[oO][dD][sS]
*.[fF][oO][dD][sS]
*.[xX][mM][lL]
*.[xX][lL][mM][lL]
*.[uU][oO][sS]
*.[wW][kKqQbB][sS1234567890]
*.[qQ][pP][wW]
*.[fF][mM][3tT]
*.[bB][iI][fF][fF][23458]
*.[rR][tT][fF]
*.[eE][tT]
*.[eE][tT][hH]
*.[nN][uU][mM][bB][eE][rR][sS]
*.[mM][oO][dD]
*.[dD][tT][aA]
*.123
*.htm
*.html
*.sheetjs
*.exe
*.img

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

@ -1,35 +1,76 @@
test_files/
modules/
packages/
.github/
tests/files/
demos/
index.html
misc/
node_modules
*.tgz
*.jsx
_book
book.json
v8.log
tmp
*.txt
*.csv
*.dif
*.prn
*.slk
*.[tT][xX][tT]
*.[cC][sS][vV]
*.[dD][iIbB][fF]
*.[pP][rR][nN]
*.[pP][mM][dD]*
*.[pP][dD][fF]
*.[sS][lL][kK]
*.[sS][yY][lL][kK]
*.socialcalc
*.xls
*.xlsb
*.xlsm
*.xlsx
*.xml
*.[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
*.sheetjs
*.exe
*.img
.gitignore
.gitattributes
.fossaignore
.spelling
.eslintignore
.eslintrc
.eslintmjs
.jshintrc
xlsx.mini.js
CONTRIBUTING.md
Makefile
make.cmd
*.lst
.npmignore
xlsworker.js
shim.js
test.js
test.mjs
test.ts
test.mts
testnocp.ts
testbun.mjs
.jscs.json
.gitmodules
.travis.yml
.flowconfig
*.flow.js
bits/
odsbits/
docbits/
tests/

189
.spelling Normal file
View File

@ -0,0 +1,189 @@
# xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com
SheetJS
sheetjs
js-xlsx
xls
xlsb
xlsx
# Excel-related terms
A1-style
AutoFilter
ECMA-376
FoxPro
Multiplan
OData
OpenDocument
OpenFormula
PivotTable
PivotTables
Quattro
SpreadsheetML
Unhide
VBA
Visicalc
chartsheet
chartsheets
dialogsheet
dialogsheets
dBASE
macrosheet
macrosheets
tooltip
tooltips
# Third-party
Browserify
CDNjs
CommonJS
Deno
Ethercalc
ExtendScript
InDesign
IndexedDB
JavaScriptCore
LocalStorage
NestJS
NPM
Nuxt
PhantomJS
Photoshop
Redis
RequireJS
Rollup
SessionStorage
SQLite
SystemJS
Vite
VueJS
WebKit
WebSQL
WK_
iOS
iWork
nodejs
node.js
npm
unpkg
webpack
weex
# Other terms
1.x
2.x
3.x
4.x
5.x
6.x
7.x
8.x
9.x
ActiveX
APIs
ArrayBuffer
Base64
Booleans
FileReader
JS
NoSQL
README
UTF-8
UTF-16
VBScript
XHR
XMLHttpRequest
bundler
bundlers
cleanroom
codepage
config
customizable
datagrid
dataset
deduplication
destructuring
embeddable
encodings
filesystem
globals
javascript
lifecycle
metadata
natively
pre-built
pre-generated
prepend
prepended
programmatically
repo
runtime
serverless
submodule
transpiled
utils
commonjs
async
uncheck
vendoring
- demos/altjs/README.md
ChakraCore
Duktape
Goja
Nashorn
QuickJS
- demos/angular/README.md
AngularJS
- demos/angular2/README.md
NativeScript
angular-cli
- demos/array/README.md
WebGL
WebAssembly
dataset
TensorFlow
- demos/database/README.md
Knex
LowDB
MariaDB
MongoDB
MySQL
PostgreSQL
schemaless
schemas
storages
- demos/extendscript/README.md
Photoshop
InDesign
minifier
- demos/function/README.md
microservice
- demos/headless/README.md
PhantomJS
SlimerJS
wkhtmltopdf
- demos/nwjs/README.md
NW.js
- demos/react/README.md
Next.js
Preact
- demos/server/README.md
hapi
- demos/showcase/README.md
vscode-data-preview
- demos/xhr/README.md
axios
superagent

View File

@ -1,16 +1,58 @@
language: node_js
dist: xenial
node_js:
- "iojs"
- "0.11.14"
- "0.10"
# - "0.8" # commented because of npm issue with camelcase
- "14"
- "13"
- "12"
- "11"
- "10"
- "9"
- "8"
matrix:
include:
- node_js: "14"
env: TZ="America/New_York"
- node_js: "13"
env: TZ="Europe/London"
- node_js: "12"
env: TZ="Asia/Seoul"
- node_js: "11"
env: TZ="America/Los_Angeles" FMTS=misc
- node_js: "10"
env: TZ="Europe/Berlin" FMTS=misc
- node_js: "9"
env: TZ="Asia/Kolkata" FMTS=misc
- node_js: "8"
env: TZ="Asia/Shanghai" FMTS=misc
- node_js: "7"
env: TZ="America/Cancun" FMTS=misc
- node_js: "6"
env: TZ="Asia/Seoul" FMTS=misc
- node_js: "5"
env: TZ="America/Anchorage" FMTS=misc
- node_js: "4"
env: TZ="America/Barbados" FMTS=misc
# see GH issue #1150
- node_js: "4.4.7"
env: TZ="Asia/Tokyo" FMTS=misc
- node_js: "0.12"
env: TZ="America/Cayman" FMTS=misc
- node_js: "0.10"
env: TZ="Pacific/Honolulu" FMTS=misc
- node_js: "0.8"
env: TZ="America/Mexico_City" FMTS=misc
before_install:
- "npm install -g mocha"
- "npm config set strict-ssl false"
- "./misc/node_version.sh"
- "npm install -g mocha@2.x voc"
- "npm install blanket"
- "npm install xlsjs"
- "npm install word"
- "npm install coveralls mocha-lcov-reporter"
# note: jsdom 11.x expects node >= 6 but is missing engines.node
- "npm install jsdom@11.x"
before_script:
- "make init"
- "cd test_files; make all; cd -"
- "cd test_files; make all; cd -"
after_success:
- "make coveralls-spin"
# - "make coveralls-spin"

353
CHANGELOG.md Normal file
View File

@ -0,0 +1,353 @@
# CHANGELOG
This log is intended to keep track of backwards-incompatible changes, including
but not limited to API changes and file location changes. Minor behavioral
changes may not be included if they are not expected to break existing code.
## v0.20.2
* Reworked parsing methods to avoid slow regexes (CVE-2024-22363)
* HTML properly encode data-v attribute
* SYLK read and write error cells
## v0.20.1
* `init` use packaged test files to work around GitHub breaking changes
* SSF date code rounding to 15 decimal digits (h/t @davidtamaki)
* `sheet_to_json` force UTC interpretation for formatted strings (h/t @Blanay)
* QPW extract result of string formula
* XLSX parse non-compliant merge cell expressions
* NUMBERS correctly handle rows omitted from official exports
* DBF parse empty logical field (h/t @Roman91)
* `dense` option added to types
* package.json add mini and core scripts to export map (h/t @stof)
## v0.20.0
* Use UTC interpretation of Date objects for date cells (potentially breaking)
* API functions support UTC and local time value interpretations
* Export `NaN` values to `#NUM!` and infinite values to `#DIV/0!`
## v0.19.3
* XLSX Ensure comment address is valid (h/t @slonser)
* Enforce Excel worksheet name restrictions
* Fixed "Prototype Pollution" vulnerability (CVE-2023-30533)
## v0.19.2
* XLSX proper decoding of hyperlinks (h/t @tw-yaxu)
* XLSX ignore unexpected attributes in rich text (h/t @colin4)
* `sheet_to_json` type fix (h/t @chsdwn)
## v0.19.1
* Fixed types issue in strict mode (h/t @younes-io)
* Numbers 12.2 parsing skip ActivityStream.iwa
## v0.19.0
* XLSX export hyperlinks compatible with google sheets (h/t Evan Bovie)
* NUMBERS export multiple sheets, full worksheet range
* formalized `dense` mode
## v0.18.12
* `package.json` added types in `exports` structure
* uncapped NUMBERS single-sheet single-table export
* DBF export records using supported codepages
## v0.18.11
* Base64 input ignore data URI wrapper
* Parse ZIP files that use ZIP64 extended information field
* More precise handling of time-only values
* Threaded Comment fallback text for older Excel
## v0.18.10
* `exports` field in package.json to satiate ViteJS and newer tooling
* JSC (Safari / Bun) perf, see <https://bugs.webkit.org/show_bug.cgi?id=243148>
* workbook `bookType` property to denote the origin format when parsed from file
* XLSX force export of stub cells with number formats when `sheetStubs` is set
## v0.18.9
* XLSX / ODS write defined names
* sync defined names to AutoFilter setting on export
* 1904 date system setting properly roundtripped
* ODS read/write number formats
## v0.18.8
* Plaintext parsing of dateless meridien time values (`1:23:45 PM`)
* Legacy format (SYLK / WK# / Multiplan) minutiae
## v0.18.7
* Normalized handling of `\r` and `\n` newline characters
## v0.18.6
* Removed all npm dependencies
* Auto-correct bad Google Sheets format `d.m`
* NUMBERS write merge cells, cells up to column "ALL"
## v0.18.5
* Enabled `sideEffects: false` in package.json
* Basic NUMBERS write support
## v0.18.4
* CSV output omits trailing record separator
* Properly terminate NodeJS Streams
* DBF preserve column types on import and use when applicable on export
## v0.18.3
* Removed references to `require` and `process` in browser builds
## v0.18.2
* Hotfix for unicode processing of XLSX exports
## v0.18.1
* Removed Node ESM build script and folded into standard ESM build
* Removed undocumented aliases including `make_formulae` and `get_formulae`
## v0.18.0
* Browser scripts only expose `XLSX` variable
* Module no longer ships with `dist/jszip.js` browser script
## v0.17.4
* CLI script moved to `xlsx-cli` package
## v0.17.3
* `window.XLSX` explicit assignment to satiate LWC
* CSV Proper formatting of errors
* HTML emit data-\* attributes
## v0.17.2
* Browser and Node optional ESM support
* DSV correct handling of bare quotes (h/t @bgamrat)
## v0.17.1
* `XLSB` writer uses short cell form when viable
## 0.17.0:
* mini build includes ODS parse/write support
* DBF explicitly cap worksheet to 1<<20 rows
* XLS throw errors on truncated records
## v0.16.2
* Disabled `PRN` parsing by default (better support for CSV without delimeters)
## v0.16.1
* skip empty custom property tags if data is absent (fixes DocSecurity issue)
* HTML output add raw value, type, number format
* DOM parse look for `v` / `t` / `z` attributes when determining value
* double quotes in properties escaped using `_x0022_`
* changed AMD structure for NetSuite and other RequireJS implementations
- `encode_cell` and `decode_cell` do not rely on `encode_col` / `decode_col`
## v0.16.0
* Date handling changed
* XLML certain tag tests are now case insensitive
* Fixed potentially vulnerable regular expressions
## v0.15.6
* CFB prevent infinite loop
* ODS empty cells marked as stub (type "z")
* `cellStyles` option implies `sheetStubs`
## v0.15.5
* `sheets` parse option to specify which sheets to parse
## v0.15.4
* AOA utilities properly preserve number formats
* Number formats captured in stub cells
## v0.15.3
* Properties and Custom Properties properly XML-encoded
## v0.15.2
- `sheet_get_cell` utility function
- `sheet_to_json` explicitly support `null` as alias for default behavior
- `encode_col` throw on negative column index
- HTML properly handle whitespace around tags in a run
- HTML use `id` option on write
- Files starting with `0x09` followed by a display character are now TSV files
- XLS parse references col/row indices mod by the correct number for BIFF ver
- XLSX comments moved to avoid overlapping cell
- XLSB outline level
- AutoFilter update `_FilterDatabase` defined name on write
- XLML skip CDATA blocks
## v0.15.1 (2019-08-14)
* XLSX ignore XML artifacts
* HTML capture and persist merges
## v0.15.0
* `dist/xlsx.mini.min.js` mini build with XLSX read/write and some utilities
* Removed legacy conversion utility functions
## v0.14.5
* XLS PtgNameX lookup
* XLS always create stub cells for blank cells with comments
## v0.14.4
* Better treatment of `skipHidden` in CSV output
* Ignore CLSID in XLS
* SYLK 7-bit character encoding
* SYLK and DBF codepage support
## v0.14.3
* Proper shifting of addresses in Shared Formulae
## v0.14.2
* Proper XML encoding of comments
## v0.14.1
* raw cell objects can be passed to `sheet_add_aoa`
* `_FilterDatabase` fix for AutoFilter-related crashes
* `stream.to_json` doesn't end up accidentally scanning to max row
## 0.14.0 (2018-09-06)
* `sheet_to_json` default flipped to `raw: true`
## 0.13.5 (2018-08-25)
* HTML output generates `<br/>` instead of encoded newline character
## 0.13.2 (2018-07-08)
* Buffer.from shim replaced, will not be defined in node `<=0.12`
## 0.13.0 (2018-06-01)
* Library reshaped to support AMD out of the box
## 0.12.11 (2018-04-27)
* XLS/XLSX/XLSB range truncation (errors in `WTF` mode)
## 0.12.4 (2018-03-04)
* `JSZip` renamed to `JSZipSync`
## 0.12.0 (2018-02-08)
* Extendscript target script in NPM package
## 0.11.19 (2018-02-03)
* Error on empty workbook
## 0.11.16 (2017-12-30)
* XLS ANSI/CP separation
* 'array' write type and ArrayBuffer processing
## 0.11.6 (2017-10-16)
* Semicolon-delimited files are detected
## 0.11.5 (2017-09-30)
* Bower main script shifted to full version
* 'binary' / 'string' encoding
## 0.11.3 (2017-08-19)
* XLS cell ixfe/XF removed
## 0.11.0 (2017-07-31)
* Strip `require` statements from minified version
* minifier mangler enabled
## 0.10.9 (2017-07-28)
* XLML/HTML resolution logic looks further into the data stream to decide type
* Errors thrown on suspected RTF files
## 0.10.5 (2017-06-09)
* HTML Table output header/footer should not include `<table>` tag
## 0.10.2 (2017-05-16)
* Dates are converted to numbers by default (set `cellDates:true` to emit Dates)
* Module does not export CFB
## 0.9.10 (2017-04-08)
* `--perf` renamed to `--read-only`
## 0.9.9 (2017-04-03)
* default output format changed to XLSB
* comment text line endings are now normalized
* errors thrown on write when worksheets have invalid names
## 0.9.7 (2017-03-28)
* XLS legacy `!range` field removed
* Hyperlink tooltip is stored in the `Tooltip` field
## 0.9.6 (2017-03-25)
* `sheet_to_json` now passes `null` values when `raw` is set to `true`
* `sheet_to_json` treats `null` stub cells as values in conjunction with `raw`
## 0.9.5 (2017-03-22)
* `cellDates` affects parsing in non-XLSX formats
## 0.9.3 (2017-03-15)
* XLML property names are more closely mapped to the XLSX equivalent
* Stub cells are now cell type `z`
## 0.9.2 (2017-03-13)
* Removed stale TypeScript definition files. Flowtype comments are used in the
`xlsx.flow.js` source and stripped to produce `xlsx.js`.
* sed usage reworked to support GNU sed in-place form. BSD sed seems to work,
but the build script has not been tested on other sed variants:
```bash
$ sed -i.ext [...] # GNU
$ sed -i .ext [...] # bsd
```
## 0.9.0 (2017-03-09)
* Removed ods.js source. The xlsx.js source absorbed the ODS logic and exposes
the ODS variable, so projects should remove references to ods.js

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
@ -28,6 +28,12 @@ shared or included in a test suite (although I will ask :)
If sending email to a gmail account is problematic, the <dev@sheetjs.com> email
inbox is self-hosted.
# Opening Pull Requests
[Squash commits](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History)
before opening a pull request, If the pull request addresses documentation or
demos, add `[ci skip]` in the body or title of the commit message to skip tests.
# Pre-Contribution Checklist
Before thinking about contributing, make sure that:
@ -50,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
@ -60,4 +66,4 @@ Keep these in mind as you work:
Before contributions are merged, you will receive an email (at the address
associated with the git commit) and will be asked to confirm the aforementioned
items. Ensure that the email addresses associated with the commits is valid.
items. Ensure that the email addresses associated with the commits are valid.

194
LICENSE
View File

@ -1,4 +1,192 @@
Copyright (C) 2012-2015 SheetJS
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright (C) 2012-present SheetJS LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -11,7 +199,3 @@ Copyright (C) 2012-2015 SheetJS
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Except where noted, this license applies to any and all software programs and associated documentation files created by the Original Author and distributed with the Software:
'jszip.js' is a modified version of JSZip, Copyright (c) Stuart Knightley, David Duponchel, Franz Buchinger, Ant'onio Afonso. JSZip is dual licensed and is used according to the terms of the MIT License.

287
Makefile
View File

@ -1,116 +1,269 @@
SHELL=/bin/bash
LIB=xlsx
FMT=xlsx xlsm xlsb ods xls xml misc full
REQS=jszip.js
REQS=
ADDONS=dist/cpexcel.js
AUXTARGETS=ods.js
AUXTARGETS=
CMDS=bin/xlsx.njs
HTMLLINT=index.html
MINITGT=xlsx.mini.js
MINIFLOW=xlsx.mini.flow.js
MINIDEPS=$(shell cat misc/mini.lst)
ESMJSTGT=xlsx.mjs
ESMJSDEPS=$(shell cat misc/mjs.lst)
ULIB=$(shell echo $(LIB) | tr a-z A-Z)
DEPS=$(sort $(wildcard bits/*.js))
TSBITS=$(patsubst modules/%,bits/%,$(wildcard modules/[0-9][0-9]_*.js))
MTSBITS=$(patsubst modules/%,misc/%,$(wildcard modules/[0-9][0-9]_*.js))
TARGET=$(LIB).js
FLOWTARGET=$(LIB).flow.js
FLOWAUX=$(patsubst %.js,%.flow.js,$(AUXTARGETS))
AUXSCPTS=xlsxworker.js
FLOWTGTS=$(TARGET) $(AUXTARGETS) $(AUXSCPTS) $(MINITGT)
UGLIFYOPTS=--support-ie8 -m
CLOSURE=/usr/local/lib/node_modules/google-closure-compiler/compiler.jar
## Main Targets
.PHONY: all
all: $(TARGET) $(AUXTARGETS)
all: $(TARGET) $(AUXTARGETS) $(AUXSCPTS) $(MINITGT) $(ESMJSTGT) ## Build library and auxiliary scripts
$(TARGET): $(DEPS)
$(FLOWTGTS): %.js : %.flow.js
node -e 'process.stdout.write(require("fs").readFileSync("$<","utf8").replace(/^[ \t]*\/\*[:#][^*]*\*\/\s*(\n)?/gm,"").replace(/\/\*[:#][^*]*\*\//gm,""))' > $@
$(FLOWTARGET): $(DEPS)
cat $^ | tr -d '\15\32' > $@
$(MINIFLOW): $(MINIDEPS)
cat $^ | tr -d '\15\32' > $@
$(ESMJSTGT): $(ESMJSDEPS)
cat $^ | tr -d '\15\32' > $@
bits/01_version.js: package.json
echo "$(ULIB).version = '"`grep version package.json | awk '{gsub(/[^0-9a-z\.-]/,"",$$2); print $$2}'`"';" > $@
bits/18_cfb.js: node_modules/cfb/dist/xlscfb.js
#bits/18_cfb.js: node_modules/cfb/xlscfb.flow.js
# cp $^ $@
$(TSBITS): bits/%: modules/%
cp $^ $@
$(MTSBITS): misc/%: modules/%
cp $^ $@
.PHONY: clean
clean:
rm -f $(TARGET)
clean: ## Remove targets and build artifacts
rm -f $(TARGET) $(FLOWTARGET) $(ESMJSTGT) $(MINITGT) $(MINIFLOW)
.PHONY: clean-data
clean-data:
rm -f *.xlsx *.xlsm *.xlsb *.xls *.xml
.PHONY: init
init:
git submodule init
git submodule update
git submodule foreach git pull origin master
git submodule foreach make
init: ## Initial setup for development
rm -rf test_files
if [ ! -e test_files.zip ]; then curl -LO https://test-files.sheetjs.com/test_files.zip; fi
unzip test_files.zip
mkdir -p tmp
DISTHDR=misc/suppress_export.js
.PHONY: dist
dist: dist-deps $(TARGET) bower.json ## Prepare JS files for distribution
mkdir -p dist
cp LICENSE dist/
uglifyjs shim.js $(UGLIFYOPTS) -o dist/shim.min.js --preamble "$$(head -n 1 bits/00_header.js)"
@#
<$(TARGET) sed "s/require('.*')/undefined/g;s/ process / undefined /g;s/process.versions/({})/g" > dist/$(TARGET)
<$(MINITGT) sed "s/require('.*')/undefined/g;s/ process / undefined /g;s/process.versions/({})/g" > dist/$(MINITGT)
@# core
uglifyjs $(REQS) dist/$(TARGET) $(UGLIFYOPTS) -o dist/$(LIB).core.min.js --source-map dist/$(LIB).core.min.map --preamble "$$(head -n 1 bits/00_header.js)"
misc/strip_sourcemap.sh dist/$(LIB).core.min.js
@# full
#cat <(head -n 1 bits/00_header.js) $(DISTHDR) $(REQS) $(ADDONS) dist/$(TARGET) $(AUXTARGETS) > dist/$(LIB).full.js
uglifyjs $(DISTHDR) $(REQS) $(ADDONS) dist/$(TARGET) $(AUXTARGETS) $(UGLIFYOPTS) -o dist/$(LIB).full.min.js --source-map dist/$(LIB).full.min.map --preamble "$$(head -n 1 bits/00_header.js)"
misc/strip_sourcemap.sh dist/$(LIB).full.min.js
@# mini
uglifyjs dist/$(MINITGT) $(UGLIFYOPTS) -o dist/$(LIB).mini.min.js --source-map dist/$(LIB).mini.min.map --preamble "$$(head -n 1 bits/00_header.js)"
misc/strip_sourcemap.sh dist/$(LIB).mini.min.js
@# extendscript
cat <(printf '\xEF\xBB\xBF') <(head -n 1 bits/00_header.js) shim.js $(DISTHDR) $(REQS) dist/$(TARGET) > dist/$(LIB).extendscript.js
@# zahl
cp modules/xlsx.zahl.js modules/xlsx.zahl.mjs dist/
@#
rm dist/$(TARGET) dist/$(MINITGT)
.PHONY: dist-deps
dist-deps: ## Copy dependencies for distribution
mkdir -p dist
cp node_modules/codepage/dist/cpexcel.full.js dist/cpexcel.js
.PHONY: aux
aux: $(AUXTARGETS)
BYTEFILEC=dist/xlsx.{full,core,mini}.min.js xlsx.mjs
BYTEFILER=dist/xlsx.extendscript.js
.PHONY: bytes
bytes: ## Display minified and gzipped file sizes
@for i in $(BYTEFILEC); do npx printj "%-30s %7d %10d" $$i $$(wc -c < $$i) $$(gzip --best --stdout $$i | wc -c); done
@for i in $(BYTEFILER); do npx printj "%-30s %7d" $$i $$(wc -c < $$i); done
@npx printj "%-30s %10d" "treeshake" "$$(npx -y esbuild@0.14.14 --bundle misc/import.js | wc -c)"
.PHONY: git
git: ## show version string
@echo "$$(node -pe 'require("./package.json").version')"
.PHONY: nexe
nexe: xlsx.exe ## Build nexe standalone executable
xlsx.exe: bin/xlsx.njs xlsx.js
tail -n+2 $< | sed 's#\.\./#./xlsx#g' > nexe.js
nexe -i nexe.js -o $@
rm nexe.js
.PHONY: pkg
pkg: bin/xlsx.njs xlsx.js ## Build pkg standalone executable
pkg $<
## Testing
.PHONY: test mocha
test mocha: test.js
mkdir -p tmp
mocha -R spec -t 20000
test mocha: test.js ## Run test suite
mocha -R spec -t 30000
.PHONY: prof
prof:
cat misc/prof.js test.js > prof.js
node --prof prof.js
#* To run tests for one format, make test_<fmt>
#* To run the core test suite, make test_misc
.PHONY: testdot
testdot: test.js ## Run test suite using dot reporter
mocha -R dot -t 30000
.PHONY: test-esm
test-esm: test.mjs ## Run Node ESM test suite
npx -y mocha@9 -R spec -t 30000 $<
test.ts: test.mts
node -pe 'var data = fs.readFileSync("'$<'", "utf8"); data.split("\n").map(function(l) { return l.replace(/^describe\((.*?)function\(\)/, "Deno.test($$1async function(t)").replace(/\b(?:it|describe)\((.*?)function\(\)/g, "await t.step($$1async function(t)").replace("assert.ok", "assert.assert"); }).join("\n")' > $@
.PHONY: test-bun
test-bun: testbun.mjs ## Run Bun test suite
bun $<
.PHONY: test-deno
test-deno: test.ts ## Run Deno test suite
deno test --check --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $<
.PHONY: test-denocp
test-denocp: testnocp.ts ## Run Deno test suite (without codepage)
deno test --check --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $<
TESTFMT=$(patsubst %,test_%,$(FMT))
.PHONY: $(TESTFMT)
$(TESTFMT): test_%:
FMTS=$* make test
TESTFMT=$(patsubst %,testdot_%,$(FMT))
.PHONY: $(TESTFMT)
$(TESTFMT): testdot_%:
FMTS=$* make testdot
TESTESMFMT=$(patsubst %,test-esm_%,$(FMT))
.PHONY: $(TESTESMFMT)
$(TESTESMFMT): test-esm_%:
FMTS=$* make test-esm
TESTDENOFMT=$(patsubst %,test-deno_%,$(FMT))
.PHONY: $(TESTDENOFMT)
$(TESTDENOFMT): test-deno_%:
FMTS=$* make test-deno
TESTDENOCPFMT=$(patsubst %,test-denocp_%,$(FMT))
.PHONY: $(TESTDENOCPFMT)
$(TESTDENOCPFMT): test-denocp_%:
FMTS=$* make test-denocp
TESTBUNFMT=$(patsubst %,test-bun_%,$(FMT))
.PHONY: $(TESTBUNFMT)
$(TESTBUNFMT): test-bun_%:
FMTS=$* make test-bun
.PHONY: travis
travis: ## Run test suite with minimal output
mocha -R dot -t 30000
.PHONY: ctest
ctest: ## Build browser test fixtures
node tests/make_fixtures.js
.PHONY: ctestserv
ctestserv: ## Start a test server on port 8000
@cd tests && python -mSimpleHTTPServer || python3 -mhttp.server || npx -y http-server -p 8000 .
## Code Checking
.PHONY: fullint
fullint: lint mdlint ## Run all checks (removed: old-lint, tslint, flow)
.PHONY: lint
lint: $(TARGET)
jshint --show-non-errors $(TARGET) $(AUXTARGETS)
jshint --show-non-errors package.json bower.json
jscs $(TARGET) $(AUXTARGETS)
lint: $(TARGET) $(AUXTARGETS) ## Run eslint checks
@./node_modules/.bin/eslint --ext .js,.njs,.json,.html,.htm $(FLOWTARGET) $(AUXTARGETS) $(CMDS) $(HTMLLINT) package.json bower.json
@if [ -x "$(CLOSURE)" ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi
.PHONY: test-osx
test-osx:
node tests/write.js
open -a Numbers sheetjs.xlsx
open -a "Microsoft Excel" sheetjs.xlsx
.PHONY: old-lint
old-lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks
@./node_modules/.bin/jscs $(TARGET) $(AUXTARGETS) test.js
@./node_modules/.bin/jshint --show-non-errors $(TARGET) $(AUXTARGETS)
@./node_modules/.bin/jshint --show-non-errors $(CMDS)
@./node_modules/.bin/jshint --show-non-errors package.json bower.json test.js
@./node_modules/.bin/jshint --show-non-errors --extract=always $(HTMLLINT)
@if [ -x "$(CLOSURE)" ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi
.PHONY: cov cov-spin
cov: misc/coverage.html
cov-spin:
make cov & bash misc/spin.sh $$!
.PHONY: tslint
tslint: $(TARGET) ## Run typescript checks
#@npm install dtslint typescript
#@npm run-script dtslint
./node_modules/.bin/dtslint types
.PHONY: flow
flow: lint ## Run flow checker
@./node_modules/.bin/flow check --all --show-all-errors --include-warnings
.PHONY: mjslint
mjslint: $(ESMJSTGT) ## Lint the ESM build
@npx eslint -c .eslintmjs $<
.PHONY: cov
cov: misc/coverage.html ## Run coverage test
#* To run coverage tests for one format, make cov_<fmt>
COVFMT=$(patsubst %,cov_%,$(FMT))
.PHONY: $(COVFMT)
$(COVFMT): cov_%:
FMTS=$* make cov
misc/coverage.html: $(TARGET) test.js
mocha --require blanket -R html-cov > $@
mocha --require blanket -R html-cov -t 30000 > $@
.PHONY: coveralls coveralls-spin
coveralls:
mocha --require blanket --reporter mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js
.PHONY: coveralls
coveralls: ## Coverage Test + Send to coveralls.io
mocha --require blanket --reporter mocha-lcov-reporter -t 30000 | node ./node_modules/coveralls/bin/coveralls.js
coveralls-spin:
make coveralls & bash misc/spin.sh $$!
MDLINT=README.md
.PHONY: mdlint
mdlint: $(MDLINT) ## Check markdown documents
./node_modules/.bin/alex $^
./node_modules/.bin/mdspell -a -n -x -r --en-us $^
bower.json: misc/_bower.json package.json
cat $< | sed 's/_VERSION_/'`grep version package.json | awk '{gsub(/[^0-9a-z\.-]/,"",$$2); print $$2}'`'/' > $@
.PHONY: help
help:
@grep -hE '(^[a-zA-Z_-][ a-zA-Z_-]*:.*?|^#[#*])' $(MAKEFILE_LIST) | bash misc/help.sh
.PHONY: dist
dist: dist-deps $(TARGET) bower.json
cp $(TARGET) dist/
cp LICENSE dist/
uglifyjs $(TARGET) -o dist/$(LIB).min.js --source-map dist/$(LIB).min.map --preamble "$$(head -n 1 bits/00_header.js)"
misc/strip_sourcemap.sh dist/$(LIB).min.js
uglifyjs $(REQS) $(TARGET) -o dist/$(LIB).core.min.js --source-map dist/$(LIB).core.min.map --preamble "$$(head -n 1 bits/00_header.js)"
misc/strip_sourcemap.sh dist/$(LIB).core.min.js
uglifyjs $(REQS) $(ADDONS) $(TARGET) -o dist/$(LIB).full.min.js --source-map dist/$(LIB).full.min.map --preamble "$$(head -n 1 bits/00_header.js)"
misc/strip_sourcemap.sh dist/$(LIB).full.min.js
.PHONY: aux
aux: $(AUXTARGETS)
.PHONY: ods
ods: ods.js
ODSDEPS=$(sort $(wildcard odsbits/*.js))
ods.js: $(ODSDEPS)
cat $(ODSDEPS) | tr -d '\15\32' > $@
cp ods.js dist/ods.js
.PHONY: dist-deps
dist-deps: ods.js
cp node_modules/codepage/dist/cpexcel.full.js dist/cpexcel.js
cp jszip.js dist/jszip.js
cp ods.js dist/ods.js
#* To show a spinner, append "-spin" to any target e.g. cov-spin
%-spin:
@make $* & bash misc/spin.sh $$!

573
README.md
View File

@ -1,568 +1,41 @@
# xlsx
# [SheetJS](https://sheetjs.com)
Parser and writer for various spreadsheet formats. Pure-JS cleanroom
implementation from official specifications and related documents.
The SheetJS Community Edition offers battle-tested open-source solutions for
extracting useful data from almost any complex spreadsheet and generating new
spreadsheets that will work with legacy and modern software alike.
Supported read formats:
[SheetJS Pro](https://sheetjs.com/pro) offers solutions beyond data processing:
Edit complex templates with ease; let out your inner Picasso with styling; make
custom sheets with images/graphs/PivotTables; evaluate formula expressions and
port calculations to web apps; automate common spreadsheet tasks, and much more!
- Excel 2007+ XML Formats (XLSX/XLSM)
- Excel 2007+ Binary Format (XLSB)
- Excel 2003-2004 XML Format (XML "SpreadsheetML")
- Excel 97-2004 (XLS BIFF8)
- Excel 5.0/95 (XLS BIFF5)
- OpenDocument Spreadsheet (ODS)
## Documentation
Supported write formats:
- [API and Usage Documentation](https://docs.sheetjs.com)
- XLSX
- CSV (and general DSV)
- JSON and JS objects (various styles)
- [Downloadable Scripts and Modules](https://cdn.sheetjs.com)
Demo: <http://oss.sheetjs.com/js-xlsx>
## Constellation
Source: <http://git.io/xlsx>
- <https://oss.sheetjs.com/notes/>: File Format Notes
## Installation
- [`ssf`](packages/ssf): Format data using ECMA-376 spreadsheet format codes
With [npm](https://www.npmjs.org/package/xlsx):
- [`xlsx-cli`](packages/xlsx-cli): NodeJS command-line tool for processing files
npm install xlsx
- [`cfb`](https://git.sheetjs.com/SheetJS/js-cfb): Container (OLE/ZIP) file
processing library
In the browser:
- [`codepage`](https://git.sheetjs.com/SheetJS/js-codepage): Legacy text
encodings for XLS and other legacy spreadsheet formats
<script lang="javascript" src="dist/xlsx.core.min.js"></script>
- [`dta`](packages/dta): Stata DTA file processor
With [bower](http://bower.io/search/?q=js-xlsx):
bower install js-xlsx
CDNjs automatically pulls the latest version and makes all versions available at
<http://cdnjs.com/libraries/xlsx>
## Optional Modules
The node version automatically requires modules for additional features. Some
of these modules are rather large in size and are only needed in special
circumstances, so they do not ship with the core. For browser use, they must
be included directly:
<!-- international support from https://github.com/sheetjs/js-codepage -->
<script src="dist/cpexcel.js"></script>
<!-- ODS support -->
<script src="dist/ods.js"></script>
An appropriate version for each dependency is included in the dist/ directory.
The complete single-file version is generated at `dist/xlsx.full.min.js`
## ECMAScript 5 Compatibility
Since xlsx.js uses ES5 functions like `Array#forEach`, older browsers require
[Polyfills](http://git.io/QVh77g). This repo and the gh-pages branch include
[a shim](https://github.com/SheetJS/js-xlsx/blob/master/shim.js)
To use the shim, add the shim before the script tag that loads xlsx.js:
<script type="text/javascript" src="/path/to/shim.js"></script>
## Parsing Workbooks
For parsing, the first step is to read the file. This involves acquiring the
data and feeding it into the library. Here are a few common scenarios:
- node readFile:
```
if(typeof require !== 'undefined') XLSX = require('xlsx');
var workbook = XLSX.readFile('test.xlsx');
/* DO SOMETHING WITH workbook HERE */
```
- ajax (for a more complete example that works in older browsers, check the demo
at <http://oss.sheetjs.com/js-xlsx/ajax.html>):
```
/* set up XMLHttpRequest */
var url = "test_files/formula_stress_test_ajax.xlsx";
var oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
oReq.responseType = "arraybuffer";
oReq.onload = function(e) {
var arraybuffer = oReq.response;
/* convert data to binary string */
var data = new Uint8Array(arraybuffer);
var arr = new Array();
for(var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
var bstr = arr.join("");
/* Call XLSX */
var workbook = XLSX.read(bstr, {type:"binary"});
/* DO SOMETHING WITH workbook HERE */
}
oReq.send();
```
- HTML5 drag-and-drop using readAsBinaryString:
```
/* set up drag-and-drop event */
function handleDrop(e) {
e.stopPropagation();
e.preventDefault();
var files = e.dataTransfer.files;
var i,f;
for (i = 0, f = files[i]; i != files.length; ++i) {
var reader = new FileReader();
var name = f.name;
reader.onload = function(e) {
var data = e.target.result;
/* if binary string, read with type 'binary' */
var workbook = XLSX.read(data, {type: 'binary'});
/* DO SOMETHING WITH workbook HERE */
};
reader.readAsBinaryString(f);
}
}
drop_dom_element.addEventListener('drop', handleDrop, false);
```
- HTML5 input file element using readAsBinaryString:
```
function handleFile(e) {
var files = e.target.files;
var i,f;
for (i = 0, f = files[i]; i != files.length; ++i) {
var reader = new FileReader();
var name = f.name;
reader.onload = function(e) {
var data = e.target.result;
var workbook = XLSX.read(data, {type: 'binary'});
/* DO SOMETHING WITH workbook HERE */
};
reader.readAsBinaryString(f);
}
}
input_dom_element.addEventListener('change', handleFile, false);
```
## Working with the Workbook
The full object format is described later in this README.
This example extracts the value stored in cell A1 from the first worksheet:
```
var first_sheet_name = workbook.SheetNames[0];
var address_of_cell = 'A1';
/* Get worksheet */
var worksheet = workbook.Sheets[first_sheet_name];
/* Find desired cell */
var desired_cell = worksheet[address_of_cell];
/* Get the value */
var desired_value = desired_cell.v;
```
This example iterates through every nonempty of every sheet and dumps values:
```
var sheet_name_list = workbook.SheetNames;
sheet_name_list.forEach(function(y) { /* iterate through sheets */
var worksheet = workbook.Sheets[y];
for (z in worksheet) {
/* all keys that do not begin with "!" correspond to cell addresses */
if(z[0] === '!') continue;
console.log(y + "!" + z + "=" + JSON.stringify(worksheet[z].v));
}
});
```
Complete examples:
- <http://oss.sheetjs.com/js-xlsx/> HTML5 File API / Base64 Text / Web Workers
Note that older versions of IE does not support HTML5 File API, so the base64
mode is provided for testing. On OSX you can get the base64 encoding with:
$ <target_file.xlsx base64 | pbcopy
- <http://oss.sheetjs.com/js-xlsx/ajax.html> XMLHttpRequest
- <https://github.com/SheetJS/js-xlsx/blob/master/bin/xlsx.njs> node
The node version installs a command line tool `xlsx` which can read spreadsheet
files and output the contents in various formats. The source is available at
`xlsx.njs` in the bin directory.
Some helper functions in `XLSX.utils` generate different views of the sheets:
- `XLSX.utils.sheet_to_csv` generates CSV
- `XLSX.utils.sheet_to_json` generates an array of objects
- `XLSX.utils.sheet_to_formulae` generates a list of formulae
## Writing Workbooks
For writing, the first step is to generate output data. The helper functions
`write` and `writeFile` will produce the data in various formats suitable for
dissemination. The second step is to actual share the data with the end point.
Assuming `workbook` is a workbook object:
- nodejs write to file:
```
/* output format determined by filename */
XLSX.writeFile(workbook, 'out.xlsx');
/* at this point, out.xlsx is a file that you can distribute */
```
- write to binary string (using FileSaver.js):
```
/* bookType can be 'xlsx' or 'xlsm' or 'xlsb' */
var wopts = { bookType:'xlsx', bookSST:false, type:'binary' };
var wbout = XLSX.write(workbook,wopts);
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
/* the saveAs call downloads a file on the local machine */
saveAs(new Blob([s2ab(wbout)],{type:""}), "test.xlsx")
```
Complete examples:
- <http://sheetjs.com/demos/writexlsx.html> generates a simple file
- <http://git.io/WEK88Q> writing an array of arrays in nodejs
- <http://sheetjs.com/demos/table.html> exporting an HTML table
## Interface
`XLSX` is the exposed variable in the browser and the exported node variable
`XLSX.version` is the version of the library (added by the build script).
`XLSX.SSF` is an embedded version of the [format library](http://git.io/ssf).
### Parsing functions
`XLSX.read(data, read_opts)` attempts to parse `data`.
`XLSX.readFile(filename, read_opts)` attempts to read `filename` and parse.
### Writing functions
`XLSX.write(wb, write_opts)` attempts to write the workbook `wb`
`XLSX.writeFile(wb, filename, write_opts)` attempts to write `wb` to `filename`
### Utilities
Utilities are available in the `XLSX.utils` object:
Exporting:
- `sheet_to_json` converts a workbook object to an array of JSON objects.
- `sheet_to_csv` generates delimiter-separated-values output
- `sheet_to_formulae` generates a list of the formulae (with value fallbacks)
Cell and cell address manipulation:
- `format_cell` generates the text value for a cell (using number formats)
- `{en,de}code_{row,col}` convert between 0-indexed rows/cols and A1 forms.
- `{en,de}code_cell` converts cell addresses
- `{en,de}code_range` converts cell ranges
## Workbook / Worksheet / Cell Object Description
js-xlsx conforms to the Common Spreadsheet Format (CSF):
### General Structures
Cell address objects are stored as `{c:C, r:R}` where `C` and `R` are 0-indexed
column and row numbers, respectively. For example, the cell address `B5` is
represented by the object `{c:1, r:4}`.
Cell range objects are stored as `{s:S, e:E}` where `S` is the first cell and
`E` is the last cell in the range. The ranges are inclusive. For example, the
range `A3:B7` is represented by the object `{s:{c:0, r:2}, e:{c:1, r:6}}`. Utils
use the following pattern to walk each of the cells in a range:
```
for(var R = range.s.r; R <= range.e.r; ++R) {
for(var C = range.s.c; C <= range.e.c; ++C) {
var cell_address = {c:C, r:R};
}
}
```
### Cell Object
| Key | Description |
| --- | ----------- |
| `v` | raw value (see Data Types section for more info) |
| `w` | formatted text (if applicable) |
| `t` | cell type: `b` Boolean, `n` Number, `e` error, `s` String, `d` Date |
| `f` | cell formula (if applicable) |
| `r` | rich text encoding (if applicable) |
| `h` | HTML rendering of the rich text (if applicable) |
| `c` | comments associated with the cell ** |
| `z` | number format string associated with the cell (if requested) |
| `l` | cell hyperlink object (.Target holds link, .tooltip is tooltip) |
| `s` | the style/theme of the cell (if applicable) |
Built-in export utilities (such as the CSV exporter) will use the `w` text if it
is available. To change a value, be sure to delete `cell.w` (or set it to
`undefined`) before attempting to export. The utilities will regenerate the `w`
text from the number format (`cell.z`) and the raw value if possible.
### Data Types
The raw value is stored in the `v` field, interpreted based on the `t` field.
Type `b` is the Boolean type. `v` is interpreted according to JS truth tables
Type `e` is the Error type. `v` holds the number and `w` holds the common name:
| Value | Error Meaning |
| ----: | :------------ |
| 0x00 | #NULL! |
| 0x07 | #DIV/0! |
| 0x0F | #VALUE! |
| 0x17 | #REF! |
| 0x1D | #NAME? |
| 0x24 | #NUM! |
| 0x2A | #N/A |
| 0x2B | #GETTING_DATA |
Type `n` is the Number type. This includes all forms of data that Excel stores
as numbers, such as dates/times and Boolean fields. Excel exclusively uses data
that can be fit in an IEEE754 floating point number, just like JS Number, so the
`v` field holds the raw number. The `w` field holds formatted text.
Type `d` is the Date type, generated only when the option `cellDates` is passed.
Since JSON does not have a natural Date type, parsers are generally expected to
store ISO 8601 Date strings like you would get from `date.toISOString()`. On
the other hand, writers and exporters should be able to handle date strings and
JS Date objects. Note that Excel disregards the timezone modifier and treats all
dates in the local timezone. js-xlsx does not correct for this error.
Type `s` is the String type. `v` should be explicitly stored as a string to
avoid possible confusion.
### Worksheet Object
Each key that does not start with `!` maps to a cell (using `A-1` notation)
`worksheet[address]` returns the cell object for the specified address.
Special worksheet keys (accessible as `worksheet[key]`, each starting with `!`):
- `ws['!ref']`: A-1 based range representing the worksheet range. Functions that
work with sheets should use this parameter to determine the range. Cells that
are assigned outside of the range are not processed. In particular, when
writing a worksheet by hand, be sure to update the range. For a longer
discussion, see <http://git.io/KIaNKQ>
Functions that handle worksheets should test for the presence of `!ref` field.
If the `!ref` is omitted or is not a valid range, functions are free to treat
the sheet as empty or attempt to guess the range. The standard utilities that
ship with this library treat sheets as empty (for example, the CSV output is an
empty string).
When reading a worksheet with the `sheetRows` property set, the ref parameter
will use the restricted range. The original range is set at `ws['!fullref']`
- `ws['!cols']`: array of column properties objects. Column widths are actually
stored in files in a normalized manner, measured in terms of the "Maximum
Digit Width" (the largest width of the rendered digits 0-9, in pixels). When
parsed, the column objects store the pixel width in the `wpx` field, character
width in the `wch` field, and the maximum digit width in the `MDW` field.
- `ws['!merges']`: array of range objects corresponding to the merged cells in
the worksheet. Plaintext utilities are unaware of merge cells. CSV export
will write all cells in the merge range if they exist, so be sure that only
the first cell (upper-left) in the range is set.
### Workbook Object
`workbook.SheetNames` is an ordered list of the sheets in the workbook
`wb.Sheets[sheetname]` returns an object representing the worksheet.
`wb.Props` is an object storing the standard properties. `wb.Custprops` stores
custom properties. Since the XLS standard properties deviate from the XLSX
standard, XLS parsing stores core properties in both places. .
## Parsing Options
The exported `read` and `readFile` functions accept an options argument:
| Option Name | Default | Description |
| :---------- | ------: | :---------- |
| cellFormula | true | Save formulae to the .f field ** |
| cellHTML | true | Parse rich text and save HTML to the .h field |
| cellNF | false | Save number format string to the .z field |
| cellStyles | false | Save style/theme info to the .s field |
| cellDates | false | Store dates as type `d` (default is `n`) ** |
| sheetStubs | false | Create cell objects for stub cells |
| sheetRows | 0 | If >0, read the first `sheetRows` rows ** |
| bookDeps | false | If true, parse calculation chains |
| bookFiles | false | If true, add raw files to book object ** |
| bookProps | false | If true, only parse enough to get book metadata ** |
| bookSheets | false | If true, only parse enough to get the sheet names |
| bookVBA | false | If true, expose vbaProject.bin to `vbaraw` field ** |
| password | "" | If defined and file is encrypted, use password ** |
- `cellFormula` option only applies to formats that require extra processing to
parse formulae (XLS/XLSB).
- Even if `cellNF` is false, formatted text will be generated and saved to `.w`
- In some cases, sheets may be parsed even if `bookSheets` is false.
- `bookSheets` and `bookProps` combine to give both sets of information
- `Deps` will be an empty object if `bookDeps` is falsy
- `bookFiles` behavior depends on file type:
* `keys` array (paths in the ZIP) for ZIP-based formats
* `files` hash (mapping paths to objects representing the files) for ZIP
* `cfb` object for formats using CFB containers
- `sheetRows-1` rows will be generated when looking at the JSON object output
(since the header row is counted as a row when parsing the data)
- `bookVBA` merely exposes the raw vba object. It does not parse the data.
- `cellDates` currently does not convert numerical dates to JS dates.
- Currently only XOR encryption is supported. Unsupported error will be thrown
for files employing other encryption methods.
The defaults are enumerated in bits/84_defaults.js
## Writing Options
The exported `write` and `writeFile` functions accept an options argument:
| Option Name | Default | Description |
| :---------- | ------: | :---------- |
| cellDates | false | Store dates as type `d` (default is `n`) |
| bookSST | false | Generate Shared String Table ** |
| bookType | 'xlsx' | Type of Workbook ("xlsx" or "xlsm" or "xlsb") |
- `bookSST` is slower and more memory intensive, but has better compatibility
with older versions of iOS Numbers
- `bookType = 'xlsb'` is stubbed and far from complete
- The raw data is the only thing guaranteed to be saved. Formulae, formatting,
and other niceties may not be serialized (pending CSF standardization)
- `cellDates` only applies to XLSX output and is not guaranteed to work with
third-party readers. Excel itself does not usually write cells with type `d`
so non-Excel tools may ignore the data or blow up in the presence of dates.
## Tested Environments
- NodeJS 0.8, 0.10 (latest release), 0.11.14 (unstable), io.js
- IE 6/7/8/9/10/11 using Base64 mode (IE10/11 using HTML5 mode)
- FF 18 using Base64 or HTML5 mode
- Chrome 24 using Base64 or HTML5 mode
Tests utilize the mocha testing framework. Travis-CI and Sauce Labs links:
- <https://travis-ci.org/SheetJS/js-xlsx> for XLSX module in nodejs
- <https://travis-ci.org/SheetJS/SheetJS.github.io> for XLS* modules
- <https://saucelabs.com/u/sheetjs> for XLS* modules using Sauce Labs
## Test Files
Test files are housed in [another repo](https://github.com/SheetJS/test_files).
Running `make init` will refresh the `test_files` submodule and get the files.
## Testing
`make test` will run the node-based tests. To run the in-browser tests, clone
[the oss.sheetjs.com repo](https://github.com/SheetJS/SheetJS.github.io) and
replace the xlsx.js file (then fire up the browser and go to `stress.html`):
```
$ cp xlsx.js ../SheetJS.github.io
$ cd ../SheetJS.github.io
$ simplehttpserver # or "python -mSimpleHTTPServer" or "serve"
$ open -a Chromium.app http://localhost:8000/stress.html
```
For a much smaller test, run `make test_misc`.
## Contributing
Due to the precarious nature of the Open Specifications Promise, it is very
important to ensure code is cleanroom. Consult CONTRIBUTING.md
The xlsx.js file is constructed from the files in the `bits` subdirectory. The
build script (run `make`) will concatenate the individual bits to produce the
script. Before submitting a contribution, ensure that running make will produce
the xlsx.js file exactly. The simplest way to test is to move the script:
```
$ mv xlsx.js xlsx.new.js
$ make
$ diff xlsx.js xlsx.new.js
```
To produce the dist files, run `make dist`. The dist files are updated in each
version release and should not be committed between versions.
- [`test_files`](https://github.com/sheetjs/test_files): Test files and various
plaintext baselines.
## License
Please consult the attached LICENSE file for details. All rights not explicitly
granted by the Apache 2.0 license are reserved by the Original Author.
granted by the Apache 2.0 License are reserved by the Original Author.
It is the opinion of the Original Author that this code conforms to the terms of
the Microsoft Open Specifications Promise, falling under the same terms as
OpenOffice (which is governed by the Apache License v2). Given the vagaries of
the promise, the Original Author makes no legal claim that in fact end users are
protected from future actions. It is highly recommended that, for commercial
uses, you consult a lawyer before proceeding.
## References
ISO/IEC 29500:2012(E) "Information technology — Document description and processing languages — Office Open XML File Formats"
OSP-covered specifications:
- [MS-XLSB]: Excel (.xlsb) Binary File Format
- [MS-XLSX]: Excel (.xlsx) Extensions to the Office Open XML SpreadsheetML File Format
- [MS-OE376]: Office Implementation Information for ECMA-376 Standards Support
- [MS-CFB]: Compound File Binary File Format
- [MS-XLS]: Excel Binary File Format (.xls) Structure Specification
- [MS-ODATA]: Open Data Protocol (OData)
- [MS-OFFCRYPTO]: Office Document Cryptography Structure
- [MS-OLEDS]: Object Linking and Embedding (OLE) Data Structures
- [MS-OLEPS]: Object Linking and Embedding (OLE) Property Set Data Structures
- [MS-OSHARED]: Office Common Data Types and Objects Structures
- [MS-OVBA]: Office VBA File Format Structure
- [MS-CTXLS]: Excel Custom Toolbar Binary File Format
- [MS-XLDM]: Spreadsheet Data Model File Format
- [MS-EXSPXML3]: Excel Calculation Version 2 Web Service XML Schema
- [XLS]: Microsoft Office Excel 97-2007 Binary File Format Specification
Open Document Format for Office Applications Version 1.2 (29 September 2011)
## Badges
[![Build Status](https://travis-ci.org/SheetJS/js-xlsx.svg?branch=master)](https://travis-ci.org/SheetJS/js-xlsx)
[![Coverage Status](http://img.shields.io/coveralls/SheetJS/js-xlsx/master.svg)](https://coveralls.io/r/SheetJS/js-xlsx?branch=master)
[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/ed5bb2c4c4346a474fef270f847f3f78 "githalytics.com")](http://githalytics.com/SheetJS/js-xlsx)

View File

@ -1,31 +1,79 @@
#!/usr/bin/env node
/* xlsx.js (C) 2013-2015 SheetJS -- http://sheetjs.com */
var n = "xlsx";
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* eslint-env node */
/* vim: set ts=2 ft=javascript: */
var n = "xlsx";
var X = require('../');
var fs = require('fs'), program = require('commander');
try { X = require('../xlsx.flow'); } catch(e) {}
try { require('exit-on-epipe'); } catch(e) {}
var fs = require('fs'), program;
try { program = require('commander'); } catch(e) {
[
"The `xlsx` command line tool is deprecated in favor of `xlsx-cli`.",
"",
"For new versions of node, we recommend using `npx`:",
" $ npx xlsx-cli --help",
"",
"For older versions of node, explicitly install `xlsx-cli` globally:",
" $ npm i -g xlsx-cli",
" $ xlsx-cli --help"
].forEach(function(m) { console.error(m); });
process.exit(1);
}
program
.version(X.version)
.usage('[options] <file> [sheetname]')
.option('-f, --file <file>', 'use specified workbook')
.option('-s, --sheet <sheet>', 'print specified sheet (default first sheet)')
.option('-N, --sheet-index <idx>', 'use specified sheet index (0-based)')
.option('-p, --password <pw>', 'if file is encrypted, try with specified pw')
.option('-l, --list-sheets', 'list sheet names and exit')
.option('-o, --output <file>', 'output to specified file')
.option('-B, --xlsb', 'emit XLSB to <sheetname> or <file>.xlsb')
.option('-M, --xlsm', 'emit XLSM to <sheetname> or <file>.xlsm')
.option('-X, --xlsx', 'emit XLSX to <sheetname> or <file>.xlsx')
.option('-S, --formulae', 'print formulae')
.option('-j, --json', 'emit formatted JSON (all fields text)')
.option('-J, --raw-js', 'emit raw JS object (raw numbers)')
.option('-I, --xlam', 'emit XLAM to <sheetname> or <file>.xlam')
.option('-Y, --ods', 'emit ODS to <sheetname> or <file>.ods')
.option('-8, --xls', 'emit XLS to <sheetname> or <file>.xls (BIFF8)')
.option('-5, --biff5','emit XLS to <sheetname> or <file>.xls (BIFF5)')
.option('-4, --biff4','emit XLS to <sheetname> or <file>.xls (BIFF4)')
.option('-3, --biff3','emit XLS to <sheetname> or <file>.xls (BIFF3)')
.option('-2, --biff2','emit XLS to <sheetname> or <file>.xls (BIFF2)')
.option('-i, --xla', 'emit XLA to <sheetname> or <file>.xla')
.option('-6, --xlml', 'emit SSML to <sheetname> or <file>.xls (2003 XML)')
.option('-T, --fods', 'emit FODS to <sheetname> or <file>.fods (Flat ODS)')
.option('--wk3', 'emit WK3 to <sheetname> or <file>.txt (Lotus WK3)')
.option('--numbers', 'emit NUMBERS to <sheetname> or <file>.numbers')
.option('-S, --formulae', 'emit list of values and formulae')
.option('-j, --json', 'emit formatted JSON (all fields text)')
.option('-J, --raw-js', 'emit raw JS object (raw numbers)')
.option('-A, --arrays', 'emit rows as JS objects (raw numbers)')
.option('-H, --html', 'emit HTML to <sheetname> or <file>.html')
.option('-D, --dif', 'emit DIF to <sheetname> or <file>.dif (Lotus DIF)')
.option('-U, --dbf', 'emit DBF to <sheetname> or <file>.dbf (MSVFP DBF)')
.option('-K, --sylk', 'emit SYLK to <sheetname> or <file>.slk (Excel SYLK)')
.option('-P, --prn', 'emit PRN to <sheetname> or <file>.prn (Lotus PRN)')
.option('-E, --eth', 'emit ETH to <sheetname> or <file>.eth (Ethercalc)')
.option('-t, --txt', 'emit TXT to <sheetname> or <file>.txt (UTF-8 TSV)')
.option('-r, --rtf', 'emit RTF to <sheetname> or <file>.txt (Table RTF)')
.option('--wk1', 'emit WK1 to <sheetname> or <file>.txt (Lotus WK1)')
.option('-z, --dump', 'dump internal representation as JSON')
.option('--props', 'dump workbook properties as CSV')
.option('-F, --field-sep <sep>', 'CSV field separator', ",")
.option('-R, --row-sep <sep>', 'CSV row separator', "\n")
.option('-n, --sheet-rows <num>', 'Number of rows to process (0=all rows)')
.option('--sst', 'generate sst')
.option('--perf', 'do not generate output')
.option('--all', 'parse everything; XLS[XMB] write as much as possible')
.option('--codepage <cp>', 'default to specified codepage when ambiguous')
.option('--req <module>', 'require module before processing')
.option('--sst', 'generate shared string table for XLS* formats')
.option('--compress', 'use compression when writing XLSX/M/B and ODS')
.option('--read', 'read but do not generate output')
.option('--book', 'for single-sheet formats, emit a file per worksheet')
.option('--all', 'parse everything; write as much as possible')
.option('--dev', 'development mode')
.option('--read', 'read but do not print out contents')
.option('--sparse', 'sparse mode')
.option('-q, --quiet', 'quiet mode');
program.on('--help', function() {
@ -34,20 +82,26 @@ program.on('--help', function() {
console.log(' Web Demo: http://oss.sheetjs.com/js-'+n+'/');
});
/* flag, bookType, default ext */
var workbook_formats = [
['xlsx', 'xlsx', 'xlsx'],
['xlsm', 'xlsm', 'xlsm'],
['xlam', 'xlam', 'xlam'],
['xlsb', 'xlsb', 'xlsb'],
['xls', 'xls', 'xls'],
['xla', 'xla', 'xla'],
['biff5', 'biff5', 'xls'],
['numbers', 'numbers', 'numbers'],
['ods', 'ods', 'ods'],
['fods', 'fods', 'fods'],
['wk3', 'wk3', 'wk3']
];
var wb_formats_2 = [
['xlml', 'xlml', 'xls']
];
program.parse(process.argv);
/* see https://github.com/SheetJS/j/issues/4 */
if(process.version === 'v0.10.31') {
var msgs = [
"node v0.10.31 is known to crash on OSX and Linux, refusing to proceed.",
"see https://github.com/SheetJS/j/issues/4 for the relevant discussion.",
"see https://github.com/joyent/node/issues/8208 for the relevant node issue"
];
msgs.forEach(function(m) { console.error(m); });
process.exit(1);
}
var filename, sheetname = '';
var filename = '', sheetname = '';
if(program.args[0]) {
filename = program.args[0];
if(program.args[1]) sheetname = program.args[1];
@ -59,35 +113,61 @@ if(!filename) {
console.error(n + ": must specify a filename");
process.exit(1);
}
if(!fs.existsSync(filename)) {
console.error(n + ": " + filename + ": No such file or directory");
process.exit(2);
}
var opts = {}, wb;
if(program.req) program.req.split(",").forEach(function(r) {
require((fs.existsSync(r) || fs.existsSync(r + '.js')) ? require('path').resolve(r) : r);
});
var opts = {}, wb/*:?Workbook*/;
if(program.listSheets) opts.bookSheets = true;
if(program.sheetRows) opts.sheetRows = program.sheetRows;
if(program.password) opts.password = program.password;
if(program.xlsx || program.xlsm || program.xlsb) {
var seen = false;
function wb_fmt() {
seen = true;
opts.cellFormula = true;
opts.cellNF = true;
opts.xlfn = true;
if(program.output) sheetname = program.output;
}
else if(program.formulae);
function isfmt(m/*:string*/)/*:boolean*/ {
if(!program.output) return false;
var t = m.charAt(0) === "." ? m : "." + m;
return program.output.slice(-t.length) === t;
}
workbook_formats.forEach(function(m) { if(program[m[0]] || isfmt(m[0])) { wb_fmt(); } });
wb_formats_2.forEach(function(m) { if(program[m[0]] || isfmt(m[0])) { wb_fmt(); } });
if(seen) {
} else if(program.formulae) opts.cellFormula = true;
else opts.cellFormula = false;
var wopts = ({WTF:opts.WTF, bookSST:program.sst}/*:any*/);
if(program.compress) wopts.compression = true;
if(program.all) {
opts.cellFormula = true;
opts.bookVBA = true;
opts.cellNF = true;
opts.cellHTML = true;
opts.cellStyles = true;
opts.sheetStubs = true;
opts.cellDates = true;
wopts.cellFormula = true;
wopts.cellStyles = true;
wopts.sheetStubs = true;
wopts.bookVBA = true;
}
if(program.sparse) opts.dense = false; else opts.dense = true;
if(program.codepage) opts.codepage = +program.codepage;
if(program.dev) {
X.verbose = 2;
opts.WTF = true;
wb = X.readFile(filename, opts);
}
else try {
} else try {
wb = X.readFile(filename, opts);
} catch(e) {
var msg = (program.quiet) ? "" : n + ": error parsing ";
@ -96,38 +176,135 @@ else try {
process.exit(3);
}
if(program.read) process.exit(0);
if(!wb) { console.error(n + ": error parsing " + filename + ": empty workbook"); process.exit(0); }
/*:: if(!wb) throw new Error("unreachable"); */
if(program.listSheets) {
console.log(wb.SheetNames.join("\n"));
console.log((wb.SheetNames||[]).join("\n"));
process.exit(0);
}
if(program.dump) {
console.log(JSON.stringify(wb));
process.exit(0);
}
if(program.props) {
if(wb) dump_props(wb);
process.exit(0);
}
var wopts = {WTF:opts.WTF, bookSST:program.sst};
/* 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);
} });
if(program.xlsx) return X.writeFile(wb, sheetname || (filename + ".xlsx"), wopts);
if(program.xlsm) return X.writeFile(wb, sheetname || (filename + ".xlsm"), wopts);
if(program.xlsb) return X.writeFile(wb, sheetname || (filename + ".xlsb"), wopts);
wb_formats_2.forEach(function(m) { if(program[m[0]] || isfmt(m[0])) {
wopts.bookType = m[1];
if(wb) X.writeFile(wb, program.output || sheetname || ((filename || "") + "." + m[2]), wopts);
process.exit(0);
} });
var target_sheet = sheetname || '';
if(target_sheet === '') target_sheet = wb.SheetNames[0];
if(target_sheet === '') {
if(+program.sheetIndex < (wb.SheetNames||[]).length) target_sheet = wb.SheetNames[+program.sheetIndex];
else target_sheet = (wb.SheetNames||[""])[0];
}
var ws;
try {
ws = wb.Sheets[target_sheet];
if(!ws) throw "Sheet " + target_sheet + " cannot be found";
if(!ws) {
console.error("Sheet " + target_sheet + " cannot be found");
process.exit(3);
}
} catch(e) {
console.error(n + ": error parsing "+filename+" "+target_sheet+": " + e);
process.exit(4);
}
if(program.perf) return;
if(!program.quiet && !program.book) console.error(target_sheet);
var oo = "";
if(!program.quiet) console.error(target_sheet);
if(program.formulae) oo = X.utils.get_formulae(ws).join("\n");
else if(program.json) oo = JSON.stringify(X.utils.sheet_to_row_object_array(ws));
else if(program.rawJs) oo = JSON.stringify(X.utils.sheet_to_row_object_array(ws,{raw:true}));
else oo = X.utils.make_csv(ws, {FS:program.fieldSep, RS:program.rowSep});
/* single worksheet file formats */
[
['biff2', '.xls'],
['biff3', '.xls'],
['biff4', '.xls'],
['sylk', '.slk'],
['html', '.html'],
['prn', '.prn'],
['eth', '.eth'],
['rtf', '.rtf'],
['txt', '.txt'],
['dbf', '.dbf'],
['wk1', '.wk1'],
['dif', '.dif']
].forEach(function(m) { if(program[m[0]] || isfmt(m[1])) {
wopts.bookType = m[0];
if(program.book) {
/*:: if(wb == null) throw new Error("Unreachable"); */
wb.SheetNames.forEach(function(n, i) {
wopts.sheet = n;
X.writeFile(wb, (program.output || sheetname || filename || "") + m[1] + "." + i, wopts);
});
} else X.writeFile(wb, program.output || sheetname || ((filename || "") + m[1]), wopts);
process.exit(0);
} });
if(program.output) fs.writeFileSync(program.output, oo);
else console.log(oo);
function outit(o, fn) { if(fn) fs.writeFileSync(fn, o); else console.log(o); }
function doit(cb) {
/*:: if(!wb) throw new Error("unreachable"); */
if(program.book) wb.SheetNames.forEach(function(n, i) {
/*:: if(!wb) throw new Error("unreachable"); */
outit(cb(wb.Sheets[n]), (program.output || sheetname || filename) + "." + i);
});
else outit(cb(ws), program.output);
}
var jso = {};
switch(true) {
case program.formulae:
doit(function(ws) { return X.utils.sheet_to_formulae(ws).join("\n"); });
break;
case program.arrays: jso.header = 1;
/* falls through */
case program.rawJs: jso.raw = true;
/* falls through */
case program.json:
doit(function(ws) { return JSON.stringify(X.utils.sheet_to_json(ws,jso)); });
break;
default:
if(!program.book) {
var stream = X.stream.to_csv(ws, {FS:program.fieldSep||",", RS:program.rowSep||"\n"});
if(program.output) stream.pipe(fs.createWriteStream(program.output));
else stream.pipe(process.stdout);
} else doit(function(ws) { return X.utils.sheet_to_csv(ws,{FS:program.fieldSep, RS:program.rowSep}); });
break;
}
function dump_props(wb/*:Workbook*/) {
var propaoa = [];
if(Object.assign && Object.entries) propaoa = Object.entries(Object.assign({}, wb.Props, wb.Custprops));
else {
var Keys/*:: :Array<string> = []*/, pi;
if(wb.Props) {
Keys = Object.keys(wb.Props);
for(pi = 0; pi < Keys.length; ++pi) {
if(Object.prototype.hasOwnProperty.call(Keys, Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
}
}
if(wb.Custprops) {
Keys = Object.keys(wb.Custprops);
for(pi = 0; pi < Keys.length; ++pi) {
if(Object.prototype.hasOwnProperty.call(Keys, Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
}
}
}
console.log(X.utils.sheet_to_csv(X.utils.aoa_to_sheet(propaoa)));
}

View File

@ -1,6 +1,6 @@
/* xlsx.js (C) 2013-2015 SheetJS -- http://sheetjs.com */
/*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*jshint -W041 */
/*jshint funcscope:true, eqnull:true */
/*exported XLSX */
/*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(XLSX){
function make_xlsx_lib(XLSX){

View File

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

View File

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

2
bits/03_consts.js Normal file
View File

@ -0,0 +1,2 @@
var DENSE = null;
var DIF_XL = true;

View File

@ -1,41 +1,94 @@
var Base64 = (function make_b64(){
var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
return {
encode: function(input, utf8) {
var o = "";
var c1, c2, c3, e1, e2, e3, e4;
for(var i = 0; i < input.length; ) {
c1 = input.charCodeAt(i++);
c2 = input.charCodeAt(i++);
c3 = input.charCodeAt(i++);
e1 = c1 >> 2;
e2 = (c1 & 3) << 4 | c2 >> 4;
e3 = (c2 & 15) << 2 | c3 >> 6;
e4 = c3 & 63;
if (isNaN(c2)) { e3 = e4 = 64; }
else if (isNaN(c3)) { e4 = 64; }
o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4);
}
return o;
},
decode: function b64_decode(input, utf8) {
var o = "";
var c1, c2, c3;
var e1, e2, e3, e4;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
for(var i = 0; i < input.length;) {
e1 = map.indexOf(input.charAt(i++));
e2 = map.indexOf(input.charAt(i++));
e3 = map.indexOf(input.charAt(i++));
e4 = map.indexOf(input.charAt(i++));
c1 = e1 << 2 | e2 >> 4;
c2 = (e2 & 15) << 4 | e3 >> 2;
c3 = (e3 & 3) << 6 | e4;
o += String.fromCharCode(c1);
if (e3 != 64) { o += String.fromCharCode(c2); }
if (e4 != 64) { o += String.fromCharCode(c3); }
}
return o;
}
};
})();
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,16 +1,114 @@
var has_buf = (typeof Buffer !== 'undefined');
var has_buf = /*#__PURE__*/(function() { return typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.node; })();
function new_raw_buf(len) {
var Buffer_from = /*#__PURE__*/(function() {
if(typeof Buffer !== 'undefined') {
var nbfs = !Buffer.from;
if(!nbfs) try { Buffer.from("foo", "utf8"); } catch(e) { nbfs = true; }
return nbfs ? function(buf, enc) { return (enc) ? new Buffer(buf, enc) : new Buffer(buf); } : Buffer.from.bind(Buffer);
}
return function() {};
})();
var buf_utf16le = /*#__PURE__*/(function() {
if(typeof Buffer === 'undefined') return false;
var x = Buffer_from([65,0]);
if(!x) return false;
var o = x.toString("utf16le");
return o.length == 1;
})();
function new_raw_buf(len/*:number*/) {
/* jshint -W056 */
return new (has_buf ? Buffer : 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 s2a(s) {
if(has_buf) return new Buffer(s, "binary");
return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; });
function new_unsafe_buf(len/*:number*/) {
/* jshint -W056 */
if(has_buf) return Buffer.allocUnsafe ? Buffer.allocUnsafe(len) : new Buffer(len);
return typeof Uint8Array != "undefined" ? new Uint8Array(len) : new Array(len);
/* jshint +W056 */
}
var bconcat = function(bufs) { return [].concat.apply([], bufs); };
var s2a = function s2a(s/*:string*/)/*:any*/ {
if(has_buf) return Buffer_from(s, "binary");
return s.split("").map(function(x/*:string*/)/*:number*/{ return x.charCodeAt(0) & 0xff; });
};
var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/;
function s2ab(s/*:string*/)/*:any*/ {
if(typeof ArrayBuffer === 'undefined') return s2a(s);
var buf = new ArrayBuffer(s.length), view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
function a2s(data/*:any*/)/*:string*/ {
if(Array.isArray(data)) return data.map(function(c) { return String.fromCharCode(c); }).join("");
var o/*:Array<string>*/ = []; for(var i = 0; i < data.length; ++i) o[i] = String.fromCharCode(data[i]); return o.join("");
}
function a2u(data/*:Array<number>*/)/*:Uint8Array*/ {
if(typeof Uint8Array === 'undefined') throw new Error("Unsupported");
return new Uint8Array(data);
}
function ab2a(data/*:ArrayBuffer|Uint8Array*/)/*:Array<number>*/ {
if(typeof ArrayBuffer == 'undefined') throw new Error("Unsupported");
if(data instanceof ArrayBuffer) return ab2a(new Uint8Array(data));
/*:: if(data instanceof ArrayBuffer) throw new Error("unreachable"); */
var o = new Array(data.length);
for(var i = 0; i < data.length; ++i) o[i] = data[i];
return o;
}
var bconcat = has_buf ? function(bufs) { return Buffer.concat(bufs.map(function(buf) { return Buffer.isBuffer(buf) ? buf : Buffer_from(buf); })); } : function(bufs) {
if(typeof Uint8Array !== "undefined") {
var i = 0, maxlen = 0;
for(i = 0; i < bufs.length; ++i) maxlen += bufs[i].length;
var o = new Uint8Array(maxlen);
var len = 0;
for(i = 0, maxlen = 0; i < bufs.length; maxlen += len, ++i) {
len = bufs[i].length;
if(bufs[i] instanceof Uint8Array) o.set(bufs[i], maxlen);
else if(typeof bufs[i] == "string") o.set(new Uint8Array(s2a(bufs[i])), maxlen);
else o.set(new Uint8Array(bufs[i]), maxlen);
}
return o;
}
return [].concat.apply([], bufs.map(function(buf) { return Array.isArray(buf) ? buf : [].slice.call(buf); }));
};
function utf8decode(content/*:string*/) {
var out = [], widx = 0, L = content.length + 250;
var o = new_raw_buf(content.length + 255);
for(var ridx = 0; ridx < content.length; ++ridx) {
var c = content.charCodeAt(ridx);
if(c < 0x80) o[widx++] = c;
else if(c < 0x800) {
o[widx++] = (192|((c>>6)&31));
o[widx++] = (128|(c&63));
} else if(c >= 0xD800 && c < 0xE000) {
c = (c&1023)+64;
var d = content.charCodeAt(++ridx)&1023;
o[widx++] = (240|((c>>8)&7));
o[widx++] = (128|((c>>2)&63));
o[widx++] = (128|((d>>6)&15)|((c&3)<<4));
o[widx++] = (128|(d&63));
} else {
o[widx++] = (224|((c>>12)&15));
o[widx++] = (128|((c>>6)&63));
o[widx++] = (128|(c&63));
}
if(widx > L) {
out.push(o.slice(0, widx));
widx = 0;
o = new_raw_buf(65535);
L = 65530;
}
}
out.push(o.slice(0, widx));
return bconcat(out);
}
var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/g;

18
bits/09_types.js Normal file
View File

@ -0,0 +1,18 @@
/*::
declare type Block = any;
declare type BufArray = {
newblk(sz:number):Block;
next(sz:number):Block;
end():any;
push(buf:Block):void;
};
type RecordHopperCB = {(d:any, Rn:string, RT:number):?boolean;};
type EvertType = {[string]:string};
type EvertNumType = {[string]:number};
type EvertArrType = {[string]:Array<string>};
type StringConv = {(string):string};
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,78 @@
/* map from xlml named formats to SSF TODO: localize */
var XLMLFormatMap = {
"General Number": "General",
"General Date": SSF._table[22],
"Long Date": "dddd, mmmm dd, yyyy",
"Medium Date": SSF._table[15],
"Short Date": SSF._table[14],
"Long Time": SSF._table[19],
"Medium Time": SSF._table[18],
"Short Time": SSF._table[20],
"Currency": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
"Fixed": SSF._table[2],
"Standard": SSF._table[4],
"Percent": SSF._table[10],
"Scientific": SSF._table[11],
"Yes/No": '"Yes";"Yes";"No";@',
"True/False": '"True";"True";"False";@',
"On/Off": '"Yes";"Yes";"No";@'
var SSFImplicit/*{[number]:string}*/ = ({
"5": '"$"#,##0_);\\("$"#,##0\\)',
"6": '"$"#,##0_);[Red]\\("$"#,##0\\)',
"7": '"$"#,##0.00_);\\("$"#,##0.00\\)',
"8": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
"23": 'General', "24": 'General', "25": 'General', "26": 'General',
"27": 'm/d/yy', "28": 'm/d/yy', "29": 'm/d/yy', "30": 'm/d/yy', "31": 'm/d/yy',
"32": 'h:mm:ss', "33": 'h:mm:ss', "34": 'h:mm:ss', "35": 'h:mm:ss',
"36": 'm/d/yy',
"41": '_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)',
"42": '_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)',
"43": '_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)',
"44": '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)',
"50": 'm/d/yy', "51": 'm/d/yy', "52": 'm/d/yy', "53": 'm/d/yy', "54": 'm/d/yy',
"55": 'm/d/yy', "56": 'm/d/yy', "57": 'm/d/yy', "58": 'm/d/yy',
"59": '0',
"60": '0.00',
"61": '#,##0',
"62": '#,##0.00',
"63": '"$"#,##0_);\\("$"#,##0\\)',
"64": '"$"#,##0_);[Red]\\("$"#,##0\\)',
"65": '"$"#,##0.00_);\\("$"#,##0.00\\)',
"66": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
"67": '0%',
"68": '0.00%',
"69": '# ?/?',
"70": '# ??/??',
"71": 'm/d/yy',
"72": 'm/d/yy',
"73": 'd-mmm-yy',
"74": 'd-mmm',
"75": 'mmm-yy',
"76": 'h:mm',
"77": 'h:mm:ss',
"78": 'm/d/yy h:mm',
"79": 'mm:ss',
"80": '[h]:mm:ss',
"81": 'mmss.0'
}/*:any*/);
/* dateNF parse TODO: move to SSF */
var dateNFregex = /[dD]+|[mM]+|[yYeE]+|[Hh]+|[Ss]+/g;
function dateNF_regex(dateNF/*:string|number*/)/*:RegExp*/ {
var fmt = typeof dateNF == "number" ? table_fmt[dateNF] : dateNF;
fmt = fmt.replace(dateNFregex, "(\\d+)");
dateNFregex.lastIndex = 0;
return new RegExp("^" + fmt + "$");
}
function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/*:string*/ {
var Y = -1, m = -1, d = -1, H = -1, M = -1, S = -1;
(dateNF.match(dateNFregex)||[]).forEach(function(n, i) {
var v = parseInt(match[i+1], 10);
switch(n.toLowerCase().charAt(0)) {
case 'y': Y = v; break; case 'd': d = v; break;
case 'h': H = v; break; case 's': S = v; break;
case 'm': if(H >= 0) M = v; else m = v; break;
}
});
dateNFregex.lastIndex = 0;
if(S >= 0 && M == -1 && m >= 0) { M = m; m = -1; }
var datestr = (("" + (Y>=0?Y: new Date().getFullYear())).slice(-4) + "-" + ("00" + (m>=1?m:1)).slice(-2) + "-" + ("00" + (d>=1?d:1)).slice(-2));
if(datestr.length == 7) datestr = "0" + datestr;
if(datestr.length == 8) datestr = "20" + datestr;
var timestr = (("00" + (H>=0?H:0)).slice(-2) + ":" + ("00" + (M>=0?M:0)).slice(-2) + ":" + ("00" + (S>=0?S:0)).slice(-2));
if(H == -1 && M == -1 && S == -1) return datestr;
if(Y == -1 && m == -1 && d == -1) return timestr;
return datestr + "T" + timestr;
}
/* table of bad formats written by third-party tools */
var bad_formats = {
"d.m": "d\\.m" // Issue #2571 Google Sheets writes invalid format 'd.m', correct format is 'd"."m' or 'd\\.m'
};
function SSF__load(fmt, idx) {
return SSF_load(bad_formats[fmt] || fmt, idx);
}

File diff suppressed because it is too large Load Diff

76
bits/19_fsutils.js Normal file
View File

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

View File

@ -1,27 +1,29 @@
function isval(x) { return x !== undefined && x !== null; }
function keys(o/*:any*/)/*:Array<any>*/ {
var ks = Object.keys(o), o2 = [];
for(var i = 0; i < ks.length; ++i) if(Object.prototype.hasOwnProperty.call(o, ks[i])) o2.push(ks[i]);
return o2;
}
function keys(o) { return Object.keys(o); }
function evert_key(obj, key) {
var o = [], K = keys(obj);
for(var i = 0; i !== K.length; ++i) o[obj[K[i]][key]] = K[i];
function evert_key(obj/*:any*/, key/*:string*/)/*:EvertType*/ {
var o = ([]/*:any*/), K = keys(obj);
for(var i = 0; i !== K.length; ++i) if(o[obj[K[i]][key]] == null) o[obj[K[i]][key]] = K[i];
return o;
}
function evert(obj) {
var o = [], K = keys(obj);
function evert(obj/*:any*/)/*:EvertType*/ {
var o = ([]/*:any*/), K = keys(obj);
for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = K[i];
return o;
}
function evert_num(obj) {
var o = [], K = keys(obj);
function evert_num(obj/*:any*/)/*:EvertNumType*/ {
var o = ([]/*:any*/), K = keys(obj);
for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = parseInt(K[i],10);
return o;
}
function evert_arr(obj) {
var o = [], K = keys(obj);
function evert_arr(obj/*:any*/)/*:EvertArrType*/ {
var o/*:EvertArrType*/ = ([]/*:any*/), K = keys(obj);
for(var i = 0; i !== K.length; ++i) {
if(o[obj[K[i]]] == null) o[obj[K[i]]] = [];
o[obj[K[i]]].push(K[i]);
@ -29,16 +31,350 @@ function evert_arr(obj) {
return o;
}
/* TODO: date1904 logic */
function datenum(v, date1904) {
if(date1904) v+=1462;
var epoch = Date.parse(v);
return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
var dnthresh = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
var epoch = /*#__PURE__*/v.getTime();
var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
if(date1904) { res -= 1462; return res < -1402 ? res - 1 : res; }
return res < 60 ? res - 1 : res;
}
function numdate(v/*:number*/)/*:Date|number*/ {
if(v >= 60 && v < 61) return v;
var out = new Date();
out.setTime((v>60 ? v : (v+1)) * 24 * 60 * 60 * 1000 + dnthresh);
return out;
}
function cc2str(arr) {
var o = "";
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
/* ISO 8601 Duration */
function parse_isodur(s) {
var sec = 0, mt = 0, time = false;
var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
for(var i = 1; i != m.length; ++i) {
if(!m[i]) continue;
mt = 1;
if(i > 3) time = true;
switch(m[i].slice(m[i].length-1)) {
case 'Y':
throw new Error("Unsupported ISO Duration Field: " + m[i].slice(m[i].length-1));
case 'D': mt *= 24;
/* falls through */
case 'H': mt *= 60;
/* falls through */
case 'M':
if(!time) throw new Error("Unsupported ISO Duration Field: M");
else mt *= 60;
/* falls through */
case 'S': break;
}
sec += mt * parseInt(m[i], 10);
}
return sec;
}
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]], sans "Z"
/* parses a date string as a UTC date */
function parseDate(str/*:string*/, date1904/*:boolean*/)/*:Date*/ {
if(str instanceof Date) return str;
var m = str.match(pdre1);
if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
m = str.match(pdre2);
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
/* TODO: 1900-02-29T00:00:00.000 should return a flag to treat as a date code (affects xlml) */
m = str.match(pdre3);
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt((m[7] + "0000").slice(1,4), 10))||0)));
var d = new Date(str);
return d;
}
function cc2str(arr/*:Array<number>*/, debomit)/*:string*/ {
if(has_buf && Buffer.isBuffer(arr)) {
if(debomit && buf_utf16le) {
// TODO: temporary patch
if(arr[0] == 0xFF && arr[1] == 0xFE) return utf8write(arr.slice(2).toString("utf16le"));
if(arr[1] == 0xFE && arr[2] == 0xFF) return utf8write(utf16beread(arr.slice(2).toString("binary")));
}
return arr.toString("binary");
}
if(typeof TextDecoder !== "undefined") try {
if(debomit) {
if(arr[0] == 0xFF && arr[1] == 0xFE) return utf8write(new TextDecoder("utf-16le").decode(arr.slice(2)));
if(arr[0] == 0xFE && arr[1] == 0xFF) return utf8write(new TextDecoder("utf-16be").decode(arr.slice(2)));
}
var rev = {
"\u20ac": "\x80", "\u201a": "\x82", "\u0192": "\x83", "\u201e": "\x84",
"\u2026": "\x85", "\u2020": "\x86", "\u2021": "\x87", "\u02c6": "\x88",
"\u2030": "\x89", "\u0160": "\x8a", "\u2039": "\x8b", "\u0152": "\x8c",
"\u017d": "\x8e", "\u2018": "\x91", "\u2019": "\x92", "\u201c": "\x93",
"\u201d": "\x94", "\u2022": "\x95", "\u2013": "\x96", "\u2014": "\x97",
"\u02dc": "\x98", "\u2122": "\x99", "\u0161": "\x9a", "\u203a": "\x9b",
"\u0153": "\x9c", "\u017e": "\x9e", "\u0178": "\x9f"
};
if(Array.isArray(arr)) arr = new Uint8Array(arr);
return new TextDecoder("latin1").decode(arr).replace(/[€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ]/g, function(c) { return rev[c] || c; });
} catch(e) {}
var o = [], i = 0;
// this cascade is for the browsers and runtimes of antiquity (and for modern runtimes that lack TextEncoder)
try {
for(i = 0; i < arr.length - 65536; i+=65536) o.push(String.fromCharCode.apply(0, arr.slice(i, i + 65536)));
o.push(String.fromCharCode.apply(0, arr.slice(i)));
} catch(e) { try {
for(; i < arr.length - 16384; i+=16384) o.push(String.fromCharCode.apply(0, arr.slice(i, i + 16384)));
o.push(String.fromCharCode.apply(0, arr.slice(i)));
} catch(e) {
for(; i != arr.length; ++i) o.push(String.fromCharCode(arr[i]));
}
}
return o.join("");
}
function dup(o/*:any*/)/*:any*/ {
if(typeof JSON != 'undefined' && !Array.isArray(o)) return JSON.parse(JSON.stringify(o));
if(typeof o != 'object' || o == null) return o;
if(o instanceof Date) return new Date(o.getTime());
var out = {};
for(var k in o) if(Object.prototype.hasOwnProperty.call(o, k)) out[k] = dup(o[k]);
return out;
}
function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; }
/* TODO: stress test */
function fuzzynum(s/*:string*/)/*:number*/ {
var v/*:number*/ = Number(s);
if(!isNaN(v)) return isFinite(v) ? v : NaN;
if(!/\d/.test(s)) return v;
var wt = 1;
var ss = s.replace(/([\d]),([\d])/g,"$1$2").replace(/[$]/g,"").replace(/[%]/g, function() { wt *= 100; return "";});
if(!isNaN(v = Number(ss))) return v / wt;
ss = ss.replace(/[(]([^()]*)[)]/,function($$, $1) { wt = -wt; return $1;});
if(!isNaN(v = Number(ss))) return v / wt;
return v;
}
/* NOTE: Chrome rejects bare times like 1:23 PM */
var FDRE1 = /^(0?\d|1[0-2])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))\s+([ap])m?$/;
var FDRE2 = /^([01]?\d|2[0-3])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))$/;
var FDISO = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)(\.\d+)?[Z]?$/; // YYYY-mm-dd(T or space)HH:MM:SS[.UUU][Z]
/* TODO: 1904 adjustment */
var utc_append_works = new Date("6/9/69 00:00 UTC").valueOf() == -17798400000;
function fuzzytime1(M) /*:Date*/ {
if(!M[2]) return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0));
if(M[3]) {
if(M[4]) return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000));
else return new Date(Date.UTC(1899,11,31,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000));
}
else if(M[5]) return new Date(Date.UTC(1899,11,31, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0));
else return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0));
}
function fuzzytime2(M) /*:Date*/ {
if(!M[2]) return new Date(Date.UTC(1899,11,31,+M[1], 0, 0, 0));
if(M[3]) {
if(M[4]) return new Date(Date.UTC(1899,11,31,+M[1], +M[2], +M[4], parseFloat(M[3])*1000));
else return new Date(Date.UTC(1899,11,31,0, +M[1], +M[2], parseFloat(M[3])*1000));
}
else if(M[5]) return new Date(Date.UTC(1899,11,31, +M[1], +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0));
else return new Date(Date.UTC(1899,11,31,+M[1], +M[2], 0, 0));
}
var lower_months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'];
function fuzzydate(s/*:string*/)/*:Date*/ {
// See issue 2863 -- this is technically not supported in Excel but is otherwise useful
if(FDISO.test(s)) return s.indexOf("Z") == -1 ? local_to_utc(new Date(s)) : new Date(s);
var lower = s.toLowerCase();
var lnos = lower.replace(/\s+/g, " ").trim();
var M = lnos.match(FDRE1);
if(M) return fuzzytime1(M);
M = lnos.match(FDRE2);
if(M) return fuzzytime2(M);
M = lnos.match(pdre3);
if(M) return new Date(Date.UTC(+M[1], +M[2]-1, +M[3], +M[4], +M[5], ((M[6] && parseInt(M[6].slice(1), 10))|| 0), ((M[7] && parseInt((M[7] + "0000").slice(1,4), 10))||0)));
var o = new Date(utc_append_works && s.indexOf("UTC") == -1 ? s + " UTC": s), n = new Date(NaN);
var y = o.getYear(), m = o.getMonth(), d = o.getDate();
if(isNaN(d)) return n;
if(lower.match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) {
lower = lower.replace(/[^a-z]/g,"").replace(/([^a-z]|^)[ap]m?([^a-z]|$)/,"");
if(lower.length > 3 && lower_months.indexOf(lower) == -1) return n;
} else if(lower.replace(/[ap]m?/, "").match(/[a-z]/)) return n;
if(y < 0 || y > 8099 || s.match(/[^-0-9:,\/\\\ ]/)) return n;
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,43 +1,105 @@
function getdata(data) {
function getdatastr(data)/*:?string*/ {
if(!data) return null;
if(data.name.substr(-4) === ".bin") {
if(data.data) return char_codes(data.data);
if(data.asNodeBuffer && has_buf) return data.asNodeBuffer();
if(data._data && data._data.getContent) return Array.prototype.slice.call(data._data.getContent());
} else {
if(data.data) return data.name.substr(-4) !== ".bin" ? debom_xml(data.data) : char_codes(data.data);
if(data.asNodeBuffer && has_buf) return debom_xml(data.asNodeBuffer().toString('binary'));
if(data.asBinary) return debom_xml(data.asBinary());
if(data._data && data._data.getContent) return debom_xml(cc2str(Array.prototype.slice.call(data._data.getContent(),0)));
if(data.content && data.type) return cc2str(data.content, true);
if(data.data) return debom(data.data);
if(data.asNodeBuffer && has_buf) return debom(data.asNodeBuffer().toString('binary'));
if(data.asBinary) return debom(data.asBinary());
if(data._data && data._data.getContent) return debom(cc2str(Array.prototype.slice.call(data._data.getContent(),0)));
return null;
}
function getdatabin(data) {
if(!data) return null;
if(data.data) return char_codes(data.data);
if(data.asNodeBuffer && has_buf) return data.asNodeBuffer();
if(data._data && data._data.getContent) {
var o = data._data.getContent();
if(typeof o == "string") return char_codes(o);
return Array.prototype.slice.call(o);
}
if(data.content && data.type) return data.content;
return null;
}
function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getdatabin(data) : getdatastr(data); }
/* Part 2 Section 10.1.2 "Mapping Content Types" Names are case-insensitive */
/* OASIS does not comment on filename case sensitivity */
function safegetzipfile(zip, file/*:string*/) {
var k = zip.FullPaths || keys(zip.files);
var f = file.toLowerCase().replace(/[\/]/g, '\\'), g = f.replace(/\\/g,'\/');
for(var i=0; i<k.length; ++i) {
var n = k[i].replace(/^Root Entry[\/]/,"").toLowerCase();
if(f == n || g == n) return zip.files ? zip.files[k[i]] : zip.FileIndex[i];
}
return null;
}
function safegetzipfile(zip, file) {
var f = file; if(zip.files[f]) return zip.files[f];
f = file.toLowerCase(); if(zip.files[f]) return zip.files[f];
f = f.replace(/\//g,'\\'); if(zip.files[f]) return zip.files[f];
return null;
}
function getzipfile(zip, file) {
function getzipfile(zip, file/*:string*/) {
var o = safegetzipfile(zip, file);
if(o == null) throw new Error("Cannot find file " + file + " in zip");
return o;
}
function getzipdata(zip, file, safe) {
function getzipdata(zip, file/*:string*/, safe/*:?boolean*/)/*:any*/ {
if(!safe) return getdata(getzipfile(zip, file));
if(!file) return null;
try { return getzipdata(zip, file); } catch(e) { return null; }
}
var _fs, jszip;
if(typeof JSZip !== 'undefined') jszip = JSZip;
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
if(has_buf && typeof jszip === 'undefined') jszip = require('js'+'zip');
if(typeof jszip === 'undefined') jszip = require('./js'+'zip').JSZip;
_fs = require('f'+'s');
}
function getzipstr(zip, file/*:string*/, safe/*:?boolean*/)/*:?string*/ {
if(!safe) return getdatastr(getzipfile(zip, file));
if(!file) return null;
try { return getzipstr(zip, file); } catch(e) { return null; }
}
function getzipbin(zip, file/*:string*/, safe/*:?boolean*/)/*:any*/ {
if(!safe) return getdatabin(getzipfile(zip, file));
if(!file) return null;
try { return getzipbin(zip, file); } catch(e) { return null; }
}
function zipentries(zip) {
var k = zip.FullPaths || keys(zip.files), o = [];
for(var i = 0; i < k.length; ++i) if(k[i].slice(-1) != '/') o.push(k[i].replace(/^Root Entry[\/]/, ""));
return o.sort();
}
function zip_add_file(zip, path, content) {
if(zip.FullPaths) {
if(typeof content == "string") {
var res;
if(has_buf) res = Buffer_from(content);
/* TODO: investigate performance in Edge 13 */
//else if(typeof TextEncoder !== "undefined") res = new TextEncoder().encode(content);
else res = utf8decode(content);
return CFB.utils.cfb_add(zip, path, res);
}
CFB.utils.cfb_add(zip, path, content);
}
else zip.file(path, content);
}
function zip_new() { return CFB.utils.cfb_new(); }
function zip_read(d, o) {
switch(o.type) {
case "base64": return CFB.read(d, { type: "base64" });
case "binary": return CFB.read(d, { type: "binary" });
case "buffer": case "array": return CFB.read(d, { type: "buffer" });
}
throw new Error("Unrecognized type " + o.type);
}
function resolve_path(path/*:string*/, base/*:string*/)/*:string*/ {
if(path.charAt(0) == "/") return path.slice(1);
var result = base.split('/');
if(base.slice(-1) != "/") result.pop(); // folder path
var target = path.split('/');
while (target.length !== 0) {
var step = target.shift();
if (step === '..') result.pop();
else if (step !== '.') result.push(step);
}
return result.join('/');
}

View File

@ -1,24 +1,38 @@
var attregexg=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
var tagregex=/<[^>]*>/g;
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
var attregexg=/\s([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex1=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?<>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'"<>\s=]+))*\s*[\/\?]?>/mg, tagregex2 = /<[^<>]*>/g;
var tagregex = /*#__PURE__*/XML_HEADER.match(tagregex1) ? tagregex1 : tagregex2;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
function parsexmltag(tag, skip_root) {
var z = [];
function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*/)/*:any*/ {
var z = ({}/*:any*/);
var eq = 0, c = 0;
for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
if(!skip_root) z[0] = tag.substr(0, eq);
if(!skip_root) z[0] = tag.slice(0, eq);
if(eq === tag.length) return z;
var m = tag.match(attregexg), j=0, w="", v="", i=0, q="", cc="";
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.substr(0,c); v = cc.substring(c+2, cc.length-1);
q = cc.slice(0,c).trim();
while(cc.charCodeAt(c+1) == 32) ++c;
quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0;
v = cc.slice(c+1+quot, cc.length-quot);
for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
if(j===q.length) z[q] = v;
else z[(j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1)] = v;
if(j===q.length) {
if(q.indexOf("_") > 0) q = q.slice(0, q.indexOf("_")); // from ods
z[q] = v;
if(!skip_LC) z[q.toLowerCase()] = v;
}
else {
var k = (j===5 && q.slice(0,5)==="xmlns"?"xmlns":"")+q.slice(j+1);
if(z[k] && q.slice(j-3,j) == "ext") continue; // from ods
z[k] = v;
if(!skip_LC) z[k.toLowerCase()] = v;
}
}
return z;
}
function strip_ns(x) { return x.replace(nsregex2, "<$1"); }
function strip_ns(x/*:string*/)/*:string*/ { return x.replace(nsregex2, "<$1"); }
var encodings = {
'&quot;': '"',
@ -27,46 +41,68 @@ var encodings = {
'&lt;': '<',
'&amp;': '&'
};
var rencoding = evert(encodings);
var rencstr = "&<>'\"".split("");
var rencoding = /*#__PURE__*/evert(encodings);
//var rencstr = "&<>'\"".split("");
// TODO: CP remap (need to read file version to determine OS)
var unescapexml = (function() {
var encregex = /&[a-z]*;/g, coderegex = /_x([\da-fA-F]+)_/g;
return function unescapexml(text){
var s = text + '';
return s.replace(encregex, function($$) { return encodings[$$]; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
var 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;
function raw_unescapexml(text/*:string*/)/*:string*/ {
var s = text + '', i = s.indexOf("<![CDATA[");
if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
var j = s.indexOf("]]>");
return raw_unescapexml(s.slice(0, i)) + s.slice(i+9,j) + raw_unescapexml(s.slice(j+3));
}
return function unescapexml(text/*:string*/, xlsx/*:boolean*/) {
var out = raw_unescapexml(text);
return xlsx ? out.replace(/\r\n/g, "\n") : out;
};
})();
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
function escapexml(text){
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)).substr(-4) + "_";});
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";});
}
function escapexmltag(text/*:string*/)/*:string*/{ return escapexml(text).replace(/ /g,"_x0020_"); }
var htmlcharegex = /[\u0000-\u001f]/g;
function escapehtml(text/*:string*/)/*:string*/{
var s = text + '';
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(/\n/g, "<br/>").replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; });
}
function escapexlml(text/*:string*/)/*:string*/{
var s = text + '';
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; });
}
/* TODO: handle codepages */
var xlml_fixstr = (function() {
var xlml_fixstr/*:StringConv*/ = /*#__PURE__*/(function() {
var entregex = /&#(\d+);/g;
function entrepl($$,$1) { return String.fromCharCode(parseInt($1,10)); }
return function xlml_fixstr(str) { return str.replace(entregex,entrepl); };
function entrepl($$/*:string*/,$1/*:string*/)/*:string*/ { return String.fromCharCode(parseInt($1,10)); }
return function xlml_fixstr(str/*:string*/)/*:string*/ { return str.replace(entregex,entrepl); };
})();
function xlml_unfixstr(str/*:string*/)/*:string*/ { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); }
function parsexmlbool(value, tag) {
/* note: xsd:boolean valid values: true / 1 / false / 0 */
function parsexmlbool(value/*:any*/)/*:boolean*/ {
switch(value) {
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 = function utf8reada(orig) {
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++);
if (c < 128) { out += String.fromCharCode(c); continue; }
d = orig.charCodeAt(i++);
if (c>191 && c<224) { out += String.fromCharCode(((c & 31) << 6) | (d & 63)); continue; }
if (c>191 && c<224) { f = ((c & 31) << 6); f |= (d & 63); out += String.fromCharCode(f); continue; }
e = orig.charCodeAt(i++);
if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; }
f = orig.charCodeAt(i++);
@ -75,82 +111,135 @@ var utf8read = function utf8reada(orig) {
out += String.fromCharCode(0xDC00 + (w&1023));
}
return out;
};
if(has_buf) {
var utf8readb = function utf8readb(data) {
var out = new Buffer(2*data.length), w, i, j = 1, k = 0, ww=0, c;
for(i = 0; i < data.length; i+=j) {
j = 1;
if((c=data.charCodeAt(i)) < 128) w = c;
else if(c < 224) { w = (c&31)*64+(data.charCodeAt(i+1)&63); j=2; }
else if(c < 240) { w=(c&15)*4096+(data.charCodeAt(i+1)&63)*64+(data.charCodeAt(i+2)&63); j=3; }
else { j = 4;
w = (c & 7)*262144+(data.charCodeAt(i+1)&63)*4096+(data.charCodeAt(i+2)&63)*64+(data.charCodeAt(i+3)&63);
w -= 65536; ww = 0xD800 + ((w>>>10)&1023); w = 0xDC00 + (w&1023);
}
if(ww !== 0) { out[k++] = ww&255; out[k++] = ww>>>8; ww = 0; }
out[k++] = w%256; out[k++] = w>>>8;
}
out.length = k;
return out.toString('ucs2');
};
var corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3";
if(utf8read(corpus) == utf8readb(corpus)) utf8read = utf8readb;
var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
}
// matches <foo>...</foo> extracts content
var matchtag = (function() {
var mtcache = {};
return function matchtag(f,g) {
var t = f+"|"+g;
if(mtcache[t] !== undefined) return mtcache[t];
return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([^\u2603]*)</(?:\\w+:)?'+f+'>',(g||"")));
function utf8readb(data) {
var out = new_raw_buf(2*data.length), w, i, j = 1, k = 0, ww=0, c;
for(i = 0; i < data.length; i+=j) {
j = 1;
if((c=data.charCodeAt(i)) < 128) w = c;
else if(c < 224) { w = (c&31)*64+(data.charCodeAt(i+1)&63); j=2; }
else if(c < 240) { w=(c&15)*4096+(data.charCodeAt(i+1)&63)*64+(data.charCodeAt(i+2)&63); j=3; }
else { j = 4;
w = (c & 7)*262144+(data.charCodeAt(i+1)&63)*4096+(data.charCodeAt(i+2)&63)*64+(data.charCodeAt(i+3)&63);
w -= 65536; ww = 0xD800 + ((w>>>10)&1023); w = 0xDC00 + (w&1023);
}
if(ww !== 0) { out[k++] = ww&255; out[k++] = ww>>>8; ww = 0; }
out[k++] = w%256; out[k++] = w>>>8;
}
return out.slice(0,k).toString('ucs2');
}
function utf8readc(data) { return Buffer_from(data, 'binary').toString('utf8'); }
var utf8corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3";
var utf8read = has_buf && (/*#__PURE__*/utf8readc(utf8corpus) == /*#__PURE__*/utf8reada(utf8corpus) && utf8readc || /*#__PURE__*/utf8readb(utf8corpus) == /*#__PURE__*/utf8reada(utf8corpus) && utf8readb) || utf8reada;
var utf8write/*:StringConv*/ = has_buf ? function(data) { return Buffer_from(data, 'utf8').toString("binary"); } : function(orig/*:string*/)/*:string*/ {
var out/*:Array<string>*/ = [], i = 0, c = 0, d = 0;
while(i < orig.length) {
c = orig.charCodeAt(i++);
switch(true) {
case c < 128: out.push(String.fromCharCode(c)); break;
case c < 2048:
out.push(String.fromCharCode(192 + (c >> 6)));
out.push(String.fromCharCode(128 + (c & 63)));
break;
case c >= 55296 && c < 57344:
c -= 55296; d = orig.charCodeAt(i++) - 56320 + (c<<10);
out.push(String.fromCharCode(240 + ((d >>18) & 7)));
out.push(String.fromCharCode(144 + ((d >>12) & 63)));
out.push(String.fromCharCode(128 + ((d >> 6) & 63)));
out.push(String.fromCharCode(128 + (d & 63)));
break;
default:
out.push(String.fromCharCode(224 + (c >> 12)));
out.push(String.fromCharCode(128 + ((c >> 6) & 63)));
out.push(String.fromCharCode(128 + (c & 63)));
}
}
return out.join("");
};
var htmldecode/*:{(s:string):string}*/ = /*#__PURE__*/(function() {
var entities/*:Array<[RegExp, string]>*/ = [
['nbsp', ' '], ['middot', '·'],
['quot', '"'], ['apos', "'"], ['gt', '>'], ['lt', '<'], ['amp', '&']
].map(function(x/*:[string, string]*/) { return [new RegExp('&' + x[0] + ';', "ig"), x[1]]; });
return function htmldecode(str/*:string*/)/*:string*/ {
var o = str
// Remove new lines and spaces from start of content
.replace(/^[\t\n\r ]+/, "")
// Remove new lines and spaces from end of content
.replace(/(^|[^\t\n\r ])[\t\n\r ]+$/,"$1")
// Added line which removes any white space characters after and before html tags
.replace(/>\s+/g,">").replace(/\b\s+</g,"<")
// Replace remaining new lines and spaces with space
.replace(/[\t\n\r ]+/g, " ")
// Replace <br> tags with new lines
.replace(/<\s*[bB][rR]\s*\/?>/g,"\n")
// Strip HTML elements
.replace(/<[^<>]*>/g,"");
for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]);
return o;
};
})();
var vtregex = (function(){ var vt_cache = {};
return function vt_regex(bt) {
if(vt_cache[bt] !== undefined) return vt_cache[bt];
return (vt_cache[bt] = new RegExp("<vt:" + bt + ">(.*?)</vt:" + bt + ">", 'g') );
};})();
var vtvregex = /<\/?vt:variant>/g, vtmregex = /<vt:([^>]*)>(.*)</;
function parseVector(data) {
var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^<"'>]*)>([\s\S]*)</;
function parseVector(data/*:string*/, opts)/*:Array<{v:string,t:string}>*/ {
var h = parsexmltag(data);
var matches = data.match(vtregex(h.baseType))||[];
if(matches.length != h.size) throw "unexpected vector length " + matches.length + " != " + h.size;
var res = [];
matches.forEach(function(x) {
var matches/*:Array<string>*/ = str_match_xml_ns_g(data, h.baseType)||[];
var res/*:Array<any>*/ = [];
if(matches.length != h.size) {
if(opts.WTF) throw new Error("unexpected vector length " + matches.length + " != " + h.size);
return res;
}
matches.forEach(function(x/*:string*/) {
var v = x.replace(vtvregex,"").match(vtmregex);
res.push({v:v[2], t:v[1]});
if(v) res.push({v:utf8read(v[2]), t:v[1]});
});
return res;
}
var wtregex = /(^\s|\s$|\n)/;
function writetag(f,g) {return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>';}
function writetag(f/*:string*/,g/*:string*/)/*:string*/ { return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>'; }
function wxt_helper(h) { return keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join(""); }
function writextag(f,g,h) { return '<' + f + (isval(h) ? wxt_helper(h) : "") + (isval(g) ? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';}
function wxt_helper(h)/*:string*/ { return keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join(""); }
function writextag(f/*:string*/,g/*:?string*/,h) { return '<' + f + ((h != null) ? wxt_helper(h) : "") + ((g != null) ? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';}
function write_w3cdtf(d, t) { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } }
function write_w3cdtf(d/*:Date*/, t/*:?boolean*/)/*:string*/ { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } return ""; }
function write_vt(s) {
function write_vt(s, xlsx/*:?boolean*/)/*:string*/ {
switch(typeof s) {
case 'string': return writextag('vt:lpwstr', s);
case 'number': return writextag((s|0)==s?'vt:i4':'vt:r8', String(s));
case 'string':
var o = writextag('vt:lpwstr', escapexml(s));
if(xlsx) o = o.replace(/&quot;/g, "_x0022_");
return o;
case 'number': return writextag((s|0)==s?'vt:i4':'vt:r8', escapexml(String(s)));
case 'boolean': return writextag('vt:bool',s?'true':'false');
}
if(s instanceof Date) return writextag('vt:filetime', write_w3cdtf(s));
throw new Error("Unable to serialize " + s);
}
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
var XMLNS = {
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/',
@ -160,12 +249,21 @@ var XMLNS = {
'vt': 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes',
'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xsd': 'http://www.w3.org/2001/XMLSchema'
};
}/*:any*/);
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',
'http://schemas.microsoft.com/office/excel/2006/2'
];
var XLMLNS = ({
'o': 'urn:schemas-microsoft-com:office:office',
'x': 'urn:schemas-microsoft-com:office:excel',
'ss': 'urn:schemas-microsoft-com:office:spreadsheet',
'dt': 'uuid:C2F41010-65B3-11d1-A29F-00AA00C14882',
'mv': 'http://macVmlSchemaUri',
'v': 'urn:schemas-microsoft-com:vml',
'html': 'http://www.w3.org/TR/REC-html40'
}/*:any*/);

View File

@ -1,94 +1,129 @@
function readIEEE754(buf, idx, isLE, nl, ml) {
if(isLE === undefined) isLE = true;
if(!nl) nl = 8;
if(!ml && nl === 8) ml = 52;
var e, m, el = nl * 8 - ml - 1, eMax = (1 << el) - 1, eBias = eMax >> 1;
var bits = -7, d = isLE ? -1 : 1, i = isLE ? (nl - 1) : 0, s = buf[idx + i];
i += d;
e = s & ((1 << (-bits)) - 1); s >>>= (-bits); bits += el;
for (; bits > 0; e = e * 256 + buf[idx + i], i += d, bits -= 8);
m = e & ((1 << (-bits)) - 1); e >>>= (-bits); bits += ml;
for (; bits > 0; m = m * 256 + buf[idx + i], i += d, bits -= 8);
if (e === eMax) return m ? NaN : ((s ? -1 : 1) * Infinity);
else if (e === 0) e = 1 - eBias;
else { m = m + Math.pow(2, ml); e = e - eBias; }
return (s ? -1 : 1) * m * Math.pow(2, e - ml);
function read_double_le(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ {
var s = 1 - 2 * (b[idx + 7] >>> 7);
var e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 0x0f);
var m = (b[idx+6]&0x0f);
for(var i = 5; i >= 0; --i) m = m * 256 + b[idx + i];
if(e == 0x7ff) return m == 0 ? (s * Infinity) : NaN;
if(e == 0) e = -1022;
else { e -= 1023; m += Math.pow(2,52); }
return s * Math.pow(2, e - 52) * m;
}
var __toBuffer, ___toBuffer;
__toBuffer = ___toBuffer = function toBuffer_(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; };
var __utf16le, ___utf16le;
__utf16le = ___utf16le = function utf16le_(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join(""); };
var __hexlify, ___hexlify;
__hexlify = ___hexlify = function hexlify_(b,s,l) { return b.slice(s,(s+l)).map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); };
var __utf8, ___utf8;
__utf8 = ___utf8 = function(b,s,e) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
var __lpstr, ___lpstr;
__lpstr = ___lpstr = function lpstr_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var __lpwstr, ___lpwstr;
__lpwstr = ___lpwstr = function lpwstr_(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var __double, ___double;
__double = ___double = function(b, idx) { return readIEEE754(b, idx);};
function write_double_le(b/*:RawBytes|CFBlob*/, v/*:number*/, idx/*:number*/) {
var bs = ((((v < 0) || (1/v == -Infinity)) ? 1 : 0) << 7), e = 0, m = 0;
var av = bs ? (-v) : v;
if(!isFinite(av)) { e = 0x7ff; m = isNaN(v) ? 0x6969 : 0; }
else if(av == 0) e = m = 0;
else {
e = Math.floor(Math.log(av) / Math.LN2);
m = av * Math.pow(2, 52 - e);
if((e <= -1023) && (!isFinite(m) || (m < Math.pow(2,52)))) { e = -1022; }
else { m -= Math.pow(2,52); e+=1023; }
}
for(var i = 0; i <= 5; ++i, m/=256) b[idx + i] = m & 0xff;
b[idx + 6] = ((e & 0x0f) << 4) | (m & 0xf);
b[idx + 7] = (e >> 4) | bs;
}
var is_buf = function is_buf_a(a) { return Array.isArray(a); };
if(has_buf) {
__utf16le = function utf16le_b(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e); };
__hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
__lpstr = function lpstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
__lpwstr = function lpwstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
__utf8 = function utf8_b(s,e) { return this.toString('utf8',s,e); };
__toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);};
bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); };
__double = function double_(b,i) { if(Buffer.isBuffer(b)) return b.readDoubleLE(i); return ___double(b,i); };
is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); };
var ___toBuffer = function(bufs/*:Array<Array<RawBytes> >*/)/*:RawBytes*/ { var x=[],w=10240; for(var i=0;i<bufs[0].length;++i) if(bufs[0][i]) for(var j=0,L=bufs[0][i].length;j<L;j+=w) x.push.apply(x, bufs[0][i].slice(j,j+w)); return x; };
var __toBuffer = has_buf ? function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0].map(function(x) { return Buffer.isBuffer(x) ? x : Buffer_from(x); })) : ___toBuffer(bufs);} : ___toBuffer;
var ___utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join("").replace(chr0,''); };
var __utf16le = has_buf ? function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/ || !buf_utf16le) return ___utf16le(b,s,e); return b.toString('utf16le',s,e).replace(chr0,'')/*.replace(chr1,'!')*/; } : ___utf16le;
var ___hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); };
var __hexlify = has_buf ? function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { return Buffer.isBuffer(b)/*:: && b instanceof Buffer*/ ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); } : ___hexlify;
var ___utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
var __utf8 = has_buf ? function utf8_b(b/*:RawBytes|CFBlob*/, s/*:number*/, e/*:number*/) { return (Buffer.isBuffer(b)/*:: && (b instanceof Buffer)*/) ? b.toString('utf8',s,e) : ___utf8(b,s,e); } : ___utf8;
var ___lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var __lpstr = ___lpstr;
var ___cpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var __cpstr = ___cpstr;
var ___lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var __lpwstr = ___lpwstr;
var ___lpp4 = function lpp4_(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
var __lpp4 = ___lpp4;
var ___8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
var __8lpp4 = ___8lpp4;
var ___double = function(b/*:RawBytes|CFBlob*/, idx/*:number*/) { return read_double_le(b, idx);};
var __double = ___double;
var is_buf = function is_buf_a(a) { return Array.isArray(a) || (typeof Uint8Array !== "undefined" && a instanceof Uint8Array); };
if(has_buf/*:: && typeof Buffer !== 'undefined'*/) {
__lpstr = function lpstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
__cpstr = function cpstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___cpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
__lpwstr = function lpwstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/ || !buf_utf16le) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
__lpp4 = function lpp4_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/ || !buf_utf16le) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);};
__8lpp4 = function lpp4_8b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);};
__double = function double_(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(Buffer.isBuffer(b)/*::&& b instanceof Buffer*/) return b.readDoubleLE(i); return ___double(b,i); };
is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a) || (typeof Uint8Array !== "undefined" && a instanceof Uint8Array); };
}
/* from js-xls */
if(typeof cptable !== 'undefined') {
__utf16le = function(b,s,e) { return cptable.utils.decode(1200, b.slice(s,e)); };
__utf8 = function(b,s,e) { return cptable.utils.decode(65001, b.slice(s,e)); };
__lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";};
__lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";};
function cpdoit() {
__utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return $cptable.utils.decode(1200, b.slice(s,e)).replace(chr0, ''); };
__utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return $cptable.utils.decode(65001, b.slice(s,e)); };
__lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(current_ansi, b.slice(i+4, i+4+len-1)) : "";};
__cpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";};
__lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";};
__lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";};
__8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? $cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";};
}
if(typeof $cptable !== 'undefined') cpdoit();
var __readUInt8 = function(b, idx) { return b[idx]; };
var __readUInt16LE = function(b, idx) { return b[idx+1]*(1<<8)+b[idx]; };
var __readInt16LE = function(b, idx) { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; };
var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
var __readUInt8 = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx]; };
var __readUInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx+1]*(1<<8))+b[idx]; };
var __readInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { var u = (b[idx+1]*(1<<8))+b[idx]; return (u < 0x8000) ? u : ((0xffff - u + 1) * -1); };
var __readUInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
var __readInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
var __readInt32BE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx]<<24)|(b[idx+1]<<16)|(b[idx+2]<<8)|b[idx+3]; };
var ___unhexlify = function(s) { return s.match(/../g).map(function(x) { return parseInt(x,16);}); };
var __unhexlify = typeof Buffer !== "undefined" ? function(s) { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;
function ReadShift(size, t) {
var o="", oI, oR, oo=[], w, vv, i, loc;
function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
var o="", oI/*:: :number = 0*/, oR, oo=[], w, vv, i, loc;
switch(t) {
case 'dbcs':
loc = this.l;
if(has_buf && Buffer.isBuffer(this)) o = this.slice(this.l, this.l+2*size).toString("utf16le");
else for(i = 0; i != size; ++i) { o+=String.fromCharCode(__readUInt16LE(this, loc)); loc+=2; }
if(has_buf && Buffer.isBuffer(this) && 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;
case 'utf8': o = __utf8(this, this.l, this.l + size); break;
case 'utf16le': size *= 2; o = __utf16le(this, this.l, this.l + size); break;
case 'wstr':
if(typeof $cptable !== 'undefined') o = $cptable.utils.decode(current_codepage, this.slice(this.l, this.l+2*size));
else return ReadShift.call(this, size, 'dbcs');
size = 2 * size; break;
/* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */
case 'lpstr': o = __lpstr(this, this.l); size = 5 + o.length; break;
case 'lpstr-ansi': o = __lpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break;
case 'lpstr-cp': o = __cpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break;
/* [MS-OLEDS] 2.1.5 LengthPrefixedUnicodeString */
case 'lpwstr': o = __lpwstr(this, this.l); size = 5 + o.length; if(o[o.length-1] == '\u0000') size += 2; break;
case 'lpwstr': o = __lpwstr(this, this.l); size = 4 + 2 * __readUInt32LE(this, this.l); break;
/* [MS-OFFCRYPTO] 2.1.2 Length-Prefixed Padded Unicode String (UNICODE-LP-P4) */
case 'lpp4': size = 4 + __readUInt32LE(this, this.l); o = __lpp4(this, this.l); if(size & 0x02) size += 2; break;
/* [MS-OFFCRYPTO] 2.1.3 Length-Prefixed UTF-8 String (UTF-8-LP-P4) */
case '8lpp4': size = 4 + __readUInt32LE(this, this.l); o = __8lpp4(this, this.l); if(size & 0x03) size += 4 - (size & 0x03); break;
case 'cstr': size = 0; o = "";
while((w=__readUInt8(this, this.l + size++))!==0) oo.push(_getchar(w));
o = oo.join(""); break;
case 'wstr': size = 0; o = "";
case '_wstr': size = 0; o = "";
while((w=__readUInt16LE(this,this.l +size))!==0){oo.push(_getchar(w));size+=2;}
size+=2; o = oo.join(""); break;
/* sbcs and dbcs support continue records in the SST way TODO codepages */
case 'dbcs-cont': o = ""; loc = this.l;
for(i = 0; i != size; ++i) {
for(i = 0; i < size; ++i) {
if(this.lens && this.lens.indexOf(loc) !== -1) {
w = __readUInt8(this, loc);
this.l = loc + 1;
@ -99,6 +134,12 @@ function ReadShift(size, t) {
loc+=2;
} o = oo.join(""); size *= 2; break;
case 'cpstr':
if(typeof $cptable !== 'undefined') {
o = $cptable.utils.decode(current_codepage, this.slice(this.l, this.l + size));
break;
}
/* falls through */
case 'sbcs-cont': o = ""; loc = this.l;
for(i = 0; i != size; ++i) {
if(this.lens && this.lens.indexOf(loc) !== -1) {
@ -115,51 +156,98 @@ function ReadShift(size, t) {
switch(size) {
case 1: oI = __readUInt8(this, this.l); this.l++; return oI;
case 2: oI = (t === 'i' ? __readInt16LE : __readUInt16LE)(this, this.l); this.l += 2; return oI;
case 4:
if(t === 'i' || (this[this.l+3] & 0x80)===0) { oI = __readInt32LE(this, this.l); this.l += 4; return oI; }
else { oR = __readUInt32LE(this, this.l); this.l += 4; return oR; } break;
case 8: if(t === 'f') { oR = __double(this, this.l); this.l += 8; return oR; }
case 4: case -4:
if(t === 'i' || ((this[this.l+3] & 0x80)===0)) { oI = ((size > 0) ? __readInt32LE : __readInt32BE)(this, this.l); this.l += 4; return oI; }
else { oR = __readUInt32LE(this, this.l); this.l += 4; } return oR;
case 8: case -8:
if(t === 'f') {
if(size == 8) oR = __double(this, this.l);
else oR = __double([this[this.l+7],this[this.l+6],this[this.l+5],this[this.l+4],this[this.l+3],this[this.l+2],this[this.l+1],this[this.l+0]], 0);
this.l += 8; return oR;
} else size = 8;
/* falls through */
case 16: o = __hexlify(this, this.l, size); break;
}}
this.l+=size; return o;
}
function WriteShift(t, val, f) {
var size, i;
var __writeUInt32LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); b[idx+2] = ((val >>> 16) & 0xFF); b[idx+3] = ((val >>> 24) & 0xFF); };
var __writeInt32LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); };
var __writeUInt16LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); };
function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/)/*:any*/ {
var size = 0, i = 0;
if(f === 'dbcs') {
for(i = 0; i != val.length; ++i) this.writeUInt16LE(val.charCodeAt(i), this.l + 2 * i);
/*:: 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 switch(t) {
case 1: size = 1; this[this.l] = val&255; break;
case 3: size = 3; this[this.l+2] = val & 255; val >>>= 8; this[this.l+1] = val&255; val >>>= 8; this[this.l] = val&255; break;
case 4: size = 4; this.writeUInt32LE(val, this.l); break;
case 8: size = 8; if(f === 'f') { this.writeDoubleLE(val, this.l); break; }
} else if(f === 'sbcs' || f == 'cpstr') {
if(typeof $cptable !== 'undefined' && current_ansi == 874) {
/* TODO: use tables directly, don't encode */
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
for(i = 0; i != val.length; ++i) {
var cpp = $cptable.utils.encode(current_ansi, val.charAt(i));
this[this.l + i] = cpp[0];
}
size = val.length;
} else if(typeof $cptable !== 'undefined' && f == 'cpstr') {
cpp = $cptable.utils.encode(current_codepage, val);
/* replace null bytes with _ when relevant */
if(cpp.length == val.length) for(i = 0; i < val.length; ++i) if(cpp[i] == 0 && val.charCodeAt(i) != 0) cpp[i] = 0x5F;
if(cpp.length == 2 * val.length) for(i = 0; i < val.length; ++i) if(cpp[2*i] == 0 && cpp[2*i+1] == 0 && val.charCodeAt(i) != 0) cpp[2*i] = 0x5F;
for(i = 0; i < cpp.length; ++i) this[this.l + i] = cpp[i];
size = cpp.length;
} else {
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
val = val.replace(/[^\x00-\x7F]/g, "_");
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
for(i = 0; i != val.length; ++i) this[this.l + i] = (val.charCodeAt(i) & 0xFF);
size = val.length;
}
} else if(f === 'hex') {
for(; i < t; ++i) {
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
this[this.l++] = (parseInt(val.slice(2*i, 2*i+2), 16)||0);
} return this;
} else if(f === 'utf16le') {
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
var end/*:number*/ = Math.min(this.l + t, this.length);
for(i = 0; i < Math.min(val.length, t); ++i) {
var cc = val.charCodeAt(i);
this[this.l++] = (cc & 0xff);
this[this.l++] = (cc >> 8);
}
while(this.l < end) this[this.l++] = 0;
return this;
} else /*:: if(typeof val === 'number') */ switch(t) {
case 1: size = 1; this[this.l] = val&0xFF; break;
case 2: size = 2; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; break;
case 3: size = 3; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; val >>>= 8; this[this.l+2] = val&0xFF; break;
case 4: size = 4; __writeUInt32LE(this, val, this.l); break;
case 8: size = 8; if(f === 'f') { write_double_le(this, val, this.l); break; }
/* falls through */
case 16: break;
case -4: size = 4; this.writeInt32LE(val, this.l); break;
case -4: size = 4; __writeInt32LE(this, val, this.l); break;
}
this.l += size; return this;
}
function CheckField(hexstr, fld) {
function CheckField(hexstr/*:string*/, fld/*:string*/)/*:void*/ {
var m = __hexlify(this,this.l,hexstr.length>>1);
if(m !== hexstr) throw fld + 'Expected ' + hexstr + ' saw ' + m;
if(m !== hexstr) throw new Error(fld + 'Expected ' + hexstr + ' saw ' + m);
this.l += hexstr.length>>1;
}
function prep_blob(blob, pos) {
function prep_blob(blob, pos/*:number*/)/*:void*/ {
blob.l = pos;
blob.read_shift = ReadShift;
blob.read_shift = /*::(*/ReadShift/*:: :any)*/;
blob.chk = CheckField;
blob.write_shift = WriteShift;
}
function parsenoop(blob, length) { blob.l += length; }
function parsenoop(blob, length/*:: :number, opts?:any */) { blob.l += length; }
function writenoop(blob, length) { blob.l += length; }
function new_buf(sz) {
function new_buf(sz/*:number*/)/*:Block*/ {
var o = new_raw_buf(sz);
prep_blob(o, 0);
return o;

View File

@ -1,56 +1,65 @@
/* [MS-XLSB] 2.1.4 Record */
function recordhopper(data, cb, opts) {
function recordhopper(data, cb/*:RecordHopperCB*/, opts/*:?any*/) {
if(!data) return;
var tmpbyte, cntbyte, length;
prep_blob(data, data.l || 0);
while(data.l < data.length) {
var RT = data.read_shift(1);
var L = data.length, RT = 0, tgt = 0;
while(data.l < L) {
RT = data.read_shift(1);
if(RT & 0x80) RT = (RT & 0x7F) + ((data.read_shift(1) & 0x7F)<<7);
var R = XLSBRecordEnum[RT] || XLSBRecordEnum[0xFFFF];
tmpbyte = data.read_shift(1);
length = tmpbyte & 0x7F;
for(cntbyte = 1; cntbyte <4 && (tmpbyte & 0x80); ++cntbyte) length += ((tmpbyte = data.read_shift(1)) & 0x7F)<<(7*cntbyte);
var d = R.f(data, length, opts);
tgt = data.l + length;
var d = R.f && R.f(data, length, opts);
data.l = tgt;
if(cb(d, R, RT)) return;
}
}
/* control buffer usage for fixed-length buffers */
function buf_array() {
var bufs = [], blksz = 2048;
var newblk = function ba_newblk(sz) {
var o = new_buf(sz);
function buf_array()/*:BufArray*/ {
var bufs/*:Array<Block>*/ = [], blksz = has_buf ? 256 : 2048;
var newblk = function ba_newblk(sz/*:number*/)/*:Block*/ {
var o/*:Block*/ = (new_buf(sz)/*:any*/);
prep_blob(o, 0);
return o;
};
var curbuf = newblk(blksz);
var curbuf/*:Block*/ = newblk(blksz);
var endbuf = function ba_endbuf() {
curbuf.length = curbuf.l;
if(curbuf.length > 0) bufs.push(curbuf);
if(!curbuf) return;
// workaround for new Buffer(3).slice(0,0) bug in bun 0.1.3
if(curbuf.l) {
if(curbuf.length > curbuf.l) { curbuf = curbuf.slice(0, curbuf.l); curbuf.l = curbuf.length; }
if(curbuf.length > 0) bufs.push(curbuf);
}
curbuf = null;
};
var next = function ba_next(sz) {
if(sz < curbuf.length - curbuf.l) return curbuf;
var next = function ba_next(sz/*:number*/)/*:Block*/ {
if(curbuf && (sz < (curbuf.length - curbuf.l))) return curbuf;
endbuf();
return (curbuf = newblk(Math.max(sz+1, blksz)));
};
var end = function ba_end() {
endbuf();
return __toBuffer([bufs]);
return bconcat(bufs);
};
var push = function ba_push(buf) { endbuf(); curbuf = buf; next(blksz); };
var push = function ba_push(buf) { endbuf(); curbuf = buf; if(curbuf.l == null) curbuf.l = curbuf.length; next(blksz); };
return { next:next, push:push, end:end, _bufs:bufs };
return ({ next:next, push:push, end:end, _bufs:bufs }/*:any*/);
}
function write_record(ba, type, payload, length) {
var t = evert_RE[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;
l = 1 + (t >= 0x80 ? 1 : 0) + 1/* + length*/;
if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l;
var o = ba.next(l);
if(t <= 0x7F) o.write_shift(1, t);
@ -62,5 +71,5 @@ function write_record(ba, type, payload, length) {
if(length >= 0x80) { o.write_shift(1, (length & 0x7F)+0x80); length >>= 7; }
else { o.write_shift(1, length); break; }
}
if(length > 0 && is_buf(payload)) ba.push(payload);
if(/*:: length != null &&*/length > 0 && is_buf(payload)) ba.push(payload);
}

View File

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

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

@ -1,35 +0,0 @@
var OFFCRYPTO = {};
var make_offcrypto = function(O, _crypto) {
var crypto;
if(typeof _crypto !== 'undefined') crypto = _crypto;
else if(typeof require !== 'undefined') {
try { crypto = require('cry'+'pto'); }
catch(e) { crypto = null; }
}
O.rc4 = function(key, data) {
var S = new Array(256);
var c = 0, i = 0, j = 0, t = 0;
for(i = 0; i != 256; ++i) S[i] = i;
for(i = 0; i != 256; ++i) {
j = (j + S[i] + (key[i%key.length]).charCodeAt(0))&255;
t = S[i]; S[i] = S[j]; S[j] = t;
}
i = j = 0; out = Buffer(data.length);
for(c = 0; c != data.length; ++c) {
i = (i + 1)&255;
j = (j + S[i])%256;
t = S[i]; S[i] = S[j]; S[j] = t;
out[c] = (data[c] ^ S[(S[i]+S[j])&255]);
}
return out;
};
if(crypto) {
O.md5 = function(hex) { return crypto.createHash('md5').update(hex).digest('hex'); };
} else {
O.md5 = function(hex) { throw "unimplemented"; };
}
};
make_offcrypto(OFFCRYPTO, typeof crypto !== "undefined" ? crypto : undefined);

197
bits/27_csfutils.js Normal file
View File

@ -0,0 +1,197 @@
function decode_row(rowstr/*:string*/)/*:number*/ { return parseInt(unfix_row(rowstr),10) - 1; }
function encode_row(row/*:number*/)/*:string*/ { return "" + (row + 1); }
function fix_row(cstr/*:string*/)/*:string*/ { return cstr.replace(/([A-Z]|^)(\d+)$/,"$1$$$2"); }
function unfix_row(cstr/*:string*/)/*:string*/ { return cstr.replace(/\$(\d+)$/,"$1"); }
function decode_col(colstr/*:string*/)/*:number*/ { var c = unfix_col(colstr), d = 0, i = 0; for(; i !== c.length; ++i) d = 26*d + c.charCodeAt(i) - 64; return d - 1; }
function encode_col(col/*:number*/)/*:string*/ { if(col < 0) throw new Error("invalid column " + col); var s=""; for(++col; col; col=Math.floor((col-1)/26)) s = String.fromCharCode(((col-1)%26) + 65) + s; return s; }
function fix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^([A-Z])/,"$$$1"); }
function unfix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^\$([A-Z])/,"$1"); }
function split_cell(cstr/*:string*/)/*:Array<string>*/ { return cstr.replace(/(\$?[A-Z]*)(\$?\d*)/,"$1,$2").split(","); }
function decode_cell(cstr/*:string*/)/*:CellAddress*/ {
var R = 0, C = 0;
for(var i = 0; i < cstr.length; ++i) {
var cc = cstr.charCodeAt(i);
if(cc >= 48 && cc <= 57) R = 10 * R + (cc - 48);
else if(cc >= 65 && cc <= 90) C = 26 * C + (cc - 64);
}
return { c: C - 1, r:R - 1 };
}
function encode_cell(cell/*:CellAddress*/)/*:string*/ {
var col = cell.c + 1;
var s="";
for(; col; col=((col-1)/26)|0) s = String.fromCharCode(((col-1)%26) + 65) + s;
return s + (cell.r + 1);
}
function decode_range(range/*:string*/)/*:Range*/ {
var idx = range.indexOf(":");
if(idx == -1) return { s: decode_cell(range), e: decode_cell(range) };
return { s: decode_cell(range.slice(0, idx)), e: decode_cell(range.slice(idx + 1)) };
}
/*# if only one arg, it is assumed to be a Range. If 2 args, both are cell addresses */
function encode_range(cs/*:CellAddrSpec|Range*/,ce/*:?CellAddrSpec*/)/*:string*/ {
if(typeof ce === 'undefined' || typeof ce === 'number') {
/*:: if(!(cs instanceof Range)) throw "unreachable"; */
return encode_range(cs.s, cs.e);
}
/*:: if((cs instanceof Range)) throw "unreachable"; */
if(typeof cs !== 'string') cs = encode_cell((cs/*:any*/));
if(typeof ce !== 'string') ce = encode_cell((ce/*:any*/));
/*:: if(typeof cs !== 'string') throw "unreachable"; */
/*:: if(typeof ce !== 'string') throw "unreachable"; */
return cs == ce ? cs : cs + ":" + ce;
}
function fix_range(a1/*:string*/)/*:string*/ {
var s = decode_range(a1);
return "$" + encode_col(s.s.c) + "$" + encode_row(s.s.r) + ":$" + encode_col(s.e.c) + "$" + encode_row(s.e.r);
}
// List of invalid characters needs to be tested further
function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ {
if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name");
if (/[^\w\u4E00-\u9FFF\u3040-\u30FF]/.test(sname)) return "'" + sname.replace(/'/g, "''") + "'";
return sname;
}
function safe_decode_range(range/*:string*/)/*:Range*/ {
var o = {s:{c:0,r:0},e:{c:0,r:0}};
var idx = 0, i = 0, cc = 0;
var len = range.length;
for(idx = 0; i < len; ++i) {
if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
idx = 26*idx + cc;
}
o.s.c = --idx;
for(idx = 0; i < len; ++i) {
if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
idx = 10*idx + cc;
}
o.s.r = --idx;
if(i === len || cc != 10) { o.e.c=o.s.c; o.e.r=o.s.r; return o; }
++i;
for(idx = 0; i != len; ++i) {
if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
idx = 26*idx + cc;
}
o.e.c = --idx;
for(idx = 0; i != len; ++i) {
if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
idx = 10*idx + cc;
}
o.e.r = --idx;
return o;
}
function safe_format_cell(cell/*:Cell*/, v/*:any*/) {
var q = (cell.t == 'd' && v instanceof Date);
if(cell.z != null) try { return (cell.w = SSF_format(cell.z, q ? datenum(v) : v)); } catch(e) { }
try { return (cell.w = SSF_format((cell.XF||{}).numFmtId||(q ? 14 : 0), q ? datenum(v) : v)); } catch(e) { return ''+v; }
}
function format_cell(cell/*:Cell*/, v/*:any*/, o/*:any*/) {
if(cell == null || cell.t == null || cell.t == 'z') return "";
if(cell.w !== undefined) return cell.w;
if(cell.t == 'd' && !cell.z && o && o.dateNF) cell.z = o.dateNF;
if(cell.t == "e") return BErr[cell.v] || cell.v;
if(v == undefined) return safe_format_cell(cell, cell.v);
return safe_format_cell(cell, v);
}
function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ {
var n = opts && opts.sheet ? opts.sheet : "Sheet1";
var sheets = {}; sheets[n] = sheet;
return { SheetNames: [n], Sheets: sheets };
}
function sheet_new(opts) {
var out = {};
var o = opts || {};
if(o.dense) out["!data"] = [];
return out;
}
function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
var o = opts || {};
var dense = _ws ? (_ws["!data"] != null) : o.dense;
if(DENSE != null && dense == null) dense = DENSE;
var ws/*:Worksheet*/ = _ws || ({}/*:any*/);
if(dense && !ws["!data"]) ws["!data"] = [];
var _R = 0, _C = 0;
if(ws && o.origin != null) {
if(typeof o.origin == 'number') _R = o.origin;
else {
var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
_R = _origin.r; _C = _origin.c;
}
}
var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/);
if(ws["!ref"]){
var _range = safe_decode_range(ws['!ref']);
range.s.c = _range.s.c;
range.s.r = _range.s.r;
range.e.c = Math.max(range.e.c, _range.e.c);
range.e.r = Math.max(range.e.r, _range.e.r);
if(_R == -1) range.e.r = _R = (ws["!ref"] ? _range.e.r + 1 : 0);
} else {
range.s.c = range.e.c = range.s.r = range.e.r = 0;
}
var row = [], seen = false;
for(var R = 0; R != data.length; ++R) {
if(!data[R]) continue;
if(!Array.isArray(data[R])) throw new Error("aoa_to_sheet expects an array of arrays");
var __R = _R + R, __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 __C = _C + C;
if(range.s.r > __R) range.s.r = __R;
if(range.s.c > __C) range.s.c = __C;
if(range.e.r < __R) range.e.r = __R;
if(range.e.c < __C) range.e.c = __C;
seen = true;
if(data[R][C] && typeof data[R][C] === 'object' && !Array.isArray(data[R][C]) && !(data[R][C] instanceof Date)) cell = data[R][C];
else {
if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
if(cell.v === null) {
if(cell.f) cell.t = 'n';
else if(o.nullError) { cell.t = 'e'; cell.v = 0; }
else if(!o.sheetStubs) continue;
else cell.t = 'z';
}
else if(typeof cell.v === 'number') {
if(isFinite(cell.v)) cell.t = 'n';
else if(isNaN(cell.v)) { cell.t = 'e'; cell.v = 0x0F; /* #VALUE! */ }
else { cell.t = 'e'; cell.v = 0x07; /*# DIV/0 */ }
}
else if(typeof cell.v === 'boolean') cell.t = 'b';
else if(cell.v instanceof Date) {
cell.z = o.dateNF || table_fmt[14];
if(!o.UTC) cell.v = local_to_utc(cell.v);
if(o.cellDates) { cell.t = 'd'; cell.w = SSF_format(cell.z, datenum(cell.v, o.date1904)); }
else { cell.t = 'n'; cell.v = datenum(cell.v, o.date1904); cell.w = SSF_format(cell.z, cell.v); }
}
else cell.t = 's';
}
if(dense) {
if(row[__C] && row[__C].z) cell.z = row[__C].z;
row[__C] = cell;
} else {
var cell_ref = encode_col(__C) + __Rstr/*:any*/;
if(ws[cell_ref] && ws[cell_ref].z) cell.z = ws[cell_ref].z;
ws[cell_ref] = cell;
}
}
}
if(seen && range.s.c < 10400000) ws['!ref'] = encode_range(range);
return ws;
}
function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { return sheet_add_aoa(null, data, opts); }

View File

@ -1,109 +1,164 @@
/* [MS-XLSB] 2.5.143 */
function parse_StrRun(data, length) {
return { ich: data.read_shift(2), ifnt: data.read_shift(2) };
function parse_Int32LE(data) {
return data.read_shift(4, 'i');
}
/* [MS-XLSB] 2.1.7.121 */
function parse_RichStr(data, length) {
var start = data.l;
var flags = data.read_shift(1);
var str = parse_XLWideString(data);
var rgsStrRun = [];
var z = { t: str, h: str };
if((flags & 1) !== 0) { /* fRichStr */
/* TODO: formatted string */
var dwSizeStrRun = data.read_shift(4);
for(var i = 0; i != dwSizeStrRun; ++i) rgsStrRun.push(parse_StrRun(data));
z.r = rgsStrRun;
}
else z.r = "<t>" + escapexml(str) + "</t>";
if((flags & 2) !== 0) { /* fExtStr */
/* TODO: phonetic string */
}
data.l = start + length;
return z;
}
function write_RichStr(str, o) {
/* TODO: formatted string */
if(o == null) o = new_buf(5+2*str.t.length);
o.write_shift(1,0);
write_XLWideString(str.t, o);
return o;
}
/* [MS-XLSB] 2.5.9 */
function parse_XLSBCell(data) {
var col = data.read_shift(4);
var iStyleRef = data.read_shift(2);
iStyleRef += data.read_shift(1) <<16;
var fPhShow = data.read_shift(1);
return { c:col, iStyleRef: iStyleRef };
}
function write_XLSBCell(cell, o) {
if(o == null) o = new_buf(8);
o.write_shift(-4, cell.c);
o.write_shift(3, cell.iStyleRef === undefined ? cell.iStyleRef : cell.s);
o.write_shift(1, 0); /* fPhShow */
return o;
}
/* [MS-XLSB] 2.5.21 */
function parse_XLSBCodeName (data, length) { return parse_XLWideString(data, length); }
/* [MS-XLSB] 2.5.166 */
function parse_XLNullableWideString(data) {
var cchCharacters = data.read_shift(4);
return cchCharacters === 0 || cchCharacters === 0xFFFFFFFF ? "" : data.read_shift(cchCharacters, 'dbcs');
}
function write_XLNullableWideString(data, o) {
if(!o) o = new_buf(127);
o.write_shift(4, data.length > 0 ? data.length : 0xFFFFFFFF);
if(data.length > 0) o.write_shift(0, data, 'dbcs');
function write_UInt32LE(x/*:number*/, o) {
if (!o) o = new_buf(4);
o.write_shift(4, x);
return o;
}
/* [MS-XLSB] 2.5.168 */
function parse_XLWideString(data) {
function parse_XLWideString(data/*::, length*/)/*:string*/ {
var cchCharacters = data.read_shift(4);
return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, 'dbcs');
}
function write_XLWideString(data, o) {
if(o == null) o = new_buf(4+2*data.length);
function write_XLWideString(data/*:string*/, o) {
var _null = false; if (o == null) { _null = true; o = new_buf(4 + 2 * data.length); }
o.write_shift(4, data.length);
if(data.length > 0) o.write_shift(0, data, 'dbcs');
if (data.length > 0) o.write_shift(0, data, 'dbcs');
return _null ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.5.91 */
//function parse_LPWideString(data/*::, length*/)/*:string*/ {
// var cchCharacters = data.read_shift(2);
// return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, "utf16le");
//}
/* [MS-XLSB] 2.5.143 */
function parse_StrRun(data) {
return { ich: data.read_shift(2), ifnt: data.read_shift(2) };
}
function write_StrRun(run, o) {
if (!o) o = new_buf(4);
o.write_shift(2, run.ich || 0);
o.write_shift(2, run.ifnt || 0);
return o;
}
/* [MS-XLSB] 2.5.121 */
function parse_RichStr(data, length/*:number*/)/*:XLString*/ {
var start = data.l;
var flags = data.read_shift(1);
var str = parse_XLWideString(data);
var rgsStrRun = [];
var z = ({ t: str, h: str }/*:any*/);
if ((flags & 1) !== 0) { /* fRichStr */
/* TODO: formatted string */
var dwSizeStrRun = data.read_shift(4);
for (var i = 0; i != dwSizeStrRun; ++i) rgsStrRun.push(parse_StrRun(data));
z.r = rgsStrRun;
}
else z.r = [{ ich: 0, ifnt: 0 }];
//if((flags & 2) !== 0) { /* fExtStr */
// /* TODO: phonetic string */
//}
data.l = start + length;
return z;
}
function write_RichStr(str/*:XLString*/, o/*:?Block*/)/*:Block*/ {
/* TODO: formatted string */
var _null = false; if (o == null) { _null = true; o = new_buf(15 + 4 * str.t.length); }
o.write_shift(1, 0);
write_XLWideString(str.t, o);
return _null ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.328 BrtCommentText (RichStr w/1 run) */
var parse_BrtCommentText = parse_RichStr;
function write_BrtCommentText(str/*:XLString*/, o/*:?Block*/)/*:Block*/ {
/* TODO: formatted string */
var _null = false; if (o == null) { _null = true; o = new_buf(23 + 4 * str.t.length); }
o.write_shift(1, 1);
write_XLWideString(str.t, o);
o.write_shift(4, 1);
write_StrRun({ ich: 0, ifnt: 0 }, o);
return _null ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.5.9 */
function parse_XLSBCell(data)/*:any*/ {
var col = data.read_shift(4);
var iStyleRef = data.read_shift(2);
iStyleRef += data.read_shift(1) << 16;
data.l++; //var fPhShow = data.read_shift(1);
return { c: col, iStyleRef: iStyleRef };
}
function write_XLSBCell(cell/*:any*/, o/*:?Block*/) {
if (o == null) o = new_buf(8);
o.write_shift(-4, cell.c);
o.write_shift(3, cell.iStyleRef || cell.s);
o.write_shift(1, 0); /* fPhShow */
return o;
}
/* Short XLSB Cell does not include column */
function parse_XLSBShortCell(data)/*:any*/ {
var iStyleRef = data.read_shift(2);
iStyleRef += data.read_shift(1) <<16;
data.l++; //var fPhShow = data.read_shift(1);
return { c:-1, iStyleRef: iStyleRef };
}
function write_XLSBShortCell(cell/*:any*/, o/*:?Block*/) {
if(o == null) o = new_buf(4);
o.write_shift(3, cell.iStyleRef || cell.s);
o.write_shift(1, 0); /* fPhShow */
return o;
}
/* [MS-XLSB] 2.5.21 */
var parse_XLSBCodeName = parse_XLWideString;
var write_XLSBCodeName = write_XLWideString;
/* [MS-XLSB] 2.5.166 */
function parse_XLNullableWideString(data/*::, length*/)/*:string*/ {
var cchCharacters = data.read_shift(4);
return cchCharacters === 0 || cchCharacters === 0xFFFFFFFF ? "" : data.read_shift(cchCharacters, 'dbcs');
}
function write_XLNullableWideString(data/*:string*/, o) {
var _null = false; if (o == null) { _null = true; o = new_buf(127); }
o.write_shift(4, data.length > 0 ? data.length : 0xFFFFFFFF);
if (data.length > 0) o.write_shift(0, data, 'dbcs');
return _null ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.5.165 */
var parse_XLNameWideString = parse_XLWideString;
//var write_XLNameWideString = write_XLWideString;
/* [MS-XLSB] 2.5.114 */
var parse_RelID = parse_XLNullableWideString;
var write_RelID = write_XLNullableWideString;
/* [MS-XLSB] 2.5.122 */
/* [MS-XLS] 2.5.217 */
function parse_RkNumber(data) {
var b = data.slice(data.l, data.l+4);
var fX100 = b[0] & 1, fInt = b[0] & 2;
data.l+=4;
b[0] &= 0xFC; // b[0] &= ~3;
var RK = fInt === 0 ? __double([0,0,0,0,b[0],b[1],b[2],b[3]],0) : __readInt32LE(b,0)>>2;
return fX100 ? RK/100 : RK;
/* [MS-XLS] 2.5.217 ; [MS-XLSB] 2.5.122 */
function parse_RkNumber(data)/*:number*/ {
var b = data.slice(data.l, data.l + 4);
var fX100 = (b[0] & 1), fInt = (b[0] & 2);
data.l += 4;
var RK = fInt === 0 ? __double([0, 0, 0, 0, (b[0] & 0xFC), b[1], b[2], b[3]], 0) : __readInt32LE(b, 0) >> 2;
return fX100 ? (RK / 100) : RK;
}
function write_RkNumber(data/*:number*/, o) {
if (o == null) o = new_buf(4);
var fX100 = 0, fInt = 0, d100 = data * 100;
if ((data == (data | 0)) && (data >= -(1 << 29)) && (data < (1 << 29))) { fInt = 1; }
else if ((d100 == (d100 | 0)) && (d100 >= -(1 << 29)) && (d100 < (1 << 29))) { fInt = 1; fX100 = 1; }
if (fInt) o.write_shift(-4, ((fX100 ? d100 : data) << 2) + (fX100 + 2));
else throw new Error("unsupported RkNumber " + data); // TODO
}
/* [MS-XLSB] 2.5.153 */
function parse_UncheckedRfX(data) {
var cell = {s: {}, e: {}};
/* [MS-XLSB] 2.5.117 RfX */
function parse_RfX(data /*::, length*/)/*:Range*/ {
var cell/*:Range*/ = ({ s: {}, e: {} }/*:any*/);
cell.s.r = data.read_shift(4);
cell.e.r = data.read_shift(4);
cell.s.c = data.read_shift(4);
cell.e.c = data.read_shift(4);
return cell;
}
function write_UncheckedRfX(r, o) {
if(!o) o = new_buf(16);
function write_RfX(r/*:Range*/, o) {
if (!o) o = new_buf(16);
o.write_shift(4, r.s.r);
o.write_shift(4, r.e.r);
o.write_shift(4, r.s.c);
@ -111,46 +166,112 @@ function write_UncheckedRfX(r, o) {
return o;
}
/* [MS-XLSB] 2.5.171 */
/* [MS-XLS] 2.5.342 */
function parse_Xnum(data, length) { return data.read_shift(8, 'f'); }
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, 'f', data); }
/* [MS-XLSB] 2.5.153 UncheckedRfX */
var parse_UncheckedRfX = parse_RfX;
var write_UncheckedRfX = write_RfX;
/* [MS-XLSB] 2.5.198.2 */
var BErr = {
0x00: "#NULL!",
0x07: "#DIV/0!",
0x0F: "#VALUE!",
0x17: "#REF!",
0x1D: "#NAME?",
0x24: "#NUM!",
0x2A: "#N/A",
0x2B: "#GETTING_DATA",
0xFF: "#WTF?"
};
var RBErr = evert_num(BErr);
/* [MS-XLSB] 2.5.155 UncheckedSqRfX */
//function parse_UncheckedSqRfX(data) {
// var cnt = data.read_shift(4);
// var out = [];
// for(var i = 0; i < cnt; ++i) {
// var rng = parse_UncheckedRfX(data);
// out.push(encode_range(rng));
// }
// return out.join(",");
//}
//function write_UncheckedSqRfX(sqrfx/*:string*/) {
// var parts = sqrfx.split(/\s*,\s*/);
// var o = new_buf(4); o.write_shift(4, parts.length);
// var out = [o];
// parts.forEach(function(rng) {
// out.push(write_UncheckedRfX(safe_decode_range(rng)));
// });
// return bconcat(out);
//}
/* [MS-XLSB] 2.4.321 BrtColor */
function parse_BrtColor(data, length) {
/* [MS-XLS] 2.5.342 ; [MS-XLSB] 2.5.171 */
/* TODO: error checking, NaN and Infinity values are not valid Xnum */
function parse_Xnum(data/*::, length*/) {
if(data.length - data.l < 8) throw "XLS Xnum Buffer underflow";
return data.read_shift(8, 'f');
}
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); }
/* [MS-XLSB] 2.4.324 BrtColor */
function parse_BrtColor(data/*::, length*/) {
var out = {};
var d = data.read_shift(1);
out.fValidRGB = d & 1;
out.xColorType = d >>> 1;
out.index = data.read_shift(1);
out.nTintAndShade = data.read_shift(2, 'i');
out.bRed = data.read_shift(1);
out.bGreen = data.read_shift(1);
out.bBlue = data.read_shift(1);
out.bAlpha = data.read_shift(1);
//var fValidRGB = d & 1;
var xColorType = d >>> 1;
var index = data.read_shift(1);
var nTS = data.read_shift(2, 'i');
var bR = data.read_shift(1);
var bG = data.read_shift(1);
var bB = data.read_shift(1);
data.l++; //var bAlpha = data.read_shift(1);
switch (xColorType) {
case 0: out.auto = 1; break;
case 1:
out.index = index;
var icv = XLSIcv[index];
/* automatic pseudo index 81 */
if (icv) out.rgb = rgb2Hex(icv);
break;
case 2:
/* if(!fValidRGB) throw new Error("invalid"); */
out.rgb = rgb2Hex([bR, bG, bB]);
break;
case 3: out.theme = index; break;
}
if (nTS != 0) out.tint = nTS > 0 ? nTS / 32767 : nTS / 32768;
return out;
}
function write_BrtColor(color, o) {
if (!o) o = new_buf(8);
if (!color || color.auto) { o.write_shift(4, 0); o.write_shift(4, 0); return o; }
if (color.index != null) {
o.write_shift(1, 0x02);
o.write_shift(1, color.index);
} else if (color.theme != null) {
o.write_shift(1, 0x06);
o.write_shift(1, color.theme);
} else {
o.write_shift(1, 0x05);
o.write_shift(1, 0);
}
var nTS = color.tint || 0;
if (nTS > 0) nTS *= 32767;
else if (nTS < 0) nTS *= 32768;
o.write_shift(2, nTS);
if (!color.rgb || color.theme != null) {
o.write_shift(2, 0);
o.write_shift(1, 0);
o.write_shift(1, 0);
} else {
var rgb = (color.rgb || 'FFFFFF');
if (typeof rgb == 'number') rgb = ("000000" + rgb.toString(16)).slice(-6);
o.write_shift(1, parseInt(rgb.slice(0, 2), 16));
o.write_shift(1, parseInt(rgb.slice(2, 4), 16));
o.write_shift(1, parseInt(rgb.slice(4, 6), 16));
o.write_shift(1, 0xFF);
}
return o;
}
/* [MS-XLSB] 2.5.52 */
function parse_FontFlags(data, length) {
function parse_FontFlags(data/*::, length, opts*/) {
var d = data.read_shift(1);
data.l++;
var out = {
fItalic: d & 0x2,
fStrikeout: d & 0x8,
fBold: d & 0x01,
fItalic: d & 0x02,
fUnderline: d & 0x04,
fStrikeout: d & 0x08,
fOutline: d & 0x10,
fShadow: d & 0x20,
fCondense: d & 0x40,
@ -158,3 +279,33 @@ function parse_FontFlags(data, length) {
};
return out;
}
function write_FontFlags(font, o) {
if (!o) o = new_buf(2);
var grbit =
(font.italic ? 0x02 : 0) |
(font.strike ? 0x08 : 0) |
(font.outline ? 0x10 : 0) |
(font.shadow ? 0x20 : 0) |
(font.condense ? 0x40 : 0) |
(font.extend ? 0x80 : 0);
o.write_shift(1, grbit);
o.write_shift(1, 0);
return o;
}
/* [MS-OLEDS] 2.3.1 and 2.3.2 */
function parse_ClipboardFormatOrString(o, w/*:number*/)/*:string*/ {
// $FlowIgnore
var ClipFmt = { 2: "BITMAP", 3: "METAFILEPICT", 8: "DIB", 14: "ENHMETAFILE" };
var m/*:number*/ = o.read_shift(4);
switch (m) {
case 0x00000000: return "";
case 0xffffffff: case 0xfffffffe: return ClipFmt[o.read_shift(4)] || "";
}
if (m > 0x190) throw new Error("Unsupported Clipboard: " + m.toString(16));
o.l -= 4;
return o.read_shift(0, w == 1 ? "lpstr" : "lpwstr");
}
function parse_ClipboardFormatOrAnsiString(o) { return parse_ClipboardFormatOrString(o, 1); }
function parse_ClipboardFormatOrUnicodeString(o) { return parse_ClipboardFormatOrString(o, 2); }

View File

@ -1,45 +1,46 @@
/* [MS-OLEPS] 2.2 PropertyType */
{
var VT_EMPTY = 0x0000;
var VT_NULL = 0x0001;
var VT_I2 = 0x0002;
var VT_I4 = 0x0003;
var VT_R4 = 0x0004;
var VT_R8 = 0x0005;
var VT_CY = 0x0006;
var VT_DATE = 0x0007;
var VT_BSTR = 0x0008;
var VT_ERROR = 0x000A;
var VT_BOOL = 0x000B;
var VT_VARIANT = 0x000C;
var VT_DECIMAL = 0x000E;
var VT_I1 = 0x0010;
var VT_UI1 = 0x0011;
var VT_UI2 = 0x0012;
var VT_UI4 = 0x0013;
var VT_I8 = 0x0014;
var VT_UI8 = 0x0015;
var VT_INT = 0x0016;
var VT_UINT = 0x0017;
var VT_LPSTR = 0x001E;
var VT_LPWSTR = 0x001F;
var VT_FILETIME = 0x0040;
var VT_BLOB = 0x0041;
var VT_STREAM = 0x0042;
var VT_STORAGE = 0x0043;
var VT_STREAMED_Object = 0x0044;
var VT_STORED_Object = 0x0045;
var VT_BLOB_Object = 0x0046;
var VT_CF = 0x0047;
var VT_CLSID = 0x0048;
var VT_VERSIONED_STREAM = 0x0049;
var VT_VECTOR = 0x1000;
var VT_ARRAY = 0x2000;
// Note: some tree shakers cannot handle VT_VECTOR | $CONST, hence extra vars
//var VT_EMPTY = 0x0000;
//var VT_NULL = 0x0001;
var VT_I2 = 0x0002;
var VT_I4 = 0x0003;
//var VT_R4 = 0x0004;
//var VT_R8 = 0x0005;
//var VT_CY = 0x0006;
//var VT_DATE = 0x0007;
//var VT_BSTR = 0x0008;
//var VT_ERROR = 0x000A;
var VT_BOOL = 0x000B;
var VT_VARIANT = 0x000C;
//var VT_DECIMAL = 0x000E;
//var VT_I1 = 0x0010;
//var VT_UI1 = 0x0011;
//var VT_UI2 = 0x0012;
var VT_UI4 = 0x0013;
//var VT_I8 = 0x0014;
//var VT_UI8 = 0x0015;
//var VT_INT = 0x0016;
//var VT_UINT = 0x0017;
//var VT_LPSTR = 0x001E;
//var VT_LPWSTR = 0x001F;
var VT_FILETIME = 0x0040;
var VT_BLOB = 0x0041;
//var VT_STREAM = 0x0042;
//var VT_STORAGE = 0x0043;
//var VT_STREAMED_Object = 0x0044;
//var VT_STORED_Object = 0x0045;
//var VT_BLOB_Object = 0x0046;
var VT_CF = 0x0047;
//var VT_CLSID = 0x0048;
//var VT_VERSIONED_STREAM = 0x0049;
//var VT_VECTOR = 0x1000;
var VT_VECTOR_VARIANT = 0x100C;
var VT_VECTOR_LPSTR = 0x101E;
//var VT_ARRAY = 0x2000;
var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString
var VT_CUSTOM = [VT_STRING, VT_USTR];
}
var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString
var VT_CUSTOM = [VT_STRING, VT_USTR];
/* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */
var DocSummaryPIDDSI = {
@ -53,21 +54,26 @@ var DocSummaryPIDDSI = {
0x08: { n: 'NoteCount', t: VT_I4 },
0x09: { n: 'HiddenCount', t: VT_I4 },
0x0a: { n: 'MultimediaClipCount', t: VT_I4 },
0x0b: { n: 'Scale', t: VT_BOOL },
0x0c: { n: 'HeadingPair', t: VT_VECTOR | VT_VARIANT },
0x0d: { n: 'DocParts', t: VT_VECTOR | VT_LPSTR },
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: 'LinksDirty', t: VT_BOOL },
0x10: { n: 'LinksUpToDate', t: VT_BOOL },
0x11: { n: 'CharacterCount', t: VT_I4 },
0x13: { n: 'SharedDoc', t: VT_BOOL },
0x16: { n: 'HLinksChanged', 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: {}
0xFF: {},
/* [MS-OLEPS] 2.18 */
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 */
@ -89,23 +95,15 @@ var SummaryPIDSI = {
0x0F: { n: 'WordCount', t: VT_I4 },
0x10: { n: 'CharCount', t: VT_I4 },
0x11: { n: 'Thumbnail', t: VT_CF },
0x12: { n: 'ApplicationName', t: VT_LPSTR },
0x13: { n: 'DocumentSecurity', t: VT_I4 },
0xFF: {}
};
/* [MS-OLEPS] 2.18 */
var SpecialProperties = {
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: {}
};
(function() {
for(var y in SpecialProperties) if(SpecialProperties.hasOwnProperty(y))
DocSummaryPIDDSI[y] = SummaryPIDSI[y] = SpecialProperties[y];
})();
/* [MS-XLS] 2.4.63 Country/Region codes */
var CountryEnum = {
0x0001: "US", // United States
@ -183,10 +181,11 @@ var XLSFillPattern = [
'gray0625'
];
function rgbify(arr) { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); }
function rgbify(arr/*:Array<number>*/)/*:Array<[number, number, number]>*/ { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); }
/* [MS-XLS] 2.5.161 */
var XLSIcv = rgbify([
/* [MS-XLSB] 2.5.75 Icv */
var _XLSIcv = /*#__PURE__*/ rgbify([
/* Color Constants */
0x000000,
0xFFFFFF,
@ -197,7 +196,7 @@ var XLSIcv = rgbify([
0xFF00FF,
0x00FFFF,
/* Defaults */
/* Overridable Defaults */
0x000000,
0xFFFFFF,
0xFF0000,
@ -258,8 +257,67 @@ var XLSIcv = rgbify([
0x333399,
0x333333,
/* Sheet */
0xFFFFFF,
0x000000
/* Other entries to appease BIFF8/12 */
0x000000, /* 0x40 icvForeground ?? */
0xFFFFFF, /* 0x41 icvBackground ?? */
0x000000, /* 0x42 icvFrame ?? */
0x000000, /* 0x43 icv3D ?? */
0x000000, /* 0x44 icv3DText ?? */
0x000000, /* 0x45 icv3DHilite ?? */
0x000000, /* 0x46 icv3DShadow ?? */
0x000000, /* 0x47 icvHilite ?? */
0x000000, /* 0x48 icvCtlText ?? */
0x000000, /* 0x49 icvCtlScrl ?? */
0x000000, /* 0x4A icvCtlInv ?? */
0x000000, /* 0x4B icvCtlBody ?? */
0x000000, /* 0x4C icvCtlFrame ?? */
0x000000, /* 0x4D icvCtlFore ?? */
0x000000, /* 0x4E icvCtlBack ?? */
0x000000, /* 0x4F icvCtlNeutral */
0x000000, /* 0x50 icvInfoBk ?? */
0x000000 /* 0x51 icvInfoText ?? */
]);
var XLSIcv = /*#__PURE__*/dup(_XLSIcv);
/* [MS-XLSB] 2.5.97.2 */
var BErr = {
0x00: "#NULL!",
0x07: "#DIV/0!",
0x0F: "#VALUE!",
0x17: "#REF!",
0x1D: "#NAME?",
0x24: "#NUM!",
0x2A: "#N/A",
0x2B: "#GETTING_DATA",
0xFF: "#WTF?"
};
//var RBErr = evert_num(BErr);
var RBErr = {
"#NULL!": 0x00,
"#DIV/0!": 0x07,
"#VALUE!": 0x0F,
"#REF!": 0x17,
"#NAME?": 0x1D,
"#NUM!": 0x24,
"#N/A": 0x2A,
"#GETTING_DATA": 0x2B,
"#WTF?": 0xFF
};
var XLSLblBuiltIn = [
"_xlnm.Consolidate_Area",
"_xlnm.Auto_Open",
"_xlnm.Auto_Close",
"_xlnm.Extract",
"_xlnm.Database",
"_xlnm.Criteria",
"_xlnm.Print_Area",
"_xlnm.Print_Titles",
"_xlnm.Recorder",
"_xlnm.Data_Form",
"_xlnm.Auto_Activate",
"_xlnm.Auto_Deactivate",
"_xlnm.Sheet_Title",
"_xlnm._FilterDatabase"
];

View File

@ -1,29 +1,42 @@
/* Parts enumerated in OPC spec, MS-XLSB and MS-XLSX */
/* 12.3 Part Summary <SpreadsheetML> */
/* 14.2 Part Summary <DrawingML> */
/* [MS-XLSX] 2.1 Part Enumerations */
/* [MS-XLSB] 2.1.7 Part Enumeration */
var ct2type = {
/* [MS-XLSX] 2.1 Part Enumerations ; [MS-XLSB] 2.1.7 Part Enumeration */
var ct2type/*{[string]:string}*/ = ({
/* Workbook */
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": "workbooks",
"application/vnd.ms-excel.sheet.macroEnabled.main+xml": "workbooks",
"application/vnd.ms-excel.sheet.binary.macroEnabled.main": "workbooks",
"application/vnd.ms-excel.addin.macroEnabled.main+xml": "workbooks",
"application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml": "workbooks",
/* Worksheet */
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml": "sheets",
"application/vnd.ms-excel.worksheet": "sheets",
"application/vnd.ms-excel.binIndexWs": "TODO", /* Binary Index */
/* Chartsheet */
"application/vnd.ms-excel.chartsheet": "TODO",
"application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml": "TODO",
/* Dialogsheet */
"application/vnd.ms-excel.dialogsheet": "TODO",
"application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml": "TODO",
"application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml": "charts",
"application/vnd.ms-excel.chartsheet": "charts",
/* Macrosheet */
"application/vnd.ms-excel.macrosheet": "TODO",
"application/vnd.ms-excel.macrosheet+xml": "TODO",
"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",
@ -31,15 +44,34 @@ var ct2type = {
/* Custom Data Properties */
"application/vnd.openxmlformats-officedocument.customXmlProperties+xml": "TODO",
"application/vnd.openxmlformats-officedocument.spreadsheetml.customProperty": "TODO",
/* Comments */
"application/vnd.ms-excel.comments": "comments",
"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": "comments",
"application/vnd.ms-excel.comments": "comments",
"application/vnd.ms-excel.threadedcomments+xml": "threadedcomments",
"application/vnd.ms-excel.person+xml": "people",
/* Metadata (Stock/Geography and Dynamic Array) */
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml": "metadata",
"application/vnd.ms-excel.sheetMetadata": "metadata",
/* PivotTable */
"application/vnd.ms-excel.pivotTable": "TODO",
"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml": "TODO",
/* Chart Objects */
"application/vnd.openxmlformats-officedocument.drawingml.chart+xml": "TODO",
/* Chart Colors */
"application/vnd.ms-office.chartcolorstyle+xml": "TODO",
/* Chart Style */
"application/vnd.ms-office.chartstyle+xml": "TODO",
/* Chart Advanced */
"application/vnd.ms-office.chartex+xml": "TODO",
/* Calculation Chain */
"application/vnd.ms-excel.calcChain": "calcchains",
"application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains",
@ -59,12 +91,8 @@ var ct2type = {
"application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml": "TODO",
/* External Links */
"application/vnd.ms-excel.externalLink": "TODO",
"application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml": "TODO",
/* Metadata */
"application/vnd.ms-excel.sheetMetadata": "TODO",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml": "TODO",
"application/vnd.ms-excel.externalLink": "links",
"application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml": "links",
/* PivotCache */
"application/vnd.ms-excel.pivotCacheDefinition": "TODO",
@ -104,13 +132,16 @@ var ct2type = {
/* Themes */
"application/vnd.openxmlformats-officedocument.theme+xml": "themes",
/* Theme Override */
"application/vnd.openxmlformats-officedocument.themeOverride+xml": "TODO",
/* Timeline */
"application/vnd.ms-excel.Timeline+xml": "TODO", /* verify */
"application/vnd.ms-excel.TimelineCache+xml": "TODO", /* verify */
/* VBA */
"application/vnd.ms-office.vbaProject": "vba",
"application/vnd.ms-office.vbaProjectSignature": "vba",
"application/vnd.ms-office.vbaProjectSignature": "TODO",
/* Volatile Dependencies */
"application/vnd.ms-office.volatileDependencies": "TODO",
@ -126,8 +157,7 @@ var ct2type = {
"application/vnd.ms-excel.Survey+xml": "TODO",
/* Drawing */
"application/vnd.openxmlformats-officedocument.drawing+xml": "TODO",
"application/vnd.openxmlformats-officedocument.drawingml.chart+xml": "TODO",
"application/vnd.openxmlformats-officedocument.drawing+xml": "drawings",
"application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml": "TODO",
"application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml": "TODO",
"application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml": "TODO",
@ -140,54 +170,75 @@ var ct2type = {
"application/vnd.openxmlformats-package.relationships+xml": "rels",
"application/vnd.openxmlformats-officedocument.oleObject": "TODO",
/* Image */
"image/png": "TODO",
"sheet": "js"
}/*:any*/);
var CT_LIST = {
workbooks: {
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
xlsm: "application/vnd.ms-excel.sheet.macroEnabled.main+xml",
xlsb: "application/vnd.ms-excel.sheet.binary.macroEnabled.main",
xlam: "application/vnd.ms-excel.addin.macroEnabled.main+xml",
xltx: "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
},
strs: { /* Shared Strings */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
xlsb: "application/vnd.ms-excel.sharedStrings"
},
comments: { /* Comments */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
xlsb: "application/vnd.ms-excel.comments"
},
sheets: { /* Worksheet */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
xlsb: "application/vnd.ms-excel.worksheet"
},
charts: { /* Chartsheet */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml",
xlsb: "application/vnd.ms-excel.chartsheet"
},
dialogs: { /* Dialogsheet */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml",
xlsb: "application/vnd.ms-excel.dialogsheet"
},
macros: { /* Macrosheet (Excel 4.0 Macros) */
xlsx: "application/vnd.ms-excel.macrosheet+xml",
xlsb: "application/vnd.ms-excel.macrosheet"
},
metadata: { /* Metadata (Stock/Geography and Dynamic Array) */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml",
xlsb: "application/vnd.ms-excel.sheetMetadata"
},
styles: { /* Styles */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
xlsb: "application/vnd.ms-excel.styles"
}
};
var CT_LIST = (function(){
var o = {
workbooks: {
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
xlsm: "application/vnd.ms-excel.sheet.macroEnabled.main+xml",
xlsb: "application/vnd.ms-excel.sheet.binary.macroEnabled.main",
xltx: "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
},
strs: { /* Shared Strings */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
xlsb: "application/vnd.ms-excel.sharedStrings"
},
sheets: {
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
xlsb: "application/vnd.ms-excel.worksheet"
},
styles: {/* Styles */
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
xlsb: "application/vnd.ms-excel.styles"
}
};
keys(o).forEach(function(k) { if(!o[k].xlsm) o[k].xlsm = o[k].xlsx; });
keys(o).forEach(function(k){ keys(o[k]).forEach(function(v) { ct2type[o[k][v]] = k; }); });
return o;
})();
function new_ct()/*:any*/ {
return ({
workbooks:[], sheets:[], charts:[], dialogs:[], macros:[],
rels:[], strs:[], comments:[], threadedcomments:[], links:[],
coreprops:[], extprops:[], custprops:[], themes:[], styles:[],
calcchains:[], vba: [], drawings: [], metadata: [], people:[],
TODO:[], xmlns: "" }/*:any*/);
}
var type2ct = evert_arr(ct2type);
XMLNS.CT = 'http://schemas.openxmlformats.org/package/2006/content-types';
function parse_ct(data, opts) {
function parse_ct(data/*:?string*/) {
var ct = new_ct();
if(!data || !data.match) return ct;
var ctext = {};
if(!data || !data.match) return data;
var ct = { workbooks: [], sheets: [], calcchains: [], themes: [], styles: [],
coreprops: [], extprops: [], custprops: [], strs:[], comments: [], vba: [],
TODO:[], rels:[], xmlns: "" };
(data.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(y[0].replace(nsregex,"<")) {
case '<?xml': break;
case '<Types': ct.xmlns = y['xmlns' + (y[0].match(/<(\w+):/)||["",""])[1] ]; break;
case '<Default': ctext[y.Extension] = 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);
else if(opts.WTF) console.error(y);
break;
}
});
@ -200,42 +251,60 @@ function parse_ct(data, opts) {
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'],
['rels', type2ct.rels[0]]
].map(function(x) {
return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
});
var o/*:Array<string>*/ = [], v;
function write_ct(ct, opts) {
var o = [], 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) {
if(ct[w] && ct[w].length > 0) {
v = ct[w][0];
o[o.length] = (writextag('Override', null, {
'PartName': (v[0] == '/' ? "":"/") + v,
'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
'ContentType': CT_LIST[w][opts.bookType] || CT_LIST[w]['xlsx']
}));
}
};
/* book type-specific */
var f2 = function(w) {
ct[w].forEach(function(v) {
(ct[w]||[]).forEach(function(v) {
o[o.length] = (writextag('Override', null, {
'PartName': (v[0] == '/' ? "":"/") + v,
'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
'ContentType': CT_LIST[w][opts.bookType] || CT_LIST[w]['xlsx']
}));
});
};
/* standard type */
var f3 = function(t) {
(ct[t]||[]).forEach(function(v) {
o[o.length] = (writextag('Override', null, {
@ -244,11 +313,19 @@ function write_ct(ct, opts) {
}));
});
};
f1('workbooks');
f2('sheets');
f2('charts');
f3('themes');
['strs', 'styles'].forEach(f1);
['coreprops', 'extprops', 'custprops'].forEach(f3);
if(o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
f3('vba');
f3('comments');
f3('threadedcomments');
f3('drawings');
f2('metadata');
f3('people');
if(!raw && o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}

View File

@ -1,38 +1,59 @@
/* 9.3.2 OPC Relationships Markup */
var RELS = {
/* 9.3 Relationships */
var RELS = ({
WB: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
SHEET: "http://sheetjs.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
};
SHEET: "http://sheetjs.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
HLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
VML: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing",
XPATH: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath",
XMISS: "http://schemas.microsoft.com/office/2006/relationships/xlExternalLinkPath/xlPathMissing",
XLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLink",
CXML: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml",
CXMLP: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXmlProps",
CMNT: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",
CORE_PROPS: "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
EXT_PROPS: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties',
CUST_PROPS: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties',
SST: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings",
STY: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
THEME: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
CHART: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
CHARTEX: "http://schemas.microsoft.com/office/2014/relationships/chartEx",
CS: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet",
WS: [
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
"http://purl.oclc.org/ooxml/officeDocument/relationships/worksheet"
],
DS: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet",
MS: "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet",
IMG: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
DRAW: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing",
XLMETA: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata",
TCMNT: "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment",
PEOPLE: "http://schemas.microsoft.com/office/2017/10/relationships/person",
CONN: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/connections",
VBA: "http://schemas.microsoft.com/office/2006/relationships/vbaProject"
}/*:any*/);
function parse_rels(data, currentFilePath) {
if (!data) return data;
/* 9.3.3 Representing Relationships */
function get_rels_path(file/*:string*/)/*:string*/ {
var n = file.lastIndexOf("/");
return file.slice(0,n+1) + '_rels/' + file.slice(n+1) + ".rels";
}
function parse_rels(data/*:?string*/, currentFilePath/*:string*/) {
var rels = {"!id":{}};
if (!data) return rels;
if (currentFilePath.charAt(0) !== '/') {
currentFilePath = '/'+currentFilePath;
}
var rels = {};
var hash = {};
var resolveRelativePathIntoAbsolute = function (to) {
var toksFrom = currentFilePath.split('/');
toksFrom.pop(); // folder path
var toksTo = to.split('/');
var reversed = [];
while (toksTo.length !== 0) {
var tokTo = toksTo.shift();
if (tokTo === '..') {
toksFrom.pop();
} else if (tokTo !== '.') {
toksFrom.push(tokTo);
}
}
return toksFrom.join('/');
};
data.match(tagregex).forEach(function(x) {
(data.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
/* 9.3.2.2 OPC_Relationships */
if (y[0] === '<Relationship') {
var rel = {}; rel.Type = y.Type; rel.Target = y.Target; rel.Id = y.Id; rel.TargetMode = y.TargetMode;
var canonictarget = y.TargetMode === 'External' ? y.Target : resolveRelativePathIntoAbsolute(y.Target);
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;
}
@ -41,21 +62,33 @@ function parse_rels(data, currentFilePath) {
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) {
var o = [];
o[o.length] = (XML_HEADER);
o[o.length] = (RELS_ROOT);
keys(rels['!id']).forEach(function(rid) { var rel = rels['!id'][rid];
o[o.length] = (writextag('Relationship', null, rel));
function write_rels(rels)/*:string*/ {
var o = [XML_HEADER, writextag('Relationships', null, {
//'xmlns:ns0': XMLNS.RELS,
'xmlns': XMLNS.RELS
})];
keys(rels['!id']).forEach(function(rid) {
o[o.length] = (writextag('Relationship', null, rels['!id'][rid]));
});
if(o.length>2){ o[o.length] = ('</Relationships>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}
function add_rels(rels, rId/*:number*/, f, type, relobj, targetmode/*:?string*/)/*:number*/ {
if(!relobj) relobj = {};
if(!rels['!id']) rels['!id'] = {};
if(!rels['!idx']) rels['!idx'] = 1;
if(rId < 0) for(rId = rels['!idx']; rels['!id']['rId' + rId]; ++rId){/* empty */}
rels['!idx'] = rId + 1;
relobj.Id = 'rId' + rId;
relobj.Type = type;
relobj.Target = f;
if(targetmode) relobj.TargetMode = targetmode;
else if([RELS.HLINK, RELS.XPATH, RELS.XMISS].indexOf(relobj.Type) > -1) relobj.TargetMode = "External";
if(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId);
rels['!id'][relobj.Id] = relobj;
rels[('/' + relobj.Target).replace("//","/")] = relobj;
return rId;
}

61
bits/32_odmanrdf.js Normal file
View File

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

View File

@ -1,6 +1,6 @@
/* ECMA-376 Part II 11.1 Core Properties Part */
/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
var CORE_PROPS = [
var CORE_PROPS/*:Array<Array<string> >*/ = [
["cp:category", "Category"],
["cp:contentStatus", "ContentStatus"],
["cp:keywords", "Keywords"],
@ -18,55 +18,51 @@ var CORE_PROPS = [
["dcterms:modified", "ModifiedDate", 'date']
];
XMLNS.CORE_PROPS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
RELS.CORE_PROPS = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';
var CORE_PROPS_REGEX = (function() {
var r = new Array(CORE_PROPS.length);
for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i];
var g = "(?:"+ f[0].substr(0,f[0].indexOf(":")) +":)"+ f[0].substr(f[0].indexOf(":")+1);
r[i] = new RegExp("<" + g + "[^>]*>(.*)<\/" + g + ">");
}
return r;
})();
function parse_core_props(data) {
var p = {};
data = utf8read(data);
for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
if(cur != null && cur.length > 0) p[f[1]] = cur[1];
if(f[2] === 'date' && p[f[1]]) p[f[1]] = new Date(p[f[1]]);
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]]);
}
return p;
}
var CORE_PROPS_XML_ROOT = writextag('cp:coreProperties', null, {
//'xmlns': XMLNS.CORE_PROPS,
'xmlns:cp': XMLNS.CORE_PROPS,
'xmlns:dc': XMLNS.dc,
'xmlns:dcterms': XMLNS.dcterms,
'xmlns:dcmitype': XMLNS.dcmitype,
'xmlns:xsi': XMLNS.xsi
});
function cp_doit(f, g, h, o, p) {
if(p[f] != null || g == null || g === "") return;
p[f] = g;
g = escapexml(g);
o[o.length] = (h ? writextag(f,g,h) : writetag(f,g));
}
function write_core_props(cp, opts) {
var o = [XML_HEADER, CORE_PROPS_XML_ROOT], p = {};
if(!cp) return o.join("");
function write_core_props(cp, _opts) {
var opts = _opts || {};
var o = [XML_HEADER, writextag('cp:coreProperties', null, {
//'xmlns': XMLNS.CORE_PROPS,
'xmlns:cp': XMLNS.CORE_PROPS,
'xmlns:dc': XMLNS.dc,
'xmlns:dcterms': XMLNS.dcterms,
'xmlns:dcmitype': XMLNS.dcmitype,
'xmlns:xsi': XMLNS.xsi
})], p = {};
if(!cp && !opts.Props) return o.join("");
if(cp) {
if(cp.CreatedDate != null) cp_doit("dcterms:created", typeof cp.CreatedDate === "string" ? cp.CreatedDate : write_w3cdtf(cp.CreatedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
if(cp.ModifiedDate != null) cp_doit("dcterms:modified", typeof cp.ModifiedDate === "string" ? cp.ModifiedDate : write_w3cdtf(cp.ModifiedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
}
if(cp.CreatedDate != null) cp_doit("dcterms:created", typeof cp.CreatedDate === "string" ? cp.CreatedDate : write_w3cdtf(cp.CreatedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
if(cp.ModifiedDate != null) cp_doit("dcterms:modified", typeof cp.ModifiedDate === "string" ? cp.ModifiedDate : write_w3cdtf(cp.ModifiedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
for(var i = 0; i != CORE_PROPS.length; ++i) { var f = CORE_PROPS[i]; cp_doit(f[0], cp[f[1]], null, o, p); }
for(var i = 0; i != CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i];
var v = opts.Props && opts.Props[f[1]] != null ? opts.Props[f[1]] : cp ? cp[f[1]] : null;
if(v === true) v = "1";
else if(v === false) v = "0";
else if(typeof v == "number") v = String(v);
if(v != null) cp_doit(f[0], v, null, o, p);
}
if(o.length>2){ o[o.length] = ('</cp:coreProperties>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}

View File

@ -1,6 +1,6 @@
/* 15.2.12.3 Extended File Properties Part */
/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
var EXT_PROPS = [
var EXT_PROPS/*:Array<Array<string> >*/ = [
["Application", "Application", "string"],
["AppVersion", "AppVersion", "string"],
["Company", "Company", "string"],
@ -14,55 +14,94 @@ var EXT_PROPS = [
["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",
"Chartsheets", "ChartNames"
];
function load_props_pairs(HP/*:string|Array<Array<any>>*/, TOP, props, opts) {
var v = [];
if(typeof HP == "string") v = parseVector(HP, opts);
else for(var j = 0; j < HP.length; ++j) v = v.concat(HP[j].map(function(hp) { return {v:hp}; }));
var parts = (typeof TOP == "string") ? parseVector(TOP, opts).map(function (x) { return x.v; }) : TOP;
var idx = 0, len = 0;
if(parts.length > 0) for(var i = 0; i !== v.length; i += 2) {
len = +(v[i+1].v);
switch(v[i].v) {
case "Worksheets":
case "工作表":
case "Листы":
case "أوراق العمل":
case "ワークシート":
case "גליונות עבודה":
case "Arbeitsblätter":
case "Çalışma Sayfaları":
case "Feuilles de calcul":
case "Fogli di lavoro":
case "Folhas de cálculo":
case "Planilhas":
case "Regneark":
case "Hojas de cálculo":
case "Werkbladen":
props.Worksheets = len;
props.SheetNames = parts.slice(idx, idx + len);
break;
function parse_ext_props(data, p) {
case "Named Ranges":
case "Rangos con nombre":
case "名前付き一覧":
case "Benannte Bereiche":
case "Navngivne områder":
props.NamedRanges = len;
props.DefinedNames = parts.slice(idx, idx + len);
break;
case "Charts":
case "Diagramme":
props.Chartsheets = len;
props.ChartNames = parts.slice(idx, idx + len);
break;
}
idx += len;
}
}
function parse_ext_props(data, p, opts) {
var q = {}; if(!p) p = {};
data = utf8read(data);
EXT_PROPS.forEach(function(f) {
var xml = (str_match_xml_ns(data, f[0])||[])[1];
switch(f[2]) {
case "string": p[f[1]] = (data.match(matchtag(f[0]))||[])[1]; break;
case "bool": p[f[1]] = (data.match(matchtag(f[0]))||[])[1] === "true"; break;
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] + "[^>]*>(.*)<\/" + f[0] + ">"));
var cur = str_match_xml(data, f[0]);
if(cur && cur.length > 0) q[f[1]] = cur[1];
break;
}
});
if(q.HeadingPairs && q.TitlesOfParts) {
var v = parseVector(q.HeadingPairs);
var j = 0, widx = 0;
for(var i = 0; i !== v.length; ++i) {
switch(v[i].v) {
case "Worksheets": widx = j; p.Worksheets = +(v[++i].v); break;
case "Named Ranges": ++i; break; // TODO: Handle Named Ranges
}
}
var parts = parseVector(q.TitlesOfParts).map(function(x) { return utf8read(x.v); });
p.SheetNames = parts.slice(widx, widx + p.Worksheets);
}
if(q.HeadingPairs && q.TitlesOfParts) load_props_pairs(q.HeadingPairs, q.TitlesOfParts, 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) {
var o = [], p = {}, W = writextag;
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;
var v;
switch(f[2]) {
case 'string': v = cp[f[1]]; break;
case 'string': v = escapexml(String(cp[f[1]])); break;
case 'bool': v = cp[f[1]] ? 'true' : 'false'; break;
}
if(v !== undefined) o[o.length] = (W(f[0], v));
@ -70,7 +109,7 @@ function write_ext_props(cp, opts) {
/* TODO: HeadingPairs, TitlesOfParts */
o[o.length] = (W('HeadingPairs', W('vt:vector', W('vt:variant', '<vt:lpstr>Worksheets</vt:lpstr>')+W('vt:variant', W('vt:i4', String(cp.Worksheets))), {size:2, baseType:"variant"})));
o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + s + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + escapexml(s) + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
if(o.length>2){ o[o.length] = ('</Properties>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}

View File

@ -1,31 +1,25 @@
/* 15.2.12.2 Custom File Properties Part */
XMLNS.CUST_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
RELS.CUST_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties';
var custregex = /<[^>]+>[^<]*/g;
function parse_cust_props(data, opts) {
var p = {}, name;
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':
if(y.xmlns !== XMLNS.CUST_PROPS) throw "unrecognized xmlns " + y.xmlns;
if(y.xmlnsvt && y.xmlnsvt !== XMLNS.vt) throw "unrecognized vt " + y.xmlnsvt;
break;
case '<property': name = y.name; break;
case '<Properties': break;
case '<property': name = unescapexml(y.name); break;
case '</property>': name = null; break;
default: if (x.indexOf('<vt:') === 0) {
var toks = x.split('>');
var type = toks[0].substring(4), text = toks[1];
var type = toks[0].slice(4), text = toks[1];
/* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */
switch(type) {
case 'lpstr': case 'lpwstr': case 'bstr': case 'lpwstr':
case 'lpstr': case 'bstr': case 'lpwstr':
p[name] = unescapexml(text);
break;
case 'bool':
p[name] = parsexmlbool(text, '<vt:bool>');
p[name] = parsexmlbool(text);
break;
case 'i1': case 'i2': case 'i4': case 'i8': case 'int': case 'uint':
p[name] = parseInt(text, 10);
@ -34,35 +28,34 @@ function parse_cust_props(data, opts) {
p[name] = parseFloat(text);
break;
case 'filetime': case 'date':
p[name] = new Date(text);
p[name] = parseDate(text);
break;
case 'cy': case 'error':
p[name] = unescapexml(text);
break;
default:
if(typeof console !== 'undefined') console.warn('Unexpected', x, type, toks);
if(type.slice(-1) == '/') break;
if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks);
}
} else if(x.substr(0,2) === "</") {
} else if(x.slice(0,2) === "</") {/* empty */
} else if(opts.WTF) throw new Error(x);
}
}
return p;
}
var CUST_PROPS_XML_ROOT = writextag('Properties', null, {
'xmlns': XMLNS.CUST_PROPS,
'xmlns:vt': XMLNS.vt
});
function write_cust_props(cp, opts) {
var o = [XML_HEADER, CUST_PROPS_XML_ROOT];
function write_cust_props(cp/*::, opts*/)/*:string*/ {
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;
o[o.length] = (writextag('property', write_vt(cp[k]), {
o[o.length] = (writextag('property', write_vt(cp[k], true), {
'fmtid': '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}',
'pid': pid,
'name': k
'name': escapexml(k)
}));
});
if(o.length>2){ o[o.length] = '</Properties>'; o[1]=o[1].replace("/>",">"); }

View File

@ -1,8 +1,92 @@
function xlml_set_prop(Props, tag, val) {
/* TODO: Normalize the properties */
switch(tag) {
case 'Description': tag = 'Comments'; break;
}
/* Common Name -> XLML Name */
var XLMLDocPropsMap = {
Title: 'Title',
Subject: 'Subject',
Author: 'Author',
Keywords: 'Keywords',
Comments: 'Description',
LastAuthor: 'LastAuthor',
RevNumber: 'Revision',
Application: 'AppName',
/* TotalTime: 'TotalTime', */
LastPrinted: 'LastPrinted',
CreatedDate: 'Created',
ModifiedDate: 'LastSaved',
/* Pages */
/* Words */
/* Characters */
Category: 'Category',
/* PresentationFormat */
Manager: 'Manager',
Company: 'Company',
/* Guid */
/* HyperlinkBase */
/* Bytes */
/* Lines */
/* Paragraphs */
/* CharactersWithSpaces */
AppVersion: 'Version',
ContentStatus: 'ContentStatus', /* NOTE: missing from schema */
Identifier: 'Identifier', /* NOTE: missing from schema */
Language: 'Language' /* NOTE: missing from schema */
};
var evert_XLMLDPM;
function xlml_set_prop(Props, tag/*:string*/, val) {
if(!evert_XLMLDPM) evert_XLMLDPM = evert(XLMLDocPropsMap);
tag = evert_XLMLDPM[tag] || tag;
Props[tag] = val;
}
function xlml_write_docprops(Props, opts) {
var o/*:Array<string>*/ = [];
keys(XLMLDocPropsMap).map(function(m) {
for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i];
for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i];
throw m;
}).forEach(function(p) {
if(Props[p[1]] == null) return;
var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]];
switch(p[2]) {
case 'date': m = new Date(m).toISOString().replace(/\.\d*Z/,"Z"); break;
}
if(typeof m == 'number') m = String(m);
else if(m === true || m === false) { m = m ? "1" : "0"; }
else if(m instanceof Date) m = new Date(m).toISOString().replace(/\.\d*Z/,"");
o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m));
});
return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o });
}
function xlml_write_custprops(Props, Custprops/*::, opts*/) {
var BLACKLIST = ["Worksheets","SheetNames"];
var T = 'CustomDocumentProperties';
var o/*:Array<string>*/ = [];
if(Props) keys(Props).forEach(function(k) {
/*:: if(!Props) return; */
if(!Object.prototype.hasOwnProperty.call(Props, k)) return;
for(var i = 0; i < CORE_PROPS.length; ++i) if(k == CORE_PROPS[i][1]) return;
for(i = 0; i < EXT_PROPS.length; ++i) if(k == EXT_PROPS[i][1]) return;
for(i = 0; i < BLACKLIST.length; ++i) if(k == BLACKLIST[i]) return;
var m = Props[k];
var t = "string";
if(typeof m == 'number') { t = "float"; m = String(m); }
else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
else m = String(m);
o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
});
if(Custprops) keys(Custprops).forEach(function(k) {
/*:: if(!Custprops) return; */
if(!Object.prototype.hasOwnProperty.call(Custprops, k)) return;
if(Props && Object.prototype.hasOwnProperty.call(Props, k)) return;
var m = Custprops[k];
var t = "string";
if(typeof m == 'number') { t = "float"; m = String(m); }
else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
else if(m instanceof Date) { t = "dateTime.tz"; m = m.toISOString(); }
else m = String(m);
o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
});
return '<' + T + ' xmlns="' + XLMLNS.o + '">' + o.join("") + '</' + T + '>';
}

View File

@ -5,11 +5,21 @@ function parse_FILETIME(blob) {
var dwLowDateTime = blob.read_shift(4), dwHighDateTime = blob.read_shift(4);
return new Date(((dwHighDateTime/1e7*Math.pow(2,32) + dwLowDateTime/1e7) - 11644473600)*1000).toISOString().replace(/\.000/,"");
}
function write_FILETIME(time/*:string|Date*/) {
var date = (typeof time == "string") ? new Date(Date.parse(time)) : time;
var t = date.getTime() / 1000 + 11644473600;
var l = t % Math.pow(2,32), h = (t - l) / Math.pow(2,32);
l *= 1e7; h *= 1e7;
var w = (l / Math.pow(2,32)) | 0;
if(w > 0) { l = l % Math.pow(2,32); h += w; }
var o = new_buf(8); o.write_shift(4, l); o.write_shift(4, h); return o;
}
/* [MS-OSHARED] 2.3.3.1.4 Lpstr */
function parse_lpstr(blob, type, pad) {
var str = blob.read_shift(0, 'lpstr');
if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3;
function parse_lpstr(blob, type, pad/*:?number*/) {
var start = blob.l;
var str = blob.read_shift(0, 'lpstr-cp');
if(pad) while((blob.l - start) & 3) ++blob.l;
return str;
}
@ -28,25 +38,35 @@ function parse_VtStringBase(blob, stringType, pad) {
return parse_lpstr(blob, stringType, pad);
}
function parse_VtString(blob, t, pad) { return parse_VtStringBase(blob, t, pad === false ? 0: 4); }
function parse_VtUnalignedString(blob, t) { if(!t) throw new Error("dafuq?"); return parse_VtStringBase(blob, t, 0); }
function parse_VtString(blob, t/*:number*/, pad/*:?boolean*/) { return parse_VtStringBase(blob, t, pad === false ? 0: 4); }
function parse_VtUnalignedString(blob, t/*:number*/) { if(!t) throw new Error("VtUnalignedString must have positive length"); return parse_VtStringBase(blob, t, 0); }
/* [MS-OSHARED] 2.3.3.1.9 VtVecUnalignedLpstrValue */
function parse_VtVecUnalignedLpstrValue(blob) {
/* [MS-OSHARED] 2.3.3.1.7 VtVecLpwstrValue */
function parse_VtVecLpwstrValue(blob)/*:Array<string>*/ {
var length = blob.read_shift(4);
var ret = [];
for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr');
var ret/*:Array<string>*/ = [];
for(var i = 0; i != length; ++i) {
var start = blob.l;
ret[i] = blob.read_shift(0, 'lpwstr').replace(chr0,'');
if((blob.l - start) & 0x02) blob.l += 2;
}
return ret;
}
/* [MS-OSHARED] 2.3.3.1.10 VtVecUnalignedLpstr */
function parse_VtVecUnalignedLpstr(blob) {
return parse_VtVecUnalignedLpstrValue(blob);
/* [MS-OSHARED] 2.3.3.1.9 VtVecUnalignedLpstrValue */
function parse_VtVecUnalignedLpstrValue(blob)/*:Array<string>*/ {
var length = blob.read_shift(4);
var ret/*:Array<string>*/ = [];
for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr-cp').replace(chr0,'');
return ret;
}
/* [MS-OSHARED] 2.3.3.1.13 VtHeadingPair */
function parse_VtHeadingPair(blob) {
var start = blob.l;
var headingString = parse_TypedPropertyValue(blob, VT_USTR);
if(blob[blob.l] == 0x00 && blob[blob.l+1] == 0x00 && ((blob.l - start) & 0x02)) blob.l += 2;
var headerParts = parse_TypedPropertyValue(blob, VT_I4);
return [headingString, headerParts];
}
@ -55,24 +75,19 @@ function parse_VtHeadingPair(blob) {
function parse_VtVecHeadingPairValue(blob) {
var cElements = blob.read_shift(4);
var out = [];
for(var i = 0; i != cElements / 2; ++i) out.push(parse_VtHeadingPair(blob));
for(var i = 0; i < cElements / 2; ++i) out.push(parse_VtHeadingPair(blob));
return out;
}
/* [MS-OSHARED] 2.3.3.1.15 VtVecHeadingPair */
function parse_VtVecHeadingPair(blob) {
// NOTE: When invoked, wType & padding were already consumed
return parse_VtVecHeadingPairValue(blob);
}
/* [MS-OLEPS] 2.18.1 Dictionary (uses 2.17, 2.16) */
function parse_dictionary(blob,CodePage) {
var cnt = blob.read_shift(4);
var dict = {};
var dict/*:{[number]:string}*/ = ({}/*:any*/);
for(var j = 0; j != cnt; ++j) {
var pid = blob.read_shift(4);
var len = blob.read_shift(4);
dict[pid] = blob.read_shift(len, (CodePage === 0x4B0 ?'utf16le':'utf8')).replace(chr0,'').replace(chr1,'!');
if(CodePage === 0x4B0 && (len % 2)) blob.l += 2;
}
if(blob.l & 3) blob.l = (blob.l>>2+1)<<2;
return dict;
@ -82,7 +97,8 @@ function parse_dictionary(blob,CodePage) {
function parse_BLOB(blob) {
var size = blob.read_shift(4);
var bytes = blob.slice(blob.l,blob.l+size);
if(size & 3 > 0) blob.l += (4 - (size & 3)) & 3;
blob.l += size;
if((size & 3) > 0) blob.l += (4 - (size & 3)) & 3;
return bytes;
}
@ -92,27 +108,16 @@ function parse_ClipboardData(blob) {
var o = {};
o.Size = blob.read_shift(4);
//o.Format = blob.read_shift(4);
blob.l += o.Size;
blob.l += o.Size + 3 - (o.Size - 1) % 4;
return o;
}
/* [MS-OLEPS] 2.14 Vector and Array Property Types */
function parse_VtVector(blob, cb) {
/* [MS-OLEPS] 2.14.2 VectorHeader */
/* var Length = blob.read_shift(4);
var o = [];
for(var i = 0; i != Length; ++i) {
o.push(cb(blob));
}
return o;*/
}
/* [MS-OLEPS] 2.15 TypedPropertyValue */
function parse_TypedPropertyValue(blob, type, _opts) {
function parse_TypedPropertyValue(blob, type/*:number*/, _opts)/*:any*/ {
var t = blob.read_shift(2), ret, opts = _opts||{};
blob.l += 2;
if(type !== VT_VARIANT)
if(t !== type && VT_CUSTOM.indexOf(type)===-1) throw new Error('Expected type ' + type + ' saw ' + t);
if(t !== type && VT_CUSTOM.indexOf(type)===-1 && !((type & 0xFFFE) == 0x101E && (t & 0xFFFE) == 0x101E)) throw new Error('Expected type ' + type + ' saw ' + t);
switch(type === VT_VARIANT ? t : type) {
case 0x02 /*VT_I2*/: ret = blob.read_shift(2, 'i'); if(!opts.raw) blob.l += 2; return ret;
case 0x03 /*VT_I4*/: ret = blob.read_shift(4, 'i'); return ret;
@ -123,24 +128,35 @@ function parse_TypedPropertyValue(blob, type, _opts) {
case 0x40 /*VT_FILETIME*/: return parse_FILETIME(blob);
case 0x41 /*VT_BLOB*/: return parse_BLOB(blob);
case 0x47 /*VT_CF*/: return parse_ClipboardData(blob);
case 0x50 /*VT_STRING*/: return parse_VtString(blob, t, !opts.raw && 4).replace(chr0,'');
case 0x51 /*VT_USTR*/: return parse_VtUnalignedString(blob, t, 4).replace(chr0,'');
case 0x100C /*VT_VECTOR|VT_VARIANT*/: return parse_VtVecHeadingPair(blob);
case 0x101E /*VT_LPSTR*/: return parse_VtVecUnalignedLpstr(blob);
case 0x50 /*VT_STRING*/: return parse_VtString(blob, t, !opts.raw).replace(chr0,'');
case 0x51 /*VT_USTR*/: return parse_VtUnalignedString(blob, t/*, 4*/).replace(chr0,'');
case 0x100C /*VT_VECTOR|VT_VARIANT*/: return parse_VtVecHeadingPairValue(blob);
case 0x101E /*VT_VECTOR|VT_LPSTR*/:
case 0x101F /*VT_VECTOR|VT_LPWSTR*/:
return t == 0x101F ? parse_VtVecLpwstrValue(blob) : parse_VtVecUnalignedLpstrValue(blob);
default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + t);
}
}
/* [MS-OLEPS] 2.14.2 VectorHeader */
/*function parse_VTVectorVariant(blob) {
var Length = blob.read_shift(4);
if(Length & 1 !== 0) throw new Error("VectorHeader Length=" + Length + " must be even");
var o = [];
for(var i = 0; i != Length; ++i) {
o.push(parse_TypedPropertyValue(blob, VT_VARIANT));
function write_TypedPropertyValue(type/*:number*/, value) {
var o = new_buf(4), p = new_buf(4);
o.write_shift(4, type == 0x50 ? 0x1F : type);
switch(type) {
case 0x03 /*VT_I4*/: p.write_shift(-4, value); break;
case 0x05 /*VT_I4*/: p = new_buf(8); p.write_shift(8, value, 'f'); break;
case 0x0B /*VT_BOOL*/: p.write_shift(4, value ? 0x01 : 0x00); break;
case 0x40 /*VT_FILETIME*/: /*:: if(typeof value !== "string" && !(value instanceof Date)) throw "unreachable"; */ p = write_FILETIME(value); break;
case 0x1F /*VT_LPWSTR*/:
case 0x50 /*VT_STRING*/:
/*:: if(typeof value !== "string") throw "unreachable"; */
p = new_buf(4 + 2 * (value.length + 1) + (value.length % 2 ? 0 : 2));
p.write_shift(4, value.length + 1);
p.write_shift(0, value, "dbcs");
while(p.l != p.length) p.write_shift(1, 0);
break;
default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + value);
}
return o;
}*/
return bconcat([o, p]);
}
/* [MS-OLEPS] 2.20 PropertySet */
function parse_PropertySet(blob, PIDSI) {
@ -149,59 +165,58 @@ function parse_PropertySet(blob, PIDSI) {
var NumProps = blob.read_shift(4);
var Props = [], i = 0;
var CodePage = 0;
var Dictionary = -1, DictObj;
var Dictionary = -1, DictObj/*:{[number]:string}*/ = ({}/*:any*/);
for(i = 0; i != NumProps; ++i) {
var PropID = blob.read_shift(4);
var Offset = blob.read_shift(4);
Props[i] = [PropID, Offset + start_addr];
}
Props.sort(function(x,y) { return x[1] - y[1]; });
var PropH = {};
for(i = 0; i != NumProps; ++i) {
if(blob.l !== Props[i][1]) {
var fail = true;
if(i>0 && PIDSI) switch(PIDSI[Props[i-1][0]].t) {
case 0x02 /*VT_I2*/: if(blob.l +2 === Props[i][1]) { blob.l+=2; fail = false; } break;
case 0x02 /*VT_I2*/: if(blob.l+2 === Props[i][1]) { blob.l+=2; fail = false; } break;
case 0x50 /*VT_STRING*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
case 0x100C /*VT_VECTOR|VT_VARIANT*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
}
if(!PIDSI && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; }
if((!PIDSI||i==0) && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; }
if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i);
}
if(PIDSI) {
if(Props[i][0] == 0 && Props.length > i+1 && Props[i][1] == Props[i+1][1]) continue; // R9
var piddsi = PIDSI[Props[i][0]];
PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true});
if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + String(PropH[piddsi.n] & 0xFFFF);
if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + ("0000" + String(PropH[piddsi.n] & 0xFFFF)).slice(-4);
if(piddsi.n == "CodePage") switch(PropH[piddsi.n]) {
case 0: PropH[piddsi.n] = 1252;
/* falls through */
case 10000: // OSX Roman
case 1252: // Windows Latin
case 874: // SB Windows Thai
case 1250: // SB Windows Central Europe
case 1251: // SB Windows Cyrillic
case 1253: // SB Windows Greek
case 1254: // SB Windows Turkish
case 1255: // SB Windows Hebrew
case 1256: // SB Windows Arabic
case 1257: // SB Windows Baltic
case 1258: // SB Windows Vietnam
case 932: // DB Windows Japanese Shift-JIS
case 936: // DB Windows Simplified Chinese GBK
case 949: // DB Windows Korean
case 950: // DB Windows Traditional Chinese Big5
case 1200: // UTF16LE
case 1201: // UTF16BE
case 65000: case -536: // UTF-7
case 65001: case -535: // UTF-8
set_cp(CodePage = PropH[piddsi.n]); break;
case 874:
case 932:
case 936:
case 949:
case 950:
case 1250:
case 1251:
case 1253:
case 1254:
case 1255:
case 1256:
case 1257:
case 1258:
case 10000:
case 1200:
case 1201:
case 1252:
case 65000: case -536:
case 65001: case -535:
set_cp(CodePage = (PropH[piddsi.n]>>>0) & 0xFFFF); break;
default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
}
} else {
if(Props[i][0] === 0x1) {
CodePage = PropH.CodePage = parse_TypedPropertyValue(blob, VT_I2);
CodePage = PropH.CodePage = (parse_TypedPropertyValue(blob, VT_I2)/*:number*/);
set_cp(CodePage);
if(Dictionary !== -1) {
var oldpos = blob.l;
@ -218,13 +233,13 @@ function parse_PropertySet(blob, PIDSI) {
/* [MS-OSHARED] 2.3.3.2.3.1.2 + PROPVARIANT */
switch(blob[blob.l]) {
case 0x41 /*VT_BLOB*/: blob.l += 4; val = parse_BLOB(blob); break;
case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]); break;
case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]); 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;
case 0x0B /*VT_BOOL*/: blob.l += 4; val = parsebool(blob, 4); break;
case 0x40 /*VT_FILETIME*/: blob.l += 4; val = new Date(parse_FILETIME(blob)); break;
case 0x40 /*VT_FILETIME*/: blob.l += 4; val = parseDate(parse_FILETIME(blob)); break;
default: throw new Error("unparsed value: " + blob[blob.l]);
}
PropH[name] = val;
@ -234,42 +249,143 @@ function parse_PropertySet(blob, PIDSI) {
blob.l = start_addr + size; /* step ahead to skip padding */
return PropH;
}
var XLSPSSkip = [ "CodePage", "Thumbnail", "_PID_LINKBASE", "_PID_HLINKS", "SystemIdentifier", "FMTID" ];
function guess_property_type(val/*:any*/)/*:number*/ {
switch(typeof val) {
case "boolean": return 0x0B;
case "number": return ((val|0)==val) ? 0x03 : 0x05;
case "string": return 0x1F;
case "object": if(val instanceof Date) return 0x40; break;
}
return -1;
}
function write_PropertySet(entries, RE, PIDSI) {
var hdr = new_buf(8), piao = [], prop = [];
var sz = 8, i = 0;
var pr = new_buf(8), pio = new_buf(8);
pr.write_shift(4, 0x0002);
pr.write_shift(4, 0x04B0);
pio.write_shift(4, 0x0001);
prop.push(pr); piao.push(pio);
sz += 8 + pr.length;
if(!RE) {
pio = new_buf(8);
pio.write_shift(4, 0);
piao.unshift(pio);
var bufs = [new_buf(4)];
bufs[0].write_shift(4, entries.length);
for(i = 0; i < entries.length; ++i) {
var value = entries[i][0];
pr = new_buf(4 + 4 + 2 * (value.length + 1) + (value.length % 2 ? 0 : 2));
pr.write_shift(4, i+2);
pr.write_shift(4, value.length + 1);
pr.write_shift(0, value, "dbcs");
while(pr.l != pr.length) pr.write_shift(1, 0);
bufs.push(pr);
}
pr = bconcat(bufs);
prop.unshift(pr);
sz += 8 + pr.length;
}
for(i = 0; i < entries.length; ++i) {
if(RE && !RE[entries[i][0]]) continue;
if(XLSPSSkip.indexOf(entries[i][0]) > -1 || PseudoPropsPairs.indexOf(entries[i][0]) > -1) continue;
if(entries[i][1] == null) continue;
var val = entries[i][1], idx = 0;
if(RE) {
idx = +RE[entries[i][0]];
var pinfo = (PIDSI/*:: || {}*/)[idx]/*:: || {} */;
if(pinfo.p == "version" && typeof val == "string") {
/*:: if(typeof val !== "string") throw "unreachable"; */
var arr = val.split(".");
val = ((+arr[0])<<16) + ((+arr[1])||0);
}
pr = write_TypedPropertyValue(pinfo.t, val);
} else {
var T = guess_property_type(val);
if(T == -1) { T = 0x1F; val = String(val); }
pr = write_TypedPropertyValue(T, val);
}
prop.push(pr);
pio = new_buf(8);
pio.write_shift(4, !RE ? 2+i : idx);
piao.push(pio);
sz += 8 + pr.length;
}
var w = 8 * (prop.length + 1);
for(i = 0; i < prop.length; ++i) { piao[i].write_shift(4, w); w += prop[i].length; }
hdr.write_shift(4, sz);
hdr.write_shift(4, prop.length);
return bconcat([hdr].concat(piao).concat(prop));
}
/* [MS-OLEPS] 2.21 PropertySetStream */
function parse_PropertySetStream(file, PIDSI) {
function parse_PropertySetStream(file, PIDSI, clsid) {
var blob = file.content;
if(!blob) return ({}/*:any*/);
prep_blob(blob, 0);
var NumSets, FMTID0, FMTID1, Offset0, Offset1;
var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;
blob.chk('feff', 'Byte Order: ');
var vers = blob.read_shift(2); // TODO: check version
/*var vers = */blob.read_shift(2); // TODO: check version
var SystemIdentifier = blob.read_shift(4);
blob.chk(CFB.utils.consts.HEADER_CLSID, 'CLSID: ');
var CLSID = blob.read_shift(16);
if(CLSID !== CFB.utils.consts.HEADER_CLSID && CLSID !== clsid) throw new Error("Bad PropertySet CLSID " + CLSID);
NumSets = blob.read_shift(4);
if(NumSets !== 1 && NumSets !== 2) throw "Unrecognized #Sets: " + NumSets;
if(NumSets !== 1 && NumSets !== 2) throw new Error("Unrecognized #Sets: " + NumSets);
FMTID0 = blob.read_shift(16); Offset0 = blob.read_shift(4);
if(NumSets === 1 && Offset0 !== blob.l) throw "Length mismatch";
if(NumSets === 1 && Offset0 !== blob.l) throw new Error("Length mismatch: " + Offset0 + " !== " + blob.l);
else if(NumSets === 2) { FMTID1 = blob.read_shift(16); Offset1 = blob.read_shift(4); }
var PSet0 = parse_PropertySet(blob, PIDSI);
var rval = { SystemIdentifier: SystemIdentifier };
var rval = ({ SystemIdentifier: SystemIdentifier }/*:any*/);
for(var y in PSet0) rval[y] = PSet0[y];
//rval.blob = blob;
rval.FMTID = FMTID0;
//rval.PSet0 = PSet0;
if(NumSets === 1) return rval;
if(blob.l !== Offset1) throw "Length mismatch 2: " + blob.l + " !== " + Offset1;
if(Offset1 - blob.l == 2) blob.l += 2;
if(blob.l !== Offset1) throw new Error("Length mismatch 2: " + blob.l + " !== " + Offset1);
var PSet1;
try { PSet1 = parse_PropertySet(blob, null); } catch(e) { }
try { PSet1 = parse_PropertySet(blob, null); } catch(e) {/* empty */}
for(y in PSet1) rval[y] = PSet1[y];
rval.FMTID = [FMTID0, FMTID1]; // TODO: verify FMTID0/1
return rval;
}
function write_PropertySetStream(entries, clsid, RE, PIDSI/*:{[key:string|number]:any}*/, entries2/*:?any*/, clsid2/*:?any*/) {
var hdr = new_buf(entries2 ? 68 : 48);
var bufs = [hdr];
hdr.write_shift(2, 0xFFFE);
hdr.write_shift(2, 0x0000); /* TODO: type 1 props */
hdr.write_shift(4, 0x32363237);
hdr.write_shift(16, CFB.utils.consts.HEADER_CLSID, "hex");
hdr.write_shift(4, (entries2 ? 2 : 1));
hdr.write_shift(16, clsid, "hex");
hdr.write_shift(4, (entries2 ? 68 : 48));
var ps0 = write_PropertySet(entries, RE, PIDSI);
bufs.push(ps0);
if(entries2) {
var ps1 = write_PropertySet(entries2, null, null);
hdr.write_shift(16, clsid2, "hex");
hdr.write_shift(4, 68 + ps0.length);
bufs.push(ps1);
}
return bconcat(bufs);
}
function parsenoop2(blob, length) { blob.read_shift(length); return null; }
function writezeroes(n, o) { if(!o) o=new_buf(n); for(var j=0; j<n; ++j) o.write_shift(1, 0); return o; }
function parslurp(blob, length, cb) {
var arr = [], target = blob.l + length;
@ -278,39 +394,40 @@ function parslurp(blob, length, cb) {
return arr;
}
function parslurp2(blob, length, cb) {
var arr = [], target = blob.l + length, len = blob.read_shift(2);
while(len-- !== 0) arr.push(cb(blob, target - blob.l));
if(target !== blob.l) throw new Error("Slurp error");
return arr;
}
function parsebool(blob, length/*:number*/) { return blob.read_shift(length) === 0x1; }
function writebool(v/*:any*/, o) { if(!o) o=new_buf(2); o.write_shift(2, +!!v); return o; }
function parsebool(blob, length) { return blob.read_shift(length) === 0x1; }
function parseuint16(blob) { return blob.read_shift(2, 'u'); }
function parseuint16a(blob, length) { return parslurp(blob,length,parseuint16);}
function parseuint16(blob/*::, length:?number, opts:?any*/) { return blob.read_shift(2, 'u'); }
function writeuint16(v/*:number*/, o) { if(!o) o=new_buf(2); o.write_shift(2, v); return o; }
function parseuint16a(blob, length/*:: :?number, opts:?any*/) { return parslurp(blob,length,parseuint16);}
/* --- 2.5 Structures --- */
/* [MS-XLS] 2.5.14 Boolean */
var parse_Boolean = parsebool;
/* [MS-XLS] 2.5.10 Bes (boolean or error) */
function parse_Bes(blob) {
function parse_Bes(blob/*::, length*/) {
var v = blob.read_shift(1), t = blob.read_shift(1);
return t === 0x01 ? v : v === 0x01;
}
function write_Bes(v, t/*:string*/, o) {
if(!o) o = new_buf(2);
o.write_shift(1, ((t == 'e') ? +v : +!!v));
o.write_shift(1, ((t == 'e') ? 1 : 0));
return o;
}
/* [MS-XLS] 2.5.240 ShortXLUnicodeString */
function parse_ShortXLUnicodeString(blob, length, opts) {
var cch = blob.read_shift(1);
var width = 1, encoding = 'sbcs-cont';
var cch = blob.read_shift(opts && opts.biff >= 12 ? 2 : 1);
var encoding = 'sbcs-cont';
var cp = current_codepage;
if(opts && opts.biff >= 8) current_codepage = 1200;
if(opts === undefined || opts.biff !== 5) {
if(!opts || opts.biff == 8 ) {
var fHighByte = blob.read_shift(1);
if(fHighByte) { width = 2; encoding = 'dbcs-cont'; }
if(fHighByte) { encoding = 'dbcs-cont'; }
} else if(opts.biff == 12) {
encoding = 'wstr';
}
if(opts.biff >= 2 && opts.biff <= 5) encoding = 'cpstr';
var o = cch ? blob.read_shift(cch, encoding) : "";
current_codepage = cp;
return o;
@ -321,13 +438,13 @@ function parse_XLUnicodeRichExtendedString(blob) {
var cp = current_codepage;
current_codepage = 1200;
var cch = blob.read_shift(2), flags = blob.read_shift(1);
var fHighByte = flags & 0x1, fExtSt = flags & 0x4, fRichSt = flags & 0x8;
var /*fHighByte = flags & 0x1,*/ fExtSt = flags & 0x4, fRichSt = flags & 0x8;
var width = 1 + (flags & 0x1); // 0x0 -> utf8, 0x1 -> dbcs
var cRun, cbExtRst;
var cRun = 0, cbExtRst;
var z = {};
if(fRichSt) cRun = blob.read_shift(2);
if(fExtSt) cbExtRst = blob.read_shift(4);
var encoding = (flags & 0x1) ? 'dbcs-cont' : 'sbcs-cont';
var encoding = width == 2 ? 'dbcs-cont' : 'sbcs-cont';
var msg = cch === 0 ? "" : blob.read_shift(cch, encoding);
if(fRichSt) blob.l += 4 * cRun; //TODO: parse this
if(fExtSt) blob.l += cbExtRst; //TODO: parse this
@ -336,10 +453,29 @@ function parse_XLUnicodeRichExtendedString(blob) {
current_codepage = cp;
return z;
}
function write_XLUnicodeRichExtendedString(xlstr/*:: :XLString, opts*/) {
var str = (xlstr.t||""), nfmts = 1;
var hdr = new_buf(3 + (nfmts > 1 ? 2 : 0));
hdr.write_shift(2, str.length);
hdr.write_shift(1, (nfmts > 1 ? 0x08 : 0x00) | 0x01);
if(nfmts > 1) hdr.write_shift(2, nfmts);
var otext = new_buf(2 * str.length);
otext.write_shift(2 * str.length, str, 'utf16le');
var out = [hdr, otext];
return bconcat(out);
}
/* 2.5.296 XLUnicodeStringNoCch */
function parse_XLUnicodeStringNoCch(blob, cch, opts) {
var retval;
if(opts) {
if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'cpstr');
if(opts.biff >= 12) return blob.read_shift(cch, 'dbcs-cont');
}
var fHighByte = blob.read_shift(1);
if(fHighByte===0) { retval = blob.read_shift(cch, 'sbcs-cont'); }
else { retval = blob.read_shift(cch, 'dbcs-cont'); }
@ -348,23 +484,37 @@ function parse_XLUnicodeStringNoCch(blob, cch, opts) {
/* 2.5.294 XLUnicodeString */
function parse_XLUnicodeString(blob, length, opts) {
var cch = blob.read_shift(opts !== undefined && opts.biff > 0 && opts.biff < 8 ? 1 : 2);
var cch = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
if(cch === 0) { blob.l++; return ""; }
return parse_XLUnicodeStringNoCch(blob, cch, opts);
}
/* BIFF5 override */
function parse_XLUnicodeString2(blob, length, opts) {
if(opts.biff !== 5 && opts.biff !== 2) return parse_XLUnicodeString(blob, length, opts);
if(opts.biff > 5) return parse_XLUnicodeString(blob, length, opts);
var cch = blob.read_shift(1);
if(cch === 0) { blob.l++; return ""; }
return blob.read_shift(cch, 'sbcs-cont');
return blob.read_shift(cch, (opts.biff <= 4 || !blob.lens ) ? 'cpstr' : 'sbcs-cont');
}
/* TODO: BIFF5 and lower, codepage awareness */
function write_XLUnicodeString(str, opts, o) {
if(!o) o = new_buf(3 + 2 * str.length);
o.write_shift(2, str.length);
o.write_shift(1, 1);
o.write_shift(31, str, 'utf16le');
return o;
}
/* [MS-XLS] 2.5.61 ControlInfo */
var parse_ControlInfo = parsenoop;
function parse_ControlInfo(blob/*::, length, opts*/) {
var flags = blob.read_shift(1);
blob.l++;
var accel = blob.read_shift(2);
blob.l += 2;
return [flags, accel];
}
/* [MS-OSHARED] 2.3.7.6 URLMoniker TODO: flags */
var parse_URLMoniker = function(blob, length) {
function parse_URLMoniker(blob/*::, length, opts*/) {
var len = blob.read_shift(4), start = blob.l;
var extra = false;
if(len > 24) {
@ -376,63 +526,111 @@ var parse_URLMoniker = function(blob, length) {
var url = blob.read_shift((extra?len-24:len)>>1, 'utf16le').replace(chr0,"");
if(extra) blob.l += 24;
return url;
};
}
/* [MS-OSHARED] 2.3.7.8 FileMoniker TODO: all fields */
var parse_FileMoniker = function(blob, length) {
function parse_FileMoniker(blob/*::, length*/) {
var cAnti = blob.read_shift(2);
var ansiLength = blob.read_shift(4);
var ansiPath = blob.read_shift(ansiLength, 'cstr');
var endServer = blob.read_shift(2);
var versionNumber = blob.read_shift(2);
var cbUnicodePathSize = blob.read_shift(4);
if(cbUnicodePathSize === 0) return ansiPath.replace(/\\/g,"/");
var cbUnicodePathBytes = blob.read_shift(4);
var usKeyValue = blob.read_shift(2);
var unicodePath = blob.read_shift(cbUnicodePathBytes>>1, 'utf16le').replace(chr0,"");
return unicodePath;
};
var preamble = ""; while(cAnti-- > 0) preamble += "../";
var ansiPath = blob.read_shift(0, 'lpstr-ansi');
blob.l += 2; //var endServer = blob.read_shift(2);
if(blob.read_shift(2) != 0xDEAD) throw new Error("Bad FileMoniker");
var sz = blob.read_shift(4);
if(sz === 0) return preamble + ansiPath.replace(/\\/g,"/");
var bytes = blob.read_shift(4);
if(blob.read_shift(2) != 3) throw new Error("Bad FileMoniker");
var unicodePath = blob.read_shift(bytes>>1, 'utf16le').replace(chr0,"");
return preamble + unicodePath;
}
/* [MS-OSHARED] 2.3.7.2 HyperlinkMoniker TODO: all the monikers */
var parse_HyperlinkMoniker = function(blob, length) {
function parse_HyperlinkMoniker(blob, length) {
var clsid = blob.read_shift(16); length -= 16;
switch(clsid) {
case "e0c9ea79f9bace118c8200aa004ba90b": return parse_URLMoniker(blob, length);
case "0303000000000000c000000000000046": return parse_FileMoniker(blob, length);
default: throw "unsupported moniker " + clsid;
default: throw new Error("Unsupported Moniker " + clsid);
}
};
}
/* [MS-OSHARED] 2.3.7.9 HyperlinkString */
var parse_HyperlinkString = function(blob, length) {
function parse_HyperlinkString(blob/*::, length*/) {
var len = blob.read_shift(4);
var o = blob.read_shift(len, 'utf16le').replace(chr0, "");
var o = len > 0 ? blob.read_shift(len, 'utf16le').replace(chr0, "") : "";
return o;
};
}
function write_HyperlinkString(str/*:string*/, o) {
if(!o) o = new_buf(6 + str.length * 2);
o.write_shift(4, 1 + str.length);
for(var i = 0; i < str.length; ++i) o.write_shift(2, str.charCodeAt(i));
o.write_shift(2, 0);
return o;
}
/* [MS-OSHARED] 2.3.7.1 Hyperlink Object TODO: unify params with XLSX */
var parse_Hyperlink = function(blob, length) {
/* [MS-OSHARED] 2.3.7.1 Hyperlink Object */
function parse_Hyperlink(blob, length)/*:Hyperlink*/ {
var end = blob.l + length;
var sVer = blob.read_shift(4);
if(sVer !== 2) throw new Error("Unrecognized streamVersion: " + sVer);
var flags = blob.read_shift(2);
blob.l += 2;
var displayName, targetFrameName, moniker, oleMoniker, location, guid, fileTime;
var displayName, targetFrameName, moniker, oleMoniker, Loc="", guid, fileTime;
if(flags & 0x0010) displayName = parse_HyperlinkString(blob, end - blob.l);
if(flags & 0x0080) targetFrameName = parse_HyperlinkString(blob, end - blob.l);
if((flags & 0x0101) === 0x0101) moniker = parse_HyperlinkString(blob, end - blob.l);
if((flags & 0x0101) === 0x0001) oleMoniker = parse_HyperlinkMoniker(blob, end - blob.l);
if(flags & 0x0008) location = parse_HyperlinkString(blob, end - blob.l);
if(flags & 0x0008) Loc = parse_HyperlinkString(blob, end - blob.l);
if(flags & 0x0020) guid = blob.read_shift(16);
if(flags & 0x0040) fileTime = parse_FILETIME(blob, 8);
if(flags & 0x0040) fileTime = parse_FILETIME(blob/*, 8*/);
blob.l = end;
var target = (targetFrameName||moniker||oleMoniker);
if(location) target+="#"+location;
return {Target: target};
};
var target = targetFrameName||moniker||oleMoniker||"";
if(target && Loc) target+="#"+Loc;
if(!target) target = "#" + Loc;
if((flags & 0x0002) && target.charAt(0) == "/" && target.charAt(1) != "/") target = "file://" + target;
var out = ({Target:target}/*:any*/);
if(guid) out.guid = guid;
if(fileTime) out.time = fileTime;
if(displayName) out.Tooltip = displayName;
return out;
}
function write_Hyperlink(hl) {
var out = new_buf(512), i = 0;
var Target = hl.Target;
if(Target.slice(0,7) == "file://") Target = Target.slice(7);
var hashidx = Target.indexOf("#");
var F = hashidx > -1 ? 0x1f : 0x17;
switch(Target.charAt(0)) { case "#": F=0x1c; break; case ".": F&=~2; break; }
out.write_shift(4,2); out.write_shift(4, F);
var data = [8,6815827,6619237,4849780,83]; for(i = 0; i < data.length; ++i) out.write_shift(4, data[i]);
if(F == 0x1C) {
Target = Target.slice(1);
write_HyperlinkString(Target, out);
} else if(F & 0x02) {
data = "e0 c9 ea 79 f9 ba ce 11 8c 82 00 aa 00 4b a9 0b".split(" ");
for(i = 0; i < data.length; ++i) out.write_shift(1, parseInt(data[i], 16));
var Pretarget = hashidx > -1 ? Target.slice(0, hashidx) : Target;
out.write_shift(4, 2*(Pretarget.length + 1));
for(i = 0; i < Pretarget.length; ++i) out.write_shift(2, Pretarget.charCodeAt(i));
out.write_shift(2, 0);
if(F & 0x08) write_HyperlinkString(hashidx > -1 ? Target.slice(hashidx+1): "", out);
} else {
data = "03 03 00 00 00 00 00 00 c0 00 00 00 00 00 00 46".split(" ");
for(i = 0; i < data.length; ++i) out.write_shift(1, parseInt(data[i], 16));
var P = 0;
while(Target.slice(P*3,P*3+3)=="../"||Target.slice(P*3,P*3+3)=="..\\") ++P;
out.write_shift(2, P);
out.write_shift(4, Target.length - 3 * P + 1);
for(i = 0; i < Target.length - 3 * P; ++i) out.write_shift(1, Target.charCodeAt(i + 3 * P) & 0xFF);
out.write_shift(1, 0);
out.write_shift(2, 0xFFFF);
out.write_shift(2, 0xDEAD);
for(i = 0; i < 6; ++i) out.write_shift(4, 0);
}
return out.slice(0, out.l);
}
/* 2.5.178 LongRGBA */
function parse_LongRGBA(blob, length) { var r = blob.read_shift(1), g = blob.read_shift(1), b = blob.read_shift(1), a = blob.read_shift(1); return [r,g,b,a]; }
function parse_LongRGBA(blob/*::, length*/) { var r = blob.read_shift(1), g = blob.read_shift(1), b = blob.read_shift(1), a = blob.read_shift(1); return [r,g,b,a]; }
/* 2.5.177 LongRGB */
function parse_LongRGB(blob, length) { var x = parse_LongRGBA(blob, length); x[3] = 0; return x; }

File diff suppressed because it is too large Load Diff

1128
bits/40_harb.js Normal file

File diff suppressed because it is too large Load Diff

1183
bits/41_lotus.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,157 +1,190 @@
/* 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 */
};
/* 18.4.7 rPr CT_RPrElt */
function parse_rpr(rpr) {
var font = {}, m = rpr.match(tagregex), i = 0;
var pass = false;
if(m) for(;i!=m.length; ++i) {
var y = parsexmltag(m[i]);
switch(y[0].replace(/<\w*:/g,"<")) {
/* 18.8.12 condense CT_BooleanProperty */
/* ** not required . */
case '<condense': break;
/* 18.8.17 extend CT_BooleanProperty */
/* ** not required . */
case '<extend': break;
/* 18.8.36 shadow CT_BooleanProperty */
/* ** not required . */
case '<shadow':
if(!y.val) break;
/* falls through */
case '<shadow>':
case '<shadow/>': font.shadow = 1; break;
case '</shadow>': break;
/* Parse a list of <r> tags */
var parse_rs = (function parse_rs_factory() {
var tregex = matchtag("t"), rpregex = matchtag("rPr"), rregex = /<r>/g, rend = /<\/r>/, nlregex = /\r\n/g;
/* 18.4.7 rPr CT_RPrElt */
var parse_rpr = function parse_rpr(rpr, intro, outro) {
var font = {}, cp = 65001;
var m = rpr.match(tagregex), i = 0;
if(m) for(;i!=m.length; ++i) {
var y = parsexmltag(m[i]);
switch(y[0]) {
/* 18.8.12 condense CT_BooleanProperty */
/* ** not required . */
case '<condense': break;
/* 18.8.17 extend CT_BooleanProperty */
/* ** not required . */
case '<extend': break;
/* 18.8.36 shadow CT_BooleanProperty */
/* ** not required . */
case '<shadow':
/* falls through */
case '<shadow/>': break;
/* 18.4.1 charset CT_IntProperty TODO */
case '<charset':
if(y.val == '1') break;
font.cp = CS2CP[parseInt(y.val, 10)];
break;
/* 18.4.1 charset CT_IntProperty TODO */
case '<charset':
if(y.val == '1') break;
cp = CS2CP[parseInt(y.val, 10)];
break;
/* 18.4.2 outline CT_BooleanProperty TODO */
case '<outline':
if(!y.val) break;
/* falls through */
case '<outline>':
case '<outline/>': font.outline = 1; break;
case '</outline>': break;
/* 18.4.2 outline CT_BooleanProperty TODO */
case '<outline':
/* falls through */
case '<outline/>': break;
/* 18.4.5 rFont CT_FontName */
case '<rFont': font.name = y.val; break;
/* 18.4.5 rFont CT_FontName */
case '<rFont': font.name = y.val; break;
/* 18.4.11 sz CT_FontSize */
case '<sz': font.sz = y.val; break;
/* 18.4.11 sz CT_FontSize */
case '<sz': font.sz = y.val; break;
/* 18.4.10 strike CT_BooleanProperty */
case '<strike':
if(!y.val) break;
/* falls through */
case '<strike>':
case '<strike/>': font.strike = 1; break;
case '</strike>': break;
/* 18.4.10 strike CT_BooleanProperty */
case '<strike':
if(!y.val) break;
/* falls through */
case '<strike/>': font.strike = 1; break;
case '</strike>': break;
/* 18.4.13 u CT_UnderlineProperty */
case '<u':
if(!y.val) break;
switch(y.val) {
case 'double': font.uval = "double"; break;
case 'singleAccounting': font.uval = "single-accounting"; break;
case 'doubleAccounting': font.uval = "double-accounting"; break;
}
/* falls through */
case '<u>':
case '<u/>': font.u = 1; break;
case '</u>': break;
/* 18.4.13 u CT_UnderlineProperty */
case '<u':
if(!y.val) break;
/* falls through */
case '<u/>': font.u = 1; break;
case '</u>': break;
/* 18.8.2 b */
case '<b':
if(y.val == '0') break;
/* falls through */
case '<b>':
case '<b/>': font.b = 1; break;
case '</b>': break;
/* 18.8.2 b */
case '<b':
if(!y.val) break;
/* falls through */
case '<b/>': font.b = 1; break;
case '</b>': break;
/* 18.8.26 i */
case '<i':
if(y.val == '0') break;
/* falls through */
case '<i>':
case '<i/>': font.i = 1; break;
case '</i>': break;
/* 18.8.26 i */
case '<i':
if(!y.val) break;
/* falls through */
case '<i/>': font.i = 1; break;
case '</i>': break;
/* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */
case '<color':
if(y.rgb) font.color = y.rgb.slice(2,8);
break;
case '<color>': case '<color/>': case '</color>': break;
/* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */
case '<color':
if(y.rgb) font.color = y.rgb.substr(2,6);
break;
/* 18.8.18 family ST_FontFamily */
case '<family': font.family = y.val; break;
case '<family>': case '<family/>': case '</family>': break;
/* 18.8.18 family ST_FontFamily */
case '<family': font.family = y.val; break;
/* 18.4.14 vertAlign CT_VerticalAlignFontProperty TODO */
case '<vertAlign': font.valign = y.val; break;
case '<vertAlign>': case '<vertAlign/>': case '</vertAlign>': break;
/* 18.4.14 vertAlign CT_VerticalAlignFontProperty TODO */
case '<vertAlign': break;
/* 18.8.35 scheme CT_FontScheme TODO */
case '<scheme': break;
case '<scheme>': case '<scheme/>': case '</scheme>': break;
/* 18.8.35 scheme CT_FontScheme TODO */
case '<scheme': break;
default:
if(y[0].charCodeAt(1) !== 47) throw 'Unrecognized rich format ' + y[0];
}
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': break;
case '<ext': pass = true; break;
case '</ext>': pass = false; break;
default:
if(y[0].charCodeAt(1) !== 47 && !pass) throw new Error('Unrecognized rich format ' + y[0]);
}
/* TODO: These should be generated styles, not inline */
var style = [];
if(font.b) style.push("font-weight: bold;");
if(font.i) style.push("font-style: italic;");
intro.push('<span style="' + style.join("") + '">');
outro.push("</span>");
return cp;
};
}
return font;
}
var parse_rs = /*#__PURE__*/(function() {
/* 18.4.4 r CT_RElt */
function parse_r(r) {
var terms = [[],"",[]];
/* 18.4.12 t ST_Xstring */
var t = r.match(tregex), cp = 65001;
if(!isval(t)) return "";
terms[1] = t[1];
var t = str_match_xml_ns(r, "t")/*, cp = 65001*/;
if(!t) return {t:"s", v:""};
var rpr = r.match(rpregex);
if(isval(rpr)) cp = parse_rpr(rpr[1], terms[0], terms[2]);
var o/*:Cell*/ = ({t:'s', v:unescapexml(t[1])}/*:any*/);
var rpr = str_match_xml_ns(r, "rPr");
if(rpr) o.s = parse_rpr(rpr[1]);
return o;
}
var rregex = /<(?:\w+:)?r>/g, rend = /<\/(?:\w+:)?r>/;
return function parse_rs(rs) {
return rs.replace(rregex,"").split(rend).map(parse_r).filter(function(r) { return r.v; });
};
})();
/* Parse a list of <r> tags */
var rs_to_html = /*#__PURE__*/(function parse_rs_factory() {
var nlregex = /(\r\n|\n)/g;
function parse_rpr2(font, intro, outro) {
var style/*:Array<string>*/ = [];
if(font.u) style.push("text-decoration: underline;");
if(font.uval) style.push("text-underline-style:" + font.uval + ";");
if(font.sz) style.push("font-size:" + font.sz + "pt;");
if(font.outline) style.push("text-effect: outline;");
if(font.shadow) style.push("text-shadow: auto;");
intro.push('<span style="' + style.join("") + '">');
if(font.b) { intro.push("<b>"); outro.push("</b>"); }
if(font.i) { intro.push("<i>"); outro.push("</i>"); }
if(font.strike) { intro.push("<s>"); outro.push("</s>"); }
var align = font.valign || "";
if(align == "superscript" || align == "super") align = "sup";
else if(align == "subscript") align = "sub";
if(align != "") { intro.push("<" + align + ">"); outro.push("</" + align + ">"); }
outro.push("</span>");
return font;
}
/* 18.4.4 r CT_RElt */
function r_to_html(r) {
var terms/*:[Array<string>, string, Array<string>]*/ = [[],r.v,[]];
if(!r.v) return "";
if(r.s) parse_rpr2(r.s, terms[0], terms[2]);
return terms[0].join("") + terms[1].replace(nlregex,'<br/>') + terms[2].join("");
}
return function parse_rs(rs) {
return rs.replace(rregex,"").split(rend).map(parse_r).join("");
return rs.map(r_to_html).join("");
};
})();
/* 18.4.8 si CT_Rst */
var sitregex = /<t[^>]*>([^<]*)<\/t>/g, sirregex = /<r>/;
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 = {};
if(!x) return null;
var y;
if(!x) return { t: "" };
//var y;
/* 18.4.12 t ST_Xstring (Plaintext String) */
if(x.charCodeAt(1) === 116) {
z.t = utf8read(unescapexml(x.substr(x.indexOf(">")+1).split(/<\/t>/)[0]));
z.r = x;
if(html) z.h = z.t;
// TODO: is whitespace actually valid here?
if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) {
z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||""), true);
z.r = utf8read(x);
if(html) z.h = escapehtml(z.t);
}
/* 18.4.4 r CT_RElt (Rich Text Run) */
else if((y = x.match(sirregex))) {
z.r = x;
z.t = utf8read(unescapexml(x.match(sitregex).join("").replace(tagregex,"")));
if(html) z.h = parse_rs(x);
else if((/*y = */x.match(sirregex))) {
z.r = utf8read(x);
z.t = unescapexml(utf8read((str_remove_xml_ns_g(x, "rPh").match(sitregex)||[]).join("").replace(tagregex,"")), true);
if(html) z.h = rs_to_html(parse_rs(z.r));
}
/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
/* 18.4.6 rPh CT_PhoneticRun (TODO: needed for Asian support) */
@ -159,40 +192,41 @@ function parse_si(x, opts) {
}
/* 18.4 Shared String Table */
var sstr0 = /<sst([^>]*)>([\s\S]*)<\/sst>/;
var sstr1 = /<(?:si|sstItem)>/g;
var sstr2 = /<\/(?:si|sstItem)>/;
function parse_sst_xml(data, opts) {
var s = [], ss;
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);
if(isval(sst)) {
ss = sst[2].replace(sstr1,"").split(sstr2);
var sst = str_match_xml_ns(data, "sst");
if(sst) {
ss = sst[1].replace(sstr1,"").split(sstr2);
for(var i = 0; i != ss.length; ++i) {
var o = parse_si(ss[i], opts);
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, opts) {
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
}));
for(var i = 0; i != sst.length; ++i) { if(sst[i] == null) continue;
var s = sst[i];
var s/*:XLString*/ = sst[i];
var sitag = "<si>";
if(s.r) sitag += s.r;
else {
sitag += "<t";
if(!s.t) s.t = "";
if(typeof s.t !== "string") s.t = String(s.t);
if(s.t.match(straywsregex)) sitag += ' xml:space="preserve"';
sitag += ">" + escapexml(s.t) + "</t>";
}

View File

@ -1,21 +1,29 @@
/* [MS-XLSB] 2.4.219 BrtBeginSst */
function parse_BrtBeginSst(data, length) {
/* [MS-XLSB] 2.4.221 BrtBeginSst */
function parse_BrtBeginSst(data) {
return [data.read_shift(4), data.read_shift(4)];
}
/* [MS-XLSB] 2.1.7.45 Shared Strings */
function parse_sst_bin(data, opts) {
var s = [];
function parse_sst_bin(data, opts)/*:SST*/ {
var s/*:SST*/ = ([]/*:any*/);
var pass = false;
recordhopper(data, function hopper_sst(val, R, RT) {
switch(R.n) {
case 'BrtBeginSst': s.Count = val[0]; s.Unique = val[1]; break;
case 'BrtSSTItem': s.push(val); break;
case 'BrtEndSst': return true;
/* TODO: produce a test case with a future record */
case 'BrtFRTBegin': pass = true; break;
case 'BrtFRTEnd': pass = false; break;
default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
switch(RT) {
case 0x009F: /* BrtBeginSst */
s.Count = val[0]; s.Unique = val[1]; break;
case 0x0013: /* BrtSSTItem */
s.push(val); break;
case 0x00A0: /* BrtEndSst */
return true;
case 0x0023: /* BrtFRTBegin */
pass = true; break;
case 0x0024: /* BrtFRTEnd */
pass = false; break;
default:
if(R.T){}
if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
}
});
return s;
@ -30,10 +38,11 @@ function write_BrtBeginSst(sst, o) {
var write_BrtSSTItem = write_RichStr;
function write_sst_bin(sst, opts) {
function write_sst_bin(sst/*::, opts*/) {
var ba = buf_array();
write_record(ba, "BrtBeginSst", write_BrtBeginSst(sst));
for(var i = 0; i < sst.length; ++i) write_record(ba, "BrtSSTItem", write_BrtSSTItem(sst[i]));
write_record(ba, "BrtEndSst");
write_record(ba, 0x009F /* BrtBeginSst */, write_BrtBeginSst(sst));
for(var i = 0; i < sst.length; ++i) write_record(ba, 0x0013 /* BrtSSTItem */, write_BrtSSTItem(sst[i]));
/* FRTSST */
write_record(ba, 0x00A0 /* BrtEndSst */);
return ba.end();
}

View File

@ -1,40 +1,176 @@
function _JS2ANSI(str) { if(typeof cptable !== 'undefined') return cptable.utils.encode(1252, str); return str.split("").map(function(x) { return x.charCodeAt(0); }); }
/* [MS-OFFCRYPTO] 2.1.4 Version */
function parse_Version(blob, length) {
var o = {};
o.Major = blob.read_shift(2);
o.Minor = blob.read_shift(2);
function _JS2ANSI(str/*:string*/)/*:Array<number>*/ {
if(typeof $cptable !== 'undefined') return $cptable.utils.encode(current_ansi, str);
var o/*:Array<number>*/ = [], oo = str.split("");
for(var i = 0; i < oo.length; ++i) o[i] = oo[i].charCodeAt(0);
return o;
}
/* [MS-OFFCRYPTO] 2.3.2 Encryption Header */
function parse_EncryptionHeader(blob, length) {
/* [MS-OFFCRYPTO] 2.1.4 Version */
function parse_CRYPTOVersion(blob, length/*:?number*/) {
var o/*:any*/ = {};
o.Major = blob.read_shift(2);
o.Minor = blob.read_shift(2);
/*:: if(length == null) return o; */
if(length >= 4) blob.l += length - 4;
return o;
}
/* [MS-OFFCRYPTO] 2.1.5 DataSpaceVersionInfo */
function parse_DataSpaceVersionInfo(blob) {
var o = {};
o.Flags = blob.read_shift(4);
o.id = blob.read_shift(0, 'lpp4');
o.R = parse_CRYPTOVersion(blob, 4);
o.U = parse_CRYPTOVersion(blob, 4);
o.W = parse_CRYPTOVersion(blob, 4);
return o;
}
// Check if SizeExtra is 0x00000000
var tmp = blob.read_shift(4);
if(tmp !== 0) throw 'Unrecognized SizeExtra: ' + tmp;
/* [MS-OFFCRYPTO] 2.1.6.1 DataSpaceMapEntry Structure */
function parse_DataSpaceMapEntry(blob) {
var len = blob.read_shift(4);
var end = blob.l + len - 4;
var o = {};
var cnt = blob.read_shift(4);
var comps/*:Array<{t:number, v:string}>*/ = [];
/* [MS-OFFCRYPTO] 2.1.6.2 DataSpaceReferenceComponent Structure */
while(cnt-- > 0) comps.push({ t: blob.read_shift(4), v: blob.read_shift(0, 'lpp4') });
o.name = blob.read_shift(0, 'lpp4');
o.comps = comps;
if(blob.l != end) throw new Error("Bad DataSpaceMapEntry: " + blob.l + " != " + end);
return o;
}
/* [MS-OFFCRYPTO] 2.1.6 DataSpaceMap */
function parse_DataSpaceMap(blob) {
var o = [];
blob.l += 4; // must be 0x8
var cnt = blob.read_shift(4);
while(cnt-- > 0) o.push(parse_DataSpaceMapEntry(blob));
return o;
}
/* [MS-OFFCRYPTO] 2.1.7 DataSpaceDefinition */
function parse_DataSpaceDefinition(blob)/*:Array<string>*/ {
var o/*:Array<string>*/ = [];
blob.l += 4; // must be 0x8
var cnt = blob.read_shift(4);
while(cnt-- > 0) o.push(blob.read_shift(0, 'lpp4'));
return o;
}
/* [MS-OFFCRYPTO] 2.1.8 DataSpaceDefinition */
function parse_TransformInfoHeader(blob) {
var o = {};
/*var len = */blob.read_shift(4);
blob.l += 4; // must be 0x1
o.id = blob.read_shift(0, 'lpp4');
o.name = blob.read_shift(0, 'lpp4');
o.R = parse_CRYPTOVersion(blob, 4);
o.U = parse_CRYPTOVersion(blob, 4);
o.W = parse_CRYPTOVersion(blob, 4);
return o;
}
function parse_Primary(blob) {
/* [MS-OFFCRYPTO] 2.2.6 IRMDSTransformInfo */
var hdr = parse_TransformInfoHeader(blob);
/* [MS-OFFCRYPTO] 2.1.9 EncryptionTransformInfo */
hdr.ename = blob.read_shift(0, '8lpp4');
hdr.blksz = blob.read_shift(4);
hdr.cmode = blob.read_shift(4);
if(blob.read_shift(4) != 0x04) throw new Error("Bad !Primary record");
return hdr;
}
/* [MS-OFFCRYPTO] 2.3.2 Encryption Header */
function parse_EncryptionHeader(blob, length/*:number*/) {
var tgt = blob.l + length;
var o = {};
o.Flags = (blob.read_shift(4) & 0x3F);
blob.l += 4;
o.AlgID = blob.read_shift(4);
var valid = false;
switch(o.AlgID) {
case 0: case 0x6801: case 0x660E: case 0x660F: case 0x6610: break;
case 0x660E: case 0x660F: case 0x6610: valid = (o.Flags == 0x24); break;
case 0x6801: valid = (o.Flags == 0x04); break;
case 0: valid = (o.Flags == 0x10 || o.Flags == 0x04 || o.Flags == 0x24); break;
default: throw 'Unrecognized encryption algorithm: ' + o.AlgID;
}
parsenoop(blob, length-12);
if(!valid) throw new Error("Encryption Flags/AlgID mismatch");
o.AlgIDHash = blob.read_shift(4);
o.KeySize = blob.read_shift(4);
o.ProviderType = blob.read_shift(4);
blob.l += 8;
o.CSPName = blob.read_shift((tgt-blob.l)>>1, 'utf16le');
blob.l = tgt;
return o;
}
/* [MS-OFFCRYPTO] 2.3.3 Encryption Verifier */
function parse_EncryptionVerifier(blob, length) {
return parsenoop(blob, length);
function parse_EncryptionVerifier(blob, length/*:number*/) {
var o = {}, tgt = blob.l + length;
blob.l += 4; // SaltSize must be 0x10
o.Salt = blob.slice(blob.l, blob.l+16); blob.l += 16;
o.Verifier = blob.slice(blob.l, blob.l+16); blob.l += 16;
/*var sz = */blob.read_shift(4);
o.VerifierHash = blob.slice(blob.l, tgt); blob.l = tgt;
return o;
}
/* [MS-OFFCRYPTO] 2.3.5.1 RC4 CryptoAPI Encryption Header */
function parse_RC4CryptoHeader(blob, length) {
/* [MS-OFFCRYPTO] 2.3.4.* EncryptionInfo Stream */
function parse_EncryptionInfo(blob) {
var vers = parse_CRYPTOVersion(blob);
switch(vers.Minor) {
case 0x02: return [vers.Minor, parse_EncInfoStd(blob, vers)];
case 0x03: return [vers.Minor, parse_EncInfoExt(blob, vers)];
case 0x04: return [vers.Minor, parse_EncInfoAgl(blob, vers)];
}
throw new Error("ECMA-376 Encrypted file unrecognized Version: " + vers.Minor);
}
/* [MS-OFFCRYPTO] 2.3.4.5 EncryptionInfo Stream (Standard Encryption) */
function parse_EncInfoStd(blob/*::, vers*/) {
var flags = blob.read_shift(4);
if((flags & 0x3F) != 0x24) throw new Error("EncryptionInfo mismatch");
var sz = blob.read_shift(4);
//var tgt = blob.l + sz;
var hdr = parse_EncryptionHeader(blob, sz);
var verifier = parse_EncryptionVerifier(blob, blob.length - blob.l);
return { t:"Std", h:hdr, v:verifier };
}
/* [MS-OFFCRYPTO] 2.3.4.6 EncryptionInfo Stream (Extensible Encryption) */
function parse_EncInfoExt(/*::blob, vers*/) { throw new Error("File is password-protected: ECMA-376 Extensible"); }
/* [MS-OFFCRYPTO] 2.3.4.10 EncryptionInfo Stream (Agile Encryption) */
function parse_EncInfoAgl(blob/*::, vers*/) {
var KeyData = ["saltSize","blockSize","keyBits","hashSize","cipherAlgorithm","cipherChaining","hashAlgorithm","saltValue"];
blob.l+=4;
var xml = blob.read_shift(blob.length - blob.l, 'utf8');
var o = {};
var vers = o.EncryptionVersionInfo = parse_Version(blob, 4); length -= 4;
if(vers.Minor != 2) throw 'unrecognized minor version code: ' + vers.Minor;
if(vers.Major > 4 || vers.Major < 2) throw 'unrecognized major version code: ' + vers.Major;
xml.replace(tagregex, function xml_agile(x) {
var y/*:any*/ = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<?xml': break;
case '<encryption': case '</encryption>': break;
case '<keyData': KeyData.forEach(function(k) { o[k] = y[k]; }); break;
case '<dataIntegrity': o.encryptedHmacKey = y.encryptedHmacKey; o.encryptedHmacValue = y.encryptedHmacValue; break;
case '<keyEncryptors>': case '<keyEncryptors': o.encs = []; break;
case '</keyEncryptors>': break;
case '<keyEncryptor': o.uri = y.uri; break;
case '</keyEncryptor>': break;
case '<encryptedKey': o.encs.push(y); break;
default: throw y[0];
}
});
return o;
}
/* [MS-OFFCRYPTO] 2.3.5.1 RC4 CryptoAPI Encryption Header */
function parse_RC4CryptoHeader(blob, length/*:number*/) {
var o = {};
var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4); length -= 4;
if(vers.Minor != 2) throw new Error('unrecognized minor version code: ' + vers.Minor);
if(vers.Major > 4 || vers.Major < 2) throw new Error('unrecognized major version code: ' + vers.Major);
o.Flags = blob.read_shift(4); length -= 4;
var sz = blob.read_shift(4); length -= 4;
o.EncryptionHeader = parse_EncryptionHeader(blob, sz); length -= sz;
@ -42,9 +178,9 @@ function parse_RC4CryptoHeader(blob, length) {
return o;
}
/* [MS-OFFCRYPTO] 2.3.6.1 RC4 Encryption Header */
function parse_RC4Header(blob, length) {
function parse_RC4Header(blob/*::, length*/) {
var o = {};
var vers = o.EncryptionVersionInfo = parse_Version(blob, 4); length -= 4;
var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4);
if(vers.Major != 1 || vers.Minor != 1) throw 'unrecognized version code ' + vers.Major + ' : ' + vers.Minor;
o.Salt = blob.read_shift(16);
o.EncryptedVerifier = blob.read_shift(16);
@ -53,7 +189,7 @@ function parse_RC4Header(blob, length) {
}
/* [MS-OFFCRYPTO] 2.3.7.1 Binary Document Password Verifier Derivation */
function crypto_CreatePasswordVerifier_Method1(Password) {
function crypto_CreatePasswordVerifier_Method1(Password/*:string*/) {
var Verifier = 0x0000, PasswordArray;
var PasswordDecoded = _JS2ANSI(Password);
var len = PasswordDecoded.length + 1, i, PasswordByte;
@ -72,7 +208,7 @@ function crypto_CreatePasswordVerifier_Method1(Password) {
}
/* [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];
@ -90,7 +226,7 @@ var crypto_CreateXorArray_Method1 = (function() {
}
return XorKey;
};
return function(password) {
return function(password/*:string*/) {
var Password = _JS2ANSI(password);
var XorKey = CreateXorKey_Method1(Password);
var Index = Password.length;
@ -130,7 +266,7 @@ var crypto_CreateXorArray_Method1 = (function() {
})();
/* [MS-OFFCRYPTO] 2.3.7.3 Binary Document XOR Data Transformation Method 1 */
var crypto_DecryptData_Method1 = function(password, Data, XorArrayIndex, XorArray, O) {
var crypto_DecryptData_Method1 = function(password/*:string*/, Data, XorArrayIndex, XorArray, O) {
/* If XorArray is set, use it; if O is not set, make changes in-place */
if(!O) O = Data;
if(!XorArray) XorArray = crypto_CreateXorArray_Method1(password);
@ -145,10 +281,10 @@ var crypto_DecryptData_Method1 = function(password, Data, XorArrayIndex, XorArra
return [O, XorArrayIndex, XorArray];
};
var crypto_MakeXorDecryptor = function(password) {
var crypto_MakeXorDecryptor = function(password/*:string*/) {
var XorArrayIndex = 0, XorArray = crypto_CreateXorArray_Method1(password);
return function(Data) {
var O = crypto_DecryptData_Method1(null, Data, XorArrayIndex, XorArray);
var O = crypto_DecryptData_Method1("", Data, XorArrayIndex, XorArray);
XorArrayIndex = O[1];
return O[0];
};
@ -156,24 +292,24 @@ var crypto_MakeXorDecryptor = function(password) {
/* 2.5.343 */
function parse_XORObfuscation(blob, length, opts, out) {
var o = { key: parseuint16(blob), verificationBytes: parseuint16(blob) };
var o = ({ key: parseuint16(blob), verificationBytes: parseuint16(blob) }/*:any*/);
if(opts.password) o.verifier = crypto_CreatePasswordVerifier_Method1(opts.password);
out.valid = o.verificationBytes === o.verifier;
if(out.valid) out.insitu_decrypt = crypto_MakeXorDecryptor(opts.password);
if(out.valid) out.insitu = crypto_MakeXorDecryptor(opts.password);
return o;
}
/* 2.4.117 */
function parse_FilePassHeader(blob, length, oo) {
function parse_FilePassHeader(blob, length/*:number*/, oo) {
var o = oo || {}; o.Info = blob.read_shift(2); blob.l -= 2;
if(o.Info === 1) o.Data = parse_RC4Header(blob, length);
else o.Data = parse_RC4CryptoHeader(blob, length);
return o;
}
function parse_FilePass(blob, length, opts) {
var o = { Type: blob.read_shift(2) }; /* wEncryptionType */
function parse_FilePass(blob, length/*:number*/, opts) {
var o = ({ Type: opts.biff >= 8 ? blob.read_shift(2) : 0 }/*:any*/); /* wEncryptionType */
if(o.Type) parse_FilePassHeader(blob, length-2, o);
else parse_XORObfuscation(blob, length-2, opts, o);
else parse_XORObfuscation(blob, opts.biff >= 8 ? length : length - 2, opts, o);
return o;
}

103
bits/45_rtf.js Normal file
View File

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

@ -1,84 +0,0 @@
function hex2RGB(h) {
var o = h.substr(h[0]==="#"?1:0,6);
return [parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16)];
}
function rgb2Hex(rgb) {
for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);
return o.toString(16).toUpperCase().substr(1);
}
function rgb2HSL(rgb) {
var R = rgb[0]/255, G = rgb[1]/255, B=rgb[2]/255;
var M = Math.max(R, G, B), m = Math.min(R, G, B), C = M - m;
if(C === 0) return [0, 0, R];
var H6 = 0, S = 0, L2 = (M + m);
S = C / (L2 > 1 ? 2 - L2 : L2);
switch(M){
case R: H6 = ((G - B) / C + 6)%6; break;
case G: H6 = ((B - R) / C + 2); break;
case B: H6 = ((R - G) / C + 4); break;
}
return [H6 / 6, S, L2 / 2];
}
function hsl2RGB(hsl){
var H = hsl[0], S = hsl[1], L = hsl[2];
var C = S * 2 * (L < 0.5 ? L : 1 - L), m = L - C/2;
var rgb = [m,m,m], h6 = 6*H;
var X;
if(S !== 0) switch(h6|0) {
case 0: case 6: X = C * h6; rgb[0] += C; rgb[1] += X; break;
case 1: X = C * (2 - h6); rgb[0] += X; rgb[1] += C; break;
case 2: X = C * (h6 - 2); rgb[1] += C; rgb[2] += X; break;
case 3: X = C * (4 - h6); rgb[1] += X; rgb[2] += C; break;
case 4: X = C * (h6 - 4); rgb[2] += C; rgb[0] += X; break;
case 5: X = C * (6 - h6); rgb[2] += X; rgb[0] += C; break;
}
for(var i = 0; i != 3; ++i) rgb[i] = Math.round(rgb[i]*255);
return rgb;
}
/* 18.8.3 bgColor tint algorithm */
function rgb_tint(hex, tint) {
if(tint === 0) return hex;
var hsl = rgb2HSL(hex2RGB(hex));
if (tint < 0) hsl[2] = hsl[2] * (1 + tint);
else hsl[2] = 1 - (1 - hsl[2]) * (1 - tint);
return rgb2Hex(hsl2RGB(hsl));
}
/* 18.3.1.13 width calculations */
var DEF_MDW = 7, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
function width2px(width) { return (( width + ((128/MDW)|0)/256 )* MDW )|0; }
function px2char(px) { return (((px - 5)/MDW * 100 + 0.5)|0)/100; }
function char2width(chr) { return (((chr * MDW + 5)/MDW*256)|0)/256; }
function cycle_width(collw) { return char2width(px2char(width2px(collw))); }
function find_mdw(collw, coll) {
if(cycle_width(collw) != collw) {
for(MDW=DEF_MDW; MDW>MIN_MDW; --MDW) if(cycle_width(collw) === collw) break;
if(MDW === MIN_MDW) for(MDW=DEF_MDW+1; MDW<MAX_MDW; ++MDW) if(cycle_width(collw) === collw) break;
if(MDW === MAX_MDW) MDW = DEF_MDW;
}
}
/* [MS-EXSPXML3] 2.4.54 ST_enmPattern */
var XLMLPatternTypeMap = {
"None": "none",
"Solid": "solid",
"Gray50": "mediumGray",
"Gray75": "darkGray",
"Gray25": "lightGray",
"HorzStripe": "darkHorizontal",
"VertStripe": "darkVertical",
"ReverseDiagStripe": "darkDown",
"DiagStripe": "darkUp",
"DiagCross": "darkGrid",
"ThickDiagCross": "darkTrellis",
"ThinHorzStripe": "lightHorizontal",
"ThinVertStripe": "lightVertical",
"ThinReverseDiagStripe": "lightDown",
"ThinHorzCross": "lightGrid"
};

View File

@ -1,4 +1,118 @@
var styles = {}; // shared styles
function hex2RGB(h) {
var o = h.slice(h[0]==="#"?1:0).slice(0,6);
return [parseInt(o.slice(0,2),16),parseInt(o.slice(2,4),16),parseInt(o.slice(4,6),16)];
}
function rgb2Hex(rgb) {
for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);
return o.toString(16).toUpperCase().slice(1);
}
var themes = {}; // shared themes
function rgb2HSL(rgb) {
var R = rgb[0]/255, G = rgb[1]/255, B=rgb[2]/255;
var M = Math.max(R, G, B), m = Math.min(R, G, B), C = M - m;
if(C === 0) return [0, 0, R];
var H6 = 0, S = 0, L2 = (M + m);
S = C / (L2 > 1 ? 2 - L2 : L2);
switch(M){
case R: H6 = ((G - B) / C + 6)%6; break;
case G: H6 = ((B - R) / C + 2); break;
case B: H6 = ((R - G) / C + 4); break;
}
return [H6 / 6, S, L2 / 2];
}
function hsl2RGB(hsl){
var H = hsl[0], S = hsl[1], L = hsl[2];
var C = S * 2 * (L < 0.5 ? L : 1 - L), m = L - C/2;
var rgb = [m,m,m], h6 = 6*H;
var X;
if(S !== 0) switch(h6|0) {
case 0: case 6: X = C * h6; rgb[0] += C; rgb[1] += X; break;
case 1: X = C * (2 - h6); rgb[0] += X; rgb[1] += C; break;
case 2: X = C * (h6 - 2); rgb[1] += C; rgb[2] += X; break;
case 3: X = C * (4 - h6); rgb[1] += X; rgb[2] += C; break;
case 4: X = C * (h6 - 4); rgb[2] += C; rgb[0] += X; break;
case 5: X = C * (6 - h6); rgb[2] += X; rgb[0] += C; break;
}
for(var i = 0; i != 3; ++i) rgb[i] = Math.round(rgb[i]*255);
return rgb;
}
/* 18.8.3 bgColor tint algorithm */
function rgb_tint(hex, tint) {
if(tint === 0) return hex;
var hsl = rgb2HSL(hex2RGB(hex));
if (tint < 0) hsl[2] = hsl[2] * (1 + tint);
else hsl[2] = 1 - (1 - hsl[2]) * (1 - tint);
return rgb2Hex(hsl2RGB(hsl));
}
/* 18.3.1.13 width calculations */
/* [MS-OI29500] 2.1.595 Column Width & Formatting */
var DEF_MDW = 6, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); }
function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; }
function char2width(chr) { return (Math.round((chr * MDW + 5)/MDW*256))/256; }
//function px2char_(px) { return (((px - 5)/MDW * 100 + 0.5))/100; }
//function char2width_(chr) { return (((chr * MDW + 5)/MDW*256))/256; }
function cycle_width(collw) { return char2width(px2char(width2px(collw))); }
/* XLSX/XLSB/XLS specify width in units of MDW */
function find_mdw_colw(collw) {
var delta = Math.abs(collw - cycle_width(collw)), _MDW = MDW;
if(delta > 0.005) for(MDW=MIN_MDW; MDW<MAX_MDW; ++MDW) if(Math.abs(collw - cycle_width(collw)) <= delta) { delta = Math.abs(collw - cycle_width(collw)); _MDW = MDW; }
MDW = _MDW;
}
/* XLML specifies width in terms of pixels */
/*function find_mdw_wpx(wpx) {
var delta = Infinity, guess = 0, _MDW = MIN_MDW;
for(MDW=MIN_MDW; MDW<MAX_MDW; ++MDW) {
guess = char2width_(px2char_(wpx))*256;
guess = (guess) % 1;
if(guess > 0.5) guess--;
if(Math.abs(guess) < delta) { delta = Math.abs(guess); _MDW = MDW; }
}
MDW = _MDW;
}*/
function process_col(coll/*:ColInfo*/) {
if(coll.width) {
coll.wpx = width2px(coll.width);
coll.wch = px2char(coll.wpx);
coll.MDW = MDW;
} else if(coll.wpx) {
coll.wch = px2char(coll.wpx);
coll.width = char2width(coll.wch);
coll.MDW = MDW;
} else if(typeof coll.wch == 'number') {
coll.width = char2width(coll.wch);
coll.wpx = width2px(coll.width);
coll.MDW = MDW;
}
if(coll.customWidth) delete coll.customWidth;
}
var DEF_PPI = 96, PPI = DEF_PPI;
function px2pt(px) { return px * 96 / PPI; }
function pt2px(pt) { return pt * PPI / 96; }
/* [MS-EXSPXML3] 2.4.54 ST_enmPattern */
var XLMLPatternTypeMap = {
"None": "none",
"Solid": "solid",
"Gray50": "mediumGray",
"Gray75": "darkGray",
"Gray25": "lightGray",
"HorzStripe": "darkHorizontal",
"VertStripe": "darkVertical",
"ReverseDiagStripe": "darkDown",
"DiagStripe": "darkUp",
"DiagCross": "darkGrid",
"ThickDiagCross": "darkTrellis",
"ThinHorzStripe": "lightHorizontal",
"ThinVertStripe": "lightVertical",
"ThinReverseDiagStripe": "lightDown",
"ThinHorzCross": "lightGrid"
};

View File

@ -1,18 +1,100 @@
/* 18.8.5 borders CT_Borders */
function parse_borders(t, styles, themes, opts) {
styles.Borders = [];
var border = {};
var pass = false;
(t.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<borders': case '<borders>': case '</borders>': break;
/* 18.8.4 border CT_Border */
case '<border': case '<border>': case '<border/>':
border = /*::(*/{}/*:: :any)*/;
if(y.diagonalUp) border.diagonalUp = parsexmlbool(y.diagonalUp);
if(y.diagonalDown) border.diagonalDown = parsexmlbool(y.diagonalDown);
styles.Borders.push(border);
break;
case '</border>': break;
/* note: not in spec, appears to be CT_BorderPr */
case '<left/>': break;
case '<left': case '<left>': break;
case '</left>': break;
/* note: not in spec, appears to be CT_BorderPr */
case '<right/>': break;
case '<right': case '<right>': break;
case '</right>': break;
/* 18.8.43 top CT_BorderPr */
case '<top/>': break;
case '<top': case '<top>': break;
case '</top>': break;
/* 18.8.6 bottom CT_BorderPr */
case '<bottom/>': break;
case '<bottom': case '<bottom>': break;
case '</bottom>': break;
/* 18.8.13 diagonal CT_BorderPr */
case '<diagonal': case '<diagonal>': case '<diagonal/>': break;
case '</diagonal>': break;
/* 18.8.25 horizontal CT_BorderPr */
case '<horizontal': case '<horizontal>': case '<horizontal/>': break;
case '</horizontal>': break;
/* 18.8.44 vertical CT_BorderPr */
case '<vertical': case '<vertical>': case '<vertical/>': break;
case '</vertical>': break;
/* 18.8.37 start CT_BorderPr */
case '<start': case '<start>': case '<start/>': break;
case '</start>': break;
/* 18.8.16 end CT_BorderPr */
case '<end': case '<end>': case '<end/>': break;
case '</end>': break;
/* 18.8.? color CT_Color */
case '<color': case '<color>':
break;
case '<color/>': case '</color>': break;
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': break;
case '<ext': pass = true; break;
case '</ext>': pass = false; break;
default: if(opts && opts.WTF) {
if(!pass) throw new Error('unrecognized ' + y[0] + ' in borders');
}
}
});
}
/* 18.8.21 fills CT_Fills */
function parse_fills(t, opts) {
function parse_fills(t, styles, themes, opts) {
styles.Fills = [];
var fill = {};
t[0].match(tagregex).forEach(function(x) {
var pass = false;
(t.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(y[0]) {
switch(strip_ns(y[0])) {
case '<fills': case '<fills>': case '</fills>': break;
/* 18.8.20 fill CT_Fill */
case '<fill>': break;
case '</fill>': styles.Fills.push(fill); fill = {}; break;
case '<fill>': case '<fill': case '<fill/>':
fill = {}; styles.Fills.push(fill); break;
case '</fill>': break;
/* 18.8.24 gradientFill CT_GradientFill */
case '<gradientFill>': break;
case '<gradientFill':
case '</gradientFill>': styles.Fills.push(fill); fill = {}; break;
/* 18.8.32 patternFill CT_PatternFill */
case '<patternFill':
case '<patternFill': case '<patternFill>':
if(y.patternType) fill.patternType = y.patternType;
break;
case '<patternFill/>': case '</patternFill>': break;
@ -24,7 +106,7 @@ function parse_fills(t, opts) {
if(y.theme) fill.bgColor.theme = parseInt(y.theme, 10);
if(y.tint) fill.bgColor.tint = parseFloat(y.tint);
/* Excel uses ARGB strings */
if(y.rgb) fill.bgColor.rgb = y.rgb.substring(y.rgb.length - 6);
if(y.rgb) fill.bgColor.rgb = y.rgb.slice(-6);
break;
case '<bgColor/>': case '</bgColor>': break;
@ -34,38 +116,181 @@ function parse_fills(t, opts) {
if(y.theme) fill.fgColor.theme = parseInt(y.theme, 10);
if(y.tint) fill.fgColor.tint = parseFloat(y.tint);
/* Excel uses ARGB strings */
if(y.rgb) fill.fgColor.rgb = y.rgb.substring(y.rgb.length - 6);
if(y.rgb != null) fill.fgColor.rgb = y.rgb.slice(-6);
break;
case '<fgColor/>': case '</fgColor>': break;
default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in fills';
/* 18.8.38 stop CT_GradientStop */
case '<stop': case '<stop/>': break;
case '</stop>': break;
/* 18.8.? color CT_Color */
case '<color': case '<color/>': break;
case '</color>': break;
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': break;
case '<ext': pass = true; break;
case '</ext>': pass = false; break;
default: if(opts && opts.WTF) {
if(!pass) throw new Error('unrecognized ' + y[0] + ' in fills');
}
}
});
}
/* 18.8.23 fonts CT_Fonts */
function parse_fonts(t, styles, themes, opts) {
styles.Fonts = [];
var font = {};
var pass = false;
(t.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<fonts': case '<fonts>': case '</fonts>': break;
/* 18.8.22 font CT_Font */
case '<font': case '<font>': break;
case '</font>': case '<font/>':
styles.Fonts.push(font);
font = {};
break;
/* 18.8.29 name CT_FontName */
case '<name': if(y.val) font.name = utf8read(y.val); break;
case '<name/>': case '</name>': break;
/* 18.8.2 b CT_BooleanProperty */
case '<b': font.bold = y.val ? parsexmlbool(y.val) : 1; break;
case '<b/>': font.bold = 1; break;
/* 18.8.26 i CT_BooleanProperty */
case '<i': font.italic = y.val ? parsexmlbool(y.val) : 1; break;
case '<i/>': font.italic = 1; break;
/* 18.4.13 u CT_UnderlineProperty */
case '<u':
switch(y.val) {
case "none": font.underline = 0x00; break;
case "single": font.underline = 0x01; break;
case "double": font.underline = 0x02; break;
case "singleAccounting": font.underline = 0x21; break;
case "doubleAccounting": font.underline = 0x22; break;
} break;
case '<u/>': font.underline = 1; break;
/* 18.4.10 strike CT_BooleanProperty */
case '<strike': font.strike = y.val ? parsexmlbool(y.val) : 1; break;
case '<strike/>': font.strike = 1; break;
/* 18.4.2 outline CT_BooleanProperty */
case '<outline': font.outline = y.val ? parsexmlbool(y.val) : 1; break;
case '<outline/>': font.outline = 1; break;
/* 18.8.36 shadow CT_BooleanProperty */
case '<shadow': font.shadow = y.val ? parsexmlbool(y.val) : 1; break;
case '<shadow/>': font.shadow = 1; break;
/* 18.8.12 condense CT_BooleanProperty */
case '<condense': font.condense = y.val ? parsexmlbool(y.val) : 1; break;
case '<condense/>': font.condense = 1; break;
/* 18.8.17 extend CT_BooleanProperty */
case '<extend': font.extend = y.val ? parsexmlbool(y.val) : 1; break;
case '<extend/>': font.extend = 1; break;
/* 18.4.11 sz CT_FontSize */
case '<sz': if(y.val) font.sz = +y.val; break;
case '<sz/>': case '</sz>': break;
/* 18.4.14 vertAlign CT_VerticalAlignFontProperty */
case '<vertAlign': if(y.val) font.vertAlign = y.val; break;
case '<vertAlign/>': case '</vertAlign>': break;
/* 18.8.18 family CT_FontFamily */
case '<family': if(y.val) font.family = parseInt(y.val,10); break;
case '<family/>': case '</family>': break;
/* 18.8.35 scheme CT_FontScheme */
case '<scheme': if(y.val) font.scheme = y.val; break;
case '<scheme/>': case '</scheme>': break;
/* 18.4.1 charset CT_IntProperty */
case '<charset':
if(y.val == '1') break;
y.codepage = CS2CP[parseInt(y.val, 10)];
break;
/* 18.?.? color CT_Color */
case '<color':
if(!font.color) font.color = {};
if(y.auto) font.color.auto = parsexmlbool(y.auto);
if(y.rgb) font.color.rgb = y.rgb.slice(-6);
else if(y.indexed) {
font.color.index = parseInt(y.indexed, 10);
var icv = XLSIcv[font.color.index];
if(font.color.index == 81) icv = XLSIcv[1];
if(!icv) icv = XLSIcv[1]; //throw new Error(x); // note: 206 is valid
font.color.rgb = icv[0].toString(16) + icv[1].toString(16) + icv[2].toString(16);
} else if(y.theme) {
font.color.theme = parseInt(y.theme, 10);
if(y.tint) font.color.tint = parseFloat(y.tint);
if(y.theme && themes.themeElements && themes.themeElements.clrScheme) {
font.color.rgb = rgb_tint(themes.themeElements.clrScheme[font.color.theme].rgb, font.color.tint || 0);
}
}
break;
case '<color/>': case '</color>': break;
/* note: sometimes mc:AlternateContent appears bare */
case '<AlternateContent': pass = true; break;
case '</AlternateContent>': pass = false; break;
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': break;
case '<ext': pass = true; break;
case '</ext>': pass = false; break;
default: if(opts && opts.WTF) {
if(!pass) throw new Error('unrecognized ' + y[0] + ' in fonts');
}
}
});
}
/* 18.8.31 numFmts CT_NumFmts */
function parse_numFmts(t, opts) {
function parse_numFmts(t, styles, opts) {
styles.NumberFmt = [];
var k = keys(SSF._table);
for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
var m = t[0].match(tagregex);
var k/*Array<number>*/ = (keys(table_fmt)/*:any*/);
for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = table_fmt[k[i]];
var m = t.match(tagregex);
if(!m) return;
for(i=0; i < m.length; ++i) {
var y = parsexmltag(m[i]);
switch(y[0]) {
switch(strip_ns(y[0])) {
case '<numFmts': case '</numFmts>': case '<numFmts/>': case '<numFmts>': break;
case '<numFmt': {
var f=unescapexml(utf8read(y.formatCode)), j=parseInt(y.numFmtId,10);
styles.NumberFmt[j] = f; if(j>0) SSF.load(f,j);
styles.NumberFmt[j] = f;
if(j>0) {
if(j > 0x188) {
for(j = 0x188; j > 0x3c; --j) if(styles.NumberFmt[j] == null) break;
styles.NumberFmt[j] = f;
}
SSF__load(f,j);
}
} break;
default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in numFmts';
case '</numFmt>': break;
default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in numFmts');
}
}
}
function write_numFmts(NF, opts) {
function write_numFmts(NF/*:{[n:number|string]:string}*//*::, opts*/) {
var o = ["<numFmts>"];
[[5,8],[23,26],[41,44],[63,66],[164,392]].forEach(function(r) {
for(var i = r[0]; i <= r[1]; ++i) if(NF[i] !== undefined) o[o.length] = (writextag('numFmt',null,{numFmtId:i,formatCode:escapexml(NF[i])}));
[[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) o[o.length] = (writextag('numFmt',null,{numFmtId:i,formatCode:escapexml(NF[i])}));
});
if(o.length === 1) return "";
o[o.length] = ("</numFmts>");
@ -74,37 +299,69 @@ function write_numFmts(NF, opts) {
}
/* 18.8.10 cellXfs CT_CellXfs */
function parse_cellXfs(t, opts) {
var cellXF_uint = [ "numFmtId", "fillId", "fontId", "borderId", "xfId" ];
var cellXF_bool = [ "applyAlignment", "applyBorder", "applyFill", "applyFont", "applyNumberFormat", "applyProtection", "pivotButton", "quotePrefix" ];
function parse_cellXfs(t, styles, opts) {
styles.CellXf = [];
t[0].match(tagregex).forEach(function(x) {
var y = parsexmltag(x);
switch(y[0]) {
var xf;
var pass = false;
(t.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x), i = 0;
switch(strip_ns(y[0])) {
case '<cellXfs': case '<cellXfs>': case '<cellXfs/>': case '</cellXfs>': break;
/* 18.8.45 xf CT_Xf */
case '<xf': delete y[0];
if(y.numFmtId) y.numFmtId = parseInt(y.numFmtId, 10);
if(y.fillId) y.fillId = parseInt(y.fillId, 10);
styles.CellXf.push(y); break;
case '<xf': case '<xf/>': case '<xf>':
xf = y;
delete xf[0];
for(i = 0; i < cellXF_uint.length; ++i) if(xf[cellXF_uint[i]])
xf[cellXF_uint[i]] = parseInt(xf[cellXF_uint[i]], 10);
for(i = 0; i < cellXF_bool.length; ++i) if(xf[cellXF_bool[i]])
xf[cellXF_bool[i]] = parsexmlbool(xf[cellXF_bool[i]]);
if(styles.NumberFmt && xf.numFmtId > 0x188) {
for(i = 0x188; i > 0x3c; --i) if(styles.NumberFmt[xf.numFmtId] == styles.NumberFmt[i]) { xf.numFmtId = i; break; }
}
styles.CellXf.push(xf); break;
case '</xf>': break;
/* 18.8.1 alignment CT_CellAlignment */
case '<alignment': case '<alignment/>': break;
case '<alignment': case '<alignment/>': case '<alignment>':
var alignment = {};
if(y.vertical) alignment.vertical = y.vertical;
if(y.horizontal) alignment.horizontal = y.horizontal;
if(y.textRotation != null) alignment.textRotation = y.textRotation;
if(y.indent) alignment.indent = y.indent;
if(y.wrapText) alignment.wrapText = parsexmlbool(y.wrapText);
xf.alignment = alignment;
break;
case '</alignment>': break;
/* 18.8.33 protection CT_CellProtection */
case '<protection': case '</protection>': case '<protection/>': break;
case '<protection': case '<protection>':
break;
case '</protection>': case '<protection/>': break;
case '<extLst': case '</extLst>': break;
case '<ext': break;
default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in cellXfs';
/* note: sometimes mc:AlternateContent appears bare */
case '<AlternateContent': case '<AlternateContent>': pass = true; break;
case '</AlternateContent>': pass = false; break;
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': break;
case '<ext': pass = true; break;
case '</ext>': pass = false; break;
default: if(opts && opts.WTF) {
if(!pass) throw new Error('unrecognized ' + y[0] + ' in cellXfs');
}
}
});
}
function write_cellXfs(cellXfs) {
var o = [];
function write_cellXfs(cellXfs)/*:string*/ {
var o/*:Array<string>*/ = [];
o[o.length] = (writextag('cellXfs',null));
cellXfs.forEach(function(c) { o[o.length] = (writextag('xf', null, c)); });
cellXfs.forEach(function(c) {
o[o.length] = (writextag('xf', null, c));
});
o[o.length] = ("</cellXfs>");
if(o.length === 2) return "";
o[0] = writextag('cellXfs',null, {count:o.length-2}).replace("/>",">");
@ -112,49 +369,48 @@ function write_cellXfs(cellXfs) {
}
/* 18.8 Styles CT_Stylesheet*/
var parse_sty_xml= (function make_pstyx() {
var numFmtRegex = /<numFmts([^>]*)>.*<\/numFmts>/;
var cellXfRegex = /<cellXfs([^>]*)>.*<\/cellXfs>/;
var fillsRegex = /<fills([^>]*)>.*<\/fills>/;
var parse_sty_xml= /*#__PURE__*/(function make_pstyx() {
return function parse_sty_xml(data, opts) {
return function parse_sty_xml(data, themes, opts) {
var styles = {};
if(!data) return styles;
data = remove_doctype(str_remove_ng(data, "<!--", "-->"));
/* 18.8.39 styleSheet CT_Stylesheet */
var t;
/* numFmts CT_NumFmts ? */
if((t=data.match(numFmtRegex))) parse_numFmts(t, opts);
/* 18.8.31 numFmts CT_NumFmts ? */
if((t=str_match_xml_ns(data, "numFmts"))) parse_numFmts(t[0], styles, opts);
/* fonts CT_Fonts ? */
/*if((t=data.match(/<fonts([^>]*)>.*<\/fonts>/))) parse_fonts(t, opts);*/
/* 18.8.23 fonts CT_Fonts ? */
if((t=str_match_xml_ns(data, "fonts"))) parse_fonts(t[0], styles, themes, opts);
/* fills CT_Fills */
if((t=data.match(fillsRegex))) parse_fills(t, opts);
/* 18.8.21 fills CT_Fills ? */
if((t=str_match_xml_ns(data, "fills"))) parse_fills(t[0], styles, themes, opts);
/* borders CT_Borders ? */
/* cellStyleXfs CT_CellStyleXfs ? */
/* 18.8.5 borders CT_Borders ? */
if((t=str_match_xml_ns(data, "borders"))) parse_borders(t[0], styles, themes, opts);
/* cellXfs CT_CellXfs ? */
if((t=data.match(cellXfRegex))) parse_cellXfs(t, opts);
/* 18.8.9 cellStyleXfs CT_CellStyleXfs ? */
/* 18.8.8 cellStyles CT_CellStyles ? */
/* dxfs CT_Dxfs ? */
/* tableStyles CT_TableStyles ? */
/* colors CT_Colors ? */
/* extLst CT_ExtensionList ? */
/* 18.8.10 cellXfs CT_CellXfs ? */
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 ? */
/* 18.8.11 colors CT_Colors ? */
/* 18.2.10 extLst CT_ExtensionList ? */
return styles;
};
})();
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, opts) {
var o = [XML_HEADER, STYLES_XML_ROOT], w;
if((w = write_numFmts(wb.SSF)) != null) o[o.length] = w;
function write_sty_xml(wb/*:Workbook*/, opts)/*:string*/ {
var o = [XML_HEADER, writextag('styleSheet', null, {
'xmlns': XMLNS_main[0],
'xmlns:vt': XMLNS.vt
})], w;
if(wb.SSF && (w = write_numFmts(wb.SSF)) != null) o[o.length] = w;
o[o.length] = ('<fonts count="1"><font><sz val="12"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font></fonts>');
o[o.length] = ('<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
o[o.length] = ('<borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>');

View File

@ -1,133 +1,393 @@
/* [MS-XLSB] 2.4.651 BrtFmt */
function parse_BrtFmt(data, length) {
var ifmt = data.read_shift(2);
/* [MS-XLSB] 2.4.657 BrtFmt */
function parse_BrtFmt(data, length/*:number*/) {
var numFmtId = data.read_shift(2);
var stFmtCode = parse_XLWideString(data,length-2);
return [ifmt, stFmtCode];
return [numFmtId, stFmtCode];
}
/* [MS-XLSB] 2.4.653 BrtFont TODO */
function parse_BrtFont(data, length) {
var out = {flags:{}};
out.dyHeight = data.read_shift(2);
out.grbit = parse_FontFlags(data, 2);
out.bls = data.read_shift(2);
out.sss = data.read_shift(2);
out.uls = data.read_shift(1);
out.bFamily = data.read_shift(1);
out.bCharSet = data.read_shift(1);
data.l++;
out.brtColor = parse_BrtColor(data, 8);
out.bFontScheme = data.read_shift(1);
out.name = parse_XLWideString(data, length - 21);
out.flags.Bold = out.bls === 0x02BC;
out.flags.Italic = out.grbit.fItalic;
out.flags.Strikeout = out.grbit.fStrikeout;
out.flags.Outline = out.grbit.fOutline;
out.flags.Shadow = out.grbit.fShadow;
out.flags.Condense = out.grbit.fCondense;
out.flags.Extend = out.grbit.fExtend;
out.flags.Sub = out.sss & 0x2;
out.flags.Sup = out.sss & 0x1;
function write_BrtFmt(i/*:number*/, f/*:string*/, o) {
if(!o) o = new_buf(6 + 4 * f.length);
o.write_shift(2, i);
write_XLWideString(f, o);
var out = (o.length > o.l) ? o.slice(0, o.l) : o;
if(o.l == null) o.l = o.length;
return out;
}
/* [MS-XLSB] 2.4.816 BrtXF */
function parse_BrtXF(data, length) {
/* [MS-XLSB] 2.4.659 BrtFont TODO */
function parse_BrtFont(data, length/*:number*/, opts) {
var out = ({}/*:any*/);
out.sz = data.read_shift(2) / 20;
var grbit = parse_FontFlags(data, 2, opts);
if(grbit.fItalic) out.italic = 1;
if(grbit.fCondense) out.condense = 1;
if(grbit.fExtend) out.extend = 1;
if(grbit.fShadow) out.shadow = 1;
if(grbit.fOutline) out.outline = 1;
if(grbit.fStrikeout) out.strike = 1;
var bls = data.read_shift(2);
if(bls === 0x02BC) out.bold = 1;
switch(data.read_shift(2)) {
/* case 0: out.vertAlign = "baseline"; break; */
case 1: out.vertAlign = "superscript"; break;
case 2: out.vertAlign = "subscript"; break;
}
var underline = data.read_shift(1);
if(underline != 0) out.underline = underline;
var family = data.read_shift(1);
if(family > 0) out.family = family;
var bCharSet = data.read_shift(1);
if(bCharSet > 0) out.charset = bCharSet;
data.l++;
out.color = parse_BrtColor(data, 8);
switch(data.read_shift(1)) {
/* case 0: out.scheme = "none": break; */
case 1: out.scheme = "major"; break;
case 2: out.scheme = "minor"; break;
}
out.name = parse_XLWideString(data, length - 21);
return out;
}
function write_BrtFont(font/*:any*/, o) {
if(!o) o = new_buf(25+4*32);
o.write_shift(2, font.sz * 20);
write_FontFlags(font, o);
o.write_shift(2, font.bold ? 0x02BC : 0x0190);
var sss = 0;
if(font.vertAlign == "superscript") sss = 1;
else if(font.vertAlign == "subscript") sss = 2;
o.write_shift(2, sss);
o.write_shift(1, font.underline || 0);
o.write_shift(1, font.family || 0);
o.write_shift(1, font.charset || 0);
o.write_shift(1, 0);
write_BrtColor(font.color, o);
var scheme = 0;
if(font.scheme == "major") scheme = 1;
if(font.scheme == "minor") scheme = 2;
o.write_shift(1, scheme);
write_XLWideString(font.name, o);
return o.length > o.l ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.650 BrtFill */
var XLSBFillPTNames = [
"none",
"solid",
"mediumGray",
"darkGray",
"lightGray",
"darkHorizontal",
"darkVertical",
"darkDown",
"darkUp",
"darkGrid",
"darkTrellis",
"lightHorizontal",
"lightVertical",
"lightDown",
"lightUp",
"lightGrid",
"lightTrellis",
"gray125",
"gray0625"
];
var rev_XLSBFillPTNames/*:EvertNumType*/;
/* TODO: gradient fill representation */
var parse_BrtFill = parsenoop;
function write_BrtFill(fill, o) {
if(!o) o = new_buf(4*3 + 8*7 + 16*1);
if(!rev_XLSBFillPTNames) rev_XLSBFillPTNames = (evert(XLSBFillPTNames)/*:any*/);
var fls/*:number*/ = rev_XLSBFillPTNames[fill.patternType];
if(fls == null) fls = 0x28;
o.write_shift(4, fls);
var j = 0;
if(fls != 0x28) {
/* TODO: custom FG Color */
write_BrtColor({auto:1}, o);
/* TODO: custom BG Color */
write_BrtColor({auto:1}, o);
for(; j < 12; ++j) o.write_shift(4, 0);
} else {
for(; j < 4; ++j) o.write_shift(4, 0);
for(; j < 12; ++j) o.write_shift(4, 0); /* TODO */
/* iGradientType */
/* xnumDegree */
/* xnumFillToLeft */
/* xnumFillToRight */
/* xnumFillToTop */
/* xnumFillToBottom */
/* cNumStop */
/* xfillGradientStop */
}
return o.length > o.l ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.824 BrtXF */
function parse_BrtXF(data, length/*:number*/) {
var tgt = data.l + length;
var ixfeParent = data.read_shift(2);
var ifmt = data.read_shift(2);
parsenoop(data, length-4);
return {ixfe:ixfeParent, ifmt:ifmt };
data.l = tgt;
return {ixfe:ixfeParent, numFmtId:ifmt };
}
function write_BrtXF(data, ixfeP, o) {
if(!o) o = new_buf(16);
o.write_shift(2, ixfeP||0);
o.write_shift(2, data.numFmtId||0);
o.write_shift(2, 0); /* iFont */
o.write_shift(2, 0); /* iFill */
o.write_shift(2, 0); /* ixBorder */
o.write_shift(1, 0); /* trot */
o.write_shift(1, 0); /* indent */
var flow = 0;
o.write_shift(1, flow); /* flags */
o.write_shift(1, 0); /* flags */
o.write_shift(1, 0); /* xfGrbitAtr */
o.write_shift(1, 0);
return o;
}
/* [MS-XLSB] 2.5.4 Blxf TODO */
function write_Blxf(data, o) {
if(!o) o = new_buf(10);
o.write_shift(1, 0); /* dg */
o.write_shift(1, 0);
o.write_shift(4, 0); /* color */
o.write_shift(4, 0); /* color */
return o;
}
/* [MS-XLSB] 2.4.302 BrtBorder TODO */
var parse_BrtBorder = parsenoop;
function write_BrtBorder(border, o) {
if(!o) o = new_buf(51);
o.write_shift(1, 0); /* diagonal */
write_Blxf(null, o); /* top */
write_Blxf(null, o); /* bottom */
write_Blxf(null, o); /* left */
write_Blxf(null, o); /* right */
write_Blxf(null, o); /* diag */
return o.length > o.l ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.763 BrtStyle TODO */
function write_BrtStyle(style, o) {
if(!o) o = new_buf(12+4*10);
o.write_shift(4, style.xfId);
o.write_shift(2, 1);
o.write_shift(1, +style.builtinId);
o.write_shift(1, 0); /* iLevel */
write_XLNullableWideString(style.name || "", o);
return o.length > o.l ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.272 BrtBeginTableStyles */
function write_BrtBeginTableStyles(cnt, defTableStyle, defPivotStyle) {
var o = new_buf(4+256*2*4);
o.write_shift(4, cnt);
write_XLNullableWideString(defTableStyle, o);
write_XLNullableWideString(defPivotStyle, o);
return o.length > o.l ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.1.7.50 Styles */
function parse_sty_bin(data, opts) {
styles.NumberFmt = [];
for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y];
function parse_sty_bin(data, themes, opts) {
var styles = {};
styles.NumberFmt = ([]/*:any*/);
for(var y in table_fmt) styles.NumberFmt[y] = table_fmt[y];
styles.CellXf = [];
var state = ""; /* TODO: this should be a stack */
styles.Fonts = [];
var state/*:Array<string>*/ = [];
var pass = false;
recordhopper(data, function hopper_sty(val, R, RT) {
switch(R.n) {
case 'BrtFmt':
styles.NumberFmt[val[0]] = val[1]; SSF.load(val[1], val[0]);
switch(RT) {
case 0x002C: /* BrtFmt */
styles.NumberFmt[val[0]] = val[1]; SSF__load(val[1], val[0]);
break;
case 'BrtFont': break; /* TODO */
case 'BrtKnownFonts': break; /* TODO */
case 'BrtFill': break; /* TODO */
case 'BrtBorder': break; /* TODO */
case 'BrtXF':
if(state === "CELLXFS") {
case 0x002B: /* BrtFont */
styles.Fonts.push(val);
if(val.color.theme != null && themes && themes.themeElements && themes.themeElements.clrScheme) {
val.color.rgb = rgb_tint(themes.themeElements.clrScheme[val.color.theme].rgb, val.color.tint || 0);
}
break;
case 0x0401: /* BrtKnownFonts */ break;
case 0x002D: /* BrtFill */
break;
case 0x002E: /* BrtBorder */
break;
case 0x002F: /* BrtXF */
if(state[state.length - 1] == 0x0269 /* BrtBeginCellXFs */) {
styles.CellXf.push(val);
}
break; /* TODO */
case 'BrtStyle': break; /* TODO */
case 'BrtDXF': break; /* TODO */
case 'BrtMRUColor': break; /* TODO */
case 'BrtIndexedColor': break; /* TODO */
case 'BrtBeginStyleSheet': break;
case 'BrtEndStyleSheet': break;
case 'BrtBeginTableStyle': break;
case 'BrtTableStyleElement': break;
case 'BrtEndTableStyle': break;
case 'BrtBeginFmts': state = "FMTS"; break;
case 'BrtEndFmts': state = ""; break;
case 'BrtBeginFonts': state = "FONTS"; break;
case 'BrtEndFonts': state = ""; break;
case 'BrtACBegin': state = "ACFONTS"; break;
case 'BrtACEnd': state = ""; break;
case 'BrtBeginFills': state = "FILLS"; break;
case 'BrtEndFills': state = ""; break;
case 'BrtBeginBorders': state = "BORDERS"; break;
case 'BrtEndBorders': state = ""; break;
case 'BrtBeginCellStyleXFs': state = "CELLSTYLEXFS"; break;
case 'BrtEndCellStyleXFs': state = ""; break;
case 'BrtBeginCellXFs': state = "CELLXFS"; break;
case 'BrtEndCellXFs': state = ""; break;
case 'BrtBeginStyles': state = "STYLES"; break;
case 'BrtEndStyles': state = ""; break;
case 'BrtBeginDXFs': state = "DXFS"; break;
case 'BrtEndDXFs': state = ""; break;
case 'BrtBeginTableStyles': state = "TABLESTYLES"; break;
case 'BrtEndTableStyles': state = ""; break;
case 'BrtBeginColorPalette': state = "COLORPALETTE"; break;
case 'BrtEndColorPalette': state = ""; break;
case 'BrtBeginIndexedColors': state = "INDEXEDCOLORS"; break;
case 'BrtEndIndexedColors': state = ""; break;
case 'BrtBeginMRUColors': state = "MRUCOLORS"; break;
case 'BrtEndMRUColors': state = ""; break;
case 'BrtFRTBegin': pass = true; break;
case 'BrtFRTEnd': pass = false; break;
case 'BrtBeginStyleSheetExt14': break;
case 'BrtBeginSlicerStyles': break;
case 'BrtEndSlicerStyles': break;
case 'BrtBeginTimelineStylesheetExt15': break;
case 'BrtEndTimelineStylesheetExt15': break;
case 'BrtBeginTimelineStyles': break;
case 'BrtEndTimelineStyles': break;
case 'BrtEndStyleSheetExt14': break;
default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
break;
case 0x0030: /* BrtStyle */
case 0x01FB: /* BrtDXF */
case 0x023C: /* BrtMRUColor */
case 0x01DB: /* BrtIndexedColor */
break;
case 0x0493: /* BrtDXF14 */
case 0x0836: /* BrtDXF15 */
case 0x046A: /* BrtSlicerStyleElement */
case 0x0200: /* BrtTableStyleElement */
case 0x082F: /* BrtTimelineStyleElement */
case 0x0C00: /* BrtUid */
break;
case 0x0023: /* BrtFRTBegin */
pass = true; break;
case 0x0024: /* BrtFRTEnd */
pass = false; break;
case 0x0025: /* BrtACBegin */
state.push(RT); pass = true; break;
case 0x0026: /* BrtACEnd */
state.pop(); pass = false; break;
default:
if(R.T > 0) state.push(RT);
else if(R.T < 0) state.pop();
else if(!pass || (opts.WTF && state[state.length-1] != 0x0025 /* BrtACBegin */)) throw new Error("Unexpected record 0x" + RT.toString(16));
}
});
return styles;
}
function write_FMTS_bin(ba, NF/*:?SSFTable*/) {
if(!NF) return;
var cnt = 0;
[[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
/*:: if(!NF) return; */
for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) ++cnt;
});
if(cnt == 0) return;
write_record(ba, 0x0267 /* BrtBeginFmts */, write_UInt32LE(cnt));
[[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
/*:: if(!NF) return; */
for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_record(ba, 0x002C /* BrtFmt */, write_BrtFmt(i, NF[i]));
});
write_record(ba, 0x0268 /* BrtEndFmts */);
}
function write_FONTS_bin(ba/*::, data*/) {
var cnt = 1;
if(cnt == 0) return;
write_record(ba, 0x0263 /* BrtBeginFonts */, write_UInt32LE(cnt));
write_record(ba, 0x002B /* BrtFont */, write_BrtFont({
sz:12,
color: {theme:1},
name: "Calibri",
family: 2,
scheme: "minor"
}));
/* 1*65491BrtFont [ACFONTS] */
write_record(ba, 0x0264 /* BrtEndFonts */);
}
function write_FILLS_bin(ba/*::, data*/) {
var cnt = 2;
if(cnt == 0) return;
write_record(ba, 0x025B /* BrtBeginFills */, write_UInt32LE(cnt));
write_record(ba, 0x002D /* BrtFill */, write_BrtFill({patternType:"none"}));
write_record(ba, 0x002D /* BrtFill */, write_BrtFill({patternType:"gray125"}));
/* 1*65431BrtFill */
write_record(ba, 0x025C /* BrtEndFills */);
}
function write_BORDERS_bin(ba/*::, data*/) {
var cnt = 1;
if(cnt == 0) return;
write_record(ba, 0x0265 /* BrtBeginBorders */, write_UInt32LE(cnt));
write_record(ba, 0x002E /* BrtBorder */, write_BrtBorder({}));
/* 1*65430BrtBorder */
write_record(ba, 0x0266 /* BrtEndBorders */);
}
function write_CELLSTYLEXFS_bin(ba/*::, data*/) {
var cnt = 1;
write_record(ba, 0x0272 /* BrtBeginCellStyleXFs */, write_UInt32LE(cnt));
write_record(ba, 0x002F /* BrtXF */, write_BrtXF({
numFmtId: 0,
fontId: 0,
fillId: 0,
borderId: 0
}, 0xFFFF));
/* 1*65430(BrtXF *FRT) */
write_record(ba, 0x0273 /* BrtEndCellStyleXFs */);
}
function write_CELLXFS_bin(ba, data) {
write_record(ba, 0x0269 /* BrtBeginCellXFs */, write_UInt32LE(data.length));
data.forEach(function(c) { write_record(ba, 0x002F /* BrtXF */, write_BrtXF(c,0)); });
/* 1*65430(BrtXF *FRT) */
write_record(ba, 0x026A /* BrtEndCellXFs */);
}
function write_STYLES_bin(ba/*::, data*/) {
var cnt = 1;
write_record(ba, 0x026B /* BrtBeginStyles */, write_UInt32LE(cnt));
write_record(ba, 0x0030 /* BrtStyle */, write_BrtStyle({
xfId:0,
builtinId:0,
name:"Normal"
}));
/* 1*65430(BrtStyle *FRT) */
write_record(ba, 0x026C /* BrtEndStyles */);
}
function write_DXFS_bin(ba/*::, data*/) {
var cnt = 0;
write_record(ba, 0x01F9 /* BrtBeginDXFs */, write_UInt32LE(cnt));
/* *2147483647(BrtDXF *FRT) */
write_record(ba, 0x01FA /* BrtEndDXFs */);
}
function write_TABLESTYLES_bin(ba/*::, data*/) {
var cnt = 0;
write_record(ba, 0x01FC /* BrtBeginTableStyles */, write_BrtBeginTableStyles(cnt, "TableStyleMedium9", "PivotStyleMedium4"));
/* *TABLESTYLE */
write_record(ba, 0x01FD /* BrtEndTableStyles */);
}
function write_COLORPALETTE_bin(/*::ba, data*/) {
return;
/* BrtBeginColorPalette [INDEXEDCOLORS] [MRUCOLORS] BrtEndColorPalette */
}
/* [MS-XLSB] 2.1.7.50 Styles */
function write_sty_bin(data, opts) {
function write_sty_bin(wb, opts) {
var ba = buf_array();
write_record(ba, "BrtBeginStyleSheet");
/* [FMTS] */
/* [FONTS] */
/* [FILLS] */
/* [BORDERS] */
/* CELLSTYLEXFS */
/* CELLXFS*/
/* STYLES */
/* DXFS */
/* TABLESTYLES */
/* [COLORPALETTE] */
write_record(ba, 0x0116 /* BrtBeginStyleSheet */);
write_FMTS_bin(ba, wb.SSF);
write_FONTS_bin(ba, wb);
write_FILLS_bin(ba, wb);
write_BORDERS_bin(ba, wb);
write_CELLSTYLEXFS_bin(ba, wb);
write_CELLXFS_bin(ba, opts.cellXfs);
write_STYLES_bin(ba, wb);
write_DXFS_bin(ba, wb);
write_TABLESTYLES_bin(ba, wb);
write_COLORPALETTE_bin(ba, wb);
/* FRTSTYLESHEET*/
write_record(ba, "BrtEndStyleSheet");
write_record(ba, 0x0117 /* BrtEndStyleSheet */);
return ba.end();
}

File diff suppressed because one or more lines are too long

View File

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

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

85
bits/51_xlsxmeta.js Normal file
View File

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

52
bits/52_calcchain.js Normal file
View File

@ -0,0 +1,52 @@
/* 18.6 Calculation Chain */
function parse_cc_xml(data/*::, name, opts*/)/*:Array<any>*/ {
var d = [];
if(!data) return d;
var i = 1;
(data.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(y[0]) {
case '<?xml': break;
/* 18.6.2 calcChain CT_CalcChain 1 */
case '<calcChain': case '<calcChain>': case '</calcChain>': break;
/* 18.6.1 c CT_CalcCell 1 */
case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break;
}
});
return d;
}
//function write_cc_xml(data, opts) { }
/* [MS-XLSB] 2.6.4.1 */
function parse_BrtCalcChainItem$(data) {
var out = {};
out.i = data.read_shift(4);
var cell = {};
cell.r = data.read_shift(4);
cell.c = data.read_shift(4);
out.r = encode_cell(cell);
var flags = data.read_shift(1);
if(flags & 0x2) out.l = '1';
if(flags & 0x8) out.a = '1';
return out;
}
/* 18.6 Calculation Chain */
function parse_cc_bin(data, name, opts) {
var out = [];
var pass = false;
recordhopper(data, function hopper_cc(val, R, RT) {
switch(RT) {
case 0x003F: /* 'BrtCalcChainItem$' */
out.push(val); break;
default:
if(R.T){/* empty */}
else if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
}
});
return out;
}
//function write_cc_bin(data, opts) { }

View File

@ -1,18 +0,0 @@
/* 18.6 Calculation Chain */
function parse_cc_xml(data, opts) {
var d = [];
var l = 0, i = 1;
(data.match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(y[0]) {
case '<?xml': break;
/* 18.6.2 calcChain CT_CalcChain 1 */
case '<calcChain': case '<calcChain>': case '</calcChain>': break;
/* 18.6.1 c CT_CalcCell 1 */
case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break;
}
});
return d;
}
function write_cc_xml(data, opts) { }

View File

@ -1,30 +0,0 @@
/* [MS-XLSB] 2.6.4.1 */
function parse_BrtCalcChainItem$(data, length) {
var out = {};
out.i = data.read_shift(4);
var cell = {};
cell.r = data.read_shift(4);
cell.c = data.read_shift(4);
out.r = encode_cell(cell);
var flags = data.read_shift(1);
if(flags & 0x2) out.l = '1';
if(flags & 0x8) out.a = '1';
return out;
}
/* 18.6 Calculation Chain */
function parse_cc_bin(data, opts) {
var out = [];
var pass = false;
recordhopper(data, function hopper_cc(val, R, RT) {
switch(R.n) {
case 'BrtCalcChainItem$': out.push(val); break;
case 'BrtBeginCalcChain$': break;
case 'BrtEndCalcChain$': break;
default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
}
});
return out;
}
function write_cc_bin(data, opts) { }

50
bits/53_externlink.js Normal file
View File

@ -0,0 +1,50 @@
/* 18.14 Supplementary Workbook Data */
function parse_xlink_xml(/*::data, rel, name:string, _opts*/) {
//var opts = _opts || {};
//if(opts.WTF) throw "XLSX External Link";
}
/* [MS-XLSB] 2.1.7.25 External Link */
function parse_xlink_bin(data, rel, name/*:string*/, _opts) {
if(!data) return data;
var opts = _opts || {};
var pass = false, end = false;
recordhopper(data, function xlink_parse(val, R, RT) {
if(end) return;
switch(RT) {
case 0x0167: /* 'BrtSupTabs' */
case 0x016B: /* 'BrtExternTableStart' */
case 0x016C: /* 'BrtExternTableEnd' */
case 0x016E: /* 'BrtExternRowHdr' */
case 0x016F: /* 'BrtExternCellBlank' */
case 0x0170: /* 'BrtExternCellReal' */
case 0x0171: /* 'BrtExternCellBool' */
case 0x0172: /* 'BrtExternCellError' */
case 0x0173: /* 'BrtExternCellString' */
case 0x01D8: /* 'BrtExternValueMeta' */
case 0x0241: /* 'BrtSupNameStart' */
case 0x0242: /* 'BrtSupNameValueStart' */
case 0x0243: /* 'BrtSupNameValueEnd' */
case 0x0244: /* 'BrtSupNameNum' */
case 0x0245: /* 'BrtSupNameErr' */
case 0x0246: /* 'BrtSupNameSt' */
case 0x0247: /* 'BrtSupNameNil' */
case 0x0248: /* 'BrtSupNameBool' */
case 0x0249: /* 'BrtSupNameFmla' */
case 0x024A: /* 'BrtSupNameBits' */
case 0x024B: /* 'BrtSupNameEnd' */
break;
case 0x0023: /* 'BrtFRTBegin' */
pass = true; break;
case 0x0024: /* 'BrtFRTEnd' */
pass = false; break;
default:
if(R.T){/* empty */}
else if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
}
}, opts);
}

20
bits/54_drawing.js Normal file
View File

@ -0,0 +1,20 @@
/* 20.5 DrawingML - SpreadsheetML Drawing */
/* 20.5.2.35 wsDr CT_Drawing */
function parse_drawing(data, rels/*:any*/) {
if(!data) return "??";
/*
Chartsheet Drawing:
- 20.5.2.35 wsDr CT_Drawing
- 20.5.2.1 absoluteAnchor CT_AbsoluteAnchor
- 20.5.2.16 graphicFrame CT_GraphicalObjectFrame
- 20.1.2.2.16 graphic CT_GraphicalObject
- 20.1.2.2.17 graphicData CT_GraphicalObjectData
- chart reference
the actual type is based on the URI of the graphicData
TODO: handle embedded charts and other types of graphics
*/
var id = (data.match(/<c:chart [^<>]*r:id="([^<>"]*)"/)||["",""])[1];
return rels['!id'][id].Target;
}

94
bits/55_vml.js Normal file
View File

@ -0,0 +1,94 @@
/* L.5.5.2 SpreadsheetML Comments + VML Schema */
function parse_vml(data/*:string*/, sheet, comments) {
var cidx = 0;
(str_match_xml_ns_g(data, "shape")||[]).forEach(function(m) {
var type = "";
var hidden = true;
var aidx = -1;
var R = -1, C = -1;
m.replace(tagregex, function(x/*:string*/, idx/*:number*/) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<ClientData': if(y.ObjectType) type = y.ObjectType; break;
case '<Visible': case '<Visible/>': hidden = false; break;
case '<Row': case '<Row>': aidx = idx + x.length; break;
case '</Row>': R = +m.slice(aidx, idx).trim(); break;
case '<Column': case '<Column>': aidx = idx + x.length; break;
case '</Column>': C = +m.slice(aidx, idx).trim(); break;
}
return "";
});
switch(type) {
case 'Note':
var cell = ws_get_cell_stub(sheet, ((R>=0 && C>=0) ? encode_cell({r:R,c:C}) : comments[cidx].ref));
if(cell.c) {
cell.c.hidden = hidden;
}
++cidx;
break;
}
});
}
/* comment boxes */
function write_vml(rId/*:number*/, comments, ws) {
var csize = [21600, 21600];
/* L.5.2.1.2 Path Attribute */
var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(",");
var o = [
writextag("xml", null, { 'xmlns:v': XLMLNS.v, 'xmlns:o': XLMLNS.o, 'xmlns:x': XLMLNS.x, 'xmlns:mv': XLMLNS.mv }).replace(/\/>/,">"),
writextag("o:shapelayout", writextag("o:idmap", null, {'v:ext':"edit", 'data':rId}), {'v:ext':"edit"})
];
var _shapeid = 65536 * rId;
var _comments = comments || [];
if(_comments.length > 0) o.push(writextag("v:shapetype", [
writextag("v:stroke", null, {joinstyle:"miter"}),
writextag("v:path", null, {gradientshapeok:"t", 'o:connecttype':"rect"})
].join(""), {id:"_x0000_t202", coordsize:csize.join(","), 'o:spt':202, path:bbox}));
_comments.forEach(function(x) { ++_shapeid; o.push(write_vml_comment(x, _shapeid)); });
o.push('</xml>');
return o.join("");
}
function write_vml_comment(x, _shapeid, ws)/*:string*/ {
var c = decode_cell(x[0]);
var fillopts = /*::(*/{'color2':"#BEFF82", 'type':"gradient"}/*:: :any)*/;
if(fillopts.type == "gradient") fillopts.angle = "-180";
var fillparm = fillopts.type == "gradient" ? writextag("o:fill", null, {type:"gradientUnscaled", 'v:ext':"view"}) : null;
var fillxml = writextag('v:fill', fillparm, fillopts);
var shadata = ({on:"t", 'obscured':"t"}/*:any*/);
return [
'<v:shape' + wxt_helper({
id:'_x0000_s' + _shapeid,
type:"#_x0000_t202",
style:"position:absolute; margin-left:80pt;margin-top:5pt;width:104pt;height:64pt;z-index:10" + (x[1].hidden ? ";visibility:hidden" : "") ,
fillcolor:"#ECFAD4",
strokecolor:"#edeaa1"
}) + '>',
fillxml,
writextag("v:shadow", null, shadata),
writextag("v:path", null, {'o:connecttype':"none"}),
'<v:textbox><div style="text-align:left"></div></v:textbox>',
'<x:ClientData ObjectType="Note">',
'<x:MoveWithCells/>',
'<x:SizeWithCells/>',
/* Part 4 19.4.2.3 Anchor (Anchor) */
writetag('x:Anchor', [c.c+1, 0, c.r+1, 0, c.c+3, 20, c.r+5, 20].join(",")),
writetag('x:AutoFill', "False"),
writetag('x:Row', String(c.r)),
writetag('x:Column', String(c.c)),
x[1].hidden ? '' : '<x:Visible/>',
'</x:ClientData>',
'</v:shape>'
].join("");
}

View File

@ -1,42 +1,38 @@
function parse_comments(zip, dirComments, sheets, sheetRels, opts) {
for(var i = 0; i != dirComments.length; ++i) {
var canonicalpath=dirComments[i];
var comments=parse_cmnt(getzipdata(zip, canonicalpath.replace(/^\//,''), true), canonicalpath, opts);
if(!comments || !comments.length) continue;
// find the sheets targeted by these comments
var sheetNames = keys(sheets);
for(var j = 0; j != sheetNames.length; ++j) {
var sheetName = sheetNames[j];
var rels = sheetRels[sheetName];
if(rels) {
var rel = rels[canonicalpath];
if(rel) insertCommentsIntoSheet(sheetName, sheets[sheetName], comments);
}
}
}
}
function insertCommentsIntoSheet(sheetName, sheet, comments) {
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 cell = sheet[comment.ref];
var r = decode_cell(comment.ref);
if(r.r < 0 || r.c < 0) return;
if(dense) {
if(!sheet["!data"][r.r]) sheet["!data"][r.r] = [];
cell = sheet["!data"][r.r][r.c];
} else cell = sheet[comment.ref];
if (!cell) {
cell = {};
sheet[comment.ref] = cell;
cell = ({t:"z"}/*:any*/);
if(dense) sheet["!data"][r.r][r.c] = cell;
else sheet[comment.ref] = cell;
var range = safe_decode_range(sheet["!ref"]||"BDWGO1000001:A1");
var thisCell = decode_cell(comment.ref);
if(range.s.r > thisCell.r) range.s.r = thisCell.r;
if(range.e.r < thisCell.r) range.e.r = thisCell.r;
if(range.s.c > thisCell.c) range.s.c = thisCell.c;
if(range.e.c < thisCell.c) range.e.c = thisCell.c;
if(range.s.r > r.r) range.s.r = r.r;
if(range.e.r < r.r) range.e.r = r.r;
if(range.s.c > r.c) range.s.c = r.c;
if(range.e.c < r.c) range.e.c = r.c;
var encoded = encode_range(range);
if (encoded !== sheet["!ref"]) sheet["!ref"] = encoded;
sheet["!ref"] = encoded;
}
if (!cell.c) cell.c = [];
var o = {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

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

View File

@ -1,5 +1,5 @@
/* [MS-XLSB] 2.4.28 BrtBeginComment */
function parse_BrtBeginComment(data, length) {
function parse_BrtBeginComment(data) {
var out = {};
out.iauthor = data.read_shift(4);
var rfx = parse_UncheckedRfX(data, 16);
@ -8,39 +8,97 @@ function parse_BrtBeginComment(data, length) {
data.l += 16; /*var guid = parse_GUID(data); */
return out;
}
function write_BrtBeginComment(data, o) {
if(o == null) o = new_buf(36);
o.write_shift(4, data[1].iauthor);
write_UncheckedRfX((data[0]/*:any*/), o);
o.write_shift(4, 0);
o.write_shift(4, 0);
o.write_shift(4, 0);
o.write_shift(4, 0);
return o;
}
/* [MS-XLSB] 2.4.324 BrtCommentAuthor */
/* [MS-XLSB] 2.4.327 BrtCommentAuthor */
var parse_BrtCommentAuthor = parse_XLWideString;
/* [MS-XLSB] 2.4.325 BrtCommentText */
var parse_BrtCommentText = parse_RichStr;
function write_BrtCommentAuthor(data) { return write_XLWideString(data.slice(0, 54)); }
/* [MS-XLSB] 2.1.7.8 Comments */
function parse_comments_bin(data, opts) {
var out = [];
var authors = [];
function parse_comments_bin(data, opts)/*:Array<RawComment>*/ {
var out/*:Array<RawComment>*/ = [];
var authors/*:Array<string>*/ = [];
var c = {};
var pass = false;
recordhopper(data, function hopper_cmnt(val, R, RT) {
switch(R.n) {
case 'BrtCommentAuthor': authors.push(val); break;
case 'BrtBeginComment': c = val; break;
case 'BrtCommentText': c.t = val.t; c.h = val.h; c.r = val.r; break;
case 'BrtEndComment':
switch(RT) {
case 0x0278: /* 'BrtCommentAuthor' */
authors.push(val); break;
case 0x027B: /* 'BrtBeginComment' */
c = val; break;
case 0x027D: /* 'BrtCommentText' */
c.t = val.t; c.h = val.h; c.r = val.r; break;
case 0x027C: /* 'BrtEndComment' */
c.author = authors[c.iauthor];
delete c.iauthor;
if(opts.sheetRows && opts.sheetRows <= c.rfx.r) break;
delete (c/*:any*/).iauthor;
if(opts.sheetRows && c.rfx && opts.sheetRows <= c.rfx.r) break;
if(!c.t) c.t = "";
delete c.rfx; out.push(c); break;
case 'BrtBeginComments': break;
case 'BrtEndComments': break;
case 'BrtBeginCommentAuthors': break;
case 'BrtEndCommentAuthors': break;
case 'BrtBeginCommentList': break;
case 'BrtEndCommentList': break;
default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
case 0x0C00: /* 'BrtUid' */
break;
case 0x0023: /* 'BrtFRTBegin' */
pass = true; break;
case 0x0024: /* 'BrtFRTEnd' */
pass = false; break;
case 0x0025: /* 'BrtACBegin' */ break;
case 0x0026: /* 'BrtACEnd' */ break;
default:
if(R.T){/* empty */}
else if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
}
});
return out;
}
function write_comments_bin(data, opts) { }
function write_comments_bin(data/*::, opts*/) {
var ba = buf_array();
var iauthor/*:Array<string>*/ = [];
write_record(ba, 0x0274 /* BrtBeginComments */);
write_record(ba, 0x0276 /* BrtBeginCommentAuthors */);
data.forEach(function(comment) {
comment[1].forEach(function(c) {
if(iauthor.indexOf(c.a) > -1) return;
iauthor.push(c.a.slice(0,54));
write_record(ba, 0x0278 /* BrtCommentAuthor */, write_BrtCommentAuthor(c.a));
if(c.T && c.ID && iauthor.indexOf("tc=" + c.ID) == -1) {
iauthor.push("tc=" + c.ID);
write_record(ba, 0x0278 /* BrtCommentAuthor */, write_BrtCommentAuthor("tc=" + c.ID));
}
});
});
write_record(ba, 0x0277 /* BrtEndCommentAuthors */);
write_record(ba, 0x0279 /* BrtBeginCommentList */);
data.forEach(function(comment) {
comment[1].forEach(function(c) {
var _ia = -1;
if(c.ID) _ia = iauthor.indexOf("tc=" + c.ID);
if(_ia == -1 && comment[1][0].T && comment[1][0].ID) _ia = iauthor.indexOf("tc=" + comment[1][0].ID);
if(_ia == -1) _ia = iauthor.indexOf(c.a);
c.iauthor = _ia;
var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])};
write_record(ba, 0x027B /* BrtBeginComment */, write_BrtBeginComment([range, c]));
if(c.t && c.t.length > 0) write_record(ba, 0x027D /* BrtCommentText */, write_BrtCommentText(c));
write_record(ba, 0x027C /* BrtEndComment */);
delete c.iauthor;
});
});
write_record(ba, 0x027A /* BrtEndCommentList */);
write_record(ba, 0x0275 /* BrtEndComments */);
return ba.end();
}

21
bits/59_vba.js Normal file
View File

@ -0,0 +1,21 @@
var CT_VBA = "application/vnd.ms-office.vbaProject";
function make_vba_xls(cfb) {
var newcfb = CFB.utils.cfb_new({ root: "R" });
cfb.FullPaths.forEach(function(p, i) {
if (p.slice(-1) === "/" || !p.match(/_VBA_PROJECT_CUR/))
return;
var newpath = p.replace(/^[^\/]*/, "R").replace(/\/_VBA_PROJECT_CUR\u0000*/, "");
CFB.utils.cfb_add(newcfb, newpath, cfb.FileIndex[i].content);
});
return CFB.write(newcfb);
}
function fill_vba_xls(cfb, vba) {
vba.FullPaths.forEach(function(p, i) {
if (i == 0)
return;
var newpath = p.replace(/^[\/]*[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
if (newpath.slice(-1) !== "/")
CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content);
});
}
var VBAFMTS = ["xlsb", "xlsm", "xlam", "biff8", "xla"];

5
bits/60_macrovba.js Normal file
View File

@ -0,0 +1,5 @@
/* macro and dialog sheet stubs */
function parse_ds_bin(/*::data:any, opts, idx:number, rels, wb, themes, styles*/)/*:Worksheet*/ { return {'!type':'dialog'}; }
function parse_ds_xml(/*::data:any, opts, idx:number, rels, wb, themes, styles*/)/*:Worksheet*/ { return {'!type':'dialog'}; }
function parse_ms_bin(/*::data:any, opts, idx:number, rels, wb, themes, styles*/)/*:Worksheet*/ { return {'!type':'macro'}; }
function parse_ms_xml(/*::data:any, opts, idx:number, rels, wb, themes, styles*/)/*:Worksheet*/ { return {'!type':'macro'}; }

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,331 @@
/* [MS-XLSB] 2.5.97.4 CellParsedFormula TODO: use similar logic to js-xls */
function parse_XLSBCellParsedFormula(data, length) {
var cce = data.read_shift(4);
return parsenoop(data, length-4);
/* [MS-XLS] 2.5.198.1 TODO */
function parse_ArrayParsedFormula(blob, length, opts/*::, ref*/) {
var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
var rgcb, cce = blob.read_shift(len); // length of rgce
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
var rgce = parse_Rgce(blob, cce, opts);
if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
blob.l = target;
return [rgce, rgcb];
}
/* [MS-XLS] 2.5.198.3 TODO */
function parse_XLSCellParsedFormula(blob, length, opts) {
var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
var rgcb, cce = blob.read_shift(len); // length of rgce
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
var rgce = parse_Rgce(blob, cce, opts);
if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
blob.l = target;
return [rgce, rgcb];
}
/* [MS-XLS] 2.5.198.21 */
function parse_NameParsedFormula(blob, length, opts, cce) {
var target = blob.l + length;
var rgce = parse_Rgce(blob, cce, opts);
var rgcb;
if(target !== blob.l) rgcb = parse_RgbExtra(blob, target - blob.l, rgce, opts);
return [rgce, rgcb];
}
/* [MS-XLS] 2.5.198.118 TODO */
function parse_SharedParsedFormula(blob, length, opts) {
var target = blob.l + length;
var rgcb, cce = blob.read_shift(2); // length of rgce
var rgce = parse_Rgce(blob, cce, opts);
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
return [rgce, rgcb];
}
/* [MS-XLS] 2.5.133 TODO: how to emit empty strings? */
function parse_FormulaValue(blob/*::, length*/) {
var b;
if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return [parse_Xnum(blob),'n'];
switch(blob[blob.l]) {
case 0x00: blob.l += 8; return ["String", 's'];
case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return [b,'b'];
case 0x02: b = blob[blob.l+2]; blob.l += 8; return [b,'e'];
case 0x03: blob.l += 8; return ["",'s'];
}
return [];
}
function write_FormulaValue(value) {
if(value == null) {
// Blank String Value
var o = new_buf(8);
o.write_shift(1, 0x03);
o.write_shift(1, 0);
o.write_shift(2, 0);
o.write_shift(2, 0);
o.write_shift(2, 0xFFFF);
return o;
} else if(typeof value == "number") return write_Xnum(value);
return write_Xnum(0);
}
/* [MS-XLS] 2.4.127 TODO */
function parse_Formula(blob, length, opts) {
var end = blob.l + length;
var cell = parse_XLSCell(blob, 6, opts);
var val = parse_FormulaValue(blob,8);
var flags = blob.read_shift(1);
if(opts.biff != 2) {
blob.read_shift(1);
if(opts.biff >= 5) {
/*var chn = */blob.read_shift(4);
}
}
var cbf = parse_XLSCellParsedFormula(blob, end - blob.l, opts);
return {cell:cell, val:val[0], formula:cbf, shared: (flags >> 3) & 1, tt:val[1]};
}
function write_Formula(cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, os/*:number*/) {
// Cell
var o1 = write_XLSCell(R, C, os);
// FormulaValue
var o2 = write_FormulaValue(cell.v);
// flags + cache
var o3 = new_buf(6);
var flags = 0x01 | 0x20;
o3.write_shift(2, flags);
o3.write_shift(4, 0);
// CellParsedFormula
var bf = new_buf(cell.bf.length);
for(var i = 0; i < cell.bf.length; ++i) bf[i] = cell.bf[i];
var out = bconcat([o1, o2, o3, bf]);
return out;
}
/* XLSB Parsed Formula records have the same shape */
function parse_XLSBParsedFormula(data, length, opts) {
var cce = data.read_shift(4);
var rgce = parse_Rgce(data, cce, opts);
var cb = data.read_shift(4);
var rgcb = cb > 0 ? parse_RgbExtra(data, cb, rgce, opts) : null;
return [rgce, rgcb];
}
/* [MS-XLSB] 2.5.97.1 ArrayParsedFormula */
var parse_XLSBArrayParsedFormula = parse_XLSBParsedFormula;
/* [MS-XLSB] 2.5.97.4 CellParsedFormula */
var parse_XLSBCellParsedFormula = parse_XLSBParsedFormula;
/* [MS-XLSB] 2.5.97.8 DVParsedFormula */
//var parse_XLSBDVParsedFormula = parse_XLSBParsedFormula;
/* [MS-XLSB] 2.5.97.9 FRTParsedFormula */
//var parse_XLSBFRTParsedFormula = parse_XLSBParsedFormula2;
/* [MS-XLSB] 2.5.97.12 NameParsedFormula */
var parse_XLSBNameParsedFormula = parse_XLSBParsedFormula;
/* [MS-XLSB] 2.5.97.98 SharedParsedFormula */
var parse_XLSBSharedParsedFormula = parse_XLSBParsedFormula;
/* Writes a PtgNum or PtgInt */
function write_XLSBFormulaNum(val/*:number*/) {
if((val | 0) == val && val < Math.pow(2,16) && val >= 0) {
var oint = new_buf(11);
oint.write_shift(4, 3);
oint.write_shift(1, 0x1e);
oint.write_shift(2, val);
oint.write_shift(4, 0);
return oint;
}
var num = new_buf(17);
num.write_shift(4, 11);
num.write_shift(1, 0x1f);
num.write_shift(8, val);
num.write_shift(4, 0);
return num;
}
/* Writes a PtgErr */
function write_XLSBFormulaErr(val/*:number*/) {
var oint = new_buf(10);
oint.write_shift(4, 2);
oint.write_shift(1, 0x1C);
oint.write_shift(1, val);
oint.write_shift(4, 0);
return oint;
}
/* Writes a PtgBool */
function write_XLSBFormulaBool(val/*:boolean*/) {
var oint = new_buf(10);
oint.write_shift(4, 2);
oint.write_shift(1, 0x1D);
oint.write_shift(1, val?1:0);
oint.write_shift(4, 0);
return oint;
}
/* Writes a PtgStr */
function write_XLSBFormulaStr(val/*:string*/) {
var preamble = new_buf(7);
preamble.write_shift(4, 3 + 2 * val.length);
preamble.write_shift(1, 0x17);
preamble.write_shift(2, val.length);
var body = new_buf(2 * val.length);
body.write_shift(2 * val.length, val, "utf16le");
var postamble = new_buf(4);
postamble.write_shift(4, 0);
return bconcat([preamble, body, postamble]);
}
/* Writes a PtgRef */
function write_XLSBFormulaRef(str) {
var cell = decode_cell(str);
var out = new_buf(15);
out.write_shift(4, 7);
out.write_shift(1, 0x04 | ((1)<<5));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
out.write_shift(4, 0);
return out;
}
/* Writes a PtgRef3d */
function write_XLSBFormulaRef3D(str, wb) {
var lastbang = str.lastIndexOf("!");
var sname = str.slice(0, lastbang);
str = str.slice(lastbang+1);
var cell = decode_cell(str);
if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
var out = new_buf(17);
out.write_shift(4, 9);
out.write_shift(1, 0x1A | ((1)<<5));
out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase()));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
out.write_shift(4, 0);
return out;
}
/* Writes a PtgRefErr3d */
function write_XLSBFormulaRefErr3D(str, wb) {
var lastbang = str.lastIndexOf("!");
var sname = str.slice(0, lastbang);
str = str.slice(lastbang+1);
if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
var out = new_buf(17);
out.write_shift(4, 9);
out.write_shift(1, 0x1C | ((1)<<5));
out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase()));
out.write_shift(4, 0);
out.write_shift(2, 0); // <== ColRelShort
out.write_shift(4, 0);
return out;
}
/* Writes a single sheet range [PtgRef PtgRef PtgRange] */
function write_XLSBFormulaRange(_str) {
var parts = _str.split(":"), str = parts[0];
var out = new_buf(23);
out.write_shift(4, 15);
/* start cell */
str = parts[0]; var cell = decode_cell(str);
out.write_shift(1, 0x04 | ((1)<<5));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
out.write_shift(4, 0);
/* end cell */
str = parts[1]; cell = decode_cell(str);
out.write_shift(1, 0x04 | ((1)<<5));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
out.write_shift(4, 0);
/* PtgRange */
out.write_shift(1, 0x11);
out.write_shift(4, 0);
return out;
}
/* Writes a range with explicit sheet name [PtgRef3D PtgRef3D PtgRange] */
function write_XLSBFormulaRangeWS(_str, wb) {
var lastbang = _str.lastIndexOf("!");
var sname = _str.slice(0, lastbang);
_str = _str.slice(lastbang+1);
if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
var parts = _str.split(":");
var out = new_buf(27);
out.write_shift(4, 19);
/* start cell */
var str = parts[0], cell = decode_cell(str);
out.write_shift(1, 0x1A | ((1)<<5));
out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase()));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
/* end cell */
str = parts[1]; cell = decode_cell(str);
out.write_shift(1, 0x1A | ((1)<<5));
out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase()));
out.write_shift(4, cell.r);
out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
/* PtgRange */
out.write_shift(1, 0x11);
out.write_shift(4, 0);
return out;
}
/* Writes a range with explicit sheet name [PtgArea3d] */
function write_XLSBFormulaArea3D(_str, wb) {
var lastbang = _str.lastIndexOf("!");
var sname = _str.slice(0, lastbang);
_str = _str.slice(lastbang+1);
if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
var range = decode_range(_str);
var out = new_buf(23);
out.write_shift(4, 15);
out.write_shift(1, 0x1B | ((1)<<5));
out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase()));
out.write_shift(4, range.s.r);
out.write_shift(4, range.e.r);
out.write_shift(2, range.s.c);
out.write_shift(2, range.e.c);
out.write_shift(4, 0);
return out;
}
/* General Formula */
function write_XLSBFormula(val/*:string|number*/, wb) {
if(typeof val == "number") return write_XLSBFormulaNum(val);
if(typeof val == "boolean") return write_XLSBFormulaBool(val);
if(/^#(DIV\/0!|GETTING_DATA|N\/A|NAME\?|NULL!|NUM!|REF!|VALUE!)$/.test(val)) return write_XLSBFormulaErr(+RBErr[val]);
if(val.match(/^\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaRef(val);
if(val.match(/^\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5}):\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaRange(val);
if(val.match(/^#REF!\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5}):\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaArea3D(val, wb);
if(val.match(/^(?:'[^\\\/?*\[\]:]*'|[^'][^\\\/?*\[\]:'`~!@#$%^()\-=+{}|;,<.>]*)!\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaRef3D(val, wb);
if(val.match(/^(?:'[^\\\/?*\[\]:]*'|[^'][^\\\/?*\[\]:'`~!@#$%^()\-=+{}|;,<.>]*)!\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5}):\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaRangeWS(val, wb);
if(/^(?:'[^\\\/?*\[\]:]*'|[^'][^\\\/?*\[\]:'`~!@#$%^()\-=+{}|;,<.>]*)!#REF!$/.test(val)) return write_XLSBFormulaRefErr3D(val, wb);
if(/^".*"$/.test(val)) return write_XLSBFormulaStr(val);
if(/^[+-]\d+$/.test(val)) return write_XLSBFormulaNum(parseInt(val, 10));
throw "Formula |" + val + "| not supported for XLSB";
}
var write_XLSBNameParsedFormula = write_XLSBFormula;

File diff suppressed because it is too large Load Diff

36
bits/65_fods.js Normal file
View File

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

View File

@ -1,16 +1,75 @@
var strs = {}; // shared strings
var _ssfopts = {}; // spreadsheet formatting options
RELS.WS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet";
function get_sst_id(sst, str) {
for(var i = 0, len = sst.length; i < len; ++i) if(sst[i].t === str) { sst.Count ++; return i; }
sst[len] = {t:str}; sst.Count ++; sst.Unique ++; return len;
/*global Map */
var browser_has_Map = typeof Map !== 'undefined';
function get_sst_id(sst/*:SST*/, str/*:string*/, rev)/*:number*/ {
var i = 0, len = sst.length;
if(rev) {
if(browser_has_Map ? rev.has(str) : Object.prototype.hasOwnProperty.call(rev, str)) {
var revarr = browser_has_Map ? rev.get(str) : rev[str];
for(; i < revarr.length; ++i) {
if(sst[revarr[i]].t === str) { sst.Count ++; return revarr[i]; }
}
}
} else for(; i < len; ++i) {
if(sst[i].t === str) { sst.Count ++; return i; }
}
sst[len] = ({t:str}/*:any*/); sst.Count ++; sst.Unique ++;
if(rev) {
if(browser_has_Map) {
if(!rev.has(str)) rev.set(str, []);
rev.get(str).push(len);
} else {
if(!Object.prototype.hasOwnProperty.call(rev, str)) rev[str] = [];
rev[str].push(len);
}
}
return len;
}
function get_cell_style(styles, cell, opts) {
function col_obj_w(C/*:number*/, col) {
var p = ({min:C+1,max:C+1}/*:any*/);
/* wch (chars), wpx (pixels) */
var wch = -1;
if(col.MDW) MDW = col.MDW;
if(col.width != null) p.customWidth = 1;
else if(col.wpx != null) wch = px2char(col.wpx);
else if(col.wch != null) wch = col.wch;
if(wch > -1) { p.width = char2width(wch); p.customWidth = 1; }
else if(col.width != null) p.width = col.width;
if(col.hidden) p.hidden = true;
if(col.level != null) { p.outlineLevel = p.level = col.level; }
return p;
}
function default_margins(margins/*:Margins*/, mode/*:?string*/) {
if(!margins) return;
var defs = [0.7, 0.7, 0.75, 0.75, 0.3, 0.3];
if(mode == 'xlml') defs = [1, 1, 1, 1, 0.5, 0.5];
if(margins.left == null) margins.left = defs[0];
if(margins.right == null) margins.right = defs[1];
if(margins.top == null) margins.top = defs[2];
if(margins.bottom == null) margins.bottom = defs[3];
if(margins.header == null) margins.header = defs[4];
if(margins.footer == null) margins.footer = defs[5];
}
function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) {
var z = opts.revssf[cell.z != null ? cell.z : "General"];
for(var i = 0, len = styles.length; i != len; ++i) if(styles[i].numFmtId === z) return i;
var i = 0x3c, len = styles.length;
if(z == null && opts.ssf) {
for(; i < 0x188; ++i) if(opts.ssf[i] == null) {
SSF__load(cell.z, i);
// $FlowIgnore
opts.ssf[i] = cell.z;
opts.revssf[cell.z] = z = i;
break;
}
}
for(i = 0; i != len; ++i) if(styles[i].numFmtId === z) return i;
styles[len] = {
numFmtId:z,
fontId:0,
@ -22,29 +81,35 @@ function get_cell_style(styles, cell, opts) {
return len;
}
function safe_format(p, fmtid, fillid, opts) {
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles, date1904) {
try {
if(opts.cellNF) p.z = table_fmt[fmtid];
} catch(e) { if(opts.WTF) throw e; }
if(p.t === 'z' && !opts.cellStyles) return;
if(p.t === 'd' && typeof p.v === 'string') p.v = parseDate(p.v);
if((!opts || opts.cellText !== false) && p.t !== 'z') try {
if(table_fmt[fmtid] == null) SSF__load(SSFImplicit[fmtid] || "General", fmtid);
if(p.t === 'e') p.w = p.w || BErr[p.v];
else if(fmtid === 0) {
if(p.t === 'n') {
if((p.v|0) === p.v) p.w = SSF._general_int(p.v,_ssfopts);
else p.w = SSF._general_num(p.v,_ssfopts);
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,_ssfopts);
else p.w = SSF._general_num(dd,_ssfopts);
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);
if(opts.cellNF) p.z = SSF._table[fmtid];
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(fillid) try {
if(!opts.cellStyles) return;
if(fillid != null) try {
p.s = styles.Fills[fillid];
if (p.s.fgColor && p.s.fgColor.theme) {
if (p.s.fgColor && p.s.fgColor.theme && !p.s.fgColor.rgb) {
p.s.fgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.fgColor.theme].rgb, p.s.fgColor.tint || 0);
if(opts.WTF) p.s.fgColor.raw_rgb = themes.themeElements.clrScheme[p.s.fgColor.theme].rgb;
}
@ -52,5 +117,12 @@ function safe_format(p, fmtid, fillid, opts) {
p.s.bgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.bgColor.theme].rgb, p.s.bgColor.tint || 0);
if(opts.WTF) p.s.bgColor.raw_rgb = themes.themeElements.clrScheme[p.s.bgColor.theme].rgb;
}
} catch(e) { if(opts.WTF) throw e; }
} catch(e) { if(opts.WTF && styles.Fills) throw e; }
}
function check_ws(ws/*:Worksheet*/, sname/*:string*/, i/*:number*/) {
if(ws && ws['!ref']) {
var range = safe_decode_range(ws['!ref']);
if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
}
}

View File

@ -1,54 +1,86 @@
function parse_ws_xml_dim(ws, s) {
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 = /<mergeCell ref="[A-Z0-9:]+"\s*\/>/g;
var sheetdataregex = /<(?:\w+:)?sheetData>([^\u2603]*)<\/(?:\w+:)?sheetData>/;
var hlinkregex = /<hyperlink[^>]*\/>/g;
var mergecregex = /<(?:\w+:)?mergeCell ref=["'][A-Z0-9:]+['"]\s*[\/]?>/g;
var hlinkregex = /<(?:\w+:)?hyperlink [^<>]*>/mg;
var dimregex = /"(\w*:\w*)"/;
var colregex = /<col[^>]*\/>/g;
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, opts, rels) {
function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ {
if(!data) return data;
if(!rels) rels = {'!id':{}};
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
/* 18.3.1.99 worksheet CT_Worksheet */
var s = {};
var s = ({}/*:any*/); if(opts.dense) s["!data"] = [];
var refguess/*:Range*/ = ({s: {r:2000000, c:2000000}, e: {r:0, c:0} }/*:any*/);
/* 18.3.1.35 dimension CT_SheetDimension ? */
var ridx = data.indexOf("<dimension");
var data1 = "", data2 = "";
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);
} else data1 = data2 = data;
/* 18.3.1.82 sheetPr CT_SheetPr */
var sheetPr = data1.match(sheetprregex);
if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
else if((sheetPr = str_match_xml_ns(data1, "sheetPr"))) parse_ws_xml_sheetpr2(sheetPr[0], sheetPr[1]||"", s, wb, idx, styles, themes);
/* 18.3.1.35 dimension CT_SheetDimension */
var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
if(ridx > 0) {
var ref = data.substr(ridx,50).match(dimregex);
if(ref != null) parse_ws_xml_dim(s, ref[1]);
var ref = data1.slice(ridx,ridx+50).match(dimregex);
if(ref && !(opts && opts.nodim)) parse_ws_xml_dim(s, ref[1]);
}
/* 18.3.1.55 mergeCells CT_MergeCells */
var mergecells = [];
if(data.indexOf("</mergeCells>")!==-1) {
var merges = data.match(mergecregex);
for(ridx = 0; ridx != merges.length; ++ridx)
mergecells[ridx] = safe_decode_range(merges[ridx].substr(merges[ridx].indexOf("\"")+1));
}
/* 18.3.1.88 sheetViews CT_SheetViews */
var svs = str_match_xml_ns(data1, "sheetViews");
if(svs && svs[1]) parse_ws_xml_sheetviews(svs[1], wb);
/* 18.3.1.17 cols CT_Cols */
var columns = [];
if(opts.cellStyles && data.indexOf("</cols>")!==-1) {
var columns/*:Array<ColInfo>*/ = [];
if(opts.cellStyles) {
/* 18.3.1.13 col CT_Col */
var cols = data.match(colregex);
parse_ws_xml_cols(columns, cols);
var cols = data1.match(colregex);
if(cols) parse_ws_xml_cols(columns, cols);
}
var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} };
/* 18.3.1.80 sheetData CT_SheetData ? */
var mtch=data.match(sheetdataregex);
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess);
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);
if(afilter) s['!autofilter'] = parse_ws_xml_autofilter(afilter[0]);
/* 18.3.1.55 mergeCells CT_MergeCells */
var merges/*:Array<Range>*/ = [];
var _merge = data2.match(mergecregex);
if(_merge) for(ridx = 0; ridx != _merge.length; ++ridx)
merges[ridx] = safe_decode_range(_merge[ridx].slice(_merge[ridx].indexOf("\"")+1));
/* 18.3.1.48 hyperlinks CT_Hyperlinks */
if(data.indexOf("</hyperlinks>")!==-1) parse_ws_xml_hlinks(s, data.match(hlinkregex), rels);
var hlink = data2.match(hlinkregex);
if(hlink) parse_ws_xml_hlinks(s, hlink, rels);
/* 18.3.1.62 pageMargins CT_PageMargins */
var margins = data2.match(marginregex);
if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));
/* legacyDrawing */
var m;
if((m = data2.match(/legacyDrawing r:id="(.*?)"/))) s['!legrel'] = m[1];
if(opts && opts.nodim) refguess.s.c = refguess.s.r = 0;
if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
if(opts.sheetRows > 0 && s["!ref"]) {
var tmpref = safe_decode_range(s["!ref"]);
if(opts.sheetRows < +tmpref.e.r) {
if(opts.sheetRows <= +tmpref.e.r) {
tmpref.e.r = opts.sheetRows - 1;
if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
@ -58,92 +90,202 @@ function parse_ws_xml(data, opts, rels) {
s["!ref"] = encode_range(tmpref);
}
}
if(mergecells.length > 0) s["!merges"] = mergecells;
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;
}
function write_ws_xml_merges(merges) {
if(merges.length == 0) return "";
function write_ws_xml_merges(merges/*:Array<Range>*/)/*:string*/ {
if(merges.length === 0) return "";
var o = '<mergeCells count="' + merges.length + '">';
for(var i = 0; i != merges.length; ++i) o += '<mergeCell ref="' + encode_range(merges[i]) + '"/>';
return o + '</mergeCells>';
}
function parse_ws_xml_hlinks(s, data, rels) {
/* 18.3.1.82-3 sheetPr CT_ChartsheetPr / CT_SheetPr */
function parse_ws_xml_sheetpr(sheetPr/*:string*/, s, wb/*:WBWBProps*/, idx/*:number*/) {
var data = parsexmltag(sheetPr);
if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
if(data.codeName) wb.Sheets[idx].CodeName = unescapexml(utf8read(data.codeName));
}
function parse_ws_xml_sheetpr2(sheetPr/*:string*/, body/*:string*/, s, wb/*:WBWBProps*/, idx/*:number*/) {
parse_ws_xml_sheetpr(sheetPr.slice(0, sheetPr.indexOf(">")), s, wb, idx);
}
function write_ws_xml_sheetpr(ws, wb, idx, opts, o) {
var needed = false;
var props = {}, payload = null;
if(opts.bookType !== 'xlsx' && wb.vbaraw) {
var cname = wb.SheetNames[idx];
try { if(wb.Workbook) cname = wb.Workbook.Sheets[idx].CodeName || cname; } catch(e) {}
needed = true;
props.codeName = utf8write(escapexml(cname));
}
if(ws && ws["!outline"]) {
var outlineprops = {summaryBelow:1, summaryRight:1};
if(ws["!outline"].above) outlineprops.summaryBelow = 0;
if(ws["!outline"].left) outlineprops.summaryRight = 0;
payload = (payload||"") + writextag('outlinePr', null, outlineprops);
}
if(!needed && !payload) return;
o[o.length] = (writextag('sheetPr', payload, props));
}
/* 18.3.1.85 sheetProtection CT_SheetProtection */
var sheetprot_deffalse = ["objects", "scenarios", "selectLockedCells", "selectUnlockedCells"];
var sheetprot_deftrue = [
"formatColumns", "formatRows", "formatCells",
"insertColumns", "insertRows", "insertHyperlinks",
"deleteColumns", "deleteRows",
"sort", "autoFilter", "pivotTables"
];
function write_ws_xml_protection(sp)/*:string*/ {
// algorithmName, hashValue, saltValue, spinCount
var o = ({sheet:1}/*:any*/);
sheetprot_deffalse.forEach(function(n) { if(sp[n] != null && sp[n]) o[n] = "1"; });
sheetprot_deftrue.forEach(function(n) { if(sp[n] != null && !sp[n]) o[n] = "0"; });
/* TODO: algorithm */
if(sp.password) o.password = crypto_CreatePasswordVerifier_Method1(sp.password).toString(16).toUpperCase();
return writextag('sheetProtection', null, o);
}
function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
var dense = s["!data"] != null;
for(var i = 0; i != data.length; ++i) {
var val = parsexmltag(data[i], true);
var val = parsexmltag(utf8read(data[i]), true);
if(!val.ref) return;
var rel = rels ? rels['!id'][val.id] : null;
var rel = ((rels || {})['!id']||[])[val.id];
if(rel) {
val.Target = rel.Target;
if(val.location) val.Target += "#"+val.location;
val.Rel = rel;
if(val.location) val.Target += "#"+unescapexml(val.location);
} else {
val.Target = val.location;
rel = {Target: val.location, TargetMode: 'Internal'};
val.Rel = rel;
val.Target = "#" + unescapexml(val.location);
rel = {Target: val.Target, TargetMode: 'Internal'};
}
val.Rel = rel;
if(val.tooltip) { val.Tooltip = val.tooltip; delete val.tooltip; }
var rng = safe_decode_range(val.ref);
for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
var addr = encode_cell({c:C,r:R});
if(!s[addr]) s[addr] = {t:"stub",v:undefined};
s[addr].l = val;
var addr = encode_col(C) + encode_row(R);
if(dense) {
if(!s["!data"][R]) s["!data"][R] = [];
if(!s["!data"][R][C]) s["!data"][R][C] = {t:"z",v:undefined};
s["!data"][R][C].l = val;
} else {
if(!s[addr]) s[addr] = {t:"z",v:undefined};
s[addr].l = val;
}
}
}
}
function parse_ws_xml_margins(margin) {
var o = {};
["left", "right", "top", "bottom", "header", "footer"].forEach(function(k) {
if(margin[k]) o[k] = parseFloat(margin[k]);
});
return o;
}
function write_ws_xml_margins(margin)/*:string*/ {
default_margins(margin);
return writextag('pageMargins', null, margin);
}
function parse_ws_xml_cols(columns, cols) {
var seencol = false;
for(var coli = 0; coli != cols.length; ++coli) {
var coll = parsexmltag(cols[coli], true);
if(coll.hidden) coll.hidden = parsexmlbool(coll.hidden);
var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
delete coll.min; delete coll.max;
if(!seencol && coll.width) { seencol = true; find_mdw(+coll.width, coll); }
if(coll.width) {
coll.wpx = width2px(+coll.width);
coll.wch = px2char(coll.wpx);
coll.MDW = MDW;
}
while(colm <= colM) columns[colm++] = coll;
if(coll.outlineLevel) coll.level = (+coll.outlineLevel || 0);
delete coll.min; delete coll.max; coll.width = +coll.width;
if(!seencol && coll.width) { seencol = true; find_mdw_colw(coll.width); }
process_col(coll);
while(colm <= colM) columns[colm++] = dup(coll);
}
}
function write_ws_xml_cols(ws, cols) {
var o = ["<cols>"], col, width;
function write_ws_xml_cols(ws, cols)/*:string*/ {
var o = ["<cols>"], col;
for(var i = 0; i != cols.length; ++i) {
if(!(col = cols[i])) continue;
var p = {min:i+1,max:i+1};
/* wch (chars), wpx (pixels) */
width = -1;
if(col.wpx) width = px2char(col.wpx);
else if(col.wch) width = col.wch;
if(width > -1) { p.width = char2width(width); p.customWidth= 1; }
o[o.length] = (writextag('col', null, p));
o[o.length] = (writextag('col', null, col_obj_w(i, col)));
}
o[o.length] = "</cols>";
return o.join("");
}
function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
if(cell.v === undefined) return "";
function parse_ws_xml_autofilter(data/*:string*/) {
var o = { ref: (data.match(/ref="([^"]*)"/)||[])[1]};
return o;
}
function write_ws_xml_autofilter(data, ws, wb, idx)/*:string*/ {
var ref = typeof data.ref == "string" ? data.ref : encode_range(data.ref);
if(!wb.Workbook) wb.Workbook = ({Sheets:[]}/*:any*/);
if(!wb.Workbook.Names) wb.Workbook.Names = [];
var names/*: Array<any> */ = wb.Workbook.Names;
var range = decode_range(ref);
if(range.s.r == range.e.r) { range.e.r = decode_range(ws["!ref"]).e.r; ref = encode_range(range); }
for(var i = 0; i < names.length; ++i) {
var name = names[i];
if(name.Name != '_xlnm._FilterDatabase') continue;
if(name.Sheet != idx) continue;
name.Ref = formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref); break;
}
if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref });
return writextag("autoFilter", null, {ref:ref});
}
/* 18.3.1.88 sheetViews CT_SheetViews */
/* 18.3.1.87 sheetView CT_SheetView */
var sviewregex = /<(?:\w:)?sheetView(?:[^<>a-z][^<>]*)?\/?>/g;
function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) {
if(!wb.Views) wb.Views = [{}];
(data.match(sviewregex)||[]).forEach(function(r/*:string*/, i/*:number*/) {
var tag = parsexmltag(r);
// $FlowIgnore
if(!wb.Views[i]) wb.Views[i] = {};
// $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore
if(tag.rightToLeft && parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
});
}
function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
var sview = ({workbookViewId:"0"}/*:any*/);
// $FlowIgnore
if((((wb||{}).Workbook||{}).Views||[])[0]) sview.rightToLeft = wb.Workbook.Views[0].RTL ? "1" : "0";
return writextag("sheetViews", writextag("sheetView", null, sview), {});
}
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;
switch(cell.t) {
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.cellDates) vv = new Date(cell.v).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(cell.v));
if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
vv = ''+(cell.v = datenum(parseDate(cell.v, date1904), date1904));
}
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};
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;
@ -152,49 +294,96 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
case 'd': o.t = "d"; break;
case 'b': o.t = "b"; break;
case 'e': o.t = "e"; break;
default:
if(opts.bookSST) {
v = writetag('v', ''+get_sst_id(opts.Strings, cell.v));
case 'z': break;
default: if(cell.v == null) { delete cell.t; break; }
if(cell.v.length > 32767) throw new Error("Text length must not exceed 32767 characters");
if(opts && opts.bookSST) {
v = writetag('v', ''+get_sst_id(opts.Strings, cell.v, opts.revStrings));
o.t = "s"; break;
}
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) {
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 parse_ws_xml_data_factory() {
var cellregex = /<(?:\w+:)?c[ >]/, rowregex = /<\/(?:\w+:)?row>/;
var rregex = /r=["']([^"']*)["']/, isregex = /<is>([\S\s]*?)<\/is>/;
var match_v = matchtag("v"), match_f = matchtag("f");
var parse_ws_xml_data = /*#__PURE__*/(function() {
var cellregex = /<(?:\w+:)?c[ \/>]/, rowregex = /<\/(?:\w+:)?row>/;
var rregex = /r=["']([^"']*)["']/;
var refregex = /ref=["']([^"']*)["']/;
return function parse_ws_xml_data(sdata, s, opts, guess) {
var ri = 0, x = "", cells = [], cref = [], idx = 0, i=0, cc=0, d="", p;
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;
var fmtid = 0, fillid = 0, do_format = Array.isArray(styles.CellXf), cf;
var sstr, ftag;
var fmtid = 0, fillid = 0;
var do_format = Array.isArray(styles.CellXf), cf;
var arrayf/*:Array<[Range, string]>*/ = [];
var sharedf = [];
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;
if(xlen === 0) continue;
/* 18.3.1.73 row CT_Row */
for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
tag = parsexmltag(x.substr(0,ri), true);
/* SpreadSheetGear uses implicit r/c */
tagr = typeof tag.r !== 'undefined' ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
var rstarti = 0;
outa: for(ri = 0; ri < xlen; ++ri) switch(/*x.charCodeAt(ri)*/x[ri]) {
case ">" /*62*/:
if(/*x.charCodeAt(ri-1) != 47*/x[ri-1] != "/") { ++ri; break outa; }
if(opts && opts.cellStyles) {
// TODO: avoid duplication
tag = parsexmltag(x.slice(rstarti,ri), true);
tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
if(opts.sheetRows && opts.sheetRows < tagr) continue;
rowobj = {}; rowrite = false;
if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
if(tag.hidden && parsexmlbool(tag.hidden)) { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj;
}
break;
case "<" /*60*/: rstarti = ri; break;
}
if(rstarti >= ri) break;
tag = parsexmltag(x.slice(rstarti,ri), true);
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 && parsexmlbool(tag.hidden)) { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj;
}
/* 18.3.1.4 c CT_Cell */
cells = x.substr(ri).split(cellregex);
for(ri = typeof tag.r === 'undefined' ? 0 : 1; ri != cells.length; ++ri) {
cells = x.slice(ri).split(cellregex);
for(var rslice = 0; rslice != cells.length; ++rslice) if(cells[rslice].trim().charAt(0) != "<") break;
cells = cells.slice(rslice);
for(ri = 0; ri != cells.length; ++ri) {
x = cells[ri].trim();
if(x.length === 0) continue;
cref = x.match(rregex); idx = ri; i=0; cc=0;
x = "<c " + (x.substr(0,1)=="<"?">":"") + x;
if(cref !== null && cref.length === 2) {
x = "<c " + (x.slice(0,1)=="<"?">":"") + x;
if(cref != null && cref.length === 2) {
idx = 0; d=cref[1];
for(i=0; i != d.length; ++i) {
if((cc=d.charCodeAt(i)-64) < 1 || cc > 26) break;
@ -204,102 +393,293 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
tagc = idx;
} else ++tagc;
for(i = 0; i != x.length; ++i) if(x.charCodeAt(i) === 62) break; ++i;
tag = parsexmltag(x.substr(0,i), true);
if(!tag.r) tag.r = utils.encode_cell({r:tagr-1, c:tagc});
d = x.substr(i);
p = {t:""};
tag = parsexmltag(x.slice(0,i), true);
if(!tag.r) tag.r = encode_cell({r:tagr-1, c:tagc});
d = x.slice(i);
p = ({t:""}/*:any*/);
if((cref=d.match(match_v))!== null && cref[1] !== '') p.v=unescapexml(cref[1]);
if(opts.cellFormula && (cref=d.match(match_f))!== null) p.f=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=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[^<>]*\/>/))) {
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);
}
/* TODO: factor out contains logic */
var _tag = decode_cell(tag.r);
for(i = 0; i < arrayf.length; ++i)
if(_tag.r >= arrayf[i][0].s.r && _tag.r <= arrayf[i][0].e.r)
if(_tag.c >= arrayf[i][0].s.c && _tag.c <= arrayf[i][0].e.c)
p.F = arrayf[i][1];
}
/* SCHEMA IS ACTUALLY INCORRECT HERE. IF A CELL HAS NO T, EMIT "" */
if(tag.t === undefined && p.v === undefined) {
if(!opts.sheetStubs) continue;
p.t = "stub";
if(tag.t == null && p.v === undefined) {
if(p.f || p.F) {
p.v = 0; p.t = "n";
} else if(!sheetStubs) continue;
else p.t = "z";
}
else p.t = tag.t || "n";
if(guess.s.c > idx) guess.s.c = idx;
if(guess.e.c < idx) guess.e.c = idx;
if(guess.s.c > tagc) guess.s.c = tagc;
if(guess.e.c < tagc) guess.e.c = tagc;
/* 18.18.11 t ST_CellType */
switch(p.t) {
case 'n': p.v = parseFloat(p.v); break;
case 'n':
if(p.v == "" || p.v == null) {
if(!sheetStubs) continue;
p.t = 'z';
} else p.v = parseFloat(p.v);
break;
case 's':
sstr = strs[parseInt(p.v, 10)];
p.v = sstr.t;
p.r = sstr.r;
if(opts.cellHTML) p.h = sstr.h;
if(typeof p.v == 'undefined') {
if(!sheetStubs) continue;
p.t = 'z';
} else {
sstr = strs[parseInt(p.v, 10)];
p.v = sstr.t;
p.r = sstr.r;
if(opts.cellHTML) p.h = sstr.h;
}
break;
case 'str':
p.t = "s";
p.v = (p.v!=null) ? utf8read(p.v) : '';
if(opts.cellHTML) p.h = 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; } else p.v = "";
break; // inline string
if(cref != null && (sstr = parse_si(cref[1]))) {
p.v = sstr.t;
if(opts.cellHTML) p.h = sstr.h;
} else p.v = "";
break;
case 'b': p.v = parsexmlbool(p.v); break;
case 'd':
if(!opts.cellDates) { p.v = datenum(p.v); 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 .v, number in .v */
case 'e': p.w = p.v; p.v = RBErr[p.v]; break;
/* error string in .w, number in .v */
case 'e':
if(!opts || opts.cellText !== false) p.w = p.v;
p.v = RBErr[p.v]; break;
}
/* formatting */
fmtid = fillid = 0;
cf = null;
if(do_format && tag.s !== undefined) {
cf = styles.CellXf[tag.s];
if(cf != null) {
if(cf.numFmtId != null) fmtid = cf.numFmtId;
if(opts.cellStyles && cf.fillId != null) fillid = cf.fillId;
if(opts.cellStyles) {
if(cf.fillId != null) fillid = cf.fillId;
}
}
}
safe_format(p, fmtid, fillid, opts);
s[tag.r] = p;
safe_format(p, fmtid, fillid, opts, themes, styles, date1904);
if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.v = numdate(p.v + (date1904 ? 1462 : 0)); p.t = typeof p.v == "number" ? 'n' : 'd'; }
if(tag.cm && opts.xlmeta) {
var cm = (opts.xlmeta.Cell||[])[+tag.cm-1];
if(cm && cm.type == 'XLDAPR') p.D = true;
}
var _r;
if(opts.nodim) {
_r = decode_cell(tag.r);
if(guess.s.r > _r.r) guess.s.r = _r.r;
if(guess.e.r < _r.r) guess.e.r = _r.r;
}
if(dense) {
_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;
}
}
if(rows.length > 0) s['!rows'] = rows;
}; })();
function write_ws_xml_data(ws, opts, idx, wb) {
var o = [], r = [], range = safe_decode_range(ws['!ref']), cell, ref, rr = "", cols = [], R, C;
function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*//*::, rels*/)/*:string*/ {
var o/*:Array<string>*/ = [], r/*:Array<string>*/ = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols/*:Array<string>*/ = [], R=0, C=0, rows = ws['!rows'];
var dense = ws["!data"] != null;
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;
if(ws[ref] === undefined) continue;
if((cell = write_ws_xml_cell(ws[ref], ref, ws, opts, idx, wb)) != null) r.push(cell);
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, date1904)) != null) r.push(cell);
}
if(r.length > 0 || (rows && rows[R])) {
params = ({r:rr}/*:any*/);
if(rows && rows[R]) {
row = rows[R];
if(row.hidden) params.hidden = 1;
height = -1;
if(row.hpx) height = px2pt(row.hpx);
else if(row.hpt) height = row.hpt;
if(height > -1) { params.ht = height; params.customHeight = 1; }
if(row.level) { params.outlineLevel = row.level; }
}
o[o.length] = (writextag('row', r.join(""), params));
}
}
if(rows) for(; R < rows.length; ++R) {
if(rows && rows[R]) {
params = ({r:R+1}/*:any*/);
row = rows[R];
if(row.hidden) params.hidden = 1;
height = -1;
if (row.hpx) height = px2pt(row.hpx);
else if (row.hpt) height = row.hpt;
if (height > -1) { params.ht = height; params.customHeight = 1; }
if (row.level) { params.outlineLevel = row.level; }
o[o.length] = (writextag('row', "", params));
}
if(r.length > 0) o[o.length] = (writextag('row', r.join(""), {r:rr}));
}
return o.join("");
}
var WS_XML_ROOT = writextag('worksheet', null, {
'xmlns': XMLNS.main[0],
'xmlns:r': XMLNS.r
});
function write_ws_xml(idx, opts, wb) {
var o = [XML_HEADER, WS_XML_ROOT];
function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
var o = [XML_HEADER, writextag('worksheet', null, {
'xmlns': XMLNS_main[0],
'xmlns:r': XMLNS.r
})];
var s = wb.SheetNames[idx], sidx = 0, rdata = "";
var ws = wb.Sheets[s];
if(ws === undefined) ws = {};
var ref = ws['!ref']; if(ref === undefined) ref = 'A1';
if(ws == null) ws = {};
var ref = ws['!ref'] || 'A1';
var range = safe_decode_range(ref);
if(range.e.c > 0x3FFF || range.e.r > 0xFFFFF) {
if(opts.WTF) throw new Error("Range " + ref + " exceeds format limit A1:XFD1048576");
range.e.c = Math.min(range.e.c, 0x3FFF);
range.e.r = Math.min(range.e.c, 0xFFFFF);
ref = encode_range(range);
}
if(!rels) rels = {};
ws['!comments'] = [];
var _drawing = [];
write_ws_xml_sheetpr(ws, wb, idx, opts, o);
o[o.length] = (writextag('dimension', null, {'ref': ref}));
if(ws['!cols'] !== undefined && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols']));
o[o.length] = write_ws_xml_sheetviews(ws, opts, idx, wb);
/* TODO: store in WB, process styles */
if(opts.sheetFormat) o[o.length] = (writextag('sheetFormatPr', null, {
defaultRowHeight:opts.sheetFormat.defaultRowHeight||'16',
baseColWidth:opts.sheetFormat.baseColWidth||'10',
outlineLevelRow:opts.sheetFormat.outlineLevelRow||'7'
}));
if(ws['!cols'] != null && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols']));
o[sidx = o.length] = '<sheetData/>';
if(ws['!ref'] !== undefined) {
rdata = write_ws_xml_data(ws, opts, idx, wb);
ws['!links'] = [];
if(ws['!ref'] != null) {
rdata = write_ws_xml_data(ws, opts, idx, wb, rels);
if(rdata.length > 0) o[o.length] = (rdata);
}
if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
if(ws['!merges'] !== undefined && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
/* sheetCalcPr */
if(o.length>2) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
if(ws['!protect']) o[o.length] = write_ws_xml_protection(ws['!protect']);
/* protectedRanges */
/* scenarios */
if(ws['!autofilter'] != null) o[o.length] = write_ws_xml_autofilter(ws['!autofilter'], ws, wb, idx);
/* sortState */
/* dataConsolidate */
/* customSheetViews */
if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
/* phoneticPr */
/* conditionalFormatting */
/* dataValidations */
var relc = -1, rel, rId = -1;
if(/*::(*/ws['!links']/*::||[])*/.length > 0) {
o[o.length] = "<hyperlinks>";
/*::(*/ws['!links']/*::||[])*/.forEach(function(l) {
if(!l[1].Target) return;
rel = ({"ref":l[0]}/*:any*/);
if(l[1].Target.charAt(0) != "#") {
rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#[\s\S]*$/, ""), RELS.HLINK);
rel["r:id"] = "rId"+rId;
}
if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1));
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>";
}
delete ws['!links'];
/* printOptions */
if(ws['!margins'] != null) o[o.length] = write_ws_xml_margins(ws['!margins']);
/* pageSetup */
/* headerFooter */
/* rowBreaks */
/* colBreaks */
/* customProperties */
/* cellWatches */
if(!opts || opts.ignoreEC || (opts.ignoreEC == (void 0))) o[o.length] = writetag("ignoredErrors", writextag("ignoredError", null, {numberStoredAsText:1, sqref:ref}));
/* smartTags */
if(_drawing.length > 0) {
rId = add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
o[o.length] = writextag("drawing", null, {"r:id":"rId" + rId});
ws['!drawing'] = _drawing;
}
if(ws['!comments'].length > 0) {
rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML);
o[o.length] = writextag("legacyDrawing", null, {"r:id":"rId" + rId});
ws['!legacy'] = rId;
}
/* legacyDrawingHF */
/* picture */
/* oleObjects */
/* controls */
/* webPublishItems */
/* tableParts */
/* extLst */
if(o.length>1) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}

File diff suppressed because it is too large Load Diff

48
bits/69_chartxml.js Normal file
View File

@ -0,0 +1,48 @@
function parse_Cache(data/*:string*/)/*:[Array<number|string>, string, ?string]*/ {
var col/*:Array<number|string>*/ = [];
var num = data.match(/^<c:numCache>/);
var f;
/* 21.2.2.150 pt CT_NumVal */
(data.match(/<c:pt idx="(\d*)"[^<>\/]*><c:v>([^<])<\/c:v><\/c:pt>/mg)||[]).forEach(function(pt) {
var q = pt.match(/<c:pt idx="(\d*)"[^<>\/]*><c:v>([^<]*)<\/c:v><\/c:pt>/);
if(!q) return;
col[+q[1]] = num ? +q[2] : q[2];
});
/* 21.2.2.71 formatCode CT_Xstring */
var nf = unescapexml((str_match_xml(data, "c:formatCode") || ["","General"])[1]);
(str_match_ng(data, "<c:f>", "</c:f>")||[]).forEach(function(F) { f = F.replace(/<[^<>]*>/g,""); });
return [col, nf, f];
}
/* 21.2 DrawingML - Charts */
function parse_chart(data/*:?string*/, name/*:string*/, opts, rels, wb, csheet) {
var cs/*:Worksheet*/ = ((csheet || {"!type":"chart"})/*:any*/);
if(!data) return csheet;
/* 21.2.2.27 chart CT_Chart */
var C = 0, R = 0, col = "A";
var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
/* 21.2.2.120 numCache CT_NumData */
(str_match_ng(data, "<c:numCache>", "</c:numCache>")||[]).forEach(function(nc) {
var cache = parse_Cache(nc);
refguess.s.r = refguess.s.c = 0;
refguess.e.c = C;
col = encode_col(C);
cache[0].forEach(function(n,i) {
if(cs["!data"]) {
if(!cs["!data"][i]) cs["!data"][i] = [];
cs["!data"][i][C] = {t:'n', v:n, z:cache[1] };
} else cs[col + encode_row(i)] = {t:'n', v:n, z:cache[1] };
R = i;
});
if(refguess.e.r < R) refguess.e.r = R;
++C;
});
if(C > 0) cs["!ref"] = encode_range(refguess);
return cs;
}

102
bits/70_csheet.js Normal file
View File

@ -0,0 +1,102 @@
/* 18.3 Worksheets also covers Chartsheets */
function parse_cs_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*::, themes, styles*/)/*:Worksheet*/ {
if(!data) return data;
/* 18.3.1.12 chartsheet CT_ChartSheet */
if(!rels) rels = {'!id':{}};
var s = ({'!type':"chart", '!drawel':null, '!rel':""}/*:any*/);
var m;
/* 18.3.1.83 sheetPr CT_ChartsheetPr */
var sheetPr = data.match(sheetprregex);
if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
/* 18.3.1.36 drawing CT_Drawing */
if((m = data.match(/drawing r:id="(.*?)"/))) s['!rel'] = m[1];
if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
return s;
}
//function write_cs_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
// var o = [XML_HEADER, writextag('chartsheet', null, {
// 'xmlns': XMLNS_main[0],
// 'xmlns:r': XMLNS.r
// })];
// o[o.length] = writextag("drawing", null, {"r:id": "rId1"});
// add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
// if(o.length>2) { o[o.length] = ('</chartsheet>'); o[1]=o[1].replace("/>",">"); }
// return o.join("");
//}
/* [MS-XLSB] 2.4.331 BrtCsProp */
function parse_BrtCsProp(data, length/*:number*/) {
data.l += 10;
var name = parse_XLWideString(data, length - 10);
return { name: name };
}
/* [MS-XLSB] 2.1.7.7 Chart Sheet */
function parse_cs_bin(data, opts, idx/*:number*/, rels, wb/*::, themes, styles*/)/*:Worksheet*/ {
if(!data) return data;
if(!rels) rels = {'!id':{}};
var s = {'!type':"chart", '!drawel':null, '!rel':""};
var state/*:Array<string>*/ = [];
var pass = false;
recordhopper(data, function cs_parse(val, R, RT) {
switch(RT) {
case 0x0226: /* 'BrtDrawing' */
s['!rel'] = val; break;
case 0x028B: /* 'BrtCsProp' */
if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
if(val.name) wb.Sheets[idx].CodeName = val.name;
break;
case 0x0232: /* 'BrtBkHim' */
case 0x028C: /* 'BrtCsPageSetup' */
case 0x029D: /* 'BrtCsProtection' */
case 0x02A7: /* 'BrtCsProtectionIso' */
case 0x0227: /* 'BrtLegacyDrawing' */
case 0x0228: /* 'BrtLegacyDrawingHF' */
case 0x01DC: /* 'BrtMargins' */
case 0x0C00: /* 'BrtUid' */
break;
case 0x0023: /* 'BrtFRTBegin' */
pass = true; break;
case 0x0024: /* 'BrtFRTEnd' */
pass = false; break;
case 0x0025: /* 'BrtACBegin' */
state.push(RT); break;
case 0x0026: /* 'BrtACEnd' */
state.pop(); break;
default:
if(R.T > 0) state.push(RT);
else if(R.T < 0) state.pop();
else if(!pass || opts.WTF) throw new Error("Unexpected record 0x" + RT.toString(16));
}
}, opts);
if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
return s;
}
//function write_cs_bin(/*::idx:number, opts, wb:Workbook, rels*/) {
// var ba = buf_array();
// write_record(ba, 0x0081 /* BrtBeginSheet */);
// /* [BrtCsProp] */
// /* CSVIEWS */
// /* [[BrtCsProtectionIso] BrtCsProtection] */
// /* [USERCSVIEWS] */
// /* [BrtMargins] */
// /* [BrtCsPageSetup] */
// /* [HEADERFOOTER] */
// /* BrtDrawing */
// /* [BrtLegacyDrawing] */
// /* [BrtLegacyDrawingHF] */
// /* [BrtBkHim] */
// /* [WEBPUBITEMS] */
// /* FRTCHARTSHEET */
// write_record(ba, 0x0082 /* BrtEndSheet */);
// return ba.end();
//}

158
bits/71_wbcommon.js Normal file
View File

@ -0,0 +1,158 @@
/* 18.2.28 (CT_WorkbookProtection) Defaults */
var WBPropsDef = [
['allowRefreshQuery', false, "bool"],
['autoCompressPictures', true, "bool"],
['backupFile', false, "bool"],
['checkCompatibility', false, "bool"],
['CodeName', ''],
['date1904', false, "bool"],
['defaultThemeVersion', 0, "int"],
['filterPrivacy', false, "bool"],
['hidePivotFieldList', false, "bool"],
['promptedSolutions', false, "bool"],
['publishItems', false, "bool"],
['refreshAllConnections', false, "bool"],
['saveExternalLinkValues', true, "bool"],
['showBorderUnselectedTables', true, "bool"],
['showInkAnnotation', true, "bool"],
['showObjects', 'all'],
['showPivotChartFilter', false, "bool"],
['updateLinks', 'userSet']
];
/* 18.2.30 (CT_BookView) Defaults */
var WBViewDef = [
['activeTab', 0, "int"],
['autoFilterDateGrouping', true, "bool"],
['firstSheet', 0, "int"],
['minimized', false, "bool"],
['showHorizontalScroll', true, "bool"],
['showSheetTabs', true, "bool"],
['showVerticalScroll', true, "bool"],
['tabRatio', 600, "int"],
['visibility', 'visible']
//window{Height,Width}, {x,y}Window
];
/* 18.2.19 (CT_Sheet) Defaults */
var SheetDef = [
//['state', 'visible']
];
/* 18.2.2 (CT_CalcPr) Defaults */
var CalcPrDef = [
['calcCompleted', 'true'],
['calcMode', 'auto'],
['calcOnSave', 'true'],
['concurrentCalc', 'true'],
['fullCalcOnLoad', 'false'],
['fullPrecision', 'true'],
['iterate', 'false'],
['iterateCount', '100'],
['iterateDelta', '0.001'],
['refMode', 'A1']
];
/* 18.2.3 (CT_CustomWorkbookView) Defaults */
/*var CustomWBViewDef = [
['autoUpdate', 'false'],
['changesSavedWin', 'false'],
['includeHiddenRowCol', 'true'],
['includePrintSettings', 'true'],
['maximized', 'false'],
['minimized', 'false'],
['onlySync', 'false'],
['personalView', 'false'],
['showComments', 'commIndicator'],
['showFormulaBar', 'true'],
['showHorizontalScroll', 'true'],
['showObjects', 'all'],
['showSheetTabs', 'true'],
['showStatusbar', 'true'],
['showVerticalScroll', 'true'],
['tabRatio', '600'],
['xWindow', '0'],
['yWindow', '0']
];*/
function push_defaults_array(target, defaults) {
for(var j = 0; j != target.length; ++j) { var w = target[j];
for(var i=0; i != defaults.length; ++i) { var z = defaults[i];
if(w[z[0]] == null) w[z[0]] = z[1];
else switch(z[2]) {
case "bool": if(typeof w[z[0]] == "string") w[z[0]] = parsexmlbool(w[z[0]]); break;
case "int": if(typeof w[z[0]] == "string") w[z[0]] = parseInt(w[z[0]], 10); break;
}
}
}
}
function push_defaults(target, defaults) {
for(var i = 0; i != defaults.length; ++i) { var z = defaults[i];
if(target[z[0]] == null) target[z[0]] = z[1];
else switch(z[2]) {
case "bool": if(typeof target[z[0]] == "string") target[z[0]] = parsexmlbool(target[z[0]]); break;
case "int": if(typeof target[z[0]] == "string") target[z[0]] = parseInt(target[z[0]], 10); break;
}
}
}
function parse_wb_defaults(wb) {
push_defaults(wb.WBProps, WBPropsDef);
push_defaults(wb.CalcPr, CalcPrDef);
push_defaults_array(wb.WBView, WBViewDef);
push_defaults_array(wb.Sheets, SheetDef);
_ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904);
}
function safe1904(wb/*:Workbook*/)/*:string*/ {
/* TODO: store date1904 somewhere else */
if(!wb.Workbook) return "false";
if(!wb.Workbook.WBProps) return "false";
return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false";
}
var badchars = /*#__PURE__*/":][*?\/\\".split("");
function check_ws_name(n/*:string*/, safe/*:?boolean*/)/*:boolean*/ {
try {
if(n == "") throw new Error("Sheet name cannot be blank");
if(n.length > 31) throw new Error("Sheet name cannot exceed 31 chars");
if(n.charCodeAt(0) == 0x27 || n.charCodeAt(n.length - 1) == 0x27) throw new Error("Sheet name cannot start or end with apostrophe (')");
if(n.toLowerCase() == "history") throw new Error("Sheet name cannot be 'History'");
badchars.forEach(function(c) {
if(n.indexOf(c) == -1) return;
throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
});
} catch(e) { if(safe) return false; throw e; }
return true;
}
function check_wb_names(N, S, codes) {
N.forEach(function(n,i) {
check_ws_name(n);
for(var j = 0; j < i; ++j) if(n == N[j]) throw new Error("Duplicate Sheet Name: " + n);
if(codes) {
var cn = (S && S[i] && S[i].CodeName) || n;
if(cn.charCodeAt(0) == 95 && cn.length > 22) throw new Error("Bad Code Name: Worksheet" + cn);
}
});
}
function check_wb(wb) {
if(!wb || !wb.SheetNames || !wb.Sheets) throw new Error("Invalid Workbook");
if(!wb.SheetNames.length) throw new Error("Workbook is empty");
var Sheets = (wb.Workbook && wb.Workbook.Sheets) || [];
check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i);
wb.SheetNames.forEach(function(n, i) {
var ws = wb.Sheets[n];
if(!ws || !ws["!autofilter"]) return;
var DN;
if(!wb.Workbook) wb.Workbook = {};
if(!wb.Workbook.Names) wb.Workbook.Names = [];
wb.Workbook.Names.forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == i) DN = dn; });
var nn = formula_quote_sheet_name(n) + "!" + fix_range(ws["!autofilter"].ref);
if(DN) DN.Ref = nn;
else wb.Workbook.Names.push({Name: "_xlnm._FilterDatabase", Sheet: i, Ref: nn});
});
/* TODO: validate workbook */
}

247
bits/72_wbxml.js Normal file
View File

@ -0,0 +1,247 @@
/* 18.2 Workbook */
var wbnsregex = /<\w+:workbook/;
function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
if(!data) throw new Error("Could not find file");
var wb = /*::(*/{ AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, Names:[], xmlns: "" }/*::)*/;
var pass = false, xmlns = "xmlns";
var dname = {}, dnstart = 0;
data.replace(tagregex, function xml_wb(x, idx) {
var y/*:any*/ = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<?xml': break;
/* 18.2.27 workbook CT_Workbook 1 */
case '<workbook':
if(x.match(wbnsregex)) xmlns = "xmlns" + x.match(/<(\w+):/)[1];
wb.xmlns = y[xmlns];
break;
case '</workbook>': break;
/* 18.2.13 fileVersion CT_FileVersion ? */
case '<fileVersion': delete y[0]; wb.AppVersion = y; break;
case '<fileVersion/>': case '</fileVersion>': break;
/* 18.2.12 fileSharing CT_FileSharing ? */
case '<fileSharing':
break;
case '<fileSharing/>': break;
/* 18.2.28 workbookPr CT_WorkbookPr ? */
case '<workbookPr':
case '<workbookPr/>':
WBPropsDef.forEach(function(w) {
if(y[w[0]] == null) return;
switch(w[2]) {
case "bool": wb.WBProps[w[0]] = parsexmlbool(y[w[0]]); break;
case "int": wb.WBProps[w[0]] = parseInt(y[w[0]], 10); break;
default: wb.WBProps[w[0]] = y[w[0]];
}
});
if(y.codeName) wb.WBProps.CodeName = utf8read(y.codeName);
break;
case '</workbookPr>': break;
/* 18.2.29 workbookProtection CT_WorkbookProtection ? */
case '<workbookProtection':
break;
case '<workbookProtection/>': break;
/* 18.2.1 bookViews CT_BookViews ? */
case '<bookViews': case '<bookViews>': case '</bookViews>': break;
/* 18.2.30 workbookView CT_BookView + */
case '<workbookView': case '<workbookView/>': delete y[0]; wb.WBView.push(y); break;
case '</workbookView>': break;
/* 18.2.20 sheets CT_Sheets 1 */
case '<sheets': case '<sheets>': case '</sheets>': break; // aggregate sheet
/* 18.2.19 sheet CT_Sheet + */
case '<sheet':
switch(y.state) {
case "hidden": y.Hidden = 1; break;
case "veryHidden": y.Hidden = 2; break;
default: y.Hidden = 0;
}
delete y.state;
y.name = unescapexml(utf8read(y.name));
delete y[0]; wb.Sheets.push(y); break;
case '</sheet>': break;
/* 18.2.15 functionGroups CT_FunctionGroups ? */
case '<functionGroups': case '<functionGroups/>': break;
/* 18.2.14 functionGroup CT_FunctionGroup + */
case '<functionGroup': break;
/* 18.2.9 externalReferences CT_ExternalReferences ? */
case '<externalReferences': case '</externalReferences>': case '<externalReferences>': break;
/* 18.2.8 externalReference CT_ExternalReference + */
case '<externalReference': break;
/* 18.2.6 definedNames CT_DefinedNames ? */
case '<definedNames/>': break;
case '<definedNames>': case '<definedNames': pass=true; break;
case '</definedNames>': pass=false; break;
/* 18.2.5 definedName CT_DefinedName + */
case '<definedName': {
dname = {};
dname.Name = utf8read(y.name);
if(y.comment) dname.Comment = y.comment;
if(y.localSheetId) dname.Sheet = +y.localSheetId;
if(parsexmlbool(y.hidden||"0")) dname.Hidden = true;
dnstart = idx + x.length;
} break;
case '</definedName>': {
dname.Ref = unescapexml(utf8read(data.slice(dnstart, idx)));
wb.Names.push(dname);
} break;
case '<definedName/>': break;
/* 18.2.2 calcPr CT_CalcPr ? */
case '<calcPr': delete y[0]; wb.CalcPr = y; break;
case '<calcPr/>': delete y[0]; wb.CalcPr = y; break;
case '</calcPr>': break;
/* 18.2.16 oleSize CT_OleSize ? (ref required) */
case '<oleSize': break;
/* 18.2.4 customWorkbookViews CT_CustomWorkbookViews ? */
case '<customWorkbookViews>': case '</customWorkbookViews>': case '<customWorkbookViews': break;
/* 18.2.3 customWorkbookView CT_CustomWorkbookView + */
case '<customWorkbookView': case '</customWorkbookView>': break;
/* 18.2.18 pivotCaches CT_PivotCaches ? */
case '<pivotCaches>': case '</pivotCaches>': case '<pivotCaches': break;
/* 18.2.17 pivotCache CT_PivotCache ? */
case '<pivotCache': break;
/* 18.2.21 smartTagPr CT_SmartTagPr ? */
case '<smartTagPr': case '<smartTagPr/>': break;
/* 18.2.23 smartTagTypes CT_SmartTagTypes ? */
case '<smartTagTypes': case '<smartTagTypes>': case '</smartTagTypes>': break;
/* 18.2.22 smartTagType CT_SmartTagType ? */
case '<smartTagType': break;
/* 18.2.24 webPublishing CT_WebPublishing ? */
case '<webPublishing': case '<webPublishing/>': break;
/* 18.2.11 fileRecoveryPr CT_FileRecoveryPr ? */
case '<fileRecoveryPr': case '<fileRecoveryPr/>': break;
/* 18.2.26 webPublishObjects CT_WebPublishObjects ? */
case '<webPublishObjects>': case '<webPublishObjects': case '</webPublishObjects>': break;
/* 18.2.25 webPublishObject CT_WebPublishObject ? */
case '<webPublishObject': break;
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst': case '<extLst>': case '</extLst>': case '<extLst/>': break;
/* 18.2.7 ext CT_Extension + */
case '<ext': pass=true; break; //TODO: check with versions of excel
case '</ext>': pass=false; break;
/* Others */
case '<ArchID': break;
case '<AlternateContent':
case '<AlternateContent>': pass=true; break;
case '</AlternateContent>': pass=false; break;
/* TODO */
case '<revisionPtr': break;
default: if(!pass && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in workbook');
}
return x;
});
if(XMLNS_main.indexOf(wb.xmlns) === -1) throw new Error("Unknown Namespace: " + wb.xmlns);
parse_wb_defaults(wb);
return wb;
}
function write_wb_xml(wb/*:Workbook*//*::, opts:?WriteOpts*/)/*:string*/ {
var o = [XML_HEADER];
o[o.length] = writextag('workbook', null, {
'xmlns': XMLNS_main[0],
//'xmlns:mx': XMLNS.mx,
//'xmlns:s': XMLNS_main[0],
'xmlns:r': XMLNS.r
});
var write_names = (wb.Workbook && (wb.Workbook.Names||[]).length > 0);
/* fileVersion */
/* fileSharing */
var workbookPr/*:any*/ = ({codeName:"ThisWorkbook"}/*:any*/);
if(wb.Workbook && wb.Workbook.WBProps) {
WBPropsDef.forEach(function(x) {
/*:: if(!wb.Workbook || !wb.Workbook.WBProps) throw "unreachable"; */
if((wb.Workbook.WBProps[x[0]]/*:any*/) == null) return;
if((wb.Workbook.WBProps[x[0]]/*:any*/) == x[1]) return;
workbookPr[x[0]] = (wb.Workbook.WBProps[x[0]]/*:any*/);
});
/*:: if(!wb.Workbook || !wb.Workbook.WBProps) throw "unreachable"; */
if(wb.Workbook.WBProps.CodeName) { workbookPr.codeName = wb.Workbook.WBProps.CodeName; delete workbookPr.CodeName; }
}
o[o.length] = (writextag('workbookPr', null, workbookPr));
/* workbookProtection */
var sheets = wb.Workbook && wb.Workbook.Sheets || [];
var i = 0;
/* bookViews only written if first worksheet is hidden */
if(sheets && sheets[0] && !!sheets[0].Hidden) {
o[o.length] = "<bookViews>";
for(i = 0; i != wb.SheetNames.length; ++i) {
if(!sheets[i]) break;
if(!sheets[i].Hidden) break;
}
if(i == wb.SheetNames.length) i = 0;
o[o.length] = '<workbookView firstSheet="' + i + '" activeTab="' + i + '"/>';
o[o.length] = "</bookViews>";
}
o[o.length] = "<sheets>";
for(i = 0; i != wb.SheetNames.length; ++i) {
var sht = ({name:escapexml(wb.SheetNames[i].slice(0,31))}/*:any*/);
sht.sheetId = ""+(i+1);
sht["r:id"] = "rId"+(i+1);
if(sheets[i]) switch(sheets[i].Hidden) {
case 1: sht.state = "hidden"; break;
case 2: sht.state = "veryHidden"; break;
}
o[o.length] = (writextag('sheet',null,sht));
}
o[o.length] = "</sheets>";
/* functionGroups */
/* externalReferences */
if(write_names) {
o[o.length] = "<definedNames>";
if(wb.Workbook && wb.Workbook.Names) wb.Workbook.Names.forEach(function(n) {
var d/*:any*/ = {name:n.Name};
if(n.Comment) d.comment = n.Comment;
if(n.Sheet != null) d.localSheetId = ""+n.Sheet;
if(n.Hidden) d.hidden = "1";
if(!n.Ref) return;
o[o.length] = writextag('definedName', escapexml(n.Ref), d);
});
o[o.length] = "</definedNames>";
}
/* calcPr */
/* oleSize */
/* customWorkbookViews */
/* pivotCaches */
/* smartTagPr */
/* smartTagTypes */
/* webPublishing */
/* fileRecoveryPr */
/* webPublishObjects */
/* extLst */
if(o.length>2){ o[o.length] = '</workbook>'; o[1]=o[1].replace("/>",">"); }
return o.join("");
}

362
bits/73_wbbin.js Normal file
View File

@ -0,0 +1,362 @@
/* [MS-XLSB] 2.4.304 BrtBundleSh */
function parse_BrtBundleSh(data, length/*:number*/) {
var z = {};
z.Hidden = data.read_shift(4); //hsState ST_SheetState
z.iTabID = data.read_shift(4);
z.strRelID = parse_RelID(data,length-8);
z.name = parse_XLWideString(data);
return z;
}
function write_BrtBundleSh(data, o) {
if(!o) o = new_buf(127);
o.write_shift(4, data.Hidden);
o.write_shift(4, data.iTabID);
write_RelID(data.strRelID, o);
write_XLWideString(data.name.slice(0,31), o);
return o.length > o.l ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.815 BrtWbProp */
function parse_BrtWbProp(data, length)/*:WBProps*/ {
var o/*:WBProps*/ = ({}/*:any*/);
var flags = data.read_shift(4);
o.defaultThemeVersion = data.read_shift(4);
var strName = (length > 8) ? parse_XLWideString(data) : "";
if(strName.length > 0) o.CodeName = strName;
o.autoCompressPictures = !!(flags & 0x10000);
o.backupFile = !!(flags & 0x40);
o.checkCompatibility = !!(flags & 0x1000);
o.date1904 = !!(flags & 0x01);
o.filterPrivacy = !!(flags & 0x08);
o.hidePivotFieldList = !!(flags & 0x400);
o.promptedSolutions = !!(flags & 0x10);
o.publishItems = !!(flags & 0x800);
o.refreshAllConnections = !!(flags & 0x40000);
o.saveExternalLinkValues = !!(flags & 0x80);
o.showBorderUnselectedTables = !!(flags & 0x04);
o.showInkAnnotation = !!(flags & 0x20);
o.showObjects = ["all", "placeholders", "none"][(flags >> 13) & 0x03];
o.showPivotChartFilter = !!(flags & 0x8000);
o.updateLinks = ["userSet", "never", "always"][(flags >> 8) & 0x03];
return o;
}
function write_BrtWbProp(data/*:?WBProps*/, o) {
if(!o) o = new_buf(72);
var flags = 0;
if(data) {
/* TODO: mirror parse_BrtWbProp fields */
if(data.date1904) flags |= 0x01;
if(data.filterPrivacy) flags |= 0x08;
}
o.write_shift(4, flags);
o.write_shift(4, 0);
write_XLSBCodeName(data && data.CodeName || "ThisWorkbook", o);
return o.slice(0, o.l);
}
function parse_BrtFRTArchID$(data, length) {
var o = {};
data.read_shift(4);
o.ArchID = data.read_shift(4);
data.l += length - 8;
return o;
}
/* [MS-XLSB] 2.4.687 BrtName */
function parse_BrtName(data, length, opts) {
var end = data.l + length;
var flags = data.read_shift(4);
data.l += 1; //var chKey = data.read_shift(1);
var itab = data.read_shift(4);
var name = parse_XLNameWideString(data);
var formula;
var comment = "";
try {
formula = parse_XLSBNameParsedFormula(data, 0, opts);
try {
comment = parse_XLNullableWideString(data);
} catch(e){}
} catch(e) { console.error("Could not parse defined name " + name); }
if(flags & 0x20) name = "_xlnm." + name;
//if(0 /* fProc */) {
// unusedstring1: XLNullableWideString
// description: XLNullableWideString
// helpTopic: XLNullableWideString
// unusedstring2: XLNullableWideString
//}
data.l = end;
var out = ({Name:name, Ptg:formula, Flags: flags}/*:any*/);
if(itab < 0xFFFFFFF) out.Sheet = itab;
if(comment) out.Comment = comment;
return out;
}
function write_BrtName(name, wb) {
var o = new_buf(9);
var flags = 0;
var dname = name.Name;
if(XLSLblBuiltIn.indexOf(dname) > -1) { flags |= 0x20; dname = dname.slice(6); }
o.write_shift(4, flags); // flags
o.write_shift(1, 0); // chKey
o.write_shift(4, name.Sheet == null ? 0xFFFFFFFF : name.Sheet);
var arr = [
o,
write_XLWideString(dname),
write_XLSBNameParsedFormula(name.Ref, wb)
];
if(name.Comment) arr.push(write_XLNullableWideString(name.Comment));
else {
var x = new_buf(4);
x.write_shift(4, 0xFFFFFFFF);
arr.push(x);
}
// if macro (flags & 0x0F):
// write_shift(4, 0xFFFFFFFF);
// write_XLNullableWideString(description)
// write_XLNullableWideString(helpTopic)
// write_shift(4, 0xFFFFFFFF);
return bconcat(arr);
}
/* [MS-XLSB] 2.1.7.61 Workbook */
function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
var state/*:Array<string>*/ = [];
var pass = false;
if(!opts) opts = {};
opts.biff = 12;
var Names = [];
var supbooks = ([[]]/*:any*/);
supbooks.SheetNames = [];
supbooks.XTI = [];
XLSBRecordEnum[0x0010] = { n:"BrtFRTArchID$", f:parse_BrtFRTArchID$ };
recordhopper(data, function hopper_wb(val, R, RT) {
switch(RT) {
case 0x009C: /* 'BrtBundleSh' */
supbooks.SheetNames.push(val.name);
wb.Sheets.push(val); break;
case 0x0099: /* 'BrtWbProp' */
wb.WBProps = val; break;
case 0x0027: /* 'BrtName' */
if(val.Sheet != null) opts.SID = val.Sheet;
val.Ref = val.Ptg ? stringify_formula(val.Ptg, null, null, supbooks, opts) : "#REF!";
delete opts.SID;
delete val.Ptg;
Names.push(val);
break;
case 0x040C: /* 'BrtNameExt' */ break;
case 0x0165: /* 'BrtSupSelf' */
case 0x0166: /* 'BrtSupSame' */
case 0x0163: /* 'BrtSupBookSrc' */
case 0x029B: /* 'BrtSupAddin' */
if(!supbooks[0].length) supbooks[0] = [RT, val];
else supbooks.push([RT, val]);
supbooks[supbooks.length - 1].XTI = [];
break;
case 0x016A: /* 'BrtExternSheet' */
if(supbooks.length === 0) { supbooks[0] = []; supbooks[0].XTI = []; }
supbooks[supbooks.length - 1].XTI = supbooks[supbooks.length - 1].XTI.concat(val);
supbooks.XTI = supbooks.XTI.concat(val);
break;
case 0x0169: /* 'BrtPlaceholderName' */
break;
case 0x0817: /* 'BrtAbsPath15' */
case 0x009E: /* 'BrtBookView' */
case 0x008F: /* 'BrtBeginBundleShs' */
case 0x0298: /* 'BrtBeginFnGroup' */
case 0x0161: /* 'BrtBeginExternals' */
break;
/* case 'BrtModelTimeGroupingCalcCol' */
case 0x0C00: /* 'BrtUid' */
case 0x0C01: /* 'BrtRevisionPtr' */
case 0x0216: /* 'BrtBookProtection' */
case 0x02A5: /* 'BrtBookProtectionIso' */
case 0x009D: /* 'BrtCalcProp' */
case 0x0262: /* 'BrtCrashRecErr' */
case 0x0802: /* 'BrtDecoupledPivotCacheID' */
case 0x009B: /* 'BrtFileRecover' */
case 0x0224: /* 'BrtFileSharing' */
case 0x02A4: /* 'BrtFileSharingIso' */
case 0x0080: /* 'BrtFileVersion' */
case 0x0299: /* 'BrtFnGroup' */
case 0x0850: /* 'BrtModelRelationship' */
case 0x084D: /* 'BrtModelTable' */
case 0x0225: /* 'BrtOleSize' */
case 0x0805: /* 'BrtPivotTableRef' */
case 0x0254: /* 'BrtSmartTagType' */
case 0x081C: /* 'BrtTableSlicerCacheID' */
case 0x081B: /* 'BrtTableSlicerCacheIDs' */
case 0x0822: /* 'BrtTimelineCachePivotCacheID' */
case 0x018D: /* 'BrtUserBookView' */
case 0x009A: /* 'BrtWbFactoid' */
case 0x045D: /* 'BrtWbProp14' */
case 0x0229: /* 'BrtWebOpt' */
case 0x082B: /* 'BrtWorkBookPr15' */
break;
case 0x0023: /* 'BrtFRTBegin' */
state.push(RT); pass = true; break;
case 0x0024: /* 'BrtFRTEnd' */
state.pop(); pass = false; break;
case 0x0025: /* 'BrtACBegin' */
state.push(RT); pass = true; break;
case 0x0026: /* 'BrtACEnd' */
state.pop(); pass = false; break;
case 0x0010: /* 'BrtFRTArchID$' */ break;
default:
if(R.T){/* empty */}
else if(!pass || (opts.WTF && state[state.length-1] != 0x0025 /* BrtACBegin */ && state[state.length-1] != 0x0023 /* BrtFRTBegin */)) throw new Error("Unexpected record 0x" + RT.toString(16));
}
}, opts);
parse_wb_defaults(wb);
// $FlowIgnore
wb.Names = Names;
(wb/*:any*/).supbooks = supbooks;
return wb;
}
function write_BUNDLESHS(ba, wb/*::, opts*/) {
write_record(ba, 0x008F /* BrtBeginBundleShs */);
for(var idx = 0; idx != wb.SheetNames.length; ++idx) {
var viz = wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx] && wb.Workbook.Sheets[idx].Hidden || 0;
var d = { Hidden: viz, iTabID: idx+1, strRelID: 'rId' + (idx+1), name: wb.SheetNames[idx] };
write_record(ba, 0x009C /* BrtBundleSh */, write_BrtBundleSh(d));
}
write_record(ba, 0x0090 /* BrtEndBundleShs */);
}
/* [MS-XLSB] 2.4.649 BrtFileVersion */
function write_BrtFileVersion(data, o) {
if(!o) o = new_buf(127);
for(var i = 0; i != 4; ++i) o.write_shift(4, 0);
write_XLWideString("SheetJS", o);
write_XLWideString(XLSX.version, o);
write_XLWideString(XLSX.version, o);
write_XLWideString("7262", o);
return o.length > o.l ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.301 BrtBookView */
function write_BrtBookView(idx, o) {
if(!o) o = new_buf(29);
o.write_shift(-4, 0);
o.write_shift(-4, 460);
o.write_shift(4, 28800);
o.write_shift(4, 17600);
o.write_shift(4, 500);
o.write_shift(4, idx);
o.write_shift(4, idx);
var flags = 0x78;
o.write_shift(1, flags);
return o.length > o.l ? o.slice(0, o.l) : o;
}
function write_BOOKVIEWS(ba, wb/*::, opts*/) {
/* required if hidden tab appears before visible tab */
if(!wb.Workbook || !wb.Workbook.Sheets) return;
var sheets = wb.Workbook.Sheets;
var i = 0, vistab = -1, hidden = -1;
for(; i < sheets.length; ++i) {
if(!sheets[i] || !sheets[i].Hidden && vistab == -1) vistab = i;
else if(sheets[i].Hidden == 1 && hidden == -1) hidden = i;
}
if(hidden > vistab) return;
write_record(ba, 0x0087 /* BrtBeginBookViews */);
write_record(ba, 0x009E /* BrtBookView */, write_BrtBookView(vistab));
/* 1*(BrtBookView *FRT) */
write_record(ba, 0x0088 /* BrtEndBookViews */);
}
function write_BRTNAMES(ba, wb) {
if(!wb.Workbook || !wb.Workbook.Names) return;
wb.Workbook.Names.forEach(function(name) { try {
if(name.Flags & 0x0e) return; // TODO: macro name write
write_record(ba, 0x0027 /* BrtName */, write_BrtName(name, wb));
} catch(e) {
console.error("Could not serialize defined name " + JSON.stringify(name));
} });
}
function write_SELF_EXTERNS_xlsb(wb) {
var L = wb.SheetNames.length;
var o = new_buf(12 * L + 28);
o.write_shift(4, L + 2);
o.write_shift(4, 0); o.write_shift(4, -2); o.write_shift(4, -2); // workbook-level reference
o.write_shift(4, 0); o.write_shift(4, -1); o.write_shift(4, -1); // #REF!...
for(var i = 0; i < L; ++i) {
o.write_shift(4, 0); o.write_shift(4, i); o.write_shift(4, i);
}
return o;
}
function write_EXTERNALS_xlsb(ba, wb) {
write_record(ba, 0x0161 /* BrtBeginExternals */);
write_record(ba, 0x0165 /* BrtSupSelf */);
write_record(ba, 0x016A /* BrtExternSheet */, write_SELF_EXTERNS_xlsb(wb, 0));
write_record(ba, 0x0162 /* BrtEndExternals */);
}
/* [MS-XLSB] 2.4.305 BrtCalcProp */
/*function write_BrtCalcProp(data, o) {
if(!o) o = new_buf(26);
o.write_shift(4,0); // force recalc
o.write_shift(4,1);
o.write_shift(4,0);
write_Xnum(0, o);
o.write_shift(-4, 1023);
o.write_shift(1, 0x33);
o.write_shift(1, 0x00);
return o;
}*/
/* [MS-XLSB] 2.4.646 BrtFileRecover */
/*function write_BrtFileRecover(data, o) {
if(!o) o = new_buf(1);
o.write_shift(1,0);
return o;
}*/
/* [MS-XLSB] 2.1.7.61 Workbook */
function write_wb_bin(wb, opts) {
var ba = buf_array();
write_record(ba, 0x0083 /* BrtBeginBook */);
write_record(ba, 0x0080 /* BrtFileVersion */, write_BrtFileVersion());
/* [[BrtFileSharingIso] BrtFileSharing] */
write_record(ba, 0x0099 /* BrtWbProp */, write_BrtWbProp(wb.Workbook && wb.Workbook.WBProps || null));
/* [ACABSPATH] */
/* [[BrtBookProtectionIso] BrtBookProtection] */
write_BOOKVIEWS(ba, wb, opts);
write_BUNDLESHS(ba, wb, opts);
/* [FNGROUP] */
write_EXTERNALS_xlsb(ba, wb);
if((wb.Workbook||{}).Names) write_BRTNAMES(ba, wb);
/* write_record(ba, 0x009D BrtCalcProp, write_BrtCalcProp()); */
/* [BrtOleSize] */
/* *(BrtUserBookView *FRT) */
/* [PIVOTCACHEIDS] */
/* [BrtWbFactoid] */
/* [SMARTTAGTYPES] */
/* [BrtWebOpt] */
/* write_record(ba, 0x009B BrtFileRecover, write_BrtFileRecover()); */
/* [WEBPUBITEMS] */
/* [CRERRS] */
/* FRTWORKBOOK */
write_record(ba, 0x0084 /* BrtEndBook */);
return ba.end();
}

54
bits/74_xmlbin.js Normal file
View File

@ -0,0 +1,54 @@
function parse_wb(data, name/*:string*/, opts)/*:WorkbookFile*/ {
if(name.slice(-4)===".bin") return parse_wb_bin((data/*:any*/), opts);
return parse_wb_xml((data/*:any*/), opts);
}
function parse_ws(data, name/*:string*/, idx/*:number*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_ws_bin((data/*:any*/), opts, idx, rels, wb, themes, styles);
return parse_ws_xml((data/*:any*/), opts, idx, rels, wb, themes, styles);
}
function parse_cs(data, name/*:string*/, idx/*:number*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_cs_bin((data/*:any*/), opts, idx, rels, wb, themes, styles);
return parse_cs_xml((data/*:any*/), opts, idx, rels, wb, themes, styles);
}
function parse_ms(data, name/*:string*/, idx/*:number*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_ms_bin((data/*:any*/), opts, idx, rels, wb, themes, styles);
return parse_ms_xml((data/*:any*/), opts, idx, rels, wb, themes, styles);
}
function parse_ds(data, name/*:string*/, idx/*:number*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_ds_bin((data/*:any*/), opts, idx, rels, wb, themes, styles);
return parse_ds_xml((data/*:any*/), opts, idx, rels, wb, themes, styles);
}
function parse_sty(data, name/*:string*/, themes, opts) {
if(name.slice(-4)===".bin") return parse_sty_bin((data/*:any*/), themes, opts);
return parse_sty_xml((data/*:any*/), themes, opts);
}
function parse_sst(data, name/*:string*/, opts)/*:SST*/ {
if(name.slice(-4)===".bin") return parse_sst_bin((data/*:any*/), opts);
return parse_sst_xml((data/*:any*/), opts);
}
function parse_cmnt(data, name/*:string*/, opts)/*:Array<RawComment>*/ {
if(name.slice(-4)===".bin") return parse_comments_bin((data/*:any*/), opts);
return parse_comments_xml((data/*:any*/), opts);
}
function parse_cc(data, name/*:string*/, opts) {
if(name.slice(-4)===".bin") return parse_cc_bin((data/*:any*/), name, opts);
return parse_cc_xml((data/*:any*/), name, opts);
}
function parse_xlink(data, rel, name/*:string*/, opts) {
if(name.slice(-4)===".bin") return parse_xlink_bin((data/*:any*/), rel, name, opts);
return parse_xlink_xml((data/*:any*/), rel, name, opts);
}
function parse_xlmeta(data, name/*:string*/, opts) {
if(name.slice(-4)===".bin") return parse_xlmeta_bin((data/*:any*/), name, opts);
return parse_xlmeta_xml((data/*:any*/), name, opts);
}

1258
bits/75_xlml.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,100 +0,0 @@
/* 18.2.28 (CT_WorkbookProtection) Defaults */
var WBPropsDef = [
['allowRefreshQuery', '0'],
['autoCompressPictures', '1'],
['backupFile', '0'],
['checkCompatibility', '0'],
['codeName', ''],
['date1904', '0'],
['dateCompatibility', '1'],
//['defaultThemeVersion', '0'],
['filterPrivacy', '0'],
['hidePivotFieldList', '0'],
['promptedSolutions', '0'],
['publishItems', '0'],
['refreshAllConnections', false],
['saveExternalLinkValues', '1'],
['showBorderUnselectedTables', '1'],
['showInkAnnotation', '1'],
['showObjects', 'all'],
['showPivotChartFilter', '0']
//['updateLinks', 'userSet']
];
/* 18.2.30 (CT_BookView) Defaults */
var WBViewDef = [
['activeTab', '0'],
['autoFilterDateGrouping', '1'],
['firstSheet', '0'],
['minimized', '0'],
['showHorizontalScroll', '1'],
['showSheetTabs', '1'],
['showVerticalScroll', '1'],
['tabRatio', '600'],
['visibility', 'visible']
//window{Height,Width}, {x,y}Window
];
/* 18.2.19 (CT_Sheet) Defaults */
var SheetDef = [
['state', 'visible']
];
/* 18.2.2 (CT_CalcPr) Defaults */
var CalcPrDef = [
['calcCompleted', 'true'],
['calcMode', 'auto'],
['calcOnSave', 'true'],
['concurrentCalc', 'true'],
['fullCalcOnLoad', 'false'],
['fullPrecision', 'true'],
['iterate', 'false'],
['iterateCount', '100'],
['iterateDelta', '0.001'],
['refMode', 'A1']
];
/* 18.2.3 (CT_CustomWorkbookView) Defaults */
var CustomWBViewDef = [
['autoUpdate', 'false'],
['changesSavedWin', 'false'],
['includeHiddenRowCol', 'true'],
['includePrintSettings', 'true'],
['maximized', 'false'],
['minimized', 'false'],
['onlySync', 'false'],
['personalView', 'false'],
['showComments', 'commIndicator'],
['showFormulaBar', 'true'],
['showHorizontalScroll', 'true'],
['showObjects', 'all'],
['showSheetTabs', 'true'],
['showStatusbar', 'true'],
['showVerticalScroll', 'true'],
['tabRatio', '600'],
['xWindow', '0'],
['yWindow', '0']
];
function push_defaults_array(target, defaults) {
for(var j = 0; j != target.length; ++j) { var w = target[j];
for(var i=0; i != defaults.length; ++i) { var z = defaults[i];
if(w[z[0]] == null) w[z[0]] = z[1];
}
}
}
function push_defaults(target, defaults) {
for(var i = 0; i != defaults.length; ++i) { var z = defaults[i];
if(target[z[0]] == null) target[z[0]] = z[1];
}
}
function parse_wb_defaults(wb) {
push_defaults(wb.WBProps, WBPropsDef);
push_defaults(wb.CalcPr, CalcPrDef);
push_defaults_array(wb.WBView, WBViewDef);
push_defaults_array(wb.Sheets, SheetDef);
_ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904, 'date1904');
}

735
bits/76_xls.js Normal file
View File

@ -0,0 +1,735 @@
/* [MS-OLEDS] 2.3.8 CompObjStream */
function parse_compobj(obj/*:CFBEntry*/) {
var v = {};
var o = obj.content;
/*:: if(o == null) return; */
/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
o.l = 28;
v.AnsiUserType = o.read_shift(0, "lpstr-ansi");
v.AnsiClipboardFormat = parse_ClipboardFormatOrAnsiString(o);
if(o.length - o.l <= 4) return v;
var m/*:number*/ = o.read_shift(4);
if(m == 0 || m > 40) return v;
o.l-=4; v.Reserved1 = o.read_shift(0, "lpstr-ansi");
if(o.length - o.l <= 4) return v;
m = o.read_shift(4);
if(m !== 0x71b239f4) return v;
v.UnicodeClipboardFormat = parse_ClipboardFormatOrUnicodeString(o);
m = o.read_shift(4);
if(m == 0 || m > 40) return v;
o.l-=4; v.Reserved2 = o.read_shift(0, "lpwstr");
}
/*
Continue logic for:
- 2.4.58 Continue 0x003c
- 2.4.59 ContinueBigName 0x043c
- 2.4.60 ContinueFrt 0x0812
- 2.4.61 ContinueFrt11 0x0875
- 2.4.62 ContinueFrt12 0x087f
*/
var CONTINUE_RT = [ 0x003c, 0x043c, 0x0812, 0x0875, 0x087f ];
function slurp(RecordType, R, blob, length/*:number*/, opts)/*:any*/ {
var l = length;
var bufs = [];
var d = blob.slice(blob.l,blob.l+l);
if(opts && opts.enc && opts.enc.insitu && d.length > 0) switch(RecordType) {
case 0x0009: case 0x0209: case 0x0409: case 0x0809/* BOF */: case 0x002F /* FilePass */: case 0x0195 /* FileLock */: case 0x00E1 /* InterfaceHdr */: case 0x0196 /* RRDInfo */: case 0x0138 /* RRDHead */: case 0x0194 /* UsrExcl */: case 0x000a /* EOF */:
break;
case 0x0085 /* BoundSheet8 */:
break;
default:
opts.enc.insitu(d);
}
bufs.push(d);
blob.l += l;
var nextrt = __readUInt16LE(blob,blob.l), next = XLSRecordEnum[nextrt];
var start = 0;
while(next != null && CONTINUE_RT.indexOf(nextrt) > -1) {
l = __readUInt16LE(blob,blob.l+2);
start = blob.l + 4;
if(nextrt == 0x0812 /* ContinueFrt */) start += 4;
else if(nextrt == 0x0875 || nextrt == 0x087f) {
start += 12;
}
d = blob.slice(start,blob.l+4+l);
bufs.push(d);
blob.l += 4+l;
next = (XLSRecordEnum[nextrt = __readUInt16LE(blob, blob.l)]);
}
var b = (bconcat(bufs)/*:any*/);
prep_blob(b, 0);
var ll = 0; b.lens = [];
for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; }
if(b.length < length) throw "XLS Record 0x" + RecordType.toString(16) + " Truncated: " + b.length + " < " + length;
return R.f(b, b.length, opts);
}
function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
if(p.t === 'z') return;
if(!p.XF) return;
var fmtid = 0;
try {
fmtid = p.z || p.XF.numFmtId || 0;
if(opts.cellNF && p.z == null) p.z = table_fmt[fmtid];
} catch(e) { if(opts.WTF) throw e; }
if(!opts || opts.cellText !== false) try {
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
else if(fmtid === 0 || fmtid == "General") {
if(p.t === 'n') {
if((p.v|0) === p.v) p.w = p.v.toString(10);
else p.w = SSF_general_num(p.v);
}
else p.w = SSF_general(p.v);
}
else p.w = SSF_format(fmtid,p.v, {date1904:!!date1904, dateNF: opts && opts.dateNF});
} catch(e) { if(opts.WTF) throw e; }
if(opts.cellDates && fmtid && p.t == 'n' && fmt_is_date(table_fmt[fmtid] || String(fmtid))) {
var _d = SSF_parse_date_code(p.v + (date1904 ? 1462 : 0)); if(_d) { p.t = 'd'; p.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
}
}
function make_cell(val, ixfe, t)/*:Cell*/ {
return ({v:val, ixfe:ixfe, t:t}/*:any*/);
}
// 2.3.2
function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
var wb = ({opts:{}}/*:any*/);
var Sheets = {};
if(DENSE != null && options.dense == null) options.dense = DENSE;
var out/*:Worksheet*/ = ({}/*:any*/); if(options.dense) out["!data"] = [];
var Directory = {};
var range/*:Range*/ = ({}/*:any*/);
var last_formula = null;
var sst/*:SST*/ = ([]/*:any*/);
var cur_sheet = "";
var Preamble = {};
var lastcell, last_cell = "", cc/*:Cell*/, cmnt, rngC, rngR;
var sharedf = {};
var arrayf/*:Array<[Range, string]>*/ = [];
var temp_val/*:Cell*/;
var country;
var XFs = []; /* XF records */
var palette/*:Array<[number, number, number]>*/ = [];
var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false}, Views:[{}] }/*:any*/), wsprops = {};
var biff4w = false;
var get_rgb = function getrgb(icv/*:number*/)/*:[number, number, number]*/ {
if(icv < 8) return XLSIcv[icv];
if(icv < 64) return palette[icv-8] || XLSIcv[icv];
return XLSIcv[icv];
};
var process_cell_style = function pcs(line/*:any*/, options) {
var xfd = line.XF.data;
if(!xfd || !xfd.patternType || !options || !options.cellStyles) return;
line.s = ({}/*:any*/);
line.s.patternType = xfd.patternType;
var t;
if((t = rgb2Hex(get_rgb(xfd.icvFore)))) { line.s.fgColor = {rgb:t}; }
if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; }
};
var addcell = function addcell(cell/*:any*/, line/*:any*/, options/*:any*/) {
if(!biff4w && file_depth > 1) return;
if(options.sheetRows && cell.r >= options.sheetRows) return;
if(options.cellStyles && line.XF && line.XF.data) process_cell_style(line, options);
delete line.ixfe; delete line.XF;
lastcell = cell;
last_cell = encode_cell(cell);
if(!range || !range.s || !range.e) range = {s:{r:0,c:0},e:{r:0,c:0}};
if(cell.r < range.s.r) range.s.r = cell.r;
if(cell.c < range.s.c) range.s.c = cell.c;
if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1;
if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1;
if(options.cellFormula && line.f) {
for(var afi = 0; afi < arrayf.length; ++afi) {
if(arrayf[afi][0].s.c > cell.c || arrayf[afi][0].s.r > cell.r) continue;
if(arrayf[afi][0].e.c < cell.c || arrayf[afi][0].e.r < cell.r) continue;
line.F = encode_range(arrayf[afi][0]);
if(arrayf[afi][0].s.c != cell.c || arrayf[afi][0].s.r != cell.r) delete line.f;
if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts);
break;
}
}
{
if(options.dense) {
if(!out["!data"][cell.r]) out["!data"][cell.r] = [];
out["!data"][cell.r][cell.c] = line;
} else out[last_cell] = line;
}
};
var opts = ({
enc: false, // encrypted
sbcch: 0, // cch in the preceding SupBook
snames: [], // sheetnames
sharedf: sharedf, // shared formulae by address
arrayf: arrayf, // array formulae array
rrtabid: [], // RRTabId
lastuser: "", // Last User from WriteAccess
biff: 8, // BIFF version
codepage: 0, // CP from CodePage record
winlocked: 0, // fLockWn from WinProtect
cellStyles: !!options && !!options.cellStyles,
WTF: !!options && !!options.wtf
}/*:any*/);
if(options.password) opts.password = options.password;
var themes;
var merges/*:Array<Range>*/ = [];
var objects = [];
var colinfo/*:Array<ColInfo>*/ = [], rowinfo/*:Array<RowInfo>*/ = [];
var seencol = false;
var supbooks = ([]/*:any*/); // 1-indexed, will hold extern names
supbooks.SheetNames = opts.snames;
supbooks.sharedf = opts.sharedf;
supbooks.arrayf = opts.arrayf;
supbooks.names = [];
supbooks.XTI = [];
var last_RT = 0;
var file_depth = 0; /* TODO: make a real stack */
var BIFF2Fmt = 0, BIFF2FmtTable/*:Array<string>*/ = [];
var FilterDatabases = []; /* TODO: sort out supbooks and process elsewhere */
var last_lbl/*:?DefinedName*/;
/* explicit override for some broken writers */
opts.codepage = 1200;
set_cp(1200);
var seen_codepage = false;
while(blob.l < blob.length - 1) {
var s = blob.l;
var RecordType = blob.read_shift(2);
if(RecordType === 0 && last_RT === 0x000a /* EOF */) break;
var length = (blob.l === blob.length ? 0 : blob.read_shift(2));
var R = XLSRecordEnum[RecordType];
if(file_depth == 0 && [0x0009, 0x0209, 0x0409, 0x0809].indexOf(RecordType) == -1 /* BOF */) break;
//console.log(RecordType.toString(16), RecordType, R, blob.l, length, blob.length);
//if(!R) console.log(blob.slice(blob.l, blob.l + length));
if(R && R.f) {
if(options.bookSheets) {
if(last_RT === 0x0085 /* BoundSheet8 */ && RecordType !== 0x0085 /* R.n !== 'BoundSheet8' */) break;
}
last_RT = RecordType;
if(R.r === 2 || R.r == 12) {
var rt = blob.read_shift(2); length -= 2;
if(!opts.enc && rt !== RecordType && (((rt&0xFF)<<8)|(rt>>8)) !== RecordType) throw new Error("rt mismatch: " + rt + "!=" + RecordType);
if(R.r == 12){
blob.l += 10; length -= 10;
} // skip FRT
}
//console.error(R,blob.l,length,blob.length);
var val/*:any*/ = ({}/*:any*/);
if(RecordType === 0x000a /* EOF */) val = /*::(*/R.f(blob, length, opts)/*:: :any)*/;
else val = /*::(*/slurp(RecordType, R, blob, length, opts)/*:: :any)*/;
/*:: val = (val:any); */
if(file_depth == 0 && [0x0009, 0x0209, 0x0409, 0x0809].indexOf(last_RT) === -1 /* BOF */) continue;
switch(RecordType) {
case 0x0022 /* Date1904 */:
/*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
case 0x0086 /* WriteProtect */: wb.opts.WriteProtect = true; break;
case 0x002f /* FilePass */:
if(!opts.enc) blob.l = 0;
opts.enc = val;
if(!options.password) throw new Error("File is password-protected");
if(val.valid == null) throw new Error("Encryption scheme unsupported");
if(!val.valid) throw new Error("Password is incorrect");
break;
case 0x005c /* WriteAccess */: opts.lastuser = val; break;
case 0x0042 /* CodePage */:
var cpval = Number(val);
/* overrides based on test cases */
switch(cpval) {
case 0x5212: cpval = 1200; break;
case 0x8000: cpval = 10000; break;
case 0x8001: cpval = 1252; break;
}
set_cp(opts.codepage = cpval);
seen_codepage = true;
break;
case 0x013d /* RRTabId */: opts.rrtabid = val; break;
case 0x0019 /* WinProtect */: opts.winlocked = val; break;
case 0x01b7 /* RefreshAll */: wb.opts["RefreshAll"] = val; break;
case 0x000c /* CalcCount */: wb.opts["CalcCount"] = val; break;
case 0x0010 /* CalcDelta */: wb.opts["CalcDelta"] = val; break;
case 0x0011 /* CalcIter */: wb.opts["CalcIter"] = val; break;
case 0x000d /* CalcMode */: wb.opts["CalcMode"] = val; break;
case 0x000e /* CalcPrecision */: wb.opts["CalcPrecision"] = val; break;
case 0x005f /* CalcSaveRecalc */: wb.opts["CalcSaveRecalc"] = val; break;
case 0x000f /* CalcRefMode */: opts.CalcRefMode = val; break; // TODO: implement R1C1
case 0x08a3 /* ForceFullCalculation */: wb.opts.FullCalc = val; break;
case 0x0081 /* WsBool */:
if(val.fDialog) out["!type"] = "dialog";
if(!val.fBelow) (out["!outline"] || (out["!outline"] = {})).above = true;
if(!val.fRight) (out["!outline"] || (out["!outline"] = {})).left = true;
break; // TODO
case 0x0043: /* BIFF2XF */ case 0x0243: /* BIFF3XF */ case 0x0443: /* BIFF4XF */
case 0x00e0 /* XF */:
XFs.push(val); break;
case 0x01ae /* SupBook */:
supbooks.push([val]);
supbooks[supbooks.length-1].XTI = [];
break;
case 0x0023: case 0x0223 /* ExternName */:
supbooks[supbooks.length-1].push(val);
break;
case 0x0018: case 0x0218 /* Lbl */:
last_lbl = ({
Name: val.Name,
Ref: stringify_formula(val.rgce,range,null,supbooks,opts)
}/*:DefinedName*/);
if(val.itab > 0) last_lbl.Sheet = val.itab - 1;
supbooks.names.push(last_lbl);
if(!supbooks[0]) { supbooks[0] = []; supbooks[0].XTI = []; }
supbooks[supbooks.length-1].push(val);
if(val.Name == "_xlnm._FilterDatabase" && val.itab > 0)
if(val.rgce && val.rgce[0] && val.rgce[0][0] && val.rgce[0][0][0] == 'PtgArea3d')
FilterDatabases[val.itab - 1] = { ref: encode_range(val.rgce[0][0][1][2]) };
break;
case 0x0016 /* ExternCount */: opts.ExternCount = val; break;
case 0x0017 /* ExternSheet */:
if(supbooks.length == 0) { supbooks[0] = []; supbooks[0].XTI = []; }
supbooks[supbooks.length - 1].XTI = supbooks[supbooks.length - 1].XTI.concat(val); supbooks.XTI = supbooks.XTI.concat(val); break;
case 0x0894 /* NameCmt */:
/* TODO: search for correct name */
if(opts.biff < 8) break;
if(last_lbl != null) last_lbl.Comment = val[1];
break;
case 0x0012 /* Protect */: out["!protect"] = val; break; /* for sheet or book */
case 0x0013 /* Password */: if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
case 0x0085 /* BoundSheet8 */: {
Directory[opts.biff == 4 ? opts.snames.length : val.pos] = val;
opts.snames.push(val.name);
} break;
case 0x000a /* EOF */: {
if(--file_depth ? !biff4w : biff4w) break;
if(range.e) {
if(range.e.r > 0 && range.e.c > 0) {
range.e.r--; range.e.c--;
out["!ref"] = encode_range(range);
if(options.sheetRows && options.sheetRows <= range.e.r) {
var tmpri = range.e.r;
range.e.r = options.sheetRows - 1;
out["!fullref"] = out["!ref"];
out["!ref"] = encode_range(range);
range.e.r = tmpri;
}
range.e.r++; range.e.c++;
}
if(merges.length > 0) out["!merges"] = merges;
if(objects.length > 0) out["!objects"] = objects;
if(colinfo.length > 0) out["!cols"] = colinfo;
if(rowinfo.length > 0) out["!rows"] = rowinfo;
Workbook.Sheets.push(wsprops);
}
if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out;
out = ({}/*:any*/); if(options.dense) out["!data"] = [];
} break;
case 0x0009: case 0x0209: case 0x0409: case 0x0809 /* BOF */: {
if(opts.biff === 8) opts.biff = {
0x0009: 2,
0x0209: 3,
0x0409: 4
}[RecordType] || {
0x0200: 2,
0x0300: 3,
0x0400: 4,
0x0500: 5,
0x0600: 8,
0x0002: 2,
0x0007: 2
}[val.BIFFVer] || 8;
opts.biffguess = val.BIFFVer == 0;
if(val.BIFFVer == 0 && val.dt == 0x1000) { opts.biff = 5; seen_codepage = true; set_cp(opts.codepage = 28591); }
if(opts.biff == 4 && val.dt & 0x100) biff4w = true;
if(opts.biff == 8 && val.BIFFVer == 0 && val.dt == 16) opts.biff = 2;
if(file_depth++ && !biff4w) break;
out = ({}/*:any*/); if(options.dense) out["!data"] = [];
if(opts.biff < 8 && !seen_codepage) { seen_codepage = true; set_cp(opts.codepage = options.codepage || 1252); }
if(opts.biff == 4 && biff4w) {
cur_sheet = (Directory[opts.snames.indexOf(cur_sheet)+1] || {name:""}).name;
} else if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) {
if(cur_sheet === "") cur_sheet = "Sheet1";
range = {s:{r:0,c:0},e:{r:0,c:0}};
/* fake BoundSheet8 */
var fakebs8 = {pos: blob.l - length, name:cur_sheet};
Directory[fakebs8.pos] = fakebs8;
opts.snames.push(cur_sheet);
}
else cur_sheet = (Directory[s] || {name:""}).name;
if(val.dt == 0x20) out["!type"] = "chart";
if(val.dt == 0x40) out["!type"] = "macro";
merges = [];
objects = [];
opts.arrayf = arrayf = [];
colinfo = []; rowinfo = [];
seencol = false;
wsprops = {Hidden:(Directory[s]||{hs:0}).hs, name:cur_sheet };
} break;
case 0x0203 /* Number */: case 0x0003 /* BIFF2NUM */: case 0x0002 /* BIFF2INT */: {
if(out["!type"] == "chart") if(options.dense ? (out["!data"][val.r]||[])[val.c]: out[encode_col(val.c) + encode_row(val.r)]) ++val.c;
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe]||{}, v:val.val, t:'n'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
case 0x0005: case 0x0205 /* BoolErr */: {
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
case 0x027e /* RK */: {
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
case 0x00bd /* MulRk */: {
for(var j = val.c; j <= val.C; ++j) {
var ixfe = val.rkrec[j-val.c][0];
temp_val= ({ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:j, r:val.r}, temp_val, options);
}
} break;
case 0x0006: case 0x0206: case 0x0406 /* Formula */: {
if(val.val == 'String') { last_formula = val; break; }
temp_val = make_cell(val.val, val.cell.ixfe, val.tt);
temp_val.XF = XFs[temp_val.ixfe];
if(options.cellFormula) {
var _f = val.formula;
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
var _fe = encode_cell({r:_fr, c:_fc});
if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
else temp_val.F = ((options.dense ? (out["!data"][_fr]||[])[_fc]: out[_fe]) || {}).F;
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
}
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell(val.cell, temp_val, options);
last_formula = val;
} break;
case 0x0007: case 0x0207 /* String */: {
if(last_formula) { /* technically always true */
last_formula.val = val;
temp_val = make_cell(val, last_formula.cell.ixfe, 's');
temp_val.XF = XFs[temp_val.ixfe];
if(options.cellFormula) {
temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
}
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell(last_formula.cell, temp_val, options);
last_formula = null;
} else throw new Error("String record expects Formula");
} break;
case 0x0021: case 0x0221 /* Array */: {
arrayf.push(val);
var _arraystart = encode_cell(val[0].s);
cc = options.dense ? (out["!data"][val[0].s.r]||[])[val[0].s.c] : out[_arraystart];
if(options.cellFormula && cc) {
if(!last_formula) break; /* technically unreachable */
if(!_arraystart || !cc) break;
cc.f = ""+stringify_formula(val[1], range, val[0], supbooks, opts);
cc.F = encode_range(val[0]);
}
} break;
case 0x04bc /* ShrFmla */: {
if(!options.cellFormula) break;
if(last_cell) {
/* TODO: capture range */
if(!last_formula) break; /* technically unreachable */
sharedf[encode_cell(last_formula.cell)]= val[0];
cc = options.dense ? (out["!data"][last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
(cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
}
} break;
case 0x00fd /* LabelSst */:
temp_val=make_cell(sst[val.isst].t, val.ixfe, 's');
if(sst[val.isst].h) temp_val.h = sst[val.isst].h;
temp_val.XF = XFs[temp_val.ixfe];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
break;
case 0x0201 /* Blank */: if(options.sheetStubs) {
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
case 0x00be /* MulBlank */: if(options.sheetStubs) {
for(var _j = val.c; _j <= val.C; ++_j) {
var _ixfe = val.ixfe[_j-val.c];
temp_val= ({ixfe:_ixfe, XF:XFs[_ixfe], t:'z'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:_j, r:val.r}, temp_val, options);
}
} break;
case 0x00d6 /* RString */:
case 0x0204 /* Label */: case 0x0004 /* BIFF2STR */:
temp_val=make_cell(val.val, val.ixfe, 's');
temp_val.XF = XFs[temp_val.ixfe];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
break;
case 0x0000: case 0x0200 /* Dimensions */: {
if(file_depth === 1) range = val; /* TODO: stack */
} break;
case 0x00fc /* SST */: {
sst = val;
} break;
case 0x041e /* Format */: { /* val = [id, fmt] */
if(opts.biff >= 3 && opts.biff <= 4) {
BIFF2FmtTable[BIFF2Fmt++] = val[1];
for(var b4idx = 0; b4idx < BIFF2Fmt + 163; ++b4idx) if(table_fmt[b4idx] == val[1]) break;
if(b4idx >= 163) SSF__load(val[1], BIFF2Fmt + 163);
}
else SSF__load(val[1], val[0]);
} break;
case 0x001e /* BIFF2FORMAT */: {
BIFF2FmtTable[BIFF2Fmt++] = val;
for(var b2idx = 0; b2idx < BIFF2Fmt + 163; ++b2idx) if(table_fmt[b2idx] == val) break;
if(b2idx >= 163) SSF__load(val, BIFF2Fmt + 163);
} break;
case 0x00e5 /* MergeCells */: merges = merges.concat(val); break;
case 0x005d /* Obj */: objects[val.cmo[0]] = opts.lastobj = val; break;
case 0x01b6 /* TxO */: opts.lastobj.TxO = val; break;
case 0x007f /* ImData */: opts.lastobj.ImData = val; break;
case 0x01b8 /* HLink */: {
for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
cc = options.dense ? (out["!data"][rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
if(cc) cc.l = val[1];
}
} break;
case 0x0800 /* HLinkTooltip */: {
for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
cc = options.dense ? (out["!data"][rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
if(cc && cc.l) cc.l.Tooltip = val[1];
}
} break;
case 0x001c /* Note */: {
/* TODO: comment continuation (row == -1 / 0xFFFF) */
cc = options.dense ? (out["!data"][val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
if(!cc) {
if(options.dense) {
if(!out["!data"][val[0].r]) out["!data"][val[0].r] = [];
cc = out["!data"][val[0].r][val[0].c] = ({t:"z"}/*:any*/);
} else {
cc = out[encode_cell(val[0])] = ({t:"z"}/*:any*/);
}
range.e.r = Math.max(range.e.r, val[0].r);
range.s.r = Math.min(range.s.r, val[0].r);
range.e.c = Math.max(range.e.c, val[0].c);
range.s.c = Math.min(range.s.c, val[0].c);
}
if(!cc.c) cc.c = [];
if(opts.biff <= 5 && opts.biff >= 2) cmnt = {a:"SheetJ5", t:val[1]};
else {
var noteobj = objects[val[2]];
cmnt = {a:val[1],t:noteobj.TxO.t};
if(val[3] != null && !(val[3] & 0x02)) cc.c.hidden = true;
}
cc.c.push(cmnt);
} break;
case 0x087d /* XFExt */: update_xfext(XFs[val.ixfe], val.ext); break;
case 0x007d /* ColInfo */: {
if(!opts.cellStyles) break;
while(val.e >= val.s) {
colinfo[val.e--] = { width: val.w/256, level: (val.level || 0), hidden: !!(val.flags & 1) };
if(!seencol) { seencol = true; find_mdw_colw(val.w/256); }
process_col(colinfo[val.e+1]);
}
} break;
case 0x0208 /* Row */: {
var rowobj = {};
if(val.level != null) { rowinfo[val.r] = rowobj; rowobj.level = val.level; }
if(val.hidden) { rowinfo[val.r] = rowobj; rowobj.hidden = true; }
if(val.hpt) {
rowinfo[val.r] = rowobj;
rowobj.hpt = val.hpt; rowobj.hpx = pt2px(val.hpt);
}
} break;
case 0x0026 /* LeftMargin */:
case 0x0027 /* RightMargin */:
case 0x0028 /* TopMargin */:
case 0x0029 /* BottomMargin */:
if(!out['!margins']) default_margins(out['!margins'] = {});
out['!margins'][({0x26: "left", 0x27:"right", 0x28:"top", 0x29:"bottom"})[RecordType]] = val;
break;
case 0x00a1 /* Setup */: // TODO
if(!out['!margins']) default_margins(out['!margins'] = {});
out['!margins'].header = val.header;
out['!margins'].footer = val.footer;
break;
case 0x023e /* Window2 */: // TODO
// $FlowIgnore
if(val.RTL) Workbook.Views[0].RTL = true;
break;
case 0x0092 /* Palette */: palette = val; break;
case 0x0896 /* Theme */: themes = val; break;
case 0x008c /* Country */: country = val; break;
case 0x01ba /* CodeName */: {
/*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
if(!cur_sheet) Workbook.WBProps.CodeName = val || "ThisWorkbook";
else wsprops.CodeName = val || wsprops.name;
} break;
}
} else {
if(!R) console.error("Missing Info for XLS Record 0x" + RecordType.toString(16));
blob.l += length;
}
}
wb.SheetNames=keys(Directory).sort(function(a,b) { return Number(a) - Number(b); }).map(function(x){return Directory[x].name;});
if(!options.bookSheets) wb.Sheets=Sheets;
if(!wb.SheetNames.length && Preamble["!ref"]) {
wb.SheetNames.push("Sheet1");
/*jshint -W069 */
if(wb.Sheets) wb.Sheets["Sheet1"] = Preamble;
/*jshint +W069 */
} else wb.Preamble=Preamble;
if(wb.Sheets) FilterDatabases.forEach(function(r,i) { wb.Sheets[wb.SheetNames[i]]['!autofilter'] = r; });
wb.Strings = sst;
wb.SSF = dup(table_fmt);
if(opts.enc) wb.Encryption = opts.enc;
if(themes) wb.Themes = themes;
wb.Metadata = {};
if(country !== undefined) wb.Metadata.Country = country;
if(supbooks.names.length > 0) Workbook.Names = supbooks.names;
wb.Workbook = Workbook;
return wb;
}
/* TODO: split props*/
var PSCLSID = {
SI: "e0859ff2f94f6810ab9108002b27b3d9",
DSI: "02d5cdd59c2e1b10939708002b2cf9ae",
UDI: "05d5cdd59c2e1b10939708002b2cf9ae"
};
function parse_xls_props(cfb/*:CFBContainer*/, props, o) {
/* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
var DSI = CFB.find(cfb, '/!DocumentSummaryInformation');
if(DSI && DSI.size > 0) try {
var DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI, PSCLSID.DSI);
for(var d in DocSummary) props[d] = DocSummary[d];
} catch(e) {if(o.WTF) throw e;/* empty */}
/* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
var SI = CFB.find(cfb, '/!SummaryInformation');
if(SI && SI.size > 0) try {
var Summary = parse_PropertySetStream(SI, SummaryPIDSI, PSCLSID.SI);
for(var s in Summary) if(props[s] == null) props[s] = Summary[s];
} catch(e) {if(o.WTF) throw e;/* empty */}
if(props.HeadingPairs && props.TitlesOfParts) {
load_props_pairs(props.HeadingPairs, props.TitlesOfParts, props, o);
delete props.HeadingPairs; delete props.TitlesOfParts;
}
}
function write_xls_props(wb/*:Workbook*/, cfb/*:CFBContainer*/) {
var DSEntries = [], SEntries = [], CEntries = [];
var i = 0, Keys;
var DocSummaryRE/*:{[key:string]:string}*/ = evert_key(DocSummaryPIDDSI, "n");
var SummaryRE/*:{[key:string]:string}*/ = evert_key(SummaryPIDSI, "n");
if(wb.Props) {
Keys = keys(wb.Props);
// $FlowIgnore
for(i = 0; i < Keys.length; ++i) (Object.prototype.hasOwnProperty.call(DocSummaryRE, Keys[i]) ? DSEntries : Object.prototype.hasOwnProperty.call(SummaryRE, Keys[i]) ? SEntries : CEntries).push([Keys[i], wb.Props[Keys[i]]]);
}
if(wb.Custprops) {
Keys = keys(wb.Custprops);
// $FlowIgnore
for(i = 0; i < Keys.length; ++i) if(!Object.prototype.hasOwnProperty.call((wb.Props||{}), Keys[i])) (Object.prototype.hasOwnProperty.call(DocSummaryRE, Keys[i]) ? DSEntries : Object.prototype.hasOwnProperty.call(SummaryRE, Keys[i]) ? SEntries : CEntries).push([Keys[i], wb.Custprops[Keys[i]]]);
}
var CEntries2 = [];
for(i = 0; i < CEntries.length; ++i) {
if(XLSPSSkip.indexOf(CEntries[i][0]) > -1 || PseudoPropsPairs.indexOf(CEntries[i][0]) > -1) continue;
if(CEntries[i][1] == null) continue;
CEntries2.push(CEntries[i]);
}
if(SEntries.length) CFB.utils.cfb_add(cfb, "/\u0005SummaryInformation", write_PropertySetStream(SEntries, PSCLSID.SI, SummaryRE, SummaryPIDSI));
if(DSEntries.length || CEntries2.length) CFB.utils.cfb_add(cfb, "/\u0005DocumentSummaryInformation", write_PropertySetStream(DSEntries, PSCLSID.DSI, DocSummaryRE, DocSummaryPIDDSI, CEntries2.length ? CEntries2 : null, PSCLSID.UDI));
}
function parse_xlscfb(cfb/*:any*/, options/*:?ParseOpts*/)/*:Workbook*/ {
if(!options) options = {};
fix_read_opts(options);
reset_cp();
if(options.codepage) set_ansi(options.codepage);
var CompObj/*:?CFBEntry*/, WB/*:?any*/;
if(cfb.FullPaths) {
if(CFB.find(cfb, '/encryption')) throw new Error("File is password-protected");
CompObj = CFB.find(cfb, '!CompObj');
WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
} else {
switch(options.type) {
case 'base64': cfb = s2a(Base64_decode(cfb)); break;
case 'binary': cfb = s2a(cfb); break;
case 'buffer': break;
case 'array': if(!Array.isArray(cfb)) cfb = Array.prototype.slice.call(cfb); break;
}
prep_blob(cfb, 0);
WB = ({content: cfb}/*:any*/);
}
var /*::CompObjP, */WorkbookP/*:: :Workbook = XLSX.utils.book_new(); */;
var _data/*:?any*/;
if(CompObj) /*::CompObjP = */parse_compobj(CompObj);
if(options.bookProps && !options.bookSheets) WorkbookP = ({}/*:any*/);
else/*:: if(cfb instanceof CFBContainer) */ {
var T = has_buf ? 'buffer' : 'array';
if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options);
/* Quattro Pro 7-8 */
else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
/* Quattro Pro 9 */
else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
/* Works 4 for Mac */
else if((_data=CFB.find(cfb, 'MN0')) && _data.content) throw new Error("Unsupported Works 4 for Mac file");
else throw new Error("Cannot find Workbook stream");
if(options.bookVBA && cfb.FullPaths && CFB.find(cfb, '/_VBA_PROJECT_CUR/VBA/dir')) WorkbookP.vbaraw = make_vba_xls(cfb);
}
var props = {};
if(cfb.FullPaths) parse_xls_props(/*::((*/cfb/*:: :any):CFBContainer)*/, props, options);
WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
if(options.bookFiles) WorkbookP.cfb = cfb;
/*WorkbookP.CompObjP = CompObjP; // TODO: storage? */
return WorkbookP;
}
function write_xlscfb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:CFBContainer*/ {
var o = opts || {};
var cfb = CFB.utils.cfb_new({root:"R"});
var wbpath = "/Workbook";
switch(o.bookType || "xls") {
case "xls": o.bookType = "biff8";
/* falls through */
case "xla": if(!o.bookType) o.bookType = "xla";
/* falls through */
case "biff8": wbpath = "/Workbook"; o.biff = 8; break;
case "biff5": wbpath = "/Book"; o.biff = 5; break;
default: throw new Error("invalid type " + o.bookType + " for XLS CFB");
}
CFB.utils.cfb_add(cfb, wbpath, write_biff_buf(wb, o));
if(o.biff == 8 && (wb.Props || wb.Custprops)) write_xls_props(wb, cfb);
// TODO: SI, DSI, CO
if(o.biff == 8 && wb.vbaraw) fill_vba_xls(cfb, CFB.read(wb.vbaraw, {type: typeof wb.vbaraw == "string" ? "binary" : "buffer"}));
return cfb;
}

1334
bits/77_parsetab.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,139 +0,0 @@
/* 18.2 Workbook */
var wbnsregex = /<\w+:workbook/;
function parse_wb_xml(data, opts) {
var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
var pass = false, xmlns = "xmlns";
data.match(tagregex).forEach(function xml_wb(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<?xml': break;
/* 18.2.27 workbook CT_Workbook 1 */
case '<workbook':
if(x.match(wbnsregex)) xmlns = "xmlns" + x.match(/<(\w+):/)[1];
wb.xmlns = y[xmlns];
break;
case '</workbook>': break;
/* 18.2.13 fileVersion CT_FileVersion ? */
case '<fileVersion': delete y[0]; wb.AppVersion = y; break;
case '<fileVersion/>': break;
/* 18.2.12 fileSharing CT_FileSharing ? */
case '<fileSharing': case '<fileSharing/>': break;
/* 18.2.28 workbookPr CT_WorkbookPr ? */
case '<workbookPr': delete y[0]; wb.WBProps = y; break;
case '<workbookPr/>': delete y[0]; wb.WBProps = y; break;
/* 18.2.29 workbookProtection CT_WorkbookProtection ? */
case '<workbookProtection': break;
case '<workbookProtection/>': break;
/* 18.2.1 bookViews CT_BookViews ? */
case '<bookViews>': case '</bookViews>': break;
/* 18.2.30 workbookView CT_BookView + */
case '<workbookView': delete y[0]; wb.WBView.push(y); break;
/* 18.2.20 sheets CT_Sheets 1 */
case '<sheets>': case '</sheets>': break; // aggregate sheet
/* 18.2.19 sheet CT_Sheet + */
case '<sheet': delete y[0]; y.name = utf8read(y.name); wb.Sheets.push(y); break;
/* 18.2.15 functionGroups CT_FunctionGroups ? */
case '<functionGroups': case '<functionGroups/>': break;
/* 18.2.14 functionGroup CT_FunctionGroup + */
case '<functionGroup': break;
/* 18.2.9 externalReferences CT_ExternalReferences ? */
case '<externalReferences': case '</externalReferences>': case '<externalReferences>': break;
/* 18.2.8 externalReference CT_ExternalReference + */
case '<externalReference': break;
/* 18.2.6 definedNames CT_DefinedNames ? */
case '<definedNames/>': break;
case '<definedNames>': case '<definedNames': pass=true; break;
case '</definedNames>': pass=false; break;
/* 18.2.5 definedName CT_DefinedName + */
case '<definedName': case '<definedName/>': case '</definedName>': break;
/* 18.2.2 calcPr CT_CalcPr ? */
case '<calcPr': delete y[0]; wb.CalcPr = y; break;
case '<calcPr/>': delete y[0]; wb.CalcPr = y; break;
/* 18.2.16 oleSize CT_OleSize ? (ref required) */
case '<oleSize': break;
/* 18.2.4 customWorkbookViews CT_CustomWorkbookViews ? */
case '<customWorkbookViews>': case '</customWorkbookViews>': case '<customWorkbookViews': break;
/* 18.2.3 customWorkbookView CT_CustomWorkbookView + */
case '<customWorkbookView': case '</customWorkbookView>': break;
/* 18.2.18 pivotCaches CT_PivotCaches ? */
case '<pivotCaches>': case '</pivotCaches>': case '<pivotCaches': break;
/* 18.2.17 pivotCache CT_PivotCache ? */
case '<pivotCache': break;
/* 18.2.21 smartTagPr CT_SmartTagPr ? */
case '<smartTagPr': case '<smartTagPr/>': break;
/* 18.2.23 smartTagTypes CT_SmartTagTypes ? */
case '<smartTagTypes': case '<smartTagTypes>': case '</smartTagTypes>': break;
/* 18.2.22 smartTagType CT_SmartTagType ? */
case '<smartTagType': break;
/* 18.2.24 webPublishing CT_WebPublishing ? */
case '<webPublishing': case '<webPublishing/>': break;
/* 18.2.11 fileRecoveryPr CT_FileRecoveryPr ? */
case '<fileRecoveryPr': case '<fileRecoveryPr/>': break;
/* 18.2.26 webPublishObjects CT_WebPublishObjects ? */
case '<webPublishObjects>': case '<webPublishObjects': case '</webPublishObjects>': break;
/* 18.2.25 webPublishObject CT_WebPublishObject ? */
case '<webPublishObject': break;
/* 18.2.10 extLst CT_ExtensionList ? */
case '<extLst>': case '</extLst>': case '<extLst/>': break;
/* 18.2.7 ext CT_Extension + */
case '<ext': pass=true; break; //TODO: check with versions of excel
case '</ext>': pass=false; break;
/* Others */
case '<ArchID': break;
case '<AlternateContent': pass=true; break;
case '</AlternateContent>': pass=false; break;
default: if(!pass && opts.WTF) throw 'unrecognized ' + y[0] + ' in workbook';
}
});
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 safe1904(wb) {
/* TODO: store date1904 somewhere else */
try { return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false"; } catch(e) { return "false"; }
}
function write_wb_xml(wb, opts) {
var o = [XML_HEADER];
o[o.length] = WB_XML_ROOT;
o[o.length] = (writextag('workbookPr', null, {date1904:safe1904(wb)}));
o[o.length] = "<sheets>";
for(var i = 0; i != wb.SheetNames.length; ++i)
o[o.length] = (writextag('sheet',null,{name:wb.SheetNames[i].substr(0,31), sheetId:""+(i+1), "r:id":"rId"+(i+1)}));
o[o.length] = "</sheets>";
if(o.length>2){ o[o.length] = '</workbook>'; o[1]=o[1].replace("/>",">"); }
return o.join("");
}

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